refa: whisper detail

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-05-10 11:05:28 +08:00
parent 024e74115e
commit 024a249e6b
6 changed files with 635 additions and 616 deletions

View File

@@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:PiliPlus/build_config.dart';
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/grpc/bilibili/metadata.pb.dart';
import 'package:PiliPlus/grpc/bilibili/metadata/device.pb.dart';
@@ -60,6 +61,7 @@ class GrpcUrl {
static const keywordBlockingList = '$im2/KeywordBlockingList';
static const keywordBlockingAdd = '$im2/KeywordBlockingAdd';
static const keywordBlockingDelete = '$im2/KeywordBlockingDelete';
static const syncFetchSessionMsgs = '$im/SyncFetchSessionMsgs';
}
class GrpcRepo {
@@ -205,8 +207,11 @@ class GrpcRepo {
try {
final grpcMsg = Status.fromBuffer(msgBytes);
// UNKNOWN : -400 : msg
msg =
'${grpcMsg.code} : ${grpcMsg.message} : ${grpcMsg.details.firstOrNull?.status.message}';
final errMsg =
grpcMsg.details.map((e) => e.status.message).join('\n');
msg = BuildConfig.isDebug
? 'CODE: ${grpcMsg.code}(${grpcMsg.message})\nMSG: $errMsg'
: errMsg;
} catch (e) {
msg = utf8
.decode(msgBytes, allowMalformed: true)

View File

@@ -41,8 +41,28 @@ class ImGrpc {
);
}
static Future<LoadingState<SessionMainReply>> sessionMain(
{PbMap<int, Offset>? offset}) {
static Future<LoadingState<RspSessionMsg>> syncFetchSessionMsgs({
required int talkerId,
Int64? endSeqno,
Int64? beginSeqno,
}) {
return GrpcRepo.request(
GrpcUrl.syncFetchSessionMsgs,
ReqSessionMsg(
talkerId: Int64(talkerId),
sessionType: 1,
endSeqno: endSeqno,
beginSeqno: beginSeqno,
size: 20,
devId: '1',
),
RspSessionMsg.fromBuffer,
);
}
static Future<LoadingState<SessionMainReply>> sessionMain({
PbMap<int, Offset>? offset,
}) {
return GrpcRepo.request(
GrpcUrl.sessionMain,
SessionMainReq(

View File

@@ -46,9 +46,9 @@ class _ZanButtonGrpcState extends State<ZanButtonGrpc> {
widget.replyItem.like =
$fixnum.Int64(widget.replyItem.like.toInt() - 1);
}
widget.replyItem.replyControl.action = $fixnum.Int64(2);
widget.replyItem.replyControl.action = $fixnum.Int64.TWO;
} else {
widget.replyItem.replyControl.action = $fixnum.Int64(0);
widget.replyItem.replyControl.action = $fixnum.Int64.ZERO;
}
setState(() {});
} else {
@@ -76,11 +76,11 @@ class _ZanButtonGrpcState extends State<ZanButtonGrpc> {
if (action == 1) {
widget.replyItem.like =
$fixnum.Int64(widget.replyItem.like.toInt() + 1);
widget.replyItem.replyControl.action = $fixnum.Int64(1);
widget.replyItem.replyControl.action = $fixnum.Int64.ONE;
} else {
widget.replyItem.like =
$fixnum.Int64(widget.replyItem.like.toInt() - 1);
widget.replyItem.replyControl.action = $fixnum.Int64(0);
widget.replyItem.replyControl.action = $fixnum.Int64.ZERO;
}
setState(() {});
} else {

View File

@@ -1,67 +1,70 @@
import 'dart:async';
import 'dart:convert';
import 'package:PiliPlus/grpc/bilibili/im/interfaces/v1.pb.dart'
show EmotionInfo, RspSessionMsg;
import 'package:PiliPlus/grpc/bilibili/im/type.pb.dart' show Msg, MsgType;
import 'package:PiliPlus/grpc/im.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_list_controller.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/feed_back.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:fixnum/fixnum.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class WhisperDetailController
extends CommonListController<SessionMsgDataModel, MessageItem> {
class WhisperDetailController extends CommonListController<RspSessionMsg, Msg> {
late final ownerMid = Accounts.main.mid;
late int talkerId;
late String name;
late String face;
String? mid;
int? mid;
int? msgSeqno;
Int64? msgSeqno;
//表情转换图片规则
List<dynamic>? eInfos;
List<EmotionInfo>? eInfos;
@override
void onInit() {
super.onInit();
talkerId = int.parse(Get.parameters['talkerId']!);
name = Get.parameters['name']!;
face = Get.parameters['face']!;
mid = Get.parameters['mid'];
mid = Get.parameters['mid'] != null
? int.parse(Get.parameters['mid']!)
: null;
queryData();
}
@override
bool customHandleResponse(
bool isRefresh, Success<SessionMsgDataModel> response) {
List<MessageItem>? messageList = response.response.messages;
if (messageList?.isNotEmpty == true) {
msgSeqno = messageList!.last.msgSeqno;
if (messageList.length == 1 &&
messageList.last.msgType == 18 &&
messageList.last.msgSource == 18) {
bool customHandleResponse(bool isRefresh, Success<RspSessionMsg> response) {
List<Msg> msgs = response.response.messages;
if (msgs.isNotEmpty) {
msgSeqno = msgs.last.msgSeqno;
if (msgs.length == 1 &&
msgs.last.msgType == 18 &&
msgs.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 ??= [];
eInfos!.addAll(response.response.eInfos!);
ackSessionMsg(msgs.last.msgSeqno.toInt());
}
eInfos ??= <EmotionInfo>[];
eInfos!.addAll(response.response.eInfos);
}
return false;
}
// 消息标记已读
Future<void> ackSessionMsg(int? msgSeqno) async {
Future<void> ackSessionMsg(int msgSeqno) async {
var res = await MsgHttp.ackSessionMsg(
talkerId: talkerId,
ackSeqno: msgSeqno,
@@ -79,37 +82,24 @@ class WhisperDetailController
int? index,
}) async {
feedBack();
if (ownerMid == 0) {
SmartDialog.dismiss();
if (ownerMid == 0) {
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(
var result = await ImGrpc.sendMsg(
senderUid: ownerMid,
receiverId: int.parse(mid!),
content: msgType == 5
? message
: jsonEncode(
picMsg ?? {"content": message},
),
msgType: msgType ?? (picMsg != null ? 2 : 1),
receiverId: mid!,
content:
msgType == 5 ? message : jsonEncode(picMsg ?? {"content": message}),
msgType: MsgType.values[msgType ?? (picMsg != null ? 2 : 1)],
);
SmartDialog.dismiss();
if (result['status']) {
if (result.isSuccess) {
if (msgType == 5) {
List<MessageItem> list = (loadingState.value as Success).response;
list[index!].msgStatus = 1;
loadingState.refresh();
loadingState
..value.data![index!].msgStatus = 1
..refresh();
SmartDialog.showToast('撤回成功');
} else {
onRefresh();
@@ -117,12 +107,12 @@ class WhisperDetailController
SmartDialog.showToast('发送成功');
}
} else {
SmartDialog.showToast(result['msg']);
result.toast();
}
}
@override
List<MessageItem>? getDataList(SessionMsgDataModel response) {
List<Msg>? getDataList(RspSessionMsg response) {
if (response.hasMore == 0) {
isEnd = true;
}
@@ -138,10 +128,10 @@ class WhisperDetailController
}
@override
Future<LoadingState<SessionMsgDataModel>> customGetData() =>
MsgHttp.sessionMsg(
Future<LoadingState<RspSessionMsg>> customGetData() =>
ImGrpc.syncFetchSessionMsgs(
talkerId: talkerId,
beginSeqno: msgSeqno != null ? 0 : null,
beginSeqno: msgSeqno != null ? Int64.ZERO : null,
endSeqno: msgSeqno,
);
}

View File

@@ -3,10 +3,10 @@ import 'dart:async';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
import 'package:PiliPlus/grpc/bilibili/im/type.pb.dart' show Msg;
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/msg.dart';
import 'package:PiliPlus/models/common/publish_panel_type.dart';
import 'package:PiliPlus/models/msg/session.dart';
import 'package:PiliPlus/pages/common/common_publish_page.dart';
import 'package:PiliPlus/pages/emote/view.dart';
import 'package:PiliPlus/pages/whisper_detail/controller.dart';
@@ -110,15 +110,17 @@ class _WhisperDetailPageState
_buildBody(_whisperDetailController.loadingState.value)),
),
),
if (_whisperDetailController.mid != null) ...[
_buildInputView(theme),
buildPanelContainer(theme.colorScheme.onInverseSurface),
],
],
),
),
);
}
Widget _buildBody(LoadingState<List<MessageItem>?> loadingState) {
Widget _buildBody(LoadingState<List<Msg>?> loadingState) {
return switch (loadingState) {
Loading() => loadingWidget,
Success() => loadingState.response?.isNotEmpty == true

File diff suppressed because it is too large Load Diff