101 lines
3.1 KiB
Swift
101 lines
3.1 KiB
Swift
//
|
|
// OnboardingView.swift
|
|
// TheNoiseClock
|
|
//
|
|
// Streamlined onboarding flow optimized for time-to-value.
|
|
// Shows real clock immediately, requests AlarmKit permission,
|
|
// and gets users to their "aha moment" fast.
|
|
//
|
|
// Updated for AlarmKit (iOS 26+) - alarms now cut through
|
|
// Focus modes and silent mode automatically.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Bedrock
|
|
import Foundation
|
|
|
|
/// Streamlined onboarding optimized for activation
|
|
struct OnboardingView: View {
|
|
|
|
// MARK: - Properties
|
|
|
|
let onComplete: () -> Void
|
|
let requestAlarmPermission: () async -> Bool
|
|
let isKeepAwakeEnabled: () -> Bool
|
|
let onEnableKeepAwake: () -> Void
|
|
|
|
@State private var currentPage = 0
|
|
@State private var alarmKitPermissionGranted = false
|
|
@State private var keepAwakeEnabled = false
|
|
|
|
private let totalPages = 4
|
|
|
|
// MARK: - Body
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
AppSurface.primary
|
|
.ignoresSafeArea()
|
|
|
|
VStack(spacing: 0) {
|
|
TabView(selection: $currentPage) {
|
|
OnboardingWelcomePage()
|
|
.tag(0)
|
|
|
|
OnboardingPageView(
|
|
icon: "waveform",
|
|
iconColor: AppAccent.primary,
|
|
title: "Soothing Sounds",
|
|
description: "Choose from a variety of white noise, rain, and ambient sounds to help you drift off to sleep."
|
|
)
|
|
.tag(1)
|
|
|
|
OnboardingPermissionsPage(
|
|
alarmKitPermissionGranted: $alarmKitPermissionGranted,
|
|
keepAwakeEnabled: $keepAwakeEnabled,
|
|
requestAlarmPermission: requestAlarmPermission,
|
|
isKeepAwakeEnabled: isKeepAwakeEnabled,
|
|
onEnableKeepAwake: onEnableKeepAwake,
|
|
onAdvanceToFinal: {
|
|
withAnimation { currentPage = 3 }
|
|
}
|
|
)
|
|
.tag(2)
|
|
|
|
OnboardingGetStartedPage()
|
|
.tag(3)
|
|
}
|
|
.tabViewStyle(.page(indexDisplayMode: .never))
|
|
|
|
OnboardingBottomControls(
|
|
currentPage: $currentPage,
|
|
totalPages: totalPages,
|
|
onSkip: onComplete,
|
|
onFinish: {
|
|
withAnimation(.spring(duration: 0.45, bounce: 0.2)) {
|
|
onComplete()
|
|
}
|
|
}
|
|
)
|
|
.padding(.horizontal, Design.Spacing.xLarge)
|
|
.padding(.bottom, Design.Spacing.xxLarge)
|
|
}
|
|
.frame(maxWidth: Design.Size.maxContentWidthPortrait)
|
|
.frame(maxWidth: .infinity, alignment: .center)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Preview
|
|
|
|
#Preview {
|
|
OnboardingView {
|
|
} requestAlarmPermission: {
|
|
true
|
|
} isKeepAwakeEnabled: {
|
|
false
|
|
} onEnableKeepAwake: {
|
|
}
|
|
.preferredColorScheme(.dark)
|
|
}
|