From a3474195f33cdce63f7b0d93880962acd3dcf3ec Mon Sep 17 00:00:00 2001 From: Liplum Date: Wed, 25 Oct 2023 13:23:59 +0800 Subject: [PATCH] new file management --- assets/l10n/zh-CN.yaml | 2 +- assets/l10n/zh-TW.yaml | 2 +- lib/files.dart | 40 ++++++++++++++++++ lib/fs/manager.dart | 47 ---------------------- lib/init.dart | 2 +- lib/main.dart | 9 ++++- lib/r.dart | 3 -- lib/timetable/page/background.dart | 4 ++ lib/timetable/page/screenshot.dart | 32 ++++++++------- lib/timetable/utils.dart | 6 +-- lib/timetable/widgets/timetable/board.dart | 6 +-- 11 files changed, 78 insertions(+), 75 deletions(-) create mode 100644 lib/files.dart delete mode 100644 lib/fs/manager.dart diff --git a/assets/l10n/zh-CN.yaml b/assets/l10n/zh-CN.yaml index e79dddc58..b7d24a92b 100644 --- a/assets/l10n/zh-CN.yaml +++ b/assets/l10n/zh-CN.yaml @@ -131,7 +131,7 @@ timetable: background: title: 壁纸 opacity: 背景不透明度 - pickTip: 选择你最喜欢的图片 + pickTip: 选择你喜欢的图片 repeat: title: 重复图像 desc: 重复图像作为填充壁纸的图案 diff --git a/assets/l10n/zh-TW.yaml b/assets/l10n/zh-TW.yaml index 76b892509..06314694d 100644 --- a/assets/l10n/zh-TW.yaml +++ b/assets/l10n/zh-TW.yaml @@ -131,7 +131,7 @@ timetable: background: title: 桌布 opacity: 背景不透明度 - pickTip: 選取你最喜愛的影像 + pickTip: 選取你喜愛的影像 repeat: title: 重複影像 desc: 重複影像作為圖案來填滿桌布 diff --git a/lib/files.dart b/lib/files.dart new file mode 100644 index 000000000..0e7b87859 --- /dev/null +++ b/lib/files.dart @@ -0,0 +1,40 @@ +import 'dart:io'; + +import 'package:path/path.dart'; + +class Files { + const Files._(); + + static late final Directory temp; + static late final Directory cache; + static late final Directory internal; + static late final Directory user; + + static Directory get screenshot => temp.subDir("screenshot"); + + static const timetable = TimetableFiles(); + + static Future init() async { + await screenshot.create(recursive: true); + await timetable.init(); + } +} + +extension DirectoryX on Directory { + File subFile(String p1, [String? p2, String? p3, String? p4]) => File(join(path, p1, p2, p3, p4)); + + Directory subDir(String p1, [String? p2, String? p3, String? p4]) => Directory(join(path, p1, p2, p3, p4)); +} + +class TimetableFiles { + const TimetableFiles(); + + File get screenshotFile => Files.screenshot.subFile("timetable.png"); + File get backgroundFile => Files.user.subFile("timetable", "background.png"); + + Directory get calendarDir => Files.user.subDir("timetable", "calendar"); + + Future init() async { + await calendarDir.create(recursive: true); + } +} diff --git a/lib/fs/manager.dart b/lib/fs/manager.dart deleted file mode 100644 index 0ef35e98a..000000000 --- a/lib/fs/manager.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'dart:io'; - -import 'package:path/path.dart'; - -enum FileKind { - temp, - user, - cache, - internal; -} - -abstract class DirLoc { - final FileKind kind; - final String path; - - const DirLoc(this.kind, this.path); - - const DirLoc.temp(this.path) : kind = FileKind.temp; - - const DirLoc.cache(this.path) : kind = FileKind.cache; - - const DirLoc.user(this.path) : kind = FileKind.user; - - const DirLoc.internal(this.path) : kind = FileKind.internal; -} - -class FileLoc { - final DirLoc dir; - final String path; - - const FileLoc(this.dir, this.path); -} - -class FileManager { - // String resolvePath(FileLoc loc) { - // switch (loc.kind) { - // case FileKind.temp: - // case FileKind.user: - // case FileKind.cache: - // case FileKind.internal: - // } - // } -} - -extension DirectoryX on Directory { - File sub(String fileName) => File(join(path, fileName)); -} diff --git a/lib/init.dart b/lib/init.dart index 8a7d6c533..332f5fd11 100644 --- a/lib/init.dart +++ b/lib/init.dart @@ -110,12 +110,12 @@ class Init { static Future _init() async { debugPrint("Initializing"); + await initStorage(); // Initialize the window size before others for a better experience when loading. if (UniversalPlatform.isDesktop) { await DesktopInit.init(); } _registerEditor(); - await initStorage(); if (UniversalPlatform.isDesktop) { final lastWindowSize = Settings.lastWindowSize; if (lastWindowSize != null) { diff --git a/lib/main.dart b/lib/main.dart index dbfcc2366..e8e5d2ecb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:sit/files.dart'; import 'package:sit/init.dart'; import 'package:sit/migration/migrations.dart'; import 'package:sit/school/yellow_pages/entity/contact.dart'; @@ -21,8 +22,12 @@ void main() async { // debugPaintSizeEnabled = true; WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); - R.appDir = await getApplicationDocumentsDirectory(); - R.tmpDir = await getTemporaryDirectory(); + Files.cache = await getApplicationCacheDirectory(); + Files.temp = await getTemporaryDirectory(); + Files.internal = await getApplicationSupportDirectory(); + Files.user = await getApplicationDocumentsDirectory(); + await Files.init(); + R.roomList = await _loadRoomNumberList(); R.userAgents = await _loadUserAgents(); R.yellowPages = await _loadYellowPages(); diff --git a/lib/r.dart b/lib/r.dart index 62242d5a7..634eceb67 100644 --- a/lib/r.dart +++ b/lib/r.dart @@ -1,4 +1,3 @@ -import 'dart:io'; import 'dart:ui'; import 'package:flutter/foundation.dart'; @@ -25,8 +24,6 @@ class R { ]; static const appId = "life.mysit.SITLife"; static const appName = "SIT Life"; - static late final Directory appDir; - static late final Directory tmpDir; static late List roomList; static late List userAgents; diff --git a/lib/timetable/page/background.dart b/lib/timetable/page/background.dart index 8f2c8dc2a..6f1821e7e 100644 --- a/lib/timetable/page/background.dart +++ b/lib/timetable/page/background.dart @@ -8,6 +8,7 @@ import 'package:rettulf/rettulf.dart'; import 'package:sit/design/adaptive/foundation.dart'; import 'package:sit/design/widgets/card.dart'; import 'package:sit/design/widgets/common.dart'; +import 'package:sit/files.dart'; import 'package:sit/settings/settings.dart'; import 'package:sit/timetable/entity/background.dart'; import "../i18n.dart"; @@ -59,7 +60,10 @@ class _TimetableBackgroundEditorState extends State w PlatformTextButton( child: i18n.save.text(), onPressed: () async { + final backgroundFi = await File(background.path).copy(Files.timetable.backgroundFile.path); + await FileImage(backgroundFi).evict(); Settings.timetable.backgroundImage = background; + if (!mounted) return; context.pop(background); }, ), diff --git a/lib/timetable/page/screenshot.dart b/lib/timetable/page/screenshot.dart index abd545721..6ec50a8a4 100644 --- a/lib/timetable/page/screenshot.dart +++ b/lib/timetable/page/screenshot.dart @@ -1,15 +1,11 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:go_router/go_router.dart'; import 'package:open_file/open_file.dart'; -import 'package:path/path.dart' show join; import 'package:rettulf/rettulf.dart'; import 'package:screenshot/screenshot.dart'; import 'package:sit/design/adaptive/foundation.dart'; -import 'package:sit/fs/manager.dart'; -import 'package:sit/r.dart'; +import 'package:sit/files.dart'; import 'package:sit/timetable/entity/timetable.dart'; import "../i18n.dart"; import '../widgets/style.dart'; @@ -33,10 +29,12 @@ class TimetableScreenshotConfigEditor extends StatefulWidget { }); @override - State createState() => _TimetableScreenshotConfigEditorState(); + State createState() => + _TimetableScreenshotConfigEditorState(); } -class _TimetableScreenshotConfigEditorState extends State { +class _TimetableScreenshotConfigEditorState + extends State { final $signature = TextEditingController(text: ""); late bool grayOutTakenLessons = widget.initialGrayOut; var enableBackground = true; @@ -166,7 +164,9 @@ class TimetableWeeklyScreenshotFilm extends StatelessWidget { Widget buildBody(BuildContext context, TimetableStyleData style) { final today = DateTime.now(); return [ - buildTitle().text(style: context.textTheme.titleLarge).padSymmetric(v: 10), + buildTitle() + .text(style: context.textTheme.titleLarge) + .padSymmetric(v: 10), TimetableOneWeek( fullSize: fullSize, timetable: timetable, @@ -175,7 +175,9 @@ class TimetableWeeklyScreenshotFilm extends StatelessWidget { return StyledCourseCell( style: style, course: lesson.course, - grayOut: config.grayOutTakenLessons ? lesson.type.endTime.isBefore(today) : false, + grayOut: config.grayOutTakenLessons + ? lesson.type.endTime.isBefore(today) + : false, ); }, ), @@ -197,10 +199,12 @@ Future takeTimetableScreenshot({ required SitTimetableEntity timetable, required int weekIndex, }) async { - final config = await context.show$Sheet$((ctx) => TimetableScreenshotConfigEditor( - timetable: timetable, - initialGrayOut: TimetableStyle.of(context).cellStyle.grayOutTakenLessons, - )); + final config = await context.show$Sheet$( + (ctx) => TimetableScreenshotConfigEditor( + timetable: timetable, + initialGrayOut: + TimetableStyle.of(context).cellStyle.grayOutTakenLessons, + )); if (config == null) return; if (!context.mounted) return; var fullSize = context.mediaQuery.size; @@ -227,7 +231,7 @@ Future takeTimetableScreenshot({ context: context, pixelRatio: View.of(context).devicePixelRatio, ); - final imgFi = R.tmpDir.sub("screenshot.png"); + final imgFi = Files.timetable.screenshotFile; await imgFi.writeAsBytes(screenshot); await OpenFile.open(imgFi.path, type: "image/png"); diff --git a/lib/timetable/utils.dart b/lib/timetable/utils.dart index fd0fa6aa1..13df3ee25 100644 --- a/lib/timetable/utils.dart +++ b/lib/timetable/utils.dart @@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart'; import 'package:ical/serializer.dart'; import 'package:open_file/open_file.dart'; import 'package:sit/design/adaptive/multiplatform.dart'; -import 'package:sit/fs/manager.dart'; +import 'package:sit/files.dart'; import 'package:sit/l10n/extension.dart'; import 'package:sit/school/entity/school.dart'; import 'package:sanitize_filename/sanitize_filename.dart'; @@ -204,7 +204,7 @@ Future exportTimetableFileAndShare( }) async { final content = jsonEncode(timetable.toJson()); final fileName = sanitizeFilename("${timetable.name}.timetable", replacement: "-"); - final timetableFi = R.tmpDir.sub(fileName); + final timetableFi = Files.temp.subFile(fileName); final sharePositionOrigin = context.getSharePositionOrigin(); await timetableFi.writeAsString(content); await Share.shareXFiles( @@ -226,7 +226,7 @@ Future exportTimetableAsICalendarAndOpen( required TimetableExportCalendarConfig config, }) async { final fileName = _getICalFileName(context, timetable); - final calendarFi = R.appDir.sub(fileName); + final calendarFi = Files.timetable.calendarDir.subFile(fileName); final data = convertTimetable2ICal(timetable: timetable, config: config); await calendarFi.writeAsString(data); // final url = Uri.encodeFull("data:text/calendar,$data"); diff --git a/lib/timetable/widgets/timetable/board.dart b/lib/timetable/widgets/timetable/board.dart index 0e2fd2421..159623cec 100644 --- a/lib/timetable/widgets/timetable/board.dart +++ b/lib/timetable/widgets/timetable/board.dart @@ -1,7 +1,6 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:rettulf/rettulf.dart'; +import 'package:sit/files.dart'; import 'package:sit/timetable/entity/background.dart'; import 'package:sit/timetable/widgets/style.dart'; @@ -94,7 +93,8 @@ class _TimetableBackgroundState extends State with SingleTi Widget build(BuildContext context) { final bk = widget.background; return Image.file( - File(bk.path), + key: ValueKey(bk.path), + Files.timetable.backgroundFile, opacity: $opacity, filterQuality: bk.antialias ? FilterQuality.low : FilterQuality.none, repeat: bk.repeat ? ImageRepeat.repeat : ImageRepeat.noRepeat,