mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Fixes for multi-window support. (#5528)
* Correctly handle the re-opening of the main window. Add an additional safe-guard to ensure only one main window exists. Make sure all secondary windows use the correct tint colour. * Fix a bug where the settings screen isn't shown on macOS when the AppLock feature is enabled.
This commit is contained in:
@@ -14,8 +14,18 @@ import SwiftUI
|
||||
class SceneDelegate: NSObject, UIWindowSceneDelegate {
|
||||
weak static var windowManager: SecureWindowManagerProtocol!
|
||||
|
||||
/// The app's main window scene identifier.
|
||||
static let mainSceneID = "Main"
|
||||
/// The user info key used by SwiftUI for a `WindowGroup`s `id` parameter.
|
||||
static let sceneIDKey = "com.apple.SwiftUI.sceneID"
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
guard let windowScene = scene as? UIWindowScene else { return }
|
||||
Self.windowManager.configure(withScene: windowScene, session: session)
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
guard let windowScene = scene as? UIWindowScene else { return }
|
||||
Self.windowManager.handleSceneDisconnection(windowScene)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,15 +48,28 @@ class WindowManager: SecureWindowManagerProtocol {
|
||||
}
|
||||
|
||||
func configure(withScene scene: UIWindowScene, session: UISceneSession) {
|
||||
// This gets called for all opened windows, we're only interested in the
|
||||
// first call, for the main window (works with state restoration too).
|
||||
guard mainWindow == nil else {
|
||||
// This gets called for all opened windows, we're only interested in the main window.
|
||||
guard let userInfo = session.userInfo, userInfo[SceneDelegate.sceneIDKey] as? String == SceneDelegate.mainSceneID else {
|
||||
scene.windows.forEach { $0.tintColor = .compound.textActionPrimary } // SecondaryWindow tinting.
|
||||
return
|
||||
}
|
||||
|
||||
// Don't allow more than 1 main window to be presented.
|
||||
if mainScene != nil {
|
||||
// The window will be presented momentarily, so lets leave it blank.
|
||||
scene.keyWindow?.rootViewController = UIHostingController(rootView: Color.clear)
|
||||
UIApplication.shared.requestSceneSessionDestruction(session, options: nil)
|
||||
return
|
||||
}
|
||||
|
||||
mainScene = scene
|
||||
mainSession = session
|
||||
|
||||
// Restore the previous window size on macOS as this isn't automatic.
|
||||
if let previousSize = mainWindow?.frame.size {
|
||||
scene.resizeWindowOnMac(to: previousSize)
|
||||
}
|
||||
|
||||
mainWindow = scene.keyWindow
|
||||
mainWindow.tintColor = .compound.textActionPrimary
|
||||
|
||||
@@ -76,12 +89,20 @@ class WindowManager: SecureWindowManagerProtocol {
|
||||
delegate?.windowManagerDidConfigureWindows(self)
|
||||
}
|
||||
|
||||
func configure(withOpenWinddowAction openWindowAction: OpenWindowAction,
|
||||
func configure(withOpenWindowAction openWindowAction: OpenWindowAction,
|
||||
dismissWindowAction: DismissWindowAction) {
|
||||
self.openWindowAction = openWindowAction
|
||||
self.dismissWindowAction = dismissWindowAction
|
||||
}
|
||||
|
||||
func handleSceneDisconnection(_ scene: UIWindowScene) {
|
||||
if scene == mainScene {
|
||||
mainScene = nil
|
||||
mainSession = nil
|
||||
// Leave the mainWindow so we can reapply it's size on macOS.
|
||||
}
|
||||
}
|
||||
|
||||
func handleRoute(_ appRoute: AppRoute, windowType: SecondaryWindowType) {
|
||||
MXLog.info("Handling app route: \(appRoute) for window type: \(windowType)")
|
||||
|
||||
@@ -258,3 +279,19 @@ private struct InstantlyDismissingWindow: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension UIWindowScene {
|
||||
func resizeWindowOnMac(to size: CGSize) {
|
||||
// Hackity hack 🔨
|
||||
guard ProcessInfo.processInfo.isiOSAppOnMac, let sizeRestrictions else { return }
|
||||
|
||||
self.sizeRestrictions?.minimumSize = size
|
||||
self.sizeRestrictions?.maximumSize = size
|
||||
|
||||
Task {
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
self.sizeRestrictions?.minimumSize = sizeRestrictions.minimumSize
|
||||
self.sizeRestrictions?.maximumSize = sizeRestrictions.maximumSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ protocol SecureWindowManagerProtocol: WindowManagerProtocol {
|
||||
/// Configures the window manager to operate on the supplied scene.
|
||||
func configure(withScene scene: UIWindowScene, session: UISceneSession)
|
||||
|
||||
func configure(withOpenWinddowAction openWindowAction: OpenWindowAction, dismissWindowAction: DismissWindowAction)
|
||||
func configure(withOpenWindowAction openWindowAction: OpenWindowAction, dismissWindowAction: DismissWindowAction)
|
||||
|
||||
func handleSceneDisconnection(_ scene: UIWindowScene)
|
||||
|
||||
func handleRoute(_ appRoute: AppRoute, windowType: SecondaryWindowType)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user