Commit Graph

422 Commits

Author SHA1 Message Date
Administrator
961d59f8b8 release: v2.9.7 2026-04-19 22:28:13 +02:00
Administrator
5c7bfb48b9 fix(vidmoly): probe /api/upload/config to verify login
The old /my HTML check failed because it couldn't distinguish an XFS
session from a full SPA session. Since /api/upload/config is what the
upload actually needs, probe it directly after login — 200 JSON with
sess_id/upload_url means we're good, anything else means we're out.
2026-04-19 22:27:49 +02:00
Administrator
d0c9df7656 release: v2.9.6 2026-04-19 22:24:33 +02:00
Administrator
0e7ae5ee7b fix(vidmoly): use new /api/upload/config endpoint
The Vidmoly SPA redesign removed the /?op=upload HTML form — the old
regex-scrape of hidden inputs no longer works. The site now exposes
GET /api/upload/config which returns { sess_id, upload_url } plus the
allowed extensions. Rewrote getUploadParams() to use that endpoint;
the rest of the multipart upload flow (sess_id + utype + file_0) is
the same classic XFS shape.
2026-04-19 22:24:10 +02:00
Administrator
8e49733241 release: v2.9.5 2026-04-19 22:11:06 +02:00
Administrator
a0eae7f380 release: v2.9.4 2026-04-19 22:09:29 +02:00
Administrator
bf39b6c180 release: v2.9.3 2026-04-19 22:08:50 +02:00
Administrator
2dc94084ab fix: vidmoly login verification + retry stale-uploadId + faster account toggle
Three fixes bundled:

  - Vidmoly redesign broke login: the old check required either the
    'login' or 'xfsts' cookie, but the new site sets different cookie
    names. Now we verify by fetching /?op=my_account and looking for
    logged-in markers (Logout / My Account / My Files) in the body
    instead of relying on specific cookie names.

  - retrySelectedJobs left the stale uploadId in _jobIndexByUploadId
    when resetting a job. A late 'aborted'/'error' event from the
    original (cancelled) upload could route back to the reset job
    and overwrite its 'preview' state. Now the old uploadId is
    removed from the index and marked in _deletedJobIds so those
    stragglers get dropped.

  - toggleAccount did two IPC round-trips (saveConfig + getConfig) on
    every enable/disable click, plus four re-renders (Accounts,
    HosterSummary, HosterModal, Settings). Rapid clicks felt laggy.
    The getConfig refetch is redundant since we mutated the flag in
    place, and HosterModal/Settings don't depend on account enabled
    state. Click now renders immediately and the save runs async.
2026-04-19 22:08:22 +02:00
Administrator
976be2f566 release: v2.9.2 2026-04-19 22:02:35 +02:00
Administrator
edf35e9636 release: v2.9.1 2026-04-19 22:01:47 +02:00
Administrator
880537dcfb fix: multi-level account rotation + clear failed-accounts per batch + size-sort staleness
Three state bugs found during audit:

  1. _failedAccounts / _accountOverrides survived across batches. A
     rate-limited account from batch 1 stayed permanently blacklisted
     for the rest of the app session, so batch 2 skipped straight to
     the fallback even after the original recovered. Now cleared in
     startBatch so each run evaluates accounts fresh.

  2. Account rotation was one level deep. With three accounts [A,B,C]
     on the same hoster and A + B both failing, the job errored out
     — C was never tried. The fallback-retry was a single if-block.
     Replaced with a while-loop that keeps asking main for the next
     override and rotating until every account is exhausted.

  3. Queue sort cache included 'size' as a static key, but bytesTotal
     goes 0 → actual when previews resolve. A queue sorted by size
     during preview would cache the all-zeros order and never update.
     Removed size from _STATIC_SORT_KEYS — it now re-sorts per render
     like status/speed/progress.
