Skip to content

Use new Service Worker - #316

Merged
pietro909 merged 25 commits into
nextfrom
use-sw-2
Feb 26, 2026
Merged

pietro909 merged 25 commits into
nextfrom
use-sw-2

Conversation

@pietro909

@pietro909 pietro909 commented Feb 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Chores

    • Updated dependency sources and pnpm build config; added gitignore entry.
  • Refactor

    • Moved swap/wallet persistence to repository-backed storage and reworked service worker initialization.
    • Converted swap subscription lifecycle to async setup with safer cleanup.
    • Rewired backup flows to use the new repository approach.
  • Bug Fixes

    • Improved wallet event payload handling for more reliable updates.

@coderabbitai

coderabbitai Bot commented Feb 12, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • next-version

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Refactors swap/wallet persistence to use injected repository abstractions, replaces ArkadeLightning with a ServiceWorker-based lightning client, converts swap subscription APIs to async unsubscribe promises, updates package dependency sources and pnpm settings, and wires repositories into service worker MessageBus initialization.

Changes

Cohort / File(s) Summary
Config & deps
/.gitignore, package.json
Added .claude/ to .gitignore; updated arkade-os dependency sources and added a pnpm config block (esbuild ignored, sdk in onlyBuiltDependencies).
Swap backup & restore
src/lib/backup.ts, src/screens/Init/Restore.tsx, src/screens/Settings/Backup.tsx
BackupProvider now depends on an injected SwapRepository (IndexedDbSwapRepository passed at call sites); persistence calls switched to swapRepository.saveSwap. Constructor signature of BackupProvider updated.
Indexer & wallet lifetime
src/lib/indexer.ts, src/lib/wallet.ts
Removed IndexedDB/ContractRepository usage; added localStorage caching for commitment TX timestamps and renamed getCommitmentTxCreatedAt → getAndUpdateCommitmentTxCreatedAt. calcBatchLifetimeMs signature changed to accept Indexer (call sites updated).
Providers & initialization
src/providers/config.tsx, src/providers/lightning.tsx, src/providers/wallet.tsx
Replaced ArkadeLightning with ServiceWorkerArkadeLightning and SwapManagerClient; introduced IndexedDbSwapRepository and IndexedDB wallet/contract repositories; wired repositories into provider initialization and service worker wallet setup; added migration paths.
Subscription flow updates
src/components/SwapsList.tsx, src/screens/Apps/Boltz/Swap.tsx
Subscription APIs updated: onSwapUpdate/subscribeToSwapUpdates now return Promise<() => void>; effects now await/handle async resolution and use a cancelled guard for cleanup.
Event payload & QR handling
src/screens/Wallet/Receive/QrCode.tsx
Event handlers changed to read payload from event.data.payload (e.g., newVtxos, coins) for VTXO/UTXO update events.
Service worker & messaging
src/wallet-service-worker.ts
Replaced direct Worker usage with a MessageBus initialization; wired wallet, contract and swap repositories into the bus; added arkade lightning message handler; removed legacy reload message listener.

Sequence Diagram(s)

sequenceDiagram
  participant App as Client UI
  participant SW as ServiceWorker
  participant MB as MessageBus
  participant WR as IndexedDbWalletRepository
  participant SR as IndexedDbSwapRepository
  participant LH as ArkadeLightningHandler

  rect rgba(200,220,255,0.5)
  App->>SW: register / init ServiceWorker
  SW->>MB: create MessageBus(tickIntervalMs=5000)
  MB->>WR: wire wallet repo
  MB->>SR: wire swap repo
  MB->>LH: attach lightning message handler
  SW-->>App: ready
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • bordalix
  • Kukks
  • louisinger
🚥 Pre-merge checks | ✅ 2 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (16 files):

