- Updated comments in various components, schemas, and repositories to remove references to original Dart files.
- Ensured consistency in documentation while maintaining the context of the code.
The previous install flow had a timing race: the
`beforeinstallprompt` event fires at unpredictable times after
page load (often ~30s+ into the session, when Chrome's heuristic
finally decides the user is engaged). If the listener was
attached only inside the dialog's onClick handler, by the time
the user clicked OK the event had already fired into the void
and the deferred prompt was null — so `install()` returned
"unavailable" every time.
The new flow attaches the listener as early as possible:
1. `pwaUtil.prepareInstallPrompt()` — new public method that
calls the private `attachListener()`. Idempotent (guard via
`listenersAttached`).
2. `pwaUtil.canPromptInstall()` — companion getter that returns
whether a deferred event is currently cached. Useful for UI
to decide whether to even show the install CTA.
3. `pwa-install-overlay.tsx` — calls `prepareInstallPrompt()`
right after the isSupported / isInstalled guards. The overlay
mounts when the user enters /chat, so this is the earliest
practical point in the user flow.
4. `pwa-screen.tsx` — calls `prepareInstallPrompt()` BOTH at
module load (synchronous, so the listener is attached before
the splash screen's useEffects run) AND in a useEffect for
robustness. The splash screen is the very first screen the
user sees, so attaching here is the earliest possible.
5. `pwa-install-dialog.tsx` — `handleInstall` is now async,
and `onInstall` accepts `() => void | Promise<void>`. The
overlay calls `await pwaUtil.install()` so the deferred
prompt flow can complete before the dialog unmounts.
Together: the listener is now attached from the moment the
splash screen module loads, the deferred prompt is captured
whenever Chrome decides to fire the event, and the dialog's
install button can reliably `prompt()` against the cached
deferred. The full install flow now works end-to-end.
Facebook Graph API field expansion uses parentheses, not equals signs.
The buggy `picture.type=large` produced HTTP 400 with
`OAuthException code 2500: Syntax error ... at character 32`.
Fix `FIELDS` constant and 2 JSDoc comment lines in facebook-graph.ts
to use `picture.type(large)` per Facebook's documented syntax.
Effect: after Facebook OAuth sync, `fetchFacebookUserData` now
succeeds (HTTP 200), `UserStorage.setAvatarUrl` and
`AuthStorage.setFacebookId` get populated, and the
`[auth-machine] syncFacebookBackendActor: fetchFacebookUserData
failed (continuing anyway)` warning stops firing on the happy path.
Remove `**...**` emphasis markers from inline comments and JSDoc blocks across
auth and chat components, machine mappers, and quota helpers. These are
plain code comments, not rendered markdown, so the bold syntax was noise.
Files touched:
- src/app/auth/components/auth-screen.tsx
- src/app/chat/components/chat-header.tsx
- src/app/chat/components/chat-screen.tsx
- chat machine mapper / quota helpers
No functional or behavioral changes.
Integrate the Logger into `Result.wrap` so that caught exceptions are
recorded with stack trace, error type, and a `component: "Result"`
tag before being wrapped into a `Result<T>`. Errors are first
normalized via `toError` to preserve `.stack`, `.code`, and `.status`
fields, then logged through the standard pipeline (dev console in
development, JSON pipeline in production). Callers continue to receive
a `Result<T>` — re-throwing remains opt-in via `Result.unwrap`.
Add pino v10.3.1 to project dependencies for structured logging support, along with its transitive dependencies (pino-abstract-transport, pino-std-serializers, quick-format-unescaped, atomic-sleep, etc.).
Introduce xstate v5 and @xstate/react to manage user authentication and profile state. Implement userMachine with actors for initialization, fetching, and logout operations, along with actions for updating user data and clearing state.
Relocate the Result type from `@/data/result` to `@/utils/result` and
replace the discriminated-union API (`kind`/`value`) with a simpler
boolean-based API (`success`/`data`) across all repositories and
storage classes for improved readability and consistency.
Replace minimal background/foreground vars with a comprehensive design
system covering colors (background, text, brand, profile, gifts,
activities, nav), spacing, and border-radius tokens. Mirrors the
original Dart design constants under src/design/*.ts and supports
dark mode.