add app and apps icons

This commit is contained in:
olcxja 2026-09-25 18:42:03 +02:00
commit 7508811374
16 changed files with 554 additions and 7 deletions

View file

@ -1,7 +1,8 @@
'use strict'
const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron')
const { app, BrowserWindow, ipcMain, dialog, shell, protocol, net } = require('electron')
const path = require('path')
const fs = require('fs')
const { ensureDirs, DIRS, readJson, writeJson } = require('./paths')
const wines = require('./wines')
const prefixes = require('./prefixes')
@ -109,6 +110,70 @@ ipcMain.handle('games:list', () => library.loadGames())
ipcMain.handle('games:remove', (e, id) => library.removeGame(id))
ipcMain.handle('games:get', (e, id) => library.getGame(id))
ipcMain.handle('games:update', (e, id, patch) => library.updateGame(id, patch))
ipcMain.handle('games:clearPlaytime', (e, id) => library.updateGame(id, { playSeconds: 0, lastPlayed: 0 }))
ipcMain.handle('games:resetIcon', (e, id) => {
const game = library.getGame(id)
if (!game) return { ok: false }
for (const f of ['icon.png', 'icon.ico']) {
try {
fs.unlinkSync(path.join(DIRS.DATA, 'icons', id, f))
} catch {}
}
library.updateGame(id, { iconSource: 'none' })
return { ok: true }
})
ipcMain.handle('games:setIconFile', async (e, id, filePath) => {
const game = library.getGame(id)
if (!game || !filePath) return { ok: false, error: 'bad-request' }
try {
const dir = path.join(DIRS.DATA, 'icons', id)
fs.mkdirSync(dir, { recursive: true })
for (const f of fs.readdirSync(dir)) {
if (f.startsWith('icon.')) fs.unlinkSync(path.join(dir, f))
}
const icon = require('./icons')
let dst
if (filePath.toLowerCase().endsWith('.exe')) {
dst = path.join(dir, 'icon.ico')
const res = icon.extractIconFromExe(filePath, dst)
if (!res.ok) return res
} else {
dst = path.join(dir, `icon${path.extname(filePath).toLowerCase() || '.png'}`)
fs.copyFileSync(filePath, dst)
}
library.updateGame(id, { iconSource: dst })
return { ok: true, path: dst }
} catch (err) {
return { ok: false, error: String(err && err.message || err) }
}
})
ipcMain.handle('games:extractIcon', (e, id) => {
const game = library.getGame(id)
if (!game || !game.exePath) return { ok: false, error: 'bad-request' }
const out = path.join(DIRS.DATA, 'icons', id, 'icon.ico')
const res = require('./icons').extractIconFromExe(game.exePath, out)
if (res.ok) library.updateGame(id, { iconSource: out })
return res
})
ipcMain.handle('games:autoIcon', (e, id) => {
const game = library.getGame(id)
if (!game || !game.exePath) return { ok: false, error: 'bad-request' }
const dir = path.join(DIRS.DATA, 'icons', id)
try {
for (const f of fs.readdirSync(dir)) {
if (f.startsWith('icon.')) fs.unlinkSync(path.join(dir, f))
}
} catch {}
const out = path.join(dir, 'icon.ico')
const res = require('./icons').extractIconFromExe(game.exePath, out)
if (res.ok) library.updateGame(id, { iconSource: out })
return res
})
ipcMain.handle('games:iconPath', (e, id) => {
const game = library.getGame(id)
if (!game || !game.iconSource) return null
return fs.existsSync(game.iconSource) ? game.iconSource : null
})
ipcMain.handle('games:pickFolder', async e => {
const res = await dialog.showOpenDialog(win, {
@ -238,6 +303,24 @@ ipcMain.handle('games:isRunning', (e, id) => running.has(id))
ipcMain.handle('games:listRunning', () => [...running.keys()])
app.whenReady().then(async () => {
if (process.platform === 'linux') {
const { setAppIcon } = require('./appicon')
try {
setAppIcon(app)
} catch {}
}
protocol.handle('plgl-icon', request => {
const id = decodeURIComponent(new URL(request.url).hostname)
const dir = path.join(DIRS.DATA, 'icons', id)
let file = null
try {
const files = fs.readdirSync(dir).filter(f => f.startsWith('icon.')).sort()
const pick = files.find(f => /^icon\.(png|jpe?g|svg|ico|webp|gif|bmp)$/i.test(f))
if (pick) file = path.join(dir, pick)
} catch {}
if (!file) return new Response('', { status: 404 })
return net.fetch('file://' + file)
})
ensureDirs()
await i18n.init()
await wines.refreshWines()