From 2e743490c9bf3fb2a010ee0d8a713637351285d0 Mon Sep 17 00:00:00 2001 From: Michel Roegl-Brunner Date: Wed, 10 Sep 2025 15:13:08 +0200 Subject: [PATCH] feat: Remove executable check and add logo support for local scripts - Remove executable check from ScriptsList component - All scripts now show as runnable regardless of permissions - Add logo support using JSON data from script metadata - Update ScriptInfo interface to include logo and slug fields - Modify getCtScripts to fetch logo from corresponding JSON files - Update ScriptsList UI to display logos with fallback to file icons - Fix TypeScript errors for proper type safety --- src/app/_components/ScriptsList.tsx | 31 ++++++++++++++++--------- src/server/lib/scripts.ts | 20 +++++++++++++++- src/server/services/scriptDownloader.ts | 1 + 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/app/_components/ScriptsList.tsx b/src/app/_components/ScriptsList.tsx index e942952..5cf07a6 100644 --- a/src/app/_components/ScriptsList.tsx +++ b/src/app/_components/ScriptsList.tsx @@ -88,16 +88,30 @@ export function ScriptsList({ onRunScript }: ScriptsListProps) { >
- {getFileIcon(script.extension)} + {script.logo ? ( + {`${script.name} { + // Fallback to file icon if logo fails to load + e.currentTarget.style.display = 'none'; + const nextElement = e.currentTarget.nextElementSibling as HTMLElement; + if (nextElement) { + nextElement.style.display = 'block'; + } + }} + /> + ) : null} + + {getFileIcon(script.extension)} +

{script.name}

Size: {formatFileSize(script.size)}

Modified: {formatDate(script.lastModified)}

Extension: {script.extension}

-

- {script.executable ? '✅ Executable' : '❌ Not executable'} -

@@ -111,14 +125,9 @@ export function ScriptsList({ onRunScript }: ScriptsListProps) {
diff --git a/src/server/lib/scripts.ts b/src/server/lib/scripts.ts index dd0a2ba..0285767 100644 --- a/src/server/lib/scripts.ts +++ b/src/server/lib/scripts.ts @@ -2,6 +2,7 @@ import { readdir, stat, access } from 'fs/promises'; import { join, resolve, extname } from 'path'; import { env } from '~/env.js'; import { spawn, ChildProcess } from 'child_process'; +import { localScriptsService } from '~/server/services/localScripts'; export interface ScriptInfo { name: string; @@ -10,6 +11,8 @@ export interface ScriptInfo { size: number; lastModified: Date; executable: boolean; + logo?: string; + slug?: string; } export class ScriptManager { @@ -85,13 +88,28 @@ export class ScriptManager { // Check if file is executable const executable = await this.isExecutable(filePath); + // Extract slug from filename (remove .sh extension) + const slug = file.replace(/\.sh$/, ''); + + // Try to get logo from JSON data + let logo: string | undefined; + try { + const scriptData = await localScriptsService.getScriptBySlug(slug); + logo = scriptData?.logo || undefined; + } catch (error) { + // JSON file might not exist, that's okay + console.log(`No JSON data found for ${slug}:`, error); + } + scripts.push({ name: file, path: filePath, extension, size: stats.size, lastModified: stats.mtime, - executable + executable, + logo, + slug }); } } diff --git a/src/server/services/scriptDownloader.ts b/src/server/services/scriptDownloader.ts index 5a7ecc8..6e29e66 100644 --- a/src/server/services/scriptDownloader.ts +++ b/src/server/services/scriptDownloader.ts @@ -49,6 +49,7 @@ export class ScriptDownloaderService { const newPattern = 'SCRIPT_DIR="$(dirname "$0")" \nsource "$SCRIPT_DIR/../core/build.func"'; return content.replace(oldPattern, newPattern); + } async loadScript(script: Script): Promise<{ success: boolean; message: string; files: string[] }> {