Paired migration:
- stylelint 16.26 -> 17.9
- stylelint-config-recommended-scss 14.1 -> 17.0
- @csstools/stylelint-formatter-github 1.0 -> 2.0 (requires stylelint 17)
Fix the 26 violations from new deprecation rules:
- 'word-wrap' replaced with 'overflow-wrap' (autofix; word-wrap is a
legacy alias in CSS3, only matters that stylelint now flags it)
- 'word-break: break-word' (deprecated keyword) replaced with
'overflow-wrap: anywhere' (the spec-defined equivalent), with stale
duplicate 'overflow-wrap' declarations consolidated
- cross-env 7→10 (CLI-compatible, Node 20+ engine — already met)
- eslint 9→10 + @eslint/js 9→10 (all active plugins support v10;
fix local rule require-hydration-guard to use context.sourceCode
instead of removed context.getSourceCode())
- jasmine-core 5→6 (forbidDuplicateNames default flipped; no duplicates
in our suite — verified by running the full test:once)
- typia 11→12 (public API surface unchanged; validation specs pass)
Lint, build and the typia/auto-fix specs verified green. The 5 pre-existing
failures in immediate-upload.service.spec.ts are unrelated — also fail on
master with the same package.json that has been shipping.
Deferred from this round: stylelint 16→17 (paired migration with
@csstools/stylelint-formatter-github 1→2, separate work),
electron-dl 3→4 (forces full electron-main CJS→ESM migration),
marked 17→18 (ngx-markdown@21.2.0 peer-locks marked at ^17).
Patch/minor updates across tooling and runtime:
electron 41.2→41.4, electron-builder 26.7→26.8, prettier 3.7→3.8,
playwright 1.57→1.59, typescript-eslint 8.52→8.59, karma 6.4.2→6.4.4,
core-js 3.47→3.49, nanoid 5.1.6→5.1.11, dotenv 17.3→17.4, glob 13.0→13.0.6,
fs-extra 11.3→11.3.4, tslib 2.7→2.8, baseline-browser-mapping 2.9→2.10,
plus type defs and native binaries (@lmdb/*, @rollup/*).
Build, lint and a sample unit test all pass.
* ci(electron): verify packaged app.asar and smoke-test launch
Adds coverage for the gap that let #7320 ship: CI built electron TS
and ran electron-builder on release, but never exercised the packaged
binary. A stray relative import reaching out of electron/** was
compiled by tsc into src/app/util/*.js, fell outside the files glob
in electron-builder.yaml, and was missing from app.asar — the main
process crashed on launch for every 18.2.7 user.
Two new checks, both running on ubuntu-latest:
1. tools/verify-electron-requires.js extracts app.asar and re-resolves
every relative require() under electron/** against the packaged
tree. Runs on every PR that touches electron/**, electron-builder
config, package.json, or the workflow itself. ~10s after the build.
2. A launch-under-xvfb smoke test starts the packaged binary, waits
30s for a crash, and greps stderr for 'Cannot find module' /
'Uncaught Exception'. Runs on push to master, release tags, and
manual dispatch (not every PR — needs xvfb setup + idle wait).
Exposed as npm run electron:verify-asar for local use after dist.
* ci(electron): harden smoke workflow and verify script from review
Review feedback on the previous commit surfaced a handful of real
defects. Addressed here:
verify-electron-requires.js
- Guard resolved paths against escaping the extracted asar tree.
Without this, a relative require with enough `..` climbs above the
temp dir and Node's resolver hits the host filesystem, masking a
genuinely missing module behind a stray file on the CI runner.
- Walk .cjs and .mjs files too. electron/simple-store.test.cjs ships
via the `electron/**/*` glob and was being skipped.
- Move cleanup out of the path where `process.exit(1)` runs inside a
`try/finally` (synchronous exit does not guarantee `finally`), so
the temp dir is reliably removed.
- Code comment noting that esbuild-bundled preload.js is opaque to
this walker — that coverage comes from the launch smoke test.
electron-smoke.yml
- Broaden pull_request paths filter. The previous filter only matched
electron/**, which is exactly the wrong answer: #7320's root cause
was a file under src/app/util/ that electron/ imported. Now uses a
negative list — docs, translations, android/, ios/, other workflows.
- Explicit Xvfb screen geometry (`-screen 0 1280x720x24`) and
`--disable-dev-shm-usage` on the Electron side. Both known CI
flake preventers.
- Expanded crash-marker regex: SIGSEGV, Segmentation fault,
TypeError:, ReferenceError:, FATAL ERROR, Check failed. Also scan
the log during the liveness loop, not just at the end — catches
main-process exceptions that get logged without killing the
process.
- Move the launch log under .tmp/smoke/ so upload-artifact@v7 reliably
finds it on failure; /tmp paths are fragile across runner images.
- Sweep stray electron worker processes on teardown via pkill.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Follow-up to #7297: the simple-store regression test only ran via
local invocation. Add a test:electron npm script and run it in the
CI Tests job so simple-store fixes stay regression-guarded.
* test(e2e): update Show/hide task panel button label
The TOGGLE_DETAIL_PANEL translation was renamed from "Show/Hide
additional info" to "Show/hide task panel" in dd789d2, but e2e
selectors still referenced the old string, causing every test that
opens the task detail panel to time out.
https://claude.ai/code/session_011mX4Pr24S42svmA5j7fRux
* 18.2.1
---------
Co-authored-by: Claude <noreply@anthropic.com>
* chore: update electron to v41.1.1
* feat(start-app): clear GPU cache on Electron version change for Linux
* fix(window-decorators): disable custom window title bar for GNOME
This fixes some issues when moving and resizing the window
* refactor: Migrate url.format() (DEP0116) to file:// path approach
* refactor(start-app): remove deprecated protocol.registerFileProtocol in start-app.ts
* feat(electron-builder): update gnome content snap to gnome-42-2204 for improved compatibility and update flatpak permissions
* fix(window-decorators): improve handling of custom window title bar for GNOME
* feat(start-app): implement fallback to X11 in Snap if gnome-42-2204 runtime is unavailable
* chore: update electron to v41.1.1
* chore(package-lock): remove unused dependencies from package-lock.json
* fix(electron): move snap ozone-platform switch before app ready event
app.commandLine.appendSwitch() must be called before Chromium
initializes — after the ready event fires the GPU backend is already
running and the switch is a no-op. Move the Snap X11 fallback (defense-
in-depth for missing gnome-42-2204 runtime) to run synchronously at
startup, alongside the existing gtk-version and speech-dispatcher
switches.
* fix(electron): align IS_GNOME_DESKTOP detection with preload.ts logic
The original implementation only matched Ubuntu's GNOME session
(XDG_CURRENT_DESKTOP contains both 'gnome' AND 'ubuntu'), missing plain
GNOME on Fedora, Arch, etc. The preload.ts isGnomeDesktop() already
used the correct approach: check four environment variables with OR
logic. Align common.const.ts to match, preventing a split-brain where
the main process and renderer disagree on whether the user is on GNOME
— which would produce no title bar at all on non-Ubuntu GNOME desktops.
* fix(electron): restore v41 bump lost in merge and gate title-bar toggle
- Re-apply electron 41.2.0 + minimatch 10.2.5 override (master's 0e9218bd
reverted the dependabot bump back to 37.10.3 while this branch's
merge-base still contained 41.2.0, so the pre-merge diff was empty).
- Regenerate root package-lock.json accordingly.
- Drop unrelated esbuild additions from plugin-dev sub-lockfiles.
- misc-settings-form: gate isUseCustomWindowTitleBar on IS_ELECTRON &&
!IS_GNOME_DESKTOP so the toggle does not appear in the web/PWA build.
---------
Co-authored-by: Johannes Millan <johannes.millan@gmail.com>
- Separate JsonParseError and SyncDataCorruptedError handlers in sync wrapper
- Handle corrupted remote data gracefully instead of throwing
- Add getOrGenerateClientId() as unified entry point, eliminating dual injection
of ClientIdService + CLIENT_ID_PROVIDER in snapshot-upload, file-based-encryption,
and sync-hydration services
- Use crypto.getRandomValues() instead of Math.random() for client ID generation
- Warn user when stored client ID is invalid and must be regenerated
- Fix flaky e2e supersync tests (premature waitForURL match on daily-summary URL)
When a full-state op (SYNC_IMPORT/BACKUP_IMPORT) arrived from another
client, mergeRemoteOpClocks reset the local clock to a "minimal" form
but only preserved the current client's counter from the incoming op's
clock. If the current client had issued ops (e.g. GLOBAL_CONFIG) not
reflected in the incoming full-state op's clock, its counter was dropped,
causing subsequent ops to reuse the same counter value. Downstream clients
then saw these ops as EQUAL (duplicate) and skipped them silently.
Fix: take max(mergedClock[clientId], currentClock[clientId]) when
rebuilding the clock after a full-state op reset.
Also add __SP_E2E_BLOCK_WS_DOWNLOAD flag to WsTriggeredDownloadService
to allow E2E tests to block automatic WS-triggered downloads during
concurrent conflict scenarios.
Fix archive conflict test by blocking WS downloads on Client A during
the concurrent edit phase so it doesn't auto-receive B's rename via
WebSocket before archiving (restoring the intended conflict scenario).
Fix LWW singleton test to assert convergence rather than specific winner.
Fix renameTask helper to avoid Playwright/Angular re-render races.
Fix shepherd.js import paths that broke the Angular dev server build.
electron-dl v4 is a pure ESM package. Since the Electron main process
is compiled with TypeScript "module": "commonjs", static import() gets
transformed to require() which cannot load ESM. Use Function() to
preserve a real dynamic import() at runtime.
shepherd.js switched from MIT to AGPL-3.0 in v14. Pin to the last
MIT-compatible version and update imports to use named exports from
the main module instead of deep internal paths.
sharp is a native C++ module that fails to compile in F-Droid's
build environment. It is only used by manual icon generation scripts,
so auto-install it on demand instead.
Closes#6637
tools/load-env.js requires dotenv directly but it was only available as
a transitive dependency of @dotenv-run/cli. This caused the Docker image
publish to fail when npm ci couldn't resolve it. Also regenerates
package-lock.json to fix stale lock file entries.
Google blocks OAuth authorization in embedded WebViews (Error 400:
invalid_request). Use @capacitor/browser to open the system browser
on mobile instead of window.open() in the WebView.
https://claude.ai/code/session_01QWSy4NhhNQNMD2GJwqoYTc
Co-authored-by: Claude <noreply@anthropic.com>
Bundle preload.ts into a single file so all local imports (e.g.
ipc-events.const) are inlined at build time. This allows removing
sandbox: false since the bundled preload only requires the built-in
electron module, which is allowed in sandboxed preloads.