import { isEqual } from "lodash-es"; import { create } from "zustand"; import { combine } from "zustand/middleware"; import { shortcutServiceClient } from "@/grpcweb"; import { Shortcut } from "@/types/proto/api/v1/shortcut_service"; interface State { shortcutMapById: Record; } const getDefaultState = (): State => { return { shortcutMapById: {}, }; }; const useShortcutStore = create( combine(getDefaultState(), (set, get) => ({ fetchShortcutList: async () => { const { shortcuts } = await shortcutServiceClient.listShortcuts({}); const shortcutMap = get().shortcutMapById; shortcuts.forEach((shortcut) => { shortcutMap[shortcut.id] = shortcut; }); set({ shortcutMapById: shortcutMap }); return shortcuts; }, fetchShortcutByName: async (name: string) => { const shortcut = await shortcutServiceClient.getShortcutByName({ name, }); return shortcut; }, getOrFetchShortcutById: async (id: number) => { const shortcutMap = get().shortcutMapById; if (shortcutMap[id]) { return shortcutMap[id] as Shortcut; } const shortcut = await shortcutServiceClient.getShortcut({ id, }); shortcutMap[id] = shortcut; set({ shortcutMapById: shortcutMap }); return shortcut; }, getShortcutById: (id: number) => { const shortcutMap = get().shortcutMapById; return shortcutMap[id] || unknownShortcut; }, getShortcutList: () => { return Object.values(get().shortcutMapById); }, createShortcut: async (shortcut: Shortcut) => { const createdShortcut = await shortcutServiceClient.createShortcut({ shortcut: shortcut, }); const shortcutMap = get().shortcutMapById; shortcutMap[createdShortcut.id] = createdShortcut; set({ shortcutMapById: shortcutMap }); return createdShortcut; }, updateShortcut: async (shortcut: Partial, updateMask: string[]) => { const updatedShortcut = await shortcutServiceClient.updateShortcut({ shortcut: shortcut, updateMask, }); const shortcutMap = get().shortcutMapById; shortcutMap[updatedShortcut.id] = updatedShortcut; set({ shortcutMapById: shortcutMap }); return updatedShortcut; }, deleteShortcut: async (id: number) => { await shortcutServiceClient.deleteShortcut({ id, }); const shortcutMap = get().shortcutMapById; delete shortcutMap[id]; set({ shortcutMapById: shortcutMap }); }, })), ); const unknownShortcut: Shortcut = Shortcut.fromPartial({ id: -1, name: "Unknown", }); export const getShortcutUpdateMask = (shortcut: Shortcut, updatingShortcut: Shortcut) => { const updateMask: string[] = []; if (!isEqual(shortcut.name, updatingShortcut.name)) { updateMask.push("name"); } if (!isEqual(shortcut.link, updatingShortcut.link)) { updateMask.push("link"); } if (!isEqual(shortcut.title, updatingShortcut.title)) { updateMask.push("title"); } if (!isEqual(shortcut.description, updatingShortcut.description)) { updateMask.push("description"); } if (!isEqual(shortcut.tags, updatingShortcut.tags)) { updateMask.push("tags"); } if (!isEqual(shortcut.visibility, updatingShortcut.visibility)) { updateMask.push("visibility"); } if (!isEqual(shortcut.ogMetadata, updatingShortcut.ogMetadata)) { updateMask.push("og_metadata"); } return updateMask; }; export default useShortcutStore;