Compare commits

..

7 Commits

12 changed files with 274 additions and 182 deletions

View File

@ -36,7 +36,7 @@ class NetworkImgLayer extends StatelessWidget {
final int defaultImgQuality = GlobalData().imgQuality; final int defaultImgQuality = GlobalData().imgQuality;
final String imageUrl = final String imageUrl =
'${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp'; '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp';
// print(imageUrl); print(imageUrl);
int? memCacheWidth, memCacheHeight; int? memCacheWidth, memCacheHeight;
double aspectRatio = (width / height).toDouble(); double aspectRatio = (width / height).toDouble();

View File

@ -1,3 +1,4 @@
import 'package:expandable/expandable.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -15,6 +16,7 @@ import 'package:pilipala/pages/video/detail/widgets/ai_detail.dart';
import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/utils.dart';
import '../../../../http/user.dart';
import 'widgets/action_item.dart'; import 'widgets/action_item.dart';
import 'widgets/fav_panel.dart'; import 'widgets/fav_panel.dart';
import 'widgets/intro_detail.dart'; import 'widgets/intro_detail.dart';
@ -137,6 +139,9 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
late String memberHeroTag; late String memberHeroTag;
late bool enableAi; late bool enableAi;
bool isProcessing = false; bool isProcessing = false;
RxBool isExpand = false.obs;
late ExpandableController _expandableCtr;
void Function()? handleState(Future Function() action) { void Function()? handleState(Future Function() action) {
return isProcessing return isProcessing
? null ? null
@ -160,6 +165,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
follower = Utils.numFormat(videoIntroController.userStat['follower']); follower = Utils.numFormat(videoIntroController.userStat['follower']);
followStatus = videoIntroController.followStatus; followStatus = videoIntroController.followStatus;
enableAi = setting.get(SettingBoxKey.enableAi, defaultValue: true); enableAi = setting.get(SettingBoxKey.enableAi, defaultValue: true);
_expandableCtr = ExpandableController(initialExpanded: false);
} }
// 收藏 // 收藏
@ -212,13 +218,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
// 视频介绍 // 视频介绍
showIntroDetail() { showIntroDetail() {
feedBack(); feedBack();
showBottomSheet( isExpand.value = !(isExpand.value);
context: context, _expandableCtr.toggle();
enableDrag: true,
builder: (BuildContext context) {
return IntroDetail(videoDetail: widget.videoDetail!);
},
);
} }
// 用户主页 // 用户主页
@ -242,6 +243,12 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
); );
} }
@override
void dispose() {
_expandableCtr.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData t = Theme.of(context); final ThemeData t = Theme.of(context);
@ -259,14 +266,34 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
GestureDetector( GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () => showIntroDetail(), onTap: () => showIntroDetail(),
child: Text( child: ExpandablePanel(
widget.videoDetail!.title!, controller: _expandableCtr,
style: const TextStyle( collapsed: Text(
fontSize: 18, widget.videoDetail!.title!,
fontWeight: FontWeight.bold, softWrap: true,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
expanded: Text(
widget.videoDetail!.title!,
softWrap: true,
maxLines: 4,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
theme: const ExpandableThemeData(
animationDuration: Duration(milliseconds: 300),
scrollAnimationDuration: Duration(milliseconds: 300),
crossFadePoint: 0,
fadeCurve: Curves.ease,
sizeCurve: Curves.linear,
), ),
maxLines: 2,
overflow: TextOverflow.ellipsis,
), ),
), ),
Stack( Stack(
@ -330,6 +357,20 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
], ],
), ),
/// 视频简介
ExpandablePanel(
controller: _expandableCtr,
collapsed: const SizedBox(height: 0),
expanded: IntroDetail(videoDetail: widget.videoDetail!),
theme: const ExpandableThemeData(
animationDuration: Duration(milliseconds: 300),
scrollAnimationDuration: Duration(milliseconds: 300),
crossFadePoint: 0,
fadeCurve: Curves.ease,
sizeCurve: Curves.linear,
),
),
/// 点赞收藏转发 /// 点赞收藏转发
actionGrid(context, videoIntroController), actionGrid(context, videoIntroController),
// 合集 // 合集
@ -438,6 +479,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
margin: const EdgeInsets.only(top: 6, bottom: 4), margin: const EdgeInsets.only(top: 6, bottom: 4),
height: constraints.maxWidth / 5 * 0.8, height: constraints.maxWidth / 5 * 0.8,
child: GridView.count( child: GridView.count(
physics: const NeverScrollableScrollPhysics(),
primary: false, primary: false,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
crossAxisCount: 5, crossAxisCount: 5,
@ -451,12 +493,6 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
selectStatus: videoIntroController.hasLike.value, selectStatus: videoIntroController.hasLike.value,
text: widget.videoDetail!.stat!.like!.toString()), text: widget.videoDetail!.stat!.like!.toString()),
), ),
// ActionItem(
// icon: const Icon(FontAwesomeIcons.clock),
// onTap: () => videoIntroController.actionShareVideo(),
// selectStatus: false,
// loadingStatus: loadingStatus,
// text: '稍后再看'),
Obx( Obx(
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.b), icon: const Icon(FontAwesomeIcons.b),
@ -477,10 +513,14 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
), ),
), ),
ActionItem( ActionItem(
icon: const Icon(FontAwesomeIcons.comment), icon: const Icon(FontAwesomeIcons.clock),
onTap: () => videoDetailCtr.tabCtr.animateTo(1), onTap: () async {
final res =
await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid);
SmartDialog.showToast(res['msg']);
},
selectStatus: false, selectStatus: false,
text: widget.videoDetail!.stat!.reply!.toString(), text: '稍后看',
), ),
ActionItem( ActionItem(
icon: const Icon(FontAwesomeIcons.shareFromSquare), icon: const Icon(FontAwesomeIcons.shareFromSquare),

View File

@ -1,16 +1,10 @@
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/common/widgets/stat/danmu.dart';
import 'package:pilipala/common/widgets/stat/view.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/utils.dart';
Box localCache = GStrorage.localCache;
late double sheetHeight;
class IntroDetail extends StatelessWidget { class IntroDetail extends StatelessWidget {
const IntroDetail({ const IntroDetail({
super.key, super.key,
@ -20,105 +14,39 @@ class IntroDetail extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
sheetHeight = localCache.get('sheetHeight'); return SizedBox(
return Container( width: double.infinity,
color: Theme.of(context).colorScheme.background, child: SelectableRegion(
padding: EdgeInsets.only( focusNode: FocusNode(),
left: 14, selectionControls: MaterialTextSelectionControls(),
right: 14,
bottom: MediaQuery.of(context).padding.bottom + 20),
height: sheetHeight,
child: Column( child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
InkWell( children: <Widget>[
onTap: () => Get.back(), const SizedBox(height: 4),
child: Container( GestureDetector(
height: 35, onTap: () {
padding: const EdgeInsets.only(bottom: 2), Clipboard.setData(ClipboardData(text: videoDetail!.bvid!));
child: Center( SmartDialog.showToast('已复制');
child: Container( },
width: 32, child: Text(
height: 3, videoDetail!.bvid!,
decoration: BoxDecoration( style: TextStyle(
color: Theme.of(context).colorScheme.primary, fontSize: 13, color: Theme.of(context).colorScheme.primary),
borderRadius:
const BorderRadius.all(Radius.circular(3))),
),
),
), ),
), ),
Expanded( const SizedBox(height: 4),
child: SingleChildScrollView( Text.rich(
child: Column( style: const TextStyle(height: 1.4),
crossAxisAlignment: CrossAxisAlignment.start, TextSpan(
children: [ children: [
Text( buildContent(context, videoDetail!),
videoDetail!.title, ],
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 6),
Row(
children: [
StatView(
theme: 'gray',
view: videoDetail!.stat!.view,
size: 'medium',
),
const SizedBox(width: 10),
StatDanMu(
theme: 'gray',
danmu: videoDetail!.stat!.danmaku,
size: 'medium',
),
const SizedBox(width: 10),
Text(
Utils.dateFormat(videoDetail!.pubdate,
formatType: 'detail'),
style: TextStyle(
fontSize: 12,
color: Theme.of(context).colorScheme.outline,
),
),
],
),
const SizedBox(height: 20),
SizedBox(
width: double.infinity,
child: SelectableRegion(
focusNode: FocusNode(),
selectionControls: MaterialTextSelectionControls(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
videoDetail!.bvid!,
style: const TextStyle(fontSize: 13),
),
const SizedBox(height: 4),
Text.rich(
style: const TextStyle(
height: 1.4,
// fontSize: 13,
),
TextSpan(
children: [
buildContent(context, videoDetail!),
],
),
),
],
),
),
),
],
),
), ),
) ),
], ],
)); ),
),
);
} }
InlineSpan buildContent(BuildContext context, content) { InlineSpan buildContent(BuildContext context, content) {

View File

@ -148,14 +148,35 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
floating: true, floating: true,
delegate: _MySliverPersistentHeaderDelegate( delegate: _MySliverPersistentHeaderDelegate(
child: Container( child: Container(
height: 40, height: 45,
padding: const EdgeInsets.fromLTRB(12, 6, 6, 0), padding: const EdgeInsets.fromLTRB(12, 0, 6, 0),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
border: Border(
bottom: BorderSide(
color: Theme.of(context)
.colorScheme
.outline
.withOpacity(0.1)),
),
),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Obx(
'${_videoReplyController.sortTypeLabel.value}评论', () => AnimatedSwitcher(
style: const TextStyle(fontSize: 13), duration: const Duration(milliseconds: 400),
transitionBuilder:
(Widget child, Animation<double> animation) {
return ScaleTransition(
scale: animation, child: child);
},
child: Text(
'${_videoReplyController.count.value}条回复',
key: ValueKey<int>(
_videoReplyController.count.value),
),
),
), ),
SizedBox( SizedBox(
height: 35, height: 35,
@ -163,12 +184,10 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
onPressed: () => onPressed: () =>
_videoReplyController.queryBySort(), _videoReplyController.queryBySort(),
icon: const Icon(Icons.sort, size: 16), icon: const Icon(Icons.sort, size: 16),
label: Obx( label: Obx(() => Text(
() => Text( _videoReplyController.sortTypeLabel.value,
_videoReplyController.sortTypeLabel.value, style: const TextStyle(fontSize: 13),
style: const TextStyle(fontSize: 13), )),
),
),
), ),
) )
], ],
@ -310,8 +329,8 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
class _MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate { class _MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
_MySliverPersistentHeaderDelegate({required this.child}); _MySliverPersistentHeaderDelegate({required this.child});
final double _minExtent = 40; final double _minExtent = 45;
final double _maxExtent = 40; final double _maxExtent = 45;
final Widget child; final Widget child;
@override @override

View File

@ -498,7 +498,7 @@ InlineSpan buildContent(
return str; return str;
}); });
} }
content.message = content.message.replaceAll(RegExp(r"\{vote:.*?\}"), ' '); // content.message = content.message.replaceAll(RegExp(r"\{vote:.*?\}"), ' ');
content.message = content.message content.message = content.message
.replaceAll('&amp;', '&') .replaceAll('&amp;', '&')
.replaceAll('&lt;', '<') .replaceAll('&lt;', '<')

