mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 08:46:22 +02:00
fix: update baseline logic in useDocuments and useInbox hooks to accurately track new items and unread counts, addressing timing issues with Electric updates
This commit is contained in:
parent
1a688c7161
commit
3e4db20bcb
3 changed files with 41 additions and 17 deletions
|
|
@ -351,12 +351,14 @@ export function useDocuments(
|
||||||
const liveIds = new Set(validItems.map((d) => d.id));
|
const liveIds = new Set(validItems.map((d) => d.id));
|
||||||
const prevIds = new Set(prev.map((d) => d.id));
|
const prevIds = new Set(prev.map((d) => d.id));
|
||||||
|
|
||||||
// First callback: snapshot all Electric IDs as the baseline.
|
// Only baseline items already rendered from API.
|
||||||
// Everything in this set existed before the sidebar opened and
|
// Items in Electric but NOT in prev are genuinely new
|
||||||
// should only appear via API pagination, not Electric.
|
// (created between the API fetch and Electric's first callback).
|
||||||
if (electricBaselineIdsRef.current === null) {
|
if (electricBaselineIdsRef.current === null) {
|
||||||
electricBaselineIdsRef.current = new Set(liveIds);
|
electricBaselineIdsRef.current = new Set(
|
||||||
}
|
[...liveIds].filter((id) => prevIds.has(id))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Genuinely new = not in rendered list, not in baseline snapshot.
|
// Genuinely new = not in rendered list, not in baseline snapshot.
|
||||||
// These are docs created AFTER the sidebar opened.
|
// These are docs created AFTER the sidebar opened.
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,11 @@ export function useInbox(
|
||||||
const prevIds = new Set(prev.map((d) => d.id));
|
const prevIds = new Set(prev.map((d) => d.id));
|
||||||
|
|
||||||
if (electricBaselineIdsRef.current === null) {
|
if (electricBaselineIdsRef.current === null) {
|
||||||
electricBaselineIdsRef.current = new Set(liveIds);
|
// Only baseline items already rendered from API.
|
||||||
|
// Items in Electric but NOT in prev are genuinely new.
|
||||||
|
electricBaselineIdsRef.current = new Set(
|
||||||
|
[...liveIds].filter((id) => prevIds.has(id))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseline = electricBaselineIdsRef.current;
|
const baseline = electricBaselineIdsRef.current;
|
||||||
|
|
@ -237,11 +241,35 @@ export function useInbox(
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Calibrate the older-unread offset using baseline items
|
||||||
|
// (items present in both Electric and the API-loaded list).
|
||||||
|
// This avoids the timing bug where new items arriving between
|
||||||
|
// the API fetch and Electric's first callback would be absorbed
|
||||||
|
// into the offset, making the count appear unchanged.
|
||||||
|
const baseline = electricBaselineIdsRef.current;
|
||||||
|
if (olderUnreadOffsetRef.current === null && baseline !== null) {
|
||||||
|
const baselineUnreadCount = validItems.filter(
|
||||||
|
(item) => baseline.has(item.id) && !item.read
|
||||||
|
).length;
|
||||||
|
olderUnreadOffsetRef.current = Math.max(
|
||||||
|
0,
|
||||||
|
apiUnreadTotalRef.current - baselineUnreadCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derive unread count from all Electric items + the older offset
|
||||||
|
if (olderUnreadOffsetRef.current !== null) {
|
||||||
|
const electricUnreadCount = validItems.filter((item) => !item.read).length;
|
||||||
|
setUnreadCount(olderUnreadOffsetRef.current + electricUnreadCount);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
liveQueryRef.current = liveQuery;
|
liveQueryRef.current = liveQuery;
|
||||||
|
|
||||||
// Per-instance unread count live query filtered by category types
|
// Per-instance unread count live query filtered by category types.
|
||||||
|
// Acts as a secondary reactive path for read-status changes that
|
||||||
|
// may not trigger the items live query in all edge cases.
|
||||||
const countQuery = `SELECT COUNT(*) as count FROM notifications
|
const countQuery = `SELECT COUNT(*) as count FROM notifications
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1
|
||||||
AND (search_space_id = $2 OR search_space_id IS NULL)
|
AND (search_space_id = $2 OR search_space_id IS NULL)
|
||||||
|
|
@ -258,15 +286,8 @@ export function useInbox(
|
||||||
|
|
||||||
countLiveQuery.subscribe((result: { rows: Array<{ count: number | string }> }) => {
|
countLiveQuery.subscribe((result: { rows: Array<{ count: number | string }> }) => {
|
||||||
if (!mounted || !result.rows?.[0] || !initialLoadDoneRef.current) return;
|
if (!mounted || !result.rows?.[0] || !initialLoadDoneRef.current) return;
|
||||||
|
if (olderUnreadOffsetRef.current === null) return;
|
||||||
const liveRecentUnread = Number(result.rows[0].count) || 0;
|
const liveRecentUnread = Number(result.rows[0].count) || 0;
|
||||||
|
|
||||||
if (olderUnreadOffsetRef.current === null) {
|
|
||||||
olderUnreadOffsetRef.current = Math.max(
|
|
||||||
0,
|
|
||||||
apiUnreadTotalRef.current - liveRecentUnread
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
setUnreadCount(olderUnreadOffsetRef.current + liveRecentUnread);
|
setUnreadCount(olderUnreadOffsetRef.current + liveRecentUnread);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ const pendingSyncs = new Map<string, Promise<SyncHandle>>();
|
||||||
// real-time documents table with title/created_by_id/status columns,
|
// real-time documents table with title/created_by_id/status columns,
|
||||||
// consolidated single documents sync, pending state for document queue visibility
|
// consolidated single documents sync, pending state for document queue visibility
|
||||||
// v6: added enable_summary column to search_source_connectors
|
// v6: added enable_summary column to search_source_connectors
|
||||||
const SYNC_VERSION = 6;
|
// v7: fixed connector-popup using invalid category for useInbox
|
||||||
|
const SYNC_VERSION = 7;
|
||||||
|
|
||||||
// Database name prefix for identifying SurfSense databases
|
// Database name prefix for identifying SurfSense databases
|
||||||
const DB_PREFIX = "surfsense-";
|
const DB_PREFIX = "surfsense-";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue