From a37ae55e2db21c65e70d135fd29ae465b959fc80 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Sat, 10 Oct 2026 01:38:19 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B3=B4=EA=B4=80=20=ED=8F=B4=EB=8D=94?= =?UTF-8?q?=EC=97=90=20README.txt=20(=EC=98=81=EC=96=B4=20=C2=B7=20?= =?UTF-8?q?=ED=95=9C=EA=B5=AD=EC=96=B4):=20"=EC=84=A4=EC=A0=95=20=EB=B3=B4?= =?UTF-8?q?=EA=B4=80"=20=C2=B7=20"AI=20=EB=AA=A8=EB=8D=B8=20=EB=B3=B4?= =?UTF-8?q?=EA=B4=80"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Download 아래 한국어 이름 폴더를 한국어를 모르는 사용자도 알아보게 만들 때 안에 README.txt 를 둔다 (이미 있으면 그대로). 보관본 고르기 · 모델 되살리기에는 끼지 않는다. 작은 파일이라 동기로 쓴다 (비동기면 되돌리기 흐름에 기다릴 단계가 늘어 update_ui_test 의 Android 되돌리기가 시간 안에 끝나지 않았다). Co-Authored-By: Claude Opus 5.5 --- lib/app/folder_readme.dart | 24 ++++++++++++++++++++++++ lib/app/model_backup.dart | 3 +++ lib/app/version_snapshot.dart | 3 +++ test/model_backup_test.dart | 1 + test/version_snapshot_test.dart | 2 ++ 5 files changed, 33 insertions(+) create mode 100644 lib/app/folder_readme.dart diff --git a/lib/app/folder_readme.dart b/lib/app/folder_readme.dart new file mode 100644 index 0000000..ed75626 --- /dev/null +++ b/lib/app/folder_readme.dart @@ -0,0 +1,24 @@ +// l10n-skip-file: README.txt 의 영어 · 한국어 글 (화면 언어와 상관없이 둘 다 쓴다) +import 'dart:io'; + +import 'package:path/path.dart' as p; + +/// Download 아래에 만드는 한국어 이름 폴더 ("설정 보관" · "AI 모델 보관") 를 한국어를 모르는 사용자도 알아보게 +/// 그 폴더 안에 README.txt (영어 · 한국어). 이미 있으면 그대로. 실패해도 보관에는 영향 없음. +/// 작은 파일이라 바로 쓴다 (보관 흐름에 기다릴 단계를 더하지 않게). +void writeFolderReadme(String dir, String text) { + try { + final f = File(p.join(dir, 'README.txt')); + if (f.existsSync()) return; + Directory(dir).createSync(recursive: true); + f.writeAsStringSync('$text\r\n'); + } catch (_) {} +} + +const settingsBackupReadme = 'JJ_MKVMaker settings backup / 설정 보관\r\n' + 'Settings kept for each app version (one folder per version), used when going back to that version.\r\n' + '앱 버전마다 보관한 설정입니다 (버전마다 폴더 하나). 그 버전으로 되돌릴 때 씁니다.'; + +const modelBackupReadme = 'JJ_MKVMaker AI model backup / AI 모델 보관\r\n' + 'AI models copied aside before going back to an older version, so they do not have to be downloaded again.\r\n' + '예전 버전으로 되돌리기 전에 옮겨 둔 AI 모델입니다. 다시 받지 않아도 되게 되살립니다.'; diff --git a/lib/app/model_backup.dart b/lib/app/model_backup.dart index d74694e..c631141 100644 --- a/lib/app/model_backup.dart +++ b/lib/app/model_backup.dart @@ -5,6 +5,7 @@ import 'package:crypto/crypto.dart'; import 'package:path/path.dart' as p; import 'component_store.dart' show AccumulatorSink; +import 'folder_readme.dart'; /// P0 (되돌리기): Android 에서 예전 버전으로 되돌리면 앱을 지워야 해서 앱 안에 받은 AI 모델이 사라진다. /// 공용 폴더 (Download/JJ_MKVMaker/AI 모델 보관) 에 옮겨 두었다가, 다시 설치한 앱 (이 기능이 있는 판) 이 켜질 때 @@ -20,6 +21,7 @@ class ModelBackup { /// 공용 폴더 Download/JJ_MKVMaker (Android, main 에서 정함) static String? sharedRoot; + // l10n-skip: 실제 폴더 이름 (예전 보관을 찾아야 하므로 바꾸지 않음) static ModelBackup? get shared => sharedRoot == null ? null : ModelBackup(p.join(sharedRoot!, 'AI 모델 보관')); File get _manifest => File(p.join(dir, 'manifest.json')); @@ -89,6 +91,7 @@ class ModelBackup { }); list.add({'root': root, 'rel': p.posix.joinAll(p.split(rel)), 'size': f.lengthSync(), 'sha256': sha}); } + writeFolderReadme(dir, modelBackupReadme); // "AI 모델 보관" 은 한국어 이름이라 (영어 · 한국어) // 목록은 마지막에 (목록이 있으면 다 복사된 것) await _manifest.writeAsString(jsonEncode({'saved': DateTime.now().toIso8601String(), 'files': list})); } catch (_) { diff --git a/lib/app/version_snapshot.dart b/lib/app/version_snapshot.dart index 74d0b39..6c3df20 100644 --- a/lib/app/version_snapshot.dart +++ b/lib/app/version_snapshot.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:path/path.dart' as p; import '../core/app_update.dart'; +import 'folder_readme.dart'; /// 버전을 바꿀 때 (업데이트 · 예전 버전으로 되돌리기) 그 버전의 설정을 보관하고, 그 버전으로 돌아오면 되살린다. /// @@ -60,6 +61,8 @@ class VersionSnapshot { /// 지금 버전 ([version]) 의 설정을 보관한다 (같은 버전의 보관본은 새것으로). 공용 폴더에도 (있으면). Future save(String version) async { + // Download 아래 "설정 보관" 은 한국어 이름이라 안에 README.txt (영어 · 한국어) + if (sharedDir != null) writeFolderReadme(sharedDir!, settingsBackupReadme); for (final dir in [dirOf(version), if (sharedDir != null) p.join(sharedDir!, version)]) { final d = Directory(dir); if (await d.exists()) await d.delete(recursive: true); diff --git a/test/model_backup_test.dart b/test/model_backup_test.dart index c2b7cf7..a5c2dce 100644 --- a/test/model_backup_test.dart +++ b/test/model_backup_test.dart @@ -38,6 +38,7 @@ void main() { expect(progress.last, size); expect(backup.exists, true); expect(backup.savedSize, size); + expect(File(p.join(backup.dir, 'README.txt')).readAsStringSync(), startsWith('JJ_MKVMaker AI model backup / AI 모델 보관')); final before = File(p.join(roots['ai']!, 'models', 'sd15.safetensors')).readAsBytesSync(); wipeAppData(); // 앱을 지움 final r = await backup.restore(roots); diff --git a/test/version_snapshot_test.dart b/test/version_snapshot_test.dart index d6aebdf..d080ccb 100644 --- a/test/version_snapshot_test.dart +++ b/test/version_snapshot_test.dart @@ -42,6 +42,8 @@ void main() { await snap.save('2026.10.05_003'); await snap.save('2026.10.07_001'); expect(File(p.join(shared, '2026.10.05_003', 'settings.json')).existsSync(), isTrue); + // 한국어 이름 폴더 ("설정 보관") 를 알아보게 README.txt (영어 · 한국어) - 보관본 고르기에는 끼지 않는다 + expect(File(p.join(shared, 'README.txt')).readAsStringSync(), startsWith('JJ_MKVMaker settings backup / 설정 보관')); expect(p.basename(snap.sharedFor('2026.10.05_003')!), '2026.10.05_003'); expect(p.basename(snap.sharedFor('2026.10.01_001')!), '2026.10.07_001'); expect(VersionSnapshot(data.path).sharedFor('x'), isNull);