fix(web): code review round 2 -- critical session/connection races
- RequireAuth: a page reload lost the session even with a valid token sitting in sessionStorage -- myUserId is never persisted (by design) but nothing ever re-derived it from the reusable login token. Added connection.ts's restoreSession(), which also fixes the race the first attempt at this ran into live: React 19 StrictMode double-invokes the restore effect in dev, and Tinode.loginToken() isn't idempotent (second call on an already-authenticated connection gets 409'd), so both the connect() and the login itself needed module-level in-flight dedup, not just a per-effect cancelled flag - topics.ts: same dedup pattern for openConversation/closeConversation -- StrictMode's mount->cleanup->remount always overlapped an open with itself, and a leave() landing before its own subscribe() resolved was silently no-op'ing instead of detaching - LOGGING_ENABLED was unconditionally on, including prod builds -- Tinode's verbose logging prints the raw login secret and full message content to the console - imPost/imPatch/imPut/imDelete could silently drop the Idempotency-Key header for a caller that passes its own headers (object-spread order bug, dormant today since no call site does this yet) - DetailColumn's getFriends()/getBlocks() only ever read page 1 despite fetchAllPages existing specifically to prevent this bug class - availableActions() now defers to the server's message_policy. supported_actions when present instead of only a client-side time window, and exposes recallRemainingSeconds for the context menu's countdown label Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1bd8d7f804
commit
d3a0eb0dbc
@@ -21,12 +21,19 @@ export interface BootstrapEntry {
|
||||
route: string;
|
||||
topic?: string;
|
||||
unread_count: number;
|
||||
/** e.g. "topic" (file_assistant) vs "business" (system_messages) -- which side actually owns the
|
||||
* unread count above, confirmed live but not consumed by anything yet. */
|
||||
unread_source?: string;
|
||||
}
|
||||
|
||||
export interface BootstrapConfig {
|
||||
message_policy?: MessagePolicy;
|
||||
limits?: { max_forward_targets?: number; [key: string]: unknown };
|
||||
security?: { realname?: RealnameStatus };
|
||||
features?: Record<string, boolean>;
|
||||
permissions?: Record<string, boolean>;
|
||||
modules?: unknown;
|
||||
workbench_version?: unknown;
|
||||
entries?: {
|
||||
new_friends?: BootstrapEntry;
|
||||
groups?: BootstrapEntry;
|
||||
@@ -39,6 +46,7 @@ export interface BootstrapConfig {
|
||||
file_assistant_unread_count?: number;
|
||||
system_unread_count?: number;
|
||||
workbench_total_unread?: number;
|
||||
contacts_total_unread?: number;
|
||||
};
|
||||
system_topic?: { topic: string; type: string };
|
||||
[key: string]: unknown;
|
||||
|
||||
Reference in New Issue
Block a user