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,50 +981,79 @@ 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
spanChildren.add( int aid = int.parse(matchStr.substring(2));
TextSpan( IdUtils.av2bv(aid);
text: match.group(0), spanChildren.add(
style: TextStyle( TextSpan(
color: Theme.of(context).colorScheme.primary), // 设置颜色为蓝色 text: matchStr,
recognizer: TapGestureRecognizer() style: TextStyle(
..onTap = () { color: Theme.of(context).colorScheme.primary),
// 处理点击事件 recognizer: TapGestureRecognizer()
try { ..onTap = () {
Get.toNamed( PiliScheme.videoPush(aid, null);
'/webview',
parameters: {
'url': match.group(0)!,
'type': 'url',
'pageTitle': match.group(0)!,
}, },
); ),
} catch (err) { );
SmartDialog.showToast(err.toString()); } catch (e) {
} spanChildren.add(TextSpan(text: matchStr));
}, }
), } else if (RegExp(r'^bv\S+\b$', caseSensitive: false)
); .hasMatch(matchStr)) {
previousEndIndex = match.end; try {
} // validate
IdUtils.bv2av(matchStr);
if (previousEndIndex < currentDesc.rawText.length) { spanChildren.add(
spanChildren.add(TextSpan( TextSpan(
text: currentDesc.rawText.substring(previousEndIndex))); text: matchStr,
} style: TextStyle(
color: Theme.of(context).colorScheme.primary),
final TextSpan result = TextSpan(children: spanChildren); recognizer: TapGestureRecognizer()
return result; ..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()
..onTap = () {
try {
Get.toNamed(
'/webview',
parameters: {'url': matchStr},
);
} catch (err) {
SmartDialog.showToast(err.toString());
}
},
),
);
}
return '';
},
onNonMatch: (String nonMatchStr) {
spanChildren.add(TextSpan(text: nonMatchStr));
return '';
},
);
return TextSpan(children: spanChildren);
case 2: case 2:
final Color colorSchemePrimary = final Color colorSchemePrimary =
Theme.of(context).colorScheme.primary; Theme.of(context).colorScheme.primary;