- Updated padding and margin properties across various chat components to utilize responsive design tokens, ensuring better adaptability to different screen sizes.
- Replaced fixed sizes with responsive variables for buttons, avatars, and bubbles to enhance UI flexibility.
- Adjusted font sizes to use responsive tokens, improving text readability on various devices.
- Standardized border-radius and other dimensions using CSS variables for a cohesive design language.
- Enhanced dialog and screen components with safe area insets for better compatibility with modern devices.
- 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.
Previously, the Skip button (guest login entry) relied on the auth
state machine's `pendingRedirect` flag to trigger the navigation
to /chat after guest login completed. That introduced a
non-obvious coupling: the button dispatched an event, the machine
ran an actor, the auth screen (or splash useEffect) saw the flag
and redirected.
This refactor moves the redirect into the splash screen itself:
- `SplashButton` now takes an `onSkip` prop and no longer knows
about auth dispatch. Pure presentation component.
- `SplashScreen` provides `handleSkip` that dispatches the
`AuthGuestLoginSubmitted` event AND immediately calls
`router.replace(/chat)` for snappier perceived navigation.
- `auth-machine.ts`: `loadingGuestLogin.onDone` no longer sets
`pendingRedirect: true` (splash already navigated). Sets
it to `false` explicitly so other screens (auth, sidebar) that
also react to `pendingRedirect` don't double-navigate if the
user triggers guest login from a non-splash surface in the future.
No behavior change for the happy path: Skip → /chat works the same.
The refactor is purely about responsibility allocation and
component decoupling.
- Prioritize Athelas in --font-system font stack with system fonts as fallback
- Apply italic style to splash button heading and label for typography emphasis
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.
Remove obsolete Dart migration notes and route handling comments from splash-button.tsx and auth-machine.ts, and drop the unused `self` parameter from `chatWebSocketActor` callback signature.
Two related fixes for OAuth login failures:
- `UserSchema`: backend (Facebook/Apple) returns `null` for fields like
`email`; Zod's `.default("")` rejects `null`, causing silent login
failures. Introduce `stringOrEmpty` / `numberOrZero` / `booleanOrFalse`
helpers (`nullable().transform(v => v ?? x).default(x)`) and apply
across the schema so input accepts `string | null | undefined` while
output stays the typed primitive.
- `SplashScreen`: render `state.errorMessage` (set by auth state machine
`onError`, e.g. Facebook sync / schema mismatch) so users no longer
get stuck on splash without feedback.
- Remove ChatAuthStatusChanged dispatch from auth login flow; chat screen now subscribes directly to auth state machine (loginStatus) to derive isGuest and drive WS lifecycle
- Gate quota-exceeded and warning dialogs to guests only (non-guests have no message limit)
- Dispatch ChatLoadMoreHistory for non-guest initial load vs ChatInit for guests
- Fix AppConstants import path from @/core/constants/app_constants to @/core/app_constants
- Add defensive isGuest checks in quota effects to prevent non-guest quota triggers
- Splash Skip button now dispatches `AuthGuestLoginSubmitted` instead of
direct routing, keeping guest auth under the state machine
- Update PWA install dialog copy ("Add to Home Screen") and drop favicon
entry from manifest icons
- Add debug logging and routing sequence docs to splash-button
Update the PWA install dialog styling and content to align with the
original Dart design, including a white background with large 40px
radius, 86x86 PNG icon, gradient primary button, and dynamic app title
sourced from AppConstants.
Move new AuthPlatform(provider).signIn() out of UI components and into
the auth state machine. UI now dispatches AuthGoogle/FacebookLoginSubmitted
events; a new oauthSignIn actor inside the machine calls next-auth/react's
signIn(provider). Errors and the OAuth redirect window are exposed via
the existing state.isLoading / state.errorMessage surface, removing the
local busy / error state in auth-facebook-panel.
Co-Authored-By: Claude <noreply@anthropic.com>
Replace the separate FacebookLogin and GoogleLogin classes with a single
AuthPlatform class that takes a provider name ("facebook" | "google") as a
constructor argument. This consolidates duplicate OAuth sign-in logic behind
one entry point while preserving the existing NextAuth flow.
- Add new src/lib/auth/auth_platform.ts exporting AuthPlatform and
AuthProvider type
- Update auth-facebook-panel.tsx and splash-button.tsx to use the new API
- Rename initialContext → initialState in the auth machine for consistency
- Update inline docs and comments to reference AuthPlatform
No behavioral change for end users; both providers still route through
NextAuth's signIn() with the same callbacks and cookies.
- Remove unused CharacterIntro export from chat components index
- Drop stale JSDoc block from splash-screen server component
- Set mobile shell background to explicit black so the desktop area outside the 500px viewport is black instead of inheriting from parent
- Drop AuthGate/AuthGateState re-exports from @/lib/auth/nextauth
- Simplify SplashButton by removing skipHref prop and hardcoding ROUTES.chat
- Update comments to reference useSession() (next-auth/react) directly instead of the AuthGate wrapper, since the auth UI gate no longer needs the extra abstraction layer.
Migrate from function-based social login helpers (`facebookLogin`, `googleLogin`)
to class-based services (`new FacebookLogin().signIn()`, `new GoogleLogin().signIn()`),
updating call sites in `AuthFacebookPanel` and `SplashButton` with try/catch error
handling. The NextAuth route handler is also refactored to the v4 pattern, importing
pre-built `GET` / `POST` exports from `@/lib/auth/nextauth` instead of constructing
the handler inline with `NextAuth(authOptions)`.
- Move src/data/{api,dto,schemas} directories to src/data/services/*
- Update all relative imports across the codebase to reference new paths
- Use CSS color tokens for splash button gradient in splash-button.module.css
- Add responsive sizes attribute to splash background image
- Add JSDoc documentation to splash-background component referencing original Dart implementation