View File

@ -372,6 +372,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
false) false)
? SvgPicture.asset( ? SvgPicture.asset(
'assets/images/video/danmu_close.svg', 'assets/images/video/danmu_close.svg',
// ignore: deprecated_member_use
color:
Theme.of(context).colorScheme.outline,
) )
: SvgPicture.asset( : SvgPicture.asset(
'assets/images/video/danmu_open.svg', 'assets/images/video/danmu_open.svg',

View File

@ -17,12 +17,16 @@ class ScrollAppBar extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top; final double statusBarHeight = MediaQuery.of(context).padding.top;
final videoHeight = MediaQuery.sizeOf(context).width * 9 / 16; final videoHeight = MediaQuery.sizeOf(context).width * 9 / 16;
double scrollDistance = scrollVal;
if (scrollVal > videoHeight - kToolbarHeight) {
scrollDistance = videoHeight - kToolbarHeight;
}
return Positioned( return Positioned(
top: -videoHeight + scrollVal + kToolbarHeight + 0.5, top: -videoHeight + scrollDistance + kToolbarHeight + 0.5,
left: 0, left: 0,
right: 0, right: 0,
child: Opacity( child: Opacity(
opacity: scrollVal / (videoHeight - kToolbarHeight), opacity: scrollDistance / (videoHeight - kToolbarHeight),
child: Container( child: Container(
height: statusBarHeight + kToolbarHeight, height: statusBarHeight + kToolbarHeight,
color: Theme.of(context).colorScheme.background, color: Theme.of(context).colorScheme.background,

View File

@ -32,28 +32,14 @@ class _ExpandedSectionState extends State<ExpandedSection>
_runExpandCheck(); _runExpandCheck();
} }
///Setting up the animation
// void prepareAnimations() {
// expandController = AnimationController(
// vsync: this, duration: const Duration(milliseconds: 500));
// animation = CurvedAnimation(
// parent: expandController,
// curve: Curves.fastOutSlowIn,
// );
// }
void prepareAnimations() { void prepareAnimations() {
expandController = AnimationController( expandController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 400)); vsync: this, duration: const Duration(milliseconds: 400));
Animation<double> curve = CurvedAnimation( Animation<double> curve = CurvedAnimation(
parent: expandController, parent: expandController,
curve: Curves.fastOutSlowIn, curve: Curves.linear,
); );
animation = Tween(begin: widget.begin, end: widget.end).animate(curve); animation = Tween(begin: widget.begin, end: widget.end).animate(curve);
// animation = CurvedAnimation(
// parent: expandController,
// curve: Curves.fastOutSlowIn,
// );
} }
void _runExpandCheck() { void _runExpandCheck() {
@ -67,7 +53,9 @@ class _ExpandedSectionState extends State<ExpandedSection>
@override @override
void didUpdateWidget(ExpandedSection oldWidget) { void didUpdateWidget(ExpandedSection oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
_runExpandCheck(); if (widget.expand != oldWidget.expand) {
_runExpandCheck();
}
} }
@override @override

View File

@ -17,6 +17,7 @@ import 'package:pilipala/plugin/pl_player/index.dart';
import 'package:pilipala/plugin/pl_player/models/play_repeat.dart'; import 'package:pilipala/plugin/pl_player/models/play_repeat.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/services/shutdown_timer_service.dart'; import 'package:pilipala/services/shutdown_timer_service.dart';
import '../../../../http/danmaku.dart';
import '../../../../models/common/search_type.dart'; import '../../../../models/common/search_type.dart';
import '../../../../models/video_detail_res.dart'; import '../../../../models/video_detail_res.dart';
import '../introduction/index.dart'; import '../introduction/index.dart';
@ -52,7 +53,7 @@ class _HeaderControlState extends State<HeaderControl> {
final Box<dynamic> videoStorage = GStrorage.video; final Box<dynamic> videoStorage = GStrorage.video;
late List<double> speedsList; late List<double> speedsList;
double buttonSpace = 8; double buttonSpace = 8;
bool showTitle = false; RxBool isFullScreen = false.obs;
late String heroTag; late String heroTag;
late VideoIntroController videoIntroController; late VideoIntroController videoIntroController;
late VideoDetailData videoDetail; late VideoDetailData videoDetail;
@ -69,13 +70,8 @@ class _HeaderControlState extends State<HeaderControl> {
} }
void fullScreenStatusListener() { void fullScreenStatusListener() {
widget.videoDetailCtr!.plPlayerController.isFullScreen widget.videoDetailCtr!.plPlayerController.isFullScreen.listen((bool val) {
.listen((bool isFullScreen) { isFullScreen.value = val;
if (isFullScreen) {
showTitle = true;
} else {
showTitle = false;
}
/// TODO setState() called after dispose() /// TODO setState() called after dispose()
if (mounted) { if (mounted) {
@ -218,6 +214,87 @@ class _HeaderControlState extends State<HeaderControl> {
); );
} }
/// 发送弹幕
void showShootDanmakuSheet() {
final TextEditingController textController = TextEditingController();
bool isSending = false; // 追踪是否正在发送
showDialog(
context: Get.context!,
builder: (BuildContext context) {
// TODO: 支持更多类型和颜色的弹幕
return AlertDialog(
title: const Text('发送弹幕(测试)'),
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return TextField(
controller: textController,
);
}),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text(
'取消',
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return TextButton(
onPressed: isSending
? null
: () async {
final String msg = textController.text;
if (msg.isEmpty) {
SmartDialog.showToast('弹幕内容不能为空');
return;
} else if (msg.length > 100) {
SmartDialog.showToast('弹幕内容不能超过100个字符');
return;
}
setState(() {
isSending = true; // 开始发送,更新状态
});
//修改按钮文字
final dynamic res = await DanmakaHttp.shootDanmaku(
oid: widget.videoDetailCtr!.cid.value,
msg: textController.text,
bvid: widget.videoDetailCtr!.bvid,
progress:
widget.controller!.position.value.inMilliseconds,
type: 1,
);
setState(() {
isSending = false; // 发送结束,更新状态
});
if (res['status']) {
SmartDialog.showToast('发送成功');
// 发送成功,自动预览该弹幕,避免重新请求
// TODO: 暂停状态下预览弹幕仍会移动与计时可考虑添加到dmSegList或其他方式实现
widget.controller!.danmakuController!.addItems([
DanmakuItem(
msg,
color: Colors.white,
time: widget
.controller!.position.value.inMilliseconds,
type: DanmakuItemType.scroll,
isSend: true,
)
]);
Get.back();
} else {
SmartDialog.showToast('发送失败,错误信息为${res['msg']}');
}
},
child: Text(isSending ? '发送中...' : '发送'),
);
})
],
);
},
);
}
/// 定时关闭 /// 定时关闭
void scheduleExit() async { void scheduleExit() async {
const List<int> scheduleTimeChoices = [ const List<int> scheduleTimeChoices = [
@ -1029,7 +1106,7 @@ class _HeaderControlState extends State<HeaderControl> {
}, },
), ),
SizedBox(width: buttonSpace), SizedBox(width: buttonSpace),
if (showTitle && if (isFullScreen.value &&
isLandscape && isLandscape &&
widget.videoType == SearchType.video) ...[ widget.videoType == SearchType.video) ...[
Column( Column(
@ -1081,6 +1158,43 @@ class _HeaderControlState extends State<HeaderControl> {
// ), // ),
// fuc: () => _.screenshot(), // fuc: () => _.screenshot(),
// ), // ),
if (isFullScreen.value) ...[
SizedBox(
width: 56,
height: 34,
child: TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero),
),
onPressed: () => showShootDanmakuSheet(),
child: const Text(
'发弹幕',
style: textStyle,
),
),
),
SizedBox(
width: 34,
height: 34,
child: Obx(
() => IconButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero),
),
onPressed: () {
_.isOpenDanmu.value = !_.isOpenDanmu.value;
},
icon: Icon(
_.isOpenDanmu.value
? Icons.subtitles_outlined
: Icons.subtitles_off_outlined,
size: 19,
color: Colors.white,
),
),
),
),
],
SizedBox(width: buttonSpace), SizedBox(width: buttonSpace),
if (Platform.isAndroid) ...<Widget>[ if (Platform.isAndroid) ...<Widget>[
SizedBox( SizedBox(

View File

@ -20,7 +20,7 @@ class PiliSchame {
/// 完整链接进入 b23.无效 /// 完整链接进入 b23.无效
appScheme.getLatestScheme().then((SchemeEntity? value) { appScheme.getLatestScheme().then((SchemeEntity? value) {
if (value != null) { if (value != null) {
_routePush(value); _fullPathPush(value);
} }
}); });
@ -37,6 +37,7 @@ class PiliSchame {
final String scheme = value.scheme; final String scheme = value.scheme;
final String host = value.host; final String host = value.host;
final String path = value.path; final String path = value.path;
if (scheme == 'bilibili') { if (scheme == 'bilibili') {
if (host == 'root') { if (host == 'root') {
Navigator.popUntil( Navigator.popUntil(
@ -84,14 +85,6 @@ class PiliSchame {
} }
} else if (host == 'search') { } else if (host == 'search') {
Get.toNamed('/searchResult', parameters: {'keyword': ''}); Get.toNamed('/searchResult', parameters: {'keyword': ''});
} else if (host == 'article') {
final String id = path.split('/').last.split('?').first;
Get.toNamed('/htmlRender', parameters: {
'url': 'https://www.bilibili.com/read/cv$id',
'title': 'cv$id',
'id': 'cv$id',
'dynamicType': 'read'
});
} }
} }
if (scheme == 'https') { if (scheme == 'https') {
@ -233,13 +226,6 @@ class PiliSchame {
break; break;
case 'read': case 'read':
print('专栏'); print('专栏');
String id = 'cv${matchNum(query!['id']!).first}';
Get.toNamed('/htmlRender', parameters: {
'url': value.dataString!,
'title': '',
'id': id,
'dynamicType': 'read'
});
break; break;
case 'space': case 'space':
print('个人空间'); print('个人空间');

View File

@ -433,6 +433,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "5.0.3" version: "5.0.3"
expandable:
dependency: "direct main"
description:
name: expandable
sha256: "9604d612d4d1146dafa96c6d8eec9c2ff0994658d6d09fed720ab788c7f5afc2"
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.0.1"
extended_image: extended_image:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -142,6 +142,8 @@ dependencies:
path: 1.8.3 path: 1.8.3
# 电池优化 # 电池优化
disable_battery_optimization: ^1.1.1 disable_battery_optimization: ^1.1.1
# 展开/收起
expandable: ^5.0.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: