| … | … | @@ -68,6 +68,8 @@ function Web ({ status }) { |
| 68 | 68 | const ref = useRef(null) |
| 69 | 69 | const [canBack, setCanBack] = useState(false) |
| 70 | 70 | const [failed, setFailed] = useState(null) |
| 71 | // Has anything EVER loaded? Only a failure before the first successful page is fatal. |
| 72 | const loaded = useRef(false) |
| 71 | 73 | |
| 72 | 74 | // THE SESSION, handed to the WebView's own cookie jar. The worklet signed in over loopback and holds |
| 73 | 75 | // the token; a WebView cannot be told about that, so favela-web's /auth/handoff swaps the token for the |
| … | … | @@ -109,8 +111,17 @@ function Web ({ status }) { |
| 109 | 111 | // in a real browser is a later refinement, and refusing is the safe default in the meantime. |
| 110 | 112 | onShouldStartLoadWithRequest={(r) => r.url.startsWith(status.favelaUrl)} |
| 111 | 113 | onNavigationStateChange={(n) => setCanBack(n.canGoBack)} |
| 112 | | onError={(e) => setFailed((e.nativeEvent && e.nativeEvent.description) || 'load failed')} |
| 113 | | onHttpError={(e) => setFailed('HTTP ' + ((e.nativeEvent && e.nativeEvent.statusCode) || '?'))} |
| 114 | onLoadEnd={() => { loaded.current = true }} |
| 115 | // ⛔ A FAILED REQUEST IS NOT A FAILED APP. These fire for the MAIN FRAME, which includes the POST |
| 116 | // a compose submits — so a single 500 from one write tore down the entire rendered UI and replaced |
| 117 | // it with a full-screen "could not load the local UI", losing the user's place and making a |
| 118 | // one-request failure look like the app dying. (Observed on device 2026-08-11: post fails once, |
| 119 | // whole UI is replaced, retry works.) |
| 120 | // |
| 121 | // Only a failure BEFORE anything has ever rendered is fatal — that is the case the screen is for |
| 122 | // (server never came up). After that, the page is still there and owns its own error reporting. |
| 123 | onError={(e) => { if (!loaded.current) setFailed((e.nativeEvent && e.nativeEvent.description) || 'load failed') }} |
| 124 | onHttpError={(e) => { if (!loaded.current) setFailed('HTTP ' + ((e.nativeEvent && e.nativeEvent.statusCode) || '?')) }} |
| 114 | 125 | // Loopback only, so no mixed-content or remote-code concern; the pages need JS for likes/compose. |
| 115 | 126 | javaScriptEnabled |
| 116 | 127 | domStorageEnabled |