2026-04-19 22:01:20 +02:00
Administrator
5265bcd77a release: v2.9.0 2026-04-19 14:07:23 +02:00
Administrator
4f2d462754 perf: single-pass escapeHtml/escapeAttr
Hot path on large table rebuilds — every text cell runs through one
of these. Switching from 4 chained .replace() calls to a single regex
with a lookup map is ~3× faster. At 5000 rows × 4 fields per rebuild,
80k → 20k regex operations.
2026-04-19 14:06:52 +02:00
Administrator
b4c26f8106 release: v2.8.9 2026-04-19 14:02:59 +02:00
Administrator
2d8b3f1bf9 perf: final sweep — hot-path allocation, cached log target, sort-header skip
Last round of targeted wins:

  - upload-manager progress callback was allocating a fresh
    { jobId, speedKbs, bytesUploaded } object on every fs stream chunk
    (hundreds of times per second per active job). Now a single entry
    is created at job start and mutated in place — zero allocations
    on the steady-state progress tick.

  - upload-manager stats timer's two separate activeJobs.values()
    scans (globalSpeedKbs + inProgressBytes) merged into one pass.

  - clouddrop-upload.js reuses a single Buffer.allocUnsafe(chunkSize)
    across all chunks, taking subarray() only for the tail chunk.
    A 1 GB upload no longer allocates 64× 16 MB = 1 GB of short-lived
    buffers — real GC relief during many-file batches.

  - _resolveUploadLogTarget is now cached; the fallback ladder runs
    once per session (or when the user changes the log path / daily-log
    date rolls), not on every 500ms flush.

  - renderRecentUploadsPanel skips updateRecentSortHeaders on the
    append-only fast path — sort state hasn't changed, headers don't
    need recomputing.
2026-04-19 14:02:34 +02:00
Administrator
c73108afff release: v2.8.8 2026-04-19 13:56:02 +02:00
Administrator
f16dd9ffa6 perf: lazy history refresh + append-only recent panel + queue-cleanup merge
Three more targeted wins:

  - loadHistory() was called unconditionally on every handleBatchDone,
    doing an IPC roundtrip + full history-table rebuild even when the
    user is on the Upload tab and can't see it. Now it sets a dirty
    flag and the actual refresh is deferred until the user switches
    to the Verlauf tab. On a fresh tab click it always runs.

  - renderRecentUploadsPanel append-only fast path: when the sort is
    'date desc' (the default) and the dataset only grew, the panel
    inserts the new rows at the top via insertAdjacentHTML instead
    of rebuilding the 5000-row tbody from scratch. Length shrinks or
    sort-change still trigger a full rebuild.

  - handleBatchDone's removeFromQueueOnDone cleanup now does one pass
    (build keep-list + detach from index together) instead of two
    separate filter() scans over queueJobs.
2026-04-19 13:55:37 +02:00
Administrator
1bcd7a2078 release: v2.8.7 2026-04-19 13:39:02 +02:00
Administrator
879f6ade0e perf: O(1) lookups for selection buttons, applySummaryResults, file-drop dedup; batched upload log
Four more wins targeting batch-heavy paths:

  - updateQueueActionButtons replaced three O(n) queueJobs.some() scans
    with a single O(|selection|) pass over selectedJobIds, using the
    existing _jobIndexById map. Selection change cost on a 1000-job
    queue drops from ~3000 comparisons to |selection|.

  - applySummaryResults built a (fileName+hoster)→job Map once per call
    instead of running queueJobs.find() per result. Big batches
    (hundreds of files × multiple hosters) no longer scale O(n²).

  - addPathsToQueue and the folder-monitor auto-queue path built their
    dedup Set up front instead of running .find() per incoming path.
    Picking a folder with thousands of files now dedups in O(n+m)
    instead of O(n×m).

  - appendUploadLog became async + buffered like debugLog. A burst of
    20 files completing within a second becomes one fs.appendFile
    instead of 20 fs.appendFileSync that each blocked the main event
    loop. Fallback ladder (primary → Desktop → userData) is preserved;
    pending buffer flushes synchronously on before-quit.
2026-04-19 13:38:39 +02:00
Administrator
73e7190913 release: v2.8.6 2026-04-19 13:19:28 +02:00
Administrator
8f304f91d8 perf: buffered debug-log writer, scroll rAF-throttle, Set dedup for recent panel
Three more rounds of lag removal aimed at heavy upload sessions:

  - main-process debugLog() was doing fs.appendFileSync on every call
    and was firing hundreds of times per second during busy uploads
    (progress transitions, unhandled rejection traces, folder-monitor
    events). Replaced with an in-memory buffer flushed every 500ms via
    async appendFile — the main event loop is no longer blocked per
    line. Buffered entries flush synchronously on before-quit.

  - the renderer's 'RX upload-progress' / 'RX upload-stats' listeners
    were emitting one IPC roundtrip per event. For 20 concurrent jobs
    that's 80 IPC messages/sec just for logging. They now skip the
    debug call on the hot 'uploading' tick and only log transitions.

  - _onQueueScroll now coalesces scroll events via requestAnimationFrame
    so a fast trackpad fling triggers one virtual render per frame
    instead of one per wheel event.

  - maybeAddSessionFile switched from O(n) sessionFilesData.some() dedup
    to an O(1) Set lookup keyed on (link, filename, host). Adding 1000
    results to an already-populated panel drops from ~500ms to <5ms.