⚔️ .gitignore (content)
⚔️ package.json (content)
⚔️ pnpm-lock.yaml (content)
⚔️ public/wallet-service-worker.mjs (content)
⚔️ src/components/SwapsList.tsx (content)
⚔️ src/lib/backup.ts (content)
⚔️ src/lib/indexer.ts (content)
⚔️ src/lib/wallet.ts (content)
⚔️ src/providers/config.tsx (content)
⚔️ src/providers/lightning.tsx (content)
⚔️ src/providers/wallet.tsx (content)
⚔️ src/screens/Apps/Boltz/Swap.tsx (content)
⚔️ src/screens/Init/Restore.tsx (content)
⚔️ src/screens/Settings/Backup.tsx (content)
⚔️ src/screens/Wallet/Receive/QrCode.tsx (content)
⚔️ src/wallet-service-worker.ts (content)

These conflicts must be resolved before merging into next.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Use new Service Worker' is directly related to the main objective of the pull request, which is to introduce changes to use a new Service Worker architecture throughout the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch use-sw-2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pietro909
pietro909 marked this pull request as draft February 12, 2026 10:12
@pietro909 pietro909 changed the title Use sw 2 Use new Service Worker Feb 12, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Feb 13, 2026 •

Copy link
Copy Markdown

Deploying wallet-mutinynet with  Cloudflare Pages  Cloudflare Pages

Latest commit: afc84f1
Status: ✅  Deploy successful!
Preview URL: https://a0a5ab1f.arkade-wallet.pages.dev
Branch Preview URL: https://use-sw-2.arkade-wallet.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Feb 13, 2026 •

Copy link
Copy Markdown

Deploying wallet-bitcoin with  Cloudflare Pages  Cloudflare Pages

Latest commit: afc84f1
Status: ✅  Deploy successful!
Preview URL: https://e44f1ede.wallet-bitcoin.pages.dev
Branch Preview URL: https://use-sw-2.wallet-bitcoin.pages.dev

View logs

@pietro909
pietro909 marked this pull request as ready for review February 13, 2026 16:03
@pietro909

Copy link
Copy Markdown
Contributor Author

@coderabbitai please review - it's still a work in progress where we test the latest updates from next branches, that's why the package.json refers to Github repositories.

@coderabbitai

coderabbitai Bot commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

@pietro909: I'll review this PR for you. I've noted that this is a work in progress and that the GitHub repository references in package.json are intentional for testing the latest updates from next branches. I'll keep this context in mind during the review.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/lib/backup.ts (1)

74-97: ⚠️ Potential issue | 🟠 Major

fullBackup no longer backs up swaps — functional regression.

With the swap collections commented out (lines 77-79), fullBackup only backs up config. The iteration over data.reverseSwaps and data.submarineSwaps (lines 87-93) is dead code since those fields are always undefined. Users enabling Nostr backups will silently lose swap backup data.

Since swapRepository is now available as an injected dependency, you can resolve this by retrieving swaps from the repository before storing them. Verify the actual method signatures on SwapRepository (from @arkade-os/boltz-swap) to wire up the appropriate retrieval methods—the exact API names need to be confirmed against the package.

src/providers/wallet.tsx (1)

238-245: ⚠️ Potential issue | 🟠 Major

setInterval is never cleared — intervals accumulate on retries and across re-mounts.

Each invocation of initSvcWorkerWallet registers a new 1-second polling interval that is never cleared. On service-worker activation retries (Lines 261-267), this stacks up additional intervals. There's also no cleanup on component unmount.

Store the interval ID and clear it on cleanup/retry:

Sketch of a fix

One approach: store the interval ID in a ref and clear it during cleanup or before re-init. For example, return the interval ID from initSvcWorkerWallet so the calling effect can clear it, or manage it via a ref:

+  const statusIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null)
+
   // inside initSvcWorkerWallet, before setting the interval:
+  if (statusIntervalRef.current) clearInterval(statusIntervalRef.current)
-  setInterval(async () => {
+  statusIntervalRef.current = setInterval(async () => {
     try {
       const { walletInitialized } = await svcWallet.getStatus()
       setInitialized(walletInitialized)
     } catch (err) {
       consoleError(err, 'Error pinging wallet status')
     }
   }, 1_000)

And clean up in the component's unmount effect.

🤖 Fix all issues with AI agents
In `@src/components/SwapsList.tsx`:
- Around line 122-144: The subscription can leak if the component unmounts
before swapManager.onSwapUpdate resolves; add a cancelled flag to the effect:
set let cancelled = false before calling swapManager.onSwapUpdate, and in the
.then((unsubscribe) => { if (cancelled) { call unsubscribe immediately } else {
unsub = unsubscribe } }); update the cleanup to set cancelled = true and call
unsub?.() so any late-resolved unsubscribe is either stored for cleanup or
invoked right away; reference swapManager.onSwapUpdate, unsub, and
setSwapHistory to locate the code to change.

In `@src/lib/indexer.ts`:
- Around line 10-15: The constructor currently accepts a walletRepository but
never uses it; either remove the unused constructor parameter or switch the
class to use WalletRepository instead of localStorage for persistence. If
choosing to use the repository, replace direct localStorage access in methods
that read/write wallet data (references to localStorage at lines around where
wallets are loaded/saved) with calls to the injected walletRepository (e.g., add
or use methods on WalletRepository such as getWallets/saveWallets or similar),
and remove any direct localStorage references; if choosing to remove it, delete
the walletRepository parameter from the constructor signature and any related
private field to avoid unused injection.
- Line 3: The import of WalletRepository from '../../../ts-sdk/src/repositories'
is a fragile local filesystem reference and the constructor parameter
walletRepository in the class is unused while methods directly use localStorage
(which also fails in Service Worker/CI). Replace the relative import with the
published package import for the SDK's repositories (use the package name used
in package.json), then either remove the unused constructor parameter
walletRepository or refactor the class methods (e.g., wherever localStorage is
accessed) to call walletRepository methods (save/load/delete) so persistence
goes through the repository API and not localStorage; ensure code no longer
depends on browser localStorage so it works in Service Worker and CI.
- Around line 27-38: The Indexer class currently injects walletRepository but
persists commitment IDs using localStorage in getCommitmentTxIds and
setCommitmentTxIds (using STORAGE_KEY); either remove the unused
walletRepository parameter from the Indexer constructor and any related fields
if you intend to keep main-thread-only localStorage persistence, or replace the
localStorage usage in getCommitmentTxIds and setCommitmentTxIds with the
walletRepository's get/set methods (use the repository's equivalent persistence
API to read/write the STORAGE_KEY-backed map) so the injected walletRepository
is actually used and consistent with Service Worker-compatible storage.

In `@src/providers/lightning.tsx`:
- Around line 90-109: The effect currently captures a stale arkadeLightning
value so the cleanup never disposes the created ServiceWorkerArkadeLightning
instance; fix it by tracking the instance in a ref (e.g., arkadeRef via useRef)
and use that ref for lifecycle ops: when
ServiceWorkerArkadeLightning.create(...) resolves, assign the instance to
arkadeRef.current and still call setArkadeLightning(instance); in the effect
cleanup (and before creating a new instance) check arkadeRef.current and call
arkadeRef.current.dispose().catch(...) and then null out arkadeRef.current to
ensure the created instance is always disposed on unmount or deps change (also
handle disposing any previous instance before assigning a new one).

In `@src/screens/Apps/Boltz/Swap.tsx`:
- Around line 37-52: The effect currently leaks subscriptions if the component
unmounts before subscribeToSwapUpdates resolves; update the useEffect around
swapManager.subscribeToSwapUpdates (and the local unsub variable) to use a
cancelled flag: set let cancelled = false before calling subscribeToSwapUpdates,
and in the .then((unsubscribe) => { ... }) handler, if cancelled call
unsubscribe() immediately, else assign unsub = unsubscribe; in the cleanup set
cancelled = true and call unsub?.() so any resolved promise either gets cleaned
up immediately or assigns a safe unsub reference for cleanup. Ensure you
reference swapManager, subscribeToSwapUpdates, swapInfo.id and unsub in the
change.

