'use strict' const fs = require('fs') const path = require('path') const { xdgConfigHome } = require('./platform') // Linux 的「开机自启」只能靠 XDG 自启目录里的一个 .desktop:Electron 的 // setLoginItemSettings 在 Linux 上是空实现,桌面环境(GNOME / UKUI / 麒麟 / KDE) // 读的都是 $XDG_CONFIG_HOME/autostart 或 ~/.config/autostart。 const AUTOSTART_FILE = 'scoreboard-console.desktop' // 返回 .desktop 的绝对路径;非 Linux(Windows/macOS 走系统登录项)或拿不到 ~/.config 时 // 返回 null,由调用方回滚配置并记日志,绝不静默当成功。 function resolveAutostartFile({ platform = 'linux', env = process.env } = {}) { if (platform !== 'linux') return null const base = xdgConfigHome(env) return base ? path.join(base, 'autostart', AUTOSTART_FILE) : null } // Exec 字段不是 shell 命令行,路径带空格必须自己加引号,否则自启时会被拆成两个参数、 // 找不到程序(现场装到「Program Files」那种带空格的目录下必然遇到)。 function quoteExec(exePath) { return `"${String(exePath).replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"` } function desktopEntry(exePath) { return [ '[Desktop Entry]', 'Type=Application', 'Version=1.0', 'Name=Scoreboard Console', 'Name[zh_CN]=赛事积分榜', 'Comment=守护服务端并把大屏投到扩展屏', `Exec=${quoteExec(exePath)}`, 'Terminal=false', // 有些桌面环境只认这一个键;写 true 表明这份文件是「启用」状态(关掉是直接删文件) 'X-GNOME-Autostart-enabled=true', 'Hidden=false', '' ].join('\n') } // 「开」与「关」以文件实际状态为准(与 Windows 读登录项同一口径): // 文件在就是开。Hidden=true 是 XDG 规范里「忽略这个文件」的写法 —— 现场从桌面环境的 // 「启动应用程序」面板里关掉自启时会这么标,所以必须认出来,否则界面会显示成还开着。 function isAutostartEnabled({ platform = 'linux', env = process.env } = {}) { const file = resolveAutostartFile({ platform, env }) if (!file) return false let text try { text = fs.readFileSync(file, 'utf8') } catch { return false } return !/^\s*Hidden\s*=\s*true\s*$/im.test(text) } // 开 → 写文件(覆盖旧的,每次启动 Console 按配置重写一遍是幂等的); // 关 → 删文件。与 Windows 的「登录项一直保留、只切 enabled」不同:各桌面环境对 // X-GNOME-Autostart-enabled / Hidden 的支持不一致,写了标记却被忽略等于开关失灵, // 删文件是唯一在各地都生效的做法(差异见回报)。 // 任何失败(含拿不到路径、平台不对)都抛出去,由调用方回滚配置,界面才不会说反。 function setAutostart({ platform = 'linux', env = process.env, exePath, enabled } = {}) { const file = resolveAutostartFile({ platform, env }) if (!file) { if (platform !== 'linux') throw new Error('开机自启在 Linux 上走 XDG 自启目录,本平台请用系统登录项') throw new Error('拿不到 $XDG_CONFIG_HOME 与 $HOME,无法写自启文件') } if (enabled !== true) { // force: 文件本来就不在(目录也不在)时不算失败 fs.rmSync(file, { force: true }) return { file } } if (typeof exePath !== 'string' || exePath === '') { throw new Error('拿不到 Console 自身的可执行文件路径,无法写自启文件') } fs.mkdirSync(path.dirname(file), { recursive: true }) fs.writeFileSync(file, desktopEntry(exePath), 'utf8') return { file } } module.exports = { AUTOSTART_FILE, resolveAutostartFile, isAutostartEnabled, setAutostart }