- 登录:工号+密码走 account-service /api/login,自动登录、被踢下线回登录页 - 消息:会话列表(未读角标/免打扰/时间)、单聊群聊、文字/语音/图片/文件消息、失败重发、历史分页 - 通讯录:新的同事/我的群聊入口、按部门分组(好友 ex 字段)、搜索 - 通话:一对一语音通话(信令走 OpenIM 自定义消息 + LiveKit,token 走 /api/rtc_token) - 界面按确认效果图 m1/m2/m3 实现,主色 #3B87F5,四态视图齐全,无英文残留
107 lines
3.0 KiB
Dart
107 lines
3.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
|
|
|
|
import '../theme.dart';
|
|
import '../widgets/avatar.dart';
|
|
import 'chat_screen.dart';
|
|
|
|
/// 「我的群聊」:已加入的群列表
|
|
class GroupListScreen extends StatefulWidget {
|
|
const GroupListScreen({super.key});
|
|
|
|
@override
|
|
State<GroupListScreen> createState() => _GroupListScreenState();
|
|
}
|
|
|
|
class _GroupListScreenState extends State<GroupListScreen> {
|
|
List<GroupInfo> _groups = [];
|
|
bool _loading = true;
|
|
bool _failed = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_load();
|
|
}
|
|
|
|
Future<void> _load() async {
|
|
try {
|
|
final list = await OpenIM.iMManager.groupManager.getJoinedGroupList();
|
|
if (!mounted) return;
|
|
setState(() {
|
|
_groups = list;
|
|
_loading = false;
|
|
_failed = false;
|
|
});
|
|
} catch (_) {
|
|
if (!mounted) return;
|
|
setState(() {
|
|
_loading = false;
|
|
_failed = true;
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('我的群聊')),
|
|
body: _buildBody(),
|
|
);
|
|
}
|
|
|
|
Widget _buildBody() {
|
|
if (_loading) {
|
|
return const Center(child: CircularProgressIndicator(color: AppColors.primary));
|
|
}
|
|
if (_failed) {
|
|
return Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Text('群聊列表没加载出来', style: TextStyle(fontSize: AppFont.body, color: AppColors.textPrimary)),
|
|
const SizedBox(height: AppGap.x4),
|
|
OutlinedButton(onPressed: _load, child: const Text('重试')),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
if (_groups.isEmpty) {
|
|
return const Center(
|
|
child: Text('你还没有加入任何群聊', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)),
|
|
);
|
|
}
|
|
return ListView.separated(
|
|
itemCount: _groups.length,
|
|
separatorBuilder: (_, __) => const Divider(indent: 76),
|
|
itemBuilder: (_, i) => _tile(_groups[i]),
|
|
);
|
|
}
|
|
|
|
Widget _tile(GroupInfo g) {
|
|
final name = g.groupName ?? '';
|
|
return ListTile(
|
|
leading: NameAvatar(name: name, isGroup: true),
|
|
title: Text(name, style: const TextStyle(fontSize: AppFont.body)),
|
|
subtitle: Text('${g.memberCount ?? 0} 人', style: const TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)),
|
|
onTap: () => _openChat(g),
|
|
);
|
|
}
|
|
|
|
Future<void> _openChat(GroupInfo g) async {
|
|
try {
|
|
final conversation = await OpenIM.iMManager.conversationManager.getOneConversation(
|
|
sourceID: g.groupID,
|
|
sessionType: ConversationType.superGroup,
|
|
);
|
|
if (!mounted) return;
|
|
Navigator.of(context).push(MaterialPageRoute(builder: (_) => ChatScreen(conversation: conversation)));
|
|
} catch (_) {
|
|
if (!mounted) return;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('打开会话失败,请检查网络'), duration: Duration(seconds: 2)),
|
|
);
|
|
}
|
|
}
|
|
}
|