Three interrelated fixes for the Android Google sign-in flow:
1. API base URL mismatch (404 error):
- auth-form.tsx used 'window.location.origin || VITE_API_BASE_URL',
which fell back to 'http://tauri.localhost' in Android WebView
instead of the actual API server.
- Fix: import shared 'apiBaseUrl' from api-client.ts (already had
the correct fallback: 'https://zeavisedu.asepharyana.my.id').
- Added .env with VITE_API_BASE_URL for dev mode resilience.
2. Deep-link caused IPC callback errors:
- 'processDeepLinkUrl()' used window.location.href = target,
triggering a full page reload that orphaned pending Tauri IPC
promises, causing 'Cannot read properties of undefined (reading
'runCallback')' errors.
- Cold-start: keep get_current but use window.location.href (safe
at boot — no SPA state to lose).
- Warm-start: use sessionStorage + custom DOM event + React Router
navigate() via new <DeepLinkRouterHandler /> layout route,
avoiding any page reload.
3. SPA navigation did not trigger OAuth token handler:
- LoginPage's useEffect for ?token=xxx depended only on
[setUser, queryClient, navigate] — location.search changes
from a SPA navigate() call were ignored.
- Fix: added location.search and location to deps.
- Added visibilitychange + focus listeners so returning from the
Google auth browser always re-checks URL params.
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove local image imports for the background in login and register pages.
- Update background-image styles to use external URL links for easier asset management.
On Tauri Android, window.location.origin = http://tauri.localhost
which is the embedded dev server URL, not the API server.
Use VITE_API_BASE_URL env var which points to the production API.
Co-Authored-By: Claude <noreply@anthropic.com>
Background: Google blocks OAuth in embedded WebView (403 disallowed_useragent).
Solution: open Google login in the Android system browser, then deep-link
back to the Tauri app via custom scheme after callback.
Changes:
- Tauri: add tauri-plugin-opener + tauri-plugin-deep-link to Cargo.toml
- Tauri: register plugins in lib.rs, add capabilities
- Web: auth-form.tsx Google button uses openUrl() via @tauri-apps/plugin-opener
on Tauri (opens in system browser), falls back to window.location.href
- Web: add lib/tauri.ts for isTauri() detection + lazy opens
- API: /auth/google accepts ?platform=tauri → encodes into OAuth state param
- API: /auth/google/callback decodes state → if tauri, renders HTML page
that deep-links back via zeavisedu:// scheme; if web, 302 redirect
- Android: patch script adds deep link intent filter for zeavisedu:// scheme
Co-Authored-By: Claude <noreply@anthropic.com>
Inline SVG with official Google brand colors (blue, green, yellow, red)
placed before the label text with gap-2.5 spacing.
Co-Authored-By: Claude <noreply@anthropic.com>
- Introduce `showPassword` state in the `AuthForm` component to allow users to show or hide their password.
- Implement `Eye` and `EyeOff` icons from `lucide-react` for the toggle button UI.
- Change password input type dynamically between 'password' and 'text'.
- Clean up unused `eye` icon import from `login-page.tsx`.
- Clear error state before submitting credentials in login page
- Clear error state before submitting registration in register page
- Add optional onFieldChange callback to AuthForm to clear parent errors when fields change
- Add role="alert" to error paragraph for accessibility
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>