fixes:
- make prefix imported games paths relative to prefix - show placeholder icon as fallback - fix crossed working/exe directories - fix broken working dir in prefix imported games
This commit is contained in:
parent
b83e530392
commit
66f42f30cc
8 changed files with 74 additions and 10 deletions
|
|
@ -5,7 +5,7 @@ const path = require('path')
|
|||
const { DIRS, resolvePortablePath } = require('./paths')
|
||||
const { newGame, newGameId, addGame } = require('./library')
|
||||
const { extractIconFromExe } = require('./icons')
|
||||
const { prefixPath } = require('./prefixes')
|
||||
const { listPrefixes, prefixDriveRoot } = require('./prefixes')
|
||||
|
||||
// Directories that typically hold installers/redistributables, not the game.
|
||||
const SKIPPED_DIRS = new Set(['redist', 'directx', '_commonredist', 'support', 'dotnet', 'vc'])
|
||||
|
|
@ -68,12 +68,11 @@ async function importGame(srcDir, mode, onProgress) {
|
|||
// prefix, so wine sees the app exactly as if it had been installed
|
||||
// normally into C:\...
|
||||
async function importGameFromPrefix(prefix, srcDir, onProgress) {
|
||||
const prefixes = require('./prefixes')
|
||||
if (!prefixes.listPrefixes().prefixes.some(p => p.name === prefix)) return { ok: false, error: 'prefix-not-found' }
|
||||
if (!listPrefixes().prefixes.some(p => p.name === prefix)) return { ok: false, error: 'prefix-not-found' }
|
||||
// the folder must live inside the prefix's C: drive so the C:\ mapping
|
||||
// holds - drive_c sits at the prefix top for plain wine, under pfx/ for
|
||||
// Proton-managed prefixes
|
||||
const driveRoot = prefixes.prefixDriveRoot(prefix)
|
||||
const driveRoot = prefixDriveRoot(prefix)
|
||||
if (!driveRoot) return { ok: false, error: 'no-drive-c' }
|
||||
const rel = path.relative(driveRoot, srcDir)
|
||||
if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) return { ok: false, error: 'outside-drive-c' }
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ function registerIpc({ getWindow, onGamesChanged }) {
|
|||
// games: library -----------------------------------------------------------------
|
||||
ipcMain.handle('games:list', () => library.loadGames())
|
||||
ipcMain.handle('games:get', (e, id) => library.getGame(id))
|
||||
// prefix pin is enforced inside library.updateGame (prefix/importSource
|
||||
// fields are ignored for prefix imports), so nothing extra needed here
|
||||
ipcMain.handle('games:update', (e, id, patch) => library.updateGame(id, patch))
|
||||
ipcMain.handle('games:remove', (e, id) => {
|
||||
shortcuts.removeShortcut(id)
|
||||
|
|
@ -204,7 +206,15 @@ function registerIpc({ getWindow, onGamesChanged }) {
|
|||
|
||||
// dialogs & shell ---------------------------------------------------------------------------
|
||||
ipcMain.handle('dialog:pickFile', async (e, opts) => {
|
||||
const res = await dialog.showOpenDialog(getWindow(), { properties: ['openFile', 'openDirectory'], ...(opts || {}) })
|
||||
const o = { ...(opts || {}) }
|
||||
// Electron resolves a RELATIVE defaultPath against the process cwd (the
|
||||
// install root in packaged mode), which lands the picker somewhere
|
||||
// random like '/'. Renderer paths are FILES-relative by convention, so
|
||||
// anchor them there instead.
|
||||
if (o.defaultPath && typeof o.defaultPath === 'string' && !path.isAbsolute(o.defaultPath)) {
|
||||
o.defaultPath = path.join(DIRS.FILES, o.defaultPath)
|
||||
}
|
||||
const res = await dialog.showOpenDialog(getWindow(), { properties: ['openFile', 'openDirectory'], ...o })
|
||||
return res.canceled || !res.filePaths[0] ? null : res.filePaths[0]
|
||||
})
|
||||
ipcMain.handle('shell:openPath', (e, p) => shell.openPath(p))
|
||||
|
|
|
|||
|
|
@ -93,6 +93,14 @@ function updateGame(id, patch) {
|
|||
const games = loadGames()
|
||||
const g = games.find(x => x.id === id)
|
||||
if (!g) return null
|
||||
// prefix imports are pinned: their paths are stored relative to their
|
||||
// prefix, so NOTHING may move them to another prefix or flip their
|
||||
// import source (the patch fields are simply ignored)
|
||||
if (g.importSource === 'prefix' && patch) {
|
||||
patch = { ...patch }
|
||||
delete patch.prefix
|
||||
delete patch.importSource
|
||||
}
|
||||
// playSeconds goes to its own tiny file; the registry just mirrors it for
|
||||
// anything reading apps.json directly (loadGames prefers the file anyway).
|
||||
if (patch.playSeconds !== undefined) writePlaySeconds(id, patch.playSeconds)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue