From ae0f48a9d9543d43b120674f0e58164d7cce95ad Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sun, 14 Jun 2026 21:06:22 +0800
Subject: [PATCH] Refine Quick Switch UI states

---
 C1.source/Sources/Aligner/QuickSwitchSessionController.swift |   51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/C1.source/Sources/Aligner/QuickSwitchSessionController.swift b/C1.source/Sources/Aligner/QuickSwitchSessionController.swift
index 03e9501..daff31e 100644
--- a/C1.source/Sources/Aligner/QuickSwitchSessionController.swift
+++ b/C1.source/Sources/Aligner/QuickSwitchSessionController.swift
@@ -19,6 +19,7 @@
     private let windowCloseService: any WindowCloseServiceProtocol
     private let systemCriticalWindowDetector: any SystemCriticalWindowDetecting
     private let disableScreenshotRefresh: Bool
+    private var waterfallViewMode: QuickSwitchWaterfallViewMode
     private var closeConfirmationRequired: Bool
     private let onCloseConfirmationDisabled: (() -> Void)?
     private let debugOverlayWidth: CGFloat?
@@ -85,6 +86,7 @@
     private var lifecycleResidualOverlayWindows = 0
     private var lifecycleResidualVisibleOverlayWindows = 0
     var onSnapshotUpdated: (() -> Void)?
+    var onToggleWaterfallViewMode: (() -> Void)?
 
     private struct PendingCloseVerification {
         let request: QuickSwitchCloseRequest
@@ -120,6 +122,7 @@
         ),
         systemCriticalWindowDetector: any SystemCriticalWindowDetecting = CGWindowSystemCriticalWindowDetector(),
         disableScreenshotRefresh: Bool = false,
+        waterfallViewMode: QuickSwitchWaterfallViewMode = .verticalColumns,
         closeConfirmationRequired: Bool = true,
         onCloseConfirmationDisabled: (() -> Void)? = nil,
         debugHoveredAppGroupIndex: Int? = nil,
@@ -135,6 +138,7 @@
         self.windowCloseService = windowCloseService
         self.systemCriticalWindowDetector = systemCriticalWindowDetector
         self.disableScreenshotRefresh = disableScreenshotRefresh
+        self.waterfallViewMode = waterfallViewMode
         self.closeConfirmationRequired = closeConfirmationRequired
         self.onCloseConfirmationDisabled = onCloseConfirmationDisabled
         self.debugOverlayWidth = debugOverlayWidth
@@ -209,6 +213,9 @@
         view.onBackgroundClick = { [weak self] in
             self?.handleBackgroundClick() ?? false
         }
+        view.onToggleWaterfallViewMode = { [weak self] in
+            self?.onToggleWaterfallViewMode?()
+        }
         view.setSuppressEventInput(!debugMouseSequence.isEmpty || !debugKeySequence.isEmpty)
         view.onRequestClose = { [weak self] request in
             self?.requestClose(request)
@@ -219,6 +226,7 @@
             self.onCloseConfirmationDisabled?()
         }
         view.setCloseConfirmationRequired(closeConfirmationRequired)
+        view.setWaterfallViewMode(waterfallViewMode)
         view.apply(viewModel: nil)
         view.beginPerformanceFirstFrameMeasurement()
         coordinator.openQuickSwitch()
