mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
add identity to socket auth hopefully will fix a lot of probem
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// Hook: useUserIdentitySync
|
||||
// Purpose: Keeps local identity state synchronized with server session/auth updates. Scope: Handles identity hydration, change propagation, and persistence touch points.
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useSessionActions, useSessionSelector } from '../context/SessionContext.jsx';
|
||||
import { useSocket } from '../context/SocketContext.jsx';
|
||||
import { getBrowserFingerprintId } from '../lib/browserFingerprint.js';
|
||||
@@ -9,6 +9,7 @@ import { useSettingsNamespace } from '../settings/index.js';
|
||||
export default function useUserIdentitySync({ identitySurface = 'passive' } = {}) {
|
||||
const socket = useSocket();
|
||||
const connected = useSessionSelector((state) => state.connected);
|
||||
const serverCookieUserId = useSessionSelector((state) => state.session?.identity?.cookieUserId || '');
|
||||
const { identifySession } = useSessionActions();
|
||||
const { value: identity, status: identityStatus, save: saveIdentity } = useSettingsNamespace('identity', {
|
||||
cookieUserId: '',
|
||||
@@ -19,9 +20,6 @@ export default function useUserIdentitySync({ identitySurface = 'passive' } = {}
|
||||
{ enabled: false },
|
||||
);
|
||||
|
||||
const lastAckSocketRef = useRef(null);
|
||||
const fingerprintRef = useRef('');
|
||||
|
||||
const ready =
|
||||
identityStatus === 'ready' && profileStatus === 'ready' && overseerPreferenceStatus === 'ready';
|
||||
const cookieUserId = (identity?.cookieUserId || '').trim();
|
||||
@@ -32,23 +30,15 @@ export default function useUserIdentitySync({ identitySurface = 'passive' } = {}
|
||||
const sendIdentify = useCallback(async () => {
|
||||
if (!ready || !connected || !socket?.id) return;
|
||||
try {
|
||||
if (!fingerprintRef.current) {
|
||||
/*
|
||||
The portable cookie key is still the cross-device identity signal.
|
||||
Thumbmark adds a same-device signal that survives cookie clearing, so
|
||||
both are sent together whenever the heartbeat identifies this socket.
|
||||
*/
|
||||
fingerprintRef.current = await getBrowserFingerprintId();
|
||||
}
|
||||
/*
|
||||
Every route shares the same persisted identity key, but only the main
|
||||
driver page should trigger duplicate-tab prevention. Sending the surface
|
||||
with the heartbeat lets the server make that decision before spectator
|
||||
pages finish their role switch.
|
||||
Handshake auth establishes identity before connection handlers run.
|
||||
This event remains the live-update path for settings that change while
|
||||
the current transport stays connected, so existing callers and server
|
||||
behavior do not need a second update contract.
|
||||
*/
|
||||
const resp = await identifySession({
|
||||
cookieUserId,
|
||||
fingerprintId: fingerprintRef.current,
|
||||
fingerprintId: await getBrowserFingerprintId(),
|
||||
nickname,
|
||||
overseerEnabled,
|
||||
identitySurface: normalizedIdentitySurface,
|
||||
@@ -57,12 +47,11 @@ export default function useUserIdentitySync({ identitySurface = 'passive' } = {}
|
||||
if (nextKey && nextKey !== cookieUserId) {
|
||||
saveIdentity((current) => ({ ...(current || {}), cookieUserId: nextKey }));
|
||||
}
|
||||
lastAckSocketRef.current = socket.id;
|
||||
} catch {
|
||||
/*
|
||||
The permanent heartbeat below is the retry mechanism. A failed or
|
||||
half-open request must not create separate timer state that can stop
|
||||
future identity sends or disappear during a socket transition.
|
||||
A failed live update must not replace Socket.IO's connection lifecycle
|
||||
with custom retry state. The next reconnect reads the latest persisted
|
||||
settings through handshake auth and re-establishes the complete identity.
|
||||
*/
|
||||
}
|
||||
}, [
|
||||
@@ -78,46 +67,25 @@ export default function useUserIdentitySync({ identitySurface = 'passive' } = {}
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!ready || !connected || !socket?.id) return;
|
||||
if (lastAckSocketRef.current === socket.id) return;
|
||||
sendIdentify();
|
||||
}, [connected, ready, sendIdentify, socket?.id]);
|
||||
|
||||
useEffect(() => {
|
||||
/*
|
||||
This runs once when the route's settings become ready and again only when
|
||||
an identity value changes. Reconnects receive the same data from the auth
|
||||
callback, so there is intentionally no timer, visibility retry, or online
|
||||
retry here.
|
||||
*/
|
||||
if (!ready || !connected || !socket?.id) return;
|
||||
sendIdentify();
|
||||
}, [ready, connected, socket?.id, cookieUserId, nickname, overseerEnabled, normalizedIdentitySurface, sendIdentify]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleOnline = () => {
|
||||
if (!socket?.connected) return;
|
||||
sendIdentify();
|
||||
};
|
||||
const handleVisibility = () => {
|
||||
if (typeof document === 'undefined' || document.visibilityState !== 'visible') return;
|
||||
if (!socket?.connected) return;
|
||||
sendIdentify();
|
||||
};
|
||||
window.addEventListener('online', handleOnline);
|
||||
document.addEventListener('visibilitychange', handleVisibility);
|
||||
return () => {
|
||||
window.removeEventListener('online', handleOnline);
|
||||
document.removeEventListener('visibilitychange', handleVisibility);
|
||||
};
|
||||
}, [sendIdentify, socket?.connected]);
|
||||
|
||||
useEffect(() => {
|
||||
/*
|
||||
Keep this interval installed whenever persisted identity settings are
|
||||
ready, including while Socket.IO is reconnecting. Each tick checks the
|
||||
current connection before sending, so reconnects resume heartbeats without
|
||||
depending on an acknowledgement or another effect recreating the timer.
|
||||
A first-time browser has no portable key to send in its handshake, so the
|
||||
canonical identity service creates one. Session sync is authoritative for
|
||||
that generated value; persisting it here makes every later handshake carry
|
||||
the same user key without depending on a session:identify acknowledgement.
|
||||
*/
|
||||
if (!ready) return undefined;
|
||||
const timer = setInterval(() => {
|
||||
if (!socket?.connected) return;
|
||||
sendIdentify();
|
||||
}, 2000);
|
||||
return () => clearInterval(timer);
|
||||
}, [ready, sendIdentify, socket]);
|
||||
const nextKey = String(serverCookieUserId || '').trim();
|
||||
if (!nextKey || nextKey === cookieUserId) return;
|
||||
saveIdentity((current) => ({ ...(current || {}), cookieUserId: nextKey }));
|
||||
}, [cookieUserId, saveIdentity, serverCookieUserId]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user