Browse Source

feat(message): 实现聊天页面消息分页加载功能

- 将 ChatPage 从 StatelessWidget 改为 StatefulWidget
- 添加 ScrollController 监听列表滚动
- 实现滚动到底部时自动加载更多消息- 新增 _loadMoreMessages 方法处理分页逻辑
- 在控制器中调用 fetchMessages 方法加载历史消息- 添加加载状态防止重复请求
- 优化 dispose 方法释放滚动控制器资源
ios
Jolie 4 months ago
parent
commit
a13b441a2c
1 changed files with 81 additions and 28 deletions
  1. 109
      lib/pages/message/chat_page.dart

109
lib/pages/message/chat_page.dart

@ -10,15 +10,48 @@ import '../../generated/assets.dart';
import '../../../widget/message/chat_input_bar.dart';
import '../../../widget/message/message_item.dart';
class ChatPage extends StatelessWidget {
class ChatPage extends StatefulWidget {
final String userId;
const ChatPage({required this.userId, super.key});
@override
State<ChatPage> createState() => _ChatPageState();
}
class _ChatPageState extends State<ChatPage> {
final ScrollController _scrollController = ScrollController();
bool _isLoadingMore = false;
late ChatController _controller;
@override
void initState() {
super.initState();
// controller
_controller = Get.put(ChatController(userId: widget.userId));
//
_scrollController.addListener(() {
if (_scrollController.hasClients &&
_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent - 100 &&
!_isLoadingMore &&
_controller.messages.isNotEmpty) {
_loadMoreMessages();
}
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GetBuilder<ChatController>(
init: ChatController(userId: userId),
init: _controller,
builder: (controller) {
return WillPopScope(
onWillPop: () async {
@ -57,6 +90,7 @@ class ChatPage extends StatelessWidget {
},
behavior: HitTestBehavior.opaque,
child: ListView.builder(
controller: _scrollController,
reverse: true,
padding: EdgeInsets.all(16.w),
itemCount: controller.messages.length,
@ -79,34 +113,53 @@ class ChatPage extends StatelessWidget {
),
),
),
// 使
ChatInputBar(
onSendMessage: (message) async {
await controller.sendMessage(message);
},
onImageSelected: (imagePaths) async {
//
for (var imagePath in imagePaths) {
await controller.sendImageMessage(imagePath);
}
},
onVoiceRecorded: (filePath, seconds) async {
//
await controller.sendVoiceMessage(filePath, seconds);
},
onVideoRecorded: (filePath, duration) async {
print('🎬 [ChatPage] 收到视频录制/选择回调');
print('文件路径: $filePath');
print('时长: $duration');
// /
await controller.sendVideoMessage(filePath, duration);
},
),
],
// 使
ChatInputBar(
onSendMessage: (message) async {
await controller.sendMessage(message);
},
onImageSelected: (imagePaths) async {
//
for (var imagePath in imagePaths) {
await controller.sendImageMessage(imagePath);
}
},
onVoiceRecorded: (filePath, seconds) async {
//
await controller.sendVoiceMessage(filePath, seconds);
},
onVideoRecorded: (filePath, duration) async {
print('🎬 [ChatPage] 收到视频录制/选择回调');
print('文件路径: $filePath');
print('时长: $duration');
// /
await controller.sendVideoMessage(filePath, duration);
},
),
],
),
),
),
);
);
},
);
}
//
Future<void> _loadMoreMessages() async {
if (_isLoadingMore) return;
setState(() {
_isLoadingMore = true;
});
try {
await _controller.fetchMessages(loadMore: true);
} finally {
if (mounted) {
setState(() {
_isLoadingMore = false;
});
}
}
}
}
Loading…
Cancel
Save