보관 폴더에 README.txt (영어 · 한국어): "설정 보관" · "AI 모델 보관"

Download 아래 한국어 이름 폴더를 한국어를 모르는 사용자도 알아보게 만들 때 안에 README.txt 를 둔다
(이미 있으면 그대로). 보관본 고르기 · 모델 되살리기에는 끼지 않는다. 작은 파일이라 동기로 쓴다
(비동기면 되돌리기 흐름에 기다릴 단계가 늘어 update_ui_test 의 Android 되돌리기가 시간 안에 끝나지 않았다).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
묶음4
RyuJongJin 2026-10-10 01:38:19 +09:00
parent 388d01a0e3
commit a37ae55e2d
5 changed files with 33 additions and 0 deletions

View File

@ -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 모델입니다. 다시 받지 않아도 되게 되살립니다.';

View File

@ -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 (_) {

View File

@ -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<void> 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);

View File

@ -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);

View File

@ -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);