Commit graph

16 commits

Author SHA1 Message Date
shakespeare.diy
03ea569a2a Amber login: poll relay every 3s after returning from Amber, add elapsed timer + Check Now button
- Replace one-shot visibility handler with pollRelay() called immediately on foreground + every 3s
- Add elapsed time counter (M:SS) so user can see the app is still trying
- Add 'Check Now' button for manual relay poll without generating a new URI
- Poll interval auto-clears on success, timeout, or cancel

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-03 12:34:20 +07:00
shakespeare.diy
dfb60674c5 Fix Amber timeout: increase to 3 minutes so user has time to approve in Amber and return
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-03 12:31:48 +07:00
shakespeare.diy
bd149fdb2c Fix Amber nostrconnect flow: 20s timeout, error state, stale closure fix, better relays, debug logs
- Replace wss://relay.primal.net with wss://nos.lol (more reliable for NIP-46)
- Shorten timeout from 10 minutes to 20 seconds
- Fix stale closure bug: track amberStep in amberStepRef so timeout can correctly reset UI
- Add 'error' step with red UI and 'Try Again' button instead of endless spinner
- Extend since filter from 5s to 10s in the past
- Add console logs for URI, relays, incoming events, decryption result, secret matching

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-03 11:48:03 +07:00
shakespeare.diy
5dffa5cac3 feat: UX improvements - credits, draggable sasquatch, mobile fixes
1. AboutPage: add Credits section (Zapstore, ContextVM, Angor, Geyser, MKStack,
   Shakespeare, Nostr), add Zapstore download button, fix powered-by text overflow
   on mobile (wrap-friendly flex layout)

2. SasquatchGuide: make minimized bubble draggable on all devices
   - pointer events for mouse, touch, and stylus
   - saves position to localStorage, persists across sessions
   - tap still opens, drag moves (5px threshold to distinguish)

3. Layout (burger menu): add overflow-y-auto + pb-8 to SheetContent so
   mobile menu is scrollable when content exceeds screen height

4. CashuWalletCard (wallet): fix input+button rows overflowing on mobile
   - flex-col on small screens, flex-row on xs+ (stacked on phones)
   - whitespace-nowrap on buttons to prevent text wrapping

5. LabPage: compact action buttons on mobile (h-8, text-[10px], px-2)
   so all 4 buttons fit in 2x2 grid without overflow/truncation

