CrownyAI 신셸 오피스 저장/열기 셸 브릿지
개요
CrownyAI 신셸(native/crowny-ai-*.m)의 오피스 탭(crowny://office, self-contained React 번들)은
자체 저장 기능이 없다(localStorage/save 0). 셸(WKWebView 호스트) 레벨에서 ⌘S/⌘O 를 가로채
편집 내용을 로컬 HTML 파일로 저장/재열람하는 브릿지를 추가했다.
무엇을 했는지
- S1 저장(⌘S): 오피스 탭에서만 동작. WKWebView에 JS 주입해 편집영역 휴리스틱 탐색
(①
[contenteditable=true] 최장 innerText ②
[role=textbox] ③
.prose/.doc-body/.editor
④ 그래도 없으면 nav/header/footer 제외 최장 텍스트 블록 → document.body 폴백) →
{title, html, text} 추출 →
~/Documents/CrownyOffice/<제목>-<yyyyMMdd-HHmm>.html 로
완결 HTML 저장 → CAToastCenter 성공 토스트("저장됨: ..." + "열기" 액션, Finder 선택).
- S2 열기(⌘O): 오피스 탭에서만 동작. NSOpenPanel(기본 디렉토리 CrownyOffice, .html 필터,
구 API
allowedFileTypes + 폐기경고 pragma 억제 — UniformTypeIdentifiers 프레임워크
미링크 상태 유지, Makefile 기존 타깃 무수정 원칙) → 선택 파일을 새 탭에 file:// 로드
(인플레이스 주입은 리스크 회피로 하지 않음, 1단계 왕복).
- S3 배선: File 메뉴에 "저장 ⌘S" / "열기… ⌘O" 항목 추가(menuSave:/menuOpen:) →
CAContentController 카테고리(CAOfficeIO)로 위임. 오피스 탭이 아니면 무동작 + 안내 토스트.
구현 위치
/Users/ef/crownybrowser/native/crowny-ai-content.m — CAContentController (CAOfficeIO)
카테고리:
caIsActiveTabOffice /
caSaveOfficeDocument /
caOpenOfficeDocument.
/Users/ef/crownybrowser/native/crowny-ai-main.m — 카테고리 재선언(관용구) + File 메뉴
항목 2종 +
menuSave:/
menuOpen:.
- 오피스 앱 자체(
bundle/office/app/index.html)와 crowny-browser.m/crowny-shell.m/Makefile
기존 타깃은 무수정.
실측 검증 (라이브)
make ai — 에러 0 · 경고 0. ./CrownyAI 3초 생존 확인.
- 실행 →
crowny://office 진입 → File>저장(⌘S 자체는 오피스 SPA가 keydown을 흡수하는
케이스 관측 — 메뉴 클릭은 항상 정상 동작, 스펙상 "메뉴 등록만으로 충분" 조건 충족) →
~/Documents/CrownyOffice/문서-20260714-1000.html 생성(35KB, 시트 도구 실제 렌더 캡처) +
토스트 "저장됨: 문서-20260714-1000.html" 확인(스크린샷).
- File>열기… → NSOpenPanel이 CrownyOffice 폴더를 열고 .html만 필터링해 보여줌 → 선택 →
새 탭에 저장본 로드 확인(주소창 file:///.../문서-...html).
- 비-오피스 탭(저장본을 연 file:// 탭 포함)에서 저장 시도 → "오피스 탭에서만 저장할 수
있습니다" 토스트로 정상 차단(중복/오염 저장 없음) 확인.
버그 1건 발견·수정 (라이브 테스트로 발견)
CrownyTab.urlString 은 페이지 로드 완료 KVO(
observeValueForKeyPath:URL, content.m
~1259-1270)가 실제
file://.../bundle/office/... 경로로 되돌려놓는다 — 주소창 표시만
"crowny://office" 로 재정규화될 뿐
urlString 프로퍼티 자체는 아니다. 최초 구현에서
caIsActiveTabOffice 가
urlString == "crowny://office" 만 비교해 저장 시점에는 거의 항상
거짓으로 판정되는 버그가 있었다(1회차 라이브 테스트에서 발견). 기존 코드의 동일 정규화
조건(
hasPrefix:"file://" &&
containsString:"office/")을 그대로 적용해 수정.
크라우니코드
lookup HIT 0건 / MISS 2건 / learn 2건 (오피스탭_WKWebView_저장, 오피스탭_NSOpenPanel_라운드트립)
잔여 이슈
- ⌘S 키보드 단축키 자체는 오피스 SPA가 포커스 상태에 따라 keydown을 선점할 수 있음(WKWebView
가 페이지의 preventDefault 를 존중) — 메뉴 클릭은 항상 안전하게 동작하므로 스펙 요구사항
("메뉴 등록만으로 충분")은 충족하나, 완전한 전역 단축키 신뢰성을 원하면 NSWindow/
CAContentController 레벨에서 WKWebView보다 우선하는
performKeyEquivalent: 오버라이드가
후속 과제.
- 편집영역 휴리스틱은 오피스 앱의 실제 DOM 구조(React, contenteditable 유무 미확인 — 정적
번들 grep 상 리터럴 문자열 매치 없었음, 런타임 DOM은 별도)에 따라 ④ 폴백(가장 큰 텍스트
블록/전체 body)으로 떨어질 가능성이 높음 — 실측 저장 파일(35KB)은 시트 도구 렌더 전체를
캡처했음, 텍스트 문서 편집기에서 재검증 권장.