101 lines
3.1 KiB
JavaScript
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 }
|