feat: 消息添加未阅读数量

This commit is contained in:
orz12
2024-01-24 14:45:15 +08:00
parent 772a6a9843
commit 65e4d6f61e
5 changed files with 272 additions and 181 deletions

View File

@@ -328,6 +328,8 @@ class Api {
// 获取指定分组下的up // 获取指定分组下的up
static const String followUpGroup = '/x/relation/tag'; static const String followUpGroup = '/x/relation/tag';
static const String msgFeedUnread = '/x/msgfeed/unread';
/// 私聊 /// 私聊
/// 'https://api.vc.bilibili.com/session_svr/v1/session_svr/get_sessions? /// 'https://api.vc.bilibili.com/session_svr/v1/session_svr/get_sessions?
/// session_type=1& /// session_type=1&

View File

@@ -5,6 +5,22 @@ import 'api.dart';
import 'init.dart'; import 'init.dart';
class MsgHttp { class MsgHttp {
static Future msgFeedUnread() async {
var res = await Request().get(Api.msgFeedUnread);
if (res.data['code'] == 0) {
return {
'status': true,
'data': res.data['data'],
};
} else {
return {
'status': false,
'date': [],
'msg': res.data['message'],
};
}
}
// 会话列表 // 会话列表
static Future sessionList({int? endTs}) async { static Future sessionList({int? endTs}) async {
Map<String, dynamic> params = { Map<String, dynamic> params = {

View File

@@ -0,0 +1,26 @@
class MsgFeedUnread {
MsgFeedUnread({
this.at = 0,
this.chat = 0,
this.like = 0,
this.reply = 0,
this.sys_msg = 0,
this.up = 0,
});
int at = 0;
int chat = 0;
int like = 0;
int reply = 0;
int sys_msg = 0;
int up = 0;
MsgFeedUnread.fromJson(Map<String, dynamic> json) {
at = json['at'] ?? 0;
chat = json['chat'] ?? 0;
like = json['like'] ?? 0;
reply = json['reply'] ?? 0;
sys_msg = json['sys_msg'] ?? 0;
up = json['up'] ?? 0;
}
}

View File

@@ -1,12 +1,58 @@
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/http/msg.dart'; import 'package:pilipala/http/msg.dart';
import 'package:pilipala/models/msg/account.dart'; import 'package:pilipala/models/msg/account.dart';
import 'package:pilipala/models/msg/session.dart'; import 'package:pilipala/models/msg/session.dart';
import '../../models/msg/msgfeed_unread.dart';
class WhisperController extends GetxController { class WhisperController extends GetxController {
RxList<SessionList> sessionList = <SessionList>[].obs; RxList<SessionList> sessionList = <SessionList>[].obs;
RxList<AccountListModel> accountList = <AccountListModel>[].obs; RxList<AccountListModel> accountList = <AccountListModel>[].obs;
bool isLoading = false; bool isLoading = false;
Rx<MsgFeedUnread> msgFeedUnread = MsgFeedUnread().obs;
RxList msgFeedTop = [
{
"name":"回复我的",
"icon":Icons.message_outlined,
"route": "/",
"value": 0
},
{
"name":"@我",
"icon":Icons.alternate_email_outlined,
"route": "/",
"value": 0
},
{
"name":"收到的赞",
"icon":Icons.favorite_border_outlined,
"route": "/",
"value": 0
},
{
"name":"系统通知",
"icon":Icons.notifications_none_outlined,
"route": "/",
"value": 0
},
].obs;
Future queryMsgFeedUnread() async {
var res = await MsgHttp.msgFeedUnread();
if (res['status']) {
msgFeedUnread.value = MsgFeedUnread.fromJson(res['data']);
msgFeedTop.value[0]["value"] = msgFeedUnread.value.reply;
msgFeedTop.value[1]["value"] = msgFeedUnread.value.at;
msgFeedTop.value[2]["value"] = msgFeedUnread.value.like;
msgFeedTop.value[3]["value"] = msgFeedUnread.value.sys_msg;
// 触发更新
msgFeedTop.refresh();
} else {
SmartDialog.showToast(res['msg']);
}
}
Future querySessionList(String? type) async { Future querySessionList(String? type) async {
if (isLoading) return; if (isLoading) return;

View File

@@ -22,6 +22,7 @@ class _WhisperPageState extends State<WhisperPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_whisperController.queryMsgFeedUnread();
_futureBuilderFuture = _whisperController.querySessionList('init'); _futureBuilderFuture = _whisperController.querySessionList('init');
_scrollController.addListener(_scrollListener); _scrollController.addListener(_scrollListener);
} }
@@ -43,60 +44,7 @@ class _WhisperPageState extends State<WhisperPage> {
appBar: AppBar( appBar: AppBar(
title: const Text('消息'), title: const Text('消息'),
), ),
body: Column( body: RefreshIndicator(
children: [
// LayoutBuilder(
// builder: (BuildContext context, BoxConstraints constraints) {
// // 在这里根据父级容器的约束条件构建小部件树
// return Padding(
// padding: const EdgeInsets.only(left: 20, right: 20),
// child: SizedBox(
// height: constraints.maxWidth / 5,
// child: GridView.count(
// primary: false,
// crossAxisCount: 4,
// padding: const EdgeInsets.all(0),
// childAspectRatio: 1.25,
// children: [
// Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// SizedBox(
// width: 36,
// height: 36,
// child: IconButton(
// style: ButtonStyle(
// padding:
// MaterialStateProperty.all(EdgeInsets.zero),
// backgroundColor:
// MaterialStateProperty.resolveWith((states) {
// return Theme.of(context)
// .colorScheme
// .primary
// .withOpacity(0.1);
// }),
// ),
// onPressed: () {},
// icon: Icon(
// Icons.message_outlined,
// size: 18,
// color: Theme.of(context).colorScheme.primary,
// ),
// ),
// ),
// const SizedBox(height: 6),
// const Text('回复我的', style: TextStyle(fontSize: 13))
// ],
// ),
// ],
// ),
// ),
// );
// },
// ),
Expanded(
child: RefreshIndicator(
onRefresh: () async { onRefresh: () async {
await _whisperController.onRefresh(); await _whisperController.onRefresh();
}, },
@@ -104,6 +52,73 @@ class _WhisperPageState extends State<WhisperPage> {
controller: _scrollController, controller: _scrollController,
child: Column( child: Column(
children: [ children: [
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
// 在这里根据父级容器的约束条件构建小部件树
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: SizedBox(
height: constraints.maxWidth / 5,
child: Obx(
() => GridView.count(
primary: false,
crossAxisCount: 4,
padding: const EdgeInsets.all(0),
childAspectRatio: 1.25,
children:
_whisperController.msgFeedTop.value.map((item) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Badge(
isLabelVisible: item['value'] > 0,
backgroundColor:
Theme.of(context).colorScheme.primary,
textColor: Theme.of(context)
.colorScheme
.onInverseSurface,
label: Text(" ${item['value']} "),
alignment: Alignment.topRight,
child: SizedBox(
width: 36,
height: 36,
child: IconButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(
EdgeInsets.zero),
backgroundColor:
MaterialStateProperty.resolveWith(
(states) {
return Theme.of(context)
.colorScheme
.primary
.withOpacity(0.1);
}),
),
onPressed: () => Get.toNamed(
item['route'],
),
icon: Icon(
item['icon'],
size: 18,
color: Theme.of(context)
.colorScheme
.primary,
),
),
)),
const SizedBox(height: 6),
Text(item['name'],
style: const TextStyle(fontSize: 13))
],
);
}).toList(),
),
),
),
);
}),
FutureBuilder( FutureBuilder(
future: _futureBuilderFuture, future: _futureBuilderFuture,
builder: (context, snapshot) { builder: (context, snapshot) {
@@ -117,22 +132,16 @@ class _WhisperPageState extends State<WhisperPage> {
: ListView.separated( : ListView.separated(
itemCount: sessionList.length, itemCount: sessionList.length,
shrinkWrap: true, shrinkWrap: true,
physics: physics: const NeverScrollableScrollPhysics(),
const NeverScrollableScrollPhysics(),
itemBuilder: (_, int i) { itemBuilder: (_, int i) {
return ListTile( return ListTile(
onTap: () => Get.toNamed( onTap: () => Get.toNamed(
'/whisperDetail', '/whisperDetail',
parameters: { parameters: {
'talkerId': sessionList[i] 'talkerId':
.talkerId sessionList[i].talkerId.toString(),
.toString(), 'name': sessionList[i].accountInfo.name,
'name': sessionList[i] 'face': sessionList[i].accountInfo.face,
.accountInfo
.name,
'face': sessionList[i]
.accountInfo
.face,
'mid': sessionList[i] 'mid': sessionList[i]
.accountInfo .accountInfo
.mid .mid
@@ -142,9 +151,8 @@ class _WhisperPageState extends State<WhisperPage> {
leading: Badge( leading: Badge(
isLabelVisible: isLabelVisible:
sessionList[i].unreadCount > 0, sessionList[i].unreadCount > 0,
backgroundColor: Theme.of(context) backgroundColor:
.colorScheme Theme.of(context).colorScheme.primary,
.primary,
textColor: Theme.of(context) textColor: Theme.of(context)
.colorScheme .colorScheme
.onInverseSurface, .onInverseSurface,
@@ -155,13 +163,11 @@ class _WhisperPageState extends State<WhisperPage> {
width: 45, width: 45,
height: 45, height: 45,
type: 'avatar', type: 'avatar',
src: sessionList[i] src: sessionList[i].accountInfo.face,
.accountInfo
.face,
), ),
), ),
title: Text( title:
sessionList[i].accountInfo.name), Text(sessionList[i].accountInfo.name),
subtitle: Text( subtitle: Text(
sessionList[i] sessionList[i]
.lastMsg .lastMsg
@@ -174,8 +180,7 @@ class _WhisperPageState extends State<WhisperPage> {
.content['title'] ?? .content['title'] ??
sessionList[i] sessionList[i]
.lastMsg .lastMsg
.content[ .content['reply_content'] ??
'reply_content'] ??
'', '',
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@@ -187,9 +192,8 @@ class _WhisperPageState extends State<WhisperPage> {
.colorScheme .colorScheme
.outline)), .outline)),
trailing: Text( trailing: Text(
Utils.dateFormat(sessionList[i] Utils.dateFormat(
.lastMsg sessionList[i].lastMsg.timestamp),
.timestamp),
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.labelSmall! .labelSmall!
@@ -225,9 +229,6 @@ class _WhisperPageState extends State<WhisperPage> {
), ),
), ),
), ),
),
],
),
); );
} }
} }