diff --git a/lib/http/msg.dart b/lib/http/msg.dart index bb0647ca..96acac1d 100644 --- a/lib/http/msg.dart +++ b/lib/http/msg.dart @@ -455,9 +455,8 @@ class MsgHttp { } } - static Future sessionMsg({ - int? talkerId, - }) async { + static Future> sessionMsg( + {int? talkerId}) async { Map params = await WbiSign.makSign({ 'talker_id': talkerId, 'session_type': 1, @@ -469,15 +468,13 @@ class MsgHttp { var res = await Request().get(Api.sessionMsg, queryParameters: params); if (res.data['code'] == 0) { try { - return { - 'status': true, - 'data': SessionMsgDataModel.fromJson(res.data['data']), - }; + return LoadingState.success( + SessionMsgDataModel.fromJson(res.data['data'])); } catch (err) { - debugPrint(err.toString()); + return LoadingState.error(err.toString()); } } else { - return {'status': false, 'msg': res.data['message']}; + return LoadingState.error(res.data['message']); } } diff --git a/lib/pages/whisper/controller.dart b/lib/pages/whisper/controller.dart index c80223b3..f88172b6 100644 --- a/lib/pages/whisper/controller.dart +++ b/lib/pages/whisper/controller.dart @@ -13,7 +13,6 @@ import '../../utils/storage.dart'; class WhisperController extends CommonListController?, SessionList> { - late final bool disableLikeMsg; late final List msgFeedTopItems; late final RxList unreadCounts; @@ -22,7 +21,7 @@ class WhisperController @override void onInit() { super.onInit(); - disableLikeMsg = + final disableLikeMsg = GStorage.setting.get(SettingBoxKey.disableLikeMsg, defaultValue: false); msgFeedTopItems = [ { diff --git a/lib/pages/whisper_detail/controller.dart b/lib/pages/whisper_detail/controller.dart index 2276d0cf..8c1b06c4 100644 --- a/lib/pages/whisper_detail/controller.dart +++ b/lib/pages/whisper_detail/controller.dart @@ -1,5 +1,7 @@ import 'dart:convert'; +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -8,12 +10,15 @@ import 'package:PiliPlus/models/msg/session.dart'; import '../../utils/feed_back.dart'; import '../../utils/storage.dart'; -class WhisperDetailController extends GetxController { +class WhisperDetailController + extends CommonListController { + late final ownerMid = Accounts.main.mid; + late int talkerId; late String name; late String face; String? mid; - RxList messageList = [].obs; + //表情转换图片规则 List? eInfos; @@ -25,48 +30,41 @@ class WhisperDetailController extends GetxController { face = Get.parameters['face']!; mid = Get.parameters['mid']; - querySessionMsg(); + queryData(); } - Future querySessionMsg() async { - var res = await MsgHttp.sessionMsg(talkerId: talkerId); - if (res['status']) { - messageList.value = res['data'].messages; - if (messageList.isNotEmpty) { - if (messageList.length == 1 && - messageList.last.msgType == 18 && - messageList.last.msgSource == 18) { - // debugPrint(messageList.last); - // debugPrint(messageList.last.content); - //{content: [{"text":"对方主动回复或关注你前,最多发送1条消息","color_day":"#9499A0","color_nig":"#9499A0"}]} - } else { - ackSessionMsg(); - } - if (res['data'].eInfos != null) { - eInfos = res['data'].eInfos; - } + @override + bool customHandleResponse( + bool isRefresh, Success response) { + List? messageList = response.response.messages; + if (messageList?.isNotEmpty == true) { + if (messageList!.length == 1 && + messageList.last.msgType == 18 && + messageList.last.msgSource == 18) { + // debugPrint(messageList.last); + // debugPrint(messageList.last.content); + //{content: [{"text":"对方主动回复或关注你前,最多发送1条消息","color_day":"#9499A0","color_nig":"#9499A0"}]} + } else { + ackSessionMsg(messageList.last.msgSeqno); + } + if (response.response.eInfos != null) { + eInfos = response.response.eInfos; } - } else { - SmartDialog.showToast(res['msg']); } + return false; } // 消息标记已读 - Future ackSessionMsg() async { - if (messageList.isEmpty) { - return; - } + Future ackSessionMsg(int? msgSeqno) async { var res = await MsgHttp.ackSessionMsg( talkerId: talkerId, - ackSeqno: messageList.last.msgSeqno, + ackSeqno: msgSeqno, ); if (!res['status']) { SmartDialog.showToast(res['msg']); } } - late final ownerMid = Accounts.main.mid; - Future sendMsg({ required String message, dynamic picMsg, @@ -80,16 +78,16 @@ class WhisperDetailController extends GetxController { SmartDialog.showToast('请先登录'); return; } - if (picMsg == null && message == '') { - SmartDialog.dismiss(); - SmartDialog.showToast('请输入内容'); - return; - } if (mid == null) { SmartDialog.dismiss(); SmartDialog.showToast('这里不能发'); return; } + if (picMsg == null && message == '') { + SmartDialog.dismiss(); + SmartDialog.showToast('请输入内容'); + return; + } var result = await MsgHttp.sendMsg( senderUid: ownerMid, receiverId: int.parse(mid!), @@ -99,13 +97,13 @@ class WhisperDetailController extends GetxController { ); SmartDialog.dismiss(); if (result['status']) { - // debugPrint(result['data']); if (msgType == 5) { - messageList[index!].msgStatus = 1; - messageList.refresh(); + List list = (loadingState.value as Success).response; + list[index!].msgStatus = 1; + loadingState.refresh(); SmartDialog.showToast('撤回成功'); } else { - querySessionMsg(); + queryData(); onClearText(); SmartDialog.showToast('发送成功'); } @@ -113,4 +111,13 @@ class WhisperDetailController extends GetxController { SmartDialog.showToast(result['msg']); } } + + @override + List? getDataList(SessionMsgDataModel response) { + return response.messages; + } + + @override + Future> customGetData() => + MsgHttp.sessionMsg(talkerId: talkerId); } diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index c5c87726..1068d8a5 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -1,5 +1,7 @@ import 'dart:async'; +import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; +import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/msg.dart'; import 'package:PiliPlus/models/msg/session.dart'; import 'package:PiliPlus/pages/common/common_publish_page.dart'; @@ -45,11 +47,10 @@ class _WhisperDetailPageState height: 34, child: IconButton( tooltip: '返回', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - backgroundColor: WidgetStateProperty.resolveWith((states) { - return Theme.of(context).colorScheme.secondaryContainer; - }), + style: IconButton.styleFrom( + padding: EdgeInsets.zero, + backgroundColor: + Theme.of(context).colorScheme.secondaryContainer, ), onPressed: Get.back, icon: Icon( @@ -60,48 +61,49 @@ class _WhisperDetailPageState ), ), ), - title: SizedBox( - width: double.infinity, - height: 50, + title: GestureDetector( + onTap: () { + feedBack(); + Get.toNamed( + '/member?mid=${_whisperDetailController.mid}', + arguments: { + 'face': _whisperDetailController.face, + }, + ); + }, child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - GestureDetector( - onTap: () { - feedBack(); - Get.toNamed( - '/member?mid=${_whisperDetailController.mid}', - arguments: { - 'face': _whisperDetailController.face, - 'heroTag': null - }, - ); - }, - child: Row( - children: [ - NetworkImgLayer( - width: 34, - height: 34, - type: 'avatar', - src: _whisperDetailController.face, - ), - const SizedBox(width: 6), - Text( - _whisperDetailController.name, - style: Theme.of(context).textTheme.titleMedium, - ), - ], + NetworkImgLayer( + width: 34, + height: 34, + type: 'avatar', + src: _whisperDetailController.face, + ), + const SizedBox(width: 6), + Expanded( + child: Text( + _whisperDetailController.name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.titleMedium, ), ), - const SizedBox(width: 36, height: 36), ], ), ), ), body: Column( - mainAxisAlignment: MainAxisAlignment.center, children: [ - Expanded(child: _buildList()), + Expanded( + child: Listener( + child: Obx(() => + _buildBody(_whisperDetailController.loadingState.value)), + onPointerDown: (event) { + // Hide panel when touch ListView. + hidePanel(); + }, + ), + ), _buildInputView(), buildPanelContainer(Theme.of(context).colorScheme.onInverseSurface), ], @@ -109,82 +111,81 @@ class _WhisperDetailPageState ); } - Widget _buildList() { - Widget resultWidget = Obx( - () { - List messageList = _whisperDetailController.messageList; - if (messageList.isEmpty) { - return const Center( - child: CircularProgressIndicator(), - ); - } - return refreshIndicator( - onRefresh: _whisperDetailController.querySessionMsg, - child: ListView.builder( - shrinkWrap: true, - reverse: true, - itemCount: messageList.length, - itemBuilder: (context, int index) { - return ChatItem( - item: messageList[index], - eInfos: _whisperDetailController.eInfos, - onLongPress: messageList[index].senderUid == - _whisperDetailController.ownerMid - ? () { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - clipBehavior: Clip.hardEdge, - contentPadding: - const EdgeInsets.fromLTRB(0, 12, 0, 12), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - onTap: () { - Get.back(); - _whisperDetailController.sendMsg( - message: '${messageList[index].msgKey}', - onClearText: editController.clear, - msgType: 5, - index: index, - ); - }, - dense: true, - title: const Text('撤回', - style: TextStyle(fontSize: 14)), + Widget _buildBody(LoadingState?> loadingState) { + return switch (loadingState) { + Loading() => loadingWidget, + Success() => loadingState.response?.isNotEmpty == true + ? refreshIndicator( + onRefresh: () async { + await _whisperDetailController.onRefresh(); + }, + child: ListView.builder( + shrinkWrap: true, + reverse: true, + itemCount: loadingState.response!.length, + padding: const EdgeInsets.only(bottom: 12), + itemBuilder: (context, int index) { + final item = loadingState.response![index]; + return ChatItem( + item: item, + eInfos: _whisperDetailController.eInfos, + onLongPress: item.senderUid == + _whisperDetailController.ownerMid + ? () { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + clipBehavior: Clip.hardEdge, + contentPadding: + const EdgeInsets.symmetric(vertical: 12), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + onTap: () { + Get.back(); + _whisperDetailController.sendMsg( + message: '${item.msgKey}', + onClearText: editController.clear, + msgType: 5, + index: index, + ); + }, + dense: true, + title: const Text( + '撤回', + style: TextStyle(fontSize: 14), + ), + ), + // ListTile( + // onTap: () { + // Get.back(); + // }, + // dense: true, + // title: const Text('删除', + // style: TextStyle(fontSize: 14)), + // ), + ], ), - // ListTile( - // onTap: () { - // Get.back(); - // }, - // dense: true, - // title: const Text('删除', - // style: TextStyle(fontSize: 14)), - // ), - ], - ), + ); + }, ); - }, - ); - } - : null, - ); - }, - padding: const EdgeInsets.only(bottom: 20), - ), - ); - }, - ); - resultWidget = Listener( - child: resultWidget, - onPointerDown: (event) { - // Hide panel when touch ListView. - hidePanel(); - }, - ); - return resultWidget; + } + : null, + ); + }, + ), + ) + : scrollErrorWidget( + callback: _whisperDetailController.onReload, + ), + Error() => scrollErrorWidget( + errMsg: loadingState.errMsg, + callback: _whisperDetailController.onReload, + ), + _ => throw UnimplementedError(), + }; } Widget _buildInputView() { diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index 13198344..92d5d08f 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:PiliPlus/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart'; +import 'package:PiliPlus/models/msg/session.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; @@ -41,13 +42,13 @@ enum MsgType { } class ChatItem extends StatelessWidget { - final dynamic item; + final MessageItem item; final List? eInfos; final VoidCallback? onLongPress; const ChatItem({ super.key, - this.item, + required this.item, this.eInfos, this.onLongPress, }) : isOwner = onLongPress != null; @@ -137,7 +138,7 @@ class ChatItem extends StatelessWidget { } Widget messageContent(BuildContext context) { - switch (MsgType.parse(item.msgType)) { + switch (MsgType.parse(item.msgType!)) { case MsgType.notify_msg: return SystemNotice(item: item); case MsgType.pic_card: