opt: system message

This commit is contained in:
guozhigq
2024-10-19 21:38:03 +08:00
parent be29f70b30
commit bb2d5e5494
4 changed files with 145 additions and 19 deletions

View File

@ -1,7 +1,10 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/models/msg/system.dart';
import 'package:pilipala/pages/message/utils/index.dart';
import 'package:pilipala/utils/app_scheme.dart';
import 'controller.dart';
class MessageSystemPage extends StatefulWidget {
@ -97,6 +100,13 @@ class SystemItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
// if (item.content is Map) {
// var res = MessageUtils().extractLinks(item.content['web']);
// print('res: $res');
// } else {
// var res = MessageUtils().extractLinks(item.content);
// print('res: $res');
// }
return Padding(
padding: const EdgeInsets.fromLTRB(14, 14, 14, 12),
child: Column(
@ -111,9 +121,73 @@ class SystemItem extends StatelessWidget {
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
const SizedBox(height: 6),
Text(item.content is String ? item.content : item.content!['web']),
Text.rich(
TextSpan(
children: [
buildContent(
context,
item.content is String ? item.content : item.content!['web']!,
),
],
),
),
// if (item.content is String)
// Text(item.content)
// else ...[
// Text(item.content!['web']!),
// ]
],
),
);
}
InlineSpan buildContent(
BuildContext context,
String content,
) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
final List<InlineSpan> spanChilds = <InlineSpan>[];
Map<String, dynamic> contentMap = MessageUtils().extractLinks(content);
List<String> keys = contentMap.keys.toList();
keys.removeWhere((element) => element == 'message');
String patternStr = keys.join('|');
RegExp regExp = RegExp(patternStr, caseSensitive: false);
contentMap['message'].splitMapJoin(
regExp,
onMatch: (Match match) {
if (!match.group(0)!.startsWith('BV')) {
spanChilds.add(
WidgetSpan(
child: Icon(Icons.link, color: colorScheme.primary, size: 16),
),
);
}
spanChilds.add(
TextSpan(
text: match.group(0),
style: TextStyle(
color: colorScheme.primary,
),
recognizer: TapGestureRecognizer()
..onTap = () {
PiliSchame.routePush(Uri.parse(contentMap[match.group(0)]));
},
),
);
return '';
},
onNonMatch: (String text) {
spanChilds.add(
TextSpan(
text: text,
),
);
return '';
},
);
return TextSpan(
children: spanChilds,
);
}
}

View File

@ -86,4 +86,56 @@ class MessageUtils {
),
);
}
// 匹配链接
Map<String, String> extractLinks(String text) {
Map<String, String> result = {};
String message = '';
// 是否匹配到bv
RegExp bvRegex = RegExp(r'bv1[\d\w]{9}', caseSensitive: false);
final Iterable<RegExpMatch> bvMatches = bvRegex.allMatches(text);
for (var match in bvMatches) {
result[match.group(0)!] =
'https://www.bilibili.com/video/${match.group(0)!}';
}
// 定义正则表达式
RegExp regex = RegExp(
r'(?:(?:(?:http:\/\/|https:\/\/)(?:[a-zA-Z0-9_.-]+\.)*(?:bilibili|biligame)\.com(?:\/[/.$*?~=#!%@&\-\w]*)?)|(?:(?:http:\/\/|https:\/\/)(?:[a-zA-Z0-9_.-]+\.)*(?:acg|b23)\.tv(?:\/[/.$*?~=#!%@&\-\w]*)?)|(?:(?:http:\/\/|https:\/\/)dl\.(?:hdslb)\.com(?:\/[/.$*?~=#!%@&\-\w]*)?))');
// 链接文字
RegExp linkTextRegex = RegExp(r"#\{(.*?)\}");
final Iterable<RegExpMatch> matches = regex.allMatches(text);
int lastMatchEnd = 0;
if (matches.isNotEmpty) {
for (var match in matches) {
final int start = match.start;
final int end = match.end;
String str = text.substring(lastMatchEnd, start);
final Iterable<RegExpMatch> linkTextMatches =
linkTextRegex.allMatches(str);
if (linkTextMatches.isNotEmpty) {
for (var linkTextMatch in linkTextMatches) {
if (linkTextMatch.group(1) != null) {
String linkText = linkTextMatch.group(1)!;
str = str
.replaceAll(linkTextMatch.group(0)!, linkText)
.replaceAll('{', '')
.replaceAll('}', '');
result[linkText] = match.group(0)!;
}
message += str;
}
} else {
message += '$str查看详情';
result['查看详情'] = match.group(0)!;
}
lastMatchEnd = end;
}
result['message'] = message;
} else {
result['message'] = text;
}
return result;
}
}