2026-04-19 13:19:04 +02:00
Administrator
ae46d90dc2 release: v2.8.5 2026-04-19 12:59:33 +02:00
Administrator
9158949480 perf: memoize queue sort, dedup stats scan per tick, skip no-op DOM writes
Three more wins on top of the previous pass:
  - sortQueueJobs memoizes the result for static sort keys
    (filename, host, size) — these don't change during upload, so
    every 200ms progress render now reuses the same sorted array
    instead of running an O(n log n) Collator compare.
  - _computeQueueStats caches within a single tick via queueMicrotask.
    updateStatusBar + updateStatsPanel are always called back-to-back
    and now share one queue scan instead of running two.
  - _updateRowInPlace writes DOM values only when they actually
    changed. Idle/queued/done rows (the majority) incur zero DOM
    mutations per progress tick.
2026-04-19 12:59:10 +02:00
Administrator
571d507889 release: v2.8.4 2026-04-19 12:27:46 +02:00
Administrator
85287aa620 perf: kill lag with 1000s of rows during upload
The two worst hot paths were:
  - clicking a row triggered a full table rebuild with sort+innerHTML
    (queue AND recent panel), and the opposite panel got cleared with
    another full rebuild
  - every upload progress tick (4/sec) scanned queueJobs twice and
    filtered sessionFilesData twice just to update the status bar

Fixes:
  - applyQueueSelectionClasses / applyRecentSelectionClasses toggle the
    .selected class on existing rows instead of rebuilding the tbody.
    Click selection is now O(rendered rows) instead of O(total × sort).
  - maybeAddSessionFile schedules renderRecentUploadsPanel via rAF so
    a batch of 1000 successful uploads coalesces into one render.
  - sortRecentFiles memoizes its result per (sortKey, direction, len)
    — unchanged sort state + unchanged length returns the cached array
    instead of re-sorting thousands of entries.
  - _computeQueueStats now also returns inProgressBytes, dropping the
    second queueJobs scan in updateStatusBar.
  - session done/error counts are maintained incrementally, replacing
    two sessionFilesData.filter().length calls every status-bar tick.
  - handleRowClick uses the _jobIndexById map instead of Array.find.
2026-04-19 12:27:16 +02:00
Administrator
7dc68c7615 release: v2.8.3 2026-04-19 11:54:26 +02:00
Administrator
60ceea41d7 fix: encrypt hoster credentials at rest; history CSV Link column urls-only
Two issues:
1. Verlauf-Export CSV put the opaque file_code in the Link column when
   the upload had no real URL, so the column looked like just a bunch
   of IDs. Now only real http(s) URLs land in that column.
2. Hoster passwords and API keys were stored as plaintext in
   electron-config.json. Now wrapped with Electron's safeStorage (DPAPI
   on Windows, Keychain on macOS, libsecret on Linux) and stored as
   'enc:v1:<base64>'.

Credentials are decrypted on load so in-memory flows stay unchanged,
and backups still export plaintext inside the existing .mhu envelope
so they remain portable between machines/users. Legacy plaintext
configs auto-migrate on next write.
2026-04-19 11:53:59 +02:00
Administrator
b80ca7238d release: v2.8.2 2026-04-19 11:47:17 +02:00
Administrator
415162e058 fix(log): fall back to user's Desktop before AppData, keep daily-log naming
If the configured log path (or the default exe-adjacent path) isn't
writable, we now try the current user's Desktop first — that's where
users actually look — and only fall back to AppData if Desktop is
also unavailable. The daily-log filename suffix is preserved on the
fallback file so the format stays consistent.
2026-04-19 11:46:50 +02:00
Administrator
fdac28040d release: v2.8.1 2026-04-19 11:43:00 +02:00
Administrator
3472f4e1ed fix(import): strip machine-specific paths when importing backup
A backup made on 'Server A' carries absolute paths (logFilePath,
folderMonitor.folderPath, pendingQueue file paths) that do not exist
on 'Server B' — leading to silent log-write failures, folder-monitor
start errors on missing directories, and queue jobs pointing at
non-existent files.

