Files
PiliPlus/lib/pages/msg_feed_top/sys_msg/view.dart
dom e1b73f4766 refa: query data (#659)
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-04-10 21:43:01 +08:00

240 lines
8.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:convert';
import 'package:PiliPlus/common/widgets/dialog.dart';
import 'package:PiliPlus/common/widgets/loading_widget.dart';
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/msg/msgfeed_sys_msg.dart';
import 'package:PiliPlus/utils/app_scheme.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.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 = Get.put(SysMsgController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('系统通知'),
),
body: refreshIndicator(
onRefresh: () async {
await _sysMsgController.onRefresh();
},
child: Obx(() => _buildBody(_sysMsgController.loadingState.value)),
),
);
}
Widget _buildBody(LoadingState<List<SystemNotifyList>?> loadingState) {
return switch (loadingState) {
Loading() => loadingWidget,
Success() => loadingState.response?.isNotEmpty == true
? ListView.separated(
itemCount: loadingState.response!.length,
physics: const AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom + 80),
itemBuilder: (context, int index) {
if (index == loadingState.response!.length - 1) {
_sysMsgController.onLoadMore();
}
final item = loadingState.response![index];
String? content = item.content;
if (content != null) {
try {
dynamic jsonContent = json.decode(content);
if (jsonContent != null && jsonContent['web'] != null) {
content = jsonContent['web'];
}
} catch (_) {}
}
return ListTile(
onTap: () {},
onLongPress: () {
showConfirmDialog(
context: context,
title: '确定删除该通知?',
onConfirm: () {
_sysMsgController.onRemove(item.id, index);
},
);
},
title: Text(
"${item.title}",
style: Theme.of(context).textTheme.titleMedium,
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 4),
Text.rich(
_buildContent(content ?? ''),
style: TextStyle(
fontSize: 14,
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.85),
),
),
const SizedBox(height: 5),
SizedBox(
width: double.infinity,
child: Text(
"${item.timeAt}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
fontSize: 13,
color: Theme.of(context).colorScheme.outline,
),
textAlign: TextAlign.end,
),
),
],
),
);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(
indent: 72,
endIndent: 20,
height: 6,
color: Colors.grey.withOpacity(0.1),
);
},
)
: scrollErrorWidget(callback: _sysMsgController.onReload),
Error() => scrollErrorWidget(
errMsg: loadingState.errMsg,
callback: _sysMsgController.onReload,
),
LoadingState() => throw UnimplementedError(),
};
}
InlineSpan _buildContent(String content) {
final List<InlineSpan> spanChildren = <InlineSpan>[];
RegExp urlRegExp = RegExp(
r'#\{([^}]*)\}\{([^}]*)\}|https?:\/\/[^\s/\$.?#].[^\s]*|www\.[^\s/\$.?#].[^\s]*|【(.*?)】|(\d+)');
content.splitMapJoin(
urlRegExp,
onMatch: (Match match) {
String matchStr = match[0]!;
if (matchStr.startsWith('#')) {
spanChildren.add(
TextSpan(
text: match[1],
style: TextStyle(color: Theme.of(context).colorScheme.primary),
recognizer: TapGestureRecognizer()
..onTap = () {
try {
PiliScheme.routePushFromUrl(match[2]!.replaceAll('"', ''));
} catch (err) {
SmartDialog.showToast(err.toString());
}
},
),
);
} else if (matchStr.startsWith('')) {
try {
bool isBV = match[3]?.startsWith('BV') == true;
// validate
if (isBV) {
IdUtils.bv2av(match[3]!);
} else {
IdUtils.av2bv(int.parse(match[3]!));
}
spanChildren.add(TextSpan(text: ''));
spanChildren.add(
TextSpan(
text: match[3],
style: TextStyle(color: Theme.of(context).colorScheme.primary),
recognizer: TapGestureRecognizer()
..onTap = () {
try {
PiliScheme.videoPush(
isBV ? null : int.parse(match[3]!),
isBV ? match[3]! : null,
);
} catch (err) {
SmartDialog.showToast(err.toString());
}
},
),
);
spanChildren.add(TextSpan(text: ''));
} catch (e) {
spanChildren.add(TextSpan(text: match[0]));
}
} else if (matchStr.startsWith('')) {
try {
match[4]; // dynId
spanChildren.add(TextSpan(text: ''));
spanChildren.add(
TextSpan(
text: '查看动态',
style: TextStyle(color: Theme.of(context).colorScheme.primary),
recognizer: TapGestureRecognizer()
..onTap = () {
try {
Utils.pushDynFromId(match[4]);
} catch (err) {
SmartDialog.showToast(err.toString());
}
},
),
);
spanChildren.add(TextSpan(text: ''));
} catch (e) {
spanChildren.add(TextSpan(text: match[0]));
}
} else {
spanChildren.add(
TextSpan(
text: '\u{1F517}网页链接',
style: TextStyle(color: Theme.of(context).colorScheme.primary),
recognizer: TapGestureRecognizer()
..onTap = () {
try {
PiliScheme.routePushFromUrl(match[0]!);
} catch (err) {
SmartDialog.showToast(err.toString());
Utils.copyText(match[0] ?? '');
}
},
),
);
}
return '';
},
onNonMatch: (String nonMatchStr) {
spanChildren.add(
TextSpan(text: nonMatchStr),
);
return '';
},
);
return TextSpan(children: spanChildren);
}
}