Skip to content

Commit 8ff0f54

Browse files
committed
fix: embed local plugin registry as fallback, always shows plugins
Even if GitHub registry fetch fails, plugins are always available from the embedded LOCAL_REGISTRY. No more 'No plugins available'.
1 parent 2becee5 commit 8ff0f54

2 files changed

Lines changed: 27 additions & 19 deletions

File tree

apps/server/src/index.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ app.get("/widgets", (_req, res) => {
221221

222222
// Plugin store
223223
const REGISTRY_URL = "https://raw.githubusercontent.com/florextech/deck-plugins/main/registry.json";
224+
const LOCAL_REGISTRY = [
225+
{ id: "clock", name: "Clock", description: "Shows current time and date", author: "Deck", version: "1.0.0", official: true, tags: ["widget","utility"], platforms: ["macos","windows","linux"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/clock.js" },
226+
{ id: "system-monitor", name: "System Monitor", description: "CPU, RAM usage and uptime widget", author: "Deck", version: "1.0.0", official: true, tags: ["widget","system"], platforms: ["macos","windows","linux"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/system-monitor.js" },
227+
{ id: "spotify", name: "Spotify", description: "Control Spotify playback and see now playing", author: "Deck", version: "1.0.0", official: true, tags: ["media","music"], platforms: ["macos"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/spotify.js" },
228+
{ id: "pomodoro", name: "Pomodoro Timer", description: "25 min focus timer with notification", author: "Deck", version: "1.0.0", official: true, tags: ["productivity","timer"], platforms: ["macos","windows","linux"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/pomodoro.js" },
229+
];
224230

225231
function currentPlatform(): string {
226232
const p = process.platform;
@@ -234,22 +240,19 @@ app.get("/plugins/store", async (_req, res) => {
234240
const installed = existsSync(pluginsDir) ? readdirSync(pluginsDir).filter(f => f.endsWith(".js")).map(f => f.replace(".js", "")) : [];
235241
const state = loadPluginsState();
236242
const platform = currentPlatform();
243+
let registryPlugins: Array<{ id: string; platforms?: string[]; [k: string]: unknown }> = LOCAL_REGISTRY;
237244
try {
238245
const r = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(5000) });
239-
const data = await r.json() as { plugins: unknown[] };
240-
const plugins = (data.plugins as Array<{ id: string; platforms?: string[] }>).map(p => ({ ...p, installed: installed.includes(p.id), disabled: !!state[p.id]?.disabled, currentPlatform: platform }));
241-
// Add local-only plugins not in registry
242-
for (const id of installed) {
243-
if (!plugins.find(p => p.id === id)) {
244-
plugins.push({ id, name: id, description: "Installed locally", installed: true, disabled: !!state[id]?.disabled, currentPlatform: platform } as never);
245-
}
246+
const data = await r.json() as { plugins: Array<{ id: string; platforms?: string[] }> };
247+
if (data.plugins && data.plugins.length) registryPlugins = data.plugins;
248+
} catch { /* use local fallback */ }
249+
const plugins = registryPlugins.map(p => ({ ...p, installed: installed.includes(p.id), disabled: !!state[p.id]?.disabled, currentPlatform: platform }));
250+
for (const id of installed) {
251+
if (!plugins.find(p => p.id === id)) {
252+
plugins.push({ id, name: id, description: "Installed locally", installed: true, disabled: !!state[id]?.disabled, currentPlatform: platform } as never);
246253
}
247-
res.json({ plugins });
248-
} catch {
249-
// Fallback: show installed plugins even if registry is unreachable
250-
const plugins = installed.map(id => ({ id, name: id, description: "Installed locally", installed: true, disabled: !!state[id]?.disabled, currentPlatform: platform }));
251-
res.json({ plugins, offline: true });
252254
}
255+
res.json({ plugins });
253256
});
254257

255258
app.post("/plugins/toggle", (req, res) => {

electron/main.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ app.whenReady().then(() => {
113113
const pluginsDir = join(app.getPath("userData"), "plugins");
114114
const pluginsStatePath = join(app.getPath("userData"), "plugins-state.json");
115115
const REGISTRY_URL = "https://raw.githubusercontent.com/florextech/deck-plugins/main/registry.json";
116+
const LOCAL_REGISTRY = [
117+
{ id: "clock", name: "Clock", description: "Shows current time and date", author: "Deck", version: "1.0.0", official: true, tags: ["widget","utility"], platforms: ["macos","windows","linux"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/clock.js" },
118+
{ id: "system-monitor", name: "System Monitor", description: "CPU, RAM usage and uptime widget", author: "Deck", version: "1.0.0", official: true, tags: ["widget","system"], platforms: ["macos","windows","linux"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/system-monitor.js" },
119+
{ id: "spotify", name: "Spotify", description: "Control Spotify playback and see now playing", author: "Deck", version: "1.0.0", official: true, tags: ["media","music"], platforms: ["macos"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/spotify.js" },
120+
{ id: "pomodoro", name: "Pomodoro Timer", description: "25 min focus timer with notification", author: "Deck", version: "1.0.0", official: true, tags: ["productivity","timer"], platforms: ["macos","windows","linux"], url: "https://raw.githubusercontent.com/florextech/deck/main/plugins-available/pomodoro.js" },
121+
];
116122

117123
function loadPluginsState() { try { return JSON.parse(readFileSync(pluginsStatePath, "utf-8")); } catch { return {}; } }
118124
function savePluginsState(state) { writeFileSync(pluginsStatePath, JSON.stringify(state, null, 2)); }
@@ -122,16 +128,15 @@ app.whenReady().then(() => {
122128
const installed = existsSync(pluginsDir) ? readdirSync(pluginsDir).filter(f => f.endsWith(".js")).map(f => f.replace(".js", "")) : [];
123129
const state = loadPluginsState();
124130
const platform = currentPlatform();
131+
let registryPlugins = LOCAL_REGISTRY;
125132
try {
126133
const r = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(5000) });
127134
const data = await r.json();
128-
const plugins = data.plugins.map(p => ({ ...p, installed: installed.includes(p.id), disabled: !!state[p.id]?.disabled, currentPlatform: platform }));
129-
for (const id of installed) { if (!plugins.find(p => p.id === id)) plugins.push({ id, name: id, description: "Installed locally", installed: true, disabled: !!state[id]?.disabled, currentPlatform: platform }); }
130-
res.json({ plugins });
131-
} catch {
132-
const plugins = installed.map(id => ({ id, name: id, description: "Installed locally", installed: true, disabled: !!state[id]?.disabled, currentPlatform: platform }));
133-
res.json({ plugins, offline: true });
134-
}
135+
if (data.plugins && data.plugins.length) registryPlugins = data.plugins;
136+
} catch {}
137+
const plugins = registryPlugins.map(p => ({ ...p, installed: installed.includes(p.id), disabled: !!state[p.id]?.disabled, currentPlatform: platform }));
138+
for (const id of installed) { if (!plugins.find(p => p.id === id)) plugins.push({ id, name: id, description: "Installed locally", installed: true, disabled: !!state[id]?.disabled, currentPlatform: platform }); }
139+
res.json({ plugins });
135140
});
136141

137142
srv.post("/plugins/toggle", (req, res) => {

0 commit comments

Comments
 (0)