mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-08 22:02:54 +00:00
Refactor DM loading to be opportunistic and serialize notification updates
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
d639d0f2df
commit
77cd03b2f7
2 files changed
+146
-116
No files matched your search
@@ -39,6 +39,7 @@ export class DmNotificationManager {
|
||||
constructor({ logger } = {}) {
|
||||
this.logger = logger || userLogger;
|
||||
this.conversationCache = new Map();
|
||||
this.updateQueue = new Map();
|
||||
this.focusedConversationId = "";
|
||||
}
|
||||
|
||||
@@ -46,8 +47,24 @@ export class DmNotificationManager {
|
||||
return this.focusedConversationId;
|
||||
}
|
||||
|
||||
enqueueUpdate(conversationId, task) {
|
||||
const key = conversationId || "global";
|
||||
const previous = this.updateQueue.get(key) || Promise.resolve();
|
||||
const next = previous
|
||||
.then(() => task())
|
||||
.catch((error) => {
|
||||
this.logger.warn(
|
||||
`[dmNotifications] Update task failed for ${key}:`,
|
||||
error,
|
||||
);
|
||||
});
|
||||
this.updateQueue.set(key, next);
|
||||
return next;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.conversationCache.clear();
|
||||
this.updateQueue.clear();
|
||||
this.focusedConversationId = "";
|
||||
}
|
||||
|
||||
@@ -97,9 +114,9 @@ export class DmNotificationManager {
|
||||
}
|
||||
}
|
||||
|
||||
async recordMessage({ record, preview = "", direction = "" } = {}) {
|
||||
recordMessage({ record, preview = "", direction = "" } = {}) {
|
||||
if (!record || typeof record !== "object") {
|
||||
return null;
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const conversationId =
|
||||
@@ -107,84 +124,89 @@ export class DmNotificationManager {
|
||||
? record.conversation_id.trim()
|
||||
: "";
|
||||
if (!conversationId) {
|
||||
return null;
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const createdAt = sanitizeTimestamp(record.created_at);
|
||||
const conversationState = await this.ensureConversationState(conversationId);
|
||||
if (!conversationState) {
|
||||
return null;
|
||||
}
|
||||
return this.enqueueUpdate(conversationId, async () => {
|
||||
const createdAt = sanitizeTimestamp(record.created_at);
|
||||
const conversationState = await this.ensureConversationState(conversationId);
|
||||
if (!conversationState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isIncoming = direction === "incoming";
|
||||
const isFocused = this.focusedConversationId === conversationId;
|
||||
const shouldNotify =
|
||||
isIncoming && !isFocused && createdAt > conversationState.opened_until;
|
||||
const unseenDelta =
|
||||
isIncoming && createdAt > conversationState.opened_until ? 1 : 0;
|
||||
const isIncoming = direction === "incoming";
|
||||
const isFocused = this.focusedConversationId === conversationId;
|
||||
const shouldNotify =
|
||||
isIncoming && !isFocused && createdAt > conversationState.opened_until;
|
||||
const unseenDelta =
|
||||
isIncoming && createdAt > conversationState.opened_until ? 1 : 0;
|
||||
|
||||
let updated = null;
|
||||
try {
|
||||
updated = await updateConversationFromMessage(record, {
|
||||
preview,
|
||||
unseenDelta,
|
||||
downloadedUntil: createdAt,
|
||||
let updated = null;
|
||||
try {
|
||||
updated = await updateConversationFromMessage(record, {
|
||||
preview,
|
||||
unseenDelta,
|
||||
downloadedUntil: createdAt,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.warn("[dmNotifications] Failed to update conversation", error);
|
||||
}
|
||||
|
||||
const normalizedUpdate = normalizeConversationState({
|
||||
conversation_id: conversationId,
|
||||
...(updated || conversationState),
|
||||
opened_until: updated?.opened_until ?? conversationState.opened_until,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.warn("[dmNotifications] Failed to update conversation", error);
|
||||
}
|
||||
|
||||
const normalizedUpdate = normalizeConversationState({
|
||||
conversation_id: conversationId,
|
||||
...updated,
|
||||
opened_until: conversationState.opened_until,
|
||||
this.conversationCache.set(conversationId, normalizedUpdate);
|
||||
|
||||
return {
|
||||
conversation: normalizedUpdate,
|
||||
shouldNotify,
|
||||
isFocused,
|
||||
};
|
||||
});
|
||||
|
||||
this.conversationCache.set(conversationId, normalizedUpdate);
|
||||
|
||||
return {
|
||||
conversation: normalizedUpdate,
|
||||
shouldNotify,
|
||||
isFocused,
|
||||
};
|
||||
}
|
||||
|
||||
async acknowledgeRenderedMessages({ conversationId, renderedUntil } = {}) {
|
||||
acknowledgeRenderedMessages({ conversationId, renderedUntil } = {}) {
|
||||
if (typeof conversationId !== "string" || !conversationId.trim()) {
|
||||
return null;
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const normalized = conversationId.trim();
|
||||
const conversationState = await this.ensureConversationState(normalized);
|
||||
if (!conversationState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nextOpenedUntil = Math.max(
|
||||
conversationState.opened_until || 0,
|
||||
sanitizeTimestamp(renderedUntil),
|
||||
);
|
||||
return this.enqueueUpdate(normalized, async () => {
|
||||
const conversationState = await this.ensureConversationState(normalized);
|
||||
if (!conversationState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let updated = null;
|
||||
try {
|
||||
updated = await updateConversationOpenState(normalized, {
|
||||
openedUntil: nextOpenedUntil,
|
||||
unseenCount: 0,
|
||||
const nextOpenedUntil = Math.max(
|
||||
conversationState.opened_until || 0,
|
||||
sanitizeTimestamp(renderedUntil),
|
||||
);
|
||||
|
||||
let updated = null;
|
||||
try {
|
||||
updated = await updateConversationOpenState(normalized, {
|
||||
openedUntil: nextOpenedUntil,
|
||||
unseenCount: 0,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.warn("[dmNotifications] Failed to update opened_until", error);
|
||||
}
|
||||
|
||||
const normalizedUpdate = normalizeConversationState({
|
||||
conversation_id: normalized,
|
||||
...conversationState,
|
||||
...updated,
|
||||
opened_until: nextOpenedUntil,
|
||||
unseen_count: 0,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.warn("[dmNotifications] Failed to update opened_until", error);
|
||||
}
|
||||
|
||||
const normalizedUpdate = normalizeConversationState({
|
||||
conversation_id: normalized,
|
||||
...conversationState,
|
||||
...updated,
|
||||
opened_until: nextOpenedUntil,
|
||||
unseen_count: 0,
|
||||
this.conversationCache.set(normalized, normalizedUpdate);
|
||||
return normalizedUpdate;
|
||||
});
|
||||
|
||||
this.conversationCache.set(normalized, normalizedUpdate);
|
||||
return normalizedUpdate;
|
||||
}
|
||||
|
||||
async listConversationSummaries() {
|
||||
|
||||
Reference in new issue
Block a user