JJ_MKVMaker/lib/ui/explorer/explorer_jobs.dart

69 lines
2.6 KiB
Dart

import 'dart:async';
import 'package:flutter/foundation.dart';
import '../../app/transfer_job.dart';
import '../../core/file_ops.dart' show samePath;
import '../../core/vfs.dart' show vBasename, vDirname, vExists, vJoin;
import 'explorer_controller.dart';
/// 약속 (E5d-5): 지금 도는 복사 · 이동 · rsync 작업 (아래에서 올라오는 진행 패널의 목록). 23: 여럿이 함께 돈다.
/// 끝난 것은 진행 막대가 잠깐 100% 를 보인 뒤 ([dropDelay]) 목록에서 내려간다. 바뀌면 알림
class ExplorerJobs extends ChangeNotifier {
ExplorerJobs(this.ctl);
final ExplorerController ctl;
static const dropDelay = Duration(milliseconds: 1200);
List<TransferJob> list = const [];
bool get isEmpty => list.isEmpty;
/// 새 작업을 목록에 (끝난 것은 이때 뺀다)
void start(TransferJob job) {
list = [...list.where((j) => !j.finished), job];
notifyListeners();
}
/// 같은 것을 같은 곳으로 복사 · 이동하는 중인지 (그것만 막는다)
bool busyWith(List<String> sources, String dest) =>
list.any((j) => !j.finished && samePath(j.dest, dest) && j.sources.toSet().containsAll(sources));
/// [jobs] 를 잠깐 뒤 목록에서 뺀다
Future<void> dropLater(Iterable<TransferJob> jobs) async {
await Future<void>.delayed(dropDelay);
if (!ctl.host.alive || !list.any(jobs.contains)) return;
list = [for (final j in list) if (!jobs.contains(j)) j];
notifyListeners();
}
/// X-plore 숨기기: 옮긴 것은 숨긴 목록도 새 자리로 (원래 자리에 없고 새 자리에 있는 것만 - 같은 이름 바꾸기 · 실패는 그대로)
Future<void> followMoved(TransferJob job) async {
if (!job.move || job.contents || ctl.c.settings.explorer.hiddenItems.isEmpty) return;
final moved = <(String, String)>[];
for (final s in job.sources) {
final to = vJoin(job.dest, vBasename(s));
if (!await vExists(s) && await vExists(to)) moved.add((s, to));
}
await ctl.followHidden(moved: moved);
}
/// 52: 이 화면을 떠난 사이에 시작된 (또는 앞의 화면이 시작한) 작업을 다시 보이고, 끝나면 새로 읽고 막대를 내린다
void adopt(TransferJob job) {
if (list.contains(job)) return;
list = [...list, job];
notifyListeners();
unawaited(job.done.then((_) async {
if (!ctl.host.alive) return;
await followMoved(job);
if (!ctl.host.alive) return;
await ctl.refreshAll([job.dest, ...job.sources.map(vDirname)]);
for (final x in ctl.panes) {
x.changed();
}
await dropLater([job]);
}));
}
}