Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
74ece5a71a
commit
7bd01554de
@ -12,14 +12,25 @@ import Bedrock
|
||||
struct ContentView: View {
|
||||
|
||||
// MARK: - Body
|
||||
private enum Tab: Hashable {
|
||||
case clock
|
||||
case alarms
|
||||
case noise
|
||||
case settings
|
||||
}
|
||||
|
||||
@State private var selectedTab: Tab = .clock
|
||||
@State private var clockViewModel = ClockViewModel()
|
||||
|
||||
var body: some View {
|
||||
TabView {
|
||||
TabView(selection: $selectedTab) {
|
||||
NavigationStack {
|
||||
ClockView()
|
||||
ClockView(viewModel: clockViewModel)
|
||||
}
|
||||
.tabItem {
|
||||
Label("Clock", systemImage: "clock")
|
||||
}
|
||||
.tag(Tab.clock)
|
||||
|
||||
NavigationStack {
|
||||
AlarmView()
|
||||
@ -27,6 +38,7 @@ struct ContentView: View {
|
||||
.tabItem {
|
||||
Label("Alarms", systemImage: "alarm")
|
||||
}
|
||||
.tag(Tab.alarms)
|
||||
|
||||
NavigationStack {
|
||||
NoiseView()
|
||||
@ -34,6 +46,19 @@ struct ContentView: View {
|
||||
.tabItem {
|
||||
Label("Noise", systemImage: "waveform")
|
||||
}
|
||||
.tag(Tab.noise)
|
||||
|
||||
NavigationStack {
|
||||
ClockSettingsView(style: clockViewModel.style) { newStyle in
|
||||
clockViewModel.updateStyle(newStyle)
|
||||
}
|
||||
.navigationTitle("Settings")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
.tabItem {
|
||||
Label("Settings", systemImage: "gearshape")
|
||||
}
|
||||
.tag(Tab.settings)
|
||||
}
|
||||
.accentColor(AppAccent.primary)
|
||||
.background(Color.Branding.primary.ignoresSafeArea())
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Bedrock
|
||||
|
||||
/// Main alarm management view
|
||||
struct AlarmView: View {
|
||||
@ -26,6 +27,8 @@ struct AlarmView: View {
|
||||
.onTapGesture {
|
||||
showAddAlarm = true
|
||||
}
|
||||
.frame(maxWidth: Design.Size.maxContentWidthPortrait)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
} else {
|
||||
List {
|
||||
ForEach(viewModel.alarms) { alarm in
|
||||
@ -43,6 +46,8 @@ struct AlarmView: View {
|
||||
}
|
||||
.onDelete(perform: deleteAlarm)
|
||||
}
|
||||
.frame(maxWidth: Design.Size.maxContentWidthPortrait)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Alarms")
|
||||
|
||||
@ -354,7 +354,7 @@ class ClockStyle: Codable, Equatable {
|
||||
|
||||
// Color-aware brightness adaptation
|
||||
let colorAwareBrightness = getColorAwareBrightness()
|
||||
Design.debugLog("[brightness] effectiveBrightness: Color-aware brightness = \(String(format: \"%.2f\", colorAwareBrightness))")
|
||||
Design.debugLog("[brightness] effectiveBrightness: Color-aware brightness = \(String(format: "%.2f", colorAwareBrightness))")
|
||||
return colorAwareBrightness
|
||||
}
|
||||
|
||||
|
||||
@ -61,15 +61,15 @@ class AmbientLightService {
|
||||
let previousBrightness = UIScreen.main.brightness
|
||||
|
||||
Design.debugLog("[ambient] AmbientLightService.setBrightness:")
|
||||
Design.debugLog("[ambient] - Requested brightness: \(String(format: \"%.2f\", brightness))")
|
||||
Design.debugLog("[ambient] - Clamped brightness: \(String(format: \"%.2f\", clampedBrightness))")
|
||||
Design.debugLog("[ambient] - Previous screen brightness: \(String(format: \"%.2f\", previousBrightness))")
|
||||
Design.debugLog("[ambient] - Requested brightness: \(String(format: "%.2f", brightness))")
|
||||
Design.debugLog("[ambient] - Clamped brightness: \(String(format: "%.2f", clampedBrightness))")
|
||||
Design.debugLog("[ambient] - Previous screen brightness: \(String(format: "%.2f", previousBrightness))")
|
||||
|
||||
UIScreen.main.brightness = clampedBrightness
|
||||
currentBrightness = clampedBrightness
|
||||
|
||||
Design.debugLog("[ambient] - New screen brightness: \(String(format: \"%.2f\", UIScreen.main.brightness))")
|
||||
Design.debugLog("[ambient] - Service currentBrightness: \(String(format: \"%.2f\", currentBrightness))")
|
||||
Design.debugLog("[ambient] - New screen brightness: \(String(format: "%.2f", UIScreen.main.brightness))")
|
||||
Design.debugLog("[ambient] - Service currentBrightness: \(String(format: "%.2f", currentBrightness))")
|
||||
}
|
||||
|
||||
/// Get current screen brightness
|
||||
@ -90,7 +90,7 @@ class AmbientLightService {
|
||||
let previousBrightness = currentBrightness
|
||||
currentBrightness = newBrightness
|
||||
|
||||
Design.debugLog("[ambient] AmbientLightService: Brightness changed from \(String(format: \"%.2f\", previousBrightness)) to \(String(format: \"%.2f\", newBrightness))")
|
||||
Design.debugLog("[ambient] AmbientLightService: Brightness changed from \(String(format: "%.2f", previousBrightness)) to \(String(format: "%.2f", newBrightness))")
|
||||
|
||||
// Notify that brightness changed
|
||||
onBrightnessChange?()
|
||||
|
||||
@ -221,16 +221,16 @@ class ClockViewModel {
|
||||
|
||||
Design.debugLog("[brightness] Auto Brightness Debug:")
|
||||
Design.debugLog("[brightness] - Auto brightness enabled: \(style.autoBrightness)")
|
||||
Design.debugLog("[brightness] - Current screen brightness: \(String(format: \"%.2f\", currentScreenBrightness))")
|
||||
Design.debugLog("[brightness] - Target brightness: \(String(format: \"%.2f\", targetBrightness))")
|
||||
Design.debugLog("[brightness] - Current screen brightness: \(String(format: "%.2f", currentScreenBrightness))")
|
||||
Design.debugLog("[brightness] - Target brightness: \(String(format: "%.2f", targetBrightness))")
|
||||
Design.debugLog("[brightness] - Night mode active: \(isNightMode)")
|
||||
Design.debugLog("[brightness] - Color theme: \(style.selectedColorTheme)")
|
||||
Design.debugLog("[brightness] - Ambient light threshold: \(String(format: \"%.2f\", style.ambientLightThreshold))")
|
||||
Design.debugLog("[brightness] - Ambient light threshold: \(String(format: "%.2f", style.ambientLightThreshold))")
|
||||
|
||||
ambientLightService.setBrightness(targetBrightness)
|
||||
|
||||
Design.debugLog("[brightness] - Brightness set to: \(String(format: \"%.2f\", targetBrightness))")
|
||||
Design.debugLog("[brightness] - Actual screen brightness now: \(String(format: \"%.2f\", UIScreen.main.brightness))")
|
||||
Design.debugLog("[brightness] - Brightness set to: \(String(format: "%.2f", targetBrightness))")
|
||||
Design.debugLog("[brightness] - Actual screen brightness now: \(String(format: "%.2f", UIScreen.main.brightness))")
|
||||
Design.debugLog("[brightness] ---")
|
||||
} else {
|
||||
Design.debugLog("[brightness] Auto Brightness: DISABLED")
|
||||
|
||||
@ -18,7 +18,6 @@ struct ClockSettingsView: View {
|
||||
@State private var digitColor: Color = .white
|
||||
@State private var backgroundColor: Color = .black
|
||||
@State private var showAdvancedSettings = false
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
// MARK: - Init
|
||||
init(style: ClockStyle, onCommit: @escaping (ClockStyle) -> Void) {
|
||||
@ -28,94 +27,88 @@ struct ClockSettingsView: View {
|
||||
|
||||
// MARK: - Body
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ScrollView {
|
||||
VStack(spacing: Design.Spacing.xxLarge) {
|
||||
BasicAppearanceSection(
|
||||
style: $style,
|
||||
digitColor: $digitColor,
|
||||
backgroundColor: $backgroundColor
|
||||
)
|
||||
ScrollView {
|
||||
VStack(spacing: Design.Spacing.xxLarge) {
|
||||
BasicAppearanceSection(
|
||||
style: $style,
|
||||
digitColor: $digitColor,
|
||||
backgroundColor: $backgroundColor
|
||||
)
|
||||
|
||||
BasicDisplaySection(style: $style)
|
||||
BasicDisplaySection(style: $style)
|
||||
|
||||
if showAdvancedSettings {
|
||||
AdvancedAppearanceSection(style: $style)
|
||||
if showAdvancedSettings {
|
||||
AdvancedAppearanceSection(style: $style)
|
||||
|
||||
FontSection(style: $style)
|
||||
FontSection(style: $style)
|
||||
|
||||
NightModeSection(style: $style)
|
||||
NightModeSection(style: $style)
|
||||
|
||||
OverlaySection(style: $style)
|
||||
OverlaySection(style: $style)
|
||||
|
||||
AdvancedDisplaySection(style: $style)
|
||||
}
|
||||
AdvancedDisplaySection(style: $style)
|
||||
}
|
||||
|
||||
SettingsSectionHeader(
|
||||
title: "Advanced",
|
||||
systemImage: "gearshape",
|
||||
SettingsSectionHeader(
|
||||
title: "Advanced",
|
||||
systemImage: "gearshape",
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
|
||||
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
|
||||
SettingsToggle(
|
||||
title: "Show Advanced Settings",
|
||||
subtitle: "Reveal additional customization options",
|
||||
isOn: $showAdvancedSettings,
|
||||
accentColor: AppAccent.primary
|
||||
)
|
||||
}
|
||||
|
||||
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
|
||||
SettingsToggle(
|
||||
title: "Show Advanced Settings",
|
||||
subtitle: "Reveal additional customization options",
|
||||
isOn: $showAdvancedSettings,
|
||||
accentColor: AppAccent.primary
|
||||
#if DEBUG
|
||||
SettingsSectionHeader(
|
||||
title: "Debug",
|
||||
systemImage: "ant.fill",
|
||||
accentColor: AppStatus.error
|
||||
)
|
||||
|
||||
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
|
||||
SettingsNavigationRow(
|
||||
title: "Icon Generator",
|
||||
subtitle: "Generate and save app icon",
|
||||
backgroundColor: AppSurface.primary
|
||||
) {
|
||||
IconGeneratorView(config: .noiseClock, appName: "TheNoiseClock")
|
||||
}
|
||||
|
||||
SettingsNavigationRow(
|
||||
title: "Branding Preview",
|
||||
subtitle: "Preview icon and launch screen",
|
||||
backgroundColor: AppSurface.primary
|
||||
) {
|
||||
BrandingPreviewView(
|
||||
iconConfig: .noiseClock,
|
||||
launchConfig: .noiseClock,
|
||||
appName: "TheNoiseClock"
|
||||
)
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
SettingsSectionHeader(
|
||||
title: "Debug",
|
||||
systemImage: "ant.fill",
|
||||
accentColor: AppStatus.error
|
||||
)
|
||||
|
||||
SettingsCard(backgroundColor: AppSurface.card, borderColor: AppBorder.subtle) {
|
||||
SettingsNavigationRow(
|
||||
title: "Icon Generator",
|
||||
subtitle: "Generate and save app icon",
|
||||
backgroundColor: AppSurface.primary
|
||||
) {
|
||||
IconGeneratorView(config: .noiseClock, appName: "TheNoiseClock")
|
||||
}
|
||||
|
||||
SettingsNavigationRow(
|
||||
title: "Branding Preview",
|
||||
subtitle: "Preview icon and launch screen",
|
||||
backgroundColor: AppSurface.primary
|
||||
) {
|
||||
BrandingPreviewView(
|
||||
iconConfig: .noiseClock,
|
||||
launchConfig: .noiseClock,
|
||||
appName: "TheNoiseClock"
|
||||
)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
.padding(.horizontal, Design.Spacing.large)
|
||||
.padding(.top, Design.Spacing.large)
|
||||
.padding(.bottom, Design.Spacing.xxxLarge)
|
||||
}
|
||||
.background(AppSurface.primary)
|
||||
.navigationTitle("Clock Settings")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button("Done") { dismiss() }
|
||||
.foregroundStyle(AppAccent.primary)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
digitColor = Color(hex: style.digitColorHex) ?? .white
|
||||
backgroundColor = Color(hex: style.backgroundHex) ?? .black
|
||||
}
|
||||
.onDisappear {
|
||||
onCommit(style)
|
||||
#endif
|
||||
}
|
||||
.frame(maxWidth: Design.Size.maxContentWidthPortrait)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.padding(.horizontal, Design.Spacing.large)
|
||||
.padding(.top, Design.Spacing.large)
|
||||
.padding(.bottom, Design.Spacing.xxxLarge)
|
||||
}
|
||||
.background(AppSurface.primary)
|
||||
.navigationTitle("Clock Settings")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.onAppear {
|
||||
digitColor = Color(hex: style.digitColorHex) ?? .white
|
||||
backgroundColor = Color(hex: style.backgroundHex) ?? .black
|
||||
}
|
||||
.onDisappear {
|
||||
onCommit(style)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,8 +12,7 @@ import Bedrock
|
||||
struct ClockView: View {
|
||||
|
||||
// MARK: - Properties
|
||||
@State private var viewModel = ClockViewModel()
|
||||
@State private var showSettings = false
|
||||
@Bindable var viewModel: ClockViewModel
|
||||
@State private var showFullScreenHint = false
|
||||
|
||||
// MARK: - Body
|
||||
@ -43,20 +42,10 @@ struct ClockView: View {
|
||||
}
|
||||
.ignoresSafeArea(.all, edges: viewModel.isDisplayMode ? .bottom : [])
|
||||
.statusBarHidden(viewModel.isDisplayMode)
|
||||
.sheet(isPresented: $showSettings) {
|
||||
ClockSettingsView(style: viewModel.style) { newStyle in
|
||||
viewModel.updateStyle(newStyle)
|
||||
}
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.hidden)
|
||||
.presentationBackgroundInteraction(.enabled)
|
||||
.presentationBackground(AppSurface.overlay)
|
||||
}
|
||||
.overlay {
|
||||
// Toolbar overlay
|
||||
ClockToolbar(
|
||||
isDisplayMode: viewModel.isDisplayMode,
|
||||
onSettingsTap: { showSettings = true },
|
||||
onFullScreenTap: {
|
||||
if !viewModel.isDisplayMode {
|
||||
viewModel.toggleDisplayMode()
|
||||
@ -87,7 +76,7 @@ struct ClockView: View {
|
||||
// MARK: - Preview
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
ClockView()
|
||||
ClockView(viewModel: ClockViewModel())
|
||||
}
|
||||
.frame(width: 400, height: 600)
|
||||
.background(Color.black)
|
||||
|
||||
@ -12,7 +12,6 @@ struct ClockToolbar: View {
|
||||
|
||||
// MARK: - Properties
|
||||
let isDisplayMode: Bool
|
||||
let onSettingsTap: () -> Void
|
||||
let onFullScreenTap: () -> Void
|
||||
|
||||
// MARK: - Body
|
||||
@ -30,15 +29,6 @@ struct ClockToolbar: View {
|
||||
.transition(.opacity)
|
||||
}
|
||||
.accessibilityLabel("Enter Full Screen Mode")
|
||||
|
||||
Button {
|
||||
onSettingsTap()
|
||||
} label: {
|
||||
Image(systemName: "gear")
|
||||
.font(.title2)
|
||||
.transition(.opacity)
|
||||
}
|
||||
.accessibilityLabel("Clock Settings")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,7 +42,6 @@ struct ClockToolbar: View {
|
||||
NavigationStack {
|
||||
ClockToolbar(
|
||||
isDisplayMode: false,
|
||||
onSettingsTap: {},
|
||||
onFullScreenTap: {}
|
||||
)
|
||||
}
|
||||
|
||||
@ -27,14 +27,19 @@ struct NoiseView: View {
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
let isLandscape = geometry.size.width > geometry.size.height
|
||||
let maxWidth = isLandscape ? Design.Size.maxContentWidthLandscape : Design.Size.maxContentWidthPortrait
|
||||
|
||||
if isLandscape {
|
||||
// Landscape layout: Player on left, sounds on right
|
||||
landscapeLayout
|
||||
} else {
|
||||
// Portrait layout: Stacked vertically
|
||||
portraitLayout
|
||||
Group {
|
||||
if isLandscape {
|
||||
// Landscape layout: Player on left, sounds on right
|
||||
landscapeLayout
|
||||
} else {
|
||||
// Portrait layout: Stacked vertically
|
||||
portraitLayout
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: maxWidth)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
.animation(.easeInOut(duration: 0.3), value: selectedSound)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user