@@ -273,6 +281,23 @@
     func retriggerFromShortcut() {
         DevelopmentDiagnostics.log("quickSwitch.session.retriggerFromShortcut")
         show()
+    }
+
+    func setWaterfallViewMode(_ mode: QuickSwitchWaterfallViewMode) {
+        guard waterfallViewMode != mode else { return }
+
+        waterfallViewMode = mode
+        DevelopmentDiagnostics.log("quickSwitch.session.waterfallViewModeChanged", [
+            "mode": mode.rawValue,
+            "visible": isVisible,
+            "hasViewModel": currentViewModel != nil
+        ])
+
+        view.setWaterfallViewMode(mode)
+        if isVisible, let currentViewModel {
+            view.applyProjected(viewModel: currentViewModel)
+        }
+        onSnapshotUpdated?()
     }
 
     func reportDictionary() -> [String: Any] {
@@ -819,12 +844,12 @@
                 "result": Self.closeResultString(result)
             ])
             if result == .requested {
-                suppressCloseTarget(request)
                 DevelopmentDiagnostics.log("quickSwitch.close.request.refreshAfterClose", [
                     "targetKind": request.kindDescription,
                     "appGroupIndex": request.appGroupIndex,
                     "appName": request.appName,
-                    "windowID": request.windowID
+                    "windowID": request.windowID,
+                    "optimisticRemove": false
                 ])
                 pendingCloseVerification = PendingCloseVerification(
                     request: request,
@@ -1453,6 +1478,8 @@
     let fixtureCandidateFiltering: Bool
     let fixtureActivation: Bool
     let fixtureSpaceFilter: Bool
+    let fixtureSplitView: Bool
+    let fixtureMultiPageIdentity: Bool
     let debugHoveredAppGroupIndex: Int?
     let debugOverlayWidth: CGFloat?
     let debugKeySequence: [String]
@@ -1461,6 +1488,7 @@
     let debugWindowActivation: Bool
     let debugWindowClose: Bool
     let disableScreenshotRefresh: Bool
+    let waterfallViewMode: QuickSwitchWaterfallViewMode?
     let lifecycleCycles: Int?
     let lifecycleInterval: TimeInterval
     let lifecycleVisibleDuration: TimeInterval
@@ -1480,6 +1508,8 @@
             fixtureCandidateFiltering: arguments.contains("--round01-fixture-candidate-filtering"),
             fixtureActivation: arguments.contains("--round01-fixture-window-activation"),
             fixtureSpaceFilter: arguments.contains("--round01-fixture-space-filter"),
+            fixtureSplitView: arguments.contains("--round01-fixture-split-view"),
+            fixtureMultiPageIdentity: arguments.contains("--round01-fixture-multi-page-identity"),
             debugHoveredAppGroupIndex: intValue(for: "--round01-debug-hover-app-index", in: arguments),
             debugOverlayWidth: cgFloatValue(for: "--round01-debug-overlay-width", in: arguments),
             debugKeySequence: stringListValue(for: "--round01-debug-key-sequence", in: arguments),
@@ -1488,6 +1518,7 @@
             debugWindowActivation: arguments.contains("--round01-debug-window-activation"),
             debugWindowClose: arguments.contains("--round01-debug-window-close"),
             disableScreenshotRefresh: arguments.contains("--round01-disable-screenshot-refresh"),
+            waterfallViewMode: waterfallViewModeValue(for: "--round01-waterfall-view-mode", in: arguments),
             lifecycleCycles: intValue(for: "--round01-quick-switch-lifecycle-cycles", in: arguments),
             lifecycleInterval: timeInterval(for: "--round01-quick-switch-lifecycle-interval", in: arguments) ?? 0.02,
             lifecycleVisibleDuration: timeInterval(for: "--round01-quick-switch-lifecycle-visible-duration", in: arguments) ?? 0.16
@@ -1512,6 +1543,22 @@
         return String(argument.dropFirst(prefix.count))
     }
 
+    private static func waterfallViewModeValue(
+        for key: String,
+        in arguments: [String]
+    ) -> QuickSwitchWaterfallViewMode? {
+        guard let value = stringValue(for: key, in: arguments) else { return nil }
+
+        switch value {
+        case "vertical", "vertical-columns", "verticalColumns":
+            return .verticalColumns
+        case "horizontal", "horizontal-masonry", "horizontalMasonry":
+            return .horizontalMasonry
+        default:
+            return nil
+        }
+    }
+
     private static func intValue(for key: String, in arguments: [String]) -> Int? {
         stringValue(for: key, in: arguments).flatMap(Int.init)
     }

--
Gitblit v1.9.3