예전 판에서 올라오면 바뀐 동작을 한 번 알림: 받는 쪽이 더 새것이면 건너뜀 · robocopy 링크 (193)

- 사용자 편의 (관리자 지시): 기존 사용자에게 동작이 바뀐 것을 '이번 업데이트로 바뀐 기본 설정' 창에

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
묶음5
RyuJongJin 2026-10-12 02:06:16 +09:00
parent e32cd7d648
commit 624076f787
6 changed files with 36 additions and 0 deletions

View File

@ -281,6 +281,7 @@
"lsync (실시간 동기화)": "lsync (live sync)", "lsync (실시간 동기화)": "lsync (live sync)",
"lsync 로 이동": "Move to lsync", "lsync 로 이동": "Move to lsync",
"quit 시작": "quit started", "quit 시작": "quit started",
"robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요": "robocopy copy · move: links and junctions inside the source are no longer followed and are skipped (/XJ - before, files in the outside folder a link pointed to were copied or moved too). To copy links as links, add /SJ to the robocopy options",
"robocopy 옵션": "robocopy options", "robocopy 옵션": "robocopy options",
"robocopy 종료 코드 {0}": "robocopy exit code {0}", "robocopy 종료 코드 {0}": "robocopy exit code {0}",
"rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE. When off, only adds · updates in the target", "rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE. When off, only adds · updates in the target",
@ -994,6 +995,7 @@
"복사 · 이동 {0}개": "{0} copy · move", "복사 · 이동 {0}개": "{0} copy · move",
"복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "{0} copy/move tasks have not finished. Exiting stops them, and the file being copied is removed so no incomplete file is left.", "복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "{0} copy/move tasks have not finished. Exiting stops them, and the file being copied is removed so no incomplete file is left.",
"복사 · 이동 중입니다": "Copying · moving in progress", "복사 · 이동 중입니다": "Copying · moving in progress",
"복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). 건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기": "Copy · move: files are skipped when the receiving side is newer (before, the older source overwrote them, and a move also deleted the source). Skipped files stay in the source and their number appears in the finish notice. To change back: Settings > File explorer (or Rsync) > Skip when the receiving side is newer",
"복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "Copy · move works with two panes (Pane layout > Two panes).", "복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "Copy · move works with two panes (Pane layout > Two panes).",
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "If the destination folder already has the same name (built-in method · WebDAV)", "복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "If the destination folder already has the same name (built-in method · WebDAV)",
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "Choose items to copy · move (tap, or mark with the circle on the right).", "복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "Choose items to copy · move (tap, or mark with the circle on the right).",

View File

@ -281,6 +281,7 @@
"lsync (실시간 동기화)": "lsync (リアルタイム同期)", "lsync (실시간 동기화)": "lsync (リアルタイム同期)",
"lsync 로 이동": "lsync へ移動", "lsync 로 이동": "lsync へ移動",
"quit 시작": "終了開始", "quit 시작": "終了開始",
"robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요": "robocopy のコピー · 移動: 元の中のリンク · ジャンクションはたどらずにスキップします (/XJ - 以前はリンク先の外のフォルダーのファイルまでコピー · 移動していました)。リンクのままコピーするには robocopy オプション欄に /SJ を入れてください",
"robocopy 옵션": "robocopy オプション", "robocopy 옵션": "robocopy オプション",
"robocopy 종료 코드 {0}": "robocopy 終了コード {0}", "robocopy 종료 코드 {0}": "robocopy 終了コード {0}",
"rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE。オフなら対象に追加 · 更新のみ", "rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE。オフなら対象に追加 · 更新のみ",
@ -994,6 +995,7 @@
"복사 · 이동 {0}개": "コピー・移動 {0} 件", "복사 · 이동 {0}개": "コピー・移動 {0} 件",
"복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "コピー・移動 {0} 件がまだ終わっていません。終了すると止まり、コピー中のファイルは未完成のまま残らないよう削除します。", "복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "コピー・移動 {0} 件がまだ終わっていません。終了すると止まり、コピー中のファイルは未完成のまま残らないよう削除します。",
"복사 · 이동 중입니다": "コピー・移動中です", "복사 · 이동 중입니다": "コピー・移動中です",
"복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). 건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기": "コピー · 移動: 受け取る側のファイルが新しければスキップします (以前は古い元で上書きし、移動なら元も削除していました)。スキップしたファイルは元に残り、終了の通知にその数が出ます。戻すには: 環境設定 > ファイルエクスプローラー (または Rsync) > 受け取る側が新しければスキップ",
"복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "コピー · 移動は 2 ペインで使います (ペインの配置 > 2 ペイン)。", "복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "コピー · 移動は 2 ペインで使います (ペインの配置 > 2 ペイン)。",
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "コピー・移動先のフォルダーに同じ名前がある場合 (現在の方式・WebDAV)", "복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "コピー・移動先のフォルダーに同じ名前がある場合 (現在の方式・WebDAV)",
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "コピー · 移動する項目を選んでください (タップ、または右の丸でマーク)。", "복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "コピー · 移動する項目を選んでください (タップ、または右の丸でマーク)。",