In `@src/wallet-service-worker.ts`:
- Around line 13-17: The worker instantiation currently hardcodes debug: true
which will produce noisy logs in production; change the MessageBus options to
derive debug from an environment/config flag instead (e.g., use
process.env.WORKER_DEBUG or check process.env.NODE_ENV !== 'production'), parse
the value to a boolean, and pass that boolean to the MessageBus constructor
where debug is currently set (the object passed to new MessageBus in
src/wallet-service-worker.ts that also sets messageHandlers, tickIntervalMs).
Ensure the new behavior defaults to false in production when the env var is
unset or explicitly set to "false".
🧹 Nitpick comments (6)
package.json (1)

7-8: Non-reproducible dependency references pinned to branch tips.

Both @arkade-os/boltz-swap and @arkade-os/sdk point to #next branches, so every install can resolve a different commit. This is fine for WIP testing (as noted), but before merging to next, consider pinning to a specific commit SHA or a published version to ensure reproducible builds.

src/lib/backup.ts (1)

108-109: TODO left in restore path — ensure parity with backup.

The comment "restore as contracts via ad-hoc utils in boltz-swap" suggests the restore path is also incomplete. While saveSwap calls on Lines 111/115 do persist individual swaps, confirm this is sufficient for the full restore flow (e.g., are contract-level semantics needed beyond saving raw swap objects?).

Would you like me to open an issue to track the remaining TODO items in this file?

src/providers/config.tsx (1)

53-53: Each call site creates a new IndexedDbSwapRepository instance.

backupConfig is called on every config change when Nostr backup is enabled, and each invocation creates a fresh IndexedDbSwapRepository (plus a fresh BackupProvider). The repository isn't even used in the backupConfig code path — it's only needed for restore.

Consider sharing a single repository instance (e.g., via context or a module-level singleton) across config.tsx, Backup.tsx, and Restore.tsx to avoid redundant IndexedDB setup and improve consistency.

src/providers/wallet.tsx (2)

197-210: Migration errors are silently swallowed — consider surfacing them to the user.

The migration try/catch logs the error but the user has no indication that their data may not have been fully migrated. For a WIP this is acceptable, but before merging you may want to track migration status (e.g., a flag/toast) so users can retry or be informed.


104-104: A new Indexer is created on every effect execution.

new Indexer(aspInfo, svcWallet.walletRepository) is re-instantiated each time the dependencies [initialized, vtxos, svcWallet, aspInfo] change. The constructor is cheap (stores references), so this is not a performance problem today, but memoizing the Indexer instance (e.g., via useMemo) would avoid unnecessary object creation and would make the code clearer about instance identity.

src/providers/lightning.tsx (1)

99-99: Inconsistent error handler: .catch(console.error) bypasses the app's logging system.

Line 99 uses console.error directly, while the rest of the file (and codebase) uses consoleError from ../lib/logs for structured logging.

Proposed fix
-      .catch(console.error)
+      .catch((err) => consoleError(err, 'Failed to create ServiceWorkerArkadeLightning'))

Comment thread src/components/SwapsList.tsx Resolved
Comment thread src/lib/indexer.ts Resolved
Comment thread src/lib/indexer.ts Resolved
Comment thread src/lib/indexer.ts Resolved
Comment thread src/providers/lightning.tsx Resolved
Comment thread src/screens/Apps/Boltz/Swap.tsx Resolved
Comment thread src/wallet-service-worker.ts Resolved
@pietro909

Copy link
Copy Markdown
Contributor Author

@coderabbitai review again, I've addressed your comments in the last commit

@coderabbitai

coderabbitai Bot commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

@pietro909: Thank you for addressing the comments! I'll review the changes again and check the latest commit.


