mycode/myApp/HaruDanim/Widgets/WidgetTheme.swift
2026-07-13 01:55:54 +09:00

141 lines
5.1 KiB
Swift

//
// WidgetTheme.swift
// Haru_DanimWidgets
//
// (CLAUDE.md §8.1)
// - (Intent) [ / / ] .
// - containerBackground(iOS 17+) , /( )
// ·
// (Color.clear)
// (white-on-white) .
//
import SwiftUI
import WidgetKit
import AppIntents
// MARK: - ( )
enum WidgetThemeOption: String, AppEnum {
case matchApp
case light
case dark
static let typeDisplayRepresentation = TypeDisplayRepresentation(name: "테마")
static let caseDisplayRepresentations: [WidgetThemeOption: DisplayRepresentation] = [
.matchApp: "앱 설정과 일치",
.light: "라이트 모드 고정",
.dark: "다크 모드 고정",
]
///
var scheme: ColorScheme {
switch self {
case .matchApp: return WidgetAppearance.appScheme
case .light: return .light
case .dark: return .dark
}
}
}
enum WidgetAppearance {
/// ("light" | "dark")
static var appScheme: ColorScheme {
let raw = AppGroup.defaults.string(forKey: SettingsKeys.theme)
?? UserDefaults.standard.string(forKey: SettingsKeys.theme) ?? "light"
return raw == "dark" ? .dark : .light
}
}
// MARK: -
struct WidgetThemeModifier: ViewModifier {
@Environment(\.widgetRenderingMode) private var renderingMode
let theme: WidgetThemeOption
func body(content: Content) -> some View {
if renderingMode != .fullColor {
// /( ) : ·
// ()
content
.containerBackground(for: .widget) { Color.clear }
} else {
let scheme = theme.scheme
content
.environment(\.colorScheme, scheme)
.containerBackground(for: .widget) {
// containerBackground ( )
//
AppTheme.background
.environment(\.colorScheme, scheme)
}
}
}
}
extension View {
/// ( + containerBackground )
func widgetAppTheme(_ theme: WidgetThemeOption = .matchApp) -> some View {
modifier(WidgetThemeModifier(theme: theme))
}
}
// MARK: -
/// ().
/// fullBleed = (ContainerRelativeShape)
/// /( )
/// white-on-white ,
/// ( 0.2 ).
struct WidgetCellBackground: View {
@Environment(\.widgetRenderingMode) private var renderingMode
var fullBleed = false
private var fill: AnyShapeStyle {
renderingMode == .fullColor
? AnyShapeStyle(AppTheme.surface)
: AnyShapeStyle(Color.white.opacity(0.14))
}
var body: some View {
if fullBleed {
ContainerRelativeShape().fill(fill)
} else {
RoundedRectangle(cornerRadius: 14, style: .continuous).fill(fill)
}
}
}
///
struct WidgetTintedCellBackground: View {
let color: Color
var fullBleed = false
var body: some View {
if fullBleed {
ContainerRelativeShape().fill(color)
} else {
RoundedRectangle(cornerRadius: 14, style: .continuous).fill(color)
}
}
}
/// / ( )
struct WidgetBlankCellView: View {
var fullBleed = false
var body: some View {
Group {
if fullBleed {
ContainerRelativeShape()
.strokeBorder(style: StrokeStyle(lineWidth: 1.5, dash: [5, 4]))
} else {
RoundedRectangle(cornerRadius: 14, style: .continuous)
.strokeBorder(style: StrokeStyle(lineWidth: 1.5, dash: [5, 4]))
}
}
.foregroundStyle(.quaternary)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}