From 392f5b99588011ef45f59c4c54c29c6068a843c9 Mon Sep 17 00:00:00 2001 From: codebymini Date: Sat, 25 Oct 2025 23:38:35 +0200 Subject: [PATCH] Fix alignment on Snooze button when using iOS Display Zoom --- LoopFollow/Snoozer/SnoozerView.swift | 106 +++++++++++++++------------ 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/LoopFollow/Snoozer/SnoozerView.swift b/LoopFollow/Snoozer/SnoozerView.swift index 1e78ba1cc..a275e9150 100644 --- a/LoopFollow/Snoozer/SnoozerView.swift +++ b/LoopFollow/Snoozer/SnoozerView.swift @@ -95,6 +95,56 @@ struct SnoozerView: View { .transition(.move(edge: .top).combined(with: .opacity)) } } + .overlay(alignment: .bottom) { + if let alarm = vm.activeAlarm { + VStack(spacing: 16) { + // Alarm name at the top + Text(alarm.name) + .font(.system(size: 30, weight: .semibold)) + .foregroundColor(.white) + .lineLimit(1) + .minimumScaleFactor(0.5) + .padding(.top, 20) + + Divider() + + // Snooze duration controls + if alarm.type.snoozeTimeUnit != .none { + HStack { + VStack(alignment: .leading, spacing: 4) { + Text("Snooze for") + .font(.headline) + Text("\(vm.snoozeUnits) \(vm.timeUnitLabel)") + .font(.title3).bold() + } + Spacer() + Stepper("", value: $vm.snoozeUnits, + in: alarm.type.snoozeRange, + step: alarm.type.snoozeStep) + .labelsHidden() + } + .padding(.horizontal, 24) + } + + // Snooze button anchored to tab bar edge (bottom of VStack) + Button(action: vm.snoozeTapped) { + Text(vm.snoozeUnits == 0 ? "Acknowledge" : "Snooze") + .font(.system(size: 30, weight: .bold)) + .frame(maxWidth: .infinity, minHeight: 60) + .background(Color.orange) + .foregroundColor(.white) + .clipShape(Capsule()) + } + .padding(.horizontal, 24) + .padding(.bottom, 20) + } + .background(.ultraThinMaterial) + .cornerRadius(20, corners: [.topLeft, .topRight]) + .transition(.move(edge: .bottom).combined(with: .opacity)) + .animation(.spring(), value: vm.activeAlarm != nil) + .padding(.bottom, 0) // Anchor directly to bottom edge + } + } .sheet(isPresented: $showDatePickerDate) { datePickerSheetDate() } .sheet(isPresented: $showDatePickerTime) { datePickerSheetTime() } } @@ -171,57 +221,23 @@ struct SnoozerView: View { .padding(.bottom, 8) } - if let alarm = vm.activeAlarm { - VStack(spacing: 16) { - Text(alarm.name) - .font(.system(size: 30, weight: .semibold)) - .foregroundColor(.white) - .lineLimit(1) - .minimumScaleFactor(0.5) - .padding(.top, 20) - Divider() - - if alarm.type.snoozeTimeUnit != .none { - HStack { - VStack(alignment: .leading, spacing: 4) { - Text("Snooze for") - .font(.headline) - Text("\(vm.snoozeUnits) \(vm.timeUnitLabel)") - .font(.title3).bold() - } - Spacer() - Stepper("", value: $vm.snoozeUnits, - in: alarm.type.snoozeRange, - step: alarm.type.snoozeStep) - .labelsHidden() - } - .padding(.horizontal, 24) - } + if snoozerEmoji.value { + TimelineView(.periodic(from: .now, by: 1)) { context in + VStack(spacing: 4) { + Text(bgEmoji) + .font(.system(size: 128)) + .minimumScaleFactor(0.5) - Button(action: vm.snoozeTapped) { - Text(vm.snoozeUnits == 0 ? "Acknowledge" : "Snooze") - .font(.system(size: 30, weight: .bold)) - .frame(maxWidth: .infinity, minHeight: 60) - .background(Color.orange) + Text(context.date, format: Date.FormatStyle(date: .omitted, time: .shortened)) + .font(.system(size: 70)) + .minimumScaleFactor(0.5) .foregroundColor(.white) - .clipShape(Capsule()) + .frame(height: 78) } - .padding(.horizontal, 24) - .padding(.bottom, 20) } - .background(.ultraThinMaterial) - .cornerRadius(20, corners: [.topLeft, .topRight]) - .transition(.move(edge: .bottom).combined(with: .opacity)) - .animation(.spring(), value: vm.activeAlarm != nil) } else { TimelineView(.periodic(from: .now, by: 1)) { context in VStack(spacing: 4) { - if snoozerEmoji.value { - Text(bgEmoji) - .font(.system(size: 128)) - .minimumScaleFactor(0.5) - } - Text(context.date, format: Date.FormatStyle(date: .omitted, time: .shortened)) .font(.system(size: 70)) .minimumScaleFactor(0.5) @@ -229,8 +245,8 @@ struct SnoozerView: View { .frame(height: 78) } } - Spacer() } + Spacer() } }