diff --git a/assets/l10n/en.json b/assets/l10n/en.json index 9edcb03..ce8dc41 100644 --- a/assets/l10n/en.json +++ b/assets/l10n/en.json @@ -1480,6 +1480,7 @@ "이 언어 지우기": "Remove this language", "이 위치 (네트워크 드라이브 · 네트워크 공유 · USB 메모리 등) 에는 휴지통이 없어 바로 지워집니다.": "This location (network drive, network share, USB memory etc.) has no Recycle Bin, so items are deleted right away.", "이 이동 버튼 지우기": "Delete this move button", + "이 이동을 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?": "These options will be used the next time this move runs. Run it now with the new options?", "이 파일에 맞는 자막 우선 (영상 해시)": "Prefer subtitles that match this file (video hash)", "이 파일용": "For this file", "이 파일을 열 수 있는 앱이 없습니다.": "No app can open this file.", @@ -1767,6 +1768,7 @@ "지금 것만 취소 (다음 것부터 이어서)": "Cancel only the current one (continue with the next)", "지금 것만 취소: {0}": "Cancelled only the current one: {0}", "지금 도는 복사는 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?": "The running copy uses the previous options. Stop it and run again with the new options?", + "지금 도는 이동은 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?": "The running move is using the previous options. Stop it and run again with the new options?", "지금 마스터 (또는 최상) 비밀번호": "Current master (or top) password", "지금 맞추기": "Sync now", "지금 맞추는 중입니다. 끝난 뒤에 하세요.": "Syncing right now. Try again when it finishes.", diff --git a/assets/l10n/ja.json b/assets/l10n/ja.json index 69eca3d..98e5438 100644 --- a/assets/l10n/ja.json +++ b/assets/l10n/ja.json @@ -1480,6 +1480,7 @@ "이 언어 지우기": "この言語を削除", "이 위치 (네트워크 드라이브 · 네트워크 공유 · USB 메모리 등) 에는 휴지통이 없어 바로 지워집니다.": "この場所 (ネットワークドライブ・ネットワーク共有・USB メモリなど) にはごみ箱がないため、すぐに削除されます。", "이 이동 버튼 지우기": "この移動ボタンを削除", + "이 이동을 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?": "この移動を次に行うときにこのオプションを使います。今すぐ新しいオプションで実行しますか?", "이 파일에 맞는 자막 우선 (영상 해시)": "このファイルに合う字幕を優先(動画ハッシュ)", "이 파일용": "このファイル用", "이 파일을 열 수 있는 앱이 없습니다.": "このファイルを開けるアプリがありません。", @@ -1767,6 +1768,7 @@ "지금 것만 취소 (다음 것부터 이어서)": "今のものだけ取り消し (次から続ける)", "지금 것만 취소: {0}": "今のものだけ取り消し: {0}", "지금 도는 복사는 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?": "実行中のコピーは前のオプションで動いています。止めて新しいオプションで再実行しますか?", + "지금 도는 이동은 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?": "実行中の移動は前のオプションで動いています。止めて新しいオプションでやり直しますか?", "지금 마스터 (또는 최상) 비밀번호": "現在のマスター (または最上位) パスワード", "지금 맞추기": "今すぐ同期", "지금 맞추는 중입니다. 끝난 뒤에 하세요.": "同期中です。終わってから行ってください。", diff --git a/assets/l10n/zh-Hans.json b/assets/l10n/zh-Hans.json index 173d99d..8b5b828 100644 --- a/assets/l10n/zh-Hans.json +++ b/assets/l10n/zh-Hans.json @@ -1480,6 +1480,7 @@ "이 언어 지우기": "删除此语言", "이 위치 (네트워크 드라이브 · 네트워크 공유 · USB 메모리 등) 에는 휴지통이 없어 바로 지워집니다.": "此位置 (网络驱动器 · 网络共享 · U 盘等) 没有回收站,会直接删除。", "이 이동 버튼 지우기": "删除此移动按钮", + "이 이동을 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?": "下次执行此移动时将使用这些选项。现在用新选项执行吗?", "이 파일에 맞는 자막 우선 (영상 해시)": "优先匹配此文件的字幕(视频哈希)", "이 파일용": "适用于此文件", "이 파일을 열 수 있는 앱이 없습니다.": "没有可以打开此文件的应用。", @@ -1767,6 +1768,7 @@ "지금 것만 취소 (다음 것부터 이어서)": "仅取消当前项(从下一个继续)", "지금 것만 취소: {0}": "仅取消当前项:{0}", "지금 도는 복사는 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?": "正在运行的复制使用的是之前的选项。停止并用新选项重新运行吗?", + "지금 도는 이동은 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?": "正在进行的移动使用的是之前的选项。要停止并用新选项重新执行吗?", "지금 마스터 (또는 최상) 비밀번호": "当前主密码 (或最高密码)", "지금 맞추기": "立即同步", "지금 맞추는 중입니다. 끝난 뒤에 하세요.": "正在同步。请等结束后再进行。", diff --git a/lib/ui/copy_sync_settings.dart b/lib/ui/copy_sync_settings.dart index 675028f..42b3d48 100644 --- a/lib/ui/copy_sync_settings.dart +++ b/lib/ui/copy_sync_settings.dart @@ -151,13 +151,7 @@ class _CopySyncSettingsState extends State { onChanged: (v) => c.updateSettings((x) => x.copyConflict = v ?? 'ask'), ), ), - // 229: 폴더 안의 것을 맞출 때 (모니터링의 현재 방식 · WebDAV) - rsync 의 -u 와 같다 - SwitchListTile( - value: s.copySkipNewer, - onChanged: (v) => c.updateSettings((x) => x.copySkipNewer = v), - title: Text(tr('받는 쪽이 더 새것이면 건너뛰기')), - subtitle: Text(tr('현재 방식 · robocopy · WebDAV 로 복사 · 이동할 때 (rsync 의 -u, robocopy 의 /XO 와 같음). 건너뛴 파일은 이동이라도 원본에 남깁니다')), - ), + _skipNewerTile(), SettingTile( title: Text(tr('속도 제한 (KB/s)')), subtitle: Text(tr('0 = 제한 없음. 모든 방법에 적용: rsync --bwlimit, 현재 방식은 앱이 조절, robocopy 는 /IPG 로 비슷하게. ' @@ -178,6 +172,14 @@ class _CopySyncSettingsState extends State { } /// Rsync 화면: rsync 옵션 · rsync 가져오기 · 실시간 동기화 (lsync) + /// 229: 받는 쪽이 더 새것이면 건너뛰기 - 파일 탐색기 · Rsync 탭 두 곳에 같은 설정 (Rsync 화면 · 모니터링에서도 쓰여 찾기 쉽게) + Widget _skipNewerTile() => SwitchListTile( + value: c.settings.copySkipNewer, + onChanged: (v) => c.updateSettings((x) => x.copySkipNewer = v), + title: Text(tr('받는 쪽이 더 새것이면 건너뛰기')), + subtitle: Text(tr('현재 방식 · robocopy · WebDAV 로 복사 · 이동할 때 (rsync 의 -u, robocopy 의 /XO 와 같음). 건너뛴 파일은 이동이라도 원본에 남깁니다')), + ); + Widget _rsyncPart() { final s = c.settings; final desk = Platform.isWindows; @@ -186,6 +188,7 @@ class _CopySyncSettingsState extends State { _options(tr('rsync 옵션'), tr('예: -avPog (보관 · 자세히 · 진행 · 소유자 · 그룹). 속도 제한은 파일 탐색기의 속도 제한을 함께 씀. ' '새로 맞추는 폴더 쌍에 씁니다 - 이미 실행한 쌍은 기억한 옵션을 쓰며 모니터링 > 복사 · rsync 에서 따로 고칩니다'), s.rsyncOptions, defaultRsyncOptions, (x, v) => x.rsyncOptions = v), + _skipNewerTile(), SettingTile( title: Text(tr('rsync 가져오기')), subtitle: Text(_checking diff --git a/lib/ui/monitor_page.dart b/lib/ui/monitor_page.dart index 7fcb0de..adb81b2 100644 --- a/lib/ui/monitor_page.dart +++ b/lib/ui/monitor_page.dart @@ -435,8 +435,13 @@ class _CopyCardState extends State<_CopyCard> { scrollable: true, title: Text(tr('옵션을 저장했습니다')), content: Text(running - ? tr('지금 도는 복사는 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?') - : tr('이 복사를 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?')), + // 233: 이동 카드는 "이동" 으로 + ? (t.move + ? tr('지금 도는 이동은 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?') + : tr('지금 도는 복사는 앞의 옵션으로 돌고 있습니다. 멈추고 새 옵션으로 다시 실행할까요?')) + : (t.move + ? tr('이 이동을 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?') + : tr('이 복사를 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?'))), actions: [ TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(tr('현재 유지'))), FilledButton(onPressed: () => Navigator.pop(ctx, true), child: Text(tr('설정 반영 후 실행'))), diff --git a/test/monitor_test.dart b/test/monitor_test.dart index 0f8869b..f170a85 100644 --- a/test/monitor_test.dart +++ b/test/monitor_test.dart @@ -11,6 +11,7 @@ import 'package:jj_mkvmaker/core/cron_window.dart'; import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart'; import 'package:jj_mkvmaker/platform/windows/process_media_tool.dart'; import 'package:jj_mkvmaker/services/platform_services.dart'; +import 'package:jj_mkvmaker/ui/copy_sync_settings.dart' show CopySyncSettings; import 'package:jj_mkvmaker/ui/monitor_page.dart'; import 'package:path/path.dart' as p; @@ -300,6 +301,7 @@ void main() { await tester.tap(find.text('저장')); await tester.pumpAndSettle(); expect(find.text('옵션을 저장했습니다'), findsOneWidget); + expect(find.text('이 복사를 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?'), findsOneWidget); expect(find.text('설정 반영 후 실행'), findsOneWidget); await tester.tap(find.text('현재 유지')); await tester.pumpAndSettle(); @@ -313,4 +315,30 @@ void main() { expect(find.text('지금 맞추기'), findsOneWidget); expect(find.text('복사 · rsync 로 이동'), findsOneWidget); }); + + testWidgets('233: 이동 카드의 저장 창은 "이 이동을" · 229 설정은 Rsync 탭에도 있다', (tester) async { + final tmp = Directory.systemTemp.createTempSync('jj_mon233_'); + addTearDown(() => tmp.deleteSync(recursive: true)); + final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); + c.settings.copyTasks = [CopyTask(id: '1', sources: [tmp.path], dest: p.join(tmp.path, '..'), move: true, method: 'builtin')]; + tester.view.physicalSize = const Size(1500, 1000); + tester.view.devicePixelRatio = 1; + addTearDown(tester.view.reset); + await tester.pumpWidget(MaterialApp(home: MonitorPage(c: c))); + await tester.pump(); + await tester.enterText(find.widgetWithText(TextField, '속도 제한'), '500'); + await tester.pump(); + await tester.tap(find.text('저장')); + await tester.pumpAndSettle(); + expect(find.text('이 이동을 다시 할 때 이 옵션을 씁니다. 지금 새 옵션으로 실행할까요?'), findsOneWidget); + await tester.tap(find.text('현재 유지')); + await tester.pumpAndSettle(); + // Rsync 탭의 설정에도 같은 스위치 + await tester.pumpWidget(MaterialApp(home: Scaffold(body: SingleChildScrollView(child: CopySyncSettings(c: c, rsync: true))))); + await tester.pump(); + expect(find.text('받는 쪽이 더 새것이면 건너뛰기'), findsOneWidget); + await tester.tap(find.text('받는 쪽이 더 새것이면 건너뛰기')); + await tester.pump(); + expect(c.settings.copySkipNewer, isFalse); + }); }