feat: 未读消息计数

This commit is contained in:
guozhigq
2024-06-15 20:34:28 +08:00
parent f62eae55d2
commit 86023e46a6
4 changed files with 194 additions and 135 deletions

View File

@ -539,4 +539,7 @@ class Api {
/// 关闭会话 /// 关闭会话
static const String removeSession = static const String removeSession =
'${HttpString.tUrl}/session_svr/v1/session_svr/remove_session'; '${HttpString.tUrl}/session_svr/v1/session_svr/remove_session';
/// 消息未读数
static const String unread = '${HttpString.tUrl}/x/im/web/msgfeed/unread';
} }

View File

@ -225,4 +225,16 @@ class MsgHttp {
return {'status': false, 'date': [], 'msg': res.data['message']}; return {'status': false, 'date': [], 'msg': res.data['message']};
} }
} }
static Future unread() async {
var res = await Request().get(Api.unread);
if (res.data['code'] == 0) {
return {
'status': true,
'data': res.data['data'],
};
} else {
return {'status': false, 'date': [], 'msg': res.data['message']};
}
}
} }

View File

@ -1,3 +1,4 @@
import 'package:flutter/material.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';
@ -7,6 +8,38 @@ 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;
RxList noticesList = [
{
'icon': Icons.message_outlined,
'title': '回复我的',
'path': '',
'count': 0,
},
{
'icon': Icons.alternate_email,
'title': '@ 我的',
'path': '',
'count': 0,
},
{
'icon': Icons.thumb_up_outlined,
'title': '收到的赞',
'path': '',
'count': 0,
},
{
'icon': Icons.notifications_none_outlined,
'title': '系统通知',
'path': '',
'count': 0,
}
].obs;
@override
void onInit() {
unread();
super.onInit();
}
Future querySessionList(String? type) async { Future querySessionList(String? type) async {
if (isLoading) return; if (isLoading) return;
@ -77,4 +110,16 @@ class WhisperController extends GetxController {
sessionList.removeWhere((p0) => p0.talkerId == talkerId); sessionList.removeWhere((p0) => p0.talkerId == talkerId);
sessionList.refresh(); sessionList.refresh();
} }
// 消息未读数
void unread() async {
var res = await MsgHttp.unread();
if (res['status']) {
noticesList[0]['count'] = res['data']['reply'];
noticesList[1]['count'] = res['data']['at'];
noticesList[2]['count'] = res['data']['like'];
noticesList[3]['count'] = res['data']['sys_msg'];
noticesList.refresh();
}
}
} }

View File

