diff --git a/lib/pages/about/index.dart b/lib/pages/about/index.dart index 75ab5b110..72d826abb 100644 --- a/lib/pages/about/index.dart +++ b/lib/pages/about/index.dart @@ -30,6 +30,8 @@ class _AboutPageState extends State { 'https://github.com/guozhigq/pilipala'; static const String _upstreamUrl = 'https://github.com/orz12/PiliPalaX'; + late int _pressCount = 0; + @override void initState() { super.initState(); @@ -51,12 +53,36 @@ class _AboutPageState extends State { appBar: AppBar(title: Text('关于')), body: ListView( children: [ - ConstrainedBox( - constraints: const BoxConstraints(maxHeight: 150), - child: ExcludeSemantics( + GestureDetector( + onTap: () { + _pressCount++; + if (_pressCount == 5) { + _pressCount = 0; + showDialog( + context: context, + builder: (context) { + String text = ''; + return AlertDialog( + content: TextField( + onChanged: (value) => text = value, + onSubmitted: (value) { + Get.back(); + Get.toNamed('/webview', parameters: {'url': text}); + }, + ), + ); + }, + ); + } + }, + child: ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 150), + child: ExcludeSemantics( child: Image.asset( - 'assets/images/logo/logo_android_2.png', - )), + 'assets/images/logo/logo_android_2.png', + ), + ), + ), ), ListTile( title: Text('PiliPlus', diff --git a/lib/pages/hot/controller.dart b/lib/pages/hot/controller.dart index 016b48026..54c32cdbb 100644 --- a/lib/pages/hot/controller.dart +++ b/lib/pages/hot/controller.dart @@ -1,10 +1,14 @@ import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/pages/common/common_controller.dart'; import 'package:PiliPlus/http/video.dart'; +import 'package:PiliPlus/utils/storage.dart'; +import 'package:get/get.dart'; class HotController extends CommonController { // int idx = 0; + late RxBool showHotRcmd = GStorage.showHotRcmd.obs; + @override void onInit() { super.onInit(); diff --git a/lib/pages/hot/view.dart b/lib/pages/hot/view.dart index 5a09c130c..b897a7682 100644 --- a/lib/pages/hot/view.dart +++ b/lib/pages/hot/view.dart @@ -3,6 +3,9 @@ import 'dart:async'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/video_card_h.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/tab_type.dart'; +import 'package:PiliPlus/pages/rank/view.dart'; +import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; @@ -56,6 +59,27 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { super.dispose(); } + Widget _buildEntranceItem({ + required String iconUrl, + required String title, + required VoidCallback onTap, + }) { + return GestureDetector( + onTap: onTap, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image.network(width: 35, height: 35, iconUrl), + const SizedBox(height: 2), + Text( + title, + style: TextStyle(fontSize: 12), + ), + ], + ), + ); + } + @override Widget build(BuildContext context) { super.build(context); @@ -67,6 +91,67 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { physics: const AlwaysScrollableScrollPhysics(), controller: _hotController.scrollController, slivers: [ + SliverToBoxAdapter( + child: Obx( + () => _hotController.showHotRcmd.value + ? Padding( + padding: + const EdgeInsets.only(left: 12, top: 12, right: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildEntranceItem( + iconUrl: + 'http://i0.hdslb.com/bfs/archive/a3f11218aaf4521b4967db2ae164ecd3052586b9.png', + title: '排行榜', + onTap: () { + try { + HomeController homeController = + Get.find(); + int index = homeController.tabs.indexWhere( + (item) => item['type'] == TabType.rank, + ); + if (index != -1) { + homeController.tabController.animateTo(index); + } else { + Get.to( + Scaffold( + appBar: AppBar(title: const Text('排行榜')), + body: RankPage(), + ), + ); + } + } catch (_) {} + }, + ), + _buildEntranceItem( + iconUrl: + 'http://i0.hdslb.com/bfs/archive/552ebe8c4794aeef30ebd1568b59ad35f15e21ad.png', + title: '每周必看', + onTap: () { + Utils.handleWebview( + 'https://www.bilibili.com/h5/weekly-recommend', + inApp: true, + ); + }, + ), + _buildEntranceItem( + iconUrl: + 'http://i0.hdslb.com/bfs/archive/3693ec9335b78ca57353ac0734f36a46f3d179a9.png', + title: '入站必刷', + onTap: () { + Utils.handleWebview( + 'https://www.bilibili.com/h5/good-history', + inApp: true, + ); + }, + ), + ], + ), + ) + : const SizedBox.shrink(), + ), + ), SliverPadding( padding: EdgeInsets.only( top: StyleString.safeSpace - 5, diff --git a/lib/pages/setting/widgets/model.dart b/lib/pages/setting/widgets/model.dart index f4404ffbd..b2a505a2b 100644 --- a/lib/pages/setting/widgets/model.dart +++ b/lib/pages/setting/widgets/model.dart @@ -15,6 +15,7 @@ import 'package:PiliPlus/models/video/play/CDN.dart'; import 'package:PiliPlus/models/video/play/quality.dart'; import 'package:PiliPlus/models/video/play/subtitle.dart'; import 'package:PiliPlus/pages/home/controller.dart'; +import 'package:PiliPlus/pages/hot/controller.dart'; import 'package:PiliPlus/pages/main/controller.dart'; import 'package:PiliPlus/pages/member/new/controller.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; @@ -1762,6 +1763,19 @@ List get extraSettings => [ setKey: SettingBoxKey.mergeDanmaku, defaultVal: false, ), + SettingsModel( + settingsType: SettingsType.sw1tch, + title: '显示热门推荐', + subtitle: '热门页面显示每周必看等推荐内容入口', + leading: Icon(Icons.local_fire_department_outlined), + setKey: SettingBoxKey.showHotRcmd, + defaultVal: false, + onChanged: (value) { + try { + Get.find().showHotRcmd.value = value; + } catch (_) {} + }, + ), SettingsModel( settingsType: SettingsType.sw1tch, enableFeedback: true, diff --git a/lib/pages/webview/webview_page.dart b/lib/pages/webview/webview_page.dart index 9cc2e8374..a5d08d947 100644 --- a/lib/pages/webview/webview_page.dart +++ b/lib/pages/webview/webview_page.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:PiliPlus/http/constants.dart'; import 'package:PiliPlus/http/init.dart'; +import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -178,18 +179,20 @@ class _WebviewPageNewState extends State { : null, ), onLoadStop: (controller, url) { - _webViewController?.evaluateJavascript( - source: ''' - document.styleSheets[0].insertRule('div.open-app-btn.bili-btn-warp {display:none;}', 0); - document.styleSheets[0].insertRule('#app__display-area > div.control-panel {display:none;}', 0); - ''', - ); - _webViewController?.evaluateJavascript( - source: ''' - document.querySelector('#internationalHeader').remove(); - document.querySelector('#message-navbar').remove(); - ''', - ); + if (url.toString().startsWith('https://live.bilibili.com')) { + _webViewController?.evaluateJavascript( + source: ''' + document.styleSheets[0].insertRule('div.open-app-btn.bili-btn-warp {display:none;}', 0); + document.styleSheets[0].insertRule('#app__display-area > div.control-panel {display:none;}', 0); + ''', + ); + } + // _webViewController?.evaluateJavascript( + // source: ''' + // document.querySelector('#internationalHeader').remove(); + // document.querySelector('#message-navbar').remove(); + // ''', + // ); }, shouldOverrideUrlLoading: (controller, navigationAction) async { final String str = navigationAction.request.url!.pathSegments[0]; @@ -206,7 +209,23 @@ class _WebviewPageNewState extends State { } var url = navigationAction.request.url!.toString(); - if (!url.startsWith('http')) { + + if (url.startsWith('http')) { + if (RegExp(r'https://www.bilibili.com/video/BV[a-zA-Z\d]+') + .hasMatch(url)) { + PiliScheme.routePush(Uri.parse(url)); + return NavigationActionPolicy.CANCEL; + } else if (url.startsWith('http://m.bilibili.com/playlist/')) { + try { + String? bvid = + RegExp(r'bvid=(BV[a-zA-Z\d]+)').firstMatch(url)?.group(1); + if (bvid != null) { + PiliScheme.videoPush(null, bvid); + return NavigationActionPolicy.CANCEL; + } + } catch (_) {} + } + } else { if (url.startsWith('bilibili://video/')) { String str = Uri.parse(url).pathSegments[0]; Get.offAndToNamed( diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 552f19566..3cd4457d4 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -342,6 +342,9 @@ class GStorage { static bool get mergeDanmaku => GStorage.setting.get(SettingBoxKey.mergeDanmaku, defaultValue: false); + static bool get showHotRcmd => + GStorage.setting.get(SettingBoxKey.showHotRcmd, defaultValue: false); + static List get dynamicDetailRatio => List.from(setting .get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0])); @@ -562,6 +565,7 @@ class SettingBoxKey { refreshDisplacement = 'refreshDisplacement', showVipDanmaku = 'showVipDanmaku', mergeDanmaku = 'mergeDanmaku', + showHotRcmd = 'showHotRcmd', // Sponsor Block enableSponsorBlock = 'enableSponsorBlock', diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index f2bc864de..ced8b9070 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -63,8 +63,12 @@ class Utils { ); } - static void handleWebview(String url, {bool off = false}) { - if (GStorage.openInBrowser) { + static void handleWebview( + String url, { + bool off = false, + bool inApp = false, + }) { + if (inApp.not && GStorage.openInBrowser) { launchURL(url); } else { if (off) {