From 7e400701df795f866ca4a2896178c59eb938909a Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Thu, 9 Jan 2025 12:24:50 +0800 Subject: [PATCH] mod: handle video intro Closes #126 Signed-off-by: bggRGjQaUbCoE --- lib/pages/video/detail/introduction/view.dart | 115 +++++++++++------- 1 file changed, 73 insertions(+), 42 deletions(-) diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 71c0bd86..cf8235f5 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -2,7 +2,9 @@ import 'dart:async'; import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.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/id_utils.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; @@ -979,50 +981,79 @@ class _VideoInfoState extends State with TickerProviderStateMixin { switch (currentDesc.type) { case 1: final List spanChildren = []; - final RegExp urlRegExp = RegExp(r'https?://\S+\b'); - final Iterable matches = - urlRegExp.allMatches(currentDesc.rawText); + final RegExp urlRegExp = + RegExp(r'https?://\S+\b|av\d+|bv\S+\b', caseSensitive: false); - int previousEndIndex = 0; - for (final Match match in matches) { - if (match.start > previousEndIndex) { - spanChildren.add(TextSpan( - text: currentDesc.rawText - .substring(previousEndIndex, match.start))); - } - spanChildren.add( - TextSpan( - text: match.group(0), - style: TextStyle( - color: Theme.of(context).colorScheme.primary), // 设置颜色为蓝色 - recognizer: TapGestureRecognizer() - ..onTap = () { - // 处理点击事件 - try { - Get.toNamed( - '/webview', - parameters: { - 'url': match.group(0)!, - 'type': 'url', - 'pageTitle': match.group(0)!, + (currentDesc.rawText as String).splitMapJoin( + urlRegExp, + onMatch: (Match match) { + String matchStr = match[0]!; + if (RegExp(r'^av\d+$', caseSensitive: false).hasMatch(matchStr)) { + try { + // validate + int aid = int.parse(matchStr.substring(2)); + IdUtils.av2bv(aid); + spanChildren.add( + TextSpan( + text: matchStr, + style: TextStyle( + color: Theme.of(context).colorScheme.primary), + recognizer: TapGestureRecognizer() + ..onTap = () { + PiliScheme.videoPush(aid, null); }, - ); - } catch (err) { - SmartDialog.showToast(err.toString()); - } - }, - ), - ); - previousEndIndex = match.end; - } - - if (previousEndIndex < currentDesc.rawText.length) { - spanChildren.add(TextSpan( - text: currentDesc.rawText.substring(previousEndIndex))); - } - - final TextSpan result = TextSpan(children: spanChildren); - return result; + ), + ); + } 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() + ..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: final Color colorSchemePrimary = Theme.of(context).colorScheme.primary;