7 Commits

Author SHA1 Message Date
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
ddd46a4084 feat(widget): lock-screen quest dots fill by progress ratio
- 잠금화면 위젯 '다짐 점'이 달성/미달성 이진 채움이라 진행 정도를 알 수 없다는 보고 → 각 점이 진행률(ratio)만큼 아래에서부터 차오르게 변경. 표시 전용 소형 뷰 수정이라 위험 낮음 판단 후 진행
- ratio를 그대로 쓰므로 달성=완전 채움(기존과 동일), '이하 유지'는 ratio가 1/0이라 한도 안=채움/초과=빈 점 동작 불변. 작은 크기(5~6pt)에선 부채꼴보다 물높이 방식이 가독성 좋아 채택
- 위젯 미리보기 잠금 섹션에 '다짐 여러 개+주간' 항목 추가 — 부분 채움(반쯤 찬 점/빈 점/가득 점) 시뮬 스크린샷으로 circular/rectangular 모두 확인
- 새 문자열 없음(카탈로그 클린), 도움말 무변경(스타일 세부 서술 없음). CLAUDE.md §10 갱신. Debug/Store 빌드 성공

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CkLDi8Lr21vGqo4SjZaTp
2026-07-19 05:36:46 +09:00
songyc macbook
fced5d1958 fix(l10n): localize widget/complication placeholder sample labels
- placeholder()의 생 한국어 리터럴 6곳을 String(localized:)로: ③다짐 링·④다짐 현황·잠금화면 위젯의 spanLabel "오늘"(기존 키 재사용), 워치 목표/다짐 달성률 "목표"/"하루"(기존 키 재사용), 워치 현재 현황 샘플 "독서"(워치위젯 카탈로그 신규 1키 — en Reading/ja 読書, iOS 위젯 카탈로그와 동일 값)
- placeholder는 갤러리/로딩 스켈레톤 전용 경로라 타임라인 예산·버튼 반응성·갱신 경로 무영향 — ①⑤ 위젯 placeholder가 이미 쓰던 패턴과 동일
- 검증: Debug·Store·워치 3스킴 빌드 성공, 전 카탈로그 missing/stale 0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-16 02:53:43 +09:00
songyc macbook
c7024ea612 fix(widget): fix AppIntent button interactions and streamline widget configuration options while preserving real-time sync
Two independent widget issues, both confined to the widget/intent layer.
The app→widget real-time sync path (IntentStore.refresh + performWrite +
reloadAllTimelines) is intentionally left untouched.

