diff --git a/electron-main.js b/electron-main.js index b0c38ab..4a65f9c 100644 --- a/electron-main.js +++ b/electron-main.js @@ -111,7 +111,8 @@ async function executeAction(action) { const stealsFocus = ['keystroke', 'copy', 'paste', 'cut'].includes(type); if (stealsFocus) { app.hide(); - await sleep(80); + // Várjuk meg, amíg tényleg az előző app kapja vissza a fókuszt + await waitForAppFocus(); } try { @@ -135,9 +136,15 @@ async function executeAction(action) { /* ─── Clipboard: copy ──────────────────────────────────────────────── */ case 'copy': { - await execPromise(`osascript -e 'tell application "System Events" to keystroke "c" using command down'`); - await sleep(100); - const text = clipboard.readText(); + // Többször próbálkozunk, mert néha a fókuszváltás + billentyűzés nem elég gyors + let text = ''; + for (let attempt = 0; attempt < 3; attempt++) { + await execPromise(`osascript -e 'tell application "System Events" to keystroke "c" using command down'`); + await sleep(120); + text = clipboard.readText(); + if (text) break; + await sleep(50); + } console.log(`Copied: "${text.substring(0, 80)}..."`); if (mainWindow && !mainWindow.isDestroyed()) { mainWindow.webContents.send('clipboard-result', { action: 'copy', text }); @@ -147,18 +154,35 @@ async function executeAction(action) { /* ─── Clipboard: paste ─────────────────────────────────────────────── */ case 'paste': { - const stored = value || clipboard.readText(); - clipboard.writeText(stored); - await execPromise(`osascript -e 'tell application "System Events" to keystroke "v" using command down'`); + // Ha value meg van adva, azt illesztjük be (és utána visszaállítjuk a régit) + if (value) { + const prevClip = clipboard.readText(); + clipboard.writeText(value); + await execPromise(`osascript -e 'tell application "System Events" to keystroke "v" using command down'`); + await sleep(150); + // Visszaállítjuk az eredeti vágólap tartalmat + // (kis késleltetéssel, hogy a cél app befejezze a fogadást) + clipboard.writeText(prevClip); + } else { + // Nincs value – simán illesszük be, ami a vágólapon van + await execPromise(`osascript -e 'tell application "System Events" to keystroke "v" using command down'`); + } break; } /* ─── Clipboard: cut ───────────────────────────────────────────────── */ case 'cut': { - await execPromise(`osascript -e 'tell application "System Events" to keystroke "x" using command down'`); - await sleep(100); + let text = ''; + for (let attempt = 0; attempt < 3; attempt++) { + await execPromise(`osascript -e 'tell application "System Events" to keystroke "x" using command down'`); + await sleep(120); + text = clipboard.readText(); + if (text) break; + await sleep(50); + } + console.log(`Cut: "${text.substring(0, 80)}..."`); if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('clipboard-result', { action: 'cut', text: clipboard.readText() }); + mainWindow.webContents.send('clipboard-result', { action: 'cut', text }); } break; } @@ -214,7 +238,8 @@ async function executeAction(action) { // Visszahozzuk az ablakot if (stealsFocus) { - await sleep(50); + // Várjunk egy kicsit, hogy a cél app megkapja a billentyűzet parancsot + await sleep(150); app.show(); if (mainWindow && !mainWindow.isDestroyed()) { mainWindow.show(); @@ -376,6 +401,33 @@ function execPromise(cmd) { function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } +/** + * Várunk amíg az aktuális fókusz átvált a StreamDeck-ről az előző app-ra. + * app.hide() után pollozzuk a frontmost app-ot, max 500ms-ig. + */ +async function waitForAppFocus() { + const maxWait = 800; // max 800ms + const interval = 40; // 40ms-ként ellenőrizzük + let waited = 0; + while (waited < maxWait) { + try { + const frontApp = execSync( + `osascript -e 'tell application "System Events" to get name of first process whose frontmost is true' 2>/dev/null`, + { timeout: 500, encoding: 'utf-8' } + ).trim(); + // Ha már nem a StreamDeck az aktív app, kész + if (frontApp && frontApp !== 'StreamDeck') { + return; + } + } catch (e) { + // Ha hiba van, próbáljuk tovább + } + await sleep(interval); + waited += interval; + } + // Timeout után is folytatjuk – hátha működik +} + function parseKeystroke(str) { if (!str) return null; const parts = str.toLowerCase().split('+'); diff --git a/public/app.js b/public/app.js index 19165ae..9fdb010 100644 --- a/public/app.js +++ b/public/app.js @@ -446,6 +446,33 @@ document.addEventListener('keydown', (e) => { if (e.key === 'ArrowLeft' && currentPage > 0) renderPage(currentPage - 1); }); +/* ─── Clipboard result toast ────────────────────────────────────────────── */ +const toastEl = document.getElementById('toast'); +let toastTimer = null; + +function showToast(msg, duration) { + duration = duration || 2000; + if (!toastEl) return; + toastEl.textContent = msg; + toastEl.style.display = 'block'; + if (toastTimer) clearTimeout(toastTimer); + toastTimer = setTimeout(() => { + toastEl.style.display = 'none'; + }, duration); +} + +if (IS_ELECTRON) { + window.electronAPI.onClipboardResult((data) => { + if (data.action === 'copy' && data.text) { + const short = data.text.length > 60 ? data.text.substring(0, 57) + '…' : data.text; + showToast(`Copied: "${short}"`, 2500); + } else if (data.action === 'cut' && data.text) { + const short = data.text.length > 60 ? data.text.substring(0, 57) + '…' : data.text; + showToast(`Cut: "${short}"`, 2500); + } + }); +} + /* ─── Document-level event logger (for troubleshooting touch) ──────────── */ function docLog(e) { window.debugLog(`📄 ${e.type}`, `target:${e.target?.tagName} pt:${e.pointerType || '-'} btn:${e.which || e.button || 0}`); diff --git a/public/index.html b/public/index.html index 4023bcc..d9cc174 100644 --- a/public/index.html +++ b/public/index.html @@ -31,6 +31,7 @@
+