diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3065293..988e905 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: - "*.*.*" jobs: - build: + release: name: Create release runs-on: ubuntu-latest steps: diff --git a/AppExample/Example (watchOS) Watch App/ContentView.swift b/AppExample/Example (watchOS) Watch App/ContentView.swift index 9cce011..b173e94 100644 --- a/AppExample/Example (watchOS) Watch App/ContentView.swift +++ b/AppExample/Example (watchOS) Watch App/ContentView.swift @@ -3,14 +3,14 @@ // ContentView.swift, created on 19.05.2024 // -import OversizeKit +import OversizeCalendarKit import OversizeContactsKit +import OversizeKit import OversizeLocationKit -import OversizePhotoKit -import OversizeCalendarKit import OversizeNoticeKit import OversizeNotificationKit import OversizeOnboardingKit +import OversizePhotoKit import SwiftUI struct ContentView: View { diff --git a/AppExample/Example (watchOS) Watch App/Example__watchOS_App.swift b/AppExample/Example (watchOS) Watch App/Example__watchOS_App.swift index fbf5231..c00dd47 100644 --- a/AppExample/Example (watchOS) Watch App/Example__watchOS_App.swift +++ b/AppExample/Example (watchOS) Watch App/Example__watchOS_App.swift @@ -11,9 +11,8 @@ import SwiftUI @main struct Example__watchOS__Watch_AppApp: App { - @Injected(\.appStateService) var appStateService: AppStateService - + var body: some Scene { WindowGroup { ContentView() diff --git a/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate b/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate index 7fd7482..131e000 100644 Binary files a/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate and b/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist b/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist index 747e56b..33cfa4a 100644 --- a/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ Example (watchOS) Watch App.xcscheme_^#shared#^_ orderHint - 1 + 2 Example.xcscheme_^#shared#^_ orderHint - 0 + 1 SuppressBuildableAutocreation diff --git a/AppExample/Example/Screens/Onboarding/OnboardingView.swift b/AppExample/Example/Screens/Onboarding/OnboardingView.swift index ab5152a..c3b89b6 100644 --- a/AppExample/Example/Screens/Onboarding/OnboardingView.swift +++ b/AppExample/Example/Screens/Onboarding/OnboardingView.swift @@ -3,8 +3,6 @@ // OnboardingView.swift, created on 25.09.2023 // - - import Factory import OversizeServices import OversizeUI diff --git a/AppExample/Example/Test/TestView.swift b/AppExample/Example/Test/TestView.swift index 979fd84..9787784 100644 --- a/AppExample/Example/Test/TestView.swift +++ b/AppExample/Example/Test/TestView.swift @@ -1,16 +1,16 @@ // // Copyright © 2024 Alexander Romanov // TestView.swift, created on 19.05.2024 -// +// -import OversizeKit +import OversizeCalendarKit import OversizeContactsKit +import OversizeKit import OversizeLocationKit -import OversizePhotoKit -import OversizeCalendarKit import OversizeNoticeKit import OversizeNotificationKit import OversizeOnboardingKit +import OversizePhotoKit import SwiftUI struct TestView: View { diff --git a/AppExample/Package.swift b/AppExample/Package.swift new file mode 100644 index 0000000..9fdca6f --- /dev/null +++ b/AppExample/Package.swift @@ -0,0 +1,4 @@ +// swift-tools-version: 5.6 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription diff --git a/Package.swift b/Package.swift index f08bfb2..81a3155 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version: 6.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import Foundation @@ -6,7 +6,7 @@ import PackageDescription let productionDependencies: [PackageDescription.Package.Dependency] = [ .package(url: "https://github.com/oversizedev/OversizeUI.git", .upToNextMajor(from: "3.0.2")), - .package(url: "https://github.com/oversizedev/OversizeCore.git", .upToNextMajor(from: "1.3.0")), + .package(url: "https://github.com/oversizedev/OversizeCore.git", .upToNextMajor(from: "2.0.0")), .package(url: "https://github.com/oversizedev/OversizeServices.git", .upToNextMajor(from: "1.4.0")), .package(url: "https://github.com/oversizedev/OversizeLocalizable.git", .upToNextMajor(from: "1.4.0")), .package(url: "https://github.com/oversizedev/OversizeComponents.git", .upToNextMajor(from: "1.2.0")), @@ -43,10 +43,10 @@ if ProcessInfo.processInfo.environment["RELEASE_DEPENDENCIES"].flatMap(Bool.init let package = Package( name: "OversizeKit", platforms: [ - .iOS(.v16), - .macOS(.v13), - .tvOS(.v16), - .watchOS(.v9), + .iOS(.v17), + .macOS(.v14), + .tvOS(.v17), + .watchOS(.v10), ], products: [ .library(name: "OversizeKit", targets: ["OversizeKit"]), @@ -58,7 +58,7 @@ let package = Package( .library(name: "OversizeNotificationKit", targets: ["OversizeNotificationKit"]), .library(name: "OversizePhotoKit", targets: ["OversizePhotoKit"]), ], - dependencies: productionDependencies, + dependencies: developmentDependencies, targets: [ .target( name: "OversizeKit", diff --git a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift index d75db38..cfdb2ca 100644 --- a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift +++ b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift @@ -71,7 +71,7 @@ import SwiftUI .controlBorderShape(.capsule) .controlSize(.mini) } - .navigationBarDividerColor(Color.onSurfaceHighEmphasis.opacity(0.1)) + .navigationBarDividerColor(Color.onSurfacePrimary.opacity(0.1)) .safeAreaInset(edge: .bottom) { bottomBar } @@ -98,7 +98,7 @@ import SwiftUI TextField("Event name", text: $viewModel.title) .title(.bold) .focused($focusedField, equals: .title) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() .padding(.bottom, .xxxSmall) .padding(.horizontal, .small) @@ -129,7 +129,7 @@ import SwiftUI HStack { Text("All-day event") .headline(.semibold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .padding(.leading, .xxxSmall) Spacer() @@ -148,7 +148,7 @@ import SwiftUI var textEditor: some View { VStack(spacing: 2) { TextEditor(text: $viewModel.note) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() .padding(.horizontal, .xSmall) .padding(.vertical, .xxSmall) .focused($focusedField, equals: .note) @@ -162,7 +162,7 @@ import SwiftUI if viewModel.note.isEmpty { Text("Note") .body(.medium) - .onSurfaceDisabledForegroundColor() + .onSurfaceTertiaryForeground() .padding(.small) } } @@ -173,7 +173,7 @@ import SwiftUI if viewModel.note.isEmpty { Text("Note") .body(.medium) - .onSurfaceDisabledForegroundColor() + .onSurfaceTertiaryForeground() .padding(.small) } } @@ -183,7 +183,7 @@ import SwiftUI TextField("URL", text: $viewModel.url) .focused($focusedField, equals: .url) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() .body(.medium) .padding(.horizontal, .small) .padding(.vertical, 18) @@ -209,7 +209,7 @@ import SwiftUI viewModel.present(.repeat) } leading: { IconDeprecated(.refresh) - .iconColor(.onSurfaceHighEmphasis) + .iconColor(.onSurfacePrimary) } .rowClearButton(style: .onSurface) { viewModel.repitRule = .never @@ -235,7 +235,7 @@ import SwiftUI viewModel.present(.invites) } leading: { IconDeprecated(.user) - .iconColor(.onSurfaceHighEmphasis) + .iconColor(.onSurfacePrimary) } .rowClearButton(style: .onSurface) { viewModel.members.remove(email) @@ -269,7 +269,7 @@ import SwiftUI viewModel.present(.alarm) } leading: { IconDeprecated(.bell) - .iconColor(.onSurfaceHighEmphasis) + .iconColor(.onSurfacePrimary) } .rowClearButton(style: .onSurface) { viewModel.alarms.remove(alarm) @@ -303,7 +303,7 @@ import SwiftUI viewModel.present(.location) } leading: { IconDeprecated(.mapPin) - .iconColor(.onSurfaceHighEmphasis) + .iconColor(.onSurfacePrimary) } .rowClearButton(style: .onSurface) { viewModel.locationName = nil @@ -356,16 +356,16 @@ import SwiftUI } label: { VStack(alignment: .leading, spacing: .xxxSmall) { Text("Starts") - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .subheadline(.semibold) Text(startDateText) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() .headline(.semibold) if !isCurrentYearEvent { Text(viewModel.dateStart.formatted(.dateTime.year())) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() .headline(.semibold) } } @@ -384,16 +384,16 @@ import SwiftUI } label: { VStack(alignment: .leading, spacing: .xxxSmall) { Text("Ended") - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .subheadline(.semibold) Text(endDateText) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() .headline(.semibold) if !isCurrentYearEvent { Text(viewModel.dateEnd.formatted(.dateTime.year())) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() .headline(.semibold) } } @@ -478,13 +478,13 @@ import SwiftUI .buttonStyle(.scale) .padding(.horizontal, .medium) .padding(.vertical, 20) - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() #if !os(watchOS) .background(.ultraThinMaterial) #endif .overlay(alignment: .top) { Rectangle() - .fill(Color.onSurfaceHighEmphasis.opacity(0.05)) + .fill(Color.onSurfacePrimary.opacity(0.05)) .frame(height: 1) } } diff --git a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift index f9fac0f..beb178c 100644 --- a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift +++ b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift @@ -102,7 +102,6 @@ import SwiftUI #endif case .repeat: RepeatPicker(selectionRule: $viewModel.repitRule, selectionEndRule: $viewModel.repitEndRule) - case .alarm: AlarmPicker(selection: $viewModel.alarms) .presentationDetents([.height(630), .large]) diff --git a/Sources/OversizeCalendarKit/CreateEventScreen/SaveForView/SaveForView.swift b/Sources/OversizeCalendarKit/CreateEventScreen/SaveForView/SaveForView.swift index ba4f08f..676b9a5 100644 --- a/Sources/OversizeCalendarKit/CreateEventScreen/SaveForView/SaveForView.swift +++ b/Sources/OversizeCalendarKit/CreateEventScreen/SaveForView/SaveForView.swift @@ -28,7 +28,7 @@ import SwiftUI } leading: { Image.Date.calendar .renderingMode(.template) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } Row("Save for feature events") { @@ -37,7 +37,7 @@ import SwiftUI } leading: { Image.Base.calendar .renderingMode(.template) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } } } diff --git a/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift b/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift index be20de4..2c32cb8 100644 --- a/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift +++ b/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift @@ -113,7 +113,7 @@ import SwiftUI #if os(iOS) .keyboardType(.numberPad) #endif - .textFieldStyle(DefaultPlaceholderTextFieldStyle()) + .textFieldStyle(.default) .focused($isFocusedRepitCount) case .endDate: #if !os(watchOS) diff --git a/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift b/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift index 25d53c8..3bca2d1 100644 --- a/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift +++ b/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift @@ -83,7 +83,7 @@ import SwiftUI .fillBackgroundPrimary() } Image(systemName: participant.symbolName) - .onPrimaryHighEmphasisForegroundColor() + .onPrimaryForeground() .font(.system(size: 9, weight: .black)) } } diff --git a/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift b/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift index c575fcb..053b539 100644 --- a/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift +++ b/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift @@ -50,7 +50,7 @@ import SwiftUI } .topToolbar { TextField("Email or name", text: $viewModel.searchText) - .textFieldStyle(DefaultPlaceholderTextFieldStyle()) + .textFieldStyle(.default) .focused($isFocusSearth) #if os(iOS) .keyboardType(.emailAddress) @@ -98,7 +98,7 @@ import SwiftUI Spacer() } .title3() - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .padding(.vertical, .xxSmall) .paddingContent(.horizontal) @@ -136,7 +136,7 @@ import SwiftUI Spacer() } .title3() - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .padding(.vertical, .xxSmall) .paddingContent(.horizontal) .padding(.top, viewModel.lastSelectedEmails.isEmpty ? .zero : .small) diff --git a/Sources/OversizeKit/AdsKit/AdView.swift b/Sources/OversizeKit/AdsKit/AdView.swift index a115595..b2e4836 100644 --- a/Sources/OversizeKit/AdsKit/AdView.swift +++ b/Sources/OversizeKit/AdsKit/AdView.swift @@ -30,6 +30,7 @@ public struct AdView: View { await viewModel.fetchAd() } } + case let .result(appAd): #if os(iOS) Surface { @@ -79,7 +80,7 @@ public struct AdView: View { HStack { Text(appAd.title) .subheadline(.bold) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() Bage(color: .warning) { Text("Our app") @@ -89,7 +90,7 @@ public struct AdView: View { Text(appAd.description) .subheadline() - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() } .padding(.leading, .xSmall) diff --git a/Sources/OversizeKit/LauncherKit/Launcher.swift b/Sources/OversizeKit/LauncherKit/Launcher.swift index 4576ace..51a704f 100644 --- a/Sources/OversizeKit/LauncherKit/Launcher.swift +++ b/Sources/OversizeKit/LauncherKit/Launcher.swift @@ -14,10 +14,8 @@ public struct Launcher: View { private var onboarding: Onboarding? private let content: Content - private var transaction = Transaction() @StateObject private var viewModel = LauncherViewModel() - @State private var blurRadius: CGFloat = 0 public init(@ViewBuilder content: () -> Content) { self.content = content() @@ -39,15 +37,19 @@ public struct Launcher: View { .appLaunchCover(item: $viewModel.activeFullScreenSheet) { fullScreenCover(sheet: $0) .systemServices() + #if os(macOS) + .frame(width: 840, height: 672) + // .interactiveDismissDisabled(!viewModel.appStateService.isCompletedOnbarding) + #endif } - .onChange(of: viewModel.appStateService.isCompletedOnbarding) { isCompletedOnbarding in + .onChange(of: viewModel.appStateService.isCompletedOnbarding) { _, isCompletedOnbarding in if isCompletedOnbarding, !viewModel.isPremium { viewModel.setPayWall() } else { viewModel.activeFullScreenSheet = nil } } - .onChange(of: scenePhase, perform: { value in + .onChange(of: scenePhase) { _, value in switch value { case .background: viewModel.authState = .locked @@ -55,7 +57,7 @@ public struct Launcher: View { default: break } - }) + } } @ViewBuilder @@ -67,7 +69,9 @@ public struct Launcher: View { } else { content .onAppear { - viewModel.reviewService.launchEvent() + Task { @MainActor in + await viewModel.reviewService.launchEvent() + } viewModel.launcherSheetsChek() } } @@ -84,14 +88,15 @@ public struct Launcher: View { } private var lockscreenView: some View { - LockscreenView(pinCode: $viewModel.pinCodeField, - state: $viewModel.authState, - title: L10n.Security.enterPINCode, - errorText: L10n.Security.invalidPIN, - pinCodeEnabled: viewModel.settingsService.pinCodeEnabend, - biometricEnabled: viewModel.settingsService.biometricEnabled, - biometricType: viewModel.biometricService.biometricType) - { + LockscreenView( + pinCode: $viewModel.pinCodeField, + state: $viewModel.authState, + title: L10n.Security.enterPINCode, + errorText: L10n.Security.invalidPIN, + pinCodeEnabled: viewModel.settingsService.pinCodeEnabend, + biometricEnabled: viewModel.settingsService.biometricEnabled, + biometricType: viewModel.biometricService.biometricType + ) { viewModel.checkPassword() } biometricAction: { viewModel.appLockValidation() @@ -122,7 +127,6 @@ public extension View { Launcher { self } - .systemServices() } func appLaunch(@ViewBuilder onboarding: @escaping () -> some View) -> some View { @@ -130,7 +134,6 @@ public extension View { self } .onboarding(onboarding: onboarding) - .systemServices() } } @@ -139,8 +142,7 @@ private extension View { item: Binding, onDismiss: (() -> Void)? = nil, @ViewBuilder content: @escaping (Item) -> some View ) -> some View where Item: Identifiable { #if os(macOS) - interactiveDismissDisabled() - .sheet(item: item, onDismiss: onDismiss, content: content) + sheet(item: item, onDismiss: onDismiss, content: content) #else fullScreenCover(item: item, onDismiss: onDismiss, content: content) #endif diff --git a/Sources/OversizeKit/LauncherKit/LauncherViewModel.swift b/Sources/OversizeKit/LauncherKit/LauncherViewModel.swift index a8e4e0c..8899600 100644 --- a/Sources/OversizeKit/LauncherKit/LauncherViewModel.swift +++ b/Sources/OversizeKit/LauncherKit/LauncherViewModel.swift @@ -49,7 +49,7 @@ public final class LauncherViewModel: ObservableObject { } extension LauncherViewModel { - enum FullScreenSheet: Identifiable, Equatable { + enum FullScreenSheet: Identifiable, Equatable, Sendable { case onboarding case payWall case rate @@ -124,7 +124,9 @@ public extension LauncherViewModel { func setPayWall() { activeFullScreenSheet = nil delay(time: 0.2) { - self.activeFullScreenSheet = .payWall + Task { @MainActor in + self.activeFullScreenSheet = .payWall + } } } diff --git a/Sources/OversizeKit/LauncherKit/RateAppScreen.swift b/Sources/OversizeKit/LauncherKit/RateAppScreen.swift index 54a5bd2..b859b0d 100644 --- a/Sources/OversizeKit/LauncherKit/RateAppScreen.swift +++ b/Sources/OversizeKit/LauncherKit/RateAppScreen.swift @@ -17,7 +17,7 @@ struct RateAppScreen: View { VStack { Text("If you love, evaluate)") .largeTitle(.bold) - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() Spacer() @@ -29,14 +29,14 @@ struct RateAppScreen: View { Text((Info.app.name ?? "App") + " is developed only one person, and your assessment would very much drop in") .title3() - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() Spacer() if let reviewUrl = Info.url.appStoreReview { HStack(spacing: .large) { Link(destination: reviewUrl) { - IconDeprecated(.thumbsUp, color: .onPrimaryHighEmphasis) + IconDeprecated(.thumbsUp, color: .onPrimary) } .buttonStyle(.primary(infinityWidth: false)) .accent() @@ -49,7 +49,7 @@ struct RateAppScreen: View { reviewService.estimate(goodRating: false) dismiss() } label: { - IconDeprecated(.thumbsDown, color: .onSurfaceHighEmphasis) + IconDeprecated(.thumbsDown, color: .onSurfacePrimary) } .buttonStyle(.secondary(infinityWidth: false)) } @@ -67,7 +67,7 @@ struct RateAppScreen: View { reviewService.rewiewBunnerClosed() dismiss() } label: { - IconDeprecated(.xMini, color: .onSurfaceHighEmphasis) + IconDeprecated(.xMini, color: .onSurfacePrimary) } .buttonStyle(.tertiary(infinityWidth: false)) .controlBorderShape(.capsule) diff --git a/Sources/OversizeKit/LockscreenKit/LockscreenView.swift b/Sources/OversizeKit/LockscreenKit/LockscreenView.swift index 0833b73..cfb01ef 100644 --- a/Sources/OversizeKit/LockscreenKit/LockscreenView.swift +++ b/Sources/OversizeKit/LockscreenKit/LockscreenView.swift @@ -87,7 +87,7 @@ public struct LockscreenView: View { public var body: some View { content() .background(Color.surfacePrimary.ignoresSafeArea(.all)) - .onChange(of: scenePhase) { phase in + .onChange(of: scenePhase) { _, phase in switch phase { case .active: if state == .locked, biometricEnabled { @@ -125,14 +125,14 @@ public struct LockscreenView: View { #else Text(biometricType.rawValue) .title2(.bold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) #endif } else { Text(biometricType.rawValue) .title2(.semibold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } Spacer() @@ -165,7 +165,7 @@ public struct LockscreenView: View { Text(title ?? "") .title2(.bold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .opacity(title != nil ? 1 : 0) Spacer() @@ -180,7 +180,7 @@ public struct LockscreenView: View { Text(errorText ?? "") .subheadline() - .errorForegroundColor() + .errorForeground() .opacity(state == .error ? 1 : 0) if isShowTitle { @@ -247,18 +247,18 @@ public struct LockscreenView: View { EmptyView() case .touchID: Image(systemName: "touchid") - .foregroundColor(Color.onBackgroundHighEmphasis) + .foregroundColor(Color.onBackgroundPrimary) .font(.system(size: 26)) .frame(width: 24, height: 24, alignment: .center) case .faceID: Image(systemName: "faceid") .font(.system(size: 26)) - .foregroundColor(Color.onBackgroundHighEmphasis) + .foregroundColor(Color.onBackgroundPrimary) .frame(width: 24, height: 24, alignment: .center) case .opticID: Image(systemName: "opticid") .font(.system(size: 26)) - .foregroundColor(Color.onBackgroundHighEmphasis) + .foregroundColor(Color.onBackgroundPrimary) .frame(width: 24, height: 24, alignment: .center) } } @@ -284,7 +284,6 @@ public struct LockscreenView: View { .frame(width: 12, height: 12) .offset(x: leftOffset) // .animation(Animation.easeInOut(duration: 1).delay(0.2 * Double(number))) - .scaleEffect(shouldAnimate ? 0.5 : 1) .animation(Animation.easeInOut(duration: 0.5) .repeatForever() @@ -332,7 +331,7 @@ public struct NumpadButtonStyle: ButtonStyle { public func makeBody(configuration: Self.Configuration) -> some View { configuration.label .title2() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .frame(width: 72, height: 72, alignment: .center) .background( Circle() diff --git a/Sources/OversizeKit/RouterKit/SettingsRouter/SettingsRouting.swift b/Sources/OversizeKit/RouterKit/SettingsRouter/SettingsRouting.swift deleted file mode 100644 index 9a7c7fc..0000000 --- a/Sources/OversizeKit/RouterKit/SettingsRouter/SettingsRouting.swift +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright © 2024 Alexander Romanov -// SettingsRouting.swift, created on 10.05.2024 -// - -import OversizeRouter -import SwiftUI - -public struct SettingsRoutingView: View where Root: View { - @StateObject private var router: Router = .init() - @StateObject private var hudRouter: HUDRouter = .init() - private let root: () -> Root - - public init(@ViewBuilder root: @escaping () -> Root) { - self.root = root - } - - public var body: some View { - NavigationStack(path: $router.path) { - root() - .navigationDestination(for: SettingsScreen.self) { destination in - destination.view() - } - } - .onSettingsNavigate(routerNavigate) - .sheet( - item: $router.sheet, - content: { sheet in - NavigationStack(path: $router.sheetPath) { - sheet.view() - .navigationDestination(for: SettingsScreen.self) { destination in - destination.view() - } - } - .presentationDetents(router.sheetDetents) - .presentationDragIndicator(router.dragIndicator) - .interactiveDismissDisabled(router.dismissDisabled) - .systemServices() - .onSettingsNavigate(routerNavigate) - } - ) - #if os(iOS) - .fullScreenCover(item: $router.fullScreenCover) { fullScreenCover in - fullScreenCover.view() - .systemServices() - .onSettingsNavigate(routerNavigate) - } - #endif - } - - func routerNavigate(navigationType: SettingsNavigationType) { - switch navigationType { - case let .move(screen): - router.move(screen) - case .backToRoot: - router.backToRoot() - case let .back(count): - router.back(count) - case let .present(sheet, detents: detents, indicator: indicator, dismissDisabled: dismissDisabled): - router.present(sheet, detents: detents, indicator: indicator, dismissDisabled: dismissDisabled) - case .dismiss: - router.dismiss() - case .dismissSheet: - router.dismissSheet() - case .dismissFullScreenCover: - router.dismissFullScreenCover() - case let .dismissDisabled(isDismissDisabled): - router.dismissDisabled(isDismissDisabled) - case let .presentHUD(text, type): - hudRouter.present(text, type: type) - } - } -} diff --git a/Sources/OversizeKit/RouterKit/SettingsRouter/ResolveRouter.swift b/Sources/OversizeKit/SettingsKit/SettingsRouter/ResolveRouter.swift similarity index 92% rename from Sources/OversizeKit/RouterKit/SettingsRouter/ResolveRouter.swift rename to Sources/OversizeKit/SettingsKit/SettingsRouter/ResolveRouter.swift index 48a29ec..0da5cbe 100644 --- a/Sources/OversizeKit/RouterKit/SettingsRouter/ResolveRouter.swift +++ b/Sources/OversizeKit/SettingsKit/SettingsRouter/ResolveRouter.swift @@ -7,11 +7,12 @@ import Foundation import OversizeComponents import OversizeLocalizable import OversizeNetwork +import OversizeRouter import SwiftUI -extension SettingsScreen { - @ViewBuilder - func view() -> some View { +extension SettingsScreen: @preconcurrency RoutableView { + @MainActor @ViewBuilder + public func view() -> some View { switch self { case .premium: StoreView() diff --git a/Sources/OversizeKit/SettingsKit/Views/Screens.swift b/Sources/OversizeKit/SettingsKit/SettingsRouter/Screens.swift similarity index 54% rename from Sources/OversizeKit/SettingsKit/Views/Screens.swift rename to Sources/OversizeKit/SettingsKit/SettingsRouter/Screens.swift index fa48fb7..33e34fe 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Screens.swift +++ b/Sources/OversizeKit/SettingsKit/SettingsRouter/Screens.swift @@ -1,8 +1,9 @@ // // Copyright © 2024 Alexander Romanov -// File.swift, created on 15.04.2024 +// SettingsScreen.swift, created on 15.04.2024 // +import OversizeComponents import OversizeModels import OversizeNetwork import OversizeRouter @@ -75,39 +76,40 @@ public extension SettingsScreen { } } -public struct SettingsNavigateAction { - public typealias Action = (SettingsNavigationType) -> Void - public let action: Action - public func callAsFunction(_ navigationType: SettingsNavigationType) { - action(navigationType) - } -} +//public struct SettingsNavigateAction { +// public typealias Action = (SettingsNavigationType) -> Void +// public let action: Action +// public func callAsFunction(_ navigationType: SettingsNavigationType) { +// action(navigationType) +// } +//} -public enum SettingsNavigationType { - case move(SettingsScreen) - case backToRoot - case back(Int = 1) - case present(_ sheet: SettingsScreen, detents: Set = [.large], indicator: Visibility = .hidden, dismissDisabled: Bool = false) - case dismiss - case dismissSheet - case dismissFullScreenCover - case dismissDisabled(_ isDismissDisabled: Bool = true) - case presentHUD(_ text: String, type: HUDMessageType) -} +//public enum SettingsNavigationType { +// case move(SettingsScreen) +// case backToRoot +// case back(Int = 1) +// case present(_ sheet: SettingsScreen, detents: Set = [.large], indicator: Visibility = .hidden, dismissDisabled: Bool = false) +// case dismiss +// case dismissSheet +// case dismissFullScreenCover +// case dismissDisabled(_ isDismissDisabled: Bool = true) +// case presentHUD(_ text: String, type: HUDMessageType) +//} -public struct SettingsNavigateEnvironmentKey: EnvironmentKey { - public static var defaultValue: SettingsNavigateAction = .init(action: { _ in }) -} - -public extension EnvironmentValues { - var settingsNavigate: SettingsNavigateAction { - get { self[SettingsNavigateEnvironmentKey.self] } - set { self[SettingsNavigateEnvironmentKey.self] = newValue } - } -} - -public extension View { - func onSettingsNavigate(_ action: @escaping SettingsNavigateAction.Action) -> some View { - environment(\.settingsNavigate, SettingsNavigateAction(action: action)) - } -} +// +// public struct SettingsNavigateEnvironmentKey: EnvironmentKey { +// public static var defaultValue: SettingsNavigateAction = .init(action: { _ in }) +// } +// +// public extension EnvironmentValues { +// var settingsNavigate: SettingsNavigateAction { +// get { self[SettingsNavigateEnvironmentKey.self] } +// set { self[SettingsNavigateEnvironmentKey.self] = newValue } +// } +// } +// +// public extension View { +// func onSettingsNavigate(_ action: @escaping SettingsNavigateAction.Action) -> some View { +// environment(\.settingsNavigate, SettingsNavigateAction(action: action)) +// } +// } diff --git a/Sources/OversizeKit/SettingsKit/SettingsRouter/SettingsRouting.swift b/Sources/OversizeKit/SettingsKit/SettingsRouter/SettingsRouting.swift new file mode 100644 index 0000000..3045579 --- /dev/null +++ b/Sources/OversizeKit/SettingsKit/SettingsRouter/SettingsRouting.swift @@ -0,0 +1,23 @@ +// +// Copyright © 2024 Alexander Romanov +// SettingsRouting.swift, created on 10.05.2024 +// + + import OversizeRouter + import SwiftUI + + public struct SettingsRoutingView: View { + + public init() { + + } + + public var body: some View { + RoutingView { + SettingsView { + EmptyView() + } + } + .systemServices() + } + } diff --git a/Sources/OversizeKit/SettingsKit/Views/About/About/AboutView.swift b/Sources/OversizeKit/SettingsKit/Views/About/About/AboutView.swift index be4a46e..d852126 100644 --- a/Sources/OversizeKit/SettingsKit/Views/About/About/AboutView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/About/About/AboutView.swift @@ -8,6 +8,7 @@ import OversizeComponents import OversizeCore import OversizeLocalizable import OversizeResources +import OversizeRouter import OversizeServices import OversizeUI import SwiftUI @@ -18,7 +19,7 @@ import SwiftUI #endif public struct AboutView: View { - @Environment(\.settingsNavigate) var settingsNavigate + @Environment(Router.self) var router @Environment(\.screenSize) var screenSize @Environment(\.iconStyle) var iconStyle: IconStyle @@ -118,7 +119,7 @@ public struct AboutView: View { Text(app.name) .caption(.medium) .multilineTextAlignment(.center) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) .frame(width: 74) } } @@ -146,7 +147,7 @@ public struct AboutView: View { Text("All apps") .caption(.medium) .multilineTextAlignment(.center) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) .frame(width: 74) } } @@ -166,12 +167,12 @@ public struct AboutView: View { Image.Brands.Oversize.fill .resizable() .renderingMode(.template) - .foregroundColor(Color.onSurfaceHighEmphasis) + .foregroundColor(Color.onSurfacePrimary) .frame(width: 32, height: 32) Resource.overszieTextLogo .renderingMode(.template) - .foregroundColor(Color.onSurfaceHighEmphasis) + .foregroundColor(Color.onSurfacePrimary) } .padding(.top, -40) .padding(.bottom, .xSmall) @@ -181,12 +182,12 @@ public struct AboutView: View { Image.Brands.Oversize.fill .resizable() .renderingMode(.template) - .foregroundColor(Color.onSurfaceHighEmphasis) + .foregroundColor(Color.onSurfacePrimary) .frame(width: 48, height: 48) Resource.overszieTextLogo .renderingMode(.template) - .foregroundColor(Color.onSurfaceHighEmphasis) + .foregroundColor(Color.onSurfacePrimary) } .padding(.top, 42) .padding(.bottom, .medium) @@ -194,7 +195,7 @@ public struct AboutView: View { Text("The Oversize project is made with love and attention to the design of the forces of only one person") .title3(.semibold) - .foregroundColor(.onBackgroundHighEmphasis) + .foregroundColor(.onBackgroundPrimary) .padding(.horizontal, isLargeScreen ? 72 : 52) .padding(.bottom, .large) .multilineTextAlignment(.center) @@ -259,7 +260,7 @@ public struct AboutView: View { HStack { Text(L10n.About.otherApplications.uppercased()) .caption(true) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) .padding(.top, 12) .padding(.leading, 26) .padding(.bottom, 18) @@ -273,19 +274,19 @@ public struct AboutView: View { SectionView { VStack(spacing: .zero) { Row("Our open resources") { - settingsNavigate(.move(.ourResorses)) + router.move(.ourResorses) } .rowArrow() if let privacyUrl = Info.url.appPrivacyPolicyUrl { Row(L10n.Store.privacyPolicy) { - settingsNavigate(.present(.webView(url: privacyUrl))) + router.present(.webView(url: privacyUrl)) } } if let termsOfUde = Info.url.appTermsOfUseUrl { Row(L10n.Store.termsOfUse) { - settingsNavigate(.present(.webView(url: termsOfUde))) + router.present(.webView(url: termsOfUde)) } } } @@ -339,7 +340,7 @@ public struct AboutView: View { Spacer() Image.Brands.Facebook.Circle.fill .renderingMode(.template) - .foregroundColor(Color.onSurfaceMediumEmphasis) + .foregroundColor(Color.onSurfaceSecondary) Spacer() } // } @@ -353,7 +354,7 @@ public struct AboutView: View { Spacer() Image.Brands.Instagram.fill .renderingMode(.template) - .foregroundColor(Color.onSurfaceMediumEmphasis) + .foregroundColor(Color.onSurfaceSecondary) Spacer() } // } @@ -367,7 +368,7 @@ public struct AboutView: View { Spacer() Image.Brands.xCom .renderingMode(.template) - .foregroundColor(Color.onSurfaceMediumEmphasis) + .foregroundColor(Color.onSurfaceSecondary) Spacer() } // } @@ -381,7 +382,7 @@ public struct AboutView: View { Spacer() Image.Brands.Telegram.fill .renderingMode(.template) - .foregroundColor(Color.onSurfaceMediumEmphasis) + .foregroundColor(Color.onSurfaceSecondary) Spacer() } // } @@ -395,7 +396,7 @@ public struct AboutView: View { Spacer() Image.Brands.Dribbble.fill .renderingMode(.template) - .foregroundColor(Color.onSurfaceMediumEmphasis) + .foregroundColor(Color.onSurfaceSecondary) Spacer() } // } @@ -476,11 +477,11 @@ public struct AboutView: View { { Text("© 2024 \(developerName). \(appName) \(appVersion) (\(appBuild))") .footnote() - .foregroundColor(.onBackgroundDisabled) + .foregroundColor(.onBackgroundTertiary) } else { Text("Developer") .footnote() - .foregroundColor(.onBackgroundDisabled) + .foregroundColor(.onBackgroundTertiary) } } } diff --git a/Sources/OversizeKit/SettingsKit/Views/About/FeedbackView.swift b/Sources/OversizeKit/SettingsKit/Views/About/FeedbackView.swift index dfc01ac..bd8491f 100644 --- a/Sources/OversizeKit/SettingsKit/Views/About/FeedbackView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/About/FeedbackView.swift @@ -9,12 +9,13 @@ import OversizeComponents import OversizeLocalizable import OversizeResources +import OversizeRouter import OversizeServices import OversizeUI import SwiftUI public struct FeedbackView: View { - @Environment(\.settingsNavigate) var settingsNavigate + @Environment(Router.self) var router @Environment(\.iconStyle) var iconStyle: IconStyle public init() {} @@ -31,7 +32,7 @@ public struct FeedbackView: View { .toolbar { ToolbarItem(placement: .cancellationAction) { Button { - settingsNavigate(.dismiss) + router.dismiss() } label: { Image.Base.close.icon() } @@ -69,7 +70,7 @@ public struct FeedbackView: View { let subject = "Feedback" Row(L10n.Settings.feedbakAuthor) { - settingsNavigate(.present(.sendMail(to: mail, subject: subject, content: contentPreText))) + router.present(.sendMail(to: mail, subject: subject, content: contentPreText)) } leading: { mailIcon.icon() } diff --git a/Sources/OversizeKit/SettingsKit/Views/About/SupportView.swift b/Sources/OversizeKit/SettingsKit/Views/About/SupportView.swift index 42fe265..d0aa8cc 100644 --- a/Sources/OversizeKit/SettingsKit/Views/About/SupportView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/About/SupportView.swift @@ -9,12 +9,13 @@ import OversizeComponents import OversizeLocalizable import OversizeResources +import OversizeRouter import OversizeServices import OversizeUI import SwiftUI public struct SupportView: View { - @Environment(\.settingsNavigate) var settingsNavigate + @Environment(Router.self) var router @Environment(\.iconStyle) var iconStyle: IconStyle public init() {} @@ -31,7 +32,7 @@ public struct SupportView: View { .toolbar { ToolbarItem(placement: .cancellationAction) { Button { - settingsNavigate(.dismissSheet) + router.dismissSheet() } label: { Image.Base.close.icon() } @@ -60,7 +61,7 @@ public struct SupportView: View { let subject = "Support" Row("Contact Us") { - settingsNavigate(.present(.sendMail(to: mail, subject: subject, content: contentPreText))) + router.present(.sendMail(to: mail, subject: subject, content: contentPreText)) } leading: { mailIcon.icon() } diff --git a/Sources/OversizeKit/SettingsKit/Views/Apperance/AppearanceSettingView.swift b/Sources/OversizeKit/SettingsKit/Views/Apperance/AppearanceSettingView.swift index 6a4e4be..89946c5 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Apperance/AppearanceSettingView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/Apperance/AppearanceSettingView.swift @@ -5,12 +5,13 @@ import OversizeCore import OversizeLocalizable +import OversizeRouter import OversizeServices import OversizeUI import SwiftUI public struct AppearanceSettingView: View { - @Environment(\.settingsNavigate) var settingsNavigate + @Environment(Router.self) var router @Environment(\.theme) private var theme: ThemeSettings @Environment(\.iconStyle) var iconStyle: IconStyle @Environment(\.isPremium) var isPremium: Bool @@ -62,7 +63,6 @@ public struct AppearanceSettingView: View { } .frame(width: 400, height: 300) // swiftlint:disable multiple_closures_with_trailing_closure superfluous_disable_command - .navigationTitle("Appearance") .preferredColorScheme(theme.appearance.colorScheme) } @@ -77,7 +77,7 @@ public struct AppearanceSettingView: View { VStack(spacing: .zero) { Text(appearance.name) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .font(.subheadline) .bold() @@ -87,7 +87,7 @@ public struct AppearanceSettingView: View { if appearance == theme.appearance { IconDeprecated(.checkCircle, color: Color.accent) } else { - IconDeprecated(.circle, color: .onSurfaceMediumEmphasis) + IconDeprecated(.circle, color: .onSurfaceSecondary) } } Spacer() @@ -129,7 +129,7 @@ public struct AppearanceSettingView: View { ) .onTapGesture { if index != 0, isPremium == false { - settingsNavigate(.present(.premium)) + router.present(.premium) } else { let defaultIconIndex = iconSettings.iconNames .firstIndex(of: UIApplication.shared.alternateIconName) ?? 0 @@ -158,7 +158,7 @@ public struct AppearanceSettingView: View { SectionView("Advanced settings") { VStack(spacing: .zero) { Row("Fonts") { - settingsNavigate(.move(.font)) + router.move(.font) } leading: { textIcon.icon() } @@ -168,14 +168,14 @@ public struct AppearanceSettingView: View { Switch(isOn: theme.$borderApp) { Row("Borders") { - settingsNavigate(.move(.border)) + router.move(.border) } leading: { borderIcon.icon() } .premium() } .onPremiumTap() - .onChange(of: theme.borderApp) { value in + .onChange(of: theme.borderApp) { _, value in theme.borderSurface = value theme.borderButtons = value theme.borderControls = value @@ -183,7 +183,7 @@ public struct AppearanceSettingView: View { } Row("Radius") { - settingsNavigate(.move(.radius)) + router.move(.radius) } leading: { radiusIcon.icon() } @@ -229,6 +229,7 @@ public struct AppearanceSettingView: View { } #if os(iOS) + @MainActor public class AppIconSettings: ObservableObject { public var iconNames: [String?] = [nil] @Published public var currentIndex = 0 diff --git a/Sources/OversizeKit/SettingsKit/Views/Apperance/BorderSettingView.swift b/Sources/OversizeKit/SettingsKit/Views/Apperance/BorderSettingView.swift index 70cba4f..6a41ab4 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Apperance/BorderSettingView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/Apperance/BorderSettingView.swift @@ -31,14 +31,14 @@ public struct BorderSettingView: View { SectionView { VStack(spacing: .zero) { Toggle("Borders in app", isOn: theme.$borderApp) - .onChange(of: theme.borderApp) { value in + .onChange(of: theme.borderApp) { _, value in theme.borderSurface = value theme.borderButtons = value theme.borderControls = value theme.borderTextFields = value } .headline() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .padding(.horizontal, .medium) .padding(.vertical, .small) @@ -50,13 +50,13 @@ public struct BorderSettingView: View { HStack { Text("Size") .subheadline() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Spacer() Text(String(format: "%.1f", theme.borderSize) + " px") .subheadline() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } Slider(value: theme.$borderSize, in: 0.5 ... 2, step: 0.5) diff --git a/Sources/OversizeKit/SettingsKit/Views/Apperance/FontSettingView.swift b/Sources/OversizeKit/SettingsKit/Views/Apperance/FontSettingView.swift index ed4fba7..ad9c8cf 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Apperance/FontSettingView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/Apperance/FontSettingView.swift @@ -56,11 +56,11 @@ public struct FontSettingView: View { VStack(alignment: .leading, spacing: 8) { Text("Aa") .font(.system(size: 34, weight: .heavy, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(fontStyle.rawValue.capitalizingFirstLetter()) .font(.system(size: 16, weight: .medium, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } Spacer() }.padding() @@ -74,11 +74,11 @@ public struct FontSettingView: View { VStack(alignment: .leading, spacing: 8) { Text("Aa") .font(.system(size: 34, weight: .heavy, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(fontStyle.rawValue.capitalizingFirstLetter()) .font(.system(size: 16, weight: .medium, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } Spacer() }.padding() @@ -91,16 +91,16 @@ public struct FontSettingView: View { Text("Button".uppercased()) .bold() .caption() - .onBackgroundMediumEmphasisForegroundColor() + .onBackgroundSecondaryForeground() SegmentedPickerSelector(FontDesignType.allCases, selection: theme.$fontButton) { fontStyle, _ in VStack(alignment: .center, spacing: 8) { Text("Aa") .font(.system(size: 28, weight: .heavy, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(fontStyle.rawValue.capitalizingFirstLetter()) .font(.system(size: 12, weight: .medium, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } } .segmentedControlStyle(.island(selected: .graySurface)) @@ -110,16 +110,16 @@ public struct FontSettingView: View { Text("Overline & caption".uppercased()) .bold() .caption() - .onBackgroundMediumEmphasisForegroundColor() + .onBackgroundSecondaryForeground() SegmentedPickerSelector(FontDesignType.allCases, selection: theme.$fontOverline) { fontStyle, _ in VStack(alignment: .center, spacing: 8) { Text("Aa") .font(.system(size: 28, weight: .heavy, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(fontStyle.rawValue.capitalizingFirstLetter()) .font(.system(size: 12, weight: .medium, design: fontStyle.system)) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } } .segmentedControlStyle(.island(selected: .graySurface)) @@ -138,34 +138,34 @@ extension FontSettingView { Text("Overline".uppercased()) .bold() .caption() - .onBackgroundMediumEmphasisForegroundColor() + .onBackgroundSecondaryForeground() Text("Large title") .largeTitle() - .onBackgroundHighEmphasisForegroundColor() + .onBackgroundPrimaryForeground() Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") .body() - .onBackgroundMediumEmphasisForegroundColor() + .onBackgroundSecondaryForeground() } VStack(alignment: .leading, spacing: Space.xxSmall.rawValue) { Text("Title") .title3() - .onBackgroundHighEmphasisForegroundColor() + .onBackgroundPrimaryForeground() Text("Subtitle") .headline() - .onBackgroundHighEmphasisForegroundColor() + .onBackgroundPrimaryForeground() Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") .bold() .subheadline() - .onBackgroundHighEmphasisForegroundColor() + .onBackgroundPrimaryForeground() Text("Button") .body() - .onBackgroundHighEmphasisForegroundColor() + .onBackgroundPrimaryForeground() .padding(.top, .xxxSmall) } } diff --git a/Sources/OversizeKit/SettingsKit/Views/Apperance/RadiusSettingView.swift b/Sources/OversizeKit/SettingsKit/Views/Apperance/RadiusSettingView.swift index 277773a..1d63b74 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Apperance/RadiusSettingView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/Apperance/RadiusSettingView.swift @@ -32,13 +32,13 @@ public struct RadiusSettingView: View { HStack { Text("Size") .subheadline() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Spacer() Text(String(format: "%.0f", theme.radius) + " px") .subheadline() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) } Slider(value: theme.$radius, in: 0 ... 12, step: 4) diff --git a/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeView.swift b/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeView.swift index bd3d913..c0484ee 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeView.swift @@ -9,8 +9,8 @@ import OversizeUI import SwiftUI public struct SetPINCodeView: View { - @Environment(\.settingsNavigate) var settingsNavigate - @EnvironmentObject private var hudRouter: HUDRouter + @Environment(Router.self) var router + @Environment(HUDRouter.self) private var hudRouter: HUDRouter @ObservedObject var viewModel: SetPINCodeViewModel @Environment(\.dismiss) var dismiss @@ -23,7 +23,7 @@ public struct SetPINCodeView: View { .toolbar { ToolbarItem(placement: .cancellationAction) { Button { - settingsNavigate(.dismiss) + router.dismiss() } label: { Image.Base.close.icon() } @@ -53,6 +53,7 @@ public struct SetPINCodeView: View { { viewModel.checkNewPINCode() } biometricAction: {} + case .confirmNewPINField: LockscreenView(pinCode: $viewModel.confirmNewCodeField, state: $viewModel.authState, diff --git a/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeViewModel.swift b/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeViewModel.swift index a75ebd3..3ef7f19 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeViewModel.swift +++ b/Sources/OversizeKit/SettingsKit/Views/Security/PINCode/SetPINCodeViewModel.swift @@ -9,17 +9,18 @@ import OversizeServices import OversizeUI import SwiftUI -public enum PINCodeAction: Identifiable { +public enum PINCodeAction: Identifiable, Sendable { case set, update public var id: Int { hashValue } } -public enum SetPINCodeViewState { +public enum SetPINCodeViewState: Sendable { case oldPINField, newPINField, confirmNewPINField } +@MainActor public final class SetPINCodeViewModel: ObservableObject { @Published public var settingsStore: SettingsService diff --git a/Sources/OversizeKit/SettingsKit/Views/Security/SecuritySettingsView.swift b/Sources/OversizeKit/SettingsKit/Views/Security/SecuritySettingsView.swift index 1bb69ed..dc09593 100644 --- a/Sources/OversizeKit/SettingsKit/Views/Security/SecuritySettingsView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/Security/SecuritySettingsView.swift @@ -5,6 +5,7 @@ import Factory import OversizeLocalizable +import OversizeRouter import OversizeServices import OversizeUI import SwiftUI @@ -13,7 +14,7 @@ import SwiftUI public struct SecuritySettingsView: View { @Injected(\.biometricService) var biometricService - @Environment(\.settingsNavigate) var settingsNavigate + @Environment(Router.self) var router @StateObject var settingsService = SettingsService() public init() {} @@ -51,7 +52,7 @@ extension SecuritySettingsView { ) { Row(biometricService.biometricType.rawValue) { Image(systemName: biometricImageName) - .foregroundColor(Color.onBackgroundHighEmphasis) + .foregroundColor(Color.onBackgroundPrimary) .font(.system(size: 20, weight: .semibold)) .frame(width: 24, height: 24, alignment: .center) } @@ -66,7 +67,7 @@ extension SecuritySettingsView { if settingsService.isSetedPinCode() { settingsService.pinCodeEnabend = $0 } else { - settingsNavigate(.present(.setPINCode)) + router.present(.setPINCode) } }) ) { @@ -77,7 +78,7 @@ extension SecuritySettingsView { if settingsService.isSetedPinCode() { Row(L10n.Security.changePINCode) { - settingsNavigate(.present(.updatePINCode)) + router.present(.updatePINCode) } .rowArrow() } diff --git a/Sources/OversizeKit/SettingsKit/Views/SettingsView.swift b/Sources/OversizeKit/SettingsKit/Views/SettingsView.swift index 3799b59..dec2871 100644 --- a/Sources/OversizeKit/SettingsKit/Views/SettingsView.swift +++ b/Sources/OversizeKit/SettingsKit/Views/SettingsView.swift @@ -5,14 +5,15 @@ import OversizeLocalizable import OversizeResources +import OversizeRouter import OversizeServices import OversizeUI import SwiftUI // swiftlint:disable line_length - public struct SettingsView: View { - @Environment(\.settingsNavigate) var settingsNavigate + + @Environment(Router.self) var router @Environment(\.iconStyle) var iconStyle: IconStyle @Environment(\.theme) var theme: ThemeSettings @StateObject var settingsService = SettingsService() @@ -78,7 +79,7 @@ extension SettingsView { VStack(spacing: .zero) { if FeatureFlags.app.apperance.valueOrFalse { Row(L10n.Settings.apperance) { - settingsNavigate(.move(.appearance)) + router.move(.appearance) } leading: { apperanceSettingsIcon.icon() } @@ -87,7 +88,7 @@ extension SettingsView { if FeatureFlags.app.сloudKit.valueOrFalse || FeatureFlags.app.healthKit.valueOrFalse { Row(L10n.Title.synchronization) { - settingsNavigate(.move(.sync)) + router.move(.sync) } leading: { cloudKitIcon.icon() } @@ -103,7 +104,7 @@ extension SettingsView { || FeatureFlags.secure.photoBreaker.valueOrFalse { Row(L10n.Security.title) { - settingsNavigate(.move(.security)) + router.move(.security) } leading: { securityIcon.icon() } @@ -112,7 +113,7 @@ extension SettingsView { if FeatureFlags.app.sounds.valueOrFalse || FeatureFlags.app.vibration.valueOrFalse { Row(soundsAndVibrationTitle) { - settingsNavigate(.move(.soundAndVibration)) + router.move(.soundAndVibration) } leading: { FeatureFlags.app.sounds.valueOrFalse ? soundIcon.icon() : vibrationIcon.icon() } @@ -121,7 +122,7 @@ extension SettingsView { if FeatureFlags.app.notifications.valueOrFalse { Row(L10n.Settings.notifications) { - settingsNavigate(.move(.notifications)) + router.move(.notifications) } leading: { notificationsIcon.icon() } @@ -204,7 +205,9 @@ extension SettingsView { SectionView(L10n.Settings.supportSection) { VStack(alignment: .leading) { Row("Get help") { - settingsNavigate(.present(.support, detents: [.medium])) + #if os(iOS) + router.present(.support, detents: [.medium]) + #endif } leading: { helpIcon.icon() } @@ -212,7 +215,9 @@ extension SettingsView { .buttonStyle(.row) Row("Send feedback") { - settingsNavigate(.present(.feedback, detents: [.medium])) + #if os(iOS) + router.present(.feedback, detents: [.medium]) + #endif } leading: { chatIcon.icon() } @@ -292,7 +297,7 @@ extension SettingsView { SectionView { VStack(spacing: .zero) { Row(L10n.Settings.about) { - settingsNavigate(.move(.about)) + router.move(.about) } leading: { infoIcon.icon() } diff --git a/Sources/OversizeKit/StateKit/LoadingViewState.swift b/Sources/OversizeKit/StateKit/LoadingViewState.swift index 07b19d2..05176b8 100644 --- a/Sources/OversizeKit/StateKit/LoadingViewState.swift +++ b/Sources/OversizeKit/StateKit/LoadingViewState.swift @@ -6,9 +6,44 @@ import Foundation import OversizeModels -public enum LoadingViewState { +public enum LoadingViewState: Equatable { + case idle case loading case result(Result) - case empty(String) case error(AppError) } + +public extension LoadingViewState { + var isLoading: Bool { + switch self { + case .loading, .idle: + return true + default: + return false + } + } + + var result: Result? { + switch self { + case let .result(result): + return result + default: + return nil + } + } + + static func == (lhs: LoadingViewState, rhs: LoadingViewState) -> Bool { + switch (lhs, rhs) { + case (.idle, .idle): + return true + case (.loading, .loading): + return true + case (.result, .result): + return true + case (.error, .error): + return true + default: + return false + } + } +} diff --git a/Sources/OversizeKit/StoreKit/StoreScreen/AppStoreProduct/AppStoreProductViewController.swift b/Sources/OversizeKit/StoreKit/StoreScreen/AppStoreProduct/AppStoreProductViewController.swift index 3b18d10..1928817 100644 --- a/Sources/OversizeKit/StoreKit/StoreScreen/AppStoreProduct/AppStoreProductViewController.swift +++ b/Sources/OversizeKit/StoreKit/StoreScreen/AppStoreProduct/AppStoreProductViewController.swift @@ -57,7 +57,7 @@ } } - extension AppStoreProductViewController: SKStoreProductViewControllerDelegate { + extension AppStoreProductViewController: @preconcurrency SKStoreProductViewControllerDelegate { public func productViewControllerDidFinish(_ viewController: SKStoreProductViewController) { viewController.dismiss(animated: true) } diff --git a/Sources/OversizeKit/StoreKit/StoreScreen/StoreInstuctinsView.swift b/Sources/OversizeKit/StoreKit/StoreScreen/StoreInstuctinsView.swift index a736466..b579acd 100644 --- a/Sources/OversizeKit/StoreKit/StoreScreen/StoreInstuctinsView.swift +++ b/Sources/OversizeKit/StoreKit/StoreScreen/StoreInstuctinsView.swift @@ -59,7 +59,7 @@ public struct StoreInstuctinsView: View { .environmentObject(viewModel) } } - .onChange(of: isPremium) { status in + .onChange(of: isPremium) { _, status in if status { dismiss() } @@ -80,12 +80,12 @@ public struct StoreInstuctinsView: View { VStack(spacing: .xSmall) { Text("How your free trial works") .largeTitle() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) if viewModel.isHaveSale { Group { Text("Begin your path towards feeling better with a ") - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) + Text("--% discount") .foregroundColor(.accent) @@ -107,7 +107,7 @@ public struct StoreInstuctinsView: View { .overlay { ScrollArrow(width: 30, offset: -5 + (offset * 0.05)) .stroke(style: StrokeStyle(lineWidth: 5, lineCap: .round)) - .foregroundColor(.onSurfaceHighEmphasis.opacity(0.3)) + .foregroundColor(.onSurfacePrimary.opacity(0.3)) .frame(width: 30) .offset(y: screenSize.safeAreaHeight - 300) // .opacity(1 - (offset * 0.01)) @@ -128,12 +128,12 @@ public struct StoreInstuctinsView: View { VStack(spacing: .xSmall) { Text("How your free trial works") .largeTitle() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) if viewModel.isHaveSale { Group { Text("Begin your path towards feeling better with a ") - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) + Text("\(viewModel.saleProcent)% discount") .foregroundColor(.accent) @@ -155,7 +155,7 @@ public struct StoreInstuctinsView: View { .overlay { ScrollArrow(width: 30, offset: -5 + (offset * 0.05)) .stroke(style: StrokeStyle(lineWidth: 5, lineCap: .round)) - .foregroundColor(.onSurfaceHighEmphasis.opacity(0.3)) + .foregroundColor(.onSurfacePrimary.opacity(0.3)) .frame(width: 30) .offset(y: screenSize.safeAreaHeight - 300) // .opacity(1 - (offset * 0.01)) @@ -179,7 +179,7 @@ public struct StoreInstuctinsView: View { await viewModel.updateSubscriptionStatus(products: data) } } - .onChange(of: data.purchasedAutoRenewable) { _ in + .onChange(of: data.purchasedAutoRenewable) { _, _ in Task { await viewModel.updateSubscriptionStatus(products: data) } @@ -192,7 +192,7 @@ public struct StoreInstuctinsView: View { HStack(alignment: .top, spacing: .small) { Resource.Store.zap .renderingMode(.template) - .foregroundColor(.onPrimaryHighEmphasis) + .foregroundColor(.onPrimary) .padding(.small) .background { Circle() @@ -226,7 +226,7 @@ public struct StoreInstuctinsView: View { HStack(alignment: .top, spacing: .small) { Image.Base.Notification.fill .renderingMode(.template) - .foregroundColor(Color.onSurfaceDisabled) + .foregroundColor(Color.onSurfaceTertiary) .padding(14) .background { Circle() @@ -252,7 +252,7 @@ public struct StoreInstuctinsView: View { HStack(alignment: .top, spacing: .small) { Image.Base.Star.fill .renderingMode(.template) - .foregroundColor(Color.onSurfaceDisabled) + .foregroundColor(Color.onSurfaceTertiary) .padding(14) .background { Circle() diff --git a/Sources/OversizeKit/StoreKit/StoreScreen/StoreSpecialOfferView.swift b/Sources/OversizeKit/StoreKit/StoreScreen/StoreSpecialOfferView.swift index 2f522b6..e2c0f39 100644 --- a/Sources/OversizeKit/StoreKit/StoreScreen/StoreSpecialOfferView.swift +++ b/Sources/OversizeKit/StoreKit/StoreScreen/StoreSpecialOfferView.swift @@ -43,7 +43,7 @@ public struct StoreSpecialOfferView: View { } } - .onChange(of: isPremium) { status in + .onChange(of: isPremium) { _, status in if status { dismiss() } @@ -223,7 +223,7 @@ public struct StoreSpecialOfferView: View { .overlay { ScrollArrow(width: 30, offset: -5 + (offset * 0.05)) .stroke(style: StrokeStyle(lineWidth: 5, lineCap: .round)) - .foregroundColor(.onSurfaceHighEmphasis.opacity(0.3)) + .foregroundColor(.onSurfacePrimary.opacity(0.3)) .frame(width: 30) .offset(y: screenSize.safeAreaHeight - 280) .opacity(1 - (offset * 0.01)) @@ -232,7 +232,7 @@ public struct StoreSpecialOfferView: View { VStack(spacing: .zero) { Text("Additional features in\nthe subscription") .title() - .onBackgroundHighEmphasisForegroundColor() + .onBackgroundPrimaryForeground() .multilineTextAlignment(.center) .fixedSize() .padding(.top, .large) @@ -252,7 +252,7 @@ public struct StoreSpecialOfferView: View { .task { await viewModel.updateSubscriptionStatus(products: data) } - .onChange(of: data.purchasedAutoRenewable) { _ in + .onChange(of: data.purchasedAutoRenewable) { _, _ in Task { await viewModel.updateSubscriptionStatus(products: data) } @@ -264,12 +264,12 @@ public struct StoreSpecialOfferView: View { VStack(spacing: .zero) { Text(badgeText.uppercased()) .footnote(.semibold) - .onBackgroundMediumEmphasisForegroundColor() + .onBackgroundSecondaryForeground() .padding(.bottom, .xxxSmall) Text(headline) .title(.bold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .frame(maxWidth: .infinity, alignment: .center) Text(event.title) @@ -277,7 +277,7 @@ public struct StoreSpecialOfferView: View { .foregroundColor(titleColor) Text(description) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) .headline(.regular) .padding(.top, .xSmall) } @@ -332,7 +332,7 @@ public struct StoreSpecialOfferView: View { if let accentColor = event.accentColor { return Color(hex: accentColor) } else { - return Color.onBackgroundHighEmphasis + return Color.onBackgroundPrimary } } diff --git a/Sources/OversizeKit/StoreKit/StoreScreen/StoreView.swift b/Sources/OversizeKit/StoreKit/StoreScreen/StoreView.swift index 42f78c7..861a886 100644 --- a/Sources/OversizeKit/StoreKit/StoreScreen/StoreView.swift +++ b/Sources/OversizeKit/StoreKit/StoreScreen/StoreView.swift @@ -93,11 +93,11 @@ import SwiftUI VStack(spacing: .xxSmall) { Text(titleText) .title() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(subtitleText) .headline() - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) } .multilineTextAlignment(.center) @@ -120,11 +120,11 @@ import SwiftUI VStack(spacing: .xxSmall) { Text(titleText) .title() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(subtitleText) .headline() - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) } .multilineTextAlignment(.center) @@ -163,14 +163,14 @@ import SwiftUI await viewModel.updateSubscriptionStatus(products: data) } } - .onChange(of: data.purchasedAutoRenewable) { _ in + .onChange(of: data.purchasedAutoRenewable) { _, _ in Task { // When `purchasedSubscriptions` changes, get the latest subscription status. await viewModel.updateSubscriptionStatus(products: data) } } - .onChange(of: viewModel.isPremium) { newValue in - isShowFireworks = newValue + .onChange(of: viewModel.isPremium) { _, status in + isShowFireworks = status DispatchQueue.main.asyncAfter(deadline: .now() + 30) { isShowFireworks = false } diff --git a/Sources/OversizeKit/StoreKit/StoreScreen/ViewModel/StoreViewModel.swift b/Sources/OversizeKit/StoreKit/StoreScreen/ViewModel/StoreViewModel.swift index fc1d271..346fe95 100644 --- a/Sources/OversizeKit/StoreKit/StoreScreen/ViewModel/StoreViewModel.swift +++ b/Sources/OversizeKit/StoreKit/StoreScreen/ViewModel/StoreViewModel.swift @@ -138,7 +138,6 @@ extension StoreViewModel { } } - // Percentage of decrease = |239.88 - 59.99|/239.88 = 179.89/239.88 = 0.74991662497916 = 74.991662497916% var saleProcent: String { guard let yearSubscriptionProduct else { return "" } if let monthSubscriptionProduct { diff --git a/Sources/OversizeKit/StoreKit/ViewModifier/PremiumBlockOverlay.swift b/Sources/OversizeKit/StoreKit/ViewModifier/PremiumBlockOverlay.swift index 0594af7..7fa7602 100644 --- a/Sources/OversizeKit/StoreKit/ViewModifier/PremiumBlockOverlay.swift +++ b/Sources/OversizeKit/StoreKit/ViewModifier/PremiumBlockOverlay.swift @@ -45,12 +45,12 @@ public struct PremiumBlockOverlay: ViewModifier { VStack(spacing: .small) { Text(title) .title() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) if let subtitle { Text(subtitle) .headline(.medium) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) } } .multilineTextAlignment(.center) diff --git a/Sources/OversizeKit/StoreKit/Views/BuyButtonStyle.swift b/Sources/OversizeKit/StoreKit/Views/BuyButtonStyle.swift index caa0b85..9e71cad 100644 --- a/Sources/OversizeKit/StoreKit/Views/BuyButtonStyle.swift +++ b/Sources/OversizeKit/StoreKit/Views/BuyButtonStyle.swift @@ -49,7 +49,7 @@ public struct PaymentButtonStyle: ButtonStyle { configuration.label .body(true) .opacity(isLoading ? 0 : 1) - .foregroundColor(.onPrimaryHighEmphasis) + .foregroundColor(.onPrimary) .padding(.horizontal, horizontalPadding) .padding(.vertical, verticalPadding) .frame(maxWidth: maxWidth) @@ -67,7 +67,7 @@ public struct PaymentButtonStyle: ButtonStyle { ) .overlay { RoundedRectangle(cornerRadius: 10, style: .continuous) - .strokeBorder(Color.onSurfaceHighEmphasis.opacity(0.15), lineWidth: 2) + .strokeBorder(Color.onSurfacePrimary.opacity(0.15), lineWidth: 2) .opacity(isBordered || theme.borderButtons ? 1 : 0) } } @@ -76,7 +76,7 @@ public struct PaymentButtonStyle: ButtonStyle { private func loadingView(for _: ButtonRole?) -> some View { if isLoading { ProgressView() - .progressViewStyle(CircularProgressViewStyle(tint: Color.onPrimaryHighEmphasis)) + .progressViewStyle(CircularProgressViewStyle(tint: Color.onPrimary)) } else { EmptyView() } diff --git a/Sources/OversizeKit/StoreKit/Views/FireworksBubbles.swift b/Sources/OversizeKit/StoreKit/Views/FireworksBubbles.swift index c2e78af..6db793a 100644 --- a/Sources/OversizeKit/StoreKit/Views/FireworksBubbles.swift +++ b/Sources/OversizeKit/StoreKit/Views/FireworksBubbles.swift @@ -54,7 +54,7 @@ struct FireworksBubbles: View { ZStack { ForEach(0 ..< Int.random(in: 2 ... 5), id: \.self) { _ in Circle() - .fill(Color.onPrimaryDisabled) + .fill(Color.onPrimaryTertiary) .frame(width: 30, height: 30) .modifier(ParticlesBubblesModifier()) .offset(x: CGFloat.random(in: -200 ... 200), y: CGFloat.random(in: -200 ... 200)) diff --git a/Sources/OversizeKit/StoreKit/Views/PrmiumBannerRow.swift b/Sources/OversizeKit/StoreKit/Views/PrmiumBannerRow.swift index d479082..7818f76 100644 --- a/Sources/OversizeKit/StoreKit/Views/PrmiumBannerRow.swift +++ b/Sources/OversizeKit/StoreKit/Views/PrmiumBannerRow.swift @@ -67,14 +67,14 @@ public struct PrmiumBannerRow: View { Text(Info.store.subscriptionsName) .headline(.semibold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Spacer() HStack(spacing: .small) { Text(viewModel.subsribtionStatusText) .headline(.medium) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) Circle() .foregroundColor(viewModel.subsribtionStatusColor) @@ -118,13 +118,13 @@ public extension PrmiumBannerRow { } .background( RoundedRectangle(cornerRadius: Radius.small.rawValue, style: .continuous) - .fill(Color.onPrimaryHighEmphasis + .fill(Color.onPrimary )) Text(Info.store.subscriptionsDescription) .headline(.semibold) - .onPrimaryHighEmphasisForegroundColor() + .onPrimaryForeground() .multilineTextAlignment(.center) .padding(.top, Space.xSmall) .frame(maxWidth: 260) diff --git a/Sources/OversizeKit/StoreKit/Views/StoreFeatureDetailView.swift b/Sources/OversizeKit/StoreKit/Views/StoreFeatureDetailView.swift index d0ff026..d192629 100644 --- a/Sources/OversizeKit/StoreKit/Views/StoreFeatureDetailView.swift +++ b/Sources/OversizeKit/StoreKit/Views/StoreFeatureDetailView.swift @@ -45,13 +45,16 @@ public struct StoreFeatureDetailView: View { Button { dismiss() } label: { - IconDeprecated(.xMini, color: selection.screenURL != nil ? .onPrimaryHighEmphasis : .onSurfaceDisabled) - .padding(.xxSmall) - .background { - Circle() - .fill(.ultraThinMaterial) - } - .padding(.small) + IconDeprecated( + .xMini, + color: selection.screenURL != nil ? .onPrimary : .onSurfaceTertiary + ) + .padding(.xxSmall) + .background { + Circle() + .fill(.ultraThinMaterial) + } + .padding(.small) } } #endif diff --git a/Sources/OversizeKit/StoreKit/Views/StoreFeaturesLargeView.swift b/Sources/OversizeKit/StoreKit/Views/StoreFeaturesLargeView.swift index 0668344..3b20f80 100644 --- a/Sources/OversizeKit/StoreKit/Views/StoreFeaturesLargeView.swift +++ b/Sources/OversizeKit/StoreKit/Views/StoreFeaturesLargeView.swift @@ -54,11 +54,11 @@ struct StoreFeaturesLargeView: View { VStack(spacing: .xxSmall) { Text(feature.title.valueOrEmpty) .title2(.bold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(feature.subtitle.valueOrEmpty) .body(.medium) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) } .padding(.vertical, .medium) .padding(.horizontal, .xSmall) @@ -119,11 +119,11 @@ struct StoreFeaturesLargeView: View { VStack(spacing: .xSmall) { Text(feature.title.valueOrEmpty) .title2(.bold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(feature.subtitle.valueOrEmpty) .body(.medium) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) } } .padding(.vertical, .large) diff --git a/Sources/OversizeKit/StoreKit/Views/StoreFeaturesView.swift b/Sources/OversizeKit/StoreKit/Views/StoreFeaturesView.swift index a0c895b..c20fc1a 100644 --- a/Sources/OversizeKit/StoreKit/Views/StoreFeaturesView.swift +++ b/Sources/OversizeKit/StoreKit/Views/StoreFeaturesView.swift @@ -31,7 +31,7 @@ struct StoreFeaturesView: View { .renderingMode(.template) } } - .onPrimaryHighEmphasisForegroundColor() + .onPrimaryForeground() .iconOnSurface(surfaceSolor: backgroundColor(feature: feature)) } .rowArrow() diff --git a/Sources/OversizeKit/StoreKit/Views/StorePaymentButtonBar.swift b/Sources/OversizeKit/StoreKit/Views/StorePaymentButtonBar.swift index 0399d3b..42ad0df 100644 --- a/Sources/OversizeKit/StoreKit/Views/StorePaymentButtonBar.swift +++ b/Sources/OversizeKit/StoreKit/Views/StorePaymentButtonBar.swift @@ -23,7 +23,7 @@ struct StorePaymentButtonBar: View { if showDescription { Text(viewModel.selectedProductButtonDescription) .subheadline(.semibold) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) .padding(.vertical, 20) } diff --git a/Sources/OversizeKit/StoreKit/Views/StoreProductView.swift b/Sources/OversizeKit/StoreKit/Views/StoreProductView.swift index 2fa0d08..a10a81c 100644 --- a/Sources/OversizeKit/StoreKit/Views/StoreProductView.swift +++ b/Sources/OversizeKit/StoreKit/Views/StoreProductView.swift @@ -148,7 +148,7 @@ public struct StoreProductView: View { if isSelected { Circle() - .fill(Color.onPrimaryHighEmphasis) + .fill(Color.onPrimary) .frame(width: 20, height: 20) .overlay { IconDeprecated(.checkMini, color: topLabelbackgroundColor) @@ -174,21 +174,21 @@ public struct StoreProductView: View { VStack(spacing: .zero) { Text(product.displayMonthsCount) .title2() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Text(product.displayMonthsCountDescription) .footnote(.bold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) HStack(spacing: .zero) { Text(product.displayPrice) .subheadline(.semibold) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .padding(.top, .xxxSmall) Text(product.displayPeriod) .caption2() - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) .padding(.top, .xxxSmall) } .padding(.top, .xxxSmall) @@ -209,7 +209,7 @@ public struct StoreProductView: View { .fill(topLabelbackgroundColor) .frame(width: 20, height: 20) .overlay { - IconDeprecated(.checkMini, color: Color.onPrimaryHighEmphasis) + IconDeprecated(.checkMini, color: Color.onPrimary) } .padding(.top, .xxxSmall) .padding(.trailing, .xxxSmall) @@ -230,12 +230,12 @@ public struct StoreProductView: View { HStack { Text(product.displayName) .headline() - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) if isHaveSale, !isPurchased { Text("Save " + saleProcent + "%") .caption2(.bold) - .foregroundColor(.onPrimaryHighEmphasis) + .foregroundColor(.onPrimary) .padding(.horizontal, .xxSmall) .padding(.vertical, .xxxSmall) .background { @@ -267,14 +267,14 @@ public struct StoreProductView: View { .caption2() .padding(.top, .xxxSmall) } - .foregroundColor(.onSurfaceDisabled) + .foregroundColor(.onSurfaceTertiary) .padding(.vertical, .xxSmall) #if os(iOS) if isHaveSale, !isPurchased { Text("Save " + saleProcent + "%") .caption2(.bold) - .foregroundColor(.onPrimaryHighEmphasis) + .foregroundColor(.onPrimary) .padding(.vertical, .xxxSmall) .frame(maxWidth: .infinity) .background { @@ -299,7 +299,7 @@ public struct StoreProductView: View { VStack(alignment: .trailing, spacing: .xxSmall) { Text(product.displayPriceWithPeriod) .headline(.semibold) - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) if let subscriptionUnit = product.subscription?.subscriptionPeriod.unit, subscriptionUnit == .year { HStack(spacing: 2) { @@ -307,12 +307,12 @@ public struct StoreProductView: View { Text(monthSubscriptionProduct.displayPrice) .strikethrough() .subheadline() - .foregroundColor(.onSurfaceDisabled) + .foregroundColor(.onSurfaceTertiary) } Text(product.displayMonthPrice + product.displayMonthPricePeriod) .subheadline() - .foregroundColor(.onSurfaceMediumEmphasis) + .foregroundColor(.onSurfaceSecondary) } } } @@ -379,7 +379,7 @@ public struct StoreProductView: View { var topLabelForegroundColor: Color { if isPurchased || isSelected { - return .onPrimaryHighEmphasis + return .onPrimary } else { return Palette.violet.color } @@ -387,7 +387,7 @@ public struct StoreProductView: View { var descriptionForegroundColor: Color { if isPurchased || product.type != .autoRenewable { - return .onSurfaceMediumEmphasis + return .onSurfaceSecondary } else { return .warning } diff --git a/Sources/OversizeKit/StoreKit/Views/SubscriptionPrivacyView.swift b/Sources/OversizeKit/StoreKit/Views/SubscriptionPrivacyView.swift index 692e91e..6b8ec96 100644 --- a/Sources/OversizeKit/StoreKit/Views/SubscriptionPrivacyView.swift +++ b/Sources/OversizeKit/StoreKit/Views/SubscriptionPrivacyView.swift @@ -21,11 +21,11 @@ struct SubscriptionPrivacyView: View { VStack(spacing: .xxSmall) { Text("About \(Info.store.subscriptionsName) subscription") .subheadline(.bold) - .foregroundColor(Color.onSurfaceDisabled) + .foregroundColor(Color.onSurfaceTertiary) Text("\(Info.store.subscriptionsName) subscription is required to get access to all functions. Regardless whether the subscription has free trial period or not it automatically renews with the price and duration given above unless it is canceled at least 24 hours before the end of the current period. Payment will be charged to your Apple ID account at the confirmation of purchase. Your account will be charged for renewal within 24 hours prior to the end of the current period. You can manage and cancel your subscriptions by going to your account settings on the App Store after purchase. Any unused portion of a free trial period, if offered, will be forfeited when the user purchases a subscription to that publication, where applicable.") .caption() - .foregroundColor(Color.onSurfaceMediumEmphasis) + .foregroundColor(Color.onSurfaceSecondary) #if os(iOS) HStack(spacing: .xxSmall) { @@ -62,7 +62,7 @@ struct SubscriptionPrivacyView: View { } } .subheadline(.bold) - .foregroundColor(Color.onSurfaceDisabled) + .foregroundColor(Color.onSurfaceTertiary) .padding(.top, .xxxSmall) #endif } diff --git a/Sources/OversizeKit/SystemKit/SystemServices.swift b/Sources/OversizeKit/SystemKit/SystemServices.swift index dbbef9a..a9cc75f 100644 --- a/Sources/OversizeKit/SystemKit/SystemServices.swift +++ b/Sources/OversizeKit/SystemKit/SystemServices.swift @@ -4,26 +4,25 @@ // import Factory -import OversizeCore -import OversizeLocalizable import OversizeServices import OversizeStoreService import OversizeUI import SwiftUI public struct SystemServicesModifier: ViewModifier { - @Injected(\.appStateService) var appState: AppStateService - @Injected(\.settingsService) var settingsService: SettingsServiceProtocol - @Injected(\.appStoreReviewService) var appStoreReviewService: AppStoreReviewServiceProtocol + @Injected(\.appStateService) private var appState: AppStateService + @Injected(\.settingsService) private var settingsService: SettingsServiceProtocol + @Injected(\.appStoreReviewService) private var appStoreReviewService: AppStoreReviewServiceProtocol - @Environment(\.scenePhase) var scenePhase: ScenePhase - @Environment(\.theme) var theme: ThemeSettings - @AppStorage("AppState.PremiumState") var isPremium: Bool = false + @Environment(\.scenePhase) private var scenePhase: ScenePhase + @Environment(\.theme) private var theme: ThemeSettings + @AppStorage("AppState.PremiumState") private var isPremium: Bool = false - @State var blurRadius: CGFloat = 0 - @State var oppacity: CGFloat = 1 + @State private var blurRadius: CGFloat = 0 + @State private var oppacity: CGFloat = 1 + @State private var screnSize: ScreenSize = .init(width: 375, height: 667) - enum FullScreenSheet: Identifiable, Equatable { + private enum FullScreenSheet: Identifiable, Equatable, Sendable { case onboarding case payWall case lockscreen @@ -32,41 +31,11 @@ public struct SystemServicesModifier: ViewModifier { } } - public init() {} - - @State private var screnSize: ScreenSize = .init(width: 375, height: 667) + public nonisolated init() {} public func body(content: Content) -> some View { GeometryReader { geometry in content - .onChange(of: scenePhase, perform: { value in - switch value { - case .active: - if settingsService.blurMinimizeEnabend { - withAnimation { - blurRadius = 0 - } - } - case .background: - if settingsService.blurMinimizeEnabend { - withAnimation { - blurRadius = 10 - } - } - case .inactive: - if settingsService.blurMinimizeEnabend { - withAnimation { - blurRadius = 10 - } - } - @unknown default: - break - } - }) - .onAppear { - let updatedScreenSize = ScreenSize(geometry: geometry) - screnSize = updatedScreenSize - } .blur(radius: blurRadius) .preferredColorScheme(theme.appearance.colorScheme) .premiumStatus(isPremium) @@ -75,12 +44,46 @@ public struct SystemServicesModifier: ViewModifier { #if os(iOS) .accentColor(theme.accentColor) #endif + .onAppear(perform: { onAppear(geometry: geometry) }) + .onChange(of: scenePhase) { _, phase in + onChangeScenePhase(phase) + } } } + + private func onChangeScenePhase(_ phase: ScenePhase) { + switch phase { + case .active: + if settingsService.blurMinimizeEnabend { + withAnimation { + blurRadius = 0 + } + } + case .background: + if settingsService.blurMinimizeEnabend { + withAnimation { + blurRadius = 10 + } + } + case .inactive: + if settingsService.blurMinimizeEnabend { + withAnimation { + blurRadius = 10 + } + } + @unknown default: + break + } + } + + private func onAppear(geometry: GeometryProxy) { + let updatedScreenSize = ScreenSize(geometry: geometry) + screnSize = updatedScreenSize + } } public extension View { - func systemServices() -> some View { + nonisolated func systemServices() -> some View { modifier(SystemServicesModifier()) } } diff --git a/Sources/OversizeLocationKit/AddressField/AddressField.swift b/Sources/OversizeLocationKit/AddressField/AddressField.swift index a126453..2582a24 100644 --- a/Sources/OversizeLocationKit/AddressField/AddressField.swift +++ b/Sources/OversizeLocationKit/AddressField/AddressField.swift @@ -59,7 +59,7 @@ public struct AddressField: View { HStack { Text(title) .subheadline(.medium) - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) Spacer() } } @@ -70,7 +70,7 @@ public struct AddressField: View { Text(title) .font(!isSlectedAddress ? .headline : .subheadline) .fontWeight(!isSlectedAddress ? .medium : .semibold) - .onSurfaceDisabledForegroundColor() + .onSurfaceTertiaryForeground() .offset(y: !isSlectedAddress ? 0 : -13) .opacity(!isSlectedAddress ? 0 : 1) } @@ -81,12 +81,12 @@ public struct AddressField: View { .lineLimit(1) } Spacer() - IconDeprecated(.chevronDown, color: .onSurfaceHighEmphasis) + IconDeprecated(.chevronDown, color: .onSurfacePrimary) } } .contentShape(Rectangle()) } - .foregroundColor(.onSurfaceHighEmphasis) + .foregroundColor(.onSurfacePrimary) .buttonStyle(.field) #if !os(watchOS) .sheet(isPresented: $isShowPicker) { diff --git a/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift b/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift index d4a92a4..c46b204 100644 --- a/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift +++ b/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift @@ -44,7 +44,7 @@ import SwiftUI Spacer() } .title3() - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .padding(.vertical, .xxSmall) .paddingContent(.horizontal) @@ -60,7 +60,7 @@ import SwiftUI .topToolbar { TextField("Search places or addresses", text: $viewModel.searchTerm) .submitScope(viewModel.searchTerm.count < 2) - .textFieldStyle(DefaultPlaceholderTextFieldStyle()) + .textFieldStyle(.default) .focused($isFocusSearth) .submitLabel(.done) .onSubmit { diff --git a/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift b/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift index f004927..e36b40d 100644 --- a/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift +++ b/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift @@ -81,7 +81,7 @@ import SwiftUI viewModel.zoomIn() } label: { IconDeprecated(.plus) - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .padding(.xxSmall) } @@ -89,7 +89,7 @@ import SwiftUI viewModel.zoomOut() } label: { IconDeprecated(.minus) - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .padding(.xxSmall) } } @@ -106,7 +106,7 @@ import SwiftUI } label: { IconDeprecated(.navigation) - .onSurfaceMediumEmphasisForegroundColor() + .onSurfaceSecondaryForeground() .padding(.xxSmall) } .background { diff --git a/Sources/OversizeNotificationKit/LocalNotificationSetScreenViewModel.swift b/Sources/OversizeNotificationKit/LocalNotificationSetScreenViewModel.swift index 66f9e4e..94d24ed 100644 --- a/Sources/OversizeNotificationKit/LocalNotificationSetScreenViewModel.swift +++ b/Sources/OversizeNotificationKit/LocalNotificationSetScreenViewModel.swift @@ -38,13 +38,20 @@ import SwiftUI func setNotification(timeBefore: LocalNotificationTime) async { let notificationTime = date.addingTimeInterval(timeBefore.timeInterval) let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: notificationTime) + + let stringUserInfo = userInfo?.reduce(into: [String: String]()) { result, pair in + if let key = pair.key as? String, let value = pair.value as? String { + result[key] = value + } + } + await localNotificationService.schedule(localNotification: .init( id: id, title: title, body: body, dateComponents: dateComponents, repeats: false, - userInfo: userInfo + userInfo: stringUserInfo )) } diff --git a/Sources/OversizeOnboardingKit/OnboardingItem.swift b/Sources/OversizeOnboardingKit/OnboardingItem.swift deleted file mode 100644 index 76e1028..0000000 --- a/Sources/OversizeOnboardingKit/OnboardingItem.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright © 2022 Alexander Romanov -// OnboardingItem.swift -// - -import SwiftUI - -public struct OnboardingItem: Identifiable, Equatable { - public var id = UUID() - public var image: Image? - public var title: String? - public var subtitle: String? - - public init(id: UUID = UUID(), image: Image? = nil, title: String? = nil, subtitle: String? = nil) { - self.id = id - self.image = image - self.title = title - self.subtitle = subtitle - } -} diff --git a/Sources/OversizeOnboardingKit/OnboardingItemPreferenceKey.swift b/Sources/OversizeOnboardingKit/OnboardingItemPreferenceKey.swift deleted file mode 100644 index 0335c7f..0000000 --- a/Sources/OversizeOnboardingKit/OnboardingItemPreferenceKey.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Copyright © 2022 Alexander Romanov -// OnboardingItemPreferenceKey.swift -// - -import SwiftUI - -struct OnboardingItemPreferenceKey: PreferenceKey { - static var defaultValue: [OnboardingItem] = [] - - static func reduce(value: inout [OnboardingItem], nextValue: () -> [OnboardingItem]) { - value += nextValue() - } -} diff --git a/Sources/OversizeOnboardingKit/OnboardingItemViewModifier.swift b/Sources/OversizeOnboardingKit/OnboardingItemViewModifier.swift deleted file mode 100644 index 23590f6..0000000 --- a/Sources/OversizeOnboardingKit/OnboardingItemViewModifier.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2022 Alexander Romanov -// OnboardingItemViewModifier.swift -// - -import SwiftUI - -struct OnboardingItemViewModifier: ViewModifier { - let onboardingItem: OnboardingItem - - func body(content: Content) -> some View { - content - .preference(key: OnboardingItemPreferenceKey.self, value: [onboardingItem]) - } -} - -public extension View { - func onboardingItem(_ label: () -> OnboardingItem) -> some View { - modifier(OnboardingItemViewModifier(onboardingItem: label())) - } -} diff --git a/Sources/OversizeOnboardingKit/OnboardingView.swift b/Sources/OversizeOnboardingKit/OnboardingView.swift index a12d76e..6ac81eb 100644 --- a/Sources/OversizeOnboardingKit/OnboardingView.swift +++ b/Sources/OversizeOnboardingKit/OnboardingView.swift @@ -1,111 +1,125 @@ // -// Copyright © 2023 Alexander Romanov -// OnboardingView.swift +// Copyright © 2024 Alexander Romanov +// OnboardView.swift, created on 16.09.2024 // import OversizeUI import SwiftUI -public struct OnboardingView: View { - @Environment(\.screenSize) var screenSize - - @Binding private var selection: Int - - @Namespace private var onboardingItem - - @State private var slides: [OnboardingItem] = [] - - private let finishAction: (() -> Void)? - - private var content: Content - - public init(selection: Binding, finishAction: (() -> Void)? = nil, @ViewBuilder content: () -> Content) { +public struct OnboardView: View where A: View, C: View { + private let content: C + private let actions: Group + private let backAction: (() -> Void)? + private let skipAction: (() -> Void)? + private let helpAction: (() -> Void)? + + public init( + @ViewBuilder content: () -> C, + @ViewBuilder actions: () -> A, + backAction: (() -> Void)? = nil, + skipAction: (() -> Void)? = nil, + helpAction: (() -> Void)? = nil + ) { self.content = content() - self.finishAction = finishAction - _selection = selection + self.actions = Group { actions() } + self.backAction = backAction + self.skipAction = skipAction + self.helpAction = helpAction } public var body: some View { - ZStack { - VStack { - PageIndexView($selection, maxIndex: slides.count) - .padding(.top, .large) - Spacer() - } - - TabView(selection: $selection) { - // ForEach(Array(slides.enumerated()), id: \.offset) { index, element in + content + .ignoresSafeArea(.all) + .frame( + maxWidth: .infinity, + maxHeight: .infinity + ) + .safeAreaInset(edge: .top, content: topButtons) + .safeAreaInset(edge: .bottom, content: bottomButtons) + } - tabItem(tabItem: OnboardingItem(title: "Title", subtitle: "Sub"), index: 0) - // .tag(index) - // } - } + private func topButtons() -> some View { + HStack { #if os(iOS) - .tabViewStyle(.page(indexDisplayMode: .never)) - .indexViewStyle(.page(backgroundDisplayMode: .never)) + if helpAction != nil { + Button { + helpAction?() + } label: { + Text("Help") + } + .buttonStyle(.tertiary) + .controlBorderShape(.capsule) + .accent() + .controlSize(.mini) + } #endif + + Spacer() + + if skipAction != nil { + Button { + skipAction?() + } label: { + Text("Skip") + } + .buttonStyle(.tertiary) + .controlBorderShape(.capsule) + .accent() + #if !os(tvOS) + .controlSize(.mini) + #endif + } } - .background( - Color.backgroundSecondary.ignoresSafeArea() - ) - .onPreferenceChange(OnboardingItemPreferenceKey.self) { value in - slides = value - } + .padding(.medium) } - private func tabItem(tabItem: OnboardingItem, index _: Int) -> some View { - VStack(spacing: .small) { - if let image = tabItem.image { - image - } + private func bottomButtons() -> some View { + #if os(iOS) + HStack(spacing: .small) { + if let backAction { + Button { + backAction() + } label: { + Image.Base.arrowLeft.icon() + } + .buttonStyle(.quaternary) + .accentColor(.secondary) + } - VStack { - if let title = tabItem.title { - Text(title) - .largeTitle() - .foregroundColor(.onSurfaceHighEmphasis) - .padding(.bottom, .small) + VStack(spacing: .xxxSmall) { + actions + } + } + .padding(.medium) + #else + HStack(spacing: .xSmall) { + if let helpAction { + Button("Help", action: helpAction) + .help("Help") + .controlSize(.extraLarge) + .buttonStyle(.bordered) } - if let subtitle = tabItem.subtitle { - Text(subtitle) - .foregroundColor(.onSurfaceMediumEmphasis) - .fontWeight(.regular) - .font(.system(size: 19)) + Spacer() + + if let backAction { + Button( + "Back", + action: backAction + ) + .controlSize(.extraLarge) + .buttonStyle(.bordered) } + + actions + .controlSize(.extraLarge) + .buttonStyle(.borderedProminent) } - .offset(y: screenSize.height < 812 ? -50 : 0) - } - .multilineTextAlignment(.center) - .frame(maxWidth: 320) - .offset(y: -50) - .padding(.bottom, .xLarge) + .padding(.small) + .background(Color.surfacePrimary) + .overlay(alignment: .top) { + Separator() + } + #endif } } - -// struct FloatingTabBarExample: View { -// @State var selection = 0 -// -// var body: some View { -// FloatingTabBar(selection: $selection, plusAction: { print("plus") }) { -// Color.gray -// .floatingTabItem { -// TabItem(icon: Image(systemName: "star")) -// } -// .opacity(selection == 0 ? 1 : 0) -// -// Color.blue -// .floatingTabItem { -// TabItem(icon: Image(systemName: "plus")) -// } -// .opacity(selection == 1 ? 1 : 0) -// } -// } -// } - -// struct FloatingTabBar_Previews: PreviewProvider { -// static var previews: some View { -// FloatingTabBarExample() -// } -// } -// diff --git a/Sources/OversizePhotoKit/PhotosGalleryView.swift b/Sources/OversizePhotoKit/PhotosGalleryView.swift index 7aff10e..5c13e1c 100644 --- a/Sources/OversizePhotoKit/PhotosGalleryView.swift +++ b/Sources/OversizePhotoKit/PhotosGalleryView.swift @@ -23,7 +23,7 @@ public struct PhotosGalleryView: View { if images.isEmpty { Text("Not photos") .title3() - .onSurfaceHighEmphasisForegroundColor() + .onSurfacePrimaryForeground() } else { ImageGridView(images, columnCount: .constant(3)) { image in let index = images.firstIndex(of: image)