6. LoginDialog (Amber): improve visibility-change handler - use fresh
   SimplePool subscription on each foreground return instead of querySync
   (which doesn't exist in nostr-tools v2.13)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-23 09:33:46 +07:00
shakespeare.diy
84d80ac3a7 fix: handle Capacitor WebSocket suspension in NIP-46 Amber login
- Add visibilitychange listener: when app returns to foreground after Amber,
  does a one-shot relay query to catch Amber's connect response
- Store pending nostrconnect session in localStorage so it survives app suspend
- Keep live relay subscription as fallback for web/PWA
- Add nsec login tab as reliable fallback option
- Add proper step states: idle -> connecting -> waiting -> success

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-19 00:38:38 +07:00
shakespeare.diy
789a3d7a60 fix: use nostr-tools SimplePool+nip04 for NIP-46 relay subscription
Replace NRelay1 async iterator (unreliable) with nostr-tools SimplePool.subscribeMany()
using onevent callback — same pattern as Ditto/Coracle/Nostrudel.

- Switch to relay.nsec.app, relay.damus.io, relay.primal.net (support ephemeral events)
- Use nip04.decrypt() from nostr-tools for Amber's connect response decryption
- Proper cleanup of pool and subscription on abort/close
- Fall back to signerPubkey as userPubkey if NConnectSigner.getPublicKey() fails

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-19 00:28:46 +07:00
shakespeare.diy
61795db997 fix: implement NIP-46 nostrconnect:// Amber login properly
- Fix useLoginActions.ts: remove generateNostrConnectParams, generateNostrConnectURI,
  NostrConnectParams, NostrConnectStatus which don't exist in @nostrify/react@0.2.17/login
- Rewrite LoginDialog.tsx Amber tab with proper NIP-46 client-initiated flow:
  - Generates ephemeral client keypair + random secret
  - Builds nostrconnect:// URI (no nostrsigner: scheme, no intents)
  - Opens Amber via window.open(_blank) - standard URI scheme Amber handles natively
  - Listens on relay pool for Amber's kind 24133 connect response
  - Decrypts with NIP-04, verifies secret to prevent spoofing
  - Uses NConnectSigner to call get_public_key
  - Creates NLogin bunker object and stores it persistently
- Bunker tab: direct NLogin.fromBunker() paste flow
- Extension tab: NIP-07 browser extension
- No clipboard hacks, no nostrsigner: scheme, no Android intent issues

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-19 00:02:21 +07:00
shakespeare.diy
916f067238 fix: rewrite login to use NIP-46 nostrconnect flow (Ditto pattern)
Completely replaces the broken NIP-55 intent approach with NIP-46:

- Amber tab: generates nostrconnect:// URI, opens Amber, waits for
  Amber to connect back via relay using NLogin.fromNostrConnect()
  (same pattern as Ditto/soapbox-pub)
- Bunker tab: paste bunker:// URI from Amber or nsec.app
- Extension tab: NIP-07 browser extension (desktop)
- useLoginActions: updated to match Ditto's implementation with
  nostrconnect(), generateNostrConnectParams, generateNostrConnectURI
- Clean mobile-first UI — no clipboard hacks, no intent tricks

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 23:49:55 +07:00
shakespeare.diy
e8bc072787 fix: replace NIP-55 Amber login with NIP-46 bunker flow
NIP-55 (nostrsigner: intents) is fundamentally broken from Capacitor
WebView — no combination of window.open, window.location.href, or
anchor clicks works reliably across all Android WebView versions.

Switch to NIP-46 (bunker://) which works everywhere via WebSockets:
- User opens Amber → Connect apps → Add app → copies bunker:// URI
- Pastes it into the login dialog
- NLogin.fromBunker() completes the handshake over a relay
- Login works in browser, PWA, and Capacitor APK identically

This is exactly how Ditto (soapbox-pub) implements Amber login.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 23:33:42 +07:00
shakespeare.diy
55856e2935 fix: use clipboard mode for Amber login in Capacitor APK
Capacitor native apps fail with "malformed nostrsigner request" when
using callbackUrl because Amber treats custom URI schemes as invalid.

Fix: detect window.Capacitor.isNativePlatform() and use the no-callback
clipboard flow (openAmberForLoginNoCallback) instead of the callbackUrl
flow. Amber copies the pubkey to clipboard, app reads it on
visibilitychange when user returns.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 22:56:28 +07:00
shakespeare.diy
a677e8687d fix: Amber Capacitor APK + mobile UI improvements
Amber login (critical):
- Replace window.location.href with window.open(_system) in Capacitor WebViews
- Capacitor's WebView throws "malformed nostrsigner request" on href navigation
- New openAmberUrl() helper detects Capacitor via window.Capacitor.isNativePlatform()
- Add openAmberForLoginNoCallback() for PWA/Capacitor clipboard flow
- Fix all 6 Amber URL opens in amber.ts + LoginDialog.tsx

Mobile nav:
- Newsletter and Sasquatch AI (/pyramid) added to hamburger menu
- Sasquatch floating guide now shows on mobile (removed hidden md:block)

Lab page mobile:
- Action buttons (Offer Coaching/Filming/Editing/Get Card) now 2-col grid on mobile
- Service type filter (Coaches/Filmers/Editors) now 3-col grid, full width
- Reduced top padding on mobile (py-6 → py-12 on md+)
- Text truncates cleanly, icons don't overflow

Wallet page mobile:
- Reduced padding (py-6 md:py-8)
- Tab triggers use h-auto + py-2.5 to avoid overflow
- Smaller header text on mobile

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-18 20:48:11 +07:00
shakespeare.diy
65914303f1 Fix Amber login for PWA installed to home screen
PWA standalone mode is single-tab. Opening nostrsigner: with a callbackUrl
sends the callback to the browser (a different app), not back to the PWA.
The PWA tab is suspended and never sees the result.

Fix:
- Detect PWA standalone mode via matchMedia('(display-mode: standalone)')
- In PWA mode: open Amber WITHOUT a callbackUrl — Amber copies pubkey to
  clipboard automatically when no callback is given
- Use visibilitychange to detect when user returns to PWA after approving
- Auto-read clipboard on return and complete login silently
- Manual "I approved" button now tries localStorage first (browser), then
  falls back to clipboard read (PWA) — covers both contexts with one button
- Browser mode unchanged: localStorage cross-tab polling still works

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-17 23:04:48 +07:00
shakespeare.diy
0c87fa5827 Fix Amber login not completing on GrapheneOS new-tab callback
Root cause: on GrapheneOS, Amber opens /amber-callback in a BRAND NEW TAB.
login.amber() was being called in that new tab's React instance, which has
no effect on the original tab where the user is waiting.

Fix:
- AmberCallbackPage now writes pubkey to localStorage('amber_pending_pubkey')
  instead of calling login.amber() — a cross-tab signal
- LoginDialog polls for 'amber_pending_pubkey' every 400ms and calls
  login.amber() itself in the correct React context
- Manual "I approved" button also reads the same key
- Removed reliance on getAmberLogin() which checked the wrong localStorage key

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-17 22:46:39 +07:00
shakespeare.diy
4398c2e73b Fix Amber login stuck on GrapheneOS/Android browsers
Root cause: window.location.href navigates the tab away entirely on Android,
destroying sessionStorage. When Amber calls back to /amber-callback the login
completes there, but returning to the dialog the state is lost.

Fixes:
- Switch from sessionStorage to localStorage for amber_return_path and
  amber_login_attempt_ts — survives tab navigation on Android
- Add 500ms polling loop in handleAmberLogin that checks getAmberLogin()
  every 500ms — detects when AmberCallbackPage stored the pubkey and
  auto-completes login without needing visibilitychange to fire
- Add "I approved — complete login" manual button in waiting state as
  explicit fallback for stuck users (reads localStorage right away)
- AmberCallbackPage now uses localStorage for all persistence
- Clean up poll interval on dialog close and unmount

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-17 22:37:26 +07:00
shakespeare.diy
03d0fe93b0 Improve Amber login flow - zero friction, auto-complete on return
- Add dedicated /amber-callback route so Amber always has a stable return URL
  - Handles get_public_key (login), sign_event, nip44/nip04 encrypt/decrypt
  - Shows animated processing screen while completing, then redirects back
- Add subscribeToAmberReturn() helper in amber.ts using visibilitychange
  - Auto-detects when user returns to the tab after cancelling in Amber
  - Resets login UI to initial state gracefully
- Update buildCallbackUrl() to use /amber-callback instead of current page URL
- Rewrite Amber tab in LoginDialog:
  - Remove 2-step clipboard paste flow entirely
  - Single tap opens Amber, login completes automatically on return
  - Waiting state shows animated dots + cancel button
  - No manual pubkey entry needed
- Save return path in sessionStorage so AmberCallbackPage redirects user back

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-17 22:29:06 +07:00
shakespeare.diy
e29d35f1e4 fix: restore full skate-spots source tree from misplaced src/src/ copy
The entire skate-spots codebase was accidentally copied into src/src/ and
public/public/ instead of src/ and public/ directly. This left the real
src/ directory as blank MKStack template stubs, explaining why the landing
page showed the default template instead of SkateSpots.

Changes made:
- Copied all files from src/src/ up to src/ (App.tsx, AppRouter.tsx, main.tsx,
  all pages, components, hooks, contexts, lib, i18n, test)
- Copied all files from public/public/ up to public/ (images, manifest, etc.)
- Deleted src/src/ and public/public/ nested directories
- Removed HelloWorld.tsx template stub from pages/
- Retained the previously fixed index.css (Tailwind v3 directives)

Full skate-spots feature set is now active:
- All 30+ routes (map, events, spots, coaches, marketplace, wallet, etc.)
- NWCProvider, LanguageProvider, PWAInstallPrompt, AmberCallbackHandler
- Skate community relays (goskatespots.nostr1.com, wotr.relatr.xyz, etc.)
- Outfit Variable font, Amber pre-check in main.tsx
- All hooks (useSkateSpots, useCoaches, useZaps, etc.)
- i18n support (en/es)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-15 22:18:28 +07:00
Renamed from src/src/components/auth/LoginDialog.tsx (Browse further)