|
|
@@ -9,6 +9,8 @@
|
|
|
import SwiftUI
|
|
|
|
|
|
struct SnoozerView: View {
|
|
|
+ @StateObject private var vm = SnoozerViewModel()
|
|
|
+
|
|
|
@ObservedObject var minAgoText = Observable.shared.minAgoText
|
|
|
@ObservedObject var bgText = Observable.shared.bgText
|
|
|
@ObservedObject var bgTextColor = Observable.shared.bgTextColor
|
|
|
@@ -16,37 +18,26 @@ struct SnoozerView: View {
|
|
|
@ObservedObject var deltaText = Observable.shared.deltaText
|
|
|
@ObservedObject var bgStale = Observable.shared.bgStale
|
|
|
|
|
|
- @Binding var snoozeMinutes: Int
|
|
|
- var onSnooze: () -> Void
|
|
|
-
|
|
|
var body: some View {
|
|
|
GeometryReader { geo in
|
|
|
- ZStack {
|
|
|
- Color.black
|
|
|
- .edgesIgnoringSafeArea(.all)
|
|
|
-
|
|
|
- Group {
|
|
|
- if geo.size.width > geo.size.height {
|
|
|
- // Landscape: two columns
|
|
|
- HStack(spacing: 0) {
|
|
|
- leftColumn
|
|
|
- rightColumn
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Portrait: single column
|
|
|
- VStack(spacing: 0) {
|
|
|
- leftColumn
|
|
|
- rightColumn
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .frame(width: geo.size.width, height: geo.size.height)
|
|
|
- }
|
|
|
+ Color.black.ignoresSafeArea()
|
|
|
+ .overlay(contentColumn(size: geo.size))
|
|
|
+ .animation(.easeInOut, value: vm.activeAlarm != nil)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // MARK: – Layout helper
|
|
|
+ @ViewBuilder private func contentColumn(size: CGSize) -> some View {
|
|
|
+ if size.width > size.height { // landscape
|
|
|
+ HStack(spacing: 0) { leftPanel ; rightPanel }
|
|
|
+ } else { // portrait
|
|
|
+ VStack(spacing: 0) { leftPanel ; rightPanel }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// MARK: - Left Column (BG / Direction / Delta / Age)
|
|
|
- private var leftColumn: some View {
|
|
|
+ private var leftPanel: some View {
|
|
|
VStack(spacing: 0) {
|
|
|
Text(bgText.value)
|
|
|
.font(.system(size: 220, weight: .black))
|
|
|
@@ -81,62 +72,58 @@ struct SnoozerView: View {
|
|
|
.padding(.horizontal, 16)
|
|
|
}
|
|
|
|
|
|
- // MARK: - Right Column (Clock/Alert + Snooze Controls)
|
|
|
- private var rightColumn: some View {
|
|
|
+ // MARK: – Right (Clock + Snooze)
|
|
|
+ private var rightPanel: some View {
|
|
|
VStack(spacing: 0) {
|
|
|
Spacer()
|
|
|
|
|
|
- VStack(spacing: 8) {
|
|
|
- TimelineView(.periodic(from: .now, by: 1)) { context in
|
|
|
- Text(context.date, format:
|
|
|
- Date.FormatStyle(date: .omitted, time: .shortened)
|
|
|
- )
|
|
|
- .font(.system(size: 70))
|
|
|
- .minimumScaleFactor(0.5)
|
|
|
+ TimelineView(.periodic(from: .now, by: 1)) { ctx in
|
|
|
+ Text(ctx.date, style: .time)
|
|
|
+ .font(.system(size: 70, weight: .regular))
|
|
|
.foregroundColor(.white)
|
|
|
- .frame(height: 78)
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- if let alarm = alarmText.value, !alarm.isEmpty {
|
|
|
- Text(alarm)
|
|
|
- .font(.system(size: 40, weight: .semibold))
|
|
|
- .foregroundColor(.red)
|
|
|
- .minimumScaleFactor(0.5)
|
|
|
- .lineLimit(1)
|
|
|
- .frame(height: 48)
|
|
|
- }
|
|
|
- */
|
|
|
+ }
|
|
|
+ .frame(height: 80)
|
|
|
+
|
|
|
+ if let alarm = vm.activeAlarm {
|
|
|
+ Text(alarm.name)
|
|
|
+ .font(.system(size: 40, weight: .semibold))
|
|
|
+ .foregroundColor(.red)
|
|
|
+ .minimumScaleFactor(0.5)
|
|
|
+ .padding(.top, 4)
|
|
|
+
|
|
|
+ Spacer(minLength: 32)
|
|
|
+
|
|
|
+ snoozeControls(alarm: alarm)
|
|
|
}
|
|
|
|
|
|
Spacer()
|
|
|
+ }
|
|
|
+ .padding(.horizontal, 24)
|
|
|
+ }
|
|
|
|
|
|
- // Snooze controls
|
|
|
- HStack(spacing: 12) {
|
|
|
+ // MARK: – Snooze UI
|
|
|
+ @ViewBuilder private func snoozeControls(alarm: Alarm) -> some View {
|
|
|
+ VStack(spacing: 16) {
|
|
|
+ HStack {
|
|
|
Text("Snooze for")
|
|
|
- .font(.system(size: 20))
|
|
|
- .foregroundColor(.white)
|
|
|
- Text("\(snoozeMinutes) min")
|
|
|
- .font(.system(size: 20, weight: .semibold))
|
|
|
- .foregroundColor(.white)
|
|
|
Spacer()
|
|
|
- Stepper("", value: $snoozeMinutes, in: 1...60)
|
|
|
- .labelsHidden()
|
|
|
+ Text("\(vm.snoozeMins) \(vm.timeUnitLabel)")
|
|
|
}
|
|
|
- .padding(.horizontal, 32)
|
|
|
- .frame(height: 44)
|
|
|
+ .font(.title3)
|
|
|
+ .foregroundColor(.white)
|
|
|
+
|
|
|
+ Stepper("", value: $vm.snoozeMins,
|
|
|
+ in: 1...120,
|
|
|
+ step: alarm.type.timeUnit == .minute ? 5 : 1)
|
|
|
+ .labelsHidden()
|
|
|
|
|
|
- Button(action: onSnooze) {
|
|
|
+ Button(action: vm.snoozeTapped) {
|
|
|
Text("Snooze")
|
|
|
- .font(.system(size: 24, weight: .bold))
|
|
|
- .frame(maxWidth: .infinity, minHeight: 56)
|
|
|
+ .bold()
|
|
|
+ .frame(maxWidth: .infinity, minHeight: 50)
|
|
|
+ .background(Color.white.opacity(0.15))
|
|
|
+ .cornerRadius(10)
|
|
|
}
|
|
|
- .background(Color(white: 0.15))
|
|
|
- .foregroundColor(.white)
|
|
|
- .cornerRadius(8)
|
|
|
- .padding(.horizontal, 32)
|
|
|
- .padding(.bottom, 32)
|
|
|
}
|
|
|
- .padding(.top, 16)
|
|
|
}
|
|
|
}
|