View File

@ -281,6 +281,7 @@
"lsync (실시간 동기화)": "lsync (实时同步)", "lsync (실시간 동기화)": "lsync (实时同步)",
"lsync 로 이동": "移到 lsync", "lsync 로 이동": "移到 lsync",
"quit 시작": "开始退出", "quit 시작": "开始退出",
"robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요": "robocopy 复制 · 移动:源中的链接 · 联接不再跟随,而是跳过(/XJ - 以前会连链接指向的外部文件夹中的文件一起复制 · 移动)。要按链接本身复制,请在 robocopy 选项栏中加入 /SJ",
"robocopy 옵션": "robocopy 选项", "robocopy 옵션": "robocopy 选项",
"robocopy 종료 코드 {0}": "robocopy 退出代码 {0}", "robocopy 종료 코드 {0}": "robocopy 退出代码 {0}",
"rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE。关闭时只在目标中添加 · 更新", "rsync --delete · robocopy /PURGE. 끄면 대상에 더하기 · 바꾸기만": "rsync --delete · robocopy /PURGE。关闭时只在目标中添加 · 更新",
@ -994,6 +995,7 @@
"복사 · 이동 {0}개": "复制 · 移动 {0} 个", "복사 · 이동 {0}개": "复制 · 移动 {0} 个",
"복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "{0} 个复制 · 移动尚未完成。退出会停止它们,并删除正在复制的文件,以免留下不完整的文件。", "복사 · 이동 {0}개가 아직 끝나지 않았습니다. 끝내면 멈추고, 복사하던 파일은 완성되지 않은 채로 남지 않게 지웁니다.": "{0} 个复制 · 移动尚未完成。退出会停止它们,并删除正在复制的文件,以免留下不完整的文件。",
"복사 · 이동 중입니다": "正在复制 · 移动", "복사 · 이동 중입니다": "正在复制 · 移动",
"복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). 건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기": "复制 · 移动:接收端文件较新时跳过(以前会用旧的源文件覆盖,移动时还会删除源)。跳过的文件留在源中,完成通知中会显示数量。恢复:设置 > 文件浏览器(或 Rsync)> 接收端较新时跳过",
"복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "复制 · 移动需在双窗格中使用 (窗格布局 > 双窗格)。", "복사 · 이동은 두 창에서 씁니다 (창 배치 > 두 창).": "复制 · 移动需在双窗格中使用 (窗格布局 > 双窗格)。",
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "目标文件夹中已有同名项目时 (当前方式 · WebDAV)", "복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "目标文件夹中已有同名项目时 (当前方式 · WebDAV)",
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "请选择要复制 · 移动的项目 (点按,或用右侧圆圈标记)。", "복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "请选择要复制 · 移动的项目 (点按,或用右侧圆圈标记)。",

View File