1. Interactive button taps were unreliable ("touch feedback but nothing
   changes; works only after several taps"). The run buttons passed a full
   AppEntity parameter — RunActionIntent(action: cell.entity). On every tap
   WidgetKit re-resolves that AppEntity through ActionEntityQuery.entities(for:),
   which opens a brand-new ModelContainer from disk each time. That heavy
   entity-resolution round-trip on the tap hot path is the classic cause of
   dropped/laggy interactive-widget taps — the write logic itself was already
   proven reliable last session. Replaced RunActionIntent's AppEntity parameter
   with a plain UUID String (actionID) that deserializes instantly with no
   query; perform() looks the action up inside the existing single-context
   performWrite path. One tap now fires immediately. RunActionIntent is
   widget-only (not a Siri AppShortcut), so this touches no shortcut. Both call
   sites (ActionRunCellView, QuestRingActionCellView) updated; the now-unused
   ActionCellSnapshot.entity helper removed.

2. Configuration screens were cluttered — every widget exposed action/goal/
   quest slots 1–4 regardless of family, so a Small widget's long-press config
   listed slots it never renders. Added a parameterSummary to all six
   WidgetConfigurationIntents so the config reads as one clean sentence, and
   labeled secondary slots with the size that uses them (e.g. "행동 2 (중형·대형)",
   "목표 3 (대형)"). WidgetKit can't hide parameters by family, so this makes the
   optional slots self-explanatory instead of noise.

Verified: BUILD SUCCEEDED (app + embedded Haru_DanimWidgets.appex); cold launch
with the widget preview renders without crashing. Physical home/lock-screen
button taps still warrant a real-device pass (the simulator can't tap widget
overlays).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-12 21:50:27 +09:00
songyc macbook
f7ddd42260 refactor(widget): complete widget architecture overhaul for reliable interactions and removed bloated configurations
- IntentStore now recreates the ModelContainer on demand in the widget
  extension (IntentStore.refresh()), called before every AppIntent
  perform() and every provider's makeEntry(). Fixes stale/blank widget
  buttons and double-toggle bugs caused by the extension process
  reading an old in-memory snapshot after CloudKit remote changes.
- Replaced the fixed 15/30-minute polling Timeline policy (which burns
  WidgetKit's daily reload budget across 6 widget kinds) with
  WidgetRefresh.timeline: idle widgets wait until the next logical-day
  boundary since value changes are already pushed via
  reloadAllTimelines, while widgets showing a live ratio (a currently
  running quest/goal) get pre-computed future entries so progress
  rings and bars keep advancing without extra reloads.
- Removed the per-widget "위젯 테마" (match app / light / dark / liquid
  glass) configuration option from all 5 home-screen widgets. It
  duplicated the same enum five times, and the liquid-glass variant's
  custom background/scheme override fought the system's own
  vibrant/tinted rendering in tinted Home Screens, which was part of
  the "블랙 화면"/렌더링 오류 reports. Widgets now simply follow the
  app's own theme setting (WidgetAppearance.appScheme), which is what
  "앱 테마와 일치" already defaulted to.
- Added shared gallery/placeholder sample data (ActionCellSnapshot,
  QuestCellSnapshot, GoalSnapshot, StatsChart sample points) so the
  widget gallery and redacted placeholders show a realistic shape
  instead of an empty/blank card.
- Unified empty-state UI via WidgetEmptyView across all 5 widgets.

Scope: Widgets/*, Shared/HaruDanimIntents.swift (widget-facing
IntentStore only), IOS/Views/WidgetPreviewScreen.swift (DEBUG preview
tool). No changes to app core data models, sync, or view logic.
2026-07-11 22:41:54 +09:00
songyc macbook
bc6cd010b7 fix(widgets): 리퀴드 글라스 테마 시인성 개선 및 틴트/클리어 렌더링 모드 대응
- 글라스 테마: 틴트 셀 불투명도 0.5→0.72, 테두리 강화로 흰 텍스트 대비 확보
- 글라스 테마 전용 텍스트 그림자(glassTextShadow) 추가 — 홈 위젯 5종 셀 콘텐츠에 적용
- widgetRenderingMode != .fullColor(홈 화면 틴트/클리어)일 때 커스텀 배경·강제
  컬러 스킴을 끄고 시스템 바이브런트 렌더링에 맡기도록 분기
- 잠금화면 위젯: AccessoryWidgetBackground + widgetAccentable + .primary 전경색으로
  비브런트/악센트 렌더링에서 시인성 확보
- 미리보기 하네스: 글라스 테마가 시스템 컬러 스킴을 따르도록 수정

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-10 21:18:43 +09:00
songyc macbook
ed8b52792a feat(widgets): 홈/잠금화면 위젯 6종 + Interactive Widgets (CLAUDE.md §8)
- 행동 실행(A): 소형1/중형3/대형4칸, Button(intent:)로 앱 없이 즉시 실행,
  측정 중 실시간 타이머 + 노란 테두리, 표시 기간(오늘/이번 주/이번 달) 옵션
- 목표 진행률(B): 하루/주간/월간 가로 진행바, 소형1/중형2/대형4
- 다짐 진행률(C): 원형 링 + 기간 옵션, 단일 행동 다짐은 눌러서 실행,
  '이하 유지'는 한도 지킴/초과로 표현
- 다짐 현황(D): 목표명 + 원형 링 그리드 (소형 2x2 / 중형 최대 8 / 대형 목표 2개)
- 통계: 행동 최대 3개 꺾은선 그래프, 앱 통계 탭과 동일 산식·색,
  소형은 '한 달 일별' 제외 (스펙 §8.3)
- 잠금화면: circular/rectangular/inline, 표시 방식 3종(게이지/숫자/다짐 점)
- 전 위젯 프리미엄 게이트 (미결제 시 잠금 안내)
- DEBUG 미리보기 화면: -widgetPreview YES|lock, -widgetPreviewScroll B|C|D|S

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-10 08:59:47 +09:00