fix(app): preserve shadowed command owners (#39044)
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
import { commandPaletteOptions, resolveKeybindOption, upsertCommandRegistration, type CommandOption } from "./command"
|
import {
|
||||||
|
activeCommandRegistrations,
|
||||||
|
addCommandRegistration,
|
||||||
|
commandPaletteOptions,
|
||||||
|
resolveKeybindOption,
|
||||||
|
type CommandOption,
|
||||||
|
} from "./command"
|
||||||
|
|
||||||
const paletteOptions: CommandOption[] = [
|
const paletteOptions: CommandOption[] = [
|
||||||
{ id: "settings.open", title: "Open settings" },
|
{ id: "settings.open", title: "Open settings" },
|
||||||
@@ -15,22 +21,31 @@ describe("commandPaletteOptions", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("upsertCommandRegistration", () => {
|
describe("command registrations", () => {
|
||||||
test("replaces keyed registrations", () => {
|
test("shadows keyed registrations while retaining the previous owner", () => {
|
||||||
const one = () => [{ id: "one", title: "One" }]
|
const one = () => [{ id: "one", title: "One" }]
|
||||||
const two = () => [{ id: "two", title: "Two" }]
|
const two = () => [{ id: "two", title: "Two" }]
|
||||||
|
|
||||||
const next = upsertCommandRegistration([{ key: "layout", options: one }], { key: "layout", options: two })
|
const registrations = addCommandRegistration([{ key: "layout", options: one }], {
|
||||||
|
key: "layout",
|
||||||
|
options: two,
|
||||||
|
})
|
||||||
|
const active = activeCommandRegistrations(registrations)
|
||||||
|
|
||||||
expect(next).toHaveLength(1)
|
expect(registrations).toHaveLength(2)
|
||||||
expect(next[0]?.options).toBe(two)
|
expect(active).toHaveLength(1)
|
||||||
|
expect(active[0]?.options).toBe(two)
|
||||||
|
|
||||||
|
const restored = activeCommandRegistrations(registrations.filter((entry) => entry.options !== two))
|
||||||
|
expect(restored).toHaveLength(1)
|
||||||
|
expect(restored[0]?.options).toBe(one)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("keeps unkeyed registrations additive", () => {
|
test("keeps unkeyed registrations additive", () => {
|
||||||
const one = () => [{ id: "one", title: "One" }]
|
const one = () => [{ id: "one", title: "One" }]
|
||||||
const two = () => [{ id: "two", title: "Two" }]
|
const two = () => [{ id: "two", title: "Two" }]
|
||||||
|
|
||||||
const next = upsertCommandRegistration([{ options: one }], { options: two })
|
const next = activeCommandRegistrations(addCommandRegistration([{ options: one }], { options: two }))
|
||||||
|
|
||||||
expect(next).toHaveLength(2)
|
expect(next).toHaveLength(2)
|
||||||
expect(next[0]?.options).toBe(two)
|
expect(next[0]?.options).toBe(two)
|
||||||
|
|||||||
@@ -114,9 +114,18 @@ export type CommandRegistration = {
|
|||||||
options: Accessor<CommandOption[]>
|
options: Accessor<CommandOption[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function upsertCommandRegistration(registrations: CommandRegistration[], entry: CommandRegistration) {
|
export function addCommandRegistration(registrations: CommandRegistration[], entry: CommandRegistration) {
|
||||||
if (entry.key === undefined) return [entry, ...registrations]
|
return [entry, ...registrations]
|
||||||
return [entry, ...registrations.filter((x) => x.key !== entry.key)]
|
}
|
||||||
|
|
||||||
|
export function activeCommandRegistrations(registrations: CommandRegistration[]) {
|
||||||
|
const keys = new Set<string>()
|
||||||
|
return registrations.filter((entry) => {
|
||||||
|
if (entry.key === undefined) return true
|
||||||
|
if (keys.has(entry.key)) return false
|
||||||
|
keys.add(entry.key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseKeybind(config: string): Keybind[] {
|
export function parseKeybind(config: string): Keybind[] {
|
||||||
@@ -281,7 +290,7 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex
|
|||||||
const seen = new Set<string>()
|
const seen = new Set<string>()
|
||||||
const all: CommandOption[] = []
|
const all: CommandOption[] = []
|
||||||
|
|
||||||
for (const reg of store.registrations) {
|
for (const reg of activeCommandRegistrations(store.registrations)) {
|
||||||
for (const opt of reg.options()) {
|
for (const opt of reg.options()) {
|
||||||
if (seen.has(opt.id)) {
|
if (seen.has(opt.id)) {
|
||||||
if (import.meta.env.DEV && !warnedDuplicates.has(opt.id)) {
|
if (import.meta.env.DEV && !warnedDuplicates.has(opt.id)) {
|
||||||
@@ -425,7 +434,7 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex
|
|||||||
key: id,
|
key: id,
|
||||||
options,
|
options,
|
||||||
}
|
}
|
||||||
setStore("registrations", (arr) => upsertCommandRegistration(arr, entry))
|
setStore("registrations", (arr) => addCommandRegistration(arr, entry))
|
||||||
onCleanup(() => {
|
onCleanup(() => {
|
||||||
setStore("registrations", (arr) => arr.filter((x) => x !== entry))
|
setStore("registrations", (arr) => arr.filter((x) => x !== entry))
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user