improvemets & fixes:
- added 'open with' handling to desktop shortcuts - move logs button to app configuration - fix sync progress disappearing after long hashing - fix sync double file counter - merge wine and proton prefix folders via symlink
This commit is contained in:
parent
8c6db38fab
commit
59ff0b1088
15 changed files with 520 additions and 113 deletions
|
|
@ -45,7 +45,6 @@ const ICONS = {
|
|||
folder: () => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>',
|
||||
trash: () => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 6h18M8 6V4h8v2M6 6l1 14h10l1-14M10 11v6M14 11v6"/></svg>',
|
||||
terminal: () => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17l6-5-6-5M12 19h8"/></svg>',
|
||||
logs: () => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 3h9l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zM9 12h6M9 16h6"/></svg>',
|
||||
star: () => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"><path d="M12 3l2.7 5.8 6.3.8-4.6 4.3 1.2 6.1-5.6-3.1-5.6 3.1 1.2-6.1L3 9.6l6.3-.8z"/></svg>',
|
||||
download: () => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12M6 9l6 6 6-6"/><path d="M4 21h16"/></svg>',
|
||||
chevronDown: () => '<svg class="chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>'
|
||||
|
|
@ -598,7 +597,6 @@ function renderLibrary() {
|
|||
<button class="button small danger" data-act="kill" style="display:none">${t('library.stop')}</button>
|
||||
<button class="button small" data-act="config" title="${t('library.config')}">${ICONS.config()}</button>
|
||||
<button class="button small" data-act="folder" title="${t('library.openFolder')}">${ICONS.folder()}</button>
|
||||
<button class="button small" data-act="logs" title="${t('library.viewLogs')}">${ICONS.logs()}</button>
|
||||
<button class="button small danger" data-act="remove" title="${t('library.remove')}">${ICONS.trash()}</button>
|
||||
</div>
|
||||
`
|
||||
|
|
@ -619,11 +617,6 @@ function renderLibrary() {
|
|||
}
|
||||
card.querySelector('[data-act=config]').onclick = () => openGameConfig(game.id)
|
||||
card.querySelector('[data-act=folder]').onclick = () => window.plwl.shellOpenPath(game.workdir)
|
||||
card.querySelector('[data-act=logs]').onclick = async () => {
|
||||
const logs = await window.plwl.gamesGetLogs(game.id)
|
||||
if (logs.length) window.plwl.shellShowItemInFolder(logs[logs.length - 1])
|
||||
else toast(t('library.viewLogs'))
|
||||
}
|
||||
card.querySelector('[data-act=remove]').onclick = async () => {
|
||||
const note = game.mode === 'copy' || game.mode === 'move'
|
||||
? t('library.removeFilesNote')
|
||||
|
|
@ -1250,6 +1243,16 @@ async function createAppShortcut() {
|
|||
}
|
||||
}
|
||||
|
||||
// Shows the newest run log in the file manager - it lives next to the app
|
||||
// configuration, where the user is when something needs debugging.
|
||||
async function showAppLogs() {
|
||||
const game = state.currentGame
|
||||
if (!game) return
|
||||
const logs = await window.plwl.gamesGetLogs(game.id)
|
||||
if (logs.length) window.plwl.shellShowItemInFolder(logs[logs.length - 1])
|
||||
else toast(t('config.noLogs'), 'error')
|
||||
}
|
||||
|
||||
function renderOverrides(overrides) {
|
||||
const box = qs('#gc-overrides')
|
||||
box.innerHTML = ''
|
||||
|
|
@ -1401,8 +1404,10 @@ const LAN_CATEGORIES = [
|
|||
{ id: 'apps-prefix', label: 'lansync.appsPrefix' },
|
||||
{ id: 'wines', label: 'lansync.wines' },
|
||||
{ id: 'prefixes', label: 'lansync.prefixes' },
|
||||
// opt-in: without it a sync never touches the other machine's defaults
|
||||
{ id: 'defaults', label: 'lansync.defaults' }
|
||||
// registry-level settings: default wine/prefix, custom names of wine builds
|
||||
// and prefixes, and each app's configuration plus its library order. No
|
||||
// files move with this category - it only patches what already exists.
|
||||
{ id: 'settings', label: 'lansync.settings' }
|
||||
]
|
||||
|
||||
// Byte sizes for the progress popups. Decimal units, the way a file manager
|
||||
|
|
@ -1742,7 +1747,11 @@ function onLanIncoming(info) {
|
|||
}
|
||||
|
||||
let receiving = false
|
||||
let receiveClosed = false
|
||||
// true only once the sender's 'done' event ended the transfer. A popup the
|
||||
// safety watchdog closed while the sender was still hashing must be allowed to
|
||||
// reopen when events resume - permanently closing it made a running sync
|
||||
// invisible even though the transfer continued.
|
||||
let receiveEnded = false
|
||||
let receiveWatchdog = null
|
||||
let receiveStall = null
|
||||
let receiveCloseTimer = null
|
||||
|
|
@ -1777,7 +1786,6 @@ function endReceiving(message) {
|
|||
}
|
||||
const wasReceiving = receiving
|
||||
receiving = false
|
||||
receiveClosed = true
|
||||
if (!wasReceiving) return
|
||||
if (message) toast(message, 'error')
|
||||
closeModal()
|
||||
|
|
@ -1801,13 +1809,14 @@ function armReceiveWatchdog() {
|
|||
function onLanReceiving(info) {
|
||||
if (!info || !info.stage) return
|
||||
if (state.lanPushing) return // our own push owns the (single) popup
|
||||
if (info.stage === 'start') receiveClosed = false
|
||||
if (info.stage === 'start') receiveEnded = false
|
||||
if (info.stage === 'done') receiveEnded = true
|
||||
if (!receiving) {
|
||||
// The popup also opens mid-sync: the sender may have been hashing for
|
||||
// minutes when this window starts listening, and a popup that the safety
|
||||
// timeout closed has to come back for the rest of the transfer. A sync
|
||||
// timeout closed comes back for the rest of the transfer. Only a sync
|
||||
// that already ended stays closed.
|
||||
if (receiveClosed && info.stage !== 'start') return
|
||||
if (receiveEnded) return
|
||||
if (qs('#modal-overlay').style.display !== 'none') return
|
||||
receiving = true
|
||||
const modal = showModal(`
|
||||
|
|
@ -1831,6 +1840,15 @@ function onLanReceiving(info) {
|
|||
function renderReceiving(info) {
|
||||
const parts = receiveModalParts()
|
||||
if (!parts) return
|
||||
// A liveness ping from the sender (it is busy hashing a unit): the watchdog
|
||||
// was re-armed by the caller, but what is on screen stays as it is - the
|
||||
// sync is not stalled, just quiet. The exception is the popup this very ping
|
||||
// just reopened (the safety timeout had closed it): every line would sit
|
||||
// blank, so the phase says what is actually happening.
|
||||
if (info.stage === 'wait') {
|
||||
if (!parts.phase.textContent) parts.phase.textContent = t('lansync.recvWaiting')
|
||||
return
|
||||
}
|
||||
// The same phases read from this side's point of view: a file arriving here
|
||||
// is being received, not sent.
|
||||
const phaseKey = RECV_PHASE_KEYS[info.stage] || 'lansync.phase.' + info.stage
|
||||
|
|
@ -1955,6 +1973,7 @@ function wireEvents() {
|
|||
qs('#btn-gc-back').addEventListener('click', () => showView('library'))
|
||||
qs('#btn-gc-save').addEventListener('click', saveGameConfig)
|
||||
qs('#btn-gc-shortcut').addEventListener('click', createAppShortcut)
|
||||
qs('#btn-gc-logs').addEventListener('click', showAppLogs)
|
||||
qs('#gc-override-add').addEventListener('click', addOverrideRow)
|
||||
qs('#gc-exe-browse').addEventListener('click', async () => {
|
||||
// start from the field being edited (exe picker from the exe field) and
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@
|
|||
|
||||
<div class="form-actions">
|
||||
<button class="button danger" id="btn-gc-clear-playtime" data-t="config.clearPlaytime"></button>
|
||||
<button class="button" id="btn-gc-logs" data-t="config.viewLogs"></button>
|
||||
<button class="button" id="btn-gc-shortcut" data-t="config.shortcut"></button>
|
||||
<button class="button primary" id="btn-gc-save" data-t="config.save"></button>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue