unneeded rgb check code

This commit is contained in:
Peter Clement 2025-03-28 17:01:16 +00:00
parent 366239635f
commit df48f9b5a0
5 changed files with 100 additions and 53 deletions

View File

@ -6,7 +6,10 @@
const BYTES_IN_MB = 1000000 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 title: string = "Upload file"
export let disabled: boolean = false export let disabled: boolean = false
export let allowClear: boolean | undefined = undefined export let allowClear: boolean | undefined = undefined

View File

@ -12,7 +12,8 @@
export let extensions: string[] | undefined = undefined export let extensions: string[] | undefined = undefined
export let error: string | undefined = undefined export let error: string | undefined = undefined
export let title: 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 tooltip: string | undefined = undefined
export let helpText: string | undefined = undefined export let helpText: string | undefined = undefined

View File

@ -25,7 +25,7 @@
let saving = false let saving = false
let pwaEnabled = true let pwaEnabled = true
let pwaBuilderIcons: any = null let uploadingIcons = false
let pwaConfig = $appStore.pwa || { let pwaConfig = $appStore.pwa || {
name: "", name: "",
@ -39,38 +39,24 @@
start_url: "", start_url: "",
} }
function ensureHexFormat(color: string) { $: iconCount = pwaConfig.icons?.length || 0
if (!color) return "#FFFFFF" $: iconFileDisplay = iconCount
if (color.startsWith("#")) return color ? {
name: `${iconCount} icons uploaded`,
const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/) type: "file",
if (rgbMatch) { }
const r = parseInt(rgbMatch[1]).toString(16).padStart(2, "0") : undefined
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"
}
function getCssVariableValue(cssVar: string) { function getCssVariableValue(cssVar: string) {
try { try {
if (cssVar?.startsWith("#")) return cssVar if (cssVar?.startsWith("#")) return cssVar
const varMatch = cssVar?.match(/var\((.*?)\)/) const varMatch = cssVar?.match(/var\((.*?)\)/)
if (!varMatch) return ensureHexFormat(cssVar) if (!varMatch) return "#FFFFFF"
const varName = varMatch[1] const varName = varMatch?.[1]
return ensureHexFormat( return (
varName &&
getComputedStyle(document.documentElement) getComputedStyle(document.documentElement)
.getPropertyValue(varName) .getPropertyValue(varName)
.trim() .trim()
@ -82,7 +68,10 @@
} }
async function handlePWAZip(file: File) { async function handlePWAZip(file: File) {
if (!file) return
try { try {
uploadingIcons = true
const data = new FormData() const data = new FormData()
data.append("file", file as any) data.append("file", file as any)
const result = await API.uploadPWAZip(data) const result = await API.uploadPWAZip(data)
@ -91,16 +80,14 @@
notifications.success( notifications.success(
`Processed ${pwaConfig.icons.length} icons from PWA Builder` `Processed ${pwaConfig.icons.length} icons from PWA Builder`
) )
pwaBuilderIcons = {
name: file instanceof File ? file.name : "PWA Icons",
type: "file",
}
} catch (error: any) { } catch (error: any) {
console.error("Error processing PWA Builder zip:", error) console.error("Error processing PWA Builder zip:", error)
notifications.error( notifications.error(
"Failed to process PWA Builder zip: " + "Failed to process PWA Builder zip: " +
(error.message || "Unknown error") (error.message || "Unknown error")
) )
} finally {
uploadingIcons = false
} }
} }
@ -208,8 +195,8 @@
notifications.error("File too large. 20mb limit")} notifications.error("File too large. 20mb limit")}
extensions={[".zip"]} extensions={[".zip"]}
on:change={e => e.detail && handlePWAZip(e.detail)} on:change={e => e.detail && handlePWAZip(e.detail)}
value={pwaBuilderIcons} value={iconFileDisplay}
disabled={!pwaEnabled} disabled={!pwaEnabled || uploadingIcons}
/> />
</div> </div>
</div> </div>
@ -257,7 +244,7 @@
</div> </div>
<div class="actions"> <div class="actions">
<Button cta on:click={handleSubmit} disabled={!pwaEnabled}> <Button cta on:click={handleSubmit} disabled={!pwaEnabled || saving}>
{saving ? "Saving..." : "Save"} {saving ? "Saving..." : "Save"}
</Button> </Button>
</div> </div>

View File

@ -144,11 +144,14 @@ export const uploadFile = async function (
export async function processPWAZip(ctx: UserCtx) { export async function processPWAZip(ctx: UserCtx) {
const file = ctx.request.files?.file const file = ctx.request.files?.file
console.log("file", file)
if (!file || Array.isArray(file)) { if (!file || Array.isArray(file)) {
ctx.throw(400, "No file or multiple files provided") 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()}`) const tempDir = join(tmpdir(), `pwa-${Date.now()}`)
try { try {
await fs.promises.mkdir(tempDir, { recursive: true }) await fs.promises.mkdir(tempDir, { recursive: true })
@ -156,35 +159,60 @@ export async function processPWAZip(ctx: UserCtx) {
await extract(file.path, { dir: tempDir }) await extract(file.path, { dir: tempDir })
const iconsJsonPath = join(tempDir, "icons.json") const iconsJsonPath = join(tempDir, "icons.json")
if (!iconsJsonPath) { if (!fs.existsSync(iconsJsonPath)) {
ctx.throw(400, "Invalid zip structure - missing icons.json") ctx.throw(400, "Invalid zip structure - missing icons.json")
} }
const iconsContent = await fs.promises.readFile(iconsJsonPath, "utf-8") let iconsData
const iconsData = JSON.parse(iconsContent) 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 icons = []
const baseDir = path.dirname(iconsJsonPath) const baseDir = path.dirname(iconsJsonPath)
const appId = context.getProdAppId()
for (const icon of iconsData.icons) { for (const icon of iconsData.icons) {
const extension = path.extname(icon.src) if (!icon.src || !icon.sizes || !fs.existsSync(join(baseDir, icon.src))) {
const key = `${context.getProdAppId()}/pwa/${uuid.v4()}${extension}` continue
}
const result = await objectStore.upload({ const extension = path.extname(icon.src) || ".png"
bucket: ObjectStoreBuckets.APPS, const key = `${appId}/pwa/${uuid.v4()}${extension}`
filename: key, const mimeType =
path: path.join(baseDir, icon.src), icon.type || (extension === ".png" ? "image/png" : "image/jpeg")
type: icon.type || "image/png",
})
if (result.Key) { try {
icons.push({ const result = await objectStore.upload({
src: result.Key, bucket: ObjectStoreBuckets.APPS,
sizes: icon.sizes, filename: key,
type: icon.type || "image/png", 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 } ctx.body = { icons }
} catch (error: any) { } catch (error: any) {
ctx.throw(500, `Error processing zip: ${error.message}`) ctx.throw(500, `Error processing zip: ${error.message}`)
@ -521,16 +549,42 @@ export async function serveManifest(ctx: UserCtx<void, any>) {
background_color: appInfo.pwa.background_color || "#FFFFFF", background_color: appInfo.pwa.background_color || "#FFFFFF",
theme_color: appInfo.pwa.theme_color || "#FFFFFF", theme_color: appInfo.pwa.theme_color || "#FFFFFF",
icons: [], icons: [],
screenshots: [],
} }
if (appInfo.pwa.icons && appInfo.pwa.icons.length > 0) { if (appInfo.pwa.icons && appInfo.pwa.icons.length > 0) {
try { try {
manifest.icons = await objectStore.enrichPWAImages(appInfo.pwa.icons) 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) { } catch (error) {
console.error("Error processing manifest icons:", error) console.error("Error processing manifest icons:", error)
} }
} }
console.log(JSON.stringify(manifest))
ctx.set("Content-Type", "application/json") ctx.set("Content-Type", "application/json")
ctx.body = manifest ctx.body = manifest
} catch (error) { } catch (error) {

View File

@ -101,6 +101,8 @@ export interface PWAManifestImage {
src: string src: string
sizes: string sizes: string
type: string type: string
form_factor?: "wide" | "narrow" | undefined
label?: string
} }
export interface AppScript { export interface AppScript {