mod: 支持系统消息查看,美化界面,点击清除未读提示,支持未读刷新

修复私信页点击视频后反复提示已读成功的问题
This commit is contained in:
orz12
2024-02-23 15:09:46 +08:00
parent 2671d0a130
commit 21ed67e569
14 changed files with 522 additions and 134 deletions

View File

@@ -348,13 +348,13 @@ class Api {
static const String msgFeedAt = '/x/msgfeed/at'; static const String msgFeedAt = '/x/msgfeed/at';
//https://api.bilibili.com/x/msgfeed/like?platform=web&build=0&mobi_app=web //https://api.bilibili.com/x/msgfeed/like?platform=web&build=0&mobi_app=web
static const String msgFeedLike = '/x/msgfeed/like'; static const String msgFeedLike = '/x/msgfeed/like';
//https://message.bilibili.com/x/sys-msg/query_user_notify?csrf=31b0caa533cea4d1a1bd2e921f045ec6&csrf=31b0caa533cea4d1a1bd2e921f045ec6&page_size=20&build=0&mobi_app=web //https://message.bilibili.com/x/sys-msg/query_user_notify?csrf=xxxx&csrf=xxxx&page_size=20&build=0&mobi_app=web
static const String msgSysUserNotify = '${HttpString.messageBaseUrl}/x/sys-msg/query_user_notify'; static const String msgSysUserNotify = '${HttpString.messageBaseUrl}/x/sys-msg/query_user_notify';
//https://message.bilibili.com/x/sys-msg/query_unified_notify?csrf=31b0caa533cea4d1a1bd2e921f045ec6&csrf=31b0caa533cea4d1a1bd2e921f045ec6&page_size=10&build=0&mobi_app=web //https://message.bilibili.com/x/sys-msg/query_unified_notify?csrf=xxxx&csrf=xxxx&page_size=10&build=0&mobi_app=web
static const String msgSysUnifiedNotify = '${HttpString.messageBaseUrl}/x/sys-msg/query_unified_notify'; static const String msgSysUnifiedNotify = '${HttpString.messageBaseUrl}/x/sys-msg/query_unified_notify';
// 系统信息光标更新(已读标记) // 系统信息光标更新(已读标记)
//https://message.bilibili.com/x/sys-msg/update_cursor?csrf=31b0caa533cea4d1a1bd2e921f045ec6&csrf=31b0caa533cea4d1a1bd2e921f045ec6&cursor=1705288500000000000&has_up=0&build=0&mobi_app=web //https://message.bilibili.com/x/sys-msg/update_cursor?csrf=xxxx&csrf=xxxx&cursor=1705288500000000000&has_up=0&build=0&mobi_app=web
static const String msgSysUpdateCursor = '${HttpString.messageBaseUrl}/x/sys-msg/update_cursor'; static const String msgSysUpdateCursor = '${HttpString.messageBaseUrl}/x/sys-msg/update_cursor';
/// 私聊 /// 私聊

View File

@@ -100,6 +100,26 @@ class MsgHttp {
}; };
} }
} }
static Future msgSysUpdateCursor(int cursor) async {
String csrf = await Request.getCsrf();
var res = await Request().get(Api.msgSysUpdateCursor, data: {
'csrf': csrf,
'csrf': csrf,
'cursor': cursor,
});
if (res.data['code'] == 0) {
return {
'status': true,
};
} else {
return {
'status': false,
'msg': res.data['message'],
};
}
}
static Future msgFeedUnread() async { static Future msgFeedUnread() async {
var res = await Request().get(Api.msgFeedUnread); var res = await Request().get(Api.msgFeedUnread);
if (res.data['code'] == 0) { if (res.data['code'] == 0) {

View File

@@ -0,0 +1,155 @@
class MsgFeedSysMsg {
List<SystemNotifyList>? systemNotifyList;
MsgFeedSysMsg({this.systemNotifyList});
MsgFeedSysMsg.fromJson(Map<String, dynamic> json) {
if (json['system_notify_list'] != null) {
systemNotifyList = <SystemNotifyList>[];
json['system_notify_list'].forEach((v) {
systemNotifyList!.add(SystemNotifyList.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (systemNotifyList != null) {
data['system_notify_list'] =
systemNotifyList!.map((v) => v.toJson()).toList();
}
return data;
}
}
class SystemNotifyList {
int? id;
int? cursor;
Publisher? publisher;
int? type;
String? title;
String? content;
Source? source;
String? timeAt;
int? cardType;
String? cardBrief;
String? cardMsgBrief;
String? cardCover;
String? cardStoryTitle;
String? cardLink;
String? mc;
int? isStation;
int? isSend;
int? notifyCursor;
SystemNotifyList(
{this.id,
this.cursor,
this.publisher,
this.type,
this.title,
this.content,
this.source,
this.timeAt,
this.cardType,
this.cardBrief,
this.cardMsgBrief,
this.cardCover,
this.cardStoryTitle,
this.cardLink,
this.mc,
this.isStation,
this.isSend,
this.notifyCursor});
SystemNotifyList.fromJson(Map<String, dynamic> json) {
id = json['id'];
cursor = json['cursor'];
publisher = json['publisher'] != null
? Publisher.fromJson(json['publisher'])
: null;
type = json['type'];
title = json['title'];
content = json['content'];
source = json['source'] != null ? Source.fromJson(json['source']) : null;
timeAt = json['time_at'];
cardType = json['card_type'];
cardBrief = json['card_brief'];
cardMsgBrief = json['card_msg_brief'];
cardCover = json['card_cover'];
cardStoryTitle = json['card_story_title'];
cardLink = json['card_link'];
mc = json['mc'];
isStation = json['is_station'];
isSend = json['is_send'];
notifyCursor = json['notify_cursor'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['cursor'] = cursor;
if (publisher != null) {
data['publisher'] = publisher!.toJson();
}
data['type'] = type;
data['title'] = title;
data['content'] = content;
if (source != null) {
data['source'] = source!.toJson();
}
data['time_at'] = timeAt;
data['card_type'] = cardType;
data['card_brief'] = cardBrief;
data['card_msg_brief'] = cardMsgBrief;
data['card_cover'] = cardCover;
data['card_story_title'] = cardStoryTitle;
data['card_link'] = cardLink;
data['mc'] = mc;
data['is_station'] = isStation;
data['is_send'] = isSend;
data['notify_cursor'] = notifyCursor;
return data;
}
}
class Publisher {
String? name;
int? mid;
String? face;
Publisher({this.name, this.mid, this.face});
Publisher.fromJson(Map<String, dynamic> json) {
name = json['name'];
mid = json['mid'];
face = json['face'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
data['mid'] = mid;
data['face'] = face;
return data;
}
}
class Source {
String? name;
String? logo;
Source({this.name, this.logo});
Source.fromJson(Map<String, dynamic> json) {
name = json['name'];
logo = json['logo'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
data['logo'] = logo;
return data;
}
}

View File

@@ -76,20 +76,31 @@ class _AtMePageState extends State<AtMePage> {
title: Text( title: Text(
"${_atMeController.msgFeedAtMeList[i].user?.nickname} " "${_atMeController.msgFeedAtMeList[i].user?.nickname} "
"${_atMeController.msgFeedAtMeList[i].item?.business}中@了我", "${_atMeController.msgFeedAtMeList[i].item?.business}中@了我",
style: Theme.of(context).textTheme.bodyMedium!, style: Theme.of(context)
), .textTheme
subtitle: Text( .titleMedium!
.copyWith(
color: Theme.of(context).colorScheme.primary,
)),
subtitle:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 4),
Text(
_atMeController _atMeController
.msgFeedAtMeList[i].item?.sourceContent ?? .msgFeedAtMeList[i].item?.sourceContent ??
"", "",
maxLines: 2, maxLines: 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.labelMedium! .bodyMedium!
.copyWith( .copyWith(
color: color:
Theme.of(context).colorScheme.outline)), Theme.of(context).colorScheme.outline))
],
),
trailing: _atMeController trailing: _atMeController
.msgFeedAtMeList[i].item?.image != .msgFeedAtMeList[i].item?.image !=
null && null &&

View File

@@ -115,7 +115,10 @@ class LikeMeList extends StatelessWidget {
String nativeUri = msgFeedLikeMeList[i].item?.nativeUri ?? ""; String nativeUri = msgFeedLikeMeList[i].item?.nativeUri ?? "";
SmartDialog.showToast("跳转至:$nativeUri(暂未实现)"); SmartDialog.showToast("跳转至:$nativeUri(暂未实现)");
}, },
leading: SizedBox( leading: Column(
children: [
const Spacer(),
SizedBox(
width: 50, width: 50,
height: 50, height: 50,
child: Stack( child: Stack(
@@ -127,33 +130,46 @@ class LikeMeList extends StatelessWidget {
left: 15 * (j % 2).toDouble(), left: 15 * (j % 2).toDouble(),
top: 15 * (j ~/ 2).toDouble(), top: 15 * (j ~/ 2).toDouble(),
child: NetworkImgLayer( child: NetworkImgLayer(
width: width: msgFeedLikeMeList[i].users!.length > 1
msgFeedLikeMeList[i].users!.length > 1 ? 30 : 45, ? 30
height: : 45,
msgFeedLikeMeList[i].users!.length > 1 ? 30 : 45, height: msgFeedLikeMeList[i].users!.length > 1
? 30
: 45,
type: 'avatar', type: 'avatar',
src: msgFeedLikeMeList[i].users![j].avatar, src: msgFeedLikeMeList[i].users![j].avatar,
)), )),
] ]
], ],
)), )),
const Spacer(),
],
),
title: Text( title: Text(
"${msgFeedLikeMeList[i].users!.map((e) => e.nickname).join("/")}" // "${msgFeedLikeMeList[i].users!.map((e) => e.nickname).join("/")}"
"等共 ${msgFeedLikeMeList[i].counts}" "${msgFeedLikeMeList[i].users?[0].nickname}"
"${msgFeedLikeMeList[i].users!.length > 1 ? '' + msgFeedLikeMeList[i].users![1].nickname.toString() + '' : ''} "
"${msgFeedLikeMeList[i].counts! > 1 ? '' + msgFeedLikeMeList[i].counts.toString() + '' : ''}"
"赞了我的${msgFeedLikeMeList[i].item?.business}", "赞了我的${msgFeedLikeMeList[i].item?.business}",
style: style: Theme.of(context).textTheme.titleSmall!.copyWith(
Theme.of(context).textTheme.labelMedium!.copyWith(height: 1.5), height: 1.5, color: Theme.of(context).colorScheme.primary),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
subtitle: msgFeedLikeMeList[i].item?.title != null && subtitle: msgFeedLikeMeList[i].item?.title != null &&
msgFeedLikeMeList[i].item?.title != "" msgFeedLikeMeList[i].item?.title != ""
? Text(msgFeedLikeMeList[i].item?.title ?? "", ? Column(
maxLines: 2, crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 4),
Text(msgFeedLikeMeList[i].item?.title ?? "",
maxLines: 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.labelMedium!.copyWith( style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
height: 1.5)) height: 1.5))
],
)
: null, : null,
trailing: msgFeedLikeMeList[i].item?.image != null && trailing: msgFeedLikeMeList[i].item?.image != null &&
msgFeedLikeMeList[i].item?.image != "" msgFeedLikeMeList[i].item?.image != ""

View File

@@ -78,7 +78,8 @@ class _ReplyMePageState extends State<ReplyMePage> {
title: Text( title: Text(
"${_replyMeController.msgFeedReplyMeList[i].user?.nickname} " "${_replyMeController.msgFeedReplyMeList[i].user?.nickname} "
"回复了我的${_replyMeController.msgFeedReplyMeList[i].item?.business}", "回复了我的${_replyMeController.msgFeedReplyMeList[i].item?.business}",
style: Theme.of(context).textTheme.bodyMedium!, style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.primary),
), ),
subtitle: Column( subtitle: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,

View File

@@ -0,0 +1,63 @@
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:PiliPalaX/http/msg.dart';
import '../../../models/msg/msgfeed_sys_msg.dart';
class SysMsgController extends GetxController {
RxList<SystemNotifyList> msgFeedSysMsgList = <SystemNotifyList>[].obs;
bool isLoading = false;
int cursor = -1;
int cursorTime = -1;
bool isEnd = false;
Future queryMsgFeedSysMsg() async {
if (isLoading) return;
isLoading = true;
var resUserNotify = await MsgHttp.msgFeedSysUserNotify();
var resUnifiedNotify = await MsgHttp.msgFeedSysUnifiedNotify();
isLoading = false;
List<SystemNotifyList> systemNotifyList = [];
if (resUserNotify['status']) {
MsgFeedSysMsg data = MsgFeedSysMsg.fromJson(resUserNotify['data']);
if (data.systemNotifyList != null) {
systemNotifyList.addAll(data.systemNotifyList!);
}
}
if (resUnifiedNotify['status']) {
MsgFeedSysMsg data = MsgFeedSysMsg.fromJson(resUnifiedNotify['data']);
if (data.systemNotifyList != null) {
systemNotifyList.addAll(data.systemNotifyList!);
}
}
if (systemNotifyList.isNotEmpty) {
systemNotifyList.sort((a, b) => b.cursor!.compareTo(a.cursor!));
msgFeedSysMsgList.assignAll(systemNotifyList);
msgSysUpdateCursor(msgFeedSysMsgList.first.cursor!);
} else {
SmartDialog.showToast(
"UserNotify: ${resUserNotify['msg']} UnifiedNotify: ${resUnifiedNotify['msg']}");
}
}
Future msgSysUpdateCursor(int cursor) async {
var res = await MsgHttp.msgSysUpdateCursor(cursor);
if (res['status']) {
SmartDialog.showToast('已读成功');
return true;
} else {
SmartDialog.showToast(res['msg']);
return false;
}
}
Future onLoad() async {
if (isEnd) return;
queryMsgFeedSysMsg();
}
Future onRefresh() async {
cursor = -1;
cursorTime = -1;
queryMsgFeedSysMsg();
}
}

View File

@@ -0,0 +1,4 @@
library whisper;
export './controller.dart';
export './view.dart';

View File

@@ -0,0 +1,123 @@
import 'dart:convert';
import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'controller.dart';
class SysMsgPage extends StatefulWidget {
const SysMsgPage({super.key});
@override
State<SysMsgPage> createState() => _SysMsgPageState();
}
class _SysMsgPageState extends State<SysMsgPage> {
late final SysMsgController _sysMsgController = Get.put(SysMsgController());
final ScrollController _scrollController = ScrollController();
@override
void initState() {
_sysMsgController.queryMsgFeedSysMsg();
super.initState();
_scrollController.addListener(_scrollListener);
}
Future _scrollListener() async {
if (_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent - 200) {
EasyThrottle.throttle('my-throttler', const Duration(milliseconds: 800),
() async {
await _sysMsgController.onLoad();
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('系统通知'),
),
body: RefreshIndicator(
onRefresh: () async {
await _sysMsgController.onRefresh();
},
child: SingleChildScrollView(
controller: _scrollController,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Obx(
() {
if (_sysMsgController.msgFeedSysMsgList.isEmpty) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.separated(
itemCount: _sysMsgController.msgFeedSysMsgList.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (_, int i) {
String? content = _sysMsgController.msgFeedSysMsgList[i].content;
if (content != null) {
try {
dynamic jsonContent = json.decode(content);
if (jsonContent != null && jsonContent['web'] != null) {
content = jsonContent['web'];
}
} catch (_) {}
}
return ListTile(
onTap: () {},
title: Text(
"${_sysMsgController.msgFeedSysMsgList[i].title}",
style: Theme.of(context).textTheme.titleMedium!.copyWith(
color: Theme.of(context).colorScheme.primary
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 4),
Text(
"$content",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
color: Theme.of(context)
.colorScheme
.outline)),
const SizedBox(height: 4),
Text(
"${_sysMsgController.msgFeedSysMsgList[i].timeAt}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
color: Theme.of(context)
.colorScheme
.outline.withOpacity(0.8))),
]));
},
separatorBuilder: (BuildContext context, int index) {
return Divider(
indent: 72,
endIndent: 20,
height: 6,
color: Colors.grey.withOpacity(0.1),
);
},
);
},
);
}),
),
),
);
}
}

