Files
sweet_chat_app/lib/pages/message_page.dart
2026-06-20 16:11:57 +08:00

172 lines
4.7 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
import 'package:provider/provider.dart';
import 'package:sweet_chat_app/apis/message_api.dart';
import 'package:sweet_chat_app/models/chat_session.dart';
import 'package:sweet_chat_app/models/contact_info.dart';
import 'package:sweet_chat_app/pages/chat_page.dart';
import 'package:sweet_chat_app/providers/app_provider.dart';
import 'package:sweet_chat_app/services/notify_service.dart';
import 'package:sweet_chat_app/services/webSocket_service.dart';
import 'package:sweet_chat_app/utils/date_utils.dart';
import 'package:sweet_chat_app/utils/sp_utils.dart';
class MessagePage extends StatefulWidget {
const MessagePage({super.key});
@override
State<MessagePage> createState() => _MessagePageState();
}
class _MessagePageState extends State<MessagePage> {
late StreamSubscription<String> _msgSub;
late List<ChatSession> _chatSessionList;
final NotifyService notifyService = NotifyService();
late int userId;
@override
void initState() {
super.initState();
userId = SpUtil.getInt('userId') ?? 0;
_chatSessionList = [];
_loadChatSession();
_msgSub = WebSocketService().messages.listen((websocketMessage) {
_loadChatSession();
});
}
@override
void dispose() {
_msgSub.cancel();
super.dispose();
}
Future<void> _loadChatSession() async {
final userId = SpUtil.getInt('userId') ?? 0;
final list = await getChatSessionApi(userId);
if (!mounted) return;
setState(() {
_chatSessionList = list;
});
}
void onTapSession(ChatSession chatSession) {
final ContactInfo contactInfo = ContactInfo(
id: chatSession.targetUserId,
name: chatSession.title,
avatar: chatSession.avatarUrl,
);
final ChatPage chatPage = ChatPage(
contactInfo: contactInfo,
conversationId: chatSession.conversationId,
);
final appProvider = Provider.of<AppProvider>(context, listen: false);
Navigator.push(context, MaterialPageRoute(builder: (_) => chatPage)).then((
_,
) {
appProvider.routerName = '';
_loadChatSession();
});
appProvider.routerName = 'chat';
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
appBar: _buildAppBar(),
body: _buildMessageList(context),
);
}
PreferredSizeWidget _buildAppBar() {
return AppBar(
backgroundColor: Color(0xFF120D25),
elevation: 0,
centerTitle: true,
leading: IconButton(
onPressed: () {},
icon: const Icon(Icons.menu, size: 22, color: Colors.white),
splashRadius: 20,
),
title: Text(
'消息 ${WebSocketService().isConnected}' ,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.search, size: 22, color: Colors.white),
splashRadius: 20,
),
IconButton(
onPressed: () {},
icon: const Icon(Icons.add, size: 22, color: Colors.white),
splashRadius: 20,
),
],
);
}
Widget _buildMessageList(BuildContext context) {
return ListView.separated(
padding: EdgeInsets.only(
left: 10,
right: 10,
top: 10,
bottom: MediaQuery.of(context).padding.bottom + 80,
),
separatorBuilder: (BuildContext context, int index) {
return SizedBox(height: 10);
},
itemCount: _chatSessionList.length,
itemBuilder: (context, index) {
final msg = _chatSessionList[index];
return _buildMessageItem(context, msg);
},
);
}
Widget _buildMessageItem(BuildContext context, ChatSession session) {
return GlassCard(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
child: ListTile(
contentPadding: EdgeInsets.zero,
onTap: () => onTapSession(session),
leading: CircleAvatar(
backgroundColor: Colors.transparent,
backgroundImage: NetworkImage(session.avatarUrl),
),
title: Text(
session.title,
style: const TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
subtitle: Text(
session.lastMessageContent,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 13, color: Color(0xFFAEAEB2)),
),
trailing: Text(
formatChatTime(session.lastMessageTime),
style: const TextStyle(fontSize: 12, color: Color(0xFF8E8E93)),
),
),
);
}
}