Fix mobile white screen: stop Outlet Date.now() remount loop (#54) (#56)
Deploy Beta / unit-tests (push) Successful in 12s
Unit Tests / test (push) Successful in 12s
Deploy Beta / deploy-beta (push) Successful in 3m33s

## Summary

- Follow-up for #54 (localStorage guard in #55 did not fix mobile white screen)
- Confirmed in production bundle: `ProtectedRoutes` rendered `<Outlet key={Date.now()} />`
- That remounts the entire authenticated tree on **every** parent re-render (account fetch, WebSocket connect/status, conversations, messages)
- On mobile this shows as: brief UI flash → solid white page (matches screen recording)
- Also memoize styled-components theme in `GlobalThemeWrapper` so `ParticleBackground` does not tear down/restart its canvas on unrelated re-renders

## Evidence

Production JS currently contains:
```js
e?(0,ma.jsx)(a.sv,{},Date.now()):(0,ma.jsx)(a.C5,{to:"/signin/",replace:!0})
```
i.e. authenticated → `<Outlet key={Date.now()} />`

## Test plan

- [ ] Mobile Vivaldi/Chrome: sign in on hesychia.ai → dashboard stays visible (header, conversations toggle, input)
- [ ] Pull-to-refresh while logged in → UI returns and stays
- [ ] Desktop login still works; switching conversations / WS reconnect does not blank the page
- [ ] Open mobile menu / Conversations sidebar still worksReviewed-on: #56
This commit was merged in pull request #56.
This commit is contained in:
2026-07-29 04:04:35 -07:00
parent 103ca2c5e4
commit e6ae9d6b1e
2 changed files with 17 additions and 17 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ const ProtectedRoutes = () => {
if (!authenticated) return <Navigate to='/signin/' replace />
//if(!needsNewPassword) return <Navigate to='/password_reset/' replace/>
return <Outlet key={Date.now()} />
return <Outlet />
}
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useMemo } from 'react';
import { ThemeProvider } from 'styled-components';
import { useMaterialUIController } from '../../ui-kit/context';
import palettes from '../../ui-kit/assets/theme/base/palettes';
@@ -11,14 +11,13 @@ const GlobalThemeWrapper = ({ children }: GlobalThemeWrapperProps): JSX.Element
const [controller] = useMaterialUIController();
const { themeColor, darkMode } = controller;
// Default to blue if themeColor is not found
// Stable theme ref — ParticleBackground restarts its canvas whenever theme identity changes.
const theme = useMemo(() => {
const selectedPalette = palettes[themeColor as keyof typeof palettes] || palettes.blue;
const theme = {
return {
main: selectedPalette.main,
focus: selectedPalette.focus,
darkMode: darkMode,
// Add other global theme variables here if needed
colors: {
background: darkMode ? '#1a2035' : '#f0f2f5',
text: darkMode ? '#ffffff' : '#344767',
@@ -26,6 +25,7 @@ const GlobalThemeWrapper = ({ children }: GlobalThemeWrapperProps): JSX.Element
cardBorder: darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.05)',
}
};
}, [themeColor, darkMode]);
return (
<ThemeProvider theme={theme}>