feat: improve voice recording UX and realtime state reconciliation
All checks were successful
CI / test (push) Successful in 20s
All checks were successful
CI / test (push) Successful in 20s
This commit is contained in:
@@ -25,6 +25,7 @@ export function useRealtime() {
|
||||
const manualCloseRef = useRef(false);
|
||||
const notificationPermissionRequestedRef = useRef(false);
|
||||
const reloadChatsTimerRef = useRef<number | null>(null);
|
||||
const reconcileIntervalRef = useRef<number | null>(null);
|
||||
|
||||
const wsUrl = useMemo(() => {
|
||||
return accessToken ? buildWsUrl(accessToken) : null;
|
||||
@@ -66,11 +67,7 @@ export function useRealtime() {
|
||||
ws.close();
|
||||
}
|
||||
}, 15000);
|
||||
const store = useChatStore.getState();
|
||||
void store.loadChats();
|
||||
if (store.activeChatId) {
|
||||
void store.loadMessages(store.activeChatId);
|
||||
}
|
||||
void reconcileState();
|
||||
if ("Notification" in window && Notification.permission === "default" && !notificationPermissionRequestedRef.current) {
|
||||
notificationPermissionRequestedRef.current = true;
|
||||
void Notification.requestPermission();
|
||||
@@ -198,6 +195,10 @@ export function useRealtime() {
|
||||
window.clearInterval(watchdogIntervalRef.current);
|
||||
watchdogIntervalRef.current = null;
|
||||
}
|
||||
if (reconcileIntervalRef.current !== null) {
|
||||
window.clearInterval(reconcileIntervalRef.current);
|
||||
reconcileIntervalRef.current = null;
|
||||
}
|
||||
if (manualCloseRef.current) {
|
||||
return;
|
||||
}
|
||||
@@ -209,9 +210,24 @@ export function useRealtime() {
|
||||
ws.onerror = () => {
|
||||
ws.close();
|
||||
};
|
||||
|
||||
if (reconcileIntervalRef.current !== null) {
|
||||
window.clearInterval(reconcileIntervalRef.current);
|
||||
}
|
||||
reconcileIntervalRef.current = window.setInterval(() => {
|
||||
void reconcileState();
|
||||
}, 60000);
|
||||
};
|
||||
|
||||
const onFocusOrVisible = () => {
|
||||
if (document.visibilityState === "visible") {
|
||||
void reconcileState();
|
||||
}
|
||||
};
|
||||
|
||||
connect();
|
||||
window.addEventListener("focus", onFocusOrVisible);
|
||||
document.addEventListener("visibilitychange", onFocusOrVisible);
|
||||
|
||||
return () => {
|
||||
manualCloseRef.current = true;
|
||||
@@ -223,6 +239,10 @@ export function useRealtime() {
|
||||
window.clearInterval(watchdogIntervalRef.current);
|
||||
watchdogIntervalRef.current = null;
|
||||
}
|
||||
if (reconcileIntervalRef.current !== null) {
|
||||
window.clearInterval(reconcileIntervalRef.current);
|
||||
reconcileIntervalRef.current = null;
|
||||
}
|
||||
if (reconnectTimeoutRef.current !== null) {
|
||||
window.clearTimeout(reconnectTimeoutRef.current);
|
||||
reconnectTimeoutRef.current = null;
|
||||
@@ -235,9 +255,20 @@ export function useRealtime() {
|
||||
wsRef.current = null;
|
||||
typingByChat.current = {};
|
||||
useChatStore.setState({ typingByChat: {} });
|
||||
window.removeEventListener("focus", onFocusOrVisible);
|
||||
document.removeEventListener("visibilitychange", onFocusOrVisible);
|
||||
};
|
||||
}, [wsUrl, meId]);
|
||||
|
||||
async function reconcileState() {
|
||||
const storeBefore = useChatStore.getState();
|
||||
await storeBefore.loadChats();
|
||||
const storeAfter = useChatStore.getState();
|
||||
if (storeAfter.activeChatId) {
|
||||
await storeAfter.loadMessages(storeAfter.activeChatId);
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleReloadChats() {
|
||||
if (reloadChatsTimerRef.current !== null) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user