import 'package:flutter/material.dart'; import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:get/get.dart'; import 'package:openim_common/openim_common.dart'; import 'package:rotated_corner_decoration/rotated_corner_decoration.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:sprintf/sprintf.dart'; import '../../company/brand/app_tokens.dart'; import '../../company/ui/state_views.dart'; import 'conversation_logic.dart'; class ConversationPage extends StatelessWidget { final logic = Get.find(); ConversationPage({super.key}); @override Widget build(BuildContext context) { return Obx(() => Scaffold( backgroundColor: AppColors.pageBg, appBar: TitleBar.conversation( statusStr: logic.imSdkStatus, isFailed: logic.isFailedSdkStatus, popCtrl: logic.popCtrl, onScan: logic.scan, onAddFriend: logic.addFriend, onAddGroup: logic.addGroup, onCreateGroup: logic.createGroup, left: Expanded( flex: 2, child: Align( alignment: Alignment.centerLeft, child: const Text( '消息', style: TextStyle( fontSize: AppFont.title, fontWeight: FontWeight.w700, color: AppColors.textPrimary, ), ), ), )), body: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(AppGap.x4, 0, AppGap.x4, AppGap.x2), child: Container( height: 36, decoration: BoxDecoration( color: AppColors.searchBg, borderRadius: BorderRadius.circular(AppRadius.control), ), padding: const EdgeInsets.symmetric(horizontal: AppGap.x3), alignment: Alignment.centerLeft, child: const Row( children: [ Icon(Icons.search, size: AppIconSize.sm, color: AppColors.textSecondary), SizedBox(width: AppGap.x2), 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, ), ), ), ], ), )); } Widget _buildConversationItemView(ConversationInfo info) => Slidable( endActionPane: ActionPane( motion: const ScrollMotion(), 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, ), if (logic.existUnreadMsg(info)) CustomSlidableAction( onPressed: (_) => logic.markMessageHasRead(info), flex: 3, backgroundColor: Styles.c_8E9AB0, padding: const EdgeInsets.all(1), child: StrRes.markHasRead.toText ..style = Styles.ts_FFFFFF_14sp ..maxLines = 1, ), CustomSlidableAction( onPressed: (_) => logic.deleteConversation(info), flex: 2, backgroundColor: Styles.c_FF381F, padding: const EdgeInsets.all(1), child: StrRes.delete.toText..style = Styles.ts_FFFFFF_14sp, ), ], ), child: _buildItemView(info), ); Widget _buildItemView(ConversationInfo info) => Ink( child: InkWell( onTap: () => logic.toChat(conversationInfo: info), child: Stack( children: [ Container( height: 72, padding: EdgeInsets.symmetric(horizontal: 16.w), child: Row( children: [ Stack( children: [ AvatarView( width: 48.w, height: 48.h, text: logic.getShowName(info), url: info.faceURL, isGroup: logic.isGroupChat(info), textStyle: Styles.ts_FFFFFF_14sp_medium, ), ], ), 12.horizontalSpace, Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( children: [ ConstrainedBox( constraints: BoxConstraints(maxWidth: 180.w), child: Text( logic.getShowName(info), maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: AppFont.body, color: AppColors.textPrimary, ), ), ), const Spacer(), logic.getTime(info).toText..style = Styles.ts_8E9AB0_12sp, ], ), 3.verticalSpace, Row( children: [ MatchTextView( text: logic.getContent(info), textStyle: Styles.ts_8E9AB0_14sp, prefixSpan: TextSpan( text: '', children: [ if (logic.isNotDisturb(info) && logic.getUnreadCount(info) > 0) TextSpan( text: '[${sprintf(StrRes.nPieces, [logic.getUnreadCount(info)])}] ', style: Styles.ts_8E9AB0_14sp, ), TextSpan( text: logic.getPrefixTag(info), style: Styles.ts_0089FF_14sp, ), ], ), maxLines: 1, overflow: TextOverflow.ellipsis, ), const Spacer(), if (logic.isNotDisturb(info)) ImageRes.notDisturb.toImage ..width = 13.63.w ..height = 14.07.h else UnreadCountView(count: logic.getUnreadCount(info)), ], ), ], ), ), ], ), ), if (logic.isPinned(info)) Container( height: 72, margin: EdgeInsets.only(right: 6.w), foregroundDecoration: RotatedCornerDecoration.withColor( color: Styles.c_0089FF, badgeSize: Size(8.29.w, 8.29.h), ), ) ], ), ), ); }