Fix pinned workspace notification reordering (#1116)

* test: cover pinned workspace notification reorder

* fix: keep pinned workspace order on notification
This commit is contained in:
Austin Wang 2026-03-09 16:05:24 -07:00 committed by GitHub
parent c447bee602
commit fc8142d61d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 81 additions and 2 deletions

View file

@ -1121,6 +1121,16 @@ class TabManager: ObservableObject {
tabs.insert(tab, at: insertIndex)
}
func moveTabToTopForNotification(_ tabId: UUID) {
guard let index = tabs.firstIndex(where: { $0.id == tabId }) else { return }
let pinnedCount = tabs.filter { $0.isPinned }.count
guard index != pinnedCount else { return }
let tab = tabs[index]
guard !tab.isPinned else { return }
tabs.remove(at: index)
tabs.insert(tab, at: pinnedCount)
}
func moveTabsToTop(_ tabIds: Set<UUID>) {
guard !tabIds.isEmpty else { return }
let selectedTabs = tabs.filter { tabIds.contains($0.id) }

View file

@ -671,6 +671,11 @@ final class TerminalNotificationStore: ObservableObject {
private var notificationSettingsURLOpener: (URL) -> Void = { url in
NSWorkspace.shared.open(url)
}
private var notificationDeliveryHandler: (TerminalNotificationStore, TerminalNotification) -> Void = {
store,
notification in
store.scheduleUserNotification(notification)
}
private var indexes = NotificationIndexes()
private init() {
@ -843,7 +848,7 @@ final class TerminalNotificationStore: ObservableObject {
}
if WorkspaceAutoReorderSettings.isEnabled() {
AppDelegate.shared?.tabManager?.moveTabToTop(tabId)
AppDelegate.shared?.tabManager?.moveTabToTopForNotification(tabId)
}
let notification = TerminalNotification(
@ -862,7 +867,7 @@ final class TerminalNotificationStore: ObservableObject {
center.removeDeliveredNotificationsOffMain(withIdentifiers: idsToClear)
center.removePendingNotificationRequestsOffMain(withIdentifiers: idsToClear)
}
scheduleUserNotification(notification)
notificationDeliveryHandler(self, notification)
}
func markRead(id: UUID) {
@ -1233,6 +1238,18 @@ final class TerminalNotificationStore: ObservableObject {
hasPromptedForSettings = false
}
func configureNotificationDeliveryHandlerForTesting(
_ handler: @escaping (TerminalNotificationStore, TerminalNotification) -> Void
) {
notificationDeliveryHandler = handler
}
func resetNotificationDeliveryHandlerForTesting() {
notificationDeliveryHandler = { store, notification in
store.scheduleUserNotification(notification)
}
}
func promptToEnableNotificationsForTesting() {
promptToEnableNotifications()
}

View file

@ -4233,6 +4233,58 @@ final class WorkspaceReorderTests: XCTestCase {
}
}
@MainActor
final class WorkspaceNotificationReorderTests: XCTestCase {
func testNotificationAutoReorderDoesNotMovePinnedWorkspace() {
let appDelegate = AppDelegate.shared ?? AppDelegate()
let manager = TabManager()
let notificationStore = TerminalNotificationStore.shared
let originalTabManager = appDelegate.tabManager
let originalNotificationStore = appDelegate.notificationStore
let defaults = UserDefaults.standard
let originalAutoReorderSetting = defaults.object(forKey: WorkspaceAutoReorderSettings.key)
let originalAppFocusOverride = AppFocusState.overrideIsFocused
notificationStore.replaceNotificationsForTesting([])
notificationStore.configureNotificationDeliveryHandlerForTesting { _, _ in }
appDelegate.tabManager = manager
appDelegate.notificationStore = notificationStore
defaults.set(true, forKey: WorkspaceAutoReorderSettings.key)
AppFocusState.overrideIsFocused = false
defer {
notificationStore.replaceNotificationsForTesting([])
notificationStore.resetNotificationDeliveryHandlerForTesting()
appDelegate.tabManager = originalTabManager
appDelegate.notificationStore = originalNotificationStore
AppFocusState.overrideIsFocused = originalAppFocusOverride
if let originalAutoReorderSetting {
defaults.set(originalAutoReorderSetting, forKey: WorkspaceAutoReorderSettings.key)
} else {
defaults.removeObject(forKey: WorkspaceAutoReorderSettings.key)
}
}
let firstPinned = manager.tabs[0]
manager.setPinned(firstPinned, pinned: true)
let secondPinned = manager.addWorkspace()
manager.setPinned(secondPinned, pinned: true)
let unpinned = manager.addWorkspace()
let expectedOrder = [firstPinned.id, secondPinned.id, unpinned.id]
notificationStore.addNotification(
tabId: secondPinned.id,
surfaceId: nil,
title: "Build finished",
subtitle: "",
body: "Pinned workspaces should stay put"
)
XCTAssertEqual(manager.tabs.map(\.id), expectedOrder)
}
}
@MainActor
final class TabManagerChildExitCloseTests: XCTestCase {
func testChildExitOnLastPanelClosesSelectedWorkspaceAndKeepsIndexStable() {