songyc macbook 417070bde7 chore: rewrite CLAUDE.md from actual code, plus safe hardening fixes
CLAUDE.md v2.0 — 기획서(v1.0)를 폐기하고 실제 구현 기준의 현행 명세로 전면 재작성:
프로젝트 구조·빌드/검증 루틴·도메인 모델(CloudKit 규칙)·집계/판정 규칙·데이터 계층
(LocalPrefs/DataChange)·화면별 상세·내보내기·프리미엄/StoreKit·위젯 6종·워치·시리·
DEBUG 런치 인자·작업 컨벤션까지 새 세션이 이 문서만으로 파악 가능하게 정리.

동작 보존 범위의 안전 수정 3건:
- Color.hexString: 와이드 컬러(P3) 성분을 0...1로 클램프 — 음수/1 초과 값이
  %02X를 거치며 자릿수 깨진 hex가 태그·목표 색으로 저장되던 잠재 버그 방지
- 일기 타임테이블 필터: 선택 즉시 명시적 save — 캘린더 일정 선택 경로와 동일하게
  영속을 보장 (autosave 의존 제거)
- 통계 평균 "%.1f회"가 String(format:)이라 영어·일본어에서도 '회'로 노출되던 것을
  Format.countAverage로 지역화 (en "times" / ja "回", 카탈로그 동기화 포함)

Debug·Store(Release) 스킴 빌드 검증 완료.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
2026-07-13 18:45:53 +09:00

61 lines
2.3 KiB
Swift

//
// Theme.swift
// Haru_Danim
//
// (CLAUDE.md §5.2)
//
import SwiftUI
import UIKit
extension Color {
/// "#RRGGBB" hex
init(hex: String) {
let cleaned = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var value: UInt64 = 0
Scanner(string: cleaned).scanHexInt64(&value)
let r = Double((value >> 16) & 0xFF) / 255
let g = Double((value >> 8) & 0xFF) / 255
let b = Double(value & 0xFF) / 255
self.init(red: r, green: g, blue: b)
}
/// /
init(light: Color, dark: Color) {
self.init(uiColor: UIColor { traits in
traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light)
})
}
/// "#RRGGBB" hex .
/// (P3) getRed 0...1
/// /1 %02X 릿 hex("#FFFFFFE6") .
var hexString: String {
let ui = UIColor(self)
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
ui.getRed(&r, green: &g, blue: &b, alpha: &a)
func component(_ value: CGFloat) -> Int {
Int(round(min(max(value, 0), 1) * 255))
}
return String(format: "#%02X%02X%02X", component(r), component(g), component(b))
}
}
enum AppTheme {
/// Primary Green: /
static let green = Color(light: Color(hex: "#2F6B4F"), dark: Color(hex: "#7FBF9E"))
/// Accent Yellow: /
static let yellow = Color(light: Color(hex: "#D9A621"), dark: Color(hex: "#E8C558"))
/// Background: /
static let background = Color(light: Color(hex: "#FAFAF6"), dark: Color(hex: "#111512"))
///
static let surface = Color(light: .white, dark: Color(hex: "#1B211D"))
/// (/ )
static let tagPresets: [String] = [
"#2F6B4F", "#D9A621", "#4A7A9D", "#9D5B4A",
"#7A5C9D", "#4F8A8B", "#C06C84", "#6B705C",
"#B5651D", "#3D5A80", "#8D6B94", "#588157",
]
}