@ -1,6 +1,7 @@
import 'package:easy_debounce/easy_throttle.dart'; import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/skeleton/skeleton.dart'; import 'package:pilipala/common/skeleton/skeleton.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/utils.dart';
@ -44,147 +45,145 @@ class _WhisperPageState extends State<WhisperPage> {
appBar: AppBar( appBar: AppBar(
title: const Text('消息'), title: const Text('消息'),
), ),
body: Column( body: RefreshIndicator(
children: [ onRefresh: () async {
// LayoutBuilder( _whisperController.unread();
// builder: (BuildContext context, BoxConstraints constraints) { await _whisperController.onRefresh();
// // 在这里根据父级容器的约束条件构建小部件树 },
// return Padding( child: SingleChildScrollView(
// padding: const EdgeInsets.only(left: 20, right: 20), controller: _scrollController,
// child: SizedBox( child: Column(
// height: constraints.maxWidth / 5, children: [
// child: GridView.count( LayoutBuilder(
// primary: false, builder: (BuildContext context, BoxConstraints constraints) {
// crossAxisCount: 4, // 在这里根据父级容器的约束条件构建小部件树
// padding: const EdgeInsets.all(0), return Padding(
// childAspectRatio: 1.25, padding: const EdgeInsets.only(left: 20, right: 20),
// children: [ child: SizedBox(
// Column( height: constraints.maxWidth / 4,
// crossAxisAlignment: CrossAxisAlignment.center, child: Obx(
// mainAxisAlignment: MainAxisAlignment.center, () => GridView.count(
// children: [ primary: false,
// SizedBox( crossAxisCount: 4,
// width: 36, padding: const EdgeInsets.all(0),
// height: 36, children: [
// child: IconButton( ..._whisperController.noticesList.map((element) {
// style: ButtonStyle( return InkWell(
// padding: onTap: () => {},
// MaterialStateProperty.all(EdgeInsets.zero), onLongPress: () {},
// backgroundColor: borderRadius: StyleString.mdRadius,
// MaterialStateProperty.resolveWith((states) { child: Column(
// return Theme.of(context) mainAxisAlignment: MainAxisAlignment.center,
// .colorScheme children: [
// .primary Badge(
// .withOpacity(0.1); isLabelVisible: element['count'] > 0,
// }), label: Text(element['count'] > 99
// ), ? '99+'
// onPressed: () {}, : element['count'].toString()),
// icon: Icon( child: Padding(
// Icons.message_outlined, padding: const EdgeInsets.all(10),
// size: 18, child: Icon(
// color: Theme.of(context).colorScheme.primary, element['icon'],
// ), size: 21,
// ), color: Theme.of(context)
// ), .colorScheme
// const SizedBox(height: 6), .primary,
// const Text('回复我的', style: TextStyle(fontSize: 13)) ),
// ], ),
// ), ),
// ], const SizedBox(height: 4),
// ), Text(element['title'])
// ), ],
// );
// },
// ),
Expanded(
child: RefreshIndicator(
onRefresh: () async {
await _whisperController.onRefresh();
},
child: SingleChildScrollView(
controller: _scrollController,
child: FutureBuilder(
future: _futureBuilderFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map? data = snapshot.data;
if (data != null && data['status']) {
RxList sessionList = _whisperController.sessionList;
return Obx(
() => sessionList.isEmpty
? const SizedBox()
: ListView.separated(
itemCount: sessionList.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (_, int i) {
return SessionItem(
sessionItem: sessionList[i],
changeFucCall: () =>
sessionList.refresh(),
);
},
separatorBuilder:
(BuildContext context, int index) {
return Divider(
indent: 72,
endIndent: 20,
height: 6,
color: Colors.grey.withOpacity(0.1),
);
},
), ),
); );
} else { }).toList(),
// 请求错误 ],
return Center( ),
child: Text(data?['msg'] ?? '请求异常'), ),
); ),
} );
},
),
FutureBuilder(
future: _futureBuilderFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map? data = snapshot.data;
if (data != null && data['status']) {
RxList sessionList = _whisperController.sessionList;
return Obx(
() => sessionList.isEmpty
? const SizedBox()
: ListView.separated(
itemCount: sessionList.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (_, int i) {
return SessionItem(
sessionItem: sessionList[i],
changeFucCall: () => sessionList.refresh(),
);
},
separatorBuilder:
(BuildContext context, int index) {
return Divider(
indent: 72,
endIndent: 20,
height: 6,
color: Colors.grey.withOpacity(0.1),
);
},
),
);
} else { } else {
// 骨架屏 // 请求错误
return ListView.builder( return Center(
itemCount: 15, child: Text(data?['msg'] ?? '请求异常'),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, int i) {
return Skeleton(
child: ListTile(
leading: Container(
width: 45,
height: 45,
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.onInverseSurface,
borderRadius: BorderRadius.circular(25),
),
),
title: Container(
width: 100,
height: 14,
color: Theme.of(context)
.colorScheme
.onInverseSurface,
),
subtitle: Container(
width: 80,
height: 14,
color: Theme.of(context)
.colorScheme
.onInverseSurface,
),
),
);
},
); );
} }
}, } else {
), // 骨架屏
return ListView.builder(
itemCount: 15,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, int i) {
return Skeleton(
child: ListTile(
leading: Container(
width: 45,
height: 45,
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.onInverseSurface,
borderRadius: BorderRadius.circular(25),
),
),
title: Container(
width: 100,
height: 14,
color: Theme.of(context)
.colorScheme
.onInverseSurface,
),
subtitle: Container(
width: 80,
height: 14,
color: Theme.of(context)
.colorScheme
.onInverseSurface,
),
),
);
},
);
}
},
), ),
), ],
), ),
], ),
), ),
); );
} }