View File

@@ -46,6 +46,7 @@ class _WhisperPageState extends State<WhisperPage> {
), ),
body: RefreshIndicator( body: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await _whisperController.queryMsgFeedUnread();
await _whisperController.onRefresh(); await _whisperController.onRefresh();
}, },
child: SingleChildScrollView( child: SingleChildScrollView(
@@ -58,27 +59,32 @@ class _WhisperPageState extends State<WhisperPage> {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 20, right: 20), padding: const EdgeInsets.only(left: 20, right: 20),
child: SizedBox( child: SizedBox(
height: constraints.maxWidth / 4, height: constraints.maxWidth / 4 + 10,
child: Obx( child: Obx(
() => GridView.count( () => GridView.count(
primary: false, primary: false,
crossAxisCount: 4, crossAxisCount: 4,
padding: const EdgeInsets.all(0), padding: const EdgeInsets.fromLTRB(0, 7, 0, 0),
childAspectRatio: 1.25, childAspectRatio: 1.2,
children: _whisperController.msgFeedTop.map((item) { children: Iterable<int>.generate(
_whisperController.msgFeedTop.length)
.map((idx) {
return GestureDetector( return GestureDetector(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Badge( Badge(
isLabelVisible: item['value'] > 0, isLabelVisible: _whisperController
.msgFeedTop[idx]['value'] >
0,
backgroundColor: backgroundColor:
Theme.of(context).colorScheme.primary, Theme.of(context).colorScheme.primary,
textColor: Theme.of(context) textColor: Theme.of(context)
.colorScheme .colorScheme
.onInverseSurface, .onInverseSurface,
label: Text(" ${item['value']} "), label: Text(
" ${_whisperController.msgFeedTop[idx]['value']} "),
alignment: Alignment.topRight, alignment: Alignment.topRight,
child: CircleAvatar( child: CircleAvatar(
radius: 22, radius: 22,
@@ -86,7 +92,8 @@ class _WhisperPageState extends State<WhisperPage> {
.colorScheme .colorScheme
.onInverseSurface, .onInverseSurface,
child: Icon( child: Icon(
item['icon'], _whisperController.msgFeedTop[idx]
['icon'],
size: 20, size: 20,
color: color:
Theme.of(context).colorScheme.primary, Theme.of(context).colorScheme.primary,
@@ -94,11 +101,17 @@ class _WhisperPageState extends State<WhisperPage> {
), ),
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
Text(item['name'], Text(_whisperController.msgFeedTop[idx]['name'],
style: const TextStyle(fontSize: 13)) style: const TextStyle(fontSize: 13))
], ],
), ),
onTap: () => Get.toNamed(item['route']), onTap: () {
setState(() {
_whisperController.msgFeedTop[idx]['value'] = 0;
});
Get.toNamed(
_whisperController.msgFeedTop[idx]['route']);
},
); );
}).toList(), }).toList(),
), ),
@@ -123,19 +136,27 @@ class _WhisperPageState extends State<WhisperPage> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemBuilder: (_, int i) { itemBuilder: (_, int i) {
return ListTile( return ListTile(
onTap: () => Get.toNamed( onTap: () {
setState(() {
sessionList[i].unreadCount = 0;
});
Get.toNamed(
'/whisperDetail', '/whisperDetail',
parameters: { parameters: {
'talkerId': 'talkerId': sessionList[i]
sessionList[i].talkerId.toString(), .talkerId
'name': sessionList[i].accountInfo.name, .toString(),
'face': sessionList[i].accountInfo.face, 'name':
sessionList[i].accountInfo.name,
'face':
sessionList[i].accountInfo.face,
'mid': sessionList[i] 'mid': sessionList[i]
.accountInfo .accountInfo
.mid .mid
.toString(), .toString(),
}, },
), );
},
leading: Badge( leading: Badge(
isLabelVisible: isLabelVisible:
sessionList[i].unreadCount > 0, sessionList[i].unreadCount > 0,
@@ -181,7 +202,7 @@ class _WhisperPageState extends State<WhisperPage> {
.outline)), .outline)),
trailing: Text( trailing: Text(
Utils.dateFormat( Utils.dateFormat(
sessionList[i].lastMsg.timestamp), sessionList[i].lastMsg.timestamp, formatType: "day"),
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.labelSmall! .labelSmall!

View File

@@ -25,15 +25,19 @@ class WhisperDetailController extends GetxController {
var res = await MsgHttp.sessionMsg(talkerId: talkerId); var res = await MsgHttp.sessionMsg(talkerId: talkerId);
if (res['status']) { if (res['status']) {
messageList.value = res['data'].messages; messageList.value = res['data'].messages;
if (messageList.isNotEmpty && res['data'].eInfos != null) { if (messageList.isNotEmpty) {
ackSessionMsg();
if (res['data'].eInfos != null) {
eInfos = res['data'].eInfos; eInfos = res['data'].eInfos;
} }
} }
return res; } else {
SmartDialog.showToast(res['msg']);
}
} }
Future ackSessionMsg() async { Future ackSessionMsg() async {
if (messageList.isEmpty){ if (messageList.isEmpty) {
return; return;
} }
var res = await MsgHttp.ackSessionMsg( var res = await MsgHttp.ackSessionMsg(

View File

@@ -16,12 +16,11 @@ class WhisperDetailPage extends StatefulWidget {
class _WhisperDetailPageState extends State<WhisperDetailPage> { class _WhisperDetailPageState extends State<WhisperDetailPage> {
final WhisperDetailController _whisperDetailController = final WhisperDetailController _whisperDetailController =
Get.put(WhisperDetailController()); Get.put(WhisperDetailController());
late Future _futureBuilderFuture;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_futureBuilderFuture = _whisperDetailController.querySessionMsg(); _whisperDetailController.querySessionMsg();
} }
@override @override
@@ -89,53 +88,23 @@ class _WhisperDetailPageState extends State<WhisperDetailPage> {
), ),
), ),
), ),
body: FutureBuilder( body: Obx(() {
future: _futureBuilderFuture,
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) {
return const SizedBox();
}
final Map data = snapshot.data as Map;
if (data['status']) {
List messageList = _whisperDetailController.messageList; List messageList = _whisperDetailController.messageList;
_whisperDetailController.ackSessionMsg(); if (messageList.isEmpty) {
return Obx( return const Center(
() => messageList.isEmpty child: CircularProgressIndicator(),
? const SizedBox() );
: ListView.builder( }
return ListView.builder(
itemCount: messageList.length, itemCount: messageList.length,
shrinkWrap: true, shrinkWrap: true,
reverse: true, reverse: true,
itemBuilder: (_, int i) { itemBuilder: (_, int i) {
if (i == 0) {
return Column(
children: [
ChatItem(
item: messageList[i],
e_infos: _whisperDetailController.eInfos),
const SizedBox(height: 12),
],
);
} else {
return ChatItem( return ChatItem(
item: messageList[i], item: messageList[i], e_infos: _whisperDetailController.eInfos);
e_infos: _whisperDetailController.eInfos);
}
}, },
),
); );
} else { }),
// 请求错误
return const SizedBox();
}
} else {
// 骨架屏
return const SizedBox();
}
},
),
// resizeToAvoidBottomInset: true,
bottomNavigationBar: Container( bottomNavigationBar: Container(
width: double.infinity, width: double.infinity,
height: MediaQuery.of(context).padding.bottom + 70, height: MediaQuery.of(context).padding.bottom + 70,

View File

@@ -34,6 +34,7 @@ import '../pages/member_dynamics/index.dart';
import '../pages/member_like/index.dart'; import '../pages/member_like/index.dart';
import '../pages/member_search/index.dart'; import '../pages/member_search/index.dart';
import '../pages/member_seasons/index.dart'; import '../pages/member_seasons/index.dart';
import '../pages/msg_feed_top/sys_msg/view.dart';
import '../pages/search/index.dart'; import '../pages/search/index.dart';
import '../pages/search_result/index.dart'; import '../pages/search_result/index.dart';
import '../pages/setting/extra_setting.dart'; import '../pages/setting/extra_setting.dart';
@@ -154,7 +155,7 @@ class Routes {
// 收到的赞 // 收到的赞
CustomGetPage(name: '/likeMe', page: () => const LikeMePage()), CustomGetPage(name: '/likeMe', page: () => const LikeMePage()),
// 系统消息 // 系统消息
CustomGetPage(name: '/sysMsg', page: () => const WhisperPage()), CustomGetPage(name: '/sysMsg', page: () => const SysMsgPage()),
// 登录页面 // 登录页面
CustomGetPage(name: '/loginPage', page: () => const LoginPage()), CustomGetPage(name: '/loginPage', page: () => const LoginPage()),
// 用户动态 // 用户动态

View File

@@ -170,13 +170,13 @@ class Utils {
.replaceAll('hh', hh) .replaceAll('hh', hh)
.replaceAll('mm', mm) .replaceAll('mm', mm)
.replaceAll('ss', ss); .replaceAll('ss', ss);
if (int.parse(YY) == DateTime.now().year && // if (int.parse(YY) == DateTime.now().year &&
int.parse(MM) == DateTime.now().month) { // int.parse(MM) == DateTime.now().month) {
// 当天 // // 当天
if (int.parse(DD) == DateTime.now().day) { // if (int.parse(DD) == DateTime.now().day) {
return '今天'; // return '今天';
} // }
} // }
return date; return date;
} }