- scaleParallelUploads used Math.max instead of Math.min, causing MORE
concurrent uploads instead of limiting them to the global count
- Settings debounce (350ms) was not flushed on app close — user changes
made right before closing were lost
- onRemoteClientCount IPC listener was re-registered on every
renderSettings() call, causing listener accumulation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 30-second timeout to health check wait loop in startUpload/
startSelectedUpload to prevent infinite spin if healthCheckRunning
gets stuck
- Clear _deletedJobIds Set when batch completes to prevent unbounded
memory growth over long sessions with many deletions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rebuild _jobIndexById after restoring queue from config on startup
(prevented progress updates from finding restored jobs)
- Show and focus mainWindow when files are dropped on floating
drop-target while window is minimized/hidden
- Escape status text in queue table HTML to prevent XSS from
unexpected status values
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Folder monitor: clear _seenFiles entry on file unlink so re-added
files (e.g. re-encoded) are detected again
- Sync IPC save (beforeunload): use atomic write pattern with backup
(.bak) creation, matching the async _atomicWrite behavior
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical: handleShutdownAfterFinish() captured shutdown mode in a
closure at scheduling time — changing mode during countdown was ignored,
causing unexpected system shutdown/restart/sleep.
Now reads shutdownMode at execution time, clears timer when mode
changes to 'nothing', clears orphaned timers before creating new ones,
and adds error handling on exec() calls.
Also: guard stats timer against double-start in upload-manager.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- batch-done handler: appendHistory failure no longer prevents the
upload-batch-done event from reaching the renderer (UI would get stuck)
- remote:input-event: validate x/y as finite numbers before passing
to sendInputEvent (prevents NaN/Infinity crash)
- VOE upload server: wrap JSON.parse in try-catch with clear error
message instead of raw stack trace
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Upload manager now rejects empty files (0 bytes) with clear error
message instead of sending useless uploads to the server
- Fix drag-drop zone highlight flickering caused by dragleave firing
on child elements (classic browser bug, fixed with enter/leave counter)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The error handler was missing clearTimeout for the auth timeout timer
and didn't clean up authenticated client state (signaling disconnect,
destroying capture window when last client drops).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Upload button no longer gets permanently stuck if startUpload()
throws after health check (try-catch with uploading=false reset)
- Wait for running health check instead of silently blocking upload
- Add abort signal check in VOE/Vidmoly upload generators
- Escape filenames with quotes/backslashes in multipart form headers
(all 4 uploaders: doodstream, voe, vidmoly, byse)
- Validate backup import structure before overwriting config
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Config write serialization via _writeQueue prevents concurrent
read-modify-write races between settings/queue/history saves
- Cancel active uploads on app quit (prevents zombie processes)
- Persist queue before update install (prevents queue loss)
- Sync IPC save in beforeunload (guarantees save before close)
- Fix double configStore.load() call
- Guard against status regression in handleProgress (done→uploading)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Right-click on queue now shows a "Hoster entfernen ▸" submenu listing
all hosters with job count (e.g. "Vidmoly (3)"). Clicking removes all
jobs for that hoster, cancels active uploads, and saves immediately.
Also fixes submenu viewport flip measurement (was reading offsetWidth
on display:none elements).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three root causes fixed:
- handleProgress() re-created deleted jobs from stale progress callbacks
- Queue save was debounced (10s during uploads), deletion lost on app close
- Delete was blocked during active uploads (removed !uploading guard)
Now: deletions save immediately, deleted IDs are tracked to prevent
re-creation, and active uploads are cancelled when their jobs are deleted.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When Doodstream requires 2FA, the account modal now dynamically
shows an OTP input field so the user can enter the code from
their email and complete the login without restarting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Windows 10/11 getBounds() includes ~7px invisible resize borders that
are not included in the window capture, causing click offset.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove restrictive resolution constraints, capture at native res
- Account for window frame/title bar when mapping click coordinates
(capture includes title bar but sendInputEvent is content-relative)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of enumerating all sources and matching by title (which falls
back to full screen capture), use BrowserWindow.getMediaSourceId() to
get the exact media source ID for the app window.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
If getCaptureStream fails, send error back through WebSocket so it
appears in proxy logs for diagnosis.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Capture window logs now forwarded to main process via IPC to diagnose
why video tracks are missing from the WebRTC answer SDP.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
RTCSessionDescription and RTCIceCandidate objects lose their properties
when sent through Electron's contextBridge IPC. Convert to plain objects
with explicit property extraction before sending.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- desktopCapturer now searches window+screen types with fallbacks
- Partial title match and screen fallback if exact match fails
- Error messages sent back from capture window via IPC
- Detailed logging for capture source selection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The capture window creation is async but the browser's WebRTC offer
arrives immediately after auth. Messages were silently dropped during
window initialization, preventing video stream from establishing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move `uploading = true` guard to immediately after the check in both
startUpload() and startSelectedUpload(), before any async calls.
Previously the flag was set after await executeHealthCheck(), allowing
a fast double-click to bypass the guard and start duplicate batches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Track completed uploads in _completedUploadKeys Set so buildQueuePreview
won't re-create jobs for files already uploaded this session
- Deduplicate queue on restore: when loading pendingQueue, keep only the
job with the best status per file+hoster pair (removes existing dupes)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The in-place update path for virtual scrolling would silently skip the
full DOM rebuild when row IDs didn't match due to sort order changes.
The break statement only exited the for-loop but return still fired,
preventing any update. Now tracks allMatch flag and falls through to
innerHTML rebuild when needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>