export settings file

Closes #950

tweak

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-07 20:59:58 +08:00
parent ef1ccabc8a
commit be998b8ee1
11 changed files with 80 additions and 39 deletions

View File

@@ -11,6 +11,7 @@ Widget videoProgressIndicator(double progress) => ClipRect(
child: LinearProgressIndicator( child: LinearProgressIndicator(
minHeight: 10, minHeight: 10,
value: progress, value: progress,
stopIndicatorColor: Colors.transparent,
), ),
), ),
); );

View File

@@ -69,6 +69,10 @@ void main() async {
Request(); Request();
await Request.setCookie(); await Request.setCookie();
SmartDialog.config.toast = SmartConfigToast(
displayType: SmartToastType.onlyRefresh,
);
if (Pref.enableLog) { if (Pref.enableLog) {
// 异常捕获 logo记录 // 异常捕获 logo记录
String buildConfig = String buildConfig =

View File

@@ -15,12 +15,16 @@ import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/update.dart'; import 'package:PiliPlus/utils/update.dart';
import 'package:PiliPlus/utils/utils.dart'; import 'package:PiliPlus/utils/utils.dart';
import 'package:dio/dio.dart' show Headers;
import 'package:document_file_save_plus/document_file_save_plus_platform_interface.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show Clipboard, ClipboardData; import 'package:flutter/services.dart' show Clipboard, ClipboardData;
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:intl/intl.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:share_plus/share_plus.dart';
class AboutPage extends StatefulWidget { class AboutPage extends StatefulWidget {
const AboutPage({super.key, this.showAppBar}); const AboutPage({super.key, this.showAppBar});
@@ -313,6 +317,42 @@ Commit Hash: ${BuildConfig.commitHash}''',
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
title: const Text('导入/导出设置'), title: const Text('导入/导出设置'),
children: [ children: [
ListTile(
dense: true,
title: const Text('导出文件至本地', style: style),
onTap: () async {
Get.back();
final res = utf8.encode(GStorage.exportAllSettings());
final name =
'piliplus_settings_${context.isTablet ? 'pad' : 'phone'}_'
'${DateFormat('yyyyMMddHHmmss').format(DateTime.now())}.json';
try {
DocumentFileSavePlusPlatform.instance
.saveMultipleFiles(
dataList: [res],
fileNameList: [name],
mimeTypeList: [Headers.jsonContentType],
);
if (Platform.isAndroid) {
SmartDialog.showToast('已保存');
}
} catch (e) {
SharePlus.instance.share(
ShareParams(
files: [
XFile.fromData(
res,
name: name,
mimeType: Headers.jsonContentType,
),
],
sharePositionOrigin:
await Utils.sharePositionOrigin,
),
);
}
},
),
ListTile( ListTile(
dense: true, dense: true,
title: const Text('导出设置至剪贴板', style: style), title: const Text('导出设置至剪贴板', style: style),

View File

@@ -143,7 +143,7 @@ class _CreateFavPageState extends State<CreateFavPage> {
aspectRatioPresets: [ aspectRatioPresets: [
CropAspectRatioPreset.ratio16x9, CropAspectRatioPreset.ratio16x9,
], ],
aspectRatioLockEnabled: true, aspectRatioLockEnabled: false,
resetAspectRatioEnabled: false, resetAspectRatioEnabled: false,
aspectRatioPickerButtonHidden: true, aspectRatioPickerButtonHidden: true,
), ),

View File

@@ -39,13 +39,12 @@ class LiveRoomController extends GetxController {
Rx<RoomInfoH5Data?> roomInfoH5 = Rx<RoomInfoH5Data?>(null); Rx<RoomInfoH5Data?> roomInfoH5 = Rx<RoomInfoH5Data?>(null);
Rx<int?> liveTime = Rx<int?>(null); Rx<int?> liveTime = Rx<int?>(null);
static const periodMins = 5;
Timer? liveTimeTimer; Timer? liveTimeTimer;
void startLiveTimer() { void startLiveTimer() {
if (liveTime.value != null) { if (liveTime.value != null) {
liveTimeTimer ??= Timer.periodic( liveTimeTimer ??= Timer.periodic(
const Duration(minutes: periodMins), const Duration(minutes: 5),
(_) => liveTime.refresh(), (_) => liveTime.refresh(),
); );
} }

View File

@@ -354,11 +354,11 @@ class _LiveRoomPageState extends State<LiveRoomPage>
if (text.isNotEmpty) { if (text.isNotEmpty) {
text += ' '; text += ' ';
} }
text += final duration = DurationUtil.formatDurationBetween(
'开播${DurationUtil.formatDurationBetween( liveTime * 1000,
liveTime * 1000, DateTime.now().millisecondsSinceEpoch,
DateTime.now().millisecondsSinceEpoch, );
)}'; text += duration.isEmpty ? '刚刚开播' : '开播$duration';
} }
if (text.isEmpty) { if (text.isEmpty) {
return const SizedBox.shrink(); return const SizedBox.shrink();
@@ -616,7 +616,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
); );
}, },
transitionDuration: fromEmote transitionDuration: fromEmote
? const Duration(milliseconds: 300) ? const Duration(milliseconds: 400)
: const Duration(milliseconds: 500), : const Duration(milliseconds: 500),
transitionBuilder: (context, animation, secondaryAnimation, child) { transitionBuilder: (context, animation, secondaryAnimation, child) {
var tween = Tween( var tween = Tween(
@@ -689,12 +689,8 @@ class _LiveDanmakuState extends State<LiveDanmaku> {
area: plPlayerController.showArea, area: plPlayerController.showArea,
opacity: plPlayerController.danmakuOpacity, opacity: plPlayerController.danmakuOpacity,
hideTop: plPlayerController.blockTypes.contains(5), hideTop: plPlayerController.blockTypes.contains(5),
hideScroll: plPlayerController.blockTypes.contains( hideScroll: plPlayerController.blockTypes.contains(2),
2, hideBottom: plPlayerController.blockTypes.contains(4),
),
hideBottom: plPlayerController.blockTypes.contains(
4,
),
duration: duration:
plPlayerController.danmakuDuration / plPlayerController.danmakuDuration /
plPlayerController.playbackSpeed, plPlayerController.playbackSpeed,

View File

@@ -35,10 +35,7 @@ class BottomControl extends StatelessWidget {
titleSpacing: 14, titleSpacing: 14,
title: Row( title: Row(
children: [ children: [
PlayOrPauseButton( PlayOrPauseButton(plPlayerController: plPlayerController),
plPlayerController: plPlayerController,
),
const SizedBox(width: 10),
ComBtn( ComBtn(
icon: const Icon( icon: const Icon(
Icons.refresh, Icons.refresh,

View File

@@ -177,8 +177,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
videoDetailController.queryVideoUrl(); videoDetailController.queryVideoUrl();
if (videoDetailController.autoPlay.value) { if (videoDetailController.autoPlay.value) {
plPlayerController = videoDetailController.plPlayerController; plPlayerController = videoDetailController.plPlayerController;
plPlayerController!.addStatusLister(playerListener); plPlayerController!
plPlayerController!.addPositionListener(positionListener); ..addStatusLister(playerListener)
..addPositionListener(positionListener);
await plPlayerController!.autoEnterFullscreen(); await plPlayerController!.autoEnterFullscreen();
} }
} }
@@ -327,8 +328,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
} else { } else {
await videoDetailController.playerInit(autoplay: true); await videoDetailController.playerInit(autoplay: true);
} }
plPlayerController!.addStatusLister(playerListener); plPlayerController!
plPlayerController!.addPositionListener(positionListener); ..addStatusLister(playerListener)
..addPositionListener(positionListener);
await plPlayerController!.autoEnterFullscreen(); await plPlayerController!.autoEnterFullscreen();
} }
@@ -336,8 +338,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
void dispose() { void dispose() {
_listenerFS?.cancel(); _listenerFS?.cancel();
videoDetailController.skipTimer?.cancel(); videoDetailController
videoDetailController.skipTimer = null; ..skipTimer?.cancel()
..skipTimer = null;
try { try {
Get.delete<HorizontalMemberPageController>( Get.delete<HorizontalMemberPageController>(
@@ -409,9 +412,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
videoDetailController videoDetailController
..makeHeartBeat() ..makeHeartBeat()
..showVP = plPlayerController!.showVP.value; ..showVP = plPlayerController!.showVP.value;
plPlayerController!.removeStatusLister(playerListener); plPlayerController!
plPlayerController!.removePositionListener(positionListener); ..removeStatusLister(playerListener)
plPlayerController!.pause(); ..removePositionListener(positionListener)
..pause();
} }
isShowing = false; isShowing = false;
super.didPushNext(); super.didPushNext();

View File

@@ -1451,6 +1451,9 @@ class PlPlayerController {
dynamic pgcType, dynamic pgcType,
VideoType? videoType, VideoType? videoType,
}) async { }) async {
if (isLive) {
return;
}
if (!enableHeart || MineController.anonymity.value || progress == 0) { if (!enableHeart || MineController.anonymity.value || progress == 0) {
return; return;
} else if (playerStatus.status.value == PlayerStatus.paused) { } else if (playerStatus.status.value == PlayerStatus.paused) {
@@ -1458,9 +1461,6 @@ class PlPlayerController {
return; return;
} }
} }
if (isLive) {
return;
}
bool isComplete = bool isComplete =
playerStatus.status.value == PlayerStatus.completed || playerStatus.status.value == PlayerStatus.completed ||
type == HeartBeatType.completed; type == HeartBeatType.completed;

View File

@@ -58,10 +58,9 @@ class PlayOrPauseButtonState extends State<PlayOrPauseButton>
height: 34, height: 34,
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () async { onTap: () {
if (player.state.completed) { if (player.state.completed) {
await player.seek(Duration.zero); player.seek(Duration.zero).whenComplete(player.play);
player.play();
} else { } else {
player.playOrPause(); player.playOrPause();
} }

View File

@@ -37,9 +37,11 @@ class DurationUtil {
int diffMillis = endMillis - startMillis; int diffMillis = endMillis - startMillis;
final duration = Duration(milliseconds: diffMillis); final duration = Duration(milliseconds: diffMillis);
final years = duration.inDays ~/ 365; final inDays = duration.inDays;
final months = (duration.inDays % 365) ~/ 30; final daysLeft = inDays % 365;
final days = (duration.inDays % 365) % 30; final years = inDays ~/ 365;
final months = daysLeft ~/ 30;
final days = daysLeft % 30;
final hours = duration.inHours % 24; final hours = duration.inHours % 24;
final minutes = duration.inMinutes % 60; final minutes = duration.inMinutes % 60;
@@ -49,8 +51,7 @@ class DurationUtil {
if (months > 0) format += '$months月'; if (months > 0) format += '$months月';
if (days > 0) format += '$days天'; if (days > 0) format += '$days天';
if (hours > 0) format += '$hours小时'; if (hours > 0) format += '$hours小时';
if (minutes > 0) format += '$minutes分钟';
format += '$minutes分钟';
return format; return format;
} }