mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-30 23:58:13 +08:00
feat: hot rcmd entrance
Closes #151 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -30,6 +30,8 @@ class _AboutPageState extends State<AboutPage> {
|
|||||||
'https://github.com/guozhigq/pilipala';
|
'https://github.com/guozhigq/pilipala';
|
||||||
static const String _upstreamUrl = 'https://github.com/orz12/PiliPalaX';
|
static const String _upstreamUrl = 'https://github.com/orz12/PiliPalaX';
|
||||||
|
|
||||||
|
late int _pressCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -51,12 +53,36 @@ class _AboutPageState extends State<AboutPage> {
|
|||||||
appBar: AppBar(title: Text('关于')),
|
appBar: AppBar(title: Text('关于')),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
GestureDetector(
|
||||||
constraints: const BoxConstraints(maxHeight: 150),
|
onTap: () {
|
||||||
child: ExcludeSemantics(
|
_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(
|
child: Image.asset(
|
||||||
'assets/images/logo/logo_android_2.png',
|
'assets/images/logo/logo_android_2.png',
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text('PiliPlus',
|
title: Text('PiliPlus',
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_controller.dart';
|
import 'package:PiliPlus/pages/common/common_controller.dart';
|
||||||
import 'package:PiliPlus/http/video.dart';
|
import 'package:PiliPlus/http/video.dart';
|
||||||
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class HotController extends CommonController {
|
class HotController extends CommonController {
|
||||||
// int idx = 0;
|
// int idx = 0;
|
||||||
|
|
||||||
|
late RxBool showHotRcmd = GStorage.showHotRcmd.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import 'dart:async';
|
|||||||
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||||
import 'package:PiliPlus/common/widgets/video_card_h.dart';
|
import 'package:PiliPlus/common/widgets/video_card_h.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.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/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -56,6 +59,27 @@ class _HotPageState extends State<HotPage> with AutomaticKeepAliveClientMixin {
|
|||||||
super.dispose();
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
@@ -67,6 +91,67 @@ class _HotPageState extends State<HotPage> with AutomaticKeepAliveClientMixin {
|
|||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
controller: _hotController.scrollController,
|
controller: _hotController.scrollController,
|
||||||
slivers: [
|
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<HomeController>();
|
||||||
|
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(
|
SliverPadding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: StyleString.safeSpace - 5,
|
top: StyleString.safeSpace - 5,
|
||||||
|
|||||||
@@ -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/quality.dart';
|
||||||
import 'package:PiliPlus/models/video/play/subtitle.dart';
|
import 'package:PiliPlus/models/video/play/subtitle.dart';
|
||||||
import 'package:PiliPlus/pages/home/controller.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/main/controller.dart';
|
||||||
import 'package:PiliPlus/pages/member/new/controller.dart';
|
import 'package:PiliPlus/pages/member/new/controller.dart';
|
||||||
import 'package:PiliPlus/pages/mine/controller.dart';
|
import 'package:PiliPlus/pages/mine/controller.dart';
|
||||||
@@ -1762,6 +1763,19 @@ List<SettingsModel> get extraSettings => [
|
|||||||
setKey: SettingBoxKey.mergeDanmaku,
|
setKey: SettingBoxKey.mergeDanmaku,
|
||||||
defaultVal: false,
|
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<HotController>().showHotRcmd.value = value;
|
||||||
|
} catch (_) {}
|
||||||
|
},
|
||||||
|
),
|
||||||
SettingsModel(
|
SettingsModel(
|
||||||
settingsType: SettingsType.sw1tch,
|
settingsType: SettingsType.sw1tch,
|
||||||
enableFeedback: true,
|
enableFeedback: true,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:PiliPlus/http/constants.dart';
|
import 'package:PiliPlus/http/constants.dart';
|
||||||
import 'package:PiliPlus/http/init.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/id_utils.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -178,18 +179,20 @@ class _WebviewPageNewState extends State<WebviewPageNew> {
|
|||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
onLoadStop: (controller, url) {
|
onLoadStop: (controller, url) {
|
||||||
_webViewController?.evaluateJavascript(
|
if (url.toString().startsWith('https://live.bilibili.com')) {
|
||||||
source: '''
|
_webViewController?.evaluateJavascript(
|
||||||
document.styleSheets[0].insertRule('div.open-app-btn.bili-btn-warp {display:none;}', 0);
|
source: '''
|
||||||
document.styleSheets[0].insertRule('#app__display-area > div.control-panel {display:none;}', 0);
|
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();
|
// _webViewController?.evaluateJavascript(
|
||||||
document.querySelector('#message-navbar').remove();
|
// source: '''
|
||||||
''',
|
// document.querySelector('#internationalHeader').remove();
|
||||||
);
|
// document.querySelector('#message-navbar').remove();
|
||||||
|
// ''',
|
||||||
|
// );
|
||||||
},
|
},
|
||||||
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
||||||
final String str = navigationAction.request.url!.pathSegments[0];
|
final String str = navigationAction.request.url!.pathSegments[0];
|
||||||
@@ -206,7 +209,23 @@ class _WebviewPageNewState extends State<WebviewPageNew> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var url = navigationAction.request.url!.toString();
|
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/')) {
|
if (url.startsWith('bilibili://video/')) {
|
||||||
String str = Uri.parse(url).pathSegments[0];
|
String str = Uri.parse(url).pathSegments[0];
|
||||||
Get.offAndToNamed(
|
Get.offAndToNamed(
|
||||||
|
|||||||
@@ -342,6 +342,9 @@ class GStorage {
|
|||||||
static bool get mergeDanmaku =>
|
static bool get mergeDanmaku =>
|
||||||
GStorage.setting.get(SettingBoxKey.mergeDanmaku, defaultValue: false);
|
GStorage.setting.get(SettingBoxKey.mergeDanmaku, defaultValue: false);
|
||||||
|
|
||||||
|
static bool get showHotRcmd =>
|
||||||
|
GStorage.setting.get(SettingBoxKey.showHotRcmd, defaultValue: false);
|
||||||
|
|
||||||
static List<double> get dynamicDetailRatio => List<double>.from(setting
|
static List<double> get dynamicDetailRatio => List<double>.from(setting
|
||||||
.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]));
|
.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]));
|
||||||
|
|
||||||
@@ -562,6 +565,7 @@ class SettingBoxKey {
|
|||||||
refreshDisplacement = 'refreshDisplacement',
|
refreshDisplacement = 'refreshDisplacement',
|
||||||
showVipDanmaku = 'showVipDanmaku',
|
showVipDanmaku = 'showVipDanmaku',
|
||||||
mergeDanmaku = 'mergeDanmaku',
|
mergeDanmaku = 'mergeDanmaku',
|
||||||
|
showHotRcmd = 'showHotRcmd',
|
||||||
|
|
||||||
// Sponsor Block
|
// Sponsor Block
|
||||||
enableSponsorBlock = 'enableSponsorBlock',
|
enableSponsorBlock = 'enableSponsorBlock',
|
||||||
|
|||||||
@@ -63,8 +63,12 @@ class Utils {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleWebview(String url, {bool off = false}) {
|
static void handleWebview(
|
||||||
if (GStorage.openInBrowser) {
|
String url, {
|
||||||
|
bool off = false,
|
||||||
|
bool inApp = false,
|
||||||
|
}) {
|
||||||
|
if (inApp.not && GStorage.openInBrowser) {
|
||||||
launchURL(url);
|
launchURL(url);
|
||||||
} else {
|
} else {
|
||||||
if (off) {
|
if (off) {
|
||||||
|
|||||||
Reference in New Issue
Block a user