From df48f9b5a06eae10b4e3ab5ee4e26570eea25676 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 28 Mar 2025 17:01:16 +0000 Subject: [PATCH] unneeded rgb check code --- packages/bbui/src/Form/Core/File.svelte | 5 +- packages/bbui/src/Form/File.svelte | 3 +- .../app/[application]/settings/pwa.svelte | 53 +++++------ .../src/api/controllers/static/index.ts | 90 +++++++++++++++---- packages/types/src/documents/app/app.ts | 2 + 5 files changed, 100 insertions(+), 53 deletions(-) diff --git a/packages/bbui/src/Form/Core/File.svelte b/packages/bbui/src/Form/Core/File.svelte index a4bc576e95..1a9014e741 100644 --- a/packages/bbui/src/Form/Core/File.svelte +++ b/packages/bbui/src/Form/Core/File.svelte @@ -6,7 +6,10 @@ const BYTES_IN_MB = 1000000 - export let value: File | undefined = undefined + export let value: + | File + | { name: string; type: string; size?: number } + | undefined = undefined export let title: string = "Upload file" export let disabled: boolean = false export let allowClear: boolean | undefined = undefined diff --git a/packages/bbui/src/Form/File.svelte b/packages/bbui/src/Form/File.svelte index b596b81537..ce7506d829 100644 --- a/packages/bbui/src/Form/File.svelte +++ b/packages/bbui/src/Form/File.svelte @@ -12,7 +12,8 @@ export let extensions: string[] | undefined = undefined export let error: string | undefined = undefined export let title: string | undefined = undefined - export let value: File | undefined = undefined + export let value: File | { name: string; type: string } | undefined = + undefined export let tooltip: string | undefined = undefined export let helpText: string | undefined = undefined diff --git a/packages/builder/src/pages/builder/app/[application]/settings/pwa.svelte b/packages/builder/src/pages/builder/app/[application]/settings/pwa.svelte index 7b4b20dff8..2d55a0bd5e 100644 --- a/packages/builder/src/pages/builder/app/[application]/settings/pwa.svelte +++ b/packages/builder/src/pages/builder/app/[application]/settings/pwa.svelte @@ -25,7 +25,7 @@ let saving = false let pwaEnabled = true - let pwaBuilderIcons: any = null + let uploadingIcons = false let pwaConfig = $appStore.pwa || { name: "", @@ -39,38 +39,24 @@ start_url: "", } - function ensureHexFormat(color: string) { - if (!color) return "#FFFFFF" - if (color.startsWith("#")) return color - - const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/) - if (rgbMatch) { - const r = parseInt(rgbMatch[1]).toString(16).padStart(2, "0") - const g = parseInt(rgbMatch[2]).toString(16).padStart(2, "0") - const b = parseInt(rgbMatch[3]).toString(16).padStart(2, "0") - return `#${r}${g}${b}`.toUpperCase() - } - - const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/) - if (rgbaMatch) { - const r = parseInt(rgbaMatch[1]).toString(16).padStart(2, "0") - const g = parseInt(rgbaMatch[2]).toString(16).padStart(2, "0") - const b = parseInt(rgbaMatch[3]).toString(16).padStart(2, "0") - return `#${r}${g}${b}`.toUpperCase() - } - - return "#FFFFFF" - } + $: iconCount = pwaConfig.icons?.length || 0 + $: iconFileDisplay = iconCount + ? { + name: `${iconCount} icons uploaded`, + type: "file", + } + : undefined function getCssVariableValue(cssVar: string) { try { if (cssVar?.startsWith("#")) return cssVar const varMatch = cssVar?.match(/var\((.*?)\)/) - if (!varMatch) return ensureHexFormat(cssVar) + if (!varMatch) return "#FFFFFF" - const varName = varMatch[1] - return ensureHexFormat( + const varName = varMatch?.[1] + return ( + varName && getComputedStyle(document.documentElement) .getPropertyValue(varName) .trim() @@ -82,7 +68,10 @@ } async function handlePWAZip(file: File) { + if (!file) return + try { + uploadingIcons = true const data = new FormData() data.append("file", file as any) const result = await API.uploadPWAZip(data) @@ -91,16 +80,14 @@ notifications.success( `Processed ${pwaConfig.icons.length} icons from PWA Builder` ) - pwaBuilderIcons = { - name: file instanceof File ? file.name : "PWA Icons", - type: "file", - } } catch (error: any) { console.error("Error processing PWA Builder zip:", error) notifications.error( "Failed to process PWA Builder zip: " + (error.message || "Unknown error") ) + } finally { + uploadingIcons = false } } @@ -208,8 +195,8 @@ notifications.error("File too large. 20mb limit")} extensions={[".zip"]} on:change={e => e.detail && handlePWAZip(e.detail)} - value={pwaBuilderIcons} - disabled={!pwaEnabled} + value={iconFileDisplay} + disabled={!pwaEnabled || uploadingIcons} /> @@ -257,7 +244,7 @@
-
diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts index 8dd13d5d30..b0ebae1a96 100644 --- a/packages/server/src/api/controllers/static/index.ts +++ b/packages/server/src/api/controllers/static/index.ts @@ -144,11 +144,14 @@ export const uploadFile = async function ( export async function processPWAZip(ctx: UserCtx) { const file = ctx.request.files?.file - console.log("file", file) if (!file || Array.isArray(file)) { ctx.throw(400, "No file or multiple files provided") } + if (!file.path || !file.name?.toLowerCase().endsWith(".zip")) { + ctx.throw(400, "Invalid file - must be a zip file") + } + const tempDir = join(tmpdir(), `pwa-${Date.now()}`) try { await fs.promises.mkdir(tempDir, { recursive: true }) @@ -156,35 +159,60 @@ export async function processPWAZip(ctx: UserCtx) { await extract(file.path, { dir: tempDir }) const iconsJsonPath = join(tempDir, "icons.json") - if (!iconsJsonPath) { + if (!fs.existsSync(iconsJsonPath)) { ctx.throw(400, "Invalid zip structure - missing icons.json") } - const iconsContent = await fs.promises.readFile(iconsJsonPath, "utf-8") - const iconsData = JSON.parse(iconsContent) + let iconsData + try { + const iconsContent = await fs.promises.readFile(iconsJsonPath, "utf-8") + iconsData = JSON.parse(iconsContent) + } catch (error) { + ctx.throw(400, "Invalid icons.json file - could not parse JSON") + } + + if (!iconsData.icons || !Array.isArray(iconsData.icons)) { + ctx.throw(400, "Invalid icons.json file - missing icons array") + } const icons = [] const baseDir = path.dirname(iconsJsonPath) + const appId = context.getProdAppId() for (const icon of iconsData.icons) { - const extension = path.extname(icon.src) - const key = `${context.getProdAppId()}/pwa/${uuid.v4()}${extension}` + if (!icon.src || !icon.sizes || !fs.existsSync(join(baseDir, icon.src))) { + continue + } - const result = await objectStore.upload({ - bucket: ObjectStoreBuckets.APPS, - filename: key, - path: path.join(baseDir, icon.src), - type: icon.type || "image/png", - }) + const extension = path.extname(icon.src) || ".png" + const key = `${appId}/pwa/${uuid.v4()}${extension}` + const mimeType = + icon.type || (extension === ".png" ? "image/png" : "image/jpeg") - if (result.Key) { - icons.push({ - src: result.Key, - sizes: icon.sizes, - type: icon.type || "image/png", + try { + const result = await objectStore.upload({ + bucket: ObjectStoreBuckets.APPS, + filename: key, + path: join(baseDir, icon.src), + type: mimeType, }) + + if (result.Key) { + icons.push({ + src: result.Key, + sizes: icon.sizes, + type: mimeType, + }) + } + } catch (uploadError) { + console.error(`Failed to upload icon ${icon.src}:`, uploadError) } } + + if (icons.length === 0) { + ctx.throw(400, "No valid icons found in the zip file") + } + ctx.body = { icons } } catch (error: any) { ctx.throw(500, `Error processing zip: ${error.message}`) @@ -521,16 +549,42 @@ export async function serveManifest(ctx: UserCtx) { background_color: appInfo.pwa.background_color || "#FFFFFF", theme_color: appInfo.pwa.theme_color || "#FFFFFF", icons: [], + screenshots: [], } if (appInfo.pwa.icons && appInfo.pwa.icons.length > 0) { try { manifest.icons = await objectStore.enrichPWAImages(appInfo.pwa.icons) + + const desktopScreenshot = manifest.icons.find( + icon => icon.sizes === "1240x600" || icon.sizes === "2480x1200" + ) + if (desktopScreenshot) { + manifest.screenshots?.push({ + src: desktopScreenshot.src, + sizes: desktopScreenshot.sizes, + type: "image/png", + form_factor: "wide", + label: "Desktop view", + }) + } + + const mobileScreenshot = manifest.icons.find( + icon => icon.sizes === "620x620" || icon.sizes === "1024x1024" + ) + if (mobileScreenshot) { + manifest.screenshots?.push({ + src: mobileScreenshot.src, + sizes: mobileScreenshot.sizes, + type: "image/png", + label: "Mobile view", + }) + } } catch (error) { console.error("Error processing manifest icons:", error) } } - console.log(JSON.stringify(manifest)) + ctx.set("Content-Type", "application/json") ctx.body = manifest } catch (error) { diff --git a/packages/types/src/documents/app/app.ts b/packages/types/src/documents/app/app.ts index e2ccc4cbcf..d61ce3c83f 100644 --- a/packages/types/src/documents/app/app.ts +++ b/packages/types/src/documents/app/app.ts @@ -101,6 +101,8 @@ export interface PWAManifestImage { src: string sizes: string type: string + form_factor?: "wide" | "narrow" | undefined + label?: string } export interface AppScript {