# web/ai_read.md — viewer UI / app.js 작업 기준

이 폴더는 웹 viewer 쪽이다.

## 목표 UI

Chrome Remote Desktop의 좋은 UX를 참고한다. 코드를 복사하는 것이 아니라 UI 구조만 참고한다.

기본 방향:

```text
화면 중앙 오른쪽 작은 [ > ] 플로팅 버튼
클릭하면 우측 사이드 패널 열림
섹션별 > / v 접기/펼치기
전체화면 지원
모바일도 고려
```

## 우측 패널 섹션

```text
세션 옵션
- 전체화면
- 화면 크기에 맞게 조정
- 연결 종료

입력 컨트롤
- 원격 제어 ON/OFF
- 가상키보드 켜기
- 단축키 안내

클립보드
- 클립 보내기
- 클립 가져오기

파일 전송
- 파일 보내기
- 파일 받기/목록은 추후

스냅샷
- 화면 변경 시 스냅샷 저장 ON/OFF
- 저장 폴더/유지 개수는 host 설정과 동기화

통계
- frames
- fps
- 해상도
- last frame KB
- avg frame KB
- MB/s
- Mbps
- 누적 수신량
- 원격 진행 시간
- 효율 표시는 tile diff 이후 추가

도움말
- 실제 PC로 입력 전송 중 설명
- 드래그/단축키/조합클릭 가능 설명
```

## 입력 이벤트

Viewer UI 클릭은 원격 PC로 전달하지 않는다.

```text
패널/버튼 클릭 = 로컬 UI 처리
canvas 클릭 = 원격 입력 전송
```

마우스/터치는 가능하면 Pointer Events 기반으로 확장한다.

모바일은 나중에 별도 입력 모드가 필요하다.

```text
터치패드 모드:
손가락 이동 = 마우스 이동
탭 = 클릭
롱탭 = 우클릭
두 손가락 = 스크롤
```

## 전체화면

Fullscreen API 사용.

```text
[전체화면]
[전체화면 해제]
ESC로 해제 가능
상태바는 작게 유지
```

## 통계 계산

브라우저에서 받은 Blob.size / ArrayBuffer.byteLength로 수신량 계산 가능.

표시 예:

```text
수신 중 | 11.8 fps | 1280x720 | 0.96 MB/s | 7.7 Mbps | 진행 00:23:18
last 76.4 KB | avg 82.1 KB | total 1.42 GB
```

효율 표시:

- 현재 전체 JPEG 방식에서는 정확한 절감률 없음.
- tile diff 구현 후 `full_frame_estimated_bytes` 대비 `actual_tile_bytes`로 계산.

## 스냅샷 viewer

나중에 `snapshot_viewer.html`을 추가한다.

```text
manifest.json 읽기
→ chain key.jpg 로드
→ diffpack 순서대로 적용
→ canvas에 최신 화면 조립
```

---

## 2026-06-22 UI 패치 기준

Chrome Remote Desktop 스타일로 viewer 기본 UI를 바꿨다.

기본 상태:

```text
- 상단 고정 topbar는 숨김
- 오른쪽 중앙 `>` 탭만 표시
- `>` 클릭 시 우측 패널 슬라이드 오픈
- 우측 패널 닫기/접기 시 다시 `>` 탭만 남김
```

상단 중앙 플로팅 헤더:

```text
- 마우스가 화면 상단 중앙 영역에 들어오면 표시
- `×` 버튼 클릭 시 우측 패널을 다시 연다
- 상태/FPS/해상도/Mbps를 작게 표시
```

구현 파일:

```text
web/viewer.html  : floatingHeader, sideTab, snapshot section 추가
web/style.css    : topbar 숨김, floating header, side panel overlay 스타일
web/app.js       : 패널 토글, 전체화면, 통계 계산, host option ack 처리
web/protocol.js  : host_option_set / host_option_ack 상수 추가
```

주의:

```text
- 원격제어/파일/클립보드 기존 기능은 건드리지 않는다.
- 스냅샷 섹션은 UI 자리만 먼저 잡은 상태다.
- 실제 key.jpg + diffpack chain 저장/조립은 snapshots 규칙에 맞춰 다음 단계에서 연결한다.
```

## v72 메모: 기능별 스레드 분리 + hover lock mp4→jpg 클릭 + AIWK legacy 제거

- 최신 기준은 이 파일과 현재 ZIP 소스다. 추측으로 변경하지 않는다.
- `AIWK_PC/domains/www.instagram.com/` 레거시 폴더는 제거 대상이다. 더 이상 이 폴더의 ws/config/log를 수정하지 않는다.
- 기존 legacy `test.py`에서 서버/yellow.php/MySQL API 호출 기능만 추출해 `D:\_St\yjm_win2rtc\host\ig_sort.py`로 이동했다.
- `ig_sort.py` 역할:
  - 서버/yellow.php/MySQL 전송 전담
  - 마우스 클릭, hover 판단, md5 계산, 파일명 변경, UI 조작은 하지 않는다.
- `instagram_auto_runner.py`는 이제 `yjm_win2rtc/host`를 실행/로그/config 기준으로 사용한다. `IG_DOMAIN_DIR`도 host로 지정한다.
- ws8771/Tk 쪽 구조는 기능별 독립 worker + queue 대화 방식으로 정리한다.

```text
Main/Tk UI Thread = 상태창 표시 + 한국말 로그 반영
WS Worker         = 크롬 EXT 요청 수신, hover/status/download 요청 즉시 큐 전달
Click Worker      = 마우스 이동/hover lock/mp4 클릭/jpg 클릭/다운 지연
File Worker       = 다운로드 완료 감지, md5/sha256, .md5, 상위 JSON 갱신
ig_sort Worker    = 서버/yellow.php/MySQL 전송, 실패해도 클릭/파일 흐름 차단하지 않음
```

- 대화창/상태창 로그는 디버그 콘솔처럼 한국말로 남긴다.

```text
ws: No001 mp4 hover 받았다. x=1003 y=209 shortcode=DZ-IGqvBXmP
click: hover 위치 잠금했다. 2.1초 뒤 mp4 클릭한다.
click: mp4 클릭했다.
click: jpg 위치로 이동했다. 1.6초 뒤 jpg 클릭한다.
file: .md5 저장했다.
ig_sort: media_insert 저장했다.
auto: 다운 지연 후 Next로 이동한다.
```

- hover OK 처리 기준:
  - `ig_rtc_hover_status_current.json`은 최신 상태다.
  - `ig_rtc_hover_ok_current.json`은 마지막 OK 상태 별도 보존이다.
  - `zone=none`이 와도 hover lock 중이면 바로 지우지 않는다.
  - Click Worker는 current와 ok_current를 모두 보고 fresh OK를 소비한다.
- hover를 찾으면 그 자리에서 lock한다.
  - 엉뚱한 곳으로 이동하지 않는다.
  - 움직여도 좌하단 2~5px 미세 이동 후 원래 hover 좌표로 돌아온다.
  - 1~3초 랜덤 대기 후 mp4 클릭한다.
  - jpg는 mp4 버튼 바로 위 위치로 이동해 1~3초 랜덤 대기 후 클릭한다.
  - 그 뒤 `다운 지연` 만큼 대기하고 Extension이 Next로 이동한다.
- 파일명/중복 기준은 v71을 유지한다.

```text
인스타어카운트_수집시각_No000_shortcode.ext
중복키 = shortcode + asset_kind + media_index
```



## v73 note

- 최신 자동 클릭 기준은 host/ai_read.md의 v73: hover OK 즉시 클릭 + 클릭 후 서성임 + jpg hover 검증이다.
