Clean up the window manager and its protocols

This commit is contained in:
Stefan Ceriu
2026-03-30 14:27:31 +03:00
committed by Stefan Ceriu
parent 685d2d083c
commit 2b2b926fdc
3 changed files with 128 additions and 78 deletions

View File

@@ -74,31 +74,6 @@ class WindowManager: SecureWindowManagerProtocol {
self.dismissWindowAction = dismissWindowAction
}
func registerCoordinator(_ coordinator: CoordinatorProtocol, flowCoordinator: FlowCoordinatorProtocol?, forWindowType type: WindowManagerWindowType) {
coordinators[type] = (coordinator, flowCoordinator)
openWindowAction(value: type)
}
func closeAllAuxiliaryWindows() {
for key in coordinators.keys {
dismissWindowAction(value: key)
}
coordinators.removeAll()
}
func windowForType(_ type: WindowManagerWindowType) -> AnyView {
guard let coordinator = coordinators[type]?.coordinator else {
return AnyView(InstantlyDismissingWindow())
}
// This behaves strangely and gets called late but cleans up enough
// and is self contained enough to be just good .. enough
return AnyView(coordinator.toPresentable().onDisappear { [weak self] in
self?.coordinators[type] = nil
})
}
func handleRoute(_ appRoute: AppRoute, windowType: WindowManagerWindowType) {
if let flowCoordinator = coordinators[windowType]?.flowCoordinator {
flowCoordinator.handleAppRoute(appRoute, animated: true)
@@ -167,6 +142,8 @@ class WindowManager: SecureWindowManagerProtocol {
mainWindow.makeKey()
}
// MARK: - OrientationManager
func setOrientation(_ orientation: UIInterfaceOrientationMask) {
mainScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
}
@@ -175,9 +152,36 @@ class WindowManager: SecureWindowManagerProtocol {
appDelegate.orientationLock = orientation
}
// MARK: - Auxiliary window support
func windowForType(_ type: WindowManagerWindowType) -> AnyView {
guard let coordinator = coordinators[type]?.coordinator else {
return AnyView(InstantlyDismissingWindow())
}
// This behaves strangely and gets called late but cleans up enough
// and is self contained enough to be just good .. enough
return AnyView(coordinator.toPresentable().onDisappear { [weak self] in
self?.coordinators[type] = nil
})
}
func registerCoordinator(_ coordinator: CoordinatorProtocol, flowCoordinator: FlowCoordinatorProtocol?, forWindowType type: WindowManagerWindowType) {
coordinators[type] = (coordinator, flowCoordinator)
openWindowAction(value: type)
}
func closeAuxiliaryWindow(forType type: WindowManagerWindowType) {
dismissWindowAction(value: type)
}
func closeAllAuxiliaryWindows() {
for key in coordinators.keys {
dismissWindowAction(value: key)
}
coordinators.removeAll()
}
}
private class PassthroughWindow: UIWindow {

View File

@@ -29,13 +29,16 @@ protocol SecureWindowManagerProtocol: WindowManagerProtocol {
func handleRoute(_ appRoute: AppRoute, windowType: WindowManagerWindowType)
func windowForType(_ type: WindowManagerWindowType) -> AnyView
/// Shows the main and overlay window combo, hiding the alternate window.
func switchToMain()
/// Shows the alternate window, hiding the main and overlay combo.
func switchToAlternate()
// MARK: - Auxiliary window support
/// Used by the Application to retrieve the root view for an auxiliary window
func windowForType(_ type: WindowManagerWindowType) -> AnyView
}
/// A window manager that supports switching between a main app window with an overlay and
@@ -54,15 +57,22 @@ protocol WindowManagerProtocol: AnyObject, OrientationManagerProtocol {
/// All the windows being managed
var windows: [UIWindow] { get }
func registerCoordinator(_ coordinator: CoordinatorProtocol, flowCoordinator: FlowCoordinatorProtocol?, forWindowType type: WindowManagerWindowType)
func closeAllAuxiliaryWindows()
/// Makes the global search window key. Used to get automatic text field focus.
func showGlobalSearch()
func hideGlobalSearch()
// MARK: - Auxiliary window support
/// Register a coordinator and it's respective flow (if any) within the WindowManager which in turn
/// invokes the Application's `OpenWindowAction`
func registerCoordinator(_ coordinator: CoordinatorProtocol,
flowCoordinator: FlowCoordinatorProtocol?,
forWindowType type: WindowManagerWindowType)
/// Closes any window previously opened by registering a coordinator
func closeAllAuxiliaryWindows()
/// Closes a previously opened window for the given type.
func closeAuxiliaryWindow(forType type: WindowManagerWindowType)
}

View File

@@ -21358,6 +21358,76 @@ class WindowManagerMock: WindowManagerProtocol, @unchecked Sendable {
var alternateWindow: UIWindow!
var windows: [UIWindow] = []
//MARK: - showGlobalSearch
var showGlobalSearchUnderlyingCallsCount = 0
var showGlobalSearchCallsCount: Int {
get {
if Thread.isMainThread {
return showGlobalSearchUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = showGlobalSearchUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
showGlobalSearchUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
showGlobalSearchUnderlyingCallsCount = newValue
}
}
}
}
var showGlobalSearchCalled: Bool {
return showGlobalSearchCallsCount > 0
}
var showGlobalSearchClosure: (() -> Void)?
func showGlobalSearch() {
showGlobalSearchCallsCount += 1
showGlobalSearchClosure?()
}
//MARK: - hideGlobalSearch
var hideGlobalSearchUnderlyingCallsCount = 0
var hideGlobalSearchCallsCount: Int {
get {
if Thread.isMainThread {
return hideGlobalSearchUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = hideGlobalSearchUnderlyingCallsCount
}
return returnValue!
}
}
set {
if Thread.isMainThread {
hideGlobalSearchUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
hideGlobalSearchUnderlyingCallsCount = newValue
}
}
}
}
var hideGlobalSearchCalled: Bool {
return hideGlobalSearchCallsCount > 0
}
var hideGlobalSearchClosure: (() -> Void)?
func hideGlobalSearch() {
hideGlobalSearchCallsCount += 1
hideGlobalSearchClosure?()
}
//MARK: - registerCoordinator
var registerCoordinatorFlowCoordinatorForWindowTypeUnderlyingCallsCount = 0
@@ -21434,17 +21504,17 @@ class WindowManagerMock: WindowManagerProtocol, @unchecked Sendable {
closeAllAuxiliaryWindowsCallsCount += 1
closeAllAuxiliaryWindowsClosure?()
}
//MARK: - showGlobalSearch
//MARK: - closeAuxiliaryWindow
var showGlobalSearchUnderlyingCallsCount = 0
var showGlobalSearchCallsCount: Int {
var closeAuxiliaryWindowForTypeUnderlyingCallsCount = 0
var closeAuxiliaryWindowForTypeCallsCount: Int {
get {
if Thread.isMainThread {
return showGlobalSearchUnderlyingCallsCount
return closeAuxiliaryWindowForTypeUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = showGlobalSearchUnderlyingCallsCount
returnValue = closeAuxiliaryWindowForTypeUnderlyingCallsCount
}
return returnValue!
@@ -21452,62 +21522,28 @@ class WindowManagerMock: WindowManagerProtocol, @unchecked Sendable {
}
set {
if Thread.isMainThread {
showGlobalSearchUnderlyingCallsCount = newValue
closeAuxiliaryWindowForTypeUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
showGlobalSearchUnderlyingCallsCount = newValue
closeAuxiliaryWindowForTypeUnderlyingCallsCount = newValue
}
}
}
}
var showGlobalSearchCalled: Bool {
return showGlobalSearchCallsCount > 0
var closeAuxiliaryWindowForTypeCalled: Bool {
return closeAuxiliaryWindowForTypeCallsCount > 0
}
var showGlobalSearchClosure: (() -> Void)?
var closeAuxiliaryWindowForTypeReceivedType: WindowManagerWindowType?
var closeAuxiliaryWindowForTypeReceivedInvocations: [WindowManagerWindowType] = []
var closeAuxiliaryWindowForTypeClosure: ((WindowManagerWindowType) -> Void)?
func showGlobalSearch() {
showGlobalSearchCallsCount += 1
showGlobalSearchClosure?()
}
//MARK: - hideGlobalSearch
var hideGlobalSearchUnderlyingCallsCount = 0
var hideGlobalSearchCallsCount: Int {
get {
if Thread.isMainThread {
return hideGlobalSearchUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = hideGlobalSearchUnderlyingCallsCount
}
return returnValue!
}
func closeAuxiliaryWindow(forType type: WindowManagerWindowType) {
closeAuxiliaryWindowForTypeCallsCount += 1
closeAuxiliaryWindowForTypeReceivedType = type
DispatchQueue.main.async {
self.closeAuxiliaryWindowForTypeReceivedInvocations.append(type)
}
set {
if Thread.isMainThread {
hideGlobalSearchUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
hideGlobalSearchUnderlyingCallsCount = newValue
}
}
}
}
var hideGlobalSearchCalled: Bool {
return hideGlobalSearchCallsCount > 0
}
var hideGlobalSearchClosure: (() -> Void)?
func hideGlobalSearch() {
hideGlobalSearchCallsCount += 1
hideGlobalSearchClosure?()
closeAuxiliaryWindowForTypeClosure?(type)
}
//MARK: - setOrientation