View File

@ -764,14 +764,14 @@ InlineSpan buildContent(
});
} else {
Uri uri = Uri.parse(matchStr.replaceAll('/?', '?'));
SchemeEntity scheme = SchemeEntity(
Uri scheme = Uri(
scheme: uri.scheme,
host: uri.host,
port: uri.port,
path: uri.path,
query: uri.queryParameters,
source: '',
dataString: matchStr,
// query: uri.queryParameters,
// source: '',
// dataString: matchStr,
);
PiliSchame.fullPathPush(scheme);
}

View File

@ -116,7 +116,7 @@ class PiliSchame {
break;
}
}
if (scheme == 'https') {
if (['http', 'https'].contains(scheme)) {
fullPathPush(value);
}
}
@ -148,16 +148,16 @@ class PiliSchame {
}
}
static Future<void> fullPathPush(SchemeEntity value) async {
static Future<void> fullPathPush(Uri value) async {
// https://m.bilibili.com/bangumi/play/ss39708
// https | m.bilibili.com | /bangumi/play/ss39708
// final String scheme = value.scheme!;
final String host = value.host!;
final String? path = value.path;
Map<String, String>? query = value.query;
final String host = value.host;
final String path = value.path;
Map<String, String>? query = value.queryParameters;
RegExp regExp = RegExp(r'^((www\.)|(m\.))?bilibili\.com$');
if (regExp.hasMatch(host)) {
final String lastPathSegment = path!.split('/').last;
final String lastPathSegment = path.split('/').last;
if (path.startsWith('/video')) {
Map matchRes = IdUtils.matchAvorBv(input: path);
if (matchRes.containsKey('AV')) {
@ -182,13 +182,13 @@ class PiliSchame {
_videoPush(Utils.matchNum(path.split('?').first).first, null);
}
} else if (host.contains('live')) {
int roomId = int.parse(path!.split('/').last);
int roomId = int.parse(path.split('/').last);
Get.toNamed(
'/liveRoom?roomid=$roomId',
arguments: {'liveItem': null, 'heroTag': roomId.toString()},
);
} else if (host.contains('space')) {
var mid = path!.split('/').last;
var mid = path.split('/').last;
Get.toNamed('/member?mid=$mid', arguments: {'face': ''});
return;
} else if (host == 'b23.tv') {
@ -223,7 +223,7 @@ class PiliSchame {
parameters: {'url': redirectUrl, 'type': 'url', 'pageTitle': ''},
);
}
} else if (path != null) {
} else {
final String area = path.split('/').last;
switch (area) {
case 'bangumi':
@ -247,12 +247,12 @@ class PiliSchame {
break;
case 'read':
print('专栏');
String id = Utils.matchNum(query!['id']!).first.toString();
String id = Utils.matchNum(query['id']!).first.toString();
Get.toNamed('/read', parameters: {
'url': value.dataString!,
'url': value.toString(),
'title': '',
'id': id,
'articleType': 'read'
'articleType': 'read',
});
break;
case 'space':
@ -270,9 +270,9 @@ class PiliSchame {
Get.toNamed(
'/webview',
parameters: {
'url': value.dataString ?? "",
'url': value.toString(),
'type': 'url',
'pageTitle': ''
'pageTitle': '',
},
);
}