Avatar for the mpiton user
mpiton
vortex
BlogDocsChangelog

Performance History

Latest Results

chore(npm): allow .npmrc and silence pnpm config warnings - Add `.npmrc` with `loglevel=error` so `npm install` no longer surfaces pnpm-only `npm_config_*` keys (`verify-deps-before-run`, `_jsr-registry`, `patched-dependencies`) inherited from a parent pnpm process. - Update `scripts/no-secrets.sh` to permit committing `.npmrc` for non-secret config; the hook still blocks any diff that introduces `_authToken`, `_password`, or `_auth` lines.
main
17 days ago
feat(link): add container import UI with drag-drop decryption (task 42) (#155) * feat(link): import containers via plugin (task 42) Drag-drop .dlc/.ccf/.rsdf/.metalink/.meta4 into Link Grabber paste zone now decrypts via vortex-mod-containers plugin (task 41) and feeds extracted URLs into the existing resolve / online-check / duplicate-detect pipeline. Auto-creates a `source_type=Container` package per imported file. New IPC `link_import_container(file_name, file_bytes)` validates extension + caps payload at 1 MiB, calls the new `PluginLoader::decrypt_container(bytes)` port, parses the plugin JSON, and persists the container package. The Extism adapter scans for the first enabled `Container`-category plugin exporting `decrypt` and ships raw bytes via the new `PluginRegistry::call_plugin_bytes` helper (existing `call_plugin` only takes `&str`, would corrupt non-UTF-8 blobs). `PasteZone` now exports `CONTAINER_EXTENSIONS` + `isContainerFile` predicate and surfaces dropped containers through a dedicated `onContainerFiles(File[])` callback rather than synthesising fake `container:<name>` URLs that LinkGrabberView used to drop on the floor (the original `LinkGrabberView.tsx:67` TODO). Container password protection is wired in spec but vacuously satisfied: vortex-mod-containers v1.0 uses fixed historic AES keys per ADR-001 and none of the four supported formats has a per-file password layer. CCF v2 + DLC v3 service-fetch are deferred to v1.1, so no `password_required` state can flow through `decrypt_container` until the plugin gains the capability. 11 new tests: - 8 backend (`import_container::tests`): golden path, validation rejections (blank/extension/empty/oversize), plugin NotFound, zero-link response, invalid JSON - 1 port default test - 1 adapter "no container plugin loaded" test - 4 frontend `PasteZone.test.tsx` cases (drop callback, callback-missing fallback, text-only drop, isContainerFile) - 2 frontend `LinkGrabberView.test.tsx` cases (drop → import_container → resolve chain ; IPC failure → toast.error) cargo test --workspace: 1493 pass / 7 ignored cargo clippy + cargo fmt clean vitest run: 702 pass oxlint + tsc -b clean * refactor(link): /simplify pass on container import (task 42) - Generic `PluginRegistry::call_plugin_inner` shared by `call_plugin` and `call_plugin_bytes`; drops ~25 duplicated lines. - `tracing::info!` → `debug!` on plugin call (per-call hot path). - Drop redundant `MAX_CONTAINER_BYTES` check in IPC layer; Tauri has already deserialized the buffer before the function body runs, so the "defensive cap" was a dead branch. - `handle_import_container` delegates package creation to the existing `handle_create_package` instead of inlining UUID mint + `Package::new` + `repo.save` + event publish. - Drop redundant `file_name` field from `ImportContainerOutcome` / `ImportContainerResultDto` (always equal to `package_name`). - Move inline IPC type to `src/types/container.ts` per project convention. - Frontend batches all extracted URLs into a single `link_resolve` call after the import loop instead of one IPC per container. - Test fixture sprawl collapsed into `Fixture` / `fixture(loader)` / `stub_fixture()` helpers (~40 lines saved). - Trim WHAT comments (4 sites): `LinkGrabberView::handleContainerFiles`, `PasteZone::handleDrop`, `import_container::MAX_CONTAINER_BYTES`, `extism_loader::decrypt_container`. Keep WHY-only one-liners. - Drop "(task 41)" reference in `import_container` module doc; the CHANGELOG carries that lineage. cargo test --workspace: 1493 pass / 7 ignored cargo clippy + cargo fmt clean vitest run: 702 pass oxlint + tsc -b clean Net: -173 / +98 lines. * fix(link): address PR #155 review comments - Pre-check container file size before reading into memory (avoid wasting RAM on oversized drops) - Batch aggregated container URLs into 500-URL chunks so large imports don't trip the resolve cap - Surface container plugin probe failures as PluginError instead of NotFound (preserves load-failure context) - Trim whitespace from decrypted URLs before collecting - Append `.meta4` to install-hint message - Document alphabetical precedence rule on `decrypt_container` port (matches adapter behavior) - Fix CHANGELOG test count: 11 -> 16 * fix(link): merge chunked container resolves before applying state Each `link_resolve` mutation onSuccess called `setResolvedLinks(resolved)` and overwrote the previous chunk's response. With >500 URLs the user only saw the last chunk. Extract the post-resolve state mutation as `applyResolvedBatch` and, on the chunked path, dispatch resolves directly via `invoke`, accumulate the results, then apply the merged batch once. * fix(link): chunk online and duplicate probes to backend cap `link_check_online` and `link_detect_duplicates` both reject batches above 500 URLs. Container imports above that threshold previously sent a single oversized call, which the backend rejected and tripped the `onError` fallback for every row — leaving large imports unable to bulk-start (status stuck on `unknown`) and bypassing the duplicate gate. Both helpers now slice into 500-URL chunks; each chunk's onError path operates on its own `inFlightChunk` set so a failed chunk does not overwrite a sibling chunk's resolved duplicate state. * fix(link): guard chunked container imports against stale completion Three race conditions surfaced in the chunked container import path: 1. The chunked `applyResolvedBatch(merged)` call ran unconditionally after a long async loop, so a fresh paste-resolve started while chunks were in flight could be overwritten when the loop completed. Add `resolveBatchRef`: `applyResolvedBatch` increments it on every call, and the chunked container handler reserves an id before the loop and bails if a newer batch landed in the meantime. 2. The per-chunk `link_check_online` `onError` fallback marked rows `unknown` with no batch guard; an older batch erroring after a newer batch had pre-seeded `checking` could clobber the live statuses. Gate the fallback on the captured `batchId`. 3. Overlapping container drops both ran to completion since the handler lived outside the resolve mutation. Add an `isImportingContainers` state, bail immediately on a re-entrant call, and feed the flag into `PasteZone`'s `isLoading` so the Analyze button reflects that an import is still resolving. * fix(link): surface backend reason in container import failure toast `containerImportFailed` translation only carried `{{fileName}}`, so the `defaultValue` carrying `String(err)` was discarded whenever the key resolved (always, in practice). Users lost actionable diagnostics — the IPC layer's "Install vortex-mod-containers..." hint never reached the surface. Add a `{{reason}}` interpolation to en + fr, pass the backend message (or a translated `containerTooLarge` for the local size cap) through the toast call. --------- Co-authored-by: Mathieu Piton <27002047+mpiton@users.noreply.github.com>
main
17 days ago

Latest Branches

CodSpeed Performance Gauge
-16%
chore(deps): bump tauri from 2.10.3 to 2.11.1 in /src-tauri#157
17 days ago
990eca5
dependabot/cargo/src-tauri/tauri-2.11.1
CodSpeed Performance Gauge
-19%
feat(link): add container import UI with drag-drop decryption (task 42)#155
17 days ago
ae1f591
feat/task-42-import-containers-ui
CodSpeed Performance Gauge
0%
18 days ago
7ca37e6
dependabot/cargo/src-tauri/openssl-0.10.79
© 2026 CodSpeed Technology
Home Terms Privacy Docs