@ -692,6 +692,7 @@ class AppSettings {
'rsyncPaths': rsyncPaths, 'rsyncPaths': rsyncPaths,
'components': components, 'components': components,
'aiImageV1': true, 'aiImageV1': true,
'robocopyLinksV1': true,
'navOrder': navOrder, 'navOrder': navOrder,
'swipeNav': swipeNav, 'swipeNav': swipeNav,
'imageExts': imageExts, 'imageExts': imageExts,
@ -1043,8 +1044,21 @@ class AppSettings {
if (j['zipComicV2'] != true && j['zipComic'] != false && j.containsKey('imageExts') && !s.zipComic) 'zipComic', if (j['zipComicV2'] != true && j['zipComic'] != false && j.containsKey('imageExts') && !s.zipComic) 'zipComic',
if (j['backgroundV2'] != true && j['runInBackground'] == false && s.runInBackground && Platform.isAndroid) if (j['backgroundV2'] != true && j['runInBackground'] == false && s.runInBackground && Platform.isAndroid)
'background', 'background',
// 193 · 229: 예전 판을 쓰던 사람 (설정 파일이 있는데 이 항목이 없음) 에게 복사 · 이동이 받는 쪽의 더 새 파일을 건너뛰게 바뀐 것을 한 번
if (j.isNotEmpty && !j.containsKey('copySkipNewer')) 'copySkipNewer',
// 193: robocopy 를 쓰던 사람 (Windows) 에게 링크 · junction 을 따라가지 않게 (/XJ) 바뀐 것을 한 번
if (j['robocopyLinksV1'] != true && Platform.isWindows && _usedRobocopy(j)) 'robocopyLinks',
]; ];
/// 193: 예전 설정에서 robocopy 를 쓰고 있었는지 (복사 방법 · 기억한 복사 · 실시간 동기화 쌍)
static bool _usedRobocopy(Map<String, dynamic> j) {
bool robo(Object? x) => x is Map && x['method'] == 'robocopy';
return j['copyMethodFile'] == 'robocopy' ||
j['copyMethodFolder'] == 'robocopy' ||
((j['copyTasks'] as List?) ?? const []).any(robo) ||
((j['liveSyncPairs'] as List?) ?? const []).any(robo);
}
/// 다운로드 기본 위치: 프로그램 폴더 (쓸 수 없으면 사용자 다운로드 폴더) /// 다운로드 기본 위치: 프로그램 폴더 (쓸 수 없으면 사용자 다운로드 폴더)
String resolvedDownloadRoot() { String resolvedDownloadRoot() {
if (downloadRoot != null && downloadRoot!.isNotEmpty) return downloadRoot!; if (downloadRoot != null && downloadRoot!.isNotEmpty) return downloadRoot!;

View File

@ -24,6 +24,10 @@ Future<void> showMigrationNotice(BuildContext context, AppController c) async {
'zipComic' => tr('ZIP · CBZ 두 번 누르기: 만화 보기 → 목록. 되돌리기: 환경 설정 > 파일 탐색기 > ZIP · CBZ 를 만화로 보기'), 'zipComic' => tr('ZIP · CBZ 두 번 누르기: 만화 보기 → 목록. 되돌리기: 환경 설정 > 파일 탐색기 > ZIP · CBZ 를 만화로 보기'),
'background' => 'background' =>
tr('백그라운드로 실행: 꺼짐 → 켜짐 (← 나 최근 앱에서 밀어도 작업이 계속됨). 되돌리기: 환경 설정 > Rsync > 백그라운드로 실행'), tr('백그라운드로 실행: 꺼짐 → 켜짐 (← 나 최근 앱에서 밀어도 작업이 계속됨). 되돌리기: 환경 설정 > Rsync > 백그라운드로 실행'),
'copySkipNewer' => tr('복사 · 이동: 받는 쪽 파일이 더 새것이면 건너뜁니다 (예전에는 예전 원본으로 덮어쓰고, 이동이면 원본도 지웠습니다). '
'건너뛴 파일은 원본에 남고 끝 알림에 그 수가 나옵니다. 되돌리기: 환경 설정 > 파일 탐색기 (또는 Rsync) > 받는 쪽이 더 새것이면 건너뛰기'),
'robocopyLinks' => tr('robocopy 복사 · 이동: 원본 안의 링크 · junction 은 따라가지 않고 건너뜁니다 (/XJ - 예전에는 링크가 가리키는 바깥 폴더의 파일까지 '
'복사 · 이동했습니다). 링크째 복사하려면 robocopy 옵션 칸에 /SJ 를 넣으세요'),
_ => id, _ => id,
}; };
final open = await showDialog<bool>( final open = await showDialog<bool>(

View File

@ -84,4 +84,16 @@ void main() {
// 처음 설치 (빈 설정) 는 알릴 것 없음 // 처음 설치 (빈 설정) 는 알릴 것 없음
expect(AppSettings.fromJson({}).migrated, isEmpty); expect(AppSettings.fromJson({}).migrated, isEmpty);
}); });
test('193: 예전 판에서 올라오면 바뀐 동작 (229 받는 쪽이 더 새것이면 건너뜀 · robocopy 링크) 을 한 번 알린다', () {
final old = AppSettings.fromJson({'copyMethodFolder': 'robocopy', 'explorerV2': true});
expect(old.migrated, contains('copySkipNewer'));
expect(old.migrated.contains('robocopyLinks'), Platform.isWindows, reason: 'robocopy 는 Windows 만');
// 저장 뒤 다시 읽으면 알리지 않음
final again = AppSettings.fromJson(old.toJson());
expect(again.migrated, isNot(contains('copySkipNewer')));
expect(again.migrated, isNot(contains('robocopyLinks')));
// robocopy 를 쓰지 않던 사람에게는 링크 알림 없음
expect(AppSettings.fromJson({'explorerV2': true}).migrated, isNot(contains('robocopyLinks')));
});
} }