Skip to content

Commit

Permalink
Fix app startup issue
Browse files Browse the repository at this point in the history
Fixes #364
Fixes #371
  • Loading branch information
jordanbaird committed Sep 23, 2024
1 parent 6d60ab8 commit 673b1bf
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 87 deletions.
41 changes: 23 additions & 18 deletions Ice/Main/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,36 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
return
}

// Assign and close the various windows.
let windowAssignments: KeyValuePairs = [
Constants.settingsWindowID: appState.assignSettingsWindow,
Constants.permissionsWindowID: appState.assignPermissionsWindow,
]
for (identifier, assign) in windowAssignments {
if let window = NSApp.window(withIdentifier: identifier) {
assign(window)
window.close()
}
}

// Hide the main menu to make more space in the menu bar.
if let mainMenu = NSApp.mainMenu {
for item in mainMenu.items {
item.isHidden = true
}
}

// Temporary hack to make sure the windows are retained on Sequoia:
// Let them open, wait a bit, then close them.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
appState.settingsWindow?.close()
appState.permissionsWindow?.close()

if !appState.isPreview {
// If we have the required permissions, set up the shared app state.
// Otherwise, open the permissions window.
if appState.permissionsManager.hasPermission {
appState.performSetup()
} else if let permissionsWindow = appState.permissionsWindow {
appState.activate(withPolicy: .regular)
permissionsWindow.center()
permissionsWindow.makeKeyAndOrderFront(nil)
} else {
Logger.appDelegate.error("Failed to open permissions window")
}
if !appState.isPreview {
// If we have the required permissions, set up the shared app state.
// Otherwise, open the permissions window.
if appState.permissionsManager.hasAllPermissions {
appState.performSetup()
} else if let permissionsWindow = appState.permissionsWindow {
appState.activate(withPolicy: .regular)
permissionsWindow.center()
permissionsWindow.makeKeyAndOrderFront(nil)
} else {
Logger.appDelegate.error("Failed to open permissions window")
}
}
}
Expand Down
34 changes: 24 additions & 10 deletions Ice/Main/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ final class AppState: ObservableObject {
/// The app's delegate.
private(set) weak var appDelegate: AppDelegate?

/// The window that contains the settings interface.
private(set) weak var settingsWindow: NSWindow?

/// The window that contains the permissions interface.
private(set) weak var permissionsWindow: NSWindow?

/// A Boolean value that indicates whether the "ShowOnHover" feature is prevented.
private(set) var isShowOnHoverPrevented = false

Expand All @@ -62,16 +68,6 @@ final class AppState: ObservableObject {
#endif
}()

/// The window that contains the settings interface.
var settingsWindow: NSWindow? {
NSApp.window(withIdentifier: Constants.settingsWindowID)
}

/// The window that contains the permissions interface.
var permissionsWindow: NSWindow? {
NSApp.window(withIdentifier: Constants.permissionsWindowID)
}

/// A Boolean value that indicates whether the application can set the cursor
/// in the background.
var setsCursorInBackground: Bool {
Expand Down Expand Up @@ -190,6 +186,24 @@ final class AppState: ObservableObject {
self.appDelegate = appDelegate
}

/// Assigns the settings window to the app state.
func assignSettingsWindow(_ settingsWindow: NSWindow) {
guard self.settingsWindow == nil else {
Logger.appState.warning("Multiple attempts made to assign settings window")
return
}
self.settingsWindow = settingsWindow
}

/// Assigns the permissions window to the app state.
func assignPermissionsWindow(_ permissionsWindow: NSWindow) {
guard self.permissionsWindow == nil else {
Logger.appState.warning("Multiple attempts made to assign permissions window")
return
}
self.permissionsWindow = permissionsWindow
}

/// Activates the app and sets its activation policy to the given value.
func activate(withPolicy policy: NSApplication.ActivationPolicy) {
// Store whether the app has previously activated inside an internal
Expand Down
4 changes: 2 additions & 2 deletions Ice/Permissions/PermissionsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Combine
@MainActor
final class PermissionsManager: ObservableObject {
/// A Boolean value that indicates whether the app has been granted all permissions.
@Published var hasPermission: Bool = false
@Published var hasAllPermissions: Bool = false

let accessibilityPermission = AccessibilityPermission()

Expand All @@ -30,7 +30,7 @@ final class PermissionsManager: ObservableObject {
accessibilityPermission.$hasPermission
.combineLatest(screenRecordingPermission.$hasPermission)
.sink { [weak self] hasPermission1, hasPermission2 in
self?.hasPermission = hasPermission1 && hasPermission2
self?.hasAllPermissions = hasPermission1 && hasPermission2
}
.store(in: &c)

Expand Down
2 changes: 1 addition & 1 deletion Ice/Permissions/PermissionsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct PermissionsView: View {
Text("Continue")
.frame(maxWidth: .infinity)
}
.disabled(!permissionsManager.hasPermission)
.disabled(!permissionsManager.hasAllPermissions)
}

@ViewBuilder
Expand Down
38 changes: 3 additions & 35 deletions Ice/Permissions/PermissionsWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,12 @@ struct PermissionsWindow: Scene {
self.permissionsManager = appState.permissionsManager
}

var body: some Scene {
permissionsWindow
.windowResizability(.contentSize)
.windowStyle(.hiddenTitleBar)
.environmentObject(permissionsManager)
}

private var permissionsWindow: some Scene {
if #available(macOS 15.0, *) {
return PermissionsWindowMacOS15()
} else {
return PermissionsWindowMacOS14()
}
}
}

@available(macOS 14.0, *)
private struct PermissionsWindowMacOS14: Scene {
var body: some Scene {
Window(Constants.permissionsWindowTitle, id: Constants.permissionsWindowID) {
PermissionsView()
}
}
}

@available(macOS 15.0, *)
private struct PermissionsWindowMacOS15: Scene {
@Environment(\.dismissWindow) private var dismissWindow
@State private var launchBehavior: SceneLaunchBehavior = .presented

var body: some Scene {
Window(Constants.permissionsWindowTitle, id: Constants.permissionsWindowID) {
PermissionsView()
.once {
dismissWindow(id: Constants.permissionsWindowID)
launchBehavior = .suppressed // Keep the window from reopening.
}
}
.defaultLaunchBehavior(launchBehavior)
.windowResizability(.contentSize)
.windowStyle(.hiddenTitleBar)
.environmentObject(permissionsManager)
}
}
30 changes: 9 additions & 21 deletions Ice/Settings/SettingsWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,18 @@ struct SettingsWindow: Scene {
@Environment(\.openWindow) private var openWindow

var body: some Scene {
settingsWindow
.commandsRemoved()
.windowResizability(.contentSize)
.defaultSize(width: 900, height: 625)
.environmentObject(appState)
.environmentObject(appState.navigationState)
}

private var settingsWindow: some Scene {
if #available(macOS 15.0, *) {
return window
.defaultLaunchBehavior(.presented)
} else {
return window
}
}

@SceneBuilder
private var window: some Scene {
Window(Constants.settingsWindowTitle, id: Constants.settingsWindowID) {
SettingsView()
.once {
openWindow(id: Constants.permissionsWindowID)
.onAppear {
if !appState.permissionsManager.hasAllPermissions {
openWindow(id: Constants.permissionsWindowID)
}
}
}
.commandsRemoved()
.windowResizability(.contentSize)
.defaultSize(width: 900, height: 625)
.environmentObject(appState)
.environmentObject(appState.navigationState)
}
}

0 comments on commit 673b1bf

Please sign in to comment.