On import, now:
  - clear logFilePath if its parent directory doesn't exist here
  - clear folderMonitor.folderPath + disable it if the directory is missing
  - clear pendingQueue (queue state is inherently per-machine)

Also harden startup: folder-monitor auto-start now verifies the path
exists and persists enabled=false if not, so one missing-path launch
doesn't keep retrying forever.
2026-04-19 11:42:33 +02:00
Administrator
62a459353a release: v2.8.0 2026-04-19 11:36:09 +02:00
Administrator
9a7354fc55 feat(recent): export all recent uploads (name+link+hoster+time)
Adds an 'Exportieren' button next to 'Alle entfernen' that writes a
pipe-delimited log of every row currently shown in the recent-uploads
panel — so session data doesn't get lost if the log file path is wrong.

Also fixes appendUploadLog silently failing: if the configured path is
unwritable (e.g. C:/Users/<nonexistent>/...), entries now go to
<userData>/fileuploader-fallback.log and the renderer warns once.
2026-04-19 11:35:41 +02:00
Administrator
299fa8a4e5 release: v2.7.9 2026-04-17 16:55:18 +02:00
Administrator
161357522e fix(backup): don't pass click event as legacy password
addEventListener('click', doBackupImport) was passing the MouseEvent
as the first argument, which got forwarded to pbkdf2 as an Object.
2026-04-17 16:54:53 +02:00
Administrator
e3c8ccdca4 release: v2.7.8 2026-04-17 11:23:01 +02:00
Administrator
edb614f985 feat(backup): import legacy password-encrypted backups
Try app-internal key first (new format); on failure, signal the
renderer to prompt for the old password and retry. Lets users import
.mhu files that were exported with a custom password in v2.7.6 or
earlier without downgrading.
2026-04-17 11:22:33 +02:00
Administrator
90c7fe297d release: v2.7.7 2026-04-17 11:17:53 +02:00
Administrator
3e9483e222 feat(backup): drop password prompt on export/import
File stays AES-GCM encrypted with a fixed app-internal key — opaque
without the app, which is the only protection we actually need for
locally-stored API keys. Removes the modal and both password dialogs.
2026-04-17 11:17:21 +02:00
Administrator
43433cbc00 release: v2.7.6 2026-04-11 15:09:43 +02:00
Administrator
6780cf3261 fix(clouddrop): route chunk PUTs via upload.clouddrop.cc (bypass CF)
Only the 16 MB chunk stream needs the upload subdomain; init and
complete are tiny and can stay on the main host.
2026-04-11 15:09:13 +02:00
Administrator
0bf3061852 release: v2.7.5 2026-04-11 07:31:11 +02:00
Administrator
79cf8ad002 fix(clouddrop): never throw after all chunks uploaded
/upload/complete was failing (non-JSON response, missing fileId, or
post-processing timeout) after all bytes were already on the server,
causing upload-manager to retry the entire multi-GB upload — which
corrupts the server-side file since two uploads end up interleaved.

Now /complete failures are swallowed and sessionId is used as the
file_code fallback. Upload is considered done once all chunks are in.
2026-04-11 07:30:39 +02:00
Administrator
215a10186e release: v2.7.4 2026-04-11 07:25:50 +02:00
Administrator
f955064524 fix(clouddrop): only upload, skip share-link generation entirely 2026-04-11 07:25:23 +02:00
Administrator
c6c59ce868 release: v2.7.3 2026-04-11 07:18:13 +02:00
Administrator
cba69a7806 fix(clouddrop): retry share-link during post-processing, never fail upload
Upload completes on server but file is still being processed, so
share-link fails. Retry up to 6x with backoff; on final failure, use
fileId-based fallback URL instead of throwing — prevents upload-manager
from retrying the entire multi-GB upload.
2026-04-11 07:17:45 +02:00
Administrator
bc32f4dc95 release: v2.7.2 2026-04-11 07:14:57 +02:00
Administrator
7db08a6ab3 fix(clouddrop): trailing slash on /files endpoint to avoid 301 2026-04-11 07:14:30 +02:00
Administrator
237da99523 release: v2.7.1 2026-04-11 07:12:55 +02:00