🧠 Learnings used
Learnt from: bordalix
Repo: arkade-os/wallet PR: 114
File: src/lib/asp.ts:0-0
Timestamp: 2025-06-30T18:33:29.839Z
Learning: In src/lib/asp.ts, only the collaborativeExit function should accept both IWallet and ServiceWorkerWallet types. Other wallet functions (getBalance, getTxHistory, getReceivingAddresses, redeemNotes, sendOnChain, settleVtxos) should maintain their original IWallet-only signatures and not be updated for consistency.

Learnt from: bordalix
Repo: arkade-os/wallet PR: 114
File: public/wallet-service-worker.mjs:6350-6353
Timestamp: 2025-06-30T18:23:34.163Z
Learning: Do not review `public/wallet-service-worker.mjs` as it is a built file generated by Vite.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/lib/indexer.ts`:
- Around line 23-27: getCommitmentTxIds currently calls JSON.parse on
localStorage data which will throw if the blob is corrupted; wrap the parse in a
try/catch and fall back to an empty object (and optionally log the parse error)
so callers like getAndUpdateCommitmentTxCreatedAt don't crash; do the same
defensive parsing in setCommitmentTxIds (and validate that the parsed value is
an object and that map[txid] values are numbers before returning, otherwise
treat as empty) and ensure you always call JSON.stringify on the safe object
when writing back to localStorage.

In `@src/providers/lightning.tsx`:
- Around line 90-119: The effect never flips the cancelled flag, causing
ServiceWorkerArkadeLightning.create() to set state after teardown; in the
cleanup (the returned function) set cancelled = true before attempting disposal
and then, if disposeArkadeLightning is non-null, call it; this ensures the
.then() branch checks cancelled and disposes the instance instead of calling
setArkadeLightning on an unmounted/stale component (refer to cancelled,
disposeArkadeLightning, ServiceWorkerArkadeLightning.create,
setArkadeLightning).
🧹 Nitpick comments (3)
src/lib/indexer.ts (1)

13-21: Naming mismatch: method name says "Ids" but it deals with a single createdAt timestamp.

getCommitmentTxIds / setCommitmentTxIds actually get/set a createdAt value for a given txid, not a collection of IDs. Consider renaming to something like getCachedCreatedAt / setCachedCreatedAt to avoid confusion.

src/providers/lightning.tsx (2)

109-109: Inconsistent error handler: console.error vs consoleError.

Line 109 uses console.error directly, while the rest of the file (lines 103, 118, 128, etc.) uses the project's consoleError wrapper which also writes to the structured log. This means creation failures won't appear in the app's log.

Proposed fix
-      .catch(console.error)
+      .catch((err) => consoleError(err, 'Failed to create ServiceWorkerArkadeLightning'))

103-105: Minor: double error catch on dispose.

Line 105 wraps instance.dispose() with .catch(consoleError), and then line 118 calls disposeArkadeLightning().catch(consoleError) again. The outer catch is redundant since the inner one already swallows errors. Not a bug, but worth simplifying for clarity.

Proposed fix — let only the call-site handle the error
-          disposeArkadeLightning = () => instance.dispose().catch(consoleError)
+          disposeArkadeLightning = () => instance.dispose()

Comment thread src/lib/indexer.ts Resolved
Comment thread src/providers/lightning.tsx Resolved
sahilc0 and others added 2 commits February 24, 2026 19:27
* feat(haptics): add cross-platform haptic feedback system

Add haptics utility with three intensity levels (tap/light/subtle) that
works across Android (vibrate API) and iOS 18+ (checkbox switch hack).
Integrate haptic feedback into 12 interactive components: buttons, toggles,
checkboxes, list items, copy actions, settings rows, and navigation.

Add haptics toggle in Settings > General so users can disable vibration.
Wire haptics enabled state through config provider.

Also adds @vitejs/plugin-basic-ssl and host:true for mobile HTTPS testing.

* style: fix prettier formatting

* fix: harden iOS detection and add aria-label to settings rows

Add iPadOS detection (MacIntel + maxTouchPoints > 1) and guard
navigator access for non-browser contexts in haptics utility.
Add descriptive aria-label to settings row Focusable wrappers.

Addresses CodeRabbit review feedback on #325.

* fix: make basicSsl conditional on HTTPS env var

Playwright e2e tests in CI connect via HTTP but the dev server was
unconditionally using HTTPS via basicSsl(), causing connection failures.
Only enable basicSsl() when HTTPS=true is set in the environment.

* feat(button): add 3D press effect with per-variant shadow colors (#326)

Replace flat box-shadow with depth-accurate per-variant shadow colors:
dark purple (#1a0b4a) under purple buttons, dark red (#6b0e0e) under
red, subtle rgba(0,0,0,0.10) under secondary/outline. Add border-radius
to outer ion-button so shadow follows rounded corners.

Add pressed state via touch/mouse events (not :active — unreliable on
mobile): translateY(4px) with shadow collapse for solid buttons,
scale(0.97) for clear buttons. Suppress Ionic's internal ripple, focus
ring, and activated state overrides.

Includes prefers-reduced-motion media query to disable transitions.

Co-authored-by: Sahil Chaturvedi <sahilc0@users.noreply.github.com>

* style: fix prettier formatting in ionic.css

* chore: add .claude and CLAUDE.md to .gitignore

* fix: address coderabbit review feedback

- Add blank lines between custom props and declarations (stylelint)
- Memoize handleClick with useCallback in Logo

---------

Co-authored-by: Sahil Chaturvedi <sahilc0@users.noreply.github.com>
sahilc0 and others added 9 commits February 25, 2026 15:42
* feat(ui): tab icon pop animation and logo tap target

Add pop animation to tab bar icons on tap using CSS keyframes.
AnimatedTabIcon component triggers scale animation on tab selection
with spring easing and prefers-reduced-motion support.

Increase logo tap target from ~47px to 71px using invisible padding
(18px around the 35px icon) so the easter egg is easier to activate.

Files: src/App.tsx, src/index.css, src/icons/Logo.tsx

* style: fix prettier formatting in tab animation keyframes

* style: run prettier formatting

* fix(ui): add comment explaining reflow trick in tab animation

* nit from rabbit

---------

Co-authored-by: Sahil Chaturvedi <sahilc0@users.noreply.github.com>
Co-authored-by: Marco Argentieri <3596602+tiero@users.noreply.github.com>
Co-authored-by: João Bordalo <bordalix@users.noreply.github.com>
* Set a maxheight restriction on announcement modal and display adjustments to ensure responsiveness

* Adjusted file formatting + fixed comment

* Changed 'margin' to 'marginTop' and removed redundant styling
* feat(ui): animate loading bar with traveling wave

Replace the static pixel-art battery SVG with a smooth traveling wave
animation. Each of the 6 segments oscillates between 30-100% fill height
using eased sine waves with phase offsets, creating a fluid wave effect.

- Use requestAnimationFrame + refs for 60fps without React re-renders
- Apply ease-in-out-cubic to raw sine for natural motion
- Respect prefers-reduced-motion via useReducedMotion hook
- Add cloudflare tunnel host to vite allowedHosts for mobile testing

Files: src/icons/LoadingBar.tsx, vite.config.ts

* style: run prettier formatting

* fix(build): replace framer-motion import with inline useReducedMotion hook

framer-motion is not a project dependency. Replace the import with a
lightweight inline hook using window.matchMedia to detect the
prefers-reduced-motion preference.

---------

Co-authored-by: Sahil Chaturvedi <sahilc0@users.noreply.github.com>
@pietro909
pietro909 merged commit 37b4b79 into next Feb 26, 2026
2 checks passed
@bordalix
bordalix deleted the use-sw-2 branch May 18, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants