mirror of
https://github.com/yattee/yattee.git
synced 2026-02-21 02:09:46 +00:00
Add opaque black background to onboarding on tvOS to prevent Home screen content from leaking through the fullScreenCover. Replace toolbar Skip button with plain overlay button to avoid blurred material style, and add tvOS card button style with default focus on Continue button.
142 lines
3.9 KiB
Swift
142 lines
3.9 KiB
Swift
//
|
|
// OnboardingSheetView.swift
|
|
// Yattee
|
|
//
|
|
// Container view for the onboarding flow with TabView and page dots.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct OnboardingSheetView: View {
|
|
@Environment(\.dismiss) private var dismiss
|
|
@Environment(\.appEnvironment) private var appEnvironment
|
|
|
|
@State private var currentPage = 0
|
|
@State private var legacyItems: [LegacyImportItem]?
|
|
@State private var hasCheckedLegacyData = false
|
|
|
|
private var totalPages: Int {
|
|
hasLegacyData ? 4 : 3
|
|
}
|
|
|
|
private var hasLegacyData: Bool {
|
|
legacyItems?.isEmpty == false
|
|
}
|
|
|
|
private var settingsManager: SettingsManager? {
|
|
appEnvironment?.settingsManager
|
|
}
|
|
|
|
private var legacyMigrationService: LegacyDataMigrationService? {
|
|
appEnvironment?.legacyMigrationService
|
|
}
|
|
|
|
var body: some View {
|
|
TabView(selection: $currentPage) {
|
|
OnboardingTitleScreen(onContinue: advanceToNextPage)
|
|
.tag(0)
|
|
|
|
// Cloud screen is now always page 1 (before migration)
|
|
// This ensures iCloud instances are synced before migration runs,
|
|
// so isDuplicate() correctly detects duplicates against iCloud-synced instances
|
|
OnboardingCloudScreen(onContinue: advanceToNextPage)
|
|
.tag(1)
|
|
|
|
// Migration screen is now page 2 (when present)
|
|
if hasLegacyData, let binding = Binding($legacyItems) {
|
|
OnboardingMigrationScreen(
|
|
onContinue: advanceToNextPage,
|
|
onSkip: advanceToNextPage,
|
|
items: binding
|
|
)
|
|
.tag(2)
|
|
}
|
|
|
|
OnboardingSourcesScreen(
|
|
onGoToSources: goToSettings,
|
|
onClose: completeOnboarding
|
|
)
|
|
.tag(hasLegacyData ? 3 : 2)
|
|
}
|
|
#if os(tvOS)
|
|
.tabViewStyle(.page)
|
|
#elseif os(iOS)
|
|
.tabViewStyle(.page(indexDisplayMode: .never))
|
|
#endif
|
|
#if os(tvOS)
|
|
.background(Color.black.ignoresSafeArea())
|
|
.overlay(alignment: .topLeading) {
|
|
Button(String(localized: "onboarding.skip")) {
|
|
completeOnboarding()
|
|
}
|
|
.buttonStyle(.plain)
|
|
.foregroundStyle(.secondary)
|
|
.padding(40)
|
|
}
|
|
#endif
|
|
.interactiveDismissDisabled()
|
|
#if !os(tvOS)
|
|
.toolbar {
|
|
ToolbarItem(placement: .cancellationAction) {
|
|
Button(String(localized: "onboarding.skip")) {
|
|
completeOnboarding()
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
.task {
|
|
guard !hasCheckedLegacyData else { return }
|
|
hasCheckedLegacyData = true
|
|
legacyItems = legacyMigrationService?.parseLegacyData()
|
|
}
|
|
}
|
|
|
|
// MARK: - Navigation
|
|
|
|
private func advanceToNextPage() {
|
|
withAnimation {
|
|
if currentPage < totalPages - 1 {
|
|
currentPage += 1
|
|
} else {
|
|
completeOnboarding()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func completeOnboarding() {
|
|
settingsManager?.onboardingCompleted = true
|
|
dismiss()
|
|
}
|
|
|
|
private func goToSettings() {
|
|
settingsManager?.onboardingCompleted = true
|
|
dismiss()
|
|
|
|
// Navigate to settings after dismiss completes
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
|
NotificationCenter.default.post(name: .showSettings, object: nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Notification
|
|
|
|
extension Notification.Name {
|
|
static let showOnboarding = Notification.Name("showOnboarding")
|
|
static let showSettings = Notification.Name("showSettings")
|
|
static let showOpenLinkSheet = Notification.Name("showOpenLinkSheet")
|
|
}
|
|
|
|
// MARK: - Preview
|
|
|
|
#Preview {
|
|
@Previewable @State var sheetPresented: Bool = true
|
|
|
|
VStack {
|
|
|
|
}.sheet(isPresented: $sheetPresented) {
|
|
OnboardingSheetView()
|
|
.appEnvironment(.preview)
|
|
}
|
|
}
|