mod: handle video intro

Closes #126

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-01-09 12:24:50 +08:00
parent 5b1ec83a34
commit 7e400701df

View File

@@ -2,7 +2,9 @@ import 'dart:async';
import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart'; import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart';
import 'package:PiliPlus/pages/search/widgets/search_text.dart'; import 'package:PiliPlus/pages/search/widgets/search_text.dart';
import 'package:PiliPlus/utils/app_scheme.dart';
import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:expandable/expandable.dart'; import 'package:expandable/expandable.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
@@ -979,33 +981,63 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
switch (currentDesc.type) { switch (currentDesc.type) {
case 1: case 1:
final List<InlineSpan> spanChildren = <InlineSpan>[]; final List<InlineSpan> spanChildren = <InlineSpan>[];
final RegExp urlRegExp = RegExp(r'https?://\S+\b'); final RegExp urlRegExp =
final Iterable<Match> matches = RegExp(r'https?://\S+\b|av\d+|bv\S+\b', caseSensitive: false);
urlRegExp.allMatches(currentDesc.rawText);
int previousEndIndex = 0; (currentDesc.rawText as String).splitMapJoin(
for (final Match match in matches) { urlRegExp,
if (match.start > previousEndIndex) { onMatch: (Match match) {
spanChildren.add(TextSpan( String matchStr = match[0]!;
text: currentDesc.rawText if (RegExp(r'^av\d+$', caseSensitive: false).hasMatch(matchStr)) {
.substring(previousEndIndex, match.start))); try {
} // validate
int aid = int.parse(matchStr.substring(2));
IdUtils.av2bv(aid);
spanChildren.add( spanChildren.add(
TextSpan( TextSpan(
text: match.group(0), text: matchStr,
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.primary), // 设置颜色为蓝色 color: Theme.of(context).colorScheme.primary),
recognizer: TapGestureRecognizer()
..onTap = () {
PiliScheme.videoPush(aid, null);
},
),
);
} catch (e) {
spanChildren.add(TextSpan(text: matchStr));
}
} else if (RegExp(r'^bv\S+\b$', caseSensitive: false)
.hasMatch(matchStr)) {
try {
// validate
IdUtils.bv2av(matchStr);
spanChildren.add(
TextSpan(
text: matchStr,
style: TextStyle(
color: Theme.of(context).colorScheme.primary),
recognizer: TapGestureRecognizer()
..onTap = () {
PiliScheme.videoPush(null, matchStr);
},
),
);
} catch (e) {
spanChildren.add(TextSpan(text: matchStr));
}
} else {
spanChildren.add(
TextSpan(
text: matchStr,
style:
TextStyle(color: Theme.of(context).colorScheme.primary),
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
// 处理点击事件
try { try {
Get.toNamed( Get.toNamed(
'/webview', '/webview',
parameters: { parameters: {'url': matchStr},
'url': match.group(0)!,
'type': 'url',
'pageTitle': match.group(0)!,
},
); );
} catch (err) { } catch (err) {
SmartDialog.showToast(err.toString()); SmartDialog.showToast(err.toString());
@@ -1013,16 +1045,15 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
}, },
), ),
); );
previousEndIndex = match.end;
} }
return '';
if (previousEndIndex < currentDesc.rawText.length) { },
spanChildren.add(TextSpan( onNonMatch: (String nonMatchStr) {
text: currentDesc.rawText.substring(previousEndIndex))); spanChildren.add(TextSpan(text: nonMatchStr));
} return '';
},
final TextSpan result = TextSpan(children: spanChildren); );
return result; return TextSpan(children: spanChildren);
case 2: case 2:
final Color colorSchemePrimary = final Color colorSchemePrimary =
Theme.of(context).colorScheme.primary; Theme.of(context).colorScheme.primary;