14 Commits

Author SHA1 Message Date
songyc macbook
92afa69f6d feat(1.5-p1): 워치 '행동 기록' 컴플리케이션 — 기간 옵트인·미니 행동 화면 딥링크
- WatchActionPeriod(하루/이번 주/이번 달/지난 7일/지난 30일) + WatchActionInfo에
  optional 기간 필드 3종(구버전 캐시 호환 — isFavorite 패턴)
- LocalPrefs.watchActions(uuid→기간 맵, 기기 로컬) + 전체 초기화 청소 목록 반영
- makeSnapshot: 옵트인 행동만 기간값 계산(rollingRange 재사용, StatSpan 무변경)
- 신규 ActionValueComplication(4패밀리·측정 중 노랑+타이머·유령 타이머 안전장치·
  빈 상태 안내·recommendations verbatim·widgetURL 딥링크)
- 워치 미니 행동 화면(WatchActionDetailView) + NavigationPath 딥링크 착지
  (뒤로가기 한 번에 메인 복귀), 행동 편집기 애플워치 섹션(토글+기간)
- 검증 인자: -watchActions <N>·-actionShowEditor·-watchOpenActionDetail
- 검증: Debug/Store/워치(26.2·11.5) 빌드, 자가 검증 49·20·27·10 ALL PASS(26.5+18.5 심),
  시각 QA 5장. 신규 문구 l10n은 계획 §10 R6대로 도움말 단계에서 일괄
- CLAUDE.md: 시뮬레이터 세트 리셋 반영(신규 UUID)·검증 인자 추가

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WtZwRRjbtM9pZJDM4FkTq6
2026-08-22 05:18:42 +09:00
songyc macbook
5b526fa650 feat(compat): iOS 하한 18.0 인하 — 글라스 버블 머티리얼 폴백·사용자 심볼 안전 렌더·Release 인라이너 크래시 우회
- 배포 타깃 26.0→18.0 (앱·위젯. 워치 10.0 불변)
- RadialNavigationView: glassEffect 계열을 @available(iOS 26) 선언 격리 + 18 머티리얼 원 폴백 (배치·연출 동일)
- DiaryZoomContainer.Coordinator → 비제네릭 톱레벨 DiaryZoomCoordinator + AnyView 소거 (하한 18 Release wholemodule에서 swift-frontend SILPerformanceInliner 무한 재귀 크래시 실측·우회)
- Image(safeSymbol:)/SymbolCompat: 카탈로그의 상위 OS 전용 심볼(18 기준 3개)이 교차 기기에서 빈 아이콘이 되지 않게 사용자 심볼 렌더 48곳+워치 7곳 폴백
- -symbolAuditDump 검증 인자 추가, iOS 18.5 시뮬 QA(빌드·radial 폴백·일기 줌·progressSelfTest 49 ALL PASS)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NNxA172hNDRpDsJ2qztKPf
2026-08-11 16:31:40 +09:00
songyc macbook
ac40e14cfe feat(ux): UX 감사 반영 배치 — 시스템 테마·온보딩·일기 잠금·기간 비교 외
2026-07-23 사용성 감사(A그룹 5건 + 지시 추가분)를 한 번에 반영.

[테마] '시스템 설정 따름' 추가 + 기본값 light→system. "system"은 스킴을
  강제하지 않아(preferredColorScheme nil) 앱·위젯('앱 일치' 옵션,
  WidgetThemeOption.scheme: ColorScheme?)·DEBUG 위젯 미리보기까지
  시스템 라이트/다크를 그대로 따른다
[온보딩] 첫 실행 3장 소개(OnboardingView — 행동→목표·다짐→정리).
  데이터가 하나도 없고 본 적 없을 때만 1회(건너뛰기 포함 재표시 없음,
  onboarding.done), 시드·마케팅 촬영 플로우는 자동 건너뜀.
  설정 → 지원 '앱 소개 다시 보기'로 재열람
[일기 잠금] 설정 → 일기(iPad 전용 표시) 토글 — DiaryLock이
  .deviceOwnerAuthentication으로 Face ID/Touch ID/Optic ID+암호 폴백을
  기기별 분기 없이 처리. 일기 탭 진입 게이트(DiaryLockGateView),
  백그라운드 재잠금, 토글 변경 시 인증 요구, 잠글 수단 없는 기기는
  통과(영구 잠김 방지). NSFaceIDUsageDescription 추가(Info.plist+
  InfoPlist.xcstrings ko/en/ja)
