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