mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 11:08:03 +08:00
@@ -35,7 +35,8 @@ class _AtMePageState extends State<AtMePage> {
|
||||
IconButton(
|
||||
onPressed: () => Get.to(
|
||||
const WhisperSettingsPage(
|
||||
imSettingType: IMSettingType.SETTING_TYPE_OLD_AT_ME),
|
||||
imSettingType: IMSettingType.SETTING_TYPE_OLD_AT_ME,
|
||||
),
|
||||
),
|
||||
icon: Icon(
|
||||
size: 20,
|
||||
@@ -53,9 +54,11 @@ class _AtMePageState extends State<AtMePage> {
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: Obx(
|
||||
() => _buildBody(theme, _atMeController.loadingState.value)),
|
||||
() => _buildBody(theme, _atMeController.loadingState.value),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -64,7 +67,9 @@ class _AtMePageState extends State<AtMePage> {
|
||||
}
|
||||
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<MsgAtItem>?> loadingState) {
|
||||
ThemeData theme,
|
||||
LoadingState<List<MsgAtItem>?> loadingState,
|
||||
) {
|
||||
late final divider = Divider(
|
||||
indent: 72,
|
||||
endIndent: 20,
|
||||
@@ -73,98 +78,102 @@ class _AtMePageState extends State<AtMePage> {
|
||||
);
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
Success(:var response) => response?.isNotEmpty == true
|
||||
? SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, int index) {
|
||||
if (index == response.length - 1) {
|
||||
_atMeController.onLoadMore();
|
||||
}
|
||||
final item = response[index];
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
String? nativeUri = item.item?.nativeUri;
|
||||
if (nativeUri == null ||
|
||||
nativeUri.isEmpty ||
|
||||
nativeUri.startsWith('?')) {
|
||||
return;
|
||||
}
|
||||
PiliScheme.routePushFromUrl(nativeUri);
|
||||
},
|
||||
onLongPress: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该通知?',
|
||||
onConfirm: () => _atMeController.onRemove(item.id, index),
|
||||
),
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.user?.mid}'),
|
||||
child: NetworkImgLayer(
|
||||
width: 45,
|
||||
height: 45,
|
||||
type: ImageType.avatar,
|
||||
src: item.user?.avatar,
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
Success(:var response) =>
|
||||
response?.isNotEmpty == true
|
||||
? SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, int index) {
|
||||
if (index == response.length - 1) {
|
||||
_atMeController.onLoadMore();
|
||||
}
|
||||
final item = response[index];
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
String? nativeUri = item.item?.nativeUri;
|
||||
if (nativeUri == null ||
|
||||
nativeUri.isEmpty ||
|
||||
nativeUri.startsWith('?')) {
|
||||
return;
|
||||
}
|
||||
PiliScheme.routePushFromUrl(nativeUri);
|
||||
},
|
||||
onLongPress: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该通知?',
|
||||
onConfirm: () => _atMeController.onRemove(item.id, index),
|
||||
),
|
||||
),
|
||||
title: Text.rich(
|
||||
TextSpan(
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.user?.mid}'),
|
||||
child: NetworkImgLayer(
|
||||
width: 45,
|
||||
height: 45,
|
||||
type: ImageType.avatar,
|
||||
src: item.user?.avatar,
|
||||
),
|
||||
),
|
||||
title: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.user?.nickname}",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " 在${item.item?.business}中@了我",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.user?.nickname}",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " 在${item.item?.business}中@了我",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item.item?.sourceContent?.isNotEmpty == true) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(item.item!.sourceContent!,
|
||||
if (item.item?.sourceContent?.isNotEmpty == true) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
item.item!.sourceContent!,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.bodyMedium!
|
||||
.copyWith(color: theme.colorScheme.outline)),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
DateUtil.dateFormat(item.atTime),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
DateUtil.dateFormat(item.atTime),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
trailing: item.item?.image != null && item.item?.image != ""
|
||||
? NetworkImgLayer(
|
||||
width: 45,
|
||||
height: 45,
|
||||
src: item.item?.image,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
)
|
||||
: HttpError(onReload: _atMeController.onReload),
|
||||
],
|
||||
),
|
||||
trailing: item.item?.image != null && item.item?.image != ""
|
||||
? NetworkImgLayer(
|
||||
width: 45,
|
||||
height: 45,
|
||||
src: item.item?.image,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
)
|
||||
: HttpError(onReload: _atMeController.onReload),
|
||||
Error(:var errMsg) => HttpError(
|
||||
errMsg: errMsg,
|
||||
onReload: _atMeController.onReload,
|
||||
),
|
||||
errMsg: errMsg,
|
||||
onReload: _atMeController.onReload,
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,10 @@ class LikeDetailPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LikeDetailPageState extends State<LikeDetailPage> {
|
||||
final LikeDetailController _controller =
|
||||
Get.put(LikeDetailController(), tag: Utils.generateRandomString(8));
|
||||
final LikeDetailController _controller = Get.put(
|
||||
LikeDetailController(),
|
||||
tag: Utils.generateRandomString(8),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -36,9 +38,11 @@ class _LikeDetailPageState extends State<LikeDetailPage> {
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver:
|
||||
Obx(() => _buildBody(theme, _controller.loadingState.value)),
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: Obx(
|
||||
() => _buildBody(theme, _controller.loadingState.value),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -47,7 +51,9 @@ class _LikeDetailPageState extends State<LikeDetailPage> {
|
||||
}
|
||||
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<MsgLikeDetailItem>?> loadingState) {
|
||||
ThemeData theme,
|
||||
LoadingState<List<MsgLikeDetailItem>?> loadingState,
|
||||
) {
|
||||
late final divider = Divider(
|
||||
indent: 72,
|
||||
endIndent: 20,
|
||||
@@ -56,38 +62,38 @@ class _LikeDetailPageState extends State<LikeDetailPage> {
|
||||
);
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
Success(:var response) => SliverMainAxisGroup(
|
||||
slivers: [
|
||||
if (_controller.card != null) ...[
|
||||
_buildCard(_controller.card!),
|
||||
SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
height: 1,
|
||||
color: Colors.grey.withValues(alpha: 0.1),
|
||||
),
|
||||
slivers: [
|
||||
if (_controller.card != null) ...[
|
||||
_buildCard(_controller.card!),
|
||||
SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
height: 1,
|
||||
color: Colors.grey.withValues(alpha: 0.1),
|
||||
),
|
||||
],
|
||||
SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == response.length - 1) {
|
||||
_controller.onLoadMore();
|
||||
}
|
||||
return _buildItem(theme, response[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
),
|
||||
],
|
||||
),
|
||||
SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == response.length - 1) {
|
||||
_controller.onLoadMore();
|
||||
}
|
||||
return _buildItem(theme, response[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
),
|
||||
],
|
||||
),
|
||||
Error(:var errMsg) => HttpError(
|
||||
errMsg: errMsg,
|
||||
onReload: _controller.onReload,
|
||||
),
|
||||
errMsg: errMsg,
|
||||
onReload: _controller.onReload,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -118,8 +124,10 @@ class _LikeDetailPageState extends State<LikeDetailPage> {
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.user!.nickname}",
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(height: 1.5, color: theme.colorScheme.primary),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
height: 1.5,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " 赞了我",
|
||||
|
||||
@@ -7,8 +7,12 @@ import 'package:PiliPlus/pages/common/common_data_controller.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
|
||||
class LikeMeController extends CommonDataController<MsgLikeData,
|
||||
Pair<List<MsgLikeItem>, List<MsgLikeItem>>> {
|
||||
class LikeMeController
|
||||
extends
|
||||
CommonDataController<
|
||||
MsgLikeData,
|
||||
Pair<List<MsgLikeItem>, List<MsgLikeItem>>
|
||||
> {
|
||||
int? cursor;
|
||||
int? cursorTime;
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
IconButton(
|
||||
onPressed: () => Get.to(
|
||||
const WhisperSettingsPage(
|
||||
imSettingType: IMSettingType.SETTING_TYPE_OLD_RECEIVE_LIKE),
|
||||
imSettingType: IMSettingType.SETTING_TYPE_OLD_RECEIVE_LIKE,
|
||||
),
|
||||
),
|
||||
icon: Icon(
|
||||
size: 20,
|
||||
@@ -54,9 +55,11 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver: Obx(() =>
|
||||
_buildBody(theme, _likeMeController.loadingState.value)),
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: Obx(
|
||||
() => _buildBody(theme, _likeMeController.loadingState.value),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -73,67 +76,67 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
);
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
Success(:var response) => Builder(
|
||||
builder: (context) {
|
||||
Pair<List<MsgLikeItem>, List<MsgLikeItem>> pair = response;
|
||||
List<MsgLikeItem> latest = pair.first;
|
||||
List<MsgLikeItem> total = pair.second;
|
||||
if (latest.isNotEmpty || total.isNotEmpty) {
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
if (latest.isNotEmpty) ...[
|
||||
_buildHeader(theme, '最新'),
|
||||
SliverList.separated(
|
||||
itemBuilder: (context, index) {
|
||||
if (total.isEmpty && index == latest.length - 1) {
|
||||
_likeMeController.onLoadMore();
|
||||
}
|
||||
return _buildItem(
|
||||
theme,
|
||||
latest[index],
|
||||
(id) {
|
||||
_likeMeController.onRemove(id, index, true);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount: latest.length,
|
||||
separatorBuilder: (context, index) => divider,
|
||||
),
|
||||
],
|
||||
if (total.isNotEmpty) ...[
|
||||
_buildHeader(theme, '累计'),
|
||||
SliverList.separated(
|
||||
itemBuilder: (context, index) {
|
||||
if (index == total.length - 1) {
|
||||
_likeMeController.onLoadMore();
|
||||
}
|
||||
return _buildItem(
|
||||
theme,
|
||||
total[index],
|
||||
(id) {
|
||||
_likeMeController.onRemove(id, index, false);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount: total.length,
|
||||
separatorBuilder: (context, index) => divider,
|
||||
),
|
||||
],
|
||||
builder: (context) {
|
||||
Pair<List<MsgLikeItem>, List<MsgLikeItem>> pair = response;
|
||||
List<MsgLikeItem> latest = pair.first;
|
||||
List<MsgLikeItem> total = pair.second;
|
||||
if (latest.isNotEmpty || total.isNotEmpty) {
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
if (latest.isNotEmpty) ...[
|
||||
_buildHeader(theme, '最新'),
|
||||
SliverList.separated(
|
||||
itemBuilder: (context, index) {
|
||||
if (total.isEmpty && index == latest.length - 1) {
|
||||
_likeMeController.onLoadMore();
|
||||
}
|
||||
return _buildItem(
|
||||
theme,
|
||||
latest[index],
|
||||
(id) {
|
||||
_likeMeController.onRemove(id, index, true);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount: latest.length,
|
||||
separatorBuilder: (context, index) => divider,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return HttpError(onReload: _likeMeController.onReload);
|
||||
},
|
||||
),
|
||||
if (total.isNotEmpty) ...[
|
||||
_buildHeader(theme, '累计'),
|
||||
SliverList.separated(
|
||||
itemBuilder: (context, index) {
|
||||
if (index == total.length - 1) {
|
||||
_likeMeController.onLoadMore();
|
||||
}
|
||||
return _buildItem(
|
||||
theme,
|
||||
total[index],
|
||||
(id) {
|
||||
_likeMeController.onRemove(id, index, false);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount: total.length,
|
||||
separatorBuilder: (context, index) => divider,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
return HttpError(onReload: _likeMeController.onReload);
|
||||
},
|
||||
),
|
||||
Error(:var errMsg) => HttpError(
|
||||
errMsg: errMsg,
|
||||
onReload: _likeMeController.onReload,
|
||||
),
|
||||
errMsg: errMsg,
|
||||
onReload: _likeMeController.onReload,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -241,19 +244,22 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
for (var j = 0;
|
||||
j < item.users!.length && j < 4;
|
||||
j++) ...<Widget>[
|
||||
for (
|
||||
var j = 0;
|
||||
j < item.users!.length && j < 4;
|
||||
j++
|
||||
) ...<Widget>[
|
||||
Positioned(
|
||||
left: 15 * (j % 2).toDouble(),
|
||||
top: 15 * (j ~/ 2).toDouble(),
|
||||
child: NetworkImgLayer(
|
||||
width: item.users!.length > 1 ? 30 : 45,
|
||||
height: item.users!.length > 1 ? 30 : 45,
|
||||
type: ImageType.avatar,
|
||||
src: item.users![j].avatar,
|
||||
)),
|
||||
]
|
||||
left: 15 * (j % 2).toDouble(),
|
||||
top: 15 * (j ~/ 2).toDouble(),
|
||||
child: NetworkImgLayer(
|
||||
width: item.users!.length > 1 ? 30 : 45,
|
||||
height: item.users!.length > 1 ? 30 : 45,
|
||||
type: ImageType.avatar,
|
||||
src: item.users![j].avatar,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -265,14 +271,18 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.users![0].nickname}",
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(height: 1.5, color: theme.colorScheme.primary),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
height: 1.5,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
if (item.counts! > 1)
|
||||
TextSpan(
|
||||
text: ' 等${item.counts}人',
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(fontSize: 12, height: 1.5),
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
fontSize: 12,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " 赞了我的${item.item?.business}",
|
||||
@@ -291,11 +301,15 @@ class _LikeMePageState extends State<LikeMePage> {
|
||||
children: [
|
||||
if (item.item?.title?.isNotEmpty == true) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(item.item!.title!,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.bodyMedium!
|
||||
.copyWith(color: theme.colorScheme.outline, height: 1.5)),
|
||||
Text(
|
||||
item.item!.title!,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
color: theme.colorScheme.outline,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
|
||||
@@ -35,7 +35,8 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
IconButton(
|
||||
onPressed: () => Get.to(
|
||||
const WhisperSettingsPage(
|
||||
imSettingType: IMSettingType.SETTING_TYPE_OLD_REPLY_ME),
|
||||
imSettingType: IMSettingType.SETTING_TYPE_OLD_REPLY_ME,
|
||||
),
|
||||
),
|
||||
icon: Icon(
|
||||
size: 20,
|
||||
@@ -53,9 +54,11 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver: Obx(() =>
|
||||
_buildBody(theme, _replyMeController.loadingState.value)),
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: Obx(
|
||||
() => _buildBody(theme, _replyMeController.loadingState.value),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -64,7 +67,9 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
}
|
||||
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<MsgReplyItem>?> loadingState) {
|
||||
ThemeData theme,
|
||||
LoadingState<List<MsgReplyItem>?> loadingState,
|
||||
) {
|
||||
late final divider = Divider(
|
||||
indent: 72,
|
||||
endIndent: 20,
|
||||
@@ -73,111 +78,125 @@ class _ReplyMePageState extends State<ReplyMePage> {
|
||||
);
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverList.builder(
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
Success(:var response) => response?.isNotEmpty == true
|
||||
? SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, int index) {
|
||||
if (index == response.length - 1) {
|
||||
_replyMeController.onLoadMore();
|
||||
}
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedTopSkeleton();
|
||||
},
|
||||
),
|
||||
Success(:var response) =>
|
||||
response?.isNotEmpty == true
|
||||
? SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, int index) {
|
||||
if (index == response.length - 1) {
|
||||
_replyMeController.onLoadMore();
|
||||
}
|
||||
|
||||
MsgReplyItem item = response[index];
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
String? nativeUri = item.item?.nativeUri;
|
||||
if (nativeUri == null ||
|
||||
nativeUri.isEmpty ||
|
||||
nativeUri.startsWith('?')) {
|
||||
return;
|
||||
}
|
||||
PiliScheme.routePushFromUrl(
|
||||
nativeUri,
|
||||
businessId: item.item?.businessId,
|
||||
oid: item.item?.subjectId,
|
||||
);
|
||||
},
|
||||
onLongPress: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该通知?',
|
||||
onConfirm: () =>
|
||||
_replyMeController.onRemove(item.id, index),
|
||||
),
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.user?.mid}'),
|
||||
child: NetworkImgLayer(
|
||||
width: 45,
|
||||
height: 45,
|
||||
type: ImageType.avatar,
|
||||
src: item.user?.avatar,
|
||||
MsgReplyItem item = response[index];
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
String? nativeUri = item.item?.nativeUri;
|
||||
if (nativeUri == null ||
|
||||
nativeUri.isEmpty ||
|
||||
nativeUri.startsWith('?')) {
|
||||
return;
|
||||
}
|
||||
PiliScheme.routePushFromUrl(
|
||||
nativeUri,
|
||||
businessId: item.item?.businessId,
|
||||
oid: item.item?.subjectId,
|
||||
);
|
||||
},
|
||||
onLongPress: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该通知?',
|
||||
onConfirm: () =>
|
||||
_replyMeController.onRemove(item.id, index),
|
||||
),
|
||||
),
|
||||
title: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "${item.user?.nickname}",
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(color: theme.colorScheme.primary),
|
||||
),
|
||||
if (item.isMulti == 1)
|
||||
leading: GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.user?.mid}'),
|
||||
child: NetworkImgLayer(
|
||||
width: 45,
|
||||
height: 45,
|
||||
type: ImageType.avatar,
|
||||
src: item.user?.avatar,
|
||||
),
|
||||
),
|
||||
title: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: " 等人",
|
||||
style: theme.textTheme.titleSmall!
|
||||
.copyWith(fontSize: 12),
|
||||
text: "${item.user?.nickname}",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
if (item.isMulti == 1)
|
||||
TextSpan(
|
||||
text: " 等人",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
" 对我的${item.item?.business}发布了${item.counts}条评论",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
item.item?.sourceContent ?? "",
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (item.item?.targetReplyContent != null &&
|
||||
item.item?.targetReplyContent != "")
|
||||
Text(
|
||||
"| ${item.item?.targetReplyContent}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
color: theme.colorScheme.outline,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
if (item.item?.rootReplyContent != null &&
|
||||
item.item?.rootReplyContent != "")
|
||||
Text(
|
||||
" | ${item.item?.rootReplyContent}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
color: theme.colorScheme.outline,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
DateUtil.dateFormat(item.replyTime),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
" 对我的${item.item?.business}发布了${item.counts}条评论",
|
||||
style: theme.textTheme.titleSmall!.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text(item.item?.sourceContent ?? "",
|
||||
style: theme.textTheme.bodyMedium),
|
||||
const SizedBox(height: 4),
|
||||
if (item.item?.targetReplyContent != null &&
|
||||
item.item?.targetReplyContent != "")
|
||||
Text("| ${item.item?.targetReplyContent}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
color: theme.colorScheme.outline, height: 1.5)),
|
||||
if (item.item?.rootReplyContent != null &&
|
||||
item.item?.rootReplyContent != "")
|
||||
Text(" | ${item.item?.rootReplyContent}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.labelMedium!.copyWith(
|
||||
color: theme.colorScheme.outline, height: 1.5)),
|
||||
Text(
|
||||
DateUtil.dateFormat(item.replyTime),
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
)
|
||||
: HttpError(onReload: _replyMeController.onReload),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
)
|
||||
: HttpError(onReload: _replyMeController.onReload),
|
||||
Error(:var errMsg) => HttpError(
|
||||
errMsg: errMsg,
|
||||
onReload: _replyMeController.onReload,
|
||||
),
|
||||
errMsg: errMsg,
|
||||
onReload: _replyMeController.onReload,
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ class SysMsgPage extends StatefulWidget {
|
||||
class _SysMsgPageState extends State<SysMsgPage> {
|
||||
late final _sysMsgController = Get.put(SysMsgController());
|
||||
late final RegExp urlRegExp = RegExp(
|
||||
r'#\{([^}]*)\}\{([^}]*)\}|https?:\/\/[^\s/\$.?#].[^\s]*|www\.[^\s/\$.?#].[^\s]*|【(.*?)】|((\d+))');
|
||||
r'#\{([^}]*)\}\{([^}]*)\}|https?:\/\/[^\s/\$.?#].[^\s]*|www\.[^\s/\$.?#].[^\s]*|【(.*?)】|((\d+))',
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -40,9 +41,11 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80),
|
||||
sliver: Obx(() =>
|
||||
_buildBody(theme, _sysMsgController.loadingState.value)),
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: Obx(
|
||||
() => _buildBody(theme, _sysMsgController.loadingState.value),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -51,7 +54,9 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
}
|
||||
|
||||
Widget _buildBody(
|
||||
ThemeData theme, LoadingState<List<MsgSysItem>?> loadingState) {
|
||||
ThemeData theme,
|
||||
LoadingState<List<MsgSysItem>?> loadingState,
|
||||
) {
|
||||
late final divider = Divider(
|
||||
indent: 72,
|
||||
endIndent: 20,
|
||||
@@ -60,67 +65,70 @@ class _SysMsgPageState extends State<SysMsgPage> {
|
||||
);
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverSafeArea(
|
||||
sliver: SliverList.builder(
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedSysMsgSkeleton();
|
||||
},
|
||||
),
|
||||
sliver: SliverList.builder(
|
||||
itemCount: 12,
|
||||
itemBuilder: (context, index) {
|
||||
return const MsgFeedSysMsgSkeleton();
|
||||
},
|
||||
),
|
||||
Success(:var response) => response?.isNotEmpty == true
|
||||
? SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, int index) {
|
||||
if (index == response.length - 1) {
|
||||
_sysMsgController.onLoadMore();
|
||||
}
|
||||
final item = response[index];
|
||||
return ListTile(
|
||||
onLongPress: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该通知?',
|
||||
onConfirm: () => _sysMsgController.onRemove(item.id, index),
|
||||
),
|
||||
title: Text(
|
||||
"${item.title}",
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text.rich(
|
||||
_buildContent(theme, item.content ?? ''),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: theme.colorScheme.onSurface
|
||||
.withValues(alpha: 0.85),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
"${item.timeAt}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
Success(:var response) =>
|
||||
response?.isNotEmpty == true
|
||||
? SliverList.separated(
|
||||
itemCount: response!.length,
|
||||
itemBuilder: (context, int index) {
|
||||
if (index == response.length - 1) {
|
||||
_sysMsgController.onLoadMore();
|
||||
}
|
||||
final item = response[index];
|
||||
return ListTile(
|
||||
onLongPress: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该通知?',
|
||||
onConfirm: () =>
|
||||
_sysMsgController.onRemove(item.id, index),
|
||||
),
|
||||
title: Text(
|
||||
"${item.title}",
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text.rich(
|
||||
_buildContent(theme, item.content ?? ''),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: theme.colorScheme.onSurface.withValues(
|
||||
alpha: 0.85,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
)
|
||||
: HttpError(onReload: _sysMsgController.onReload),
|
||||
const SizedBox(height: 5),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
"${item.timeAt}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => divider,
|
||||
)
|
||||
: HttpError(onReload: _sysMsgController.onReload),
|
||||
Error(:var errMsg) => HttpError(
|
||||
errMsg: errMsg,
|
||||
onReload: _sysMsgController.onReload,
|
||||
),
|
||||
errMsg: errMsg,
|
||||
onReload: _sysMsgController.onReload,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user