69 lines
2.6 KiB
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]);
|
|
}));
|
|
}
|
|
}
|