From de4b8eaa4000e789597a2d790c922d3d67a98934 Mon Sep 17 00:00:00 2001 From: Will Stone <654103+will-stone@users.noreply.github.com> Date: Fri, 12 Aug 2022 17:22:35 +0100 Subject: [PATCH] fix: icons not showing on M cpus without rosetta Closes Browser icons not loading #539 --- .ncurc.json | 2 +- forge.config.cjs | 4 +- package-lock.json | 134 +++++++++++++++++++++++++++++--- package.json | 2 +- src/main/utils/get-app-icons.ts | 46 +++++++---- 5 files changed, 157 insertions(+), 31 deletions(-) diff --git a/.ncurc.json b/.ncurc.json index 18514749..921b45cf 100644 --- a/.ncurc.json +++ b/.ncurc.json @@ -1,3 +1,3 @@ { - "reject": ["file-icon"] + "reject": [] } diff --git a/forge.config.cjs b/forge.config.cjs index 4bb8a619..e4511360 100644 --- a/forge.config.cjs +++ b/forge.config.cjs @@ -1,7 +1,7 @@ module.exports = { packagerConfig: { appBundleId: 'com.browserosaurus', - asar: true, + asar: false, appCategoryType: 'public.app-category.developer-tools', packageManager: 'npm', extendInfo: 'plist/Info.plist', @@ -61,7 +61,7 @@ module.exports = { '@timfish/forge-externals-plugin', { externals: ['file-icon'], - includeDeps: true, + includeDeps: false, }, ], ], diff --git a/package-lock.json b/package-lock.json index b80be296..62abc9d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "clsx": "^1.2.1", "electron-log": "^4.4.8", "fast-deep-equal": "^3.1.3", - "file-icon": "^4.0.0", + "file-icon": "^5.1.0", "immer": "^9.0.15", "lowdb": "^3.0.0", "picocolors": "^1.0.0", @@ -3708,6 +3708,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -4921,6 +4922,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, "engines": { "node": ">=6" } @@ -8082,14 +8084,79 @@ } }, "node_modules/file-icon": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/file-icon/-/file-icon-4.0.0.tgz", - "integrity": "sha512-e3L0RlV1Wq2EiJg5d3vHUJdGY5mMhmxqOKSzUfktsLtBCKFcXH5PzpJ5wMgwgW2D2DbKzOg8i2ptFJjAOlA4Pw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/file-icon/-/file-icon-5.1.0.tgz", + "integrity": "sha512-Yhx00f5jz/y70Ep5Yvd+KcRLaBLNYSqQADEOqM95sKvYlNQRN0nYST3bMja8+cFTJolCH7OlSyp+C1M3Hnzhng==", "dependencies": { - "p-map": "^4.0.0" + "p-map": "^5.3.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-icon/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-icon/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-icon/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-icon/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-icon/node_modules/p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "dependencies": { + "aggregate-error": "^4.0.0" + }, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9569,6 +9636,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "engines": { "node": ">=8" } @@ -12991,6 +13059,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -20638,6 +20707,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -21550,7 +21620,8 @@ "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true }, "cli-cursor": { "version": "3.1.0", @@ -23953,11 +24024,48 @@ } }, "file-icon": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/file-icon/-/file-icon-4.0.0.tgz", - "integrity": "sha512-e3L0RlV1Wq2EiJg5d3vHUJdGY5mMhmxqOKSzUfktsLtBCKFcXH5PzpJ5wMgwgW2D2DbKzOg8i2ptFJjAOlA4Pw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/file-icon/-/file-icon-5.1.0.tgz", + "integrity": "sha512-Yhx00f5jz/y70Ep5Yvd+KcRLaBLNYSqQADEOqM95sKvYlNQRN0nYST3bMja8+cFTJolCH7OlSyp+C1M3Hnzhng==", "requires": { - "p-map": "^4.0.0" + "p-map": "^5.3.0" + }, + "dependencies": { + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "requires": { + "escape-string-regexp": "5.0.0" + } + }, + "escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==" + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==" + }, + "p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "requires": { + "aggregate-error": "^4.0.0" + } + } } }, "filename-reserved-regex": { @@ -25056,7 +25164,8 @@ "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true }, "infer-owner": { "version": "1.0.4", @@ -27609,6 +27718,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, "requires": { "aggregate-error": "^3.0.0" } diff --git a/package.json b/package.json index 55c1b6a1..6e5ae3d0 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "clsx": "^1.2.1", "electron-log": "^4.4.8", "fast-deep-equal": "^3.1.3", - "file-icon": "^4.0.0", + "file-icon": "^5.1.0", "immer": "^9.0.15", "lowdb": "^3.0.0", "picocolors": "^1.0.0", diff --git a/src/main/utils/get-app-icons.ts b/src/main/utils/get-app-icons.ts index 1e373865..7e63951e 100644 --- a/src/main/utils/get-app-icons.ts +++ b/src/main/utils/get-app-icons.ts @@ -1,33 +1,49 @@ import log from 'electron-log' -// @ts-expect-error -- no types provided for file-icon -import fileIcon from 'file-icon' +import { execFile } from 'node:child_process' +import path from 'node:path' +import { promisify } from 'node:util' import type { AppId } from '../../config/apps' import type { Storage } from '../../shared/state/reducer.storage' import { gotAppIcons } from '../state/actions' import { dispatch } from '../state/store' +const execFileP = promisify(execFile) + +const binary = path.join( + __dirname, + '..', + '..', + 'node_modules', + 'file-icon', + 'file-icon', +) + +const HUNDRED_MEGABYTES = 1024 * 1024 * 100 + +async function getIconDataURI(file: string, size: number): Promise { + const { stdout: buffer } = await execFileP( + binary, + [JSON.stringify([{ appOrPID: file, size }])], + { encoding: null, maxBuffer: HUNDRED_MEGABYTES }, + ) + + return `data:image/png;base64,${buffer.toString('base64')}` +} + export async function getAppIcons(apps: Storage['apps']): Promise { try { - const buffers: (Buffer | null)[] = [] + const icons: Partial> = {} for await (const app of apps) { try { - const buffer = await fileIcon.buffer(app.id, { size: 64 }) - buffers.push(buffer) - } catch { - buffers.push(null) + const dataURI = await getIconDataURI(app.id, 64) + icons[app.id] = dataURI + } catch (error: unknown) { + log.warn(error) } } - const icons: Partial> = {} - - for (const [index, buffer] of Object.entries(buffers)) { - icons[apps[Number(index)].id] = buffer - ? `data:image/png;base64,${buffer.toString('base64')}` - : '' - } - dispatch(gotAppIcons(icons)) } catch (error: unknown) { log.error(error)