Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2026-01-31 11:54:14 -06:00
parent 74ece5a71a
commit 7bd01554de
9 changed files with 125 additions and 119 deletions

View File

@ -12,14 +12,25 @@ import Bedrock
struct ContentView: View { struct ContentView: View {
// MARK: - Body // 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 { var body: some View {
TabView { TabView(selection: $selectedTab) {
NavigationStack { NavigationStack {
ClockView() ClockView(viewModel: clockViewModel)
} }
.tabItem { .tabItem {
Label("Clock", systemImage: "clock") Label("Clock", systemImage: "clock")
} }
.tag(Tab.clock)
NavigationStack { NavigationStack {
AlarmView() AlarmView()
@ -27,6 +38,7 @@ struct ContentView: View {
.tabItem { .tabItem {
Label("Alarms", systemImage: "alarm") Label("Alarms", systemImage: "alarm")
} }
.tag(Tab.alarms)
NavigationStack { NavigationStack {
NoiseView() NoiseView()
@ -34,6 +46,19 @@ struct ContentView: View {
.tabItem { .tabItem {
Label("Noise", systemImage: "waveform") 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) .accentColor(AppAccent.primary)
.background(Color.Branding.primary.ignoresSafeArea()) .background(Color.Branding.primary.ignoresSafeArea())

View File

@ -6,6 +6,7 @@
// //
import SwiftUI import SwiftUI
import Bedrock
/// Main alarm management view /// Main alarm management view
struct AlarmView: View { struct AlarmView: View {
@ -26,6 +27,8 @@ struct AlarmView: View {
.onTapGesture { .onTapGesture {
showAddAlarm = true showAddAlarm = true
} }
.frame(maxWidth: Design.Size.maxContentWidthPortrait)
.frame(maxWidth: .infinity, alignment: .center)
} else { } else {
List { List {
ForEach(viewModel.alarms) { alarm in ForEach(viewModel.alarms) { alarm in
@ -43,6 +46,8 @@ struct AlarmView: View {
} }
.onDelete(perform: deleteAlarm) .onDelete(perform: deleteAlarm)
} }
.frame(maxWidth: Design.Size.maxContentWidthPortrait)
.frame(maxWidth: .infinity, alignment: .center)
} }
} }
.navigationTitle("Alarms") .navigationTitle("Alarms")

View File

@ -354,7 +354,7 @@ class ClockStyle: Codable, Equatable {
// Color-aware brightness adaptation // Color-aware brightness adaptation
let colorAwareBrightness = getColorAwareBrightness() 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 return colorAwareBrightness
} }

View File

@ -61,15 +61,15 @@ class AmbientLightService {
let previousBrightness = UIScreen.main.brightness let previousBrightness = UIScreen.main.brightness
Design.debugLog("[ambient] AmbientLightService.setBrightness:") Design.debugLog("[ambient] AmbientLightService.setBrightness:")
Design.debugLog("[ambient] - Requested brightness: \(String(format: \"%.2f\", brightness))") Design.debugLog("[ambient] - Requested brightness: \(String(format: "%.2f", brightness))")
Design.debugLog("[ambient] - Clamped brightness: \(String(format: \"%.2f\", clampedBrightness))") Design.debugLog("[ambient] - Clamped brightness: \(String(format: "%.2f", clampedBrightness))")
Design.debugLog("[ambient] - Previous screen brightness: \(String(format: \"%.2f\", previousBrightness))") Design.debugLog("[ambient] - Previous screen brightness: \(String(format: "%.2f", previousBrightness))")
UIScreen.main.brightness = clampedBrightness UIScreen.main.brightness = clampedBrightness
currentBrightness = clampedBrightness currentBrightness = clampedBrightness
Design.debugLog("[ambient] - New screen brightness: \(String(format: \"%.2f\", UIScreen.main.brightness))") Design.debugLog("[ambient] - New screen brightness: \(String(format: "%.2f", UIScreen.main.brightness))")
Design.debugLog("[ambient] - Service currentBrightness: \(String(format: \"%.2f\", currentBrightness))") Design.debugLog("[ambient] - Service currentBrightness: \(String(format: "%.2f", currentBrightness))")
} }
/// Get current screen brightness /// Get current screen brightness
@ -90,7 +90,7 @@ class AmbientLightService {
let previousBrightness = currentBrightness let previousBrightness = currentBrightness
currentBrightness = newBrightness 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 // Notify that brightness changed
onBrightnessChange?() onBrightnessChange?()

View File

@ -221,16 +221,16 @@ class ClockViewModel {
Design.debugLog("[brightness] Auto Brightness Debug:") Design.debugLog("[brightness] Auto Brightness Debug:")
Design.debugLog("[brightness] - Auto brightness enabled: \(style.autoBrightness)") Design.debugLog("[brightness] - Auto brightness enabled: \(style.autoBrightness)")
Design.debugLog("[brightness] - Current screen brightness: \(String(format: \"%.2f\", currentScreenBrightness))") Design.debugLog("[brightness] - Current screen brightness: \(String(format: "%.2f", currentScreenBrightness))")
Design.debugLog("[brightness] - Target brightness: \(String(format: \"%.2f\", targetBrightness))") Design.debugLog("[brightness] - Target brightness: \(String(format: "%.2f", targetBrightness))")
Design.debugLog("[brightness] - Night mode active: \(isNightMode)") Design.debugLog("[brightness] - Night mode active: \(isNightMode)")
Design.debugLog("[brightness] - Color theme: \(style.selectedColorTheme)") 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) ambientLightService.setBrightness(targetBrightness)
Design.debugLog("[brightness] - Brightness set to: \(String(format: \"%.2f\", 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] - Actual screen brightness now: \(String(format: "%.2f", UIScreen.main.brightness))")
Design.debugLog("[brightness] ---") Design.debugLog("[brightness] ---")
} else { } else {
Design.debugLog("[brightness] Auto Brightness: DISABLED") Design.debugLog("[brightness] Auto Brightness: DISABLED")

View File

@ -18,7 +18,6 @@ struct ClockSettingsView: View {
@State private var digitColor: Color = .white @State private var digitColor: Color = .white
@State private var backgroundColor: Color = .black @State private var backgroundColor: Color = .black
@State private var showAdvancedSettings = false @State private var showAdvancedSettings = false
@Environment(\.dismiss) private var dismiss
// MARK: - Init // MARK: - Init
init(style: ClockStyle, onCommit: @escaping (ClockStyle) -> Void) { init(style: ClockStyle, onCommit: @escaping (ClockStyle) -> Void) {
@ -28,7 +27,6 @@ struct ClockSettingsView: View {
// MARK: - Body // MARK: - Body
var body: some View { var body: some View {
NavigationStack {
ScrollView { ScrollView {
VStack(spacing: Design.Spacing.xxLarge) { VStack(spacing: Design.Spacing.xxLarge) {
BasicAppearanceSection( BasicAppearanceSection(
@ -96,6 +94,8 @@ struct ClockSettingsView: View {
} }
#endif #endif
} }
.frame(maxWidth: Design.Size.maxContentWidthPortrait)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.horizontal, Design.Spacing.large) .padding(.horizontal, Design.Spacing.large)
.padding(.top, Design.Spacing.large) .padding(.top, Design.Spacing.large)
.padding(.bottom, Design.Spacing.xxxLarge) .padding(.bottom, Design.Spacing.xxxLarge)
@ -103,12 +103,6 @@ struct ClockSettingsView: View {
.background(AppSurface.primary) .background(AppSurface.primary)
.navigationTitle("Clock Settings") .navigationTitle("Clock Settings")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Done") { dismiss() }
.foregroundStyle(AppAccent.primary)
}
}
.onAppear { .onAppear {
digitColor = Color(hex: style.digitColorHex) ?? .white digitColor = Color(hex: style.digitColorHex) ?? .white
backgroundColor = Color(hex: style.backgroundHex) ?? .black backgroundColor = Color(hex: style.backgroundHex) ?? .black
@ -117,7 +111,6 @@ struct ClockSettingsView: View {
onCommit(style) onCommit(style)
} }
} }
}
} }
// MARK: - Preview // MARK: - Preview

View File

@ -12,8 +12,7 @@ import Bedrock
struct ClockView: View { struct ClockView: View {
// MARK: - Properties // MARK: - Properties
@State private var viewModel = ClockViewModel() @Bindable var viewModel: ClockViewModel
@State private var showSettings = false
@State private var showFullScreenHint = false @State private var showFullScreenHint = false
// MARK: - Body // MARK: - Body
@ -43,20 +42,10 @@ struct ClockView: View {
} }
.ignoresSafeArea(.all, edges: viewModel.isDisplayMode ? .bottom : []) .ignoresSafeArea(.all, edges: viewModel.isDisplayMode ? .bottom : [])
.statusBarHidden(viewModel.isDisplayMode) .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 { .overlay {
// Toolbar overlay // Toolbar overlay
ClockToolbar( ClockToolbar(
isDisplayMode: viewModel.isDisplayMode, isDisplayMode: viewModel.isDisplayMode,
onSettingsTap: { showSettings = true },
onFullScreenTap: { onFullScreenTap: {
if !viewModel.isDisplayMode { if !viewModel.isDisplayMode {
viewModel.toggleDisplayMode() viewModel.toggleDisplayMode()
@ -87,7 +76,7 @@ struct ClockView: View {
// MARK: - Preview // MARK: - Preview
#Preview { #Preview {
NavigationStack { NavigationStack {
ClockView() ClockView(viewModel: ClockViewModel())
} }
.frame(width: 400, height: 600) .frame(width: 400, height: 600)
.background(Color.black) .background(Color.black)

View File

@ -12,7 +12,6 @@ struct ClockToolbar: View {
// MARK: - Properties // MARK: - Properties
let isDisplayMode: Bool let isDisplayMode: Bool
let onSettingsTap: () -> Void
let onFullScreenTap: () -> Void let onFullScreenTap: () -> Void
// MARK: - Body // MARK: - Body
@ -30,15 +29,6 @@ struct ClockToolbar: View {
.transition(.opacity) .transition(.opacity)
} }
.accessibilityLabel("Enter Full Screen Mode") .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 { NavigationStack {
ClockToolbar( ClockToolbar(
isDisplayMode: false, isDisplayMode: false,
onSettingsTap: {},
onFullScreenTap: {} onFullScreenTap: {}
) )
} }

View File

@ -27,7 +27,9 @@ struct NoiseView: View {
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
let isLandscape = geometry.size.width > geometry.size.height let isLandscape = geometry.size.width > geometry.size.height
let maxWidth = isLandscape ? Design.Size.maxContentWidthLandscape : Design.Size.maxContentWidthPortrait
Group {
if isLandscape { if isLandscape {
// Landscape layout: Player on left, sounds on right // Landscape layout: Player on left, sounds on right
landscapeLayout landscapeLayout
@ -36,6 +38,9 @@ struct NoiseView: View {
portraitLayout portraitLayout
} }
} }
.frame(maxWidth: maxWidth)
.frame(maxWidth: .infinity, alignment: .center)
}
.animation(.easeInOut(duration: 0.3), value: selectedSound) .animation(.easeInOut(duration: 0.3), value: selectedSound)
} }