From 88084e1f05319fbe204d468702c60960d3be3170 Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Mon, 30 Sep 2024 09:28:23 +0800 Subject: [PATCH] opt: sys msg --- lib/pages/msg_feed_top/sys_msg/view.dart | 158 ++++++++++++++++++----- 1 file changed, 125 insertions(+), 33 deletions(-) diff --git a/lib/pages/msg_feed_top/sys_msg/view.dart b/lib/pages/msg_feed_top/sys_msg/view.dart index 9ccb7777..efe418a9 100644 --- a/lib/pages/msg_feed_top/sys_msg/view.dart +++ b/lib/pages/msg_feed_top/sys_msg/view.dart @@ -1,7 +1,11 @@ import 'dart:convert'; +import 'package:PiliPalaX/utils/app_scheme.dart'; +import 'package:PiliPalaX/utils/utils.dart'; import 'package:easy_debounce/easy_throttle.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'; @@ -78,41 +82,48 @@ class _SysMsgPageState extends State { } 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, + onTap: () {}, + title: Text( + "${_sysMsgController.msgFeedSysMsgList[i].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.75), + ), + ), + const SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ - const SizedBox(height: 4), - SelectableText("$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))), - ])); + "${_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( @@ -130,4 +141,85 @@ class _SysMsgPageState extends State { ), ); } + + InlineSpan _buildContent(String content) { + final List spanChildren = []; + RegExp urlRegExp = RegExp('#\\{([^}]*)\\}\\{"([^}]*)"\\}'); + Iterable matches = urlRegExp.allMatches(content); + int previousEndIndex = 0; + if (matches.isNotEmpty) { + for (final Match match in matches) { + if (match.start > previousEndIndex) { + spanChildren.add( + TextSpan( + text: content.substring(previousEndIndex, match.start), + ), + ); + } + spanChildren.add( + TextSpan( + text: match.group(1), + style: TextStyle(color: Theme.of(context).colorScheme.primary), + recognizer: TapGestureRecognizer() + ..onTap = () { + try { + Uri uri = Uri.parse(match.group(2)!); + PiliScheme.routePush(uri); + } catch (err) { + SmartDialog.showToast(err.toString()); + } + }, + ), + ); + previousEndIndex = match.end; + } + } else { + urlRegExp = RegExp( + 'https?:\\/\\/[^\\s/\$.?#].[^\\s]*|www\\.[^\\s/\$.?#].[^\\s]*'); + matches = urlRegExp.allMatches(content); + if (matches.isNotEmpty) { + for (final Match match in matches) { + if (match.start > previousEndIndex) { + spanChildren.add( + TextSpan( + text: content.substring(previousEndIndex, match.start), + ), + ); + } + spanChildren.add( + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + size: MediaQuery.of(context).textScaler.scale(14), + Icons.link, + color: Theme.of(context).colorScheme.primary, + ), + ), + ); + spanChildren.add( + TextSpan( + text: '网页链接', + style: TextStyle(color: Theme.of(context).colorScheme.primary), + recognizer: TapGestureRecognizer() + ..onTap = () { + try { + Uri uri = Uri.parse(match.group(0)!); + PiliScheme.routePush(uri); + } catch (err) { + SmartDialog.showToast(err.toString()); + Utils.copyText(match.group(0) ?? ''); + } + }, + ), + ); + previousEndIndex = match.end; + } + } else { + spanChildren.add( + TextSpan(text: content), + ); + } + } + return TextSpan(children: spanChildren); + } }