mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
Merge branch 'main' of https://github.com/guozhigq/pilipala into guozhigq-main
This commit is contained in:
@@ -69,7 +69,7 @@ class VideoCardH extends StatelessWidget {
|
|||||||
final double width = (boxConstraints.maxWidth -
|
final double width = (boxConstraints.maxWidth -
|
||||||
StyleString.cardSpace *
|
StyleString.cardSpace *
|
||||||
6 /
|
6 /
|
||||||
MediaQuery.of(context).textScaleFactor) /
|
MediaQuery.textScalerOf(context).scale(1.0)) /
|
||||||
2;
|
2;
|
||||||
return Container(
|
return Container(
|
||||||
constraints: const BoxConstraints(minHeight: 88),
|
constraints: const BoxConstraints(minHeight: 88),
|
||||||
|
|||||||
@@ -342,7 +342,8 @@ class VideoStat extends StatelessWidget {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
fontSize: MediaQuery.textScalerOf(context)
|
||||||
|
.scale(Theme.of(context).textTheme.labelSmall!.fontSize),
|
||||||
color: Theme.of(context).colorScheme.outline,
|
color: Theme.of(context).colorScheme.outline,
|
||||||
),
|
),
|
||||||
text: Utils.formatTimestampToRelativeTime(videoItem.pubdate)),
|
text: Utils.formatTimestampToRelativeTime(videoItem.pubdate)),
|
||||||
|
|||||||
@@ -467,4 +467,7 @@ class Api {
|
|||||||
/// page_size
|
/// page_size
|
||||||
static const getSeasonDetailApi =
|
static const getSeasonDetailApi =
|
||||||
'/x/polymer/web-space/seasons_archives_list';
|
'/x/polymer/web-space/seasons_archives_list';
|
||||||
|
|
||||||
|
/// 获取未读动态数
|
||||||
|
static const getUnreadDynamic = '/x/web-interface/dynamic/entrance';
|
||||||
}
|
}
|
||||||
|
|||||||
17
lib/http/common.dart
Normal file
17
lib/http/common.dart
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import 'index.dart';
|
||||||
|
|
||||||
|
class CommonHttp {
|
||||||
|
static Future unReadDynamic() async {
|
||||||
|
var res = await Request().get(Api.getUnreadDynamic,
|
||||||
|
data: {'alltype_offset': 0, 'video_offset': '', 'article_offset': 0});
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {'status': true, 'data': res.data['data']['dyn_basic_infos']};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': [],
|
||||||
|
'msg': res.data['message'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -158,9 +158,8 @@ class MyApp extends StatelessWidget {
|
|||||||
return FlutterSmartDialog(
|
return FlutterSmartDialog(
|
||||||
toastBuilder: (String msg) => CustomToast(msg: msg),
|
toastBuilder: (String msg) => CustomToast(msg: msg),
|
||||||
child: MediaQuery(
|
child: MediaQuery(
|
||||||
data: MediaQuery.of(context).copyWith(
|
data: MediaQuery.of(context)
|
||||||
textScaleFactor:
|
.copyWith(textScaler: TextScaler.linear(textScale)),
|
||||||
MediaQuery.of(context).textScaleFactor * textScale),
|
|
||||||
child: child!,
|
child: child!,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ enum TabType { live, rcmd, hot, bangumi }
|
|||||||
|
|
||||||
extension TabTypeDesc on TabType {
|
extension TabTypeDesc on TabType {
|
||||||
String get description => ['直播', '推荐', '热门', '番剧'][index];
|
String get description => ['直播', '推荐', '热门', '番剧'][index];
|
||||||
|
String get id => ['live', 'rcmd', 'hot', 'bangumi'][index];
|
||||||
}
|
}
|
||||||
|
|
||||||
List tabsConfig = [
|
List tabsConfig = [
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ class _BangumiPageState extends State<BangumiPage>
|
|||||||
// 列数
|
// 列数
|
||||||
crossAxisCount: 3,
|
crossAxisCount: 3,
|
||||||
mainAxisExtent: Get.size.width / 3 / 0.65 +
|
mainAxisExtent: Get.size.width / 3 / 0.65 +
|
||||||
32 * MediaQuery.of(context).textScaleFactor,
|
MediaQuery.textScalerOf(context).scale(32.0),
|
||||||
),
|
),
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(BuildContext context, int index) {
|
(BuildContext context, int index) {
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ import 'package:pilipala/utils/storage.dart';
|
|||||||
|
|
||||||
class HomeController extends GetxController with GetTickerProviderStateMixin {
|
class HomeController extends GetxController with GetTickerProviderStateMixin {
|
||||||
bool flag = false;
|
bool flag = false;
|
||||||
late List tabs;
|
late RxList tabs = [].obs;
|
||||||
RxInt initialIndex = 1.obs;
|
RxInt initialIndex = 1.obs;
|
||||||
late TabController tabController;
|
late TabController tabController;
|
||||||
late List tabsCtrList;
|
late List tabsCtrList;
|
||||||
late List<Widget> tabsPageList;
|
late List<Widget> tabsPageList;
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
Box userInfoCache = GStrorage.userInfo;
|
||||||
|
Box settingStorage = GStrorage.setting;
|
||||||
RxBool userLogin = false.obs;
|
RxBool userLogin = false.obs;
|
||||||
RxString userFace = ''.obs;
|
RxString userFace = ''.obs;
|
||||||
var userInfo;
|
var userInfo;
|
||||||
@@ -21,6 +22,8 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
late final StreamController<bool> searchBarStream =
|
late final StreamController<bool> searchBarStream =
|
||||||
StreamController<bool>.broadcast();
|
StreamController<bool>.broadcast();
|
||||||
late bool hideSearchBar;
|
late bool hideSearchBar;
|
||||||
|
late List defaultTabs;
|
||||||
|
late List<String> tabbarSort;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@@ -28,34 +31,10 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
userInfo = userInfoCache.get('userInfoCache');
|
userInfo = userInfoCache.get('userInfoCache');
|
||||||
userLogin.value = userInfo != null;
|
userLogin.value = userInfo != null;
|
||||||
userFace.value = userInfo != null ? userInfo.face : '';
|
userFace.value = userInfo != null ? userInfo.face : '';
|
||||||
|
|
||||||
// 进行tabs配置
|
// 进行tabs配置
|
||||||
tabs = tabsConfig;
|
setTabConfig();
|
||||||
tabsCtrList = tabsConfig.map((e) => e['ctr']).toList();
|
|
||||||
tabsPageList = tabsConfig.map<Widget>((e) => e['page']).toList();
|
|
||||||
|
|
||||||
tabController = TabController(
|
|
||||||
initialIndex: initialIndex.value,
|
|
||||||
length: tabs.length,
|
|
||||||
vsync: this,
|
|
||||||
);
|
|
||||||
hideSearchBar =
|
hideSearchBar =
|
||||||
setting.get(SettingBoxKey.hideSearchBar, defaultValue: true);
|
setting.get(SettingBoxKey.hideSearchBar, defaultValue: true);
|
||||||
|
|
||||||
// 监听 tabController 切换
|
|
||||||
tabController.animation!.addListener(() {
|
|
||||||
if (tabController.indexIsChanging) {
|
|
||||||
if (initialIndex.value != tabController.index) {
|
|
||||||
initialIndex.value = tabController.index;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final int temp = tabController.animation!.value.round();
|
|
||||||
if (initialIndex.value != temp) {
|
|
||||||
initialIndex.value = temp;
|
|
||||||
tabController.index = initialIndex.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRefresh() {
|
void onRefresh() {
|
||||||
@@ -77,4 +56,42 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
|||||||
if (val) return;
|
if (val) return;
|
||||||
userFace.value = userInfo != null ? userInfo.face : '';
|
userFace.value = userInfo != null ? userInfo.face : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setTabConfig() async {
|
||||||
|
defaultTabs = tabsConfig;
|
||||||
|
tabbarSort = settingStorage.get(SettingBoxKey.tabbarSort,
|
||||||
|
defaultValue: ['live', 'rcmd', 'hot', 'bangumi']);
|
||||||
|
|
||||||
|
tabs.value = defaultTabs
|
||||||
|
.where((i) => tabbarSort.contains((i['type'] as TabType).id))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (tabbarSort.contains(TabType.rcmd.id)) {
|
||||||
|
initialIndex.value = tabbarSort.indexOf(TabType.rcmd.id);
|
||||||
|
} else {
|
||||||
|
initialIndex.value = 0;
|
||||||
|
}
|
||||||
|
tabsCtrList = tabs.map((e) => e['ctr']).toList();
|
||||||
|
tabsPageList = tabs.map<Widget>((e) => e['page']).toList();
|
||||||
|
|
||||||
|
tabController = TabController(
|
||||||
|
initialIndex: initialIndex.value,
|
||||||
|
length: tabs.length,
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
// 监听 tabController 切换
|
||||||
|
tabController.animation!.addListener(() {
|
||||||
|
if (tabController.indexIsChanging) {
|
||||||
|
if (initialIndex.value != tabController.index) {
|
||||||
|
initialIndex.value = tabController.index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final int temp = tabController.animation!.value.round();
|
||||||
|
if (initialIndex.value != temp) {
|
||||||
|
initialIndex.value = temp;
|
||||||
|
tabController.index = initialIndex.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,11 @@ class _HomePageState extends State<HomePage>
|
|||||||
ctr: _homeController,
|
ctr: _homeController,
|
||||||
callback: showUserBottomSheet,
|
callback: showUserBottomSheet,
|
||||||
),
|
),
|
||||||
const CustomTabs(),
|
if (_homeController.tabs.length > 1) ...[
|
||||||
|
const CustomTabs(),
|
||||||
|
] else ...[
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
],
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
controller: _homeController.tabController,
|
controller: _homeController.tabController,
|
||||||
@@ -250,17 +254,6 @@ class CustomTabs extends StatefulWidget {
|
|||||||
|
|
||||||
class _CustomTabsState extends State<CustomTabs> {
|
class _CustomTabsState extends State<CustomTabs> {
|
||||||
final HomeController _homeController = Get.put(HomeController());
|
final HomeController _homeController = Get.put(HomeController());
|
||||||
int currentTabIndex = 1;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_homeController.tabController.addListener(listen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void listen() {
|
|
||||||
_homeController.initialIndex.value = _homeController.tabController.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onTap(int index) {
|
void onTap(int index) {
|
||||||
feedBack();
|
feedBack();
|
||||||
@@ -271,34 +264,30 @@ class _CustomTabsState extends State<CustomTabs> {
|
|||||||
_homeController.tabController.index = index;
|
_homeController.tabController.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
_homeController.tabController.removeListener(listen);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
height: 44,
|
height: 44,
|
||||||
margin: const EdgeInsets.only(top: 4),
|
margin: const EdgeInsets.only(top: 4),
|
||||||
child: ListView.separated(
|
child: Obx(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14.0),
|
() => ListView.separated(
|
||||||
scrollDirection: Axis.horizontal,
|
padding: const EdgeInsets.symmetric(horizontal: 14.0),
|
||||||
itemCount: _homeController.tabs.length,
|
scrollDirection: Axis.horizontal,
|
||||||
separatorBuilder: (BuildContext context, int index) {
|
itemCount: _homeController.tabs.length,
|
||||||
return const SizedBox(width: 10);
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
},
|
return const SizedBox(width: 10);
|
||||||
itemBuilder: (BuildContext context, int index) {
|
},
|
||||||
String label = _homeController.tabs[index]['label'];
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return Obx(
|
String label = _homeController.tabs[index]['label'];
|
||||||
() => CustomChip(
|
return Obx(
|
||||||
onTap: () => onTap(index),
|
() => CustomChip(
|
||||||
label: label,
|
onTap: () => onTap(index),
|
||||||
selected: index == _homeController.initialIndex.value,
|
label: label,
|
||||||
),
|
selected: index == _homeController.initialIndex.value,
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,8 +162,9 @@ class _LivePageState extends State<LivePage>
|
|||||||
crossAxisCount: crossAxisCount,
|
crossAxisCount: crossAxisCount,
|
||||||
mainAxisExtent:
|
mainAxisExtent:
|
||||||
Get.size.width / crossAxisCount / StyleString.aspectRatio +
|
Get.size.width / crossAxisCount / StyleString.aspectRatio +
|
||||||
(crossAxisCount == 1 ? 48 : 68) *
|
MediaQuery.textScalerOf(context).scale(
|
||||||
MediaQuery.of(context).textScaleFactor,
|
(crossAxisCount == 1 ? 48 : 68),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(BuildContext context, int index) {
|
(BuildContext context, int index) {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
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:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:pilipala/http/common.dart';
|
||||||
import 'package:pilipala/pages/dynamics/index.dart';
|
import 'package:pilipala/pages/dynamics/index.dart';
|
||||||
import 'package:pilipala/pages/home/view.dart';
|
import 'package:pilipala/pages/home/view.dart';
|
||||||
import 'package:pilipala/pages/media/index.dart';
|
import 'package:pilipala/pages/media/index.dart';
|
||||||
@@ -27,6 +29,7 @@ class MainController extends GetxController {
|
|||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
'label': "首页",
|
'label': "首页",
|
||||||
|
'count': 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'icon': const Icon(
|
'icon': const Icon(
|
||||||
@@ -38,6 +41,7 @@ class MainController extends GetxController {
|
|||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
'label': "动态",
|
'label': "动态",
|
||||||
|
'count': 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'icon': const Icon(
|
'icon': const Icon(
|
||||||
@@ -49,6 +53,7 @@ class MainController extends GetxController {
|
|||||||
size: 21,
|
size: 21,
|
||||||
),
|
),
|
||||||
'label': "媒体库",
|
'label': "媒体库",
|
||||||
|
'count': 0,
|
||||||
}
|
}
|
||||||
].obs;
|
].obs;
|
||||||
final StreamController<bool> bottomBarStream =
|
final StreamController<bool> bottomBarStream =
|
||||||
@@ -56,6 +61,10 @@ class MainController extends GetxController {
|
|||||||
Box setting = GStrorage.setting;
|
Box setting = GStrorage.setting;
|
||||||
DateTime? _lastPressedAt;
|
DateTime? _lastPressedAt;
|
||||||
late bool hideTabBar;
|
late bool hideTabBar;
|
||||||
|
late PageController pageController;
|
||||||
|
int selectedIndex = 0;
|
||||||
|
Box userInfoCache = GStrorage.userInfo;
|
||||||
|
RxBool userLogin = false.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@@ -64,17 +73,47 @@ class MainController extends GetxController {
|
|||||||
Utils.checkUpdata();
|
Utils.checkUpdata();
|
||||||
}
|
}
|
||||||
hideTabBar = setting.get(SettingBoxKey.hideTabBar, defaultValue: true);
|
hideTabBar = setting.get(SettingBoxKey.hideTabBar, defaultValue: true);
|
||||||
|
var userInfo = userInfoCache.get('userInfoCache');
|
||||||
|
userLogin.value = userInfo != null;
|
||||||
|
getUnreadDynamic();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> onBackPressed(BuildContext context) {
|
void onBackPressed(BuildContext context) {
|
||||||
if (_lastPressedAt == null ||
|
if (_lastPressedAt == null ||
|
||||||
DateTime.now().difference(_lastPressedAt!) >
|
DateTime.now().difference(_lastPressedAt!) >
|
||||||
const Duration(seconds: 2)) {
|
const Duration(seconds: 2)) {
|
||||||
// 两次点击时间间隔超过2秒,重新记录时间戳
|
// 两次点击时间间隔超过2秒,重新记录时间戳
|
||||||
_lastPressedAt = DateTime.now();
|
_lastPressedAt = DateTime.now();
|
||||||
|
if (selectedIndex != 0) {
|
||||||
|
pageController.jumpTo(0);
|
||||||
|
}
|
||||||
SmartDialog.showToast("再按一次退出Pili");
|
SmartDialog.showToast("再按一次退出Pili");
|
||||||
return Future.value(false); // 不退出应用
|
return; // 不退出应用
|
||||||
}
|
}
|
||||||
return Future.value(true); // 退出应用
|
SystemNavigator.pop(); // 退出应用
|
||||||
|
}
|
||||||
|
|
||||||
|
void getUnreadDynamic() async {
|
||||||
|
if (!userLogin.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int dynamicItemIndex =
|
||||||
|
navigationBars.indexWhere((item) => item['label'] == "动态");
|
||||||
|
var res = await CommonHttp.unReadDynamic();
|
||||||
|
var data = res['data'];
|
||||||
|
if (dynamicItemIndex != -1) {
|
||||||
|
navigationBars[dynamicItemIndex]['count'] =
|
||||||
|
data == null ? 0 : data.length; // 修改 count 属性为新的值
|
||||||
|
}
|
||||||
|
navigationBars.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearUnread() async {
|
||||||
|
int dynamicItemIndex =
|
||||||
|
navigationBars.indexWhere((item) => item['label'] == "动态");
|
||||||
|
if (dynamicItemIndex != -1) {
|
||||||
|
navigationBars[dynamicItemIndex]['count'] = 0; // 修改 count 属性为新的值
|
||||||
|
}
|
||||||
|
navigationBars.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
final DynamicsController _dynamicController = Get.put(DynamicsController());
|
final DynamicsController _dynamicController = Get.put(DynamicsController());
|
||||||
final MediaController _mediaController = Get.put(MediaController());
|
final MediaController _mediaController = Get.put(MediaController());
|
||||||
|
|
||||||
PageController? _pageController;
|
|
||||||
int selectedIndex = 0;
|
|
||||||
int? _lastSelectTime; //上次点击时间
|
int? _lastSelectTime; //上次点击时间
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStrorage.setting;
|
||||||
late bool enableMYBar;
|
late bool enableMYBar;
|
||||||
@@ -34,13 +32,14 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_lastSelectTime = DateTime.now().millisecondsSinceEpoch;
|
_lastSelectTime = DateTime.now().millisecondsSinceEpoch;
|
||||||
_pageController = PageController(initialPage: selectedIndex);
|
_mainController.pageController =
|
||||||
|
PageController(initialPage: _mainController.selectedIndex);
|
||||||
enableMYBar = setting.get(SettingBoxKey.enableMYBar, defaultValue: true);
|
enableMYBar = setting.get(SettingBoxKey.enableMYBar, defaultValue: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIndex(int value) async {
|
void setIndex(int value) async {
|
||||||
feedBack();
|
feedBack();
|
||||||
_pageController!.jumpToPage(value);
|
_mainController.pageController.jumpToPage(value);
|
||||||
var currentPage = _mainController.pages[value];
|
var currentPage = _mainController.pages[value];
|
||||||
if (currentPage is HomePage) {
|
if (currentPage is HomePage) {
|
||||||
if (_homeController.flag) {
|
if (_homeController.flag) {
|
||||||
@@ -68,6 +67,7 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
_lastSelectTime = DateTime.now().millisecondsSinceEpoch;
|
_lastSelectTime = DateTime.now().millisecondsSinceEpoch;
|
||||||
}
|
}
|
||||||
_dynamicController.flag = true;
|
_dynamicController.flag = true;
|
||||||
|
_mainController.clearUnread();
|
||||||
} else {
|
} else {
|
||||||
_dynamicController.flag = false;
|
_dynamicController.flag = false;
|
||||||
}
|
}
|
||||||
@@ -94,14 +94,17 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
localCache.put('sheetHeight', sheetHeight);
|
localCache.put('sheetHeight', sheetHeight);
|
||||||
localCache.put('statusBarHeight', statusBarHeight);
|
localCache.put('statusBarHeight', statusBarHeight);
|
||||||
return PopScope(
|
return PopScope(
|
||||||
onPopInvoked: (bool status) => _mainController.onBackPressed(context),
|
canPop: false,
|
||||||
|
onPopInvoked: (bool didPop) async {
|
||||||
|
_mainController.onBackPressed(context);
|
||||||
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
extendBody: true,
|
extendBody: true,
|
||||||
body: PageView(
|
body: PageView(
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
controller: _pageController,
|
controller: _mainController.pageController,
|
||||||
onPageChanged: (index) {
|
onPageChanged: (index) {
|
||||||
selectedIndex = index;
|
_mainController.selectedIndex = index;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
children: _mainController.pages,
|
children: _mainController.pages,
|
||||||
@@ -116,36 +119,48 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
curve: Curves.easeInOutCubicEmphasized,
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
duration: const Duration(milliseconds: 500),
|
duration: const Duration(milliseconds: 500),
|
||||||
offset: Offset(0, snapshot.data ? 0 : 1),
|
offset: Offset(0, snapshot.data ? 0 : 1),
|
||||||
child: enableMYBar
|
child: Obx(
|
||||||
? NavigationBar(
|
() => enableMYBar
|
||||||
onDestinationSelected: (value) => setIndex(value),
|
? NavigationBar(
|
||||||
selectedIndex: selectedIndex,
|
onDestinationSelected: (value) => setIndex(value),
|
||||||
destinations: <Widget>[
|
selectedIndex: _mainController.selectedIndex,
|
||||||
..._mainController.navigationBars.map((e) {
|
destinations: <Widget>[
|
||||||
return NavigationDestination(
|
..._mainController.navigationBars.map((e) {
|
||||||
icon: e['icon'],
|
return NavigationDestination(
|
||||||
selectedIcon: e['selectIcon'],
|
icon: Badge(
|
||||||
label: e['label'],
|
label: Text(e['count'].toString()),
|
||||||
);
|
padding: const EdgeInsets.fromLTRB(6, 0, 6, 0),
|
||||||
}).toList(),
|
isLabelVisible: e['count'] > 0,
|
||||||
],
|
child: e['icon'],
|
||||||
)
|
),
|
||||||
: BottomNavigationBar(
|
selectedIcon: e['selectIcon'],
|
||||||
currentIndex: selectedIndex,
|
label: e['label'],
|
||||||
onTap: (value) => setIndex(value),
|
);
|
||||||
iconSize: 16,
|
}).toList(),
|
||||||
selectedFontSize: 12,
|
],
|
||||||
unselectedFontSize: 12,
|
)
|
||||||
items: [
|
: BottomNavigationBar(
|
||||||
..._mainController.navigationBars.map((e) {
|
currentIndex: _mainController.selectedIndex,
|
||||||
return BottomNavigationBarItem(
|
onTap: (value) => setIndex(value),
|
||||||
icon: e['icon'],
|
iconSize: 16,
|
||||||
activeIcon: e['selectIcon'],
|
selectedFontSize: 12,
|
||||||
label: e['label'],
|
unselectedFontSize: 12,
|
||||||
);
|
items: [
|
||||||
}).toList(),
|
..._mainController.navigationBars.map((e) {
|
||||||
],
|
return BottomNavigationBarItem(
|
||||||
),
|
icon: Badge(
|
||||||
|
label: Text(e['count'].toString()),
|
||||||
|
padding: const EdgeInsets.fromLTRB(6, 0, 6, 0),
|
||||||
|
isLabelVisible: e['count'] > 0,
|
||||||
|
child: e['icon'],
|
||||||
|
),
|
||||||
|
activeIcon: e['selectIcon'],
|
||||||
|
label: e['label'],
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ class _MediaPageState extends State<MediaPage>
|
|||||||
// const SizedBox(height: 10),
|
// const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 200 * MediaQuery.of(context).textScaleFactor,
|
height: MediaQuery.textScalerOf(context).scale(200),
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: _futureBuilderFuture,
|
future: _futureBuilderFuture,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
|||||||
@@ -26,10 +26,9 @@ Widget searchArticlePanel(BuildContext context, ctr, list) {
|
|||||||
StyleString.safeSpace, 5, StyleString.safeSpace, 5),
|
StyleString.safeSpace, 5, StyleString.safeSpace, 5),
|
||||||
child: LayoutBuilder(builder: (context, boxConstraints) {
|
child: LayoutBuilder(builder: (context, boxConstraints) {
|
||||||
double width = (boxConstraints.maxWidth -
|
double width = (boxConstraints.maxWidth -
|
||||||
StyleString.cardSpace *
|
StyleString.cardSpace *
|
||||||
6 /
|
6 /
|
||||||
MediaQuery.of(context).textScaleFactor) /
|
MediaQuery.textScalerOf(context).scale(2.0));
|
||||||
2;
|
|
||||||
return Container(
|
return Container(
|
||||||
constraints: const BoxConstraints(minHeight: 88),
|
constraints: const BoxConstraints(minHeight: 88),
|
||||||
height: width / StyleString.aspectRatio,
|
height: width / StyleString.aspectRatio,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Widget searchLivePanel(BuildContext context, ctr, list) {
|
|||||||
mainAxisSpacing: StyleString.cardSpace + 3,
|
mainAxisSpacing: StyleString.cardSpace + 3,
|
||||||
mainAxisExtent:
|
mainAxisExtent:
|
||||||
MediaQuery.sizeOf(context).width / 2 / StyleString.aspectRatio +
|
MediaQuery.sizeOf(context).width / 2 / StyleString.aspectRatio +
|
||||||
66 * MediaQuery.of(context).textScaleFactor),
|
MediaQuery.textScalerOf(context).scale(66.0)),
|
||||||
itemCount: list.length,
|
itemCount: list.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return LiveItem(liveItem: list![index]);
|
return LiveItem(liveItem: list![index]);
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text: i['text'],
|
text: i['text'],
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: Theme.of(context)
|
fontSize: MediaQuery.textScalerOf(context)
|
||||||
|
.scale(Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.titleSmall!
|
.titleSmall!
|
||||||
.fontSize! *
|
.fontSize!),
|
||||||
MediaQuery.of(context).textScaleFactor,
|
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: i['type'] == 'em'
|
color: i['type'] == 'em'
|
||||||
? Theme.of(context).colorScheme.primary
|
? Theme.of(context).colorScheme.primary
|
||||||
|
|||||||
90
lib/pages/setting/pages/home_tabbar_set.dart
Normal file
90
lib/pages/setting/pages/home_tabbar_set.dart
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:pilipala/models/common/tab_type.dart';
|
||||||
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
|
class TabbarSetPage extends StatefulWidget {
|
||||||
|
const TabbarSetPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<TabbarSetPage> createState() => _TabbarSetPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TabbarSetPageState extends State<TabbarSetPage> {
|
||||||
|
Box settingStorage = GStrorage.setting;
|
||||||
|
late List defaultTabs;
|
||||||
|
late List<String> tabbarSort;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
defaultTabs = tabsConfig;
|
||||||
|
tabbarSort = settingStorage.get(SettingBoxKey.tabbarSort,
|
||||||
|
defaultValue: ['live', 'rcmd', 'hot', 'bangumi']);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveEdit() {
|
||||||
|
List<String> sortedTabbar = defaultTabs
|
||||||
|
.where((i) => tabbarSort.contains((i['type'] as TabType).id))
|
||||||
|
.map<String>((i) => (i['type'] as TabType).id)
|
||||||
|
.toList();
|
||||||
|
if (sortedTabbar.isEmpty) {
|
||||||
|
SmartDialog.showToast('请至少设置一项!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settingStorage.put(SettingBoxKey.tabbarSort, sortedTabbar);
|
||||||
|
SmartDialog.showToast('保存成功,下次启动时生效');
|
||||||
|
}
|
||||||
|
|
||||||
|
void onReorder(int oldIndex, int newIndex) {
|
||||||
|
setState(() {
|
||||||
|
if (newIndex > oldIndex) {
|
||||||
|
newIndex -= 1;
|
||||||
|
}
|
||||||
|
final tabsItem = defaultTabs.removeAt(oldIndex);
|
||||||
|
defaultTabs.insert(newIndex, tabsItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final listTiles = [
|
||||||
|
for (int i = 0; i < defaultTabs.length; i++) ...[
|
||||||
|
CheckboxListTile(
|
||||||
|
key: Key(defaultTabs[i]['label']),
|
||||||
|
value: tabbarSort.contains((defaultTabs[i]['type'] as TabType).id),
|
||||||
|
onChanged: (bool? newValue) {
|
||||||
|
String tabTypeId = (defaultTabs[i]['type'] as TabType).id;
|
||||||
|
if (!newValue!) {
|
||||||
|
tabbarSort.remove(tabTypeId);
|
||||||
|
} else {
|
||||||
|
tabbarSort.add(tabTypeId);
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
title: Text(defaultTabs[i]['label']),
|
||||||
|
secondary: const Icon(Icons.drag_indicator_rounded),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Tabbar编辑'),
|
||||||
|
actions: [
|
||||||
|
TextButton(onPressed: () => saveEdit(), child: const Text('保存')),
|
||||||
|
const SizedBox(width: 12)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: ReorderableListView(
|
||||||
|
onReorder: onReorder,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
footer: SizedBox(
|
||||||
|
height: MediaQuery.of(context).padding.bottom + 30,
|
||||||
|
),
|
||||||
|
children: listTiles,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -254,6 +254,11 @@ class _StyleSettingState extends State<StyleSetting> {
|
|||||||
onTap: () => Get.toNamed('/fontSizeSetting'),
|
onTap: () => Get.toNamed('/fontSizeSetting'),
|
||||||
title: Text('字体大小', style: titleStyle),
|
title: Text('字体大小', style: titleStyle),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: false,
|
||||||
|
onTap: () => Get.toNamed('/tabbarSetting'),
|
||||||
|
title: Text('首页tabbar', style: titleStyle),
|
||||||
|
),
|
||||||
if (Platform.isAndroid)
|
if (Platform.isAndroid)
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import './controller.dart';
|
|||||||
|
|
||||||
class RelatedVideoPanel extends StatelessWidget {
|
class RelatedVideoPanel extends StatelessWidget {
|
||||||
final ReleatedController _releatedController =
|
final ReleatedController _releatedController =
|
||||||
Get.put(ReleatedController(), tag: Get.arguments['heroTag']);
|
Get.put(ReleatedController(), tag: Get.arguments?['heroTag']);
|
||||||
|
RelatedVideoPanel({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -2,12 +2,10 @@ import 'dart:async';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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/http/video.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/common/reply_type.dart';
|
import 'package:pilipala/models/common/reply_type.dart';
|
||||||
import 'package:pilipala/models/video/reply/item.dart';
|
import 'package:pilipala/models/video/reply/item.dart';
|
||||||
import 'package:pilipala/utils/feed_back.dart';
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
import 'package:pilipala/utils/storage.dart';
|
|
||||||
|
|
||||||
class VideoReplyNewDialog extends StatefulWidget {
|
class VideoReplyNewDialog extends StatefulWidget {
|
||||||
final int? oid;
|
final int? oid;
|
||||||
@@ -34,23 +32,16 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
final TextEditingController _replyContentController = TextEditingController();
|
final TextEditingController _replyContentController = TextEditingController();
|
||||||
final FocusNode replyContentFocusNode = FocusNode();
|
final FocusNode replyContentFocusNode = FocusNode();
|
||||||
final GlobalKey _formKey = GlobalKey<FormState>();
|
final GlobalKey _formKey = GlobalKey<FormState>();
|
||||||
bool ableClean = false;
|
|
||||||
Timer? timer;
|
|
||||||
Box localCache = GStrorage.localCache;
|
|
||||||
late double sheetHeight;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// 监听输入框聚焦
|
// 监听输入框聚焦
|
||||||
// replyContentFocusNode.addListener(_onFocus);
|
// replyContentFocusNode.addListener(_onFocus);
|
||||||
_replyContentController.addListener(_printLatestValue);
|
|
||||||
// 界面观察者 必须
|
// 界面观察者 必须
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
// 自动聚焦
|
// 自动聚焦
|
||||||
_autoFocus();
|
_autoFocus();
|
||||||
|
|
||||||
sheetHeight = localCache.get('sheetHeight');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_autoFocus() async {
|
_autoFocus() async {
|
||||||
@@ -60,12 +51,6 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_printLatestValue() {
|
|
||||||
setState(() {
|
|
||||||
ableClean = _replyContentController.text != '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future submitReplyAdd() async {
|
Future submitReplyAdd() async {
|
||||||
feedBack();
|
feedBack();
|
||||||
String message = _replyContentController.text;
|
String message = _replyContentController.text;
|
||||||
@@ -113,12 +98,14 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxHeight: 200,
|
maxHeight: 200,
|
||||||
),
|
minHeight: 120,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 12, right: 15, left: 15, bottom: 10),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 6, right: 15, left: 15, bottom: 10),
|
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
@@ -137,7 +124,9 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
style: Theme.of(context).textTheme.bodyLarge,
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
Divider(
|
Divider(
|
||||||
height: 1,
|
height: 1,
|
||||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||||
@@ -152,34 +141,23 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
width: 36,
|
width: 36,
|
||||||
height: 36,
|
height: 36,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (keyboardHeight > 0) {
|
FocusScope.of(context)
|
||||||
FocusScope.of(context).unfocus();
|
.requestFocus(replyContentFocusNode);
|
||||||
} else {
|
},
|
||||||
FocusScope.of(context)
|
icon: Icon(Icons.keyboard,
|
||||||
.requestFocus(replyContentFocusNode);
|
size: 22,
|
||||||
}
|
color: Theme.of(context).colorScheme.onBackground),
|
||||||
},
|
highlightColor:
|
||||||
icon: Icon(
|
Theme.of(context).colorScheme.onInverseSurface,
|
||||||
keyboardHeight > 0
|
style: ButtonStyle(
|
||||||
? Icons.keyboard_hide
|
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||||
: Icons.keyboard,
|
backgroundColor:
|
||||||
size: 22,
|
MaterialStateProperty.resolveWith((states) {
|
||||||
color: Theme.of(context).colorScheme.onBackground),
|
return Theme.of(context).highlightColor;
|
||||||
highlightColor:
|
}),
|
||||||
Theme.of(context).colorScheme.onInverseSurface,
|
),
|
||||||
style: ButtonStyle(
|
),
|
||||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
|
||||||
backgroundColor:
|
|
||||||
MaterialStateProperty.resolveWith((states) {
|
|
||||||
// 如果按钮被按下,返回高亮颜色
|
|
||||||
if (states.contains(MaterialState.pressed)) {
|
|
||||||
return Theme.of(context).highlightColor;
|
|
||||||
}
|
|
||||||
// 默认状态下,返回透明颜色
|
|
||||||
return Colors.transparent;
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -200,22 +178,3 @@ class _VideoReplyNewDialogState extends State<VideoReplyNewDialog>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef DebounceCallback = void Function();
|
|
||||||
|
|
||||||
class Debouncer {
|
|
||||||
DebounceCallback? callback;
|
|
||||||
final int? milliseconds;
|
|
||||||
Timer? _timer;
|
|
||||||
|
|
||||||
Debouncer({this.milliseconds});
|
|
||||||
|
|
||||||
run(DebounceCallback callback) {
|
|
||||||
if (_timer != null) {
|
|
||||||
_timer!.cancel();
|
|
||||||
}
|
|
||||||
_timer = Timer(Duration(milliseconds: milliseconds!), () {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
videoIntroController.isPaused = false;
|
videoIntroController.isPaused = false;
|
||||||
if (_extendNestCtr.position.pixels == 0 && autoplay) {
|
if (_extendNestCtr.position.pixels == 0 && autoplay) {
|
||||||
await Future.delayed(const Duration(milliseconds: 300));
|
await Future.delayed(const Duration(milliseconds: 300));
|
||||||
plPlayerController!.seekTo(videoDetailController.defaultST);
|
plPlayerController?.seekTo(videoDetailController.defaultST);
|
||||||
plPlayerController?.play();
|
plPlayerController?.play();
|
||||||
}
|
}
|
||||||
plPlayerController?.addStatusLister(playerListener);
|
plPlayerController?.addStatusLister(playerListener);
|
||||||
|
|||||||
@@ -621,7 +621,7 @@ class PlPlayerController {
|
|||||||
if (duration.value.inSeconds != 0) {
|
if (duration.value.inSeconds != 0) {
|
||||||
if (type != 'slider') {
|
if (type != 'slider') {
|
||||||
/// 拖动进度条调节时,不等待第一帧,防止抖动
|
/// 拖动进度条调节时,不等待第一帧,防止抖动
|
||||||
await _videoPlayerController!.stream.buffer.first;
|
await _videoPlayerController?.stream.buffer.first;
|
||||||
}
|
}
|
||||||
await _videoPlayerController?.seek(position);
|
await _videoPlayerController?.seek(position);
|
||||||
// if (playerStatus.stopped) {
|
// if (playerStatus.stopped) {
|
||||||
@@ -786,7 +786,7 @@ class PlPlayerController {
|
|||||||
volume.value = volumeNew;
|
volume.value = volumeNew;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FlutterVolumeController.showSystemUI = false;
|
FlutterVolumeController.updateShowSystemUI(false);
|
||||||
await FlutterVolumeController.setVolume(volumeNew);
|
await FlutterVolumeController.setVolume(volumeNew);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
print(err);
|
print(err);
|
||||||
@@ -1086,12 +1086,13 @@ class PlPlayerController {
|
|||||||
localCache.put(LocalCacheKey.danmakuOpacity, opacityVal);
|
localCache.put(LocalCacheKey.danmakuOpacity, opacityVal);
|
||||||
localCache.put(LocalCacheKey.danmakuFontScale, fontSizeVal);
|
localCache.put(LocalCacheKey.danmakuFontScale, fontSizeVal);
|
||||||
localCache.put(LocalCacheKey.danmakuDuration, danmakuDurationVal);
|
localCache.put(LocalCacheKey.danmakuDuration, danmakuDurationVal);
|
||||||
|
if (_videoPlayerController != null) {
|
||||||
var pp = _videoPlayerController!.platform as NativePlayer;
|
var pp = _videoPlayerController!.platform as NativePlayer;
|
||||||
await pp.setProperty('audio-files', '');
|
await pp.setProperty('audio-files', '');
|
||||||
removeListeners();
|
removeListeners();
|
||||||
await _videoPlayerController?.dispose();
|
await _videoPlayerController?.dispose();
|
||||||
_videoPlayerController = null;
|
_videoPlayerController = null;
|
||||||
|
}
|
||||||
_instance = null;
|
_instance = null;
|
||||||
// 关闭所有视频页面恢复亮度
|
// 关闭所有视频页面恢复亮度
|
||||||
resetBrightness();
|
resetBrightness();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
|
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_volume_controller/flutter_volume_controller.dart';
|
import 'package:flutter_volume_controller/flutter_volume_controller.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';
|
||||||
@@ -130,7 +129,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
setting.get(SettingBoxKey.enableBackgroundPlay, defaultValue: false);
|
setting.get(SettingBoxKey.enableBackgroundPlay, defaultValue: false);
|
||||||
Future.microtask(() async {
|
Future.microtask(() async {
|
||||||
try {
|
try {
|
||||||
FlutterVolumeController.showSystemUI = true;
|
FlutterVolumeController.updateShowSystemUI(true);
|
||||||
_ctr.volumeValue.value = (await FlutterVolumeController.getVolume())!;
|
_ctr.volumeValue.value = (await FlutterVolumeController.getVolume())!;
|
||||||
FlutterVolumeController.addListener((double value) {
|
FlutterVolumeController.addListener((double value) {
|
||||||
if (mounted && !_ctr.volumeInterceptEventStream.value) {
|
if (mounted && !_ctr.volumeInterceptEventStream.value) {
|
||||||
@@ -154,7 +153,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
|
|
||||||
Future<void> setVolume(double value) async {
|
Future<void> setVolume(double value) async {
|
||||||
try {
|
try {
|
||||||
FlutterVolumeController.showSystemUI = false;
|
FlutterVolumeController.updateShowSystemUI(false);
|
||||||
await FlutterVolumeController.setVolume(value);
|
await FlutterVolumeController.setVolume(value);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
_ctr.volumeValue.value = value;
|
_ctr.volumeValue.value = value;
|
||||||
@@ -703,7 +702,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return nil;
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import '../pages/setting/index.dart';
|
|||||||
import '../pages/setting/pages/color_select.dart';
|
import '../pages/setting/pages/color_select.dart';
|
||||||
import '../pages/setting/pages/display_mode.dart';
|
import '../pages/setting/pages/display_mode.dart';
|
||||||
import '../pages/setting/pages/font_size_select.dart';
|
import '../pages/setting/pages/font_size_select.dart';
|
||||||
|
import '../pages/setting/pages/home_tabbar_set.dart';
|
||||||
import '../pages/setting/pages/play_speed_set.dart';
|
import '../pages/setting/pages/play_speed_set.dart';
|
||||||
import '../pages/setting/recommend_setting.dart';
|
import '../pages/setting/recommend_setting.dart';
|
||||||
import '../pages/setting/play_setting.dart';
|
import '../pages/setting/play_setting.dart';
|
||||||
@@ -114,6 +115,8 @@ class Routes {
|
|||||||
//
|
//
|
||||||
CustomGetPage(name: '/blackListPage', page: () => const BlackListPage()),
|
CustomGetPage(name: '/blackListPage', page: () => const BlackListPage()),
|
||||||
CustomGetPage(name: '/colorSetting', page: () => const ColorSelectPage()),
|
CustomGetPage(name: '/colorSetting', page: () => const ColorSelectPage()),
|
||||||
|
// 首页tabbar
|
||||||
|
CustomGetPage(name: '/tabbarSetting', page: () => const TabbarSetPage()),
|
||||||
CustomGetPage(
|
CustomGetPage(
|
||||||
name: '/fontSizeSetting', page: () => const FontSizeSelectPage()),
|
name: '/fontSizeSetting', page: () => const FontSizeSelectPage()),
|
||||||
// 屏幕帧率
|
// 屏幕帧率
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ class SettingBoxKey {
|
|||||||
customRows = 'customRows', // 自定义列
|
customRows = 'customRows', // 自定义列
|
||||||
enableMYBar = 'enableMYBar',
|
enableMYBar = 'enableMYBar',
|
||||||
hideSearchBar = 'hideSearchBar', // 收起顶栏
|
hideSearchBar = 'hideSearchBar', // 收起顶栏
|
||||||
hideTabBar = 'hideTabBar'; // 收起底栏
|
hideTabBar = 'hideTabBar', // 收起底栏
|
||||||
|
tabbarSort = 'tabbarSort'; // 首页tabbar
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalCacheKey {
|
class LocalCacheKey {
|
||||||
|
|||||||
Reference in New Issue
Block a user