// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import getMacApps from "./get-mac-app"; import fs from "fs"; import path from "path"; import translate from "./translate"; import os from "os"; const icondir = path.join(os.tmpdir(), "ProcessIcon"); const exists = fs.existsSync(icondir); if (!exists) { fs.mkdirSync(icondir); } const isZhRegex = /[\u4e00-\u9fa5]/; async function getAppIcon( appPath: string, nativeImage: { createThumbnailFromPath: ( iconPath: string, size: { width: number; height: number } ) => { toDataURL: () => string }; }, name: string ) { try { const iconpath = path.join(icondir, `${name}.png`); const iconnone = path.join(icondir, `${name}.none`); const exists = fs.existsSync(iconpath); const existsnone = fs.existsSync(iconnone); if (exists) return true; if (existsnone) return false; const appName: string = appPath.split("/").pop() || ""; const extname: string = path.extname(appName); const appSubStr: string = appName.split(extname)[0]; const path1 = path.join(appPath, `/Contents/Resources/App.icns`); const path2 = path.join(appPath, `/Contents/Resources/AppIcon.icns`); const path3 = path.join(appPath, `/Contents/Resources/${appSubStr}.icns`); const path4 = path.join( appPath, `/Contents/Resources/${appSubStr.replace(" ", "")}.icns` ); let iconPath: string = path1; if (fs.existsSync(path1)) { iconPath = path1; } else if (fs.existsSync(path2)) { iconPath = path2; } else if (fs.existsSync(path3)) { iconPath = path3; } else if (fs.existsSync(path4)) { iconPath = path4; } else { // 性能最低的方式 const resourceList = fs.readdirSync( path.join(appPath, `/Contents/Resources`) ); const iconName = resourceList.filter( (file) => path.extname(file) === ".icns" )[0]; if (!iconName) { fs.writeFileSync(iconnone, "") return false; } iconPath = path.join(appPath, `/Contents/Resources/${iconName}`); } const img = await nativeImage.createThumbnailFromPath(iconPath, { width: 64, height: 64, }); const base64Data = img.toDataURL().replace(/^data:.+;base64,/, '"'); const result = Buffer.from(base64Data, "base64"); fs.writeFile(iconpath, result, "base64", () => { // todo }); return true; } catch (e) { return false; } } export default async (nativeImage: any) => { let apps: any = await getMacApps.getApps(); apps = apps.filter((app: any) => { const extname = path.extname(app.path); return extname === ".app" || extname === ".prefPane"; }); for (const app of apps) { if (await getAppIcon(app.path, nativeImage, app._name)) { app.icon = "image://" + path.join( os.tmpdir(), "ProcessIcon", `${encodeURIComponent(app._name)}.png` ); } // todo getApp size } apps = apps.filter((app: any) => !!app.icon); apps = apps.map((app: any) => { const appName: any = app.path.split("/").pop(); const extname = path.extname(appName); const appSubStr = appName.split(extname)[0]; let fileOptions = { ...app, value: "plugin", desc: app.path, pluginType: "app", action: `open ${app.path.replace(/ /g, "\\ ") as string}`, keyWords: [appSubStr], }; if (app._name && isZhRegex.test(app._name)) { const py = translate(app._name); const pinyinArr = py.split(","); const firstLatter = pinyinArr.map((py) => py[0]); // 拼音 fileOptions.keyWords.push(pinyinArr.join("")); // 缩写 fileOptions.keyWords.push(firstLatter.join("")); // 中文 fileOptions.keyWords.push(app._name); } fileOptions = { ...fileOptions, name: app._name, names: JSON.parse(JSON.stringify(fileOptions.keyWords)), }; return fileOptions; }); return apps; };