- recycle_bin: RecycleBinBackend 약속 + WindowsRecycleBin (이 기기의 휴지통). 전역 recycleBinForTest · recycle() · restoreRecycled() 없앰
- delete_ops: deletePaths(bin:) · undoRecycle(bin:) - 처음 값 WindowsRecycleBin
- ExplorerDevice.recycleBin → ExplorerFlows · ExplorerDeleteFlow(recycleBin:)
- 시험: useTestRecycleBin(device) 가 시험 기기에 시험 폴더 안의 휴지통을 넣음. 영구 삭제만 하는 약속 시험 4개는
휴지통으로 보내면 실패하는 것을 넘김 (사용자 휴지통에 닿지 않게). 넘겨받은 휴지통 약속 시험 1개 더함
- 시험용 휴지통: 자기 폴더가 없어졌으면 다시 만들지 않고 그대로 알림 (진단)
- 전부터 있던 실패 2개 고침 (E6 부터 Windows 처음 모양이 Total Commander 라 이름 · 확장자가 다른 칸):
windows_check_shot_test · windows_b3_shot_test 가 X-plore 모양을 직접 고름
확인: analyze 0 · 단위 1472 ×2 · 통합 6/6 ×2 · base10 214장 0px · windows_check_shot ×2 · windows_b3_shot ×2
(첫 확인의 통합 1회에서 412 지우기가 '경로를 찾을 수 없음' 으로 11장 벗어남 - 다시 4회 모두 0px, 원인 미확인)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- lib/app/local_fs.dart: LocalFs 약속 (list · volumes · probe), RealLocalFs = 이 기기 그대로
- ExplorerDevice.listVolumes/probeDrive → ExplorerDevice.fs (LocalFs)
- ExplorerController(fs:) → loadDir(list:) (처음 값 listEntries)
- 빈 목록 경합: reloadOpen 이 끝날 때, 시작할 때 읽어 둔 것 중 닫힌 것만 잊음
(예전: 시작할 때 찍은 열린 목록으로 지워, 다시 읽는 동안 펼친 폴더가 비어 보였다)
- 결정적 시험 explorer_reload_race_test: 다시 읽기를 붙잡는 느린 LocalFs 를 생성자로 넘김
(실제 폴더 · 실제 목록). 예전 판에서는 실패 (펼친 폴더 [] ), 고친 판에서는 통과
확인: analyze 0 · 단위 1471 ×2 · 통합 6/6 ×2 · base10 214장 0px
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- MemorySecretStore.failRead/failWrite 를 없앰 → 시험 쪽 test/support/flaky_secret_store.dart
- WebProxy.debugAndroid/debugSetProxy 를 없앰 → WebViewProxyTarget 주입 (Android=ProxyController, 그 밖=없음)
- ExitGuard.forceAndroid 를 없앰 → PlatformServices.platform (PlatformInfo)
- JJ_NLLB_LOW_MEMORY 환경 변수를 없앰 → NllbTranslator(lowMemory:), 처음 값은 PlatformInfo.host
- archive_ops · rsync_launch · file_error 의 기본값을 PlatformInfo.host 로 모음
- 이름 바꿈: WebProxy.shownForTest → shown, debugReset → reset
- 보안: 남은 Tor 웹 뷰가 있는 동안에도 removeImplicitRules (localhost 까지 Tor 로)
- 약속 시험 platform_info_contract_test 3개
확인: analyze 0 · 단위 1470 ×2 · 통합 6/6 ×2 · base10 214장 0px
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- TC 모양: 트리 대신 지금 폴더의 목록 (paneListRows - '폴더 + 파일 목록' 의 목록과 같은 함수, 목록의 스크롤).
사용자가 고른 '폴더 + 파일 목록' 배치 · Rsync 화면은 그대로 트리
- tc_key_bar: F3 보기 · F4 편집 · F5 복사 · F6 이동 · F7 새 폴더 · F8 삭제 - 이미 있는 동작을 부름
- tc_drive_space: 창 위 남은 공간 / 전체 - ExplorerDevice.diskSpace 로 받음 (시험은 TestExplorerDevice.space)
- 좁은 창 (창 폭 200 아래, narrowRowWidth): 아이콘 칸 줄임 · 끌기 손잡이 숨김 · 열 대신 이름 먼저 (크기 · 날짜는
두 줄이 들어가는 줄 높이에서 이름 아래 - TC 26 은 이름만) · 열 머리도 이름만. X-plore · TC 가 같은 ExplorerRowView
- 약속 시험 explorer_tc_look_test 4개. 점검 시험은 X-plore · TC 두 모양을 찍는다 (폴더 시각 · 남은 공간 고정)
- 확인: 단위 1456 ×2 · 통합 6/6 ×2 · 캡처 180장 2회 정확히 같음 (base8) · X-plore 1920 · 960 은 base7 과 같음
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ExplorerSettings: 처음 값 defaultStyle (Windows totalcmd · Android xplore). 예전 파일에 모양 키가 없으면 그때의 X-plore.
Windows 에서 저장된 xplore 이고 물었다는 표시 (explorerStyleV2) 가 없으면 styleAskPending (저장 안 함)
- style_ask: 탐색기를 열 때 한 번 [바꾸기] (Total Commander) / [그대로] (X-plore) - 창 밖으로 닫지 못함, 어느 쪽이든 다시 묻지 않음.
환경 설정에서 직접 고르면 묻지 않음
- 약속 시험 explorer_style_contract_test: 새 설치 · 저장된 xplore (키 없던 예전 파일 포함) · windows/totalcmd 안 물음 · [그대로] · [바꾸기]
- X-plore 모양 (트리) 을 보는 기존 시험 14개 파일 + 공용 하네스에 style = 'xplore' 를 밝힘 (기대값 그대로, 관리자 승인 10/23)
- 설정 JSON 골든: 새 키 explorerStyleV2 한 줄 · 처음 값 출력의 Windows 모양 totalcmd 만 바꿈. 사전 4개 (en · ja · zh-Hans)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- lib/app/settings/explorer_settings.dart: 탐색기 설정의 이름 · 처음 값 · 읽기 · 쓰기를 한 곳에
- AppSettings 는 explorer 분야를 갖고 분야 목록을 돌며 합치기만 (toJson · fromJson 에서 탐색기 키를 지움)
- 부르는 곳: s.explorerLayout → s.explorer.layout 꼴 (옛 이름 getter 없음), 저장 키 이름은 그대로
- 고침: fromJson 이 바뀐 기본값 알림 (_migrated) 을 분야를 읽기 전에 계산하던 것 - 분야를 먼저 읽음
- JSON 약속 시험: 알림 목록 (__migrated) · 옛 판 설정 경우를 더함, 기준은 옛 판 (db45f80) 에서 다시 만듦
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
점검 (wiki 파일 탐색기 사용 점검 10-22) U1 · U2 · U4 · U5 · U7 · U8, 관리자 승인 10/22
- U2: lib/ui/notice.dart showNotice - 단추가 있는 알림은 앱 전체 한 값 noticeDuration (10초) 뒤 저절로 닫힘, 모두 ✕.
단추 있는 SnackBar 13곳을 모두 옮김. 사용자가 닫을 때까지 두는 것은 248 DNS · 198 감지한 언어, 부르는 쪽이 닫는 것은
AI 시작 전 [취소] · 다운로드 준비 (untilClosed)
- U7: lib/ui/confirm_dialog.dart confirmDialog - [확인] 만 true · Enter = 첫 초점, 되돌릴 수 없는 일 (영구 삭제 · 늘 덮어쓰기)
은 첫 초점 [취소] (관리자 결정). 탐색기 지우기 · 영구 삭제 2곳 · 복사 · 이동 · 같은 폴더를 옮김 (나머지는 W)
- U4: 복사 · 이동 · 지우기 확인 창에 "다른 창에 N개 표시됨 (이번 대상 아님)" - 다른 창 표시는 그대로 (관리자 결정)
- U1: 저장된 경로가 없을 때만 오른쪽 창은 두 번째 저장 장치
- U5: 지금 줄은 진한 바탕 + 왼쪽 강조 막대
- U8: rc2 e785ba9 (TailText) 로 이미 됨 - 412 캡처로 확인
- 폰 세로 두 창 (E3 규칙 7) 넘침 2곳: 아래 표시 줄은 공용 lib/ui/adaptive_row.dart AdaptiveRow (좁으면 두 줄),
진행 패널 이름 칸은 min(300, 폭 45%). 넓은 화면은 그대로
- explorer_page 는 시각을 생성자로 받음 (clock, 처음 값 DateTime.now) - 폴더 두 번 누르기 판단을 시험이 정한 시각으로
- 600줄 규칙: NameClash · clashCompareText · fileDateText 를 lib/core/name_clash.dart 로 (explorer_page 6,605 → 6,590),
시험 도우미 testNow · refreshKey 를 test/support/explorer_clock_keys.dart 로 (explorer_test 2,011 → 2,009)
기대값을 바꾼 시험 (근거):
- browser_test 실행 취소 알림 5초 → noticeDuration: 5초는 정해진 값이 아님. 10/5 967b729 (HANDOFF 12) 가 정한 것은
"버튼 달린 알림은 저절로 사라짐" 이고 앱은 시간을 정하지 않아 Flutter 기본 4초였다. 성질은 지키고 시간은 관리자가
승인한 앱 전체 한 값 (U2)
- explorer_test "두 창: …" 다시 눌러도 접지 않음 (189) → 다시 누르면 접힘: 선택 규칙 노트 규칙 3 "폴더 한 번 누르기 =
펼치기 · 접기" (노트 머리: 관리자 판단과 다르면 이 노트를 따름) · E3 승인. E3 에서는 두 번째 누르기가 600ms 안에
들어와 우연히 통과했었음 → 시각 주입 (testNow) 으로 고침
확인: analyze 0 · 전체 단위 2회 통과 1,306 · 건너뜀 17 (E4 실패 0) · 점검 통합 시험 (1920 · 960 · 412) 2회 통과,
넘침 0, 두 회 파일 결과 같음. 약속 시험 notice 4 · confirm 3 (지문 notice.dart 29b3c951 · confirm_dialog.dart ff964f5f)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
관리자 지시 (10/20, 데이터 쪽): 예전에는 이 규칙들을 "미리 볼 수 없음" 으로 두고 경고만 했다. 이제 rsync (man rsync FILTER RULES ·
exclude.c) 와 같게:
- 규칙마다 걸리는 쪽 (RuleSide): 그냥 + · - 는 양쪽, H (hide) = -,s · S (show) = +,s 는 보내는 쪽 (보낼 것 고르기) 에만,
P (protect) = -,r · R (risk) = +,r 은 받는 쪽 (지울 것 고르기) 에만. ",sr" 은 양쪽. 긴 이름 (hide · show · protect · risk) 도.
- 쪽마다 그 쪽에 걸리는 규칙만 위에서부터 보고 처음 맞는 것이 이긴다 (RsyncFilter.excluded = 보내는 쪽, protects = 받는 쪽).
- --delete-excluded 면 쪽을 적지 않은 규칙은 보내는 쪽에만 (rsync 와 같음 - 예전 동작과도 같은 결과).
- 지울 때 (previewSync · _mirrorV · 실시간 동기화 diff/_gone) 는 "거른 것 · --delete-excluded 아님" 대신 protects 로 지킨다:
보내는 쪽에서만 거른 것 (H · -,s) 은 보내지 않았으므로 --delete 면 지운다 (28 의 a.txt 와 같은 일을 이제 미리 보기가 보임).
- 그 밖의 고치개 (,! · ,p · ,x · ,e 등) · H/S/P/R 에 붙은 고치개 · merge · "!" · exclude-from 파일 안의 규칙 머리는 그대로 미리 볼 수 없음.
기준 시험 rsync_phsr_test: 규칙 장면 31개 (양쪽에 같은 이름이 많은 장면) 마다 실제 rsync 를 돌린 (-n 아님) 결과 트리와
① 미리 보기로 예측한 트리 ② 원격 맞추기 (WebDAV) ③ 실시간 동기화 로컬 쌍 (묻는 목록 = rsync 가 지운 것 · 맞춘 뒤 맞출 것 없음)
④ 실시간 동기화 WebDAV 쌍 - 모두 같음. protects 를 예전처럼 (쪽 무시) 바꾸면 25개 장면이 다르게 나오는 것도 확인 (시험이 잡음).
바꾼 시험: rsync_filter_test (이 규칙들은 미리 볼 수 있음 · 15 재현은 이제 미리 보기도 a.txt 지움), P0 시험 · 경고 창 시험 ·
P0 캡처는 아직 따르지 못하는 merge 규칙 (파일 안에 "H a.txt") 으로, P 는 이제 따르므로 "묻는 목록에 지킨 것 없음" 으로.
smb_test 의 28 장면 시험에 5분 (여러 시험을 함께 돌리면 기본 30초를 넘음).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
관리자 지시 (10/20) 2번 - 위키 974 목록 8 "원격 동기화도 거르기를 따름" 의 📱 ⏸ 가운데 기기 없이 할 수 있는 것:
28 이 손으로 한 WebDAV 21 장면 비교를 시험으로 남기고 (시험 WebDAV 서버), SMB 는 가짜 채널로 같은 28개.
네 원격 (WebDAV · SFTP · FTP · SMB) 모두 결과 트리 (폴더 · 파일 · 글) 가 실제 rsync 와 같음 - 코드 변경 없음.
rsync_scenes 의 bundledRsync 를 sceneRsync 로 (live_sync.dart 의 같은 이름과 겹침).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
관리자 지시 (10/20): 28 이 WebDAV 로 비교한 장면 · 옵션 (rsync_filter_test 의 "28 의 장면" 27개 + 지우기 없는 거르기 1개) 을
SFTP (paramiko) · FTP (pyftpdlib) 시험 서버로. 같은 장면을 로컬에서 실제 rsync (앱에 든 rsync.exe) 로 맞춘 결과 트리와
원격 맞추기 (FileOps.mirror + 옵션의 지우기 · 거르기) 뒤 서버 폴더의 트리 (폴더 · 파일 · 글) 를 비교. 28개 모두 같음 - 코드 변경 없음.
거르기를 빼고 돌리면 다른 점 423줄로 실패하는 것도 확인 (시험이 실제로 잡는지).
장면 · 비교 도구는 test/support/rsync_scenes.dart 로 (다른 원격 시험도 쓰게).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
관리자 지적 (10/18): "처음 연결: 지문 안내 → … → 지문은 설정에 저장" 이 전체 시험 (wt_mgr 00e9685) 에서만 실패.
시험 서버 (paramiko) 는 PORT 를 찍기 전에 listen 하므로, 무거울 때 걸리는 것은 settle 의 횟수 (300번 ≈ 10~15초) 였다 - 키 교환이 그보다 오래 걸림.
- settle: 횟수 대신 실제 시간 (처음 90초) 까지 조건을 기다린다.
- SftpTestServer.start: PORT · FINGERPRINT 줄을 기다리는 시간을 정하고 (60 · 30초, 서버가 죽으면 끝없이 기다리지 않게), 포트가 연결을 받는 것을 본 뒤 돌려준다.
시험: sftp_explorer · sftp_stream · sftp_test 10 통과.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 환경 설정 > 파일 탐색기 > SFTP (lib/ui/sftp_settings.dart): 추가 · 고치기 · 지우기 (쓰는 곳 알림), 서버 주소 · 포트 · 아이디 ·
비밀번호 · 개인 키 파일 고르기 (내용만 안전 저장소에, 원래 경로는 저장하지 않음) · 키 암호 · 시작 폴더 · 오래된 ssh-rsa 허용,
[연결 확인] 에서 처음 보는 키는 지문을 보이고 [믿고 연결], 믿은 키 보기 · [믿은 키 지우기] (마스터 비밀번호 뒤).
- 파일 탐색기 · Rsync 화면: SFTP 서버 탭 (🔑), 탭 길게 누르기 = 고치기, 끝 버튼에 [SFTP 서버 추가] (좁으면 ⋮ 메뉴에).
처음 연결: 목록 대신 "처음 연결하는 서버입니다 · 지문" 안내와 [지문 확인하고 연결] → 확인 창 [믿고 연결] → 지문을 설정에 저장하고 읽음.
바뀐 키: 막고 예전 · 지금 지문, [서버 설정 고치기]. 경로 복사는 sftp://아이디@서버:포트/경로 (비밀번호 없음).
- 실시간 동기화 · 모니터링의 폴더 고르기에 SFTP 서버도. 화면 경로 "🔑 서버 › 폴더".
- WebDAV 에만 맞던 글 6개를 "WebDAV · SFTP" 로 (풀기 · ZIP · 분석 · MKV 목록 · Rsync 안내 · 빠른 보기). 탐색기 ⋮ 이름 "경로 입력 · 네트워크 서버".
- 파일 고르기: 확장자 목록이 비면 모든 파일 (확장자가 없는 개인 키 파일 - Windows · Android).
- 라이선스: dartssh2 4.1.0 (MIT) 를 두 고지에 (pointycastle · pinenacl · asn1lib 원문은 패키지 라이선스 화면), 판이 바뀌면 시험이 알림.
- 번역 en · ja · zh-Hans (빠진 번역 0).
- 시험: sftp_explorer_test (시험 서버로 처음 연결 → 지문 → 믿고 연결 → 목록 · 지문 저장), test/support/sftp_server.dart 로 서버 띄우기 공용,
글이 바뀐 시험 3곳 고침. 전체: 이 4곳 말고 통과, 새로 남은 임시 폴더 0 (move_settled 1번은 powershell 실행 "액세스 거부" - 다시 돌려 통과).
- 내 판단: 끝 버튼 줄에 [SFTP 서버 추가] 아이콘을 하나 더 (WebDAV 와 따로 바로 보이게).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
관리자 결정 (10/17, 개인정보):
- DNS 프록시 거절 기록: 요청 줄 대신 "방식 주소:포트" 만 (경로 · 질의 (? 뒤) 는 남기지 않음, requestLineForLog).
- DoH 주소: 작업 기록 · app.log · 안내 · 다운로드 실패 이유에는 호스트만 ("https://dns.nextdns.io/…", DnsConfig.label · hideUrlPaths).
DoH 오류 원문 안의 주소도 가림. 설정 화면은 그대로.
시험 임시 폴더 (%TEMP%\jj_*) - 전체 시험마다 8개가 남았다:
- 앱 버그 (버그 수정): AI 해상도 올리기 upscale4x 가 실패 · 취소하면 jj_up_ 임시 폴더를 지우지 않음 → 지움.
품질 올리기 (묶음6 내 코드) 는 4배 결과 폴더를 지우지 않음 → 저장했든 못 했든 지움. 사용자 기기의 임시 폴더에도 남던 것.
- 시험: 책갈피 저장이 뒤에서 늦게 끝나 폴더를 다시 만들던 3곳 (jj_bmf_ · jj_bm_ · jj_nav_) 은 파일 끝에 기다렸다 지움
(test/support/temp_dirs.dart). ai_upscale_test 는 받은 결과 폴더를 지움.
- 검사: tool/test_temp_check.ps1 - 전체 시험 앞뒤로 %TEMP% 를 비교해 시험 소스의 jj… 이름으로 새로 남은 것이 있으면 실패.
(시험 파일들이 동시에 돌아 파일마다 스스로 확인할 수 없어 전체 실행 앞뒤로 본다.) 이미 있던 폴더는 건드리지 않음.
전체 822 통과 · 17 건너뜀, 새로 남은 임시 폴더 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
관리자 지시 (10/12, 다음 릴리스 준비). 겹친 곳은 양쪽 뜻을 살려 풀었다:
- 번역 json (en · ja · zh): 세 판 (공통 · 양쪽) 으로 열쇠마다 합침 (서로 다른 값으로 바뀐 열쇠 0개).
- 225 (모르는 컴포넌트 · 화면 순서 남기기, 양쪽에 따로 들어감) 를 하나로:
settings.fromJson 은 tor_dns 쪽 (문자열만 남김), 순서 바꾸기는 묶음5 의 AppComponent.reorder (모르는 화면은 그 자리에)
+ tor_dns 의 fullOrder (Tor 는 웹 브라우저 바로 뒤, 켜지 않은 Tor 는 순서에 넣지 않음).
시험은 둘 다 남기고, 이제 tor 를 아는 판이라 "모르는 화면" 은 future_screen 으로.
- build.gradle.kts: Tor jniLibs 폴더 + 195 의 third_party_libs.txt 거르기에 tor 폴더 포함, 목록에 libtor.so 추가.
check_apk.ps1 도 tor 폴더를 본다.
- 201 (브라우저 위 막대 두 줄) 을 Tor 화면에도 (minMiddleWidth 380).
- live_sync · sync_tools · explorer_page · 흔들림 시험 (165 등) 은 tor_dns 가 건드리지 않아 묶음5 그대로.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
전체 실행에서만 한 번씩 실패한 "잘린 답 (TC) 은 TCP 로 다시 묻는다" 의 원인을 잡으려고, 실패하면 예외 · 종류 · errno 와
가짜 DNS 의 bind 시도 · TCP 받음 기록 · 질문을 출력한다 (wt_mgr 세 번 · wt_tor 두 번 전체 실행에서는 재현되지 않음).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 225 (기기 확인 a4): Tor 를 모르는 판을 거치면 구성 요소 'tor' 가 지워지던 것. 설정을 읽을 때 components · navOrder 의
모르는 id 를 버리지 않고 그대로 둔다 (40 과 같은 원칙). 화면 · 버튼은 아는 것만. 화면 순서를 바꿔 저장할 때도 모르는 id 를 남긴다.
- 226: Tor 화면을 떠난 뒤 tor 를 켜 두는 동안 "Tor 대기 중 (n분 뒤 끔)" 을 환경 설정 > Tor 와 일반 브라우저 띠에 [지금 끄기] 와 함께.
- 227: Tor 화면에서 막은 파일 링크 뒤 주소 칸을 마지막으로 보인 페이지 주소로 되돌린다.
- 포트 (관리자 지적): Windows 는 TCP · UDP 마다 막아 둔 포트 범위 (Hyper-V · WSL) 가 있어 번호를 정해 bind 하면 10013 이 날 수 있다.
시험의 가짜 DNS 는 TCP 를 OS 가 고른 번호로 먼저 열고 그 번호로 UDP (안 되면 다시). aria2 는 넘긴 번호를 열지 못해 끝나면 새 번호로 다시 (2번).
앱 안 프록시 · Tor 다리 (같은 번호 → 실패하면 OS 가 고름), Tor (auto), Android 웹 뷰 문 (0) 은 이미 그렇다.
- analysis_options: packages/whisper_ggml 도 분석에서 뺌 (자기 analysis_options 가 flutter_lints 를 찾지 못함).
- 시험: components_test 1 · tor_test 2 (226 · 227).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 202 (관리자 지시, 사용 막힘): 빈 드라이브가 많은 PC 에서 창 위 줄이 넘쳐 [경로 입력] · WebDAV 를 누를 수 없었다.
[← → ★] · 저장 장치 탭 (이것만 옆으로, 마우스 휠 · 끌기) · [WebDAV · 경로 입력] (늘 보임) 으로 나눈다.
비어 있거나 연결 안 된 드라이브는 숨기지 않고 뒤쪽으로. 창이 320 보다 좁으면 끝 버튼은 [⋮] 하나로.
- 203: 잠긴 시스템 파일의 크기 · 바뀐 날 ("-1B · 1970-01-01") 은 "—"
- 시험: 권한 없는 폴더 (E10) 가 읽히는 환경 (Git Bash · MSYS 는 백업 권한을 켬) 에서는 이유를 남기고 건너뜀.
explorer_parallel_test 37 · 122 는 202 때문에 [경로 입력] 을 못 찾던 것 - 이제 통과
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
사용자 요청 (10/10): "Tor 브라우저를 현재 브라우저 옆에 추가 · 설정에서 컴포넌트처럼 추가 ·
DNS 주소를 강제로 내가 설정한 주소로, 기본 8.8.8.8" (보조 8.8.4.4 는 관리자 결정).
DNS 강제 (환경 설정 > 네트워크 · DNS: 시스템 DNS (끄기) / 직접 지정 (기본) / DNS over HTTPS)
- 앱 안 HTTP 프록시 (127.0.0.1, CONNECT + http) 가 정한 서버로 이름을 푼다 (UDP, 잘리면 TCP, DoH,
TTL 동안 기억). 닿지 않으면 기기 DNS 로 몰래 바꾸지 않고 502 + 알림 [시스템 DNS 로 바꾸기].
- 따르는 것: 앱의 HttpClient (HttpOverrides: 업데이트 · 컴포넌트 · AI 모델 · WebDAV · 번역 · 자막),
Edge (--proxy-server) · Chrome 엔진 (webview_cef 패치 6), Android 웹 뷰 (ProxyController),
yt-dlp --proxy, aria2 --all-proxy (+ c-ares 가 있으면 --async-dns-server).
- IP 주소 · 같은 집 안 이름 (점 없는 이름, *.local, Tailscale *.ts.net 등) 은 기기 DNS (내 판단: NAS · WebDAV 가 그대로 열리게).
Tor 브라우저 (컴포넌트 'tor', 처음 꺼짐, 화면은 웹 브라우저 바로 뒤)
- Windows: 공식 Tor Expert Bundle 15.0.24 (tor 0.4.9.13) 을 받아 SHA-256 확인
(e9dc6ccc…2b65) → 앱 데이터 components/tor. Android: 같은 판의 libTor.so 를 APK 에 (tool/fetch_tor_android.ps1).
- tor 를 자식 프로세스로 (SOCKS · 제어 포트는 빈 포트, 쿠키 인증, __OwningControllerProcess), Tor 화면을 닫으면 끔.
- 웹 뷰 → Tor 다리 (HTTP 프록시 → SOCKS5, 이름은 Tor 에 넘김). Tor 100% · 프록시 적용 · 전용 프로필이
모두 된 뒤에만 웹 뷰를 만든다. WebRTC 끔, 권한 거절, 검색은 DuckDuckGo.
- Windows: 따로 WebView2 환경 (tor_webview, InPrivate). Android: 웹 뷰 프록시가 앱 전체라 Tor 화면이
열려 있는 동안 일반 브라우저도 Tor (안내 띠, 관리자 결정), androidx.webkit 프로필 'jj_tor'
(flutter_inappwebview_android 패치 jjProfile). 기능이 없으면 화면을 열지 않음.
- 상태 줄 (연결 중 % / 연결됨 / 실패 + 다시 시도), [새 경로] (NEWNYM), 처음 열 때 "공식 Tor Browser 아님" 안내.
- 라이선스: TOR_LICENSES.txt (Tor BSD-3 · Libevent · OpenSSL · zlib · zstd), tor 실행 파일은 GPL 빌드 → GPL-3.0.
시험: dns_proxy_test (가짜 DNS · 프록시 · SOCKS 다리), tor_test (새는 것 막기 · 번들 해시 · torrc),
integration_test/tor_dns_real_test (Windows 실제: 8.8.8.8 로 풀기, 닿지 않는 DNS 는 실패,
check.torproject.org "Congratulations").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
전체 시험 도중에 끊기면 사용자 휴지통에 시험 흔적이 남았다 (10/10 01:31).
- 탐색기는 recycle() · restoreRecycled() 를 쓴다 (앱은 늘 실제 휴지통, 시험만 recycleBinForTest 로 바꿈).
- test/support/fake_recycle_bin.dart: 실제와 같은 규칙 (긴 경로 거부 · 되돌릴 때 덮지 않음 · 원래 폴더 없으면 안 만듦),
다른 드라이브면 복사 후 지움. useTestRecycleBin() 은 JJ_TEST_REAL_RECYCLE=1 이 아니면 가짜로.
- recycle_bin_test 의 실제 휴지통 시험 3개와 긴 경로의 실제 함수 부르기는 실제 모드에서만.
explorer_conflict · explorer · 캡처 시험 (b3 · check) 은 기본 가짜.
- windows_check_shot_test 의 "65 · 94 · 98" 은 144 뒤로 깨져 있었다 ([그대로 두기] 창을 닫지 않아 다음 크기에서 막힘) - 닫게 고침.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- integration_test/windows_b3_shot_test: 165 · 48 · 154 · 52 · 148 · 144 를 실제 화면으로 눌러 PNG (JJ_SHOT_DIR)
- 휴지통을 건드리는 시험은 끝에 사용자 휴지통 전체에서 시험 폴더 아래 (하위 포함) 가 원래 위치인 항목이 0 인지 확인
(test/support/recycle_leftovers.dart)
- 165 보충: 카드 리더 · USB · CD (GetDriveType 2 · 5) 가 열리지 않으면 "연결 안 됨" 이 아니라 "비어 있음" (회색)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 환경 설정 > 파일 탐색기 > WebDAV: 서버 추가 · 고치기 · 지우기 · 연결 확인 (기본 인증, 인증서 확인 안 함)
- 위쪽 "SD 카드" 옆 서버 탭 (없으면 "WebDAV" 탭 → 바로 추가), 경로 dav://서버/경로
- 목록 · 새 폴더 · 이름 변경 · 삭제 · 찾기 · 복사 · 이동 (같은 서버는 MOVE), 열기 · 재생은 임시로 받아서
- Rsync · lsync: 한쪽이 WebDAV 면 앱이 크기 · 시각 비교로 맞춤 (-u · --remove-source-files 따름)
- PROPFIND 에 Content-Length (chunked 면 일부 서버가 남은 본문을 다음 요청으로 오해)
- Android: http:// NAS 연결 허용 (usesCleartextTraffic)
- 화면에는 내부 id 대신 "☁ 서버 이름/경로"
- 시험: webdav_test (시험 서버) · explorer_webdav_test · real_dav_test (JJ_REAL_DAV 일 때 실제 서버)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>