WIP 압축 펼치기: 펼친 뒤 압축 파일이 바뀌면 (크기 · 바뀐 때) 펼치거나 새로 고칠 때 목록을 다시 읽음 (검토 대기)
관리자 지시 (10/19, 사용자 "오늘 못했던 것 진행" 1번 - 압축 펼치기의 알려진 한계): 읽어 둔 압축 목록을 계속 써서, 다른 프로그램이 압축을 바꿔도 접었다 펼치거나 새로 고쳐도 예전 목록이 보였다. - 압축을 읽을 때의 (크기, 바뀐 때) 를 기억하고, 다시 펼칠 때 · 새로 고침 (F5 · [새로 고침] · 앱으로 돌아옴) 때 비교해 다르면 그 압축의 목록과 모든 창의 그 안 폴더 목록을 잊고 다시 읽는다. - 압축이 없어졌으면 목록을 잊고 그 안은 빈 목록으로 (예전 것을 보이지 않게). 시험: explorer_test (새 1: 펼친 뒤 압축을 바꾸고 F5 → 새 항목 · 예전 항목 없음) 62 통과, 임시 폴더 흔적 0 (tool/test_temp_check.ps1), analyze 문제 없음. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>next2
parent
a74e7be59b
commit
53f5c432bb
|
|
@ -908,12 +908,20 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
|
||||
Future<void> _load(_Pane pane, String dir, {bool force = false}) async {
|
||||
if (!force && pane.cache.containsKey(dir)) return;
|
||||
// X-plore 비교 f: 압축 안 (읽어 둔 목록에서)
|
||||
if (_archiveOf(dir) != null) {
|
||||
// X-plore 비교 f: 압축 안 (읽어 둔 목록에서). 새로 고침이면 압축 파일이 바뀌었는지 보고 바뀌었으면 다시 읽는다
|
||||
final arc = _archiveOf(dir);
|
||||
if (arc != null) {
|
||||
if (force && !await _readArchive(arc)) {
|
||||
pane.cache[dir] = const [];
|
||||
pane.changed();
|
||||
return;
|
||||
}
|
||||
if (_archives.containsKey(arc)) {
|
||||
pane.cache[dir] = _sorted(_archiveList(dir), dir);
|
||||
pane.changed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 80: 다시 읽는 폴더는 안이 바뀌었을 수 있다 - 그 폴더와 위 폴더들의 크기를 잊는다
|
||||
if (force) _sizes.forget(dir);
|
||||
pane.loading.add(dir);
|
||||
|
|
@ -2173,6 +2181,28 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
/// 펼쳐 본 압축의 목록 (압축 경로 → 항목)
|
||||
final _archives = <String, List<ArchiveEntry>>{};
|
||||
|
||||
/// 압축을 읽은 때의 (크기, 바뀐 때) - 바뀌었으면 다음에 펼치거나 새로 고칠 때 다시 읽는다 (관리자 지시 10/19)
|
||||
final _archiveStamps = <String, (int, DateTime)>{};
|
||||
|
||||
static Future<(int, DateTime)?> _stampOf(String path) async {
|
||||
try {
|
||||
final st = await File(path).stat();
|
||||
if (st.type == FileSystemEntityType.notFound) return null;
|
||||
return (st.size, st.modified);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// [arc] 의 읽어 둔 목록과 창들의 그 안 목록을 잊는다 (다시 읽게)
|
||||
void _forgetArchive(String arc) {
|
||||
_archives.remove(arc);
|
||||
_archiveStamps.remove(arc);
|
||||
for (final q in _panes) {
|
||||
q.cache.removeWhere((k, _) => samePath(k, arc) || isSameOrInside(k, arc));
|
||||
}
|
||||
}
|
||||
|
||||
/// 트리에서 펼칠 수 있는 압축 (이 기기의 파일 · 탐색기 화면)
|
||||
bool _canBrowseArchive(FileEntry e) => !widget.rsync && !e.isDir && !isDav(e.path) && archiveKindOf(e.path) != null;
|
||||
|
||||
|
|
@ -2196,7 +2226,13 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
|
||||
/// 압축의 목록을 읽어 둔다 (비밀번호가 걸린 7z 등은 [압축 풀기] 로 안내). 읽었으면 true
|
||||
Future<bool> _readArchive(String path) async {
|
||||
if (_archives.containsKey(path)) return true;
|
||||
final stamp = await _stampOf(path);
|
||||
if (_archives.containsKey(path)) {
|
||||
// 펼친 뒤 압축 파일이 바뀌었으면 (크기 · 바뀐 때) 다시 읽는다. 없어졌으면 잊는다
|
||||
if (stamp != null && stamp == _archiveStamps[path]) return true;
|
||||
_forgetArchive(path);
|
||||
if (stamp == null) return false;
|
||||
}
|
||||
final kind = archiveKindOf(path)!;
|
||||
try {
|
||||
if (kind == ArchiveKind.zip) {
|
||||
|
|
@ -2209,6 +2245,7 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
}
|
||||
_archives[path] = await list7z(exe, path);
|
||||
}
|
||||
if (stamp != null) _archiveStamps[path] = stamp;
|
||||
return true;
|
||||
} on ArchivePasswordException {
|
||||
_snack(tr('비밀번호가 걸린 압축은 안을 미리 볼 수 없습니다 - [압축 풀기] 로 푸세요'));
|
||||
|
|
|
|||
|
|
@ -358,6 +358,28 @@ void main() {
|
|||
await calm(tester);
|
||||
});
|
||||
|
||||
testWidgets('X-plore f 보충: 펼친 뒤 압축 파일이 바뀌면 새로 고칠 때 목록을 다시 읽는다 (관리자 지시 10/19)', (tester) async {
|
||||
final zip = p.join(left, 'pack.zip');
|
||||
File(zip).writeAsBytesSync(ZipEncoder().encode(Archive()..addFile(ArchiveFile.string('old.txt', 'old'))));
|
||||
await open(tester);
|
||||
await settle(tester, () => find.text('pack.zip').evaluate().isNotEmpty);
|
||||
await act(tester, () => tester.tap(chevronOf('pack.zip').first));
|
||||
await settle(tester, () => find.text('old.txt').evaluate().isNotEmpty);
|
||||
expect(find.text('old.txt'), findsOneWidget);
|
||||
// 다른 프로그램이 압축을 바꿈 (크기 · 바뀐 때가 달라짐)
|
||||
await tester.runAsync(() async {
|
||||
await Future<void>.delayed(const Duration(milliseconds: 1100));
|
||||
File(zip).writeAsBytesSync(ZipEncoder().encode(Archive()
|
||||
..addFile(ArchiveFile.string('new.txt', 'new content'))
|
||||
..addFile(ArchiveFile.string('more.txt', 'more'))));
|
||||
});
|
||||
await act(tester, () => tester.sendKeyEvent(LogicalKeyboardKey.f5));
|
||||
await settle(tester, () => find.text('new.txt').evaluate().isNotEmpty);
|
||||
expect(find.text('new.txt'), findsOneWidget);
|
||||
expect(find.text('more.txt'), findsOneWidget);
|
||||
expect(find.text('old.txt'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('X-plore g · h: 폴더 메뉴 [격자로 보기] (길게 = 그 자리로) · 파일 메뉴 [글 뷰어로 보기]', (tester) async {
|
||||
File(p.join(left, 'sub', 'pic.png')).writeAsBytesSync([0x89, 0x50]);
|
||||
await open(tester);
|
||||
|
|
|
|||
Loading…
Reference in New Issue