diff --git a/Normal.xcodeproj/project.pbxproj b/Normal.xcodeproj/project.pbxproj index 08d1336..c00ff82 100644 --- a/Normal.xcodeproj/project.pbxproj +++ b/Normal.xcodeproj/project.pbxproj @@ -652,7 +652,7 @@ INFOPLIST_FILE = NormalMonitor/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = NormalMonitor; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -683,7 +683,7 @@ INFOPLIST_FILE = NormalMonitor/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = NormalMonitor; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -755,7 +755,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.7; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; @@ -816,7 +816,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.7; MTL_ENABLE_DEBUG_INFO = NO; @@ -914,7 +914,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; PRODUCT_BUNDLE_IDENTIFIER = org.normalengineering.NormalTests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -935,7 +935,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; PRODUCT_BUNDLE_IDENTIFIER = org.normalengineering.NormalTests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -998,7 +998,7 @@ INFOPLIST_FILE = NormalWidget/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Normal; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1030,7 +1030,7 @@ INFOPLIST_FILE = NormalWidget/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Normal; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1061,7 +1061,7 @@ INFOPLIST_FILE = NormalShield/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = NormalShield; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1092,7 +1092,7 @@ INFOPLIST_FILE = NormalShield/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = NormalShield; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 18.0; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/Normal/Services/WidgetSync.swift b/Normal/Services/WidgetSync.swift index ca5dde0..20a5349 100644 --- a/Normal/Services/WidgetSync.swift +++ b/Normal/Services/WidgetSync.swift @@ -30,7 +30,9 @@ enum WidgetSync { static func reloadTimelines() { WidgetCenter.shared.reloadAllTimelines() - ControlCenter.shared.reloadAllControls() + if #available(iOS 18.0, *) { + ControlCenter.shared.reloadAllControls() + } } } diff --git a/Normal/Views/Settings/SettingsView.swift b/Normal/Views/Settings/SettingsView.swift index b14bbd6..e06684c 100644 --- a/Normal/Views/Settings/SettingsView.swift +++ b/Normal/Views/Settings/SettingsView.swift @@ -30,6 +30,29 @@ struct SettingsView: View { var body: some View { NavigationStack { + tabView + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button("Close") { dismiss() } + } + } + .alert("Emergency Unblock", isPresented: $showConfirmation) { + Button("Unblock All Apps", role: .destructive, action: performEmergencyUnblock) + Button("Cancel", role: .cancel) {} + } message: { + Text("This will immediately remove all app blocks. Each unblock regenerates after 6 months. You have \(settings.emergencyUnblocksAvailable) remaining.") + } + .alert("All Apps Unblocked", isPresented: $showSuccessAlert) { + Button("OK", role: .cancel) {} + } message: { + Text("All app blocks have been removed. You have \(settings.emergencyUnblocksAvailable) emergency unblock\(settings.emergencyUnblocksAvailable == 1 ? "" : "s") remaining.") + } + } + } + + @ViewBuilder + private var tabView: some View { + if #available(iOS 18.0, *) { TabView(selection: $selectedTab) { Tab(SettingsTab.general.title, systemImage: SettingsTab.general.icon, value: SettingsTab.general) { GeneralSettingsView( @@ -58,21 +81,34 @@ struct SettingsView: View { .navigationTitle("Donate") } } - .toolbar { - ToolbarItem(placement: .confirmationAction) { - Button("Close") { dismiss() } - } - } - .alert("Emergency Unblock", isPresented: $showConfirmation) { - Button("Unblock All Apps", role: .destructive, action: performEmergencyUnblock) - Button("Cancel", role: .cancel) {} - } message: { - Text("This will immediately remove all app blocks. Each unblock regenerates after 6 months. You have \(settings.emergencyUnblocksAvailable) remaining.") - } - .alert("All Apps Unblocked", isPresented: $showSuccessAlert) { - Button("OK", role: .cancel) {} - } message: { - Text("All app blocks have been removed. You have \(settings.emergencyUnblocksAvailable) emergency unblock\(settings.emergencyUnblocksAvailable == 1 ? "" : "s") remaining.") + } else { + TabView(selection: $selectedTab) { + GeneralSettingsView( + settings: settings, + availableKeyTypes: availableKeyTypes + ) + .navigationTitle(SettingsTab.general.title) + .tabItem { Label(SettingsTab.general.title, systemImage: SettingsTab.general.icon) } + .tag(SettingsTab.general) + + EmergencyUnblockView( + settings: settings, + showConfirmation: $showConfirmation, + performEmergencyUnblock: performEmergencyUnblock + ) + .navigationTitle("Emergency Unblock") + .tabItem { Label(SettingsTab.emergencyUnblock.title, systemImage: SettingsTab.emergencyUnblock.icon) } + .tag(SettingsTab.emergencyUnblock) + + FAQView() + .navigationTitle("FAQ") + .tabItem { Label(SettingsTab.faq.title, systemImage: SettingsTab.faq.icon) } + .tag(SettingsTab.faq) + + DonationView() + .navigationTitle("Donate") + .tabItem { Label(SettingsTab.donation.title, systemImage: SettingsTab.donation.icon) } + .tag(SettingsTab.donation) } } } diff --git a/Normal/Views/TabView/MainTabView.swift b/Normal/Views/TabView/MainTabView.swift index ab6c5f8..f2de8a1 100644 --- a/Normal/Views/TabView/MainTabView.swift +++ b/Normal/Views/TabView/MainTabView.swift @@ -12,12 +12,22 @@ struct MainTabView: View { ] var body: some View { - TabView(selection: $selectedTab) { - Tab("Home", systemImage: "house", value: AppTab.home) { HomeView() } - Tab("Groups", systemImage: AppIcons.groups, value: AppTab.groups) { GroupsView() } - Tab("Schedules", systemImage: "calendar.badge.clock", value: AppTab.schedules) { SchedulesView() } - Tab("App Select", systemImage: "app.dashed", value: AppTab.appSelect) { AppSelectView() } - Tab("Keys", systemImage: "key.viewfinder", value: AppTab.keys) { KeysView() } + if #available(iOS 18.0, *) { + TabView(selection: $selectedTab) { + Tab("Home", systemImage: "house", value: AppTab.home) { HomeView() } + Tab("Groups", systemImage: AppIcons.groups, value: AppTab.groups) { GroupsView() } + Tab("Schedules", systemImage: "calendar.badge.clock", value: AppTab.schedules) { SchedulesView() } + Tab("App Select", systemImage: "app.dashed", value: AppTab.appSelect) { AppSelectView() } + Tab("Keys", systemImage: "key.viewfinder", value: AppTab.keys) { KeysView() } + } + } else { + TabView(selection: $selectedTab) { + HomeView().tabItem { Label("Home", systemImage: "house") }.tag(AppTab.home) + GroupsView().tabItem { Label("Groups", systemImage: AppIcons.groups) }.tag(AppTab.groups) + SchedulesView().tabItem { Label("Schedules", systemImage: "calendar.badge.clock") }.tag(AppTab.schedules) + AppSelectView().tabItem { Label("App Select", systemImage: "app.dashed") }.tag(AppTab.appSelect) + KeysView().tabItem { Label("Keys", systemImage: "key.viewfinder") }.tag(AppTab.keys) + } } } } diff --git a/NormalWidget/BlockControls.swift b/NormalWidget/BlockControls.swift index 8311f41..cf5692c 100644 --- a/NormalWidget/BlockControls.swift +++ b/NormalWidget/BlockControls.swift @@ -2,6 +2,7 @@ import AppIntents import SwiftUI import WidgetKit +@available(iOS 18.0, *) struct BlockAllControl: ControlWidget { static let kind = "BlockAllControl" @@ -17,6 +18,7 @@ struct BlockAllControl: ControlWidget { } } +@available(iOS 18.0, *) struct BlockGroupControl: ControlWidget { static let kind = "BlockGroupControl" @@ -39,6 +41,7 @@ struct BlockGroupControl: ControlWidget { } } +@available(iOS 18.0, *) struct BlockGroupControlConfiguration: ControlConfigurationIntent { static let title: LocalizedStringResource = "Block Group" diff --git a/NormalWidget/NormalWidgetBundle.swift b/NormalWidget/NormalWidgetBundle.swift index d78ef32..5fb7834 100644 --- a/NormalWidget/NormalWidgetBundle.swift +++ b/NormalWidget/NormalWidgetBundle.swift @@ -6,7 +6,9 @@ struct NormalWidgetBundle: WidgetBundle { var body: some Widget { GroupUnlockWidget() TimedUnblockLiveActivity() - BlockAllControl() - BlockGroupControl() + if #available(iOS 18.0, *) { + BlockAllControl() + BlockGroupControl() + } } }