fix(mobile-next): 把加载、失败、断网接到真实 SDK 与目录请求
会话列表、通讯录、好友申请、添加同事页覆盖 CompanyLoadingView/CompanyFailView; 主页断网横幅跟随 IMSdkStatus.connectionFailed。不伪造状态。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
092f513708
commit
2b2c2d28a4
@@ -25,10 +25,13 @@ class ConversationLogic extends GetxController {
|
||||
final pageSize = 400;
|
||||
|
||||
final imStatus = IMSdkStatus.connectionSucceeded.obs;
|
||||
final loading = true.obs;
|
||||
final loadFailed = false.obs;
|
||||
bool reInstall = false;
|
||||
|
||||
final ItemScrollController itemScrollController = ItemScrollController();
|
||||
final ItemPositionsListener itemPositionsListener = ItemPositionsListener.create();
|
||||
final ItemPositionsListener itemPositionsListener =
|
||||
ItemPositionsListener.create();
|
||||
|
||||
int scrollIndex = -1;
|
||||
final onChangeConversations = <ConversationInfo>[];
|
||||
@@ -52,13 +55,16 @@ class ConversationLogic extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
Logger.print('IM SDK Status: $status, reinstall: $reInstall, progress: $progress');
|
||||
Logger.print(
|
||||
'IM SDK Status: $status, reinstall: $reInstall, progress: $progress');
|
||||
|
||||
if (status == IMSdkStatus.syncProgress && reInstall) {
|
||||
final p = (progress!).toDouble() / 100.0;
|
||||
|
||||
EasyLoading.showProgress(p, status: '${StrRes.synchronizing}(${(p * 100.0).truncate()}%)');
|
||||
} else if (status == IMSdkStatus.syncEnded || status == IMSdkStatus.syncFailed) {
|
||||
EasyLoading.showProgress(p,
|
||||
status: '${StrRes.synchronizing}(${(p * 100.0).truncate()}%)');
|
||||
} else if (status == IMSdkStatus.syncEnded ||
|
||||
status == IMSdkStatus.syncFailed) {
|
||||
EasyLoading.dismiss();
|
||||
if (reInstall) {
|
||||
onRefresh();
|
||||
@@ -81,7 +87,8 @@ class ConversationLogic extends GetxController {
|
||||
onChangeConversations.addAll(newList);
|
||||
}
|
||||
for (var newValue in newList) {
|
||||
Logger.print('======== conversation changed: ${newValue.toJson()} ========');
|
||||
Logger.print(
|
||||
'======== conversation changed: ${newValue.toJson()} ========');
|
||||
list.removeWhere((e) => e.conversationID == newValue.conversationID);
|
||||
}
|
||||
|
||||
@@ -132,7 +139,8 @@ class ConversationLogic extends GetxController {
|
||||
}
|
||||
|
||||
void deleteConversation(ConversationInfo info) async {
|
||||
await OpenIM.iMManager.conversationManager.deleteConversationAndDeleteAllMsg(
|
||||
await OpenIM.iMManager.conversationManager
|
||||
.deleteConversationAndDeleteAllMsg(
|
||||
conversationID: info.conversationID,
|
||||
);
|
||||
list.remove(info);
|
||||
@@ -171,7 +179,8 @@ class ConversationLogic extends GetxController {
|
||||
|
||||
final text = IMUtils.parseNtf(info.latestMsg!, isConversation: true);
|
||||
if (text != null) return text;
|
||||
if (info.isSingleChat || info.latestMsg!.sendID == OpenIM.iMManager.userID)
|
||||
if (info.isSingleChat ||
|
||||
info.latestMsg!.sendID == OpenIM.iMManager.userID)
|
||||
return IMUtils.parseMsg(info.latestMsg!, isConversation: true);
|
||||
|
||||
return "${info.latestMsg!.senderNickname}: ${IMUtils.parseMsg(info.latestMsg!, isConversation: true)} ";
|
||||
@@ -264,16 +273,31 @@ class ConversationLogic extends GetxController {
|
||||
}
|
||||
|
||||
bool get isFailedSdkStatus =>
|
||||
imStatus.value == IMSdkStatus.connectionFailed || imStatus.value == IMSdkStatus.syncFailed;
|
||||
imStatus.value == IMSdkStatus.connectionFailed ||
|
||||
imStatus.value == IMSdkStatus.syncFailed;
|
||||
|
||||
void _sortConversationList() => OpenIM.iMManager.conversationManager.simpleSort(list);
|
||||
bool get showLoading {
|
||||
if (loading.value) return true;
|
||||
if (list.isNotEmpty) return false;
|
||||
switch (imStatus.value) {
|
||||
case IMSdkStatus.connecting:
|
||||
case IMSdkStatus.syncStart:
|
||||
case IMSdkStatus.synchronizing:
|
||||
case IMSdkStatus.syncProgress:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool get showFail => list.isEmpty && (loadFailed.value || isFailedSdkStatus);
|
||||
|
||||
void _sortConversationList() =>
|
||||
OpenIM.iMManager.conversationManager.simpleSort(list);
|
||||
|
||||
void onRefresh() async {
|
||||
late List<ConversationInfo> list;
|
||||
try {
|
||||
list = await _request();
|
||||
this.list.assignAll(list);
|
||||
|
||||
await reloadConversations();
|
||||
if (list.isEmpty || list.length < pageSize) {
|
||||
refreshController.loadNoData();
|
||||
} else {
|
||||
@@ -285,16 +309,46 @@ class ConversationLogic extends GetxController {
|
||||
}
|
||||
|
||||
static Future<List<ConversationInfo>> getConversationFirstPage() async {
|
||||
final result = await OpenIM.iMManager.conversationManager.getConversationListSplit(offset: 0, count: 400);
|
||||
final result = await OpenIM.iMManager.conversationManager
|
||||
.getConversationListSplit(offset: 0, count: 400);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void getFirstPage() async {
|
||||
final result = homeLogic.conversationsAtFirstPage;
|
||||
loading.value = true;
|
||||
loadFailed.value = false;
|
||||
try {
|
||||
final cached = homeLogic.conversationsAtFirstPage;
|
||||
if (cached.isNotEmpty) {
|
||||
list.assignAll(cached);
|
||||
_sortConversationList();
|
||||
return;
|
||||
}
|
||||
final result = await _request();
|
||||
list.assignAll(result);
|
||||
_sortConversationList();
|
||||
} catch (e, s) {
|
||||
Logger.print('conversation first page e: $e $s');
|
||||
loadFailed.value = true;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
list.assignAll(result);
|
||||
_sortConversationList();
|
||||
Future<void> reloadConversations() async {
|
||||
loading.value = true;
|
||||
loadFailed.value = false;
|
||||
try {
|
||||
final result = await _request();
|
||||
list.assignAll(result);
|
||||
_sortConversationList();
|
||||
} catch (e, s) {
|
||||
Logger.print('conversation reload e: $e $s');
|
||||
loadFailed.value = true;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
void clearConversations() {
|
||||
@@ -305,20 +359,23 @@ class ConversationLogic extends GetxController {
|
||||
final temp = <ConversationInfo>[];
|
||||
|
||||
while (true) {
|
||||
var result = await OpenIM.iMManager.conversationManager.getConversationListSplit(
|
||||
var result =
|
||||
await OpenIM.iMManager.conversationManager.getConversationListSplit(
|
||||
offset: temp.length,
|
||||
count: pageSize,
|
||||
);
|
||||
if (onChangeConversations.isNotEmpty) {
|
||||
final bSet = Set.from(onChangeConversations);
|
||||
|
||||
Logger.print('replace conversation: [${onChangeConversations.length}], $bSet');
|
||||
Logger.print(
|
||||
'replace conversation: [${onChangeConversations.length}], $bSet');
|
||||
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
final info = result[i];
|
||||
|
||||
if (bSet.contains(info)) {
|
||||
result[i] = onChangeConversations[onChangeConversations.indexOf(info)];
|
||||
result[i] =
|
||||
onChangeConversations[onChangeConversations.indexOf(info)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -367,7 +424,8 @@ class ConversationLogic extends GetxController {
|
||||
if (scrollIndex == 0) {
|
||||
itemScrollController.jumpTo(index: 0);
|
||||
} else {
|
||||
itemScrollController.scrollTo(index: scrollIndex, duration: const Duration(milliseconds: 300));
|
||||
itemScrollController.scrollTo(
|
||||
index: scrollIndex, duration: const Duration(milliseconds: 300));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,7 +434,8 @@ class ConversationLogic extends GetxController {
|
||||
required int sessionType,
|
||||
}) =>
|
||||
LoadingView.singleton.wrap(
|
||||
asyncFunction: () => OpenIM.iMManager.conversationManager.getOneConversation(
|
||||
asyncFunction: () =>
|
||||
OpenIM.iMManager.conversationManager.getOneConversation(
|
||||
sourceID: sourceID,
|
||||
sessionType: sessionType,
|
||||
));
|
||||
@@ -438,9 +497,11 @@ class ConversationLogic extends GetxController {
|
||||
|
||||
addFriend() => AppNavigator.startAddColleague();
|
||||
|
||||
createGroup() => AppNavigator.startCreateGroup(defaultCheckedList: [OpenIM.iMManager.userInfo]);
|
||||
createGroup() => AppNavigator.startCreateGroup(
|
||||
defaultCheckedList: [OpenIM.iMManager.userInfo]);
|
||||
|
||||
addGroup() => AppNavigator.startAddContactsBySearch(searchType: SearchType.group);
|
||||
addGroup() =>
|
||||
AppNavigator.startAddContactsBySearch(searchType: SearchType.group);
|
||||
|
||||
void globalSearch() => AppNavigator.startGlobalSearch();
|
||||
}
|
||||
|
||||
@@ -46,7 +46,8 @@ class ConversationPage extends StatelessWidget {
|
||||
body: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(AppGap.x4, 0, AppGap.x4, AppGap.x2),
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
AppGap.x4, 0, AppGap.x4, AppGap.x2),
|
||||
child: Container(
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
@@ -57,47 +58,64 @@ class ConversationPage extends StatelessWidget {
|
||||
alignment: Alignment.centerLeft,
|
||||
child: const Row(
|
||||
children: [
|
||||
Icon(Icons.search, size: AppIconSize.sm, color: AppColors.textSecondary),
|
||||
Icon(Icons.search,
|
||||
size: AppIconSize.sm, color: AppColors.textSecondary),
|
||||
SizedBox(width: AppGap.x2),
|
||||
Text('搜索', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)),
|
||||
Text('搜索',
|
||||
style: TextStyle(
|
||||
fontSize: AppFont.sub,
|
||||
color: AppColors.textSecondary)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: logic.list.isEmpty
|
||||
? const CompanyEmptyView(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
title: '暂时没有会话',
|
||||
subtitle: '去通讯录找个同事聊聊吧',
|
||||
)
|
||||
: SlidableAutoCloseBehavior(
|
||||
child: ScrollablePositionedList.builder(
|
||||
itemScrollController: logic.itemScrollController,
|
||||
itemBuilder: (_, index) => _buildConversationItemView(
|
||||
logic.list.elementAt(index),
|
||||
),
|
||||
itemCount: logic.list.length,
|
||||
itemPositionsListener: logic.itemPositionsListener,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(child: _conversationBody()),
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Widget _conversationBody() {
|
||||
if (logic.showLoading) {
|
||||
return const CompanyLoadingView();
|
||||
}
|
||||
if (logic.showFail) {
|
||||
return CompanyFailView(onRetry: logic.reloadConversations);
|
||||
}
|
||||
if (logic.list.isEmpty) {
|
||||
return const CompanyEmptyView(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
title: '暂时没有会话',
|
||||
subtitle: '去通讯录找个同事聊聊吧',
|
||||
);
|
||||
}
|
||||
return SlidableAutoCloseBehavior(
|
||||
child: ScrollablePositionedList.builder(
|
||||
itemScrollController: logic.itemScrollController,
|
||||
itemBuilder: (_, index) => _buildConversationItemView(
|
||||
logic.list.elementAt(index),
|
||||
),
|
||||
itemCount: logic.list.length,
|
||||
itemPositionsListener: logic.itemPositionsListener,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildConversationItemView(ConversationInfo info) => Slidable(
|
||||
endActionPane: ActionPane(
|
||||
motion: const ScrollMotion(),
|
||||
extentRatio: logic.existUnreadMsg(info) ? 0.7 : (logic.isPinned(info) ? 0.5 : 0.4),
|
||||
extentRatio: logic.existUnreadMsg(info)
|
||||
? 0.7
|
||||
: (logic.isPinned(info) ? 0.5 : 0.4),
|
||||
children: [
|
||||
CustomSlidableAction(
|
||||
onPressed: (_) => logic.pinConversation(info),
|
||||
flex: logic.isPinned(info) ? 3 : 2,
|
||||
backgroundColor: Styles.c_0089FF,
|
||||
padding: const EdgeInsets.all(1),
|
||||
child: (logic.isPinned(info) ? StrRes.cancelTop : StrRes.top).toText..style = Styles.ts_FFFFFF_14sp,
|
||||
child:
|
||||
(logic.isPinned(info) ? StrRes.cancelTop : StrRes.top).toText
|
||||
..style = Styles.ts_FFFFFF_14sp,
|
||||
),
|
||||
if (logic.existUnreadMsg(info))
|
||||
CustomSlidableAction(
|
||||
@@ -163,7 +181,8 @@ class ConversationPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
logic.getTime(info).toText..style = Styles.ts_8E9AB0_12sp,
|
||||
logic.getTime(info).toText
|
||||
..style = Styles.ts_8E9AB0_12sp,
|
||||
],
|
||||
),
|
||||
3.verticalSpace,
|
||||
@@ -175,9 +194,12 @@ class ConversationPage extends StatelessWidget {
|
||||
prefixSpan: TextSpan(
|
||||
text: '',
|
||||
children: [
|
||||
if (logic.isNotDisturb(info) && logic.getUnreadCount(info) > 0)
|
||||
if (logic.isNotDisturb(info) &&
|
||||
logic.getUnreadCount(info) > 0)
|
||||
TextSpan(
|
||||
text: '[${sprintf(StrRes.nPieces, [logic.getUnreadCount(info)])}] ',
|
||||
text: '[${sprintf(StrRes.nPieces, [
|
||||
logic.getUnreadCount(info)
|
||||
])}] ',
|
||||
style: Styles.ts_8E9AB0_14sp,
|
||||
),
|
||||
TextSpan(
|
||||
@@ -195,7 +217,8 @@ class ConversationPage extends StatelessWidget {
|
||||
..width = 13.63.w
|
||||
..height = 14.07.h
|
||||
else
|
||||
UnreadCountView(count: logic.getUnreadCount(info)),
|
||||
UnreadCountView(
|
||||
count: logic.getUnreadCount(info)),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user