mirror of
https://github.com/YuzuZensai/Discord-Presence-Relay.git
synced 2026-09-13 17:01:36 +00:00
180 lines
4.4 KiB
TypeScript
180 lines
4.4 KiB
TypeScript
import { app, shell, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'electron'
|
|||
|
|
import { join } from 'path'
|
||
|
|
import * as fs from 'fs'
|
||
|
|
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||
|
|
import icon from '../../resources/icon.png?asset'
|
||
|
|
import { relay, RelayStatus } from './relay'
|
||
|
|
|
||
|
|
function settingsPath(): string {
|
||
|
|
return join(app.getPath('userData'), 'settings.json')
|
||
|
|
}
|
||
|
|
|
||
|
|
function loadDisabledMirrors(): number[] {
|
||
|
|
try {
|
||
|
|
const raw = fs.readFileSync(settingsPath(), 'utf8')
|
||
|
|
const data = JSON.parse(raw)
|
||
|
|
return Array.isArray(data?.disabledMirrors) ? data.disabledMirrors : []
|
||
|
|
} catch {
|
||
|
|
return []
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function saveDisabledMirrors(indices: number[]): void {
|
||
|
|
fs.writeFileSync(settingsPath(), JSON.stringify({ disabledMirrors: indices }), 'utf8')
|
||
|
|
}
|
||
|
|
|
||
|
|
let mainWindow: BrowserWindow | null = null
|
||
|
|
let tray: Tray | null = null
|
||
|
|
let quitting = false
|
||
|
|
|
||
|
|
function createWindow(): void {
|
||
|
|
if (mainWindow) {
|
||
|
|
mainWindow.show()
|
||
|
|
mainWindow.focus()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
mainWindow = new BrowserWindow({
|
||
|
|
width: 420,
|
||
|
|
height: 760,
|
||
|
|
show: false,
|
||
|
|
autoHideMenuBar: true,
|
||
|
|
resizable: true,
|
||
|
|
...(process.platform === 'linux' ? { icon } : {}),
|
||
|
|
webPreferences: {
|
||
|
|
preload: join(__dirname, '../preload/index.js'),
|
||
|
|
sandbox: false
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
mainWindow.on('ready-to-show', () => {
|
||
|
|
mainWindow?.show()
|
||
|
|
})
|
||
|
|
|
||
|
|
mainWindow.on('close', (e) => {
|
||
|
|
if (!quitting) {
|
||
|
|
e.preventDefault()
|
||
|
|
mainWindow?.destroy()
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
mainWindow.on('closed', () => {
|
||
|
|
mainWindow = null
|
||
|
|
})
|
||
|
|
|
||
|
|
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||
|
|
shell.openExternal(details.url)
|
||
|
|
return { action: 'deny' }
|
||
|
|
})
|
||
|
|
|
||
|
|
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||
|
|
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
||
|
|
} else {
|
||
|
|
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function createTray(): void {
|
||
|
|
const trayIcon = nativeImage.createFromPath(icon).resize({ width: 24, height: 24 })
|
||
|
|
tray = new Tray(trayIcon)
|
||
|
|
tray.setToolTip('Discord RPC Relay')
|
||
|
|
|
||
|
|
updateTrayMenu(relay.getStatus())
|
||
|
|
|
||
|
|
tray.on('click', () => {
|
||
|
|
createWindow()
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
function updateTrayMenu(status: RelayStatus): void {
|
||
|
|
if (!tray) return
|
||
|
|
|
||
|
|
const menu = Menu.buildFromTemplate([
|
||
|
|
{
|
||
|
|
label: status.running ? 'Relay: Running' : 'Relay: Stopped',
|
||
|
|
enabled: false
|
||
|
|
},
|
||
|
|
{ type: 'separator' },
|
||
|
|
{
|
||
|
|
label: status.running ? 'Stop Relay' : 'Start Relay',
|
||
|
|
click: async () => {
|
||
|
|
try {
|
||
|
|
if (status.running) {
|
||
|
|
await relay.stop()
|
||
|
|
} else {
|
||
|
|
await relay.start()
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
console.error(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
label: 'Show Window',
|
||
|
|
click: () => createWindow()
|
||
|
|
},
|
||
|
|
{ type: 'separator' },
|
||
|
|
{
|
||
|
|
label: 'Quit',
|
||
|
|
click: () => {
|
||
|
|
quitting = true
|
||
|
|
app.quit()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
])
|
||
|
|
|
||
|
|
tray.setContextMenu(menu)
|
||
|
|
}
|
||
|
|
|
||
|
|
app.whenReady().then(() => {
|
||
|
|
electronApp.setAppUserModelId('cafe.kirameki.discord-rpc-relay')
|
||
|
|
|
||
|
|
app.on('browser-window-created', (_, window) => {
|
||
|
|
optimizer.watchWindowShortcuts(window)
|
||
|
|
})
|
||
|
|
|
||
|
|
relay.setDisabledMirrors(loadDisabledMirrors())
|
||
|
|
|
||
|
|
ipcMain.handle('relay:get-status', () => relay.getStatus())
|
||
|
|
ipcMain.handle('relay:start', () => relay.start())
|
||
|
|
ipcMain.handle('relay:stop', () => relay.stop())
|
||
|
|
ipcMain.handle('relay:get-autostart', () => app.getLoginItemSettings().openAtLogin)
|
||
|
|
ipcMain.handle('relay:set-autostart', (_e, enabled: boolean) => {
|
||
|
|
app.setLoginItemSettings({ openAtLogin: enabled })
|
||
|
|
return app.getLoginItemSettings().openAtLogin
|
||
|
|
})
|
||
|
|
ipcMain.handle('relay:set-mirror-enabled', (_e, index: number, enabled: boolean) => {
|
||
|
|
const status = relay.setMirrorEnabled(index, enabled)
|
||
|
|
saveDisabledMirrors(relay.getDisabledMirrors())
|
||
|
|
return status
|
||
|
|
})
|
||
|
|
|
||
|
|
relay.on('status', (status: RelayStatus) => {
|
||
|
|
updateTrayMenu(status)
|
||
|
|
mainWindow?.webContents.send('relay:status', status)
|
||
|
|
})
|
||
|
|
|
||
|
|
createTray()
|
||
|
|
createWindow()
|
||
|
|
|
||
|
|
relay.start().catch((err) => console.error('Failed to start relay:', err))
|
||
|
|
|
||
|
|
app.on('activate', function () {
|
||
|
|
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
app.on('window-all-closed', () => {
|
||
|
|
// Keep running in the tray
|
||
|
|
})
|
||
|
|
|
||
|
|
let stopping = false
|
||
|
|
|
||
|
|
app.on('before-quit', (e) => {
|
||
|
|
quitting = true
|
||
|
|
if (stopping) return
|
||
|
|
stopping = true
|
||
|
|
e.preventDefault()
|
||
|
|
relay.stop().finally(() => app.exit(0))
|
||
|
|
})
|