Equicord/src/equicordplugins/commandPalette/runtime/recents.ts
Jake 1f3b9c9b9d
work in progress commandpalette (#790)
* okay, this is a long one. Initial commit to a long running list of commits and new features.

* multiple refactors, additions ect

* forgor to remove these

* Address Gemini's comments.

* small security fixes

* lord its done

* this has been ticking me off for a while

* lint

* fix(commandPalette): resolve stylelint specificity ordering

* general fixes

* refactor of query boxes

* fix query prompt offset

* fix: lint

* bunch bullshit

* Discard changes to package.json

* graph bullshit

* fix cursor offset

* more finnicky math bullshit

* variable support

* fixes

* fixes2

* but can it run doom?

* delete useless shit

* Delete assets/commandPaletteDoom directory

* more bullshit lol

* fixes

* fix: replace command palette doom runtime

* fix: localize bell dismiss icon

* fix(commandPalette): harden runtime behavior and typing

* fix(commandPalette): import React from webpack common

* fix(commandPalette): avoid React forwardRef dependency

---------

Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
2026-03-14 19:33:59 -04:00

87 lines
2.6 KiB
TypeScript

/*
* Vencord, a Discord client mod
* Copyright (c) 2026 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { DataStore } from "@api/index";
const RECENT_COMMAND_LIMIT = 10;
const RECENT_STORAGE_KEY = "CommandPaletteRecentCommands";
const RECENT_COMMAND_SKIP_IDS = new Set<string>([
"command-palette-rerun-last",
"command-palette-toggle-pin-last",
"command-palette-show-recent",
"command-palette-open-settings"
]);
export interface RecentsStore {
ready: Promise<void>;
record(commandId: string): Promise<void>;
mark(commandId: string): Promise<void>;
list(): string[];
newest(excludeId?: string): string | undefined;
isSkippable(commandId: string): boolean;
}
export function createRecentsStore(bumpRegistryVersion: () => void): RecentsStore {
const recentCommandIds: string[] = [];
const ready = (async () => {
try {
const stored = await DataStore.get<string[]>(RECENT_STORAGE_KEY);
if (!Array.isArray(stored)) return;
for (const id of stored) {
if (typeof id !== "string" || !id) continue;
if (RECENT_COMMAND_SKIP_IDS.has(id)) continue;
if (recentCommandIds.includes(id)) continue;
recentCommandIds.push(id);
if (recentCommandIds.length >= RECENT_COMMAND_LIMIT) break;
}
} catch {
return;
} finally {
bumpRegistryVersion();
}
})();
const persist = async () => {
try {
await ready;
await DataStore.set(RECENT_STORAGE_KEY, [...recentCommandIds]);
} catch {
return;
}
};
const recordInternal = (commandId: string) => {
const index = recentCommandIds.indexOf(commandId);
if (index !== -1) recentCommandIds.splice(index, 1);
recentCommandIds.unshift(commandId);
if (recentCommandIds.length > RECENT_COMMAND_LIMIT) {
recentCommandIds.length = RECENT_COMMAND_LIMIT;
}
};
return {
ready,
record: async commandId => {
recordInternal(commandId);
await persist();
},
mark: async commandId => {
recordInternal(commandId);
await persist();
},
list: () => [...recentCommandIds],
newest: excludeId => {
for (const id of recentCommandIds) {
if (id === excludeId || RECENT_COMMAND_SKIP_IDS.has(id)) continue;
return id;
}
return undefined;
},
isSkippable: commandId => RECENT_COMMAND_SKIP_IDS.has(commandId)
};
}