WIP 압축 안 메뉴 정리: 펼친 압축 안의 것에는 [ZIP 으로 묶기] · [Wi-Fi 로 공유] · [PDF 로 만들기] 를 숨김 (검토 대기)

관리자 지시 (10/18, 데이터 검토에서 찾은 것): 펼친 압축 안의 항목은 실제 파일이 아니라 위 셋을 눌러도 없는 경로라 오류만 났다 (데이터는 다치지 않음).
→ 누른 것이나 표시한 것 중 하나라도 압축 안이면 그 셋을 메뉴에서 뺀다. 압축 밖은 그대로.

시험: explorer_test X-plore 16 통과 (f 에 덧붙임: 압축 안 폴더 메뉴에 ZIP · Wi-Fi 없음 · 밖의 폴더에는 ZIP 있음), analyze 문제 없음.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_fix
RyuJongJin 2026-10-18 04:47:12 +09:00
parent 50bd2bf259
commit 29b4365b74
2 changed files with 17 additions and 3 deletions

View File

@ -1910,6 +1910,8 @@ class _ExplorerPageState extends State<ExplorerPage> {
// 77: 누른 것이 표시한 것 중 하나면 표시한 것 모두에 (복사 · 이동 · 삭제 · 공유 · 경로 복사) // 77: 누른 것이 표시한 것 중 하나면 표시한 것 모두에 (복사 · 이동 · 삭제 · 공유 · 경로 복사)
final targets = _isMarked(pane, e.path) && pane.marked.length > 1 ? pane.marked.toList() : [e.path]; final targets = _isMarked(pane, e.path) && pane.marked.length > 1 ? pane.marked.toList() : [e.path];
final many = targets.length > 1; final many = targets.length > 1;
// 데이터 검토 (10/18): 펼친 압축 안의 것은 실제 파일이 아니다 - 그것으로 새 파일을 만들거나 내놓는 항목 (ZIP 묶기 · Wi-Fi 공유 · PDF) 은 숨긴다
final inArchive = targets.any(_insideArchive) || _insideArchive(e.path);
// 25: Rsync 화면은 폴더만 보이므로 폴더에 맞는 것만 (고르기 · 열기 · 이름 변경 · 삭제 · 정보) // 25: Rsync 화면은 폴더만 보이므로 폴더에 맞는 것만 (고르기 · 열기 · 이름 변경 · 삭제 · 정보)
final items = widget.rsync final items = widget.rsync
? <(String, IconData, String)>[ ? <(String, IconData, String)>[
@ -1931,11 +1933,11 @@ class _ExplorerPageState extends State<ExplorerPage> {
if (!e.isDir) ('quickLook', Icons.preview_outlined, tr('미리 보기')), if (!e.isDir) ('quickLook', Icons.preview_outlined, tr('미리 보기')),
// 86: 압축 풀기 (ZIP · 7z · RAR) · ZIP 으로 묶기 (표시한 것 모두) // 86: 압축 풀기 (ZIP · 7z · RAR) · ZIP 으로 묶기 (표시한 것 모두)
if (!e.isDir && archiveKindOf(e.path) != null) ('extract', Icons.unarchive_outlined, tr('압축 풀기')), if (!e.isDir && archiveKindOf(e.path) != null) ('extract', Icons.unarchive_outlined, tr('압축 풀기')),
if (!dav) ('zip', Icons.archive_outlined, many ? trf('{0}개 ZIP 으로 묶기', [targets.length]) : tr('ZIP 으로 묶기')), if (!dav && !inArchive) ('zip', Icons.archive_outlined, many ? trf('{0}개 ZIP 으로 묶기', [targets.length]) : tr('ZIP 으로 묶기')),
// 87: 저장 공간 분석 (이 폴더 아래의 큰 폴더 · 큰 파일) // 87: 저장 공간 분석 (이 폴더 아래의 큰 폴더 · 큰 파일)
if (e.isDir) ('storage', Icons.pie_chart_outline, tr('저장 공간 분석')), if (e.isDir) ('storage', Icons.pie_chart_outline, tr('저장 공간 분석')),
// 89: 이 폴더를 Wi-Fi 로 공유 (이 기기의 폴더만) // 89: 이 폴더를 Wi-Fi 로 공유 (이 기기의 폴더만)
if (e.isDir && !dav && !widget.rsync) ('wifiShare', Icons.wifi_tethering, tr('Wi-Fi 로 공유')), if (e.isDir && !dav && !widget.rsync && !inArchive) ('wifiShare', Icons.wifi_tethering, tr('Wi-Fi 로 공유')),
// 80: 이 폴더 크기를 지금 계산 (설정이 "안 함" 이어도) // 80: 이 폴더 크기를 지금 계산 (설정이 "안 함" 이어도)
if (e.isDir) ('folderSize', Icons.data_usage, _sizes.busy(e.path) ? tr('폴더 크기 계산 멈추기') : tr('폴더 크기 계산')), if (e.isDir) ('folderSize', Icons.data_usage, _sizes.busy(e.path) ? tr('폴더 크기 계산 멈추기') : tr('폴더 크기 계산')),
// X-plore P3: 폴더 속성 (안의 파일 · 폴더 수 · 크기 · 만든 · 바뀐 때) · 파일 해시 (MD5 · SHA-256) - 이 기기의 것만 (원격은 다 받아야 해서 뺌) // X-plore P3: 폴더 속성 (안의 파일 · 폴더 수 · 크기 · 만든 · 바뀐 때) · 파일 해시 (MD5 · SHA-256) - 이 기기의 것만 (원격은 다 받아야 해서 뺌)
@ -1952,7 +1954,7 @@ class _ExplorerPageState extends State<ExplorerPage> {
if (!e.isDir) ('openWith', Icons.open_in_new, tr('다른 앱으로 열기')), if (!e.isDir) ('openWith', Icons.open_in_new, tr('다른 앱으로 열기')),
if (!e.isDir && !video) ('openDefault', Icons.launch, tr('기본 앱으로 열기')), if (!e.isDir && !video) ('openDefault', Icons.launch, tr('기본 앱으로 열기')),
if (video && !dav) ('addMkv', Icons.playlist_add, tr('MKV 목록에 추가')), if (video && !dav) ('addMkv', Icons.playlist_add, tr('MKV 목록에 추가')),
if (viewer && images.isNotEmpty) if (viewer && images.isNotEmpty && !inArchive)
('toPdf', Icons.picture_as_pdf_outlined, ('toPdf', Icons.picture_as_pdf_outlined,
images.length == 1 ? tr('PDF 로 만들기') : trf('그림 {0}장을 PDF 로 만들기', [images.length])), images.length == 1 ? tr('PDF 로 만들기') : trf('그림 {0}장을 PDF 로 만들기', [images.length])),
('select', Icons.check_circle_outline, tr('선택')), ('select', Icons.check_circle_outline, tr('선택')),

View File

@ -344,6 +344,18 @@ void main() {
expect(find.byType(TextField), findsNothing, reason: '이름 묻는 창 없음'); expect(find.byType(TextField), findsNothing, reason: '이름 묻는 창 없음');
ScaffoldMessenger.of(tester.element(find.byType(ExplorerPage))).clearSnackBars(); ScaffoldMessenger.of(tester.element(find.byType(ExplorerPage))).clearSnackBars();
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
// 데이터 검토 (10/18): 압축 안의 것 메뉴에는 [ZIP 으로 묶기] · [Wi-Fi 로 공유] 가 없다 (실제 파일이 아니라서). 압축 밖은 그대로
await tester.longPress(find.text('a'));
await calm(tester);
expect(find.text('ZIP 으로 묶기'), findsNothing);
expect(find.text('Wi-Fi 로 공유'), findsNothing);
await tester.tapAt(const Offset(5, 5));
await calm(tester);
await tester.longPress(find.text('sub'));
await calm(tester);
expect(find.text('ZIP 으로 묶기'), findsOneWidget);
await tester.tapAt(const Offset(5, 5));
await calm(tester);
}); });
testWidgets('X-plore g · h: 폴더 메뉴 [격자로 보기] (길게 = 그 자리로) · 파일 메뉴 [글 뷰어로 보기]', (tester) async { testWidgets('X-plore g · h: 폴더 메뉴 [격자로 보기] (길게 = 그 자리로) · 파일 메뉴 [글 뷰어로 보기]', (tester) async {