Files
2026-07-13 12:46:20 +08:00

101 lines
3.1 KiB
JavaScript

/**
* Install .desktop file and icon for AppImage on Linux
* so that taskbars (e.g. UOS/Deepin dde-dock) can find the icon.
*
* This is standard practice for AppImage — the format uses a volatile
* FUSE mount path, so the embedded .desktop file and icon are never
* found by desktop environments that look in XDG standard locations.
*/
const fs = require('fs')
const path = require('path')
const os = require('os')
const log = require('../common/log')
function installDesktopFile () {
if (process.platform !== 'linux' || !process.env.APPIMAGE) {
return
}
const appImagePath = process.env.APPIMAGE
const home = os.homedir()
const desktopId = 'electerm'
const appsDir = path.join(home, '.local', 'share', 'applications')
const iconsDir = path.join(
home, '.local', 'share', 'icons',
'hicolor', '128x128', 'apps'
)
const desktopFilePath = path.join(appsDir, `${desktopId}.desktop`)
const iconFilePath = path.join(iconsDir, `${desktopId}.png`)
// Icon source inside the AppImage (asar-aware path — Electron's fs
// module transparently reads from inside app.asar)
const srcIconPath = path.join(
process.resourcesPath,
'app.asar', 'assets', 'images', 'electerm-round-128x128.png'
)
const desktopContent = [
'[Desktop Entry]',
'Name=electerm',
'Comment=Terminal/SSH/SFTP client',
`Exec=${appImagePath} %U`,
`Icon=${iconFilePath}`,
'Terminal=false',
'Type=Application',
'Categories=Development;System;TerminalEmulator;',
'StartupWMClass=electerm',
'MimeType=x-scheme-handler/ssh;x-scheme-handler/telnet;' +
'x-scheme-handler/rdp;x-scheme-handler/vnc;' +
'x-scheme-handler/serial;x-scheme-handler/spice;' +
'x-scheme-handler/electerm;',
''
].join('\n')
try {
// Skip if a system-level .desktop file exists (deb/rpm installs one
// to /usr/share/applications/) — don't override it.
// Also clean up any leftover user-level file from a previous AppImage run.
const sysDesktop = '/usr/share/applications/electerm.desktop'
if (fs.existsSync(sysDesktop)) {
try {
fs.unlinkSync(desktopFilePath)
fs.unlinkSync(iconFilePath)
} catch (_) {}
return
}
// Skip if .desktop file already has the correct content
let existing = ''
try {
existing = fs.readFileSync(desktopFilePath, 'utf8')
} catch (_) {}
if (existing === desktopContent) {
return
}
fs.mkdirSync(appsDir, { recursive: true })
fs.mkdirSync(iconsDir, { recursive: true })
// Copy icon once (doesn't change between versions)
if (!fs.existsSync(iconFilePath) && fs.existsSync(srcIconPath)) {
fs.copyFileSync(srcIconPath, iconFilePath)
}
fs.writeFileSync(desktopFilePath, desktopContent)
// Refresh desktop database so the DE picks up the new entry
try {
require('child_process').execSync(
'update-desktop-database ~/.local/share/applications 2>/dev/null'
)
} catch (_) {}
log.info(`[appimage] Installed .desktop file to ${desktopFilePath}`)
} catch (e) {
log.error('[appimage] Failed to install desktop file:', e.message)
}
}
module.exports = { installDesktopFile }