Skip to content

Commit c66a5bd

Browse files
author
liuchuancong
committed
fix(优化代码)
1 parent 8016fad commit c66a5bd

5 files changed

Lines changed: 157 additions & 54 deletions

File tree

lib/common/global/initialized.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class AppInitializer {
7979
exit(0);
8080
}
8181
MediaKit.ensureInitialized();
82+
CustomCacheManager.init();
8283
await SupaBaseManager.getInstance().initial();
8384

8485
if (PlatformUtils.isDesktop) {

lib/common/global/platform/desktop_manager.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ class DesktopManager {
103103
return Obx(() {
104104
bool fullscreen = GlobalPlayerState.to.isFullscreen.value;
105105
bool isPipModel = GlobalPlayerState.to.isPipMode.value;
106-
if (!PlatformUtils.isWindows || isPipModel) {
106+
if (!PlatformUtils.isWindows) {
107107
return child ?? const SizedBox.shrink();
108108
}
109109
return Column(
110110
children: [
111-
if (!fullscreen) const CustomTitleBar(),
111+
if (!fullscreen && !isPipModel) const CustomTitleBar(),
112112
if (child != null) Expanded(child: child),
113113
],
114114
);
Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,92 @@
1-
import 'package:file/local.dart';
1+
import 'dart:io';
2+
import 'dart:developer';
3+
import 'package:rxdart/rxdart.dart';
24
import 'package:path/path.dart' as p;
35
import 'package:path_provider/path_provider.dart';
46
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
57

68
class CustomCacheManager {
7-
static const key = 'customCacheKey';
9+
static const String _key = 'customCacheKey';
810

9-
static CacheManager instance = CacheManager(
11+
static final CacheManager instance = CacheManager(
1012
Config(
11-
key,
13+
_key,
1214
stalePeriod: const Duration(days: 1),
13-
maxNrOfCacheObjects: 20,
14-
repo: JsonCacheInfoRepository(databaseName: key),
15-
fileSystem: IOFileSystem(key),
15+
maxNrOfCacheObjects: 2000,
16+
repo: JsonCacheInfoRepository(databaseName: _key),
17+
fileSystem: IOFileSystem(_key),
1618
fileService: HttpFileService(),
1719
),
1820
);
1921

20-
static Future<double> cacheSize() async {
21-
var baseDir = await getTemporaryDirectory();
22-
var path = p.join(baseDir.path, key);
22+
static final _sizeController = BehaviorSubject<double>.seeded(0.0);
23+
static Stream<double> get cacheSizeStream => _sizeController.stream;
2324

24-
var fs = const LocalFileSystem();
25-
var directory = fs.directory((path));
26-
return (await directory.stat()).size / 8 / 1000;
25+
static final _updateTrigger = PublishSubject<void>();
26+
27+
static void init() {
28+
_updateTrigger
29+
.throttleTime(const Duration(seconds: 2), trailing: true, leading: true)
30+
.asyncMap((_) => _calculateSize())
31+
.listen((size) {
32+
_sizeController.add(size);
33+
log('缓存大小已更新: ${size.toStringAsFixed(2)} MB');
34+
});
35+
36+
// 初始统计一次
37+
notifyUpdate();
38+
}
39+
40+
static void notifyUpdate() => _updateTrigger.add(null);
41+
42+
static Future<double> _calculateSize() async {
43+
final baseDir = await getTemporaryDirectory();
44+
int totalBytes = 0;
45+
46+
final fileDir = Directory(p.join(baseDir.path, _key));
47+
if (await fileDir.exists()) {
48+
await for (var file in fileDir.list(recursive: true)) {
49+
if (file is File) totalBytes += await file.length();
50+
}
51+
}
52+
53+
final dbFile = File(p.join(baseDir.path, '$_key.json'));
54+
if (await dbFile.exists()) {
55+
totalBytes += await dbFile.length();
56+
}
57+
58+
// 转换为 MB (1024 * 1024)
59+
return totalBytes / (1024 * 1024);
2760
}
2861

62+
/// 彻底清理缓存:清理数据库 + 物理删除文件夹
2963
static Future<void> clearCache() async {
30-
var baseDir = await getTemporaryDirectory();
31-
var path = p.join(baseDir.path, key);
64+
try {
65+
await instance.emptyCache();
66+
67+
// 2. 物理删除残留文件夹和 JSON 数据库文件
68+
final baseDir = await getTemporaryDirectory();
69+
final dirPath = p.join(baseDir.path, _key);
70+
final dbPath = p.join(baseDir.path, '$_key.json');
71+
72+
final dir = Directory(dirPath);
73+
if (await dir.exists()) await dir.delete(recursive: true);
74+
75+
final db = File(dbPath);
76+
if (await db.exists()) await db.delete();
77+
78+
log('清除缓存成功');
79+
80+
// 立即重置流状态
81+
_sizeController.add(0.0);
82+
} catch (e) {
83+
log('清理缓存失败: $e');
84+
}
85+
}
3286

33-
var fs = const LocalFileSystem();
34-
var directory = fs.directory((path));
35-
await directory.delete(recursive: true);
87+
/// 销毁资源
88+
static void dispose() {
89+
_sizeController.close();
90+
_updateTrigger.close();
3691
}
3792
}

lib/modules/live_play/live_play_page.dart

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,52 @@ class LivePlayPage extends GetView<LivePlayController> {
2020

2121
@override
2222
Widget build(BuildContext context) {
23-
if (settings.enableScreenKeepOn.value) {
24-
WakelockPlus.toggle(enable: settings.enableScreenKeepOn.value);
25-
}
2623
return Obx(() {
27-
if (SwitchableGlobalPlayer().isInPip.value) {
28-
return SwitchableGlobalPlayer().buildPiPOverlay();
29-
}
30-
if (controller.screenMode.value == VideoMode.normal) {
31-
return buildNormalPlayerView(context);
32-
} else if (controller.screenMode.value == VideoMode.widescreen) {
33-
return buildVideoPlayer();
24+
_updateWakelock();
25+
final isInPip = SwitchableGlobalPlayer().isInPip.value;
26+
final mode = controller.screenMode.value;
27+
28+
return Container(
29+
color: Colors.black,
30+
child: AnimatedSwitcher(
31+
duration: const Duration(milliseconds: 500),
32+
child: _buildConstrainedChild(isInPip, mode, context),
33+
layoutBuilder: (currentChild, previousChildren) {
34+
return Stack(
35+
alignment: Alignment.center,
36+
children: <Widget>[...previousChildren, if (currentChild != null) currentChild],
37+
);
38+
},
39+
),
40+
);
41+
});
42+
}
43+
44+
Widget _buildConstrainedChild(bool isInPip, VideoMode mode, BuildContext context) {
45+
if (isInPip) {
46+
return Theme(
47+
data: ThemeData.dark(),
48+
child: Container(
49+
key: const ValueKey('pip'),
50+
color: Colors.transparent,
51+
child: SwitchableGlobalPlayer().buildPiPOverlay(),
52+
),
53+
);
54+
}
55+
56+
if (mode == VideoMode.normal) {
57+
return Container(key: const ValueKey('normal'), color: Colors.black, child: buildNormalPlayerView(context));
58+
}
59+
60+
return Container(key: const ValueKey('widescreen'), color: Colors.black, child: buildVideoPlayer());
61+
}
62+
63+
void _updateWakelock() {
64+
final shouldKeepOn = settings.enableScreenKeepOn.value;
65+
WakelockPlus.enabled.then((isEnabled) {
66+
if (isEnabled != shouldKeepOn) {
67+
WakelockPlus.toggle(enable: shouldKeepOn);
3468
}
35-
return buildVideoPlayer();
3669
});
3770
}
3871

lib/modules/settings/settings_page.dart

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ class SettingsPage extends GetView<SettingsService> {
8080
subtitle: Text(S.of(context).change_language_subtitle),
8181
onTap: showLanguageSelecterDialog,
8282
),
83+
StreamBuilder<double>(
84+
stream: CustomCacheManager.cacheSizeStream,
85+
builder: (context, snapshot) {
86+
final size = snapshot.data ?? 0.0;
87+
return ListTile(
88+
leading: const Icon(Icons.download_for_offline_rounded, size: 32),
89+
title: Text("当前缓存大小: ${size.toStringAsFixed(2)} MB"),
90+
onTap: CustomCacheManager.clearCache,
91+
);
92+
},
93+
),
8394
ListTile(
8495
leading: const Icon(Icons.backup_rounded, size: 32),
8596
title: Text(S.of(context).backup_recover),
@@ -113,7 +124,7 @@ class SettingsPage extends GetView<SettingsService> {
113124
onChanged: (bool value) => controller.enableCodec.value = value,
114125
),
115126
),
116-
if (Platform.isAndroid)
127+
if (Platform.isAndroid && controller.videoPlayerIndex.value == 0)
117128
Obx(
118129
() => SwitchListTile(
119130
title: Text('兼容模式'),
@@ -162,6 +173,7 @@ class SettingsPage extends GetView<SettingsService> {
162173
onChanged: (bool value) => controller.enableFullScreenDefault.value = value,
163174
),
164175
),
176+
165177
Obx(
166178
() => ListTile(
167179
title: Text(S.of(context).prefer_resolution),
@@ -170,32 +182,34 @@ class SettingsPage extends GetView<SettingsService> {
170182
onTap: showPreferResolutionSelectorDialog,
171183
),
172184
),
173-
Padding(
174-
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
175-
child: Text("播放器高级设置", style: Get.textTheme.titleMedium),
176-
),
177-
Padding(
178-
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
179-
child: Text.rich(
180-
TextSpan(
181-
text: "请勿随意修改以下设置,除非你知道自己在做什么。\n在修改以下设置前,你应该先查阅",
182-
children: [
183-
WidgetSpan(
184-
child: GestureDetector(
185-
onTap: () {
186-
launchUrlString("https://mpv.io/manual/stable/#video-output-drivers");
187-
},
188-
child: const Text(
189-
"MPV的文档",
190-
style: TextStyle(color: Colors.blue, fontSize: 12, decoration: TextDecoration.underline),
185+
if (Platform.isAndroid && controller.videoPlayerIndex.value == 0)
186+
Padding(
187+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
188+
child: Text("播放器高级设置", style: Get.textTheme.titleMedium),
189+
),
190+
if (Platform.isAndroid && controller.videoPlayerIndex.value == 0)
191+
Padding(
192+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
193+
child: Text.rich(
194+
TextSpan(
195+
text: "请勿随意修改以下设置,除非你知道自己在做什么。\n在修改以下设置前,你应该先查阅",
196+
children: [
197+
WidgetSpan(
198+
child: GestureDetector(
199+
onTap: () {
200+
launchUrlString("https://mpv.io/manual/stable/#video-output-drivers");
201+
},
202+
child: const Text(
203+
"MPV的文档",
204+
style: TextStyle(color: Colors.blue, fontSize: 12, decoration: TextDecoration.underline),
205+
),
191206
),
192207
),
193-
),
194-
],
208+
],
209+
),
210+
style: const TextStyle(fontSize: 12, color: Colors.grey),
195211
),
196-
style: const TextStyle(fontSize: 12, color: Colors.grey),
197212
),
198-
),
199213
SettingsCard(
200214
child: Column(
201215
children: [

0 commit comments

Comments
 (0)