Merge pull request #2393 from manaflow-ai/issue-2391-cmd-p-animated-workspace-rerender

Keep cmd+p stable during animated workspace title updates
This commit is contained in:
Lawrence Chen 2026-03-30 21:21:09 -07:00 committed by GitHub
commit 112358ed01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 254 additions and 68 deletions

View file

@ -980,6 +980,7 @@ private final class WindowCommandPaletteOverlayController: NSObject {
private var focusLockTimer: DispatchSourceTimer? private var focusLockTimer: DispatchSourceTimer?
private var scheduledFocusWorkItem: DispatchWorkItem? private var scheduledFocusWorkItem: DispatchWorkItem?
private var isPaletteVisible = false private var isPaletteVisible = false
private var currentRenderFingerprint: Int?
private var windowDidBecomeKeyObserver: NSObjectProtocol? private var windowDidBecomeKeyObserver: NSObjectProtocol?
private var windowDidResignKeyObserver: NSObjectProtocol? private var windowDidResignKeyObserver: NSObjectProtocol?
@ -1230,7 +1231,7 @@ private final class WindowCommandPaletteOverlayController: NSObject {
editor.setSelectedRange(NSRange(location: length, length: 0)) editor.setSelectedRange(NSRange(location: length, length: 0))
} }
func update(rootView: AnyView, isVisible: Bool) { func update(rootView: AnyView, isVisible: Bool, renderFingerprint: Int) {
guard ensureInstalled() else { return } guard ensureInstalled() else { return }
let shouldPromote = CommandPaletteOverlayPromotionPolicy.shouldPromote( let shouldPromote = CommandPaletteOverlayPromotionPolicy.shouldPromote(
previouslyVisible: isPaletteVisible, previouslyVisible: isPaletteVisible,
@ -1238,7 +1239,10 @@ private final class WindowCommandPaletteOverlayController: NSObject {
) )
isPaletteVisible = isVisible isPaletteVisible = isVisible
if isVisible { if isVisible {
if currentRenderFingerprint != renderFingerprint {
hostingView.rootView = rootView hostingView.rootView = rootView
currentRenderFingerprint = renderFingerprint
}
containerView.capturesMouseEvents = true containerView.capturesMouseEvents = true
containerView.isHidden = false containerView.isHidden = false
containerView.alphaValue = 1 containerView.alphaValue = 1
@ -1252,6 +1256,7 @@ private final class WindowCommandPaletteOverlayController: NSObject {
_ = window.makeFirstResponder(nil) _ = window.makeFirstResponder(nil)
} }
hostingView.rootView = AnyView(EmptyView()) hostingView.rootView = AnyView(EmptyView())
currentRenderFingerprint = nil
containerView.capturesMouseEvents = false containerView.capturesMouseEvents = false
containerView.alphaValue = 0 containerView.alphaValue = 0
containerView.isHidden = true containerView.isHidden = true
@ -1727,12 +1732,53 @@ struct ContentView: View {
let shortcutHint: String? let shortcutHint: String?
let kindLabel: String? let kindLabel: String?
let keywords: [String] let keywords: [String]
let liveTitleWorkspace: Workspace?
let dismissOnRun: Bool let dismissOnRun: Bool
let action: () -> Void let action: () -> Void
init(
id: String,
rank: Int,
title: String,
subtitle: String,
shortcutHint: String?,
kindLabel: String?,
keywords: [String],
liveTitleWorkspace: Workspace? = nil,
dismissOnRun: Bool,
action: @escaping () -> Void
) {
self.id = id
self.rank = rank
self.title = title
self.subtitle = subtitle
self.shortcutHint = shortcutHint
self.kindLabel = kindLabel
self.keywords = keywords
self.liveTitleWorkspace = liveTitleWorkspace
self.dismissOnRun = dismissOnRun
self.action = action
}
var searchableTexts: [String] { var searchableTexts: [String] {
[title, subtitle] + keywords [title, subtitle] + keywords
} }
func displayTitle() -> String {
guard let liveTitleWorkspace else { return title }
return ContentView.commandPaletteWorkspaceDisplayName(liveTitleWorkspace)
}
func displayTitleMatchIndices(
matchingQuery: String,
fallbackIndices: Set<Int>
) -> Set<Int> {
guard liveTitleWorkspace != nil else { return fallbackIndices }
return CommandPaletteFuzzyMatcher.matchCharacterIndices(
query: matchingQuery,
candidate: displayTitle()
)
}
} }
private struct CommandPaletteUsageEntry: Codable, Sendable { private struct CommandPaletteUsageEntry: Codable, Sendable {
@ -1986,6 +2032,39 @@ struct ContentView: View {
var id: String { command.id } var id: String { command.id }
} }
private struct CommandPaletteLiveWorkspaceResultLabel: View {
@ObservedObject private var workspace: Workspace
private let command: CommandPaletteCommand
private let matchingQuery: String
private let fallbackMatchIndices: Set<Int>
private let trailingLabel: CommandPaletteTrailingLabel?
init(
workspace: Workspace,
command: CommandPaletteCommand,
matchingQuery: String,
fallbackMatchIndices: Set<Int>,
trailingLabel: CommandPaletteTrailingLabel?
) {
_workspace = ObservedObject(wrappedValue: workspace)
self.command = command
self.matchingQuery = matchingQuery
self.fallbackMatchIndices = fallbackMatchIndices
self.trailingLabel = trailingLabel
}
var body: some View {
ContentView.commandPaletteResultLabelContent(
title: command.displayTitle(),
matchedIndices: command.displayTitleMatchIndices(
matchingQuery: matchingQuery,
fallbackIndices: fallbackMatchIndices
),
trailingLabel: trailingLabel
)
}
}
private struct CommandPaletteResolvedSearchMatch: Sendable { private struct CommandPaletteResolvedSearchMatch: Sendable {
let commandID: String let commandID: String
let score: Int let score: Int
@ -2001,7 +2080,6 @@ struct ContentView: View {
struct CommandPaletteSwitcherFingerprintWorkspace: Sendable { struct CommandPaletteSwitcherFingerprintWorkspace: Sendable {
let id: UUID let id: UUID
let displayName: String
let metadata: CommandPaletteSwitcherSearchMetadata let metadata: CommandPaletteSwitcherSearchMetadata
let surfaces: [CommandPaletteSwitcherFingerprintSurface] let surfaces: [CommandPaletteSwitcherFingerprintSurface]
} }
@ -3036,10 +3114,29 @@ struct ContentView: View {
let tmuxOverlayController = tmuxWorkspacePaneWindowOverlayController(for: window) let tmuxOverlayController = tmuxWorkspacePaneWindowOverlayController(for: window)
tmuxOverlayController.update(state: tmuxWorkspacePaneWindowOverlayState(for: window)) tmuxOverlayController.update(state: tmuxWorkspacePaneWindowOverlayState(for: window))
let overlayController = commandPaletteWindowOverlayController(for: window) let overlayController = commandPaletteWindowOverlayController(for: window)
overlayController.update(rootView: AnyView(commandPaletteOverlay), isVisible: isCommandPalettePresented) overlayController.update(
rootView: AnyView(commandPaletteOverlay),
isVisible: isCommandPalettePresented,
renderFingerprint: commandPaletteOverlayRenderFingerprint
)
} }
})) }))
view = AnyView(view.onChange(of: commandPaletteCurrentSearchFingerprint) { _ in
guard isCommandPalettePresented, case .commands = commandPaletteMode else { return }
Task { @MainActor in
// Let the query-state transition settle first so the forced corpus refresh
// cannot rebuild the old command list after deleting the ">" prefix.
await Task.yield()
scheduleCommandPaletteResultsRefresh(
query: commandPaletteQuery,
forceSearchCorpusRefresh: true
)
updateCommandPaletteScrollTarget(resultCount: commandPaletteVisibleResults.count, animated: false)
syncCommandPaletteDebugStateForObservedWindow()
}
})
view = AnyView(view.onChange(of: bgGlassTintHex) { _ in view = AnyView(view.onChange(of: bgGlassTintHex) { _ in
updateWindowGlassTint() updateWindowGlassTint()
}) })
@ -3670,6 +3767,7 @@ struct ContentView: View {
ForEach(Array(visibleResults.enumerated()), id: \.element.id) { index, result in ForEach(Array(visibleResults.enumerated()), id: \.element.id) { index, result in
let isSelected = index == selectedIndex let isSelected = index == selectedIndex
let isHovered = commandPaletteHoveredResultIndex == index let isHovered = commandPaletteHoveredResultIndex == index
let trailingLabel = commandPaletteTrailingLabel(for: result.command)
let rowBackground: Color = isSelected let rowBackground: Color = isSelected
? cmuxAccentColor().opacity(0.12) ? cmuxAccentColor().opacity(0.12)
: (isHovered ? Color.primary.opacity(0.08) : .clear) : (isHovered ? Color.primary.opacity(0.08) : .clear)
@ -3677,30 +3775,21 @@ struct ContentView: View {
Button { Button {
runCommandPaletteResult(commandID: result.id) runCommandPaletteResult(commandID: result.id)
} label: { } label: {
HStack(spacing: 8) { Group {
commandPaletteHighlightedTitleText( if let liveTitleWorkspace = result.command.liveTitleWorkspace {
result.command.title, CommandPaletteLiveWorkspaceResultLabel(
matchedIndices: result.titleMatchIndices workspace: liveTitleWorkspace,
command: result.command,
matchingQuery: commandPaletteQueryForMatching,
fallbackMatchIndices: result.titleMatchIndices,
trailingLabel: trailingLabel
)
} else {
Self.commandPaletteResultLabelContent(
title: result.command.title,
matchedIndices: result.titleMatchIndices,
trailingLabel: trailingLabel
) )
.font(.system(size: 13, weight: .regular))
.lineLimit(1)
Spacer()
if let trailingLabel = commandPaletteTrailingLabel(for: result.command) {
switch trailingLabel.style {
case .shortcut:
Text(trailingLabel.text)
.font(.system(size: 11, weight: .medium))
.foregroundStyle(.secondary)
.padding(.horizontal, 4)
.padding(.vertical, 1)
.background(Color.primary.opacity(0.08), in: RoundedRectangle(cornerRadius: 4, style: .continuous))
case .kind:
Text(trailingLabel.text)
.font(.system(size: 11, weight: .regular))
.foregroundStyle(.secondary)
.lineLimit(1)
}
} }
} }
.padding(.horizontal, 9) .padding(.horizontal, 9)
@ -3774,19 +3863,6 @@ struct ContentView: View {
updateCommandPaletteScrollTarget(resultCount: commandPaletteVisibleResults.count, animated: false) updateCommandPaletteScrollTarget(resultCount: commandPaletteVisibleResults.count, animated: false)
syncCommandPaletteDebugStateForObservedWindow() syncCommandPaletteDebugStateForObservedWindow()
} }
.onChange(of: commandPaletteCurrentSearchFingerprint) { _ in
Task { @MainActor in
// Let the query-state transition settle first so the forced corpus refresh
// cannot rebuild the old command list after deleting the ">" prefix.
await Task.yield()
scheduleCommandPaletteResultsRefresh(
query: commandPaletteQuery,
forceSearchCorpusRefresh: true
)
updateCommandPaletteScrollTarget(resultCount: commandPaletteVisibleResults.count, animated: false)
syncCommandPaletteDebugStateForObservedWindow()
}
}
.onChange(of: commandPaletteResultsRevision) { _ in .onChange(of: commandPaletteResultsRevision) { _ in
let resultIDs = cachedCommandPaletteResults.map(\.id) let resultIDs = cachedCommandPaletteResults.map(\.id)
commandPaletteSelectedResultIndex = Self.commandPaletteResolvedSelectionIndex( commandPaletteSelectedResultIndex = Self.commandPaletteResolvedSelectionIndex(
@ -4159,6 +4235,78 @@ struct ContentView: View {
) )
} }
private var commandPaletteOverlayRenderFingerprint: Int {
var hasher = Hasher()
switch commandPaletteMode {
case .commands:
hasher.combine("commands")
case .renameInput(let target):
hasher.combine("renameInput")
combineCommandPaletteRenameTarget(target, into: &hasher)
case .renameConfirm(let target, let proposedName):
hasher.combine("renameConfirm")
combineCommandPaletteRenameTarget(target, into: &hasher)
hasher.combine(proposedName)
}
hasher.combine(commandPaletteQuery)
hasher.combine(commandPaletteRenameDraft)
hasher.combine(commandPaletteListScope.rawValue)
hasher.combine(commandPaletteSearchAllSurfaces)
hasher.combine(commandPaletteSelectedResultIndex)
hasher.combine(commandPaletteSelectionAnchorCommandID)
hasher.combine(commandPaletteHoveredResultIndex)
hasher.combine(commandPaletteScrollTargetIndex)
hasher.combine(commandPaletteScrollTargetAnchor?.x)
hasher.combine(commandPaletteScrollTargetAnchor?.y)
hasher.combine(commandPaletteVisibleResultsScope?.rawValue)
hasher.combine(commandPaletteVisibleResultsFingerprint)
hasher.combine(cachedCommandPaletteScope?.rawValue)
hasher.combine(cachedCommandPaletteFingerprint)
hasher.combine(isCommandPaletteSearchPending)
hasher.combine(commandPaletteSearchRequestID)
hasher.combine(commandPaletteResolvedSearchRequestID)
hasher.combine(commandPaletteResolvedSearchScope?.rawValue)
hasher.combine(commandPaletteResolvedSearchFingerprint)
hasher.combine(commandPaletteResolvedMatchingQuery)
hasher.combine(commandPaletteResultsRevision)
combineCommandPalettePendingActivation(commandPalettePendingActivation, into: &hasher)
return hasher.finalize()
}
private func combineCommandPaletteRenameTarget(
_ target: CommandPaletteRenameTarget,
into hasher: inout Hasher
) {
switch target.kind {
case .workspace(let workspaceId):
hasher.combine("workspace")
hasher.combine(workspaceId)
case .tab(let workspaceId, let panelId):
hasher.combine("tab")
hasher.combine(workspaceId)
hasher.combine(panelId)
}
}
private func combineCommandPalettePendingActivation(
_ activation: CommandPalettePendingActivation?,
into hasher: inout Hasher
) {
switch activation {
case .selected(let requestID, let fallbackSelectedIndex, let preferredCommandID):
hasher.combine("selected")
hasher.combine(requestID)
hasher.combine(fallbackSelectedIndex)
hasher.combine(preferredCommandID)
case .command(let requestID, let commandID):
hasher.combine("command")
hasher.combine(requestID)
hasher.combine(commandID)
case nil:
hasher.combine("none")
}
}
nonisolated private static func commandPaletteListScope(for query: String) -> CommandPaletteListScope { nonisolated private static func commandPaletteListScope(for query: String) -> CommandPaletteListScope {
if query.hasPrefix(Self.commandPaletteCommandsPrefix) { if query.hasPrefix(Self.commandPaletteCommandsPrefix) {
return .commands return .commands
@ -4705,7 +4853,6 @@ struct ContentView: View {
workspaces: commandPaletteOrderedSwitcherWorkspaces(for: context).map { workspace in workspaces: commandPaletteOrderedSwitcherWorkspaces(for: context).map { workspace in
CommandPaletteSwitcherFingerprintWorkspace( CommandPaletteSwitcherFingerprintWorkspace(
id: workspace.id, id: workspace.id,
displayName: workspaceDisplayName(workspace),
metadata: commandPaletteWorkspaceSearchMetadata(for: workspace), metadata: commandPaletteWorkspaceSearchMetadata(for: workspace),
surfaces: includeSurfaces surfaces: includeSurfaces
? commandPaletteOrderedSwitcherPanels(for: workspace).compactMap { panelId in ? commandPaletteOrderedSwitcherPanels(for: workspace).compactMap { panelId in
@ -4732,7 +4879,7 @@ struct ContentView: View {
return Self.commandPaletteSwitcherFingerprint(windowContexts: fingerprintContexts) return Self.commandPaletteSwitcherFingerprint(windowContexts: fingerprintContexts)
} }
private func commandPaletteHighlightedTitleText(_ title: String, matchedIndices: Set<Int>) -> Text { private static func commandPaletteHighlightedTitleText(_ title: String, matchedIndices: Set<Int>) -> Text {
guard !matchedIndices.isEmpty else { guard !matchedIndices.isEmpty else {
return Text(title).foregroundColor(.primary) return Text(title).foregroundColor(.primary)
} }
@ -4760,6 +4907,46 @@ struct ContentView: View {
return result return result
} }
@ViewBuilder
private static func commandPaletteTrailingLabelView(_ trailingLabel: CommandPaletteTrailingLabel?) -> some View {
if let trailingLabel {
switch trailingLabel.style {
case .shortcut:
Text(trailingLabel.text)
.font(.system(size: 11, weight: .medium))
.foregroundStyle(.secondary)
.padding(.horizontal, 4)
.padding(.vertical, 1)
.background(
Color.primary.opacity(0.08),
in: RoundedRectangle(cornerRadius: 4, style: .continuous)
)
case .kind:
Text(trailingLabel.text)
.font(.system(size: 11, weight: .regular))
.foregroundStyle(.secondary)
.lineLimit(1)
}
}
}
private static func commandPaletteResultLabelContent(
title: String,
matchedIndices: Set<Int>,
trailingLabel: CommandPaletteTrailingLabel?
) -> some View {
HStack(spacing: 8) {
commandPaletteHighlightedTitleText(
title,
matchedIndices: matchedIndices
)
.font(.system(size: 13, weight: .regular))
.lineLimit(1)
Spacer()
commandPaletteTrailingLabelView(trailingLabel)
}
}
private func commandPaletteTrailingLabel(for command: CommandPaletteCommand) -> CommandPaletteTrailingLabel? { private func commandPaletteTrailingLabel(for command: CommandPaletteCommand) -> CommandPaletteTrailingLabel? {
if let shortcutHint = command.shortcutHint { if let shortcutHint = command.shortcutHint {
return CommandPaletteTrailingLabel(text: shortcutHint, style: .shortcut) return CommandPaletteTrailingLabel(text: shortcutHint, style: .shortcut)
@ -4814,10 +5001,11 @@ struct ContentView: View {
id: workspaceCommandId, id: workspaceCommandId,
rank: nextRank, rank: nextRank,
title: workspaceName, title: workspaceName,
subtitle: commandPaletteSwitcherSubtitle(base: String(localized: "commandPalette.switcher.workspaceLabel", defaultValue: "Workspace"), windowLabel: context.windowLabel), subtitle: Self.commandPaletteSwitcherSubtitle(base: String(localized: "commandPalette.switcher.workspaceLabel", defaultValue: "Workspace"), windowLabel: context.windowLabel),
shortcutHint: nil, shortcutHint: nil,
kindLabel: String(localized: "commandPalette.kind.workspace", defaultValue: "Workspace"), kindLabel: String(localized: "commandPalette.kind.workspace", defaultValue: "Workspace"),
keywords: workspaceKeywords, keywords: workspaceKeywords,
liveTitleWorkspace: workspace,
dismissOnRun: true, dismissOnRun: true,
action: { action: {
focusCommandPaletteSwitcherTarget( focusCommandPaletteSwitcherTarget(
@ -4859,7 +5047,7 @@ struct ContentView: View {
id: surfaceCommandId, id: surfaceCommandId,
rank: nextRank, rank: nextRank,
title: surfaceName, title: surfaceName,
subtitle: commandPaletteSwitcherSubtitle(base: workspaceName, windowLabel: context.windowLabel), subtitle: Self.commandPaletteSwitcherSubtitle(base: workspaceName, windowLabel: context.windowLabel),
shortcutHint: nil, shortcutHint: nil,
kindLabel: surfaceKindLabel, kindLabel: surfaceKindLabel,
keywords: surfaceKeywords, keywords: surfaceKeywords,
@ -4931,7 +5119,7 @@ struct ContentView: View {
return contexts return contexts
} }
private func commandPaletteSwitcherSubtitle(base: String, windowLabel: String?) -> String { private static func commandPaletteSwitcherSubtitle(base: String, windowLabel: String?) -> String {
guard let windowLabel else { return base } guard let windowLabel else { return base }
return "\(base)\(windowLabel)" return "\(base)\(windowLabel)"
} }
@ -6398,7 +6586,7 @@ struct ContentView: View {
return (workspace, panelId, panel) return (workspace, panelId, panel)
} }
private func workspaceDisplayName(_ workspace: Workspace) -> String { private static func commandPaletteWorkspaceDisplayName(_ workspace: Workspace) -> String {
let custom = workspace.customTitle?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" let custom = workspace.customTitle?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if !custom.isEmpty { if !custom.isEmpty {
return custom return custom
@ -6407,6 +6595,10 @@ struct ContentView: View {
return title.isEmpty ? String(localized: "workspace.displayName.fallback", defaultValue: "Workspace") : title return title.isEmpty ? String(localized: "workspace.displayName.fallback", defaultValue: "Workspace") : title
} }
private func workspaceDisplayName(_ workspace: Workspace) -> String {
Self.commandPaletteWorkspaceDisplayName(workspace)
}
private func panelDisplayName(workspace: Workspace, panelId: UUID, fallback: String) -> String { private func panelDisplayName(workspace: Workspace, panelId: UUID, fallback: String) -> String {
let title = workspace.panelTitle(panelId: panelId)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" let title = workspace.panelTitle(panelId: panelId)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if !title.isEmpty { if !title.isEmpty {
@ -6506,7 +6698,7 @@ struct ContentView: View {
hasher.combine(context.workspaces.count) hasher.combine(context.workspaces.count)
for workspace in context.workspaces { for workspace in context.workspaces {
hasher.combine(workspace.id) hasher.combine(workspace.id)
hasher.combine(workspace.displayName) // Keep animated workspace titles from invalidating the live switcher corpus.
combineCommandPaletteSwitcherSearchMetadata(workspace.metadata, into: &hasher) combineCommandPaletteSwitcherSearchMetadata(workspace.metadata, into: &hasher)
hasher.combine(workspace.surfaces.count) hasher.combine(workspace.surfaces.count)
for surface in workspace.surfaces { for surface in workspace.surfaces {
@ -6845,7 +7037,7 @@ struct ContentView: View {
let rows = Array(commandPaletteVisibleResults.prefix(20)).map { result in let rows = Array(commandPaletteVisibleResults.prefix(20)).map { result in
CommandPaletteDebugResultRow( CommandPaletteDebugResultRow(
commandId: result.command.id, commandId: result.command.id,
title: result.command.title, title: result.command.displayTitle(),
shortcutHint: result.command.shortcutHint, shortcutHint: result.command.shortcutHint,
trailingLabel: commandPaletteTrailingLabel(for: result.command)?.text, trailingLabel: commandPaletteTrailingLabel(for: result.command)?.text,
score: result.score score: result.score

View file

@ -663,7 +663,7 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
XCTAssertNotEqual(base, renamed) XCTAssertNotEqual(base, renamed)
} }
func testSwitcherFingerprintTracksMetadataValuesAtSameCardinality() { func testSwitcherFingerprintIgnoresWorkspaceDisplayNameChurn() {
let windowID = UUID() let windowID = UUID()
let workspaceID = UUID() let workspaceID = UUID()
let base = ContentView.commandPaletteSwitcherFingerprint( let base = ContentView.commandPaletteSwitcherFingerprint(
@ -675,7 +675,6 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
workspaces: [ workspaces: [
ContentView.CommandPaletteSwitcherFingerprintWorkspace( ContentView.CommandPaletteSwitcherFingerprintWorkspace(
id: workspaceID, id: workspaceID,
displayName: "Workspace Alpha",
metadata: CommandPaletteSwitcherSearchMetadata( metadata: CommandPaletteSwitcherSearchMetadata(
directories: ["/Users/example/dev/cmuxterm"], directories: ["/Users/example/dev/cmuxterm"],
branches: ["feature/search-speed"], branches: ["feature/search-speed"],
@ -696,7 +695,6 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
workspaces: [ workspaces: [
ContentView.CommandPaletteSwitcherFingerprintWorkspace( ContentView.CommandPaletteSwitcherFingerprintWorkspace(
id: workspaceID, id: workspaceID,
displayName: "Workspace Alpha",
metadata: CommandPaletteSwitcherSearchMetadata( metadata: CommandPaletteSwitcherSearchMetadata(
directories: ["/Users/example/dev/other"], directories: ["/Users/example/dev/other"],
branches: ["feature/search-speed"], branches: ["feature/search-speed"],
@ -717,7 +715,6 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
workspaces: [ workspaces: [
ContentView.CommandPaletteSwitcherFingerprintWorkspace( ContentView.CommandPaletteSwitcherFingerprintWorkspace(
id: workspaceID, id: workspaceID,
displayName: "Workspace Beta",
metadata: CommandPaletteSwitcherSearchMetadata( metadata: CommandPaletteSwitcherSearchMetadata(
directories: ["/Users/example/dev/cmuxterm"], directories: ["/Users/example/dev/cmuxterm"],
branches: ["feature/search-speed"], branches: ["feature/search-speed"],
@ -730,8 +727,8 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
] ]
) )
XCTAssertEqual(base, changedDisplayName)
XCTAssertNotEqual(base, changedMetadata) XCTAssertNotEqual(base, changedMetadata)
XCTAssertNotEqual(base, changedDisplayName)
} }
func testSwitcherFingerprintTracksSurfaceValuesAtSameCardinality() { func testSwitcherFingerprintTracksSurfaceValuesAtSameCardinality() {
@ -748,7 +745,6 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
workspaces: [ workspaces: [
ContentView.CommandPaletteSwitcherFingerprintWorkspace( ContentView.CommandPaletteSwitcherFingerprintWorkspace(
id: workspaceID, id: workspaceID,
displayName: "Workspace Alpha",
metadata: CommandPaletteSwitcherSearchMetadata(), metadata: CommandPaletteSwitcherSearchMetadata(),
surfaces: [ surfaces: [
ContentView.CommandPaletteSwitcherFingerprintSurface( ContentView.CommandPaletteSwitcherFingerprintSurface(
@ -776,7 +772,6 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
workspaces: [ workspaces: [
ContentView.CommandPaletteSwitcherFingerprintWorkspace( ContentView.CommandPaletteSwitcherFingerprintWorkspace(
id: workspaceID, id: workspaceID,
displayName: "Workspace Alpha",
metadata: CommandPaletteSwitcherSearchMetadata(), metadata: CommandPaletteSwitcherSearchMetadata(),
surfaces: [ surfaces: [
ContentView.CommandPaletteSwitcherFingerprintSurface( ContentView.CommandPaletteSwitcherFingerprintSurface(
@ -804,7 +799,6 @@ final class CommandPaletteSearchEngineTests: XCTestCase {
workspaces: [ workspaces: [
ContentView.CommandPaletteSwitcherFingerprintWorkspace( ContentView.CommandPaletteSwitcherFingerprintWorkspace(
id: workspaceID, id: workspaceID,
displayName: "Workspace Alpha",
metadata: CommandPaletteSwitcherSearchMetadata(), metadata: CommandPaletteSwitcherSearchMetadata(),
surfaces: [ surfaces: [
ContentView.CommandPaletteSwitcherFingerprintSurface( ContentView.CommandPaletteSwitcherFingerprintSurface(