Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions Normal.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
4 changes: 3 additions & 1 deletion Normal/Services/WidgetSync.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ enum WidgetSync {

static func reloadTimelines() {
WidgetCenter.shared.reloadAllTimelines()
ControlCenter.shared.reloadAllControls()
if #available(iOS 18.0, *) {
ControlCenter.shared.reloadAllControls()
}
}
}

Expand Down
66 changes: 51 additions & 15 deletions Normal/Views/Settings/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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)
}
}
}
Expand Down
22 changes: 16 additions & 6 deletions Normal/Views/TabView/MainTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
}
3 changes: 3 additions & 0 deletions NormalWidget/BlockControls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import AppIntents
import SwiftUI
import WidgetKit

@available(iOS 18.0, *)
struct BlockAllControl: ControlWidget {
static let kind = "BlockAllControl"

Expand All @@ -17,6 +18,7 @@ struct BlockAllControl: ControlWidget {
}
}

@available(iOS 18.0, *)
struct BlockGroupControl: ControlWidget {
static let kind = "BlockGroupControl"

Expand All @@ -39,6 +41,7 @@ struct BlockGroupControl: ControlWidget {
}
}

@available(iOS 18.0, *)
struct BlockGroupControlConfiguration: ControlConfigurationIntent {
static let title: LocalizedStringResource = "Block Group"

Expand Down
6 changes: 4 additions & 2 deletions NormalWidget/NormalWidgetBundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ struct NormalWidgetBundle: WidgetBundle {
var body: some Widget {
GroupUnlockWidget()
TimedUnblockLiveActivity()
BlockAllControl()
BlockGroupControl()
if #available(iOS 18.0, *) {
BlockAllControl()
BlockGroupControl()
}
}
}
Loading