feat(ui): connection status in the header; README screenshots as WebP
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m38s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m38s
- Desktop shows "offline" with a red dot under the user name when the server is unreachable; phones show a green/red dot on the avatar. Based on the app-wide realtime connection, so a server outage is noticed even while the device has network (4 s grace period). - Screenshots converted to WebP (1280 px desktop, 480 px phone, q90), e2e/screenshots.sh converts with cwebp; new journal picture with round corners. Rules in AGENTS.md. - Release v0.26.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c1adb10b5e
commit
fdd6e38065
34 files changed
+186
-21
No files matched your search
@@ -0,0 +1,45 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { onRealtimeStatus } from './api';
|
||||
|
||||
// Grace period before a missing realtime connection counts as offline (app start, short reconnects)
|
||||
export const SERVER_OFFLINE_GRACE_MS = 4000;
|
||||
|
||||
// Whether the server is reachable, judged by the app-wide realtime connection (WebSocket/SSE). Unlike
|
||||
// navigator.onLine it also notices a server that is down while the device still has network. Without
|
||||
// device network it is offline right away; otherwise only after the connection stayed away for a moment.
|
||||
export function useServerOnline(): boolean {
|
||||
const [online, setOnline] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
let connected = false;
|
||||
let timer: number | undefined;
|
||||
// Reconnect attempts report "not connected" every few seconds; they must not restart the grace period
|
||||
const update = () => {
|
||||
if (connected) {
|
||||
window.clearTimeout(timer);
|
||||
timer = undefined;
|
||||
setOnline(true);
|
||||
} else if (navigator.onLine === false) {
|
||||
window.clearTimeout(timer);
|
||||
timer = undefined;
|
||||
setOnline(false);
|
||||
} else if (timer === undefined) {
|
||||
timer = window.setTimeout(() => setOnline(false), SERVER_OFFLINE_GRACE_MS);
|
||||
}
|
||||
};
|
||||
const unsubscribe = onRealtimeStatus((isConnected) => {
|
||||
connected = isConnected;
|
||||
update();
|
||||
});
|
||||
window.addEventListener('online', update);
|
||||
window.addEventListener('offline', update);
|
||||
return () => {
|
||||
unsubscribe();
|
||||
window.clearTimeout(timer);
|
||||
window.removeEventListener('online', update);
|
||||
window.removeEventListener('offline', update);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return online;
|
||||
}
|
||||
Reference in new issue
Block a user