JJ_MKVMaker/lib/ui/explorer/write_guard.dart

57 lines
3.3 KiB
Dart

import 'package:flutter/widgets.dart';
import '../../app/archive_browse.dart' show ArchiveRead;
import '../../core/file_ops.dart' show samePath;
import '../../core/shizuku.dart' show isRootPath, isShizuku;
import '../../l10n/tr.dart';
import '../archive_ui.dart' show extractArchiveFlow;
import 'explorer_controller.dart';
/// 약속 (E5d-5): 읽기 전용인 곳 (펼친 압축 안 · 시스템 폴더 Shizuku · 루트) 을 바꾸려는 일을 막고 까닭을 알린다 (Host).
/// 막았으면 true. 압축 안의 것은 꺼내기만 ([extractOne] · [extractFrom] - 86 의 풀기 창 그대로)
class ExplorerGuard {
ExplorerGuard(this.ctl);
final ExplorerController ctl;
bool insideArchive(String path) => ctl.arc.inside(path);
/// 압축 안을 바꾸려 하면 막고 알린다 (읽기 전용). [self] 면 압축 파일 자신도 (그 안으로 넣는 곳일 때)
bool blockArchive(List<String> paths, {bool self = false}) {
// X-plore 비교 5-2: 시스템 폴더 (Shizuku) 도 읽기 전용 - 쓰기 · 지우기 · 이름 바꾸기 · 옮기기 · 새 폴더 · 넣기를 막는다 (꺼내기만)
if (paths.any(isShizuku)) {
ctl.host.snack(paths.any(isRootPath)
? tr('루트 폴더는 읽기 전용입니다 (꺼내기 (복사) 만 할 수 있습니다)')
: tr('시스템 폴더 (Shizuku) 는 읽기 전용입니다 (꺼내기 (복사) 만 할 수 있습니다)'));
return true;
}
if (!paths.any((x) => insideArchive(x) || (self && ctl.arc.contains(x)))) return false;
ctl.host.snack(tr('압축 안은 읽기 전용입니다 (꺼내기만 할 수 있습니다)'));
return true;
}
/// 관리자 지시 (10/21, 28 지적): 시스템 폴더 · 루트 (shz://) 가 원본이나 받는 곳인 이동은 시작하지 않는다 -
/// 복사는 되고 원본 지우기에서 오류로 끝나던 것 (끌어 놓기 · 붙여넣기 · 버튼 · 메뉴 모두 여기를 지남)
bool blockShizukuMove(List<String> sources, String? dest, {required bool move}) {
if (!move || !(sources.any(isShizuku) || (dest != null && isShizuku(dest)))) return false;
ctl.host.snack(tr('읽기 전용이라 옮길 수 없습니다 - 복사를 쓰세요'));
return true;
}
/// 압축 안의 파일 하나를 임시 폴더로 꺼낸다 (보기 · 재생). 꺼낸 경로 (못 하면 null - 까닭을 알림)
Future<String?> extractOne(String path) async {
final (out, why) = await ctl.arc.extractOne(path, await ctl.c.services.storage.tempDirectory());
if (why == ArchiveRead.password) ctl.host.snack(tr('비밀번호가 걸린 파일입니다 - [압축 풀기] 로 푸세요'));
if (why == ArchiveRead.failed) ctl.host.snack(trf('압축에서 꺼내지 못했습니다: {0}', [ctl.arc.lastError]));
return out;
}
/// 압축 안의 것을 꺼내기 - 86 의 풀기 창 (검사 · 갈 곳 · 같은 이름) 그대로. 꺼낸 폴더를 다시 읽는다
Future<void> extractFrom(BuildContext context, List<String> paths, String? otherDir) async {
final arc = ctl.arc.archiveOf(paths.firstWhere(insideArchive))!;
final names = [for (final x in paths) if (insideArchive(x) && samePath(ctl.arc.archiveOf(x)!, arc)) ctl.arc.innerName(arc, x)];
final done = await extractArchiveFlow(context, ctl.c, arc, otherDir: otherDir, names: names);
if (done != null && ctl.host.alive) await ctl.refreshAll([done]);
}
}