[통계] 이전 기간 비교 카드(맨 위) — 총 시간·횟수를 어제/지난주/지난달과
  비교(▲▼%, 이전 기록 없으면 상태 문구). 이전 기간은 관계 기반
  Aggregator로 직접 집계, 필터 반영. 화면 전용(내보내기 미포함 의도)
[스플래시] 1.2→0.7초 단축 (하루에도 여러 번 여는 앱)
[워치] 행동 실행 탭 시 WKInterfaceDevice.play(.click) 햅틱 — 화면을
  안 보고 탭해도 접수 확인
[컴플리케이션] rectangular 빈 상태에 해결 안내("목표 편집에서
  '애플워치에서 보기'를 켜면 나타나요") — 옵트인 발견성 보완
[문구] 행동 편집기 꼬리표 색 규칙(여러 개면 가장 먼저 만든 꼬리표),
  새로고침 버튼 accessibilityHint

- 도움말 3주제 추가(새로고침 버튼·일기 잠금·이전 기간과 비교)
- 신규 문구 31키 en/ja 완역 + 워치 카탈로그 2키, missing/stale 0
- CLAUDE.md §6·§6.6·§6.7·§6.8·§10·§11·§14 갱신, DEBUG 인자
  -showOnboarding·-diaryLockScreen 추가
- 검증: Debug/워치/Store 빌드, 온보딩·설정·비교 카드·잠금 게이트·
  컴플리케이션 스크린샷

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 02:02:38 +09:00
songyc macbook
1dea41b472 feat(ux): 잠금화면 다짐 점 링 방식 + 즐겨찾기 순서 변경 시트 (실기기 피드백 2건)
첫 출시 전 반영 요청된 사용성 개선 — 둘 다 표시 계층·기기 로컬 설정만
건드리는 안전 범주.

① 잠금화면 위젯 다짐 점: '아래에서 차오르는 물높이' 채움은 5~6pt에서
   90%↔100% 차이(위쪽 1px)가 배경에 따라 사실상 안 보임 —
   **미완료 = 링(호) 진행(시작 최소 10%, 완료 직전에도 틈이 보이게
   최대 88%까지만 감김) / 완료 = 꽉 찬 원반**으로 교체. 링 끝의 틈은
   둘레에 생겨 눈에 띄고, 완료는 면적(빈 링 vs 원반) 자체가 달라
   어떤 배경에서도 구분된다. ratio 그대로라 '이하 유지'는
   한도 안=원반/초과=빈 트랙으로 의미 유지 (§10 문서화)

② 즐겨찾기 순서 변경: 행동 탭 ⋯ 메뉴에 '즐겨찾기 순서 변경' 시트
   추가(2개 이상일 때, 꼬리표 순서 시트와 동일 패턴 — 닫힐 때 1회
   커밋). LocalPrefs.reorderFavorites는 전역 배치에서 즐겨찾기가
   차지한 자리들만 재배열해 나머지 행동·위젯 기본 슬롯 무영향.
   모음 탭 즐겨찾기 섹션·애플워치 즐겨찾기가 같은 순서를 읽으므로
   세 표면이 자동 일관 (§6.2·§6.1·§11 문서화).
   move(fromOffsets:)는 SwiftUI 확장이라 Foundation 계층에 동일
   의미로 직접 구현

- 도움말 '즐겨찾기 모아 보기' 본문에 순서 변경 경로·워치 적용 추가
- 신규 문구 4키 en/ja 완역, 옛 본문 stale 정리 (missing/stale 0)
- §14에 -actionShowFavoriteOrder 검증 인자 추가
- 검증: Debug/Store 빌드, 잠금 위젯 프리뷰·순서 시트 스크린샷

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 21:38:16 +09:00
songyc macbook
28a453485d feat(main): 배치 편집을 즐겨찾기 섹션 인지형으로 — 끌어서 지정·해제 + '지정 순서' 규칙
즐겨찾기 v2(e09a0b7) 후속 실사용 피드백 세 가지 반영:
①즐겨찾기 안에서 순서 바꾸기가 어렵다 ②새로 지정하면 꼬리표(전역)
순서에 끼어들어 예측이 안 된다 ③배치 편집이 즐겨찾기가 없다는 듯
통짜 그리드로 떠서 디테일이 떨어진다.

- 배치 편집도 즐겨찾기/나머지 섹션 구조 그대로(항상 펼침): 섹션 안
  드래그는 실시간 순서 변경, **섹션 사이 드래그는 드롭 확정 시점에
  즐겨찾기 지정·해제 + 그 위치로 이동**(commitDrop). 호버 중 교차
  이동은 자기 섹션 안 점프로 보여 moveDragging이 무시
- 빈 섹션은 점선 드롭 존(호버 하이라이트)이 받는다 — 즐겨찾기 0개
  상태에서도 끌어서 지정 가능, 전부 즐겨찾기면 해제 존 표시
- **새 즐겨찾기는 배치 순서상 블록 끝으로**(LocalPrefs.placeNewFavoriteAtEnd
  — 롱프레스 메뉴·행동 탭 스와이프·상세 토글 3경로 공통). 해제는
  위치 무이동(나머지 상단 근처에 남음), 첫 즐겨찾기도 무이동
- 도움말 본문에 순서 규칙·끌어서 지정 사용법 반영, en/ja 번역 +
  stale 1키 정리 (드롭 존 문구 2키 포함 missing/stale 0)
- 검증: Debug/Store 빌드, 아이폰·아이패드 편집 모드 + 브라우즈
  스크린샷 (isFavorite는 모델 필드라 DataChange.commit 경유 유지)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 17:18:45 +09:00
songyc macbook
9c9c24f7df feat(a11y): VoiceOver labels for icon-only buttons + combined action-cell narration
접근성 감사 ③ — 전 화면의 아이콘 전용 버튼과 텍스트 없는 시각
요소에 보이스오버 라벨 부여 (시각 UI 변화 없음):

- 모음 탭: 행동 버튼 셀을 label(이름)+value(측정 중/오늘 누적)로
  한 덩어리 낭독 — 아이콘·타이머가 따로 읽히지 않음. 진행 중 행의
  정지 버튼 "측정 종료".
- 기록 탭: 날짜 이동 화살표(이전/다음 날짜), 내보내기, 기록 필터,
  필터 칩 해제 버튼. 타임테이블의 색 블록·횟수 점은 "행동 이름 +
  시각(구간)" verbatim 라벨로 낭독 가능하게.
- 통계 탭: 기간 이동 화살표(이전/다음 기간), 내보내기, 통계 필터,
  필터 해제.
- 행동/꼬리표/목표 탭: + 추가 버튼(행동/꼬리표/목표 추가), ⋯ 메뉴.
- 일기: 달 이동 화살표(이전/다음 달), 내보내기, ⋯ 메뉴, 기분 타일
  ("오늘 기분"), 할 일 삭제 버튼.
- ⑥ 현재 진행 중 위젯: 종료 버튼 "측정 종료".
- CLAUDE.md §15에 컨벤션 추가: 아이콘 전용 버튼 accessibilityLabel
  필수, 복합 셀은 label+value 한 덩어리, 텍스트 없는 시각 요소는
  verbatim 라벨.

신규 문구 9종 ko/en/ja 번역 + 위젯 카탈로그 '측정 종료' 번역 복사
(전 카탈로그 missing 0/stale 0). Debug·Store 빌드 성공, 접근성
수식어는 시각 렌더링에 영향 없음(스모크 런치 확인). 실기기에서
보이스오버 켜고 핵심 흐름(행동 시작/종료·날짜 이동) 낭독 확인 권장.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-14 22:24:21 +09:00
songyc macbook
e652aff0e9 fix(review): tracking-type lock on edit, week-label l10n, premium feature list, catalog hygiene
전체 코드 최종 점검(보고)에서 지시받은 A·B·D 항목 처리:

A. 행동 수정 시 추적 방식 변경 잠금
   기존 행동을 수정할 때 추적 방식(시간↔횟수) 피커가 활성화되어
   있어 도움말("추적 방식은 바꿀 수 없으니")과 어긋났고, 바꾸면
   기존 기록이 화면·통계에서 보이지 않는 것처럼 되는 문제.
   → 수정 모드에서 피커 비활성 + "만들 때만 선택할 수 있어요"
   푸터 안내(ko/en/ja). 생성 시에는 기존과 동일.

B. 주차 라벨 지역화 2건
   - 통계 탭 월간 주차별 꺾은선 x축 "N주차"가 String(localized:)
     없이 하드코딩 — en/ja에서 한국어 노출 (내보내기와 불일치)
   - ⑤ 행동 통계 위젯 주 단위 라벨 "N주" — 같은 문제 + 앱과 표기
     불일치 → 둘 다 기존 번역 키 "%lld주차"(Week %lld/第%lld週) 사용

D. 결제 화면 기능 목록에 '제어 센터에서 실행' 항목 추가(ko/en/ja,
   도움말·CLAUDE.md와 일치) + Widgets/InfoPlist.xcstrings의
   CFBundleName을 IOS와 동일하게 shouldTranslate=false 처리.

C(시리 문구 미번역 의심)는 오탐 확인 — AppShortcuts 카탈로그는
stringSet(발화 변형) 구조로 ko/en/ja 모두 translated 상태.

검증: Debug·Store 빌드 성공, 영어 실행 통계 월간 화면에서
"Week 1~5" 표시 확인, 결제 화면에 제어 센터 항목 표시 확인,
전 카탈로그 missing 0·stale 0. CLAUDE.md §6.2 갱신.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-14 18:22:23 +09:00
songyc macbook
d023f3eca1 fix(action): commit tag order and favorite changes immediately
꼬리표 순서 변경 시트와 즐겨찾기 토글(리스트 스와이프·상세 화면)이
DataChange.commit 없이 autosave에만 의존해, 저장 확정이 지연되고
꼬리표 순서를 쓰는 워치 앱 그룹핑이 다음 커밋 시점까지 낡은 순서로
남을 수 있었다.

- TagOrderSheet: 드래그마다가 아니라 시트가 닫힐 때 1회만 커밋
  ('완료'와 스와이프 내리기 모두 onDisappear 경로) — 위젯 리로드 연발 방지
- 즐겨찾기 토글 2곳: 변경 즉시 커밋

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-13 19:35:29 +09:00
songyc macbook
14fc5cb5bd feat(premium): complete StoreKit 2 purchase experience
기존 StoreKit 2 골격(상품 3종·구매·복원·권한 주입) 위에 실사용 경험 완성:
- PremiumStore.currentPlan: 현재 이용 중인 대표 플랜(평생 > 만료 먼 구독)
  추적, 구매·복원 후 위젯 타임라인 즉시 갱신
- 프리미엄 화면: '이용 중인 플랜' 섹션(플랜 이름·다음 갱신일·평생 안내),
  구독 관리 시트(manageSubscriptionsSheet), 구독 중 평생 이용권 전환 안내,
  년 구독 절약률·평생 '한 번 결제' 배지, 자동 갱신·해지·복원 안내 문구
- 잠금 안내 개선: 행동/목표/다짐 무료 한도 알림에 '프리미엄 알아보기'
  버튼 + PremiumSheetView 모달, 아이패드 일기 잠금 화면에도 버튼 추가
- 기능 소개에 '아이패드 일기' 추가, 새 문자열 en/ja 번역

가격(월 5,000/년 50,000/일회성 80,000)은 HaruDanim.storekit(로컬 테스트)과
App Store Connect에서 각각 수정 가능. DEBUG 강제 토글은 그대로 유지.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-13 15:52:49 +09:00
songyc macbook
3dd53c4fc6 refactor: decouple all UI preferences and layout settings from CloudKit sync to local device storage
- Add Shared/LocalPrefs.swift: device-local UI preferences stored in App Group
  UserDefaults (never synced by iCloud), read identically by app, widgets,
  watch snapshot, and App Intents on the same device
- Move to local storage: main-tab action button order (UUID array), pinned
  goal-progress cards on the main tab, goal quest-list collapse state, and
  per-action memo-prompt popup — reordering or repinning on iPhone no longer
  touches the iPad and vice versa
- Defense logic: actions not in the local order list (e.g. newly received via
  CloudKit from another device) are automatically appended to the end, sorted
  by legacy sortOrder then creation date
- One-time migration adopts existing @Model values (sortOrder, showsOnMain,
  isCollapsed, promptsForNote) into local prefs at launch; model properties
  stay in place so the CloudKit schema is untouched and records keep syncing
- Data remains fully synced: actions, goals, quests, sessions, count entries,
  statistics, and goal/tag/quest list order are untouched by this change
- Verified in simulator: legacy data migrates losslessly, grid renders from
  local order, unknown action lands at the end; iOS+watch+widgets build clean

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-11 20:58:34 +09:00
songyc macbook
2567b53b71 fix: correct daily goal progress calculation and optimize widget refresh logic
- 목표 하루 진행률은 오늘이 수행일인 다짐만 모수로 계산 (요일·날짜 지정으로
  오늘 쉬는 다짐은 분모에서 제외, QuestProgress.isScheduled 신설)
- 오늘 수행할 다짐이 하나도 없는 날은 0% 대신 100%(완료 상태)로 표기
- 주간/월간 진행률은 기존대로 전체 다짐 기준 유지
- 이벤트 기반 위젯 새로 고침: 앱 내 모든 핵심 Mutation(측정 시작/종료,
  횟수 추가, 기록 추가·수정·삭제, 행동·꼬리표·목표·다짐 CRUD, 순서 변경,
  목표 상태 변경)의 끝단에서 DataChange.commit() 호출 — 저장 즉시 확정 후
  Live Activity·위젯 타임라인·워치 스냅숏을 한 번에 동기화
- 주기적 백그라운드 새로 고침 없이 변경 시점에만 갱신해 WidgetKit
  업데이트 예산 절약 (타이머 표시는 기존 Text(style: .timer)로 시스템이
  자체 렌더링하므로 타임라인 소모 없음)
- 하루 시작 시간·주 시작 요일 설정 변경 시에도 위젯 집계 갱신
- 시뮬레이터 검증: 월·수·금 다짐이 있는 목표의 토요일 하루 진행률이
  33%가 아닌 50%(오늘 수행 다짐 2개 평균)로 표시됨 확인

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-11 08:30:12 +09:00
songyc macbook
a6c040cd6a feat(i18n): 전체 UI 다국어 지원 (한국어·영어·일본어)
- 언어 설정 실적용: 변경 시 AppleLanguages 오버라이드 저장, 재시작 안내 footer
- 자동 추출되지 않던 일반 문자열(탭 이름, 픽커 라벨, 상태 뱃지, 포매터,
  삼항 문구, 심볼 카테고리 등)을 String(localized:)로 전환
- 위젯·워치 앱·컴플리케이션 타깃에 Localizable.xcstrings 신설
  (중복 리소스 방지 pbxproj 예외 추가), xcstringstool sync로 키 추출
- 4개 카탈로그 전체 키(고유 430개)에 en/ja 번역 주입
- 영어의 긴 횟수 단위("times")가 잘리지 않도록 모음 탭 셀 축소 허용
- 검증: -AppleLanguages "(en)"/"(ja)"로 모음 탭·설정 화면 확인

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-10 15:03:24 +09:00
songyc macbook
26410006a6 feat(premium): 프리미엄 아키텍처 도입 (EntitlementProvider/PremiumManager/PremiumGate)
- EntitlementProvider 프로토콜로 권한 조회 추상화 — StoreKit 2 도입 시 구현체만 교체
- PremiumManager(@Observable): 앱 UI의 단일 진입점, canAddAction/Goal/Quest 게이트
- PremiumGate: 위젯·워치·인텐트용 App Group defaults 동기 캐시 (기존 값 1회 이관)
- 행동/목표/다짐 개수 제한 체크를 @AppStorage 직접 참조에서 매니저 경유로 교체
- 앱 entitlements: App Group / iCloud(CloudKit) / Siri
- DEBUG 검증 인자: -premium YES/NO

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-10 08:58:58 +09:00
songyc macbook
520e625377 change folder Haru_Danim -> HaruDanim 2026-07-10 03:02:15 +09:00