이동 뒤 원본에 남은 파일을 다시 세어 알리기 (216) · 끝 알림에 이동 / 복사 · 개수 (212)
- 216 (관리자 지시, 205 점검에서 찾음): -u · --exclude · 대상이 더 새것 등으로 건너뛴 파일은 원본에 남는데 "끝" 으로만 보였다. 이동이 끝나면 원본에 남은 파일을 다시 세어 "n개는 원본에 남음 (건너뜀)" 으로 알린다 (끝 알림 · 모니터링 카드 · 작업 기록). - 212 (관리자 지시): 끝 알림을 "이동 끝: n개 · 원본 → 대상" / "복사 끝: n개 · …" 로. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>fix_mkv
parent
37d7c0da31
commit
44663ec2b9
|
|
@ -367,6 +367,7 @@
|
|||
"{0}개 폴더를 lsync (실시간 동기화) 로 옮겼습니다.": "Moved {0} folders to lsync (live sync).",
|
||||
"{0}개 표시함": "{0} marked",
|
||||
"{0}개 풀기": "Extract {0}",
|
||||
"{0}개 항목": "{0} items",
|
||||
"{0}개 항목을 {1}": "{0} items {1}",
|
||||
"{0}개 항목을 다음 폴더로 {1}\n{2}": "{0} items to this folder — {1}\n{2}",
|
||||
"{0}개 항목을 다음 폴더로 복사할까요?\n{1}": "Copy {0} items to this folder?\n{1}",
|
||||
|
|
@ -376,6 +377,7 @@
|
|||
"{0}개 항목을 지울까요? 되돌릴 수 없습니다.": "Delete {0} items? This cannot be undone.",
|
||||
"{0}개 항목을 휴지통으로 보낼까요?": "Move {0} items to the Recycle Bin?",
|
||||
"{0}개 항목을 휴지통으로 보냈습니다.": "Moved {0} items to the Recycle Bin.",
|
||||
"{0}개는 원본에 남음 (건너뜀)": "{0} left in the source (skipped)",
|
||||
"{0}개는 지우지 않았습니다 (취소).": "{0} were not deleted (cancelled).",
|
||||
"{0}개는 휴지통보다 커서 영구 삭제했습니다 (Windows 가 물은 대로).": "{0} were too large for the Recycle Bin and were deleted permanently (as Windows asked).",
|
||||
"{0}개는 휴지통에 들어가지 않아 영구 삭제했습니다 (Windows 가 묻고 고른 대로).": "{0} didn't fit in the Recycle Bin and were deleted permanently (as chosen when Windows asked).",
|
||||
|
|
@ -979,6 +981,7 @@
|
|||
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · 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).",
|
||||
"복사 끝 ({0}): {1}개 → {2}": "Copy done ({0}): {1} → {2}",
|
||||
"복사 끝: {0}개 · {1} → {2}": "Copy done: {0} · {1} → {2}",
|
||||
"복사 모니터링": "Copy monitor",
|
||||
"복사 실패 ({0}): {1}": "Copy failed ({0}): {1}",
|
||||
"복사 작업이라 칸의 원본 지우기 옵션 (--remove-source-files · /MOV) 은 쓰지 않습니다. 옮기려면 Rsync 화면에서 [원본 파일 지우기] 를 켜세요": "This is a copy task, so source-removing options in the field (--remove-source-files · /MOV) are not used. To move, turn on [Remove source files] on the Rsync screen",
|
||||
|
|
@ -1478,6 +1481,7 @@
|
|||
"이동": "Move",
|
||||
"이동 ({0})": "Move ({0})",
|
||||
"이동 (붙여넣기로)": "Move (to paste)",
|
||||
"이동 끝: {0}개 · {1} → {2}": "Move done: {0} · {1} → {2}",
|
||||
"이동 버튼 (세부 정보 오른쪽 아래, 위로 하나씩)": "Move buttons (bottom right of the details, stacked upward)",
|
||||
"이동 버튼 추가": "Add move button",
|
||||
"이동 버튼의 폴더": "Folder of the move button",
|
||||
|
|
|
|||
|
|
@ -367,6 +367,7 @@
|
|||
"{0}개 폴더를 lsync (실시간 동기화) 로 옮겼습니다.": "{0} 個のフォルダーを lsync (リアルタイム同期) へ移しました。",
|
||||
"{0}개 표시함": "{0} 件をマーク",
|
||||
"{0}개 풀기": "{0} 個を展開",
|
||||
"{0}개 항목": "{0} 項目",
|
||||
"{0}개 항목을 {1}": "{0} 件の項目を{1}",
|
||||
"{0}개 항목을 다음 폴더로 {1}\n{2}": "{0} 件の項目を次のフォルダーへ{1}\n{2}",
|
||||
"{0}개 항목을 다음 폴더로 복사할까요?\n{1}": "{0} 件の項目を次のフォルダーへコピーしますか?\n{1}",
|
||||
|
|
@ -376,6 +377,7 @@
|
|||
"{0}개 항목을 지울까요? 되돌릴 수 없습니다.": "{0} 件の項目を削除しますか? 元に戻せません。",
|
||||
"{0}개 항목을 휴지통으로 보낼까요?": "{0} 個の項目をごみ箱に移動しますか?",
|
||||
"{0}개 항목을 휴지통으로 보냈습니다.": "{0} 個の項目をごみ箱に移動しました。",
|
||||
"{0}개는 원본에 남음 (건너뜀)": "{0} 件は元の場所に残っています (スキップ)",
|
||||
"{0}개는 지우지 않았습니다 (취소).": "{0} 個は削除しませんでした (キャンセル)。",
|
||||
"{0}개는 휴지통보다 커서 영구 삭제했습니다 (Windows 가 물은 대로).": "{0} 個はごみ箱より大きいため完全に削除しました (Windows の確認どおり)。",
|
||||
"{0}개는 휴지통에 들어가지 않아 영구 삭제했습니다 (Windows 가 묻고 고른 대로).": "{0} 件はごみ箱に入らなかったため完全に削除しました (Windows の確認で選んだとおり)。",
|
||||
|
|
@ -979,6 +981,7 @@
|
|||
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "コピー・移動先のフォルダーに同じ名前がある場合 (現在の方式・WebDAV)",
|
||||
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "コピー · 移動する項目を選んでください (タップ、または右の丸でマーク)。",
|
||||
"복사 끝 ({0}): {1}개 → {2}": "コピー完了 ({0}): {1} 件 → {2}",
|
||||
"복사 끝: {0}개 · {1} → {2}": "コピー完了: {0} 件 · {1} → {2}",
|
||||
"복사 모니터링": "コピーのモニタリング",
|
||||
"복사 실패 ({0}): {1}": "コピー失敗 ({0}): {1}",
|
||||
"복사 작업이라 칸의 원본 지우기 옵션 (--remove-source-files · /MOV) 은 쓰지 않습니다. 옮기려면 Rsync 화면에서 [원본 파일 지우기] 를 켜세요": "コピー作業のため、欄の元ファイル削除オプション (--remove-source-files · /MOV) は使いません。移動するには Rsync 画面で [元ファイルを削除] をオンにしてください",
|
||||
|
|
@ -1478,6 +1481,7 @@
|
|||
"이동": "移動",
|
||||
"이동 ({0})": "移動({0})",
|
||||
"이동 (붙여넣기로)": "移動 (貼り付け用)",
|
||||
"이동 끝: {0}개 · {1} → {2}": "移動完了: {0} 件 · {1} → {2}",
|
||||
"이동 버튼 (세부 정보 오른쪽 아래, 위로 하나씩)": "移動ボタン(詳細の右下、上に 1つずつ)",
|
||||
"이동 버튼 추가": "移動ボタンを追加",
|
||||
"이동 버튼의 폴더": "移動ボタンのフォルダー",
|
||||
|
|
|
|||
|
|
@ -367,6 +367,7 @@
|
|||
"{0}개 폴더를 lsync (실시간 동기화) 로 옮겼습니다.": "已将 {0} 个文件夹移到 lsync (实时同步)。",
|
||||
"{0}개 표시함": "已标记 {0} 个",
|
||||
"{0}개 풀기": "解压 {0} 个",
|
||||
"{0}개 항목": "{0} 个项目",
|
||||
"{0}개 항목을 {1}": "{0} 个项目{1}",
|
||||
"{0}개 항목을 다음 폴더로 {1}\n{2}": "将 {0} 个项目到以下文件夹 — {1}\n{2}",
|
||||
"{0}개 항목을 다음 폴더로 복사할까요?\n{1}": "要将 {0} 个项目复制到以下文件夹吗?\n{1}",
|
||||
|
|
@ -376,6 +377,7 @@
|
|||
"{0}개 항목을 지울까요? 되돌릴 수 없습니다.": "删除 {0} 个项目吗? 此操作无法撤销。",
|
||||
"{0}개 항목을 휴지통으로 보낼까요?": "将 {0} 个项目移到回收站吗?",
|
||||
"{0}개 항목을 휴지통으로 보냈습니다.": "已将 {0} 个项目移到回收站。",
|
||||
"{0}개는 원본에 남음 (건너뜀)": "{0} 个留在源中(已跳过)",
|
||||
"{0}개는 지우지 않았습니다 (취소).": "{0} 个未删除 (已取消)。",
|
||||
"{0}개는 휴지통보다 커서 영구 삭제했습니다 (Windows 가 물은 대로).": "{0} 个超出回收站容量,已永久删除 (按 Windows 的提示)。",
|
||||
"{0}개는 휴지통에 들어가지 않아 영구 삭제했습니다 (Windows 가 묻고 고른 대로).": "{0} 个项目无法放入回收站,已永久删除 (按 Windows 询问时的选择)。",
|
||||
|
|
@ -979,6 +981,7 @@
|
|||
"복사 · 이동할 폴더에 같은 이름이 있으면 (현재 방식 · WebDAV)": "目标文件夹中已有同名项目时 (当前方式 · WebDAV)",
|
||||
"복사 · 이동할 항목을 고르세요 (누르거나 오른쪽 동그라미로 표시).": "请选择要复制 · 移动的项目 (点按,或用右侧圆圈标记)。",
|
||||
"복사 끝 ({0}): {1}개 → {2}": "复制完成 ({0}): {1} 个 → {2}",
|
||||
"복사 끝: {0}개 · {1} → {2}": "复制完成:{0} 个 · {1} → {2}",
|
||||
"복사 모니터링": "复制监控",
|
||||
"복사 실패 ({0}): {1}": "复制失败 ({0}): {1}",
|
||||
"복사 작업이라 칸의 원본 지우기 옵션 (--remove-source-files · /MOV) 은 쓰지 않습니다. 옮기려면 Rsync 화면에서 [원본 파일 지우기] 를 켜세요": "这是复制任务,栏中的删除源文件选项(--remove-source-files · /MOV)不会使用。要移动,请在 Rsync 界面打开 [删除源文件]",
|
||||
|
|
@ -1478,6 +1481,7 @@
|
|||
"이동": "移动",
|
||||
"이동 ({0})": "移动({0})",
|
||||
"이동 (붙여넣기로)": "移动 (用于粘贴)",
|
||||
"이동 끝: {0}개 · {1} → {2}": "移动完成:{0} 个 · {1} → {2}",
|
||||
"이동 버튼 (세부 정보 오른쪽 아래, 위로 하나씩)": "移动按钮(详细信息右下角,向上依次排列)",
|
||||
"이동 버튼 추가": "添加移动按钮",
|
||||
"이동 버튼의 폴더": "移动按钮的文件夹",
|
||||
|
|
|
|||
|
|
@ -135,12 +135,18 @@ class CopyCenter extends ChangeNotifier {
|
|||
await update(cur.copyWith(
|
||||
lastRun: DateTime.now().toIso8601String(),
|
||||
lastResult: e == null ? 'done' : e is FileOpCancelled ? 'cancelled' : 'failed',
|
||||
lastMessage: e == null ? (job.pruned > 0 ? trf('빈 폴더 {0}개 지움', [job.pruned]) : '') : '$e',
|
||||
// 216: 이동 뒤 원본에 남은 것도 카드에
|
||||
lastMessage: e == null
|
||||
? [
|
||||
if (job.leftInSource > 0) trf('{0}개는 원본에 남음 (건너뜀)', [job.leftInSource]),
|
||||
if (job.pruned > 0) trf('빈 폴더 {0}개 지움', [job.pruned]),
|
||||
].join(' · ')
|
||||
: '$e',
|
||||
lastFiles: job.allDone,
|
||||
));
|
||||
}
|
||||
c.note(e == null
|
||||
? trf('복사 끝 ({0}): {1}개 → {2}', [method.label, t.sources.length, t.dest])
|
||||
? '${job.doneSummary()} (${tr(method.label)})'
|
||||
: trf('복사 실패 ({0}): {1}', [method.label, e]));
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,18 @@ class TransferJob extends ChangeNotifier {
|
|||
int get allFiles => filesTotal.fold(0, (a, b) => a + b);
|
||||
int get allDone => filesDone.fold(0, (a, b) => a + b);
|
||||
|
||||
/// 216: 이동이 끝난 뒤 원본에 남은 파일 수 (건너뛴 것)
|
||||
int leftInSource = 0;
|
||||
|
||||
/// 212 · 216: 끝 알림 한 줄 - "이동 끝: n개 · 원본 → 대상 · m개는 원본에 남음 (건너뜀)" / "복사 끝: n개 · 원본 → 대상"
|
||||
String doneSummary() {
|
||||
final from = sources.length == 1 ? vBasename(sources.first) : trf('{0}개 항목', [sources.length]);
|
||||
final total = filesTotal.fold(0, (a, b) => a + b);
|
||||
final n = move ? (total - leftInSource).clamp(0, total) : allDone;
|
||||
final head = move ? trf('이동 끝: {0}개 · {1} → {2}', [n, from, vBasename(dest)]) : trf('복사 끝: {0}개 · {1} → {2}', [n, from, vBasename(dest)]);
|
||||
return leftInSource > 0 ? '$head · ${trf('{0}개는 원본에 남음 (건너뜀)', [leftInSource])}' : head;
|
||||
}
|
||||
|
||||
/// 위쪽 진행률: 끝낸 항목 + 지금 항목의 파일 진행
|
||||
double get overall {
|
||||
if (finished) return 1;
|
||||
|
|
@ -214,6 +226,15 @@ class TransferJob extends ChangeNotifier {
|
|||
if (isDav(s) || FileSystemEntity.isDirectorySync(s)) pruned += await removeEmptyDirs(s, keepRoot: prune == 'keep');
|
||||
}
|
||||
}
|
||||
// 216: 옮긴 뒤 원본에 남은 파일을 다시 센다 (옵션 -u · --exclude · 대상이 더 새것 등으로 건너뜀, 맞춘 뒤 바뀜) -
|
||||
// 예전에는 남은 것이 있어도 "끝" 으로만 보였다
|
||||
if (move) {
|
||||
for (final s in sources) {
|
||||
try {
|
||||
if (await vExists(s)) leftInSource += await countFiles(s);
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error = cancelled ? const FileOpCancelled() : e;
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -2271,7 +2271,8 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
? tr('취소했습니다.')
|
||||
: error != null
|
||||
? trf('끝나지 못했습니다: {0}', [error])
|
||||
: trf('rsync 끝: {0}', [jobs.map((j) => '${vBasename(j.sources.first)} → ${vBasename(j.dest)}').join(' · ')]));
|
||||
// 212 · 216: 이동인지 · 몇 개인지 · 원본에 남은 것
|
||||
: jobs.map((j) => j.doneSummary()).join('\n'));
|
||||
await Future<void>.delayed(const Duration(milliseconds: 1200));
|
||||
if (mounted) setState(() => _jobs = [for (final j in _jobs) if (!jobs.contains(j)) j]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ void main() {
|
|||
expect(File(p.join(src, 'a.txt')).existsSync(), isFalse, reason: '맞춘 것은 지움');
|
||||
expect(old.existsSync(), isTrue, reason: '건너뛴 것은 남김 (예전에는 지웠다)');
|
||||
expect(File(p.join(dst, 'keep.txt')).readAsStringSync(), 'newer target');
|
||||
// 216 · 212: 원본에 남은 것을 다시 세어 끝 알림에
|
||||
expect(job.leftInSource, 1);
|
||||
expect(job.doneSummary(), contains('이동 끝: 1개 · src → dst'));
|
||||
expect(job.doneSummary(), contains('1개는 원본에 남음 (건너뜀)'));
|
||||
});
|
||||
|
||||
test('214 c: 맞추는 동안 원본에 새로 생긴 파일은 지우지 않는다', () async {
|
||||
|
|
|
|||
Loading…
Reference in New Issue