aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
Diffstat (limited to 'src/features')
-rw-r--r--src/features/messages.js18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index e812520..cb63e04 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -545,7 +545,9 @@ export function messagesFeature(ctx) {
// least recently seen faces give theirs up first. The row itself stays —
// that face just paints the way it used to.
if (JSON.stringify(s).length > THUMB_BUDGET) {
- const oldestFirst = Object.keys(s).filter((k) => s[k].thumb).sort((a, b) => (s[a].t || 0) - (s[b].t || 0));
+ // never our own: the header face is the one that must paint offline
+ const mine = new Set(myPubkeys());
+ const oldestFirst = Object.keys(s).filter((k) => s[k].thumb && !mine.has(k)).sort((a, b) => (s[a].t || 0) - (s[b].t || 0));
for (const k of oldestFirst) {
delete s[k].thumb; delete s[k].thumbFor;
if (JSON.stringify(s).length <= THUMB_BUDGET) break;
@@ -648,7 +650,7 @@ export function messagesFeature(ctx) {
// won't have us is asked about twice a month rather than every boot.
if (p.thumbFailVersion === THUMB_VERSION && p.thumbFail === p.picture
&& Date.now() - (p.thumbFailAt || 0) < Math.min(THUMB_RETRY * 2 ** ((p.thumbFails || 1) - 1), THUMB_RETRY_MAX)) return;
- if (thumbing.has(pk) || thumbing.size >= 3) return; // a few at a time
+ if (thumbing.has(pk) || (thumbing.size >= 3 && !isMe(pk))) return; // a few at a time — our own face never waits
// Making the thumbnail costs one more fetch of the original today to
// save every fetch after it — but not on a connection someone is
// nursing. Data Saver keeps today's behaviour.
@@ -1128,11 +1130,13 @@ export function messagesFeature(ctx) {
msgs.set(rumor.id, { rumor, author });
bumpMsgRev();
room.typing.delete(author); // the message itself ends the "typing…"
+ schedulePersist(room);
} else if (rumor.kind === 5) {
for (const e of rumor.tags.filter((x) => x[0] === 'e')) {
const m = room.byChannel.get(channelId)?.get(e[1]);
if (!m || m.author === author) room.deletes.add(e[1]);
}
+ schedulePersist(room);
} else if (rumor.kind === 3302) {
const target = tag('e')?.[1];
if (target) {
@@ -1162,6 +1166,16 @@ export function messagesFeature(ctx) {
return room.jm.channels || [];
};
+ // Messages that ARRIVE get cached too, not only ones we send: the cache
+ // used to be written on our own actions alone, so a member who only reads
+ // had nothing on an offline boot — the room said "No messages yet" with a
+ // hundred messages read the day before. A backfill lands in a burst, so
+ // the write waits for it to settle.
+ const persistTimers = new Map(); // room -> timer
+ function schedulePersist(room) {
+ clearTimeout(persistTimers.get(room));
+ persistTimers.set(room, setTimeout(() => { persistTimers.delete(room); try { persistCache(room); } catch {} }, 2500));
+ }
function persistCache(room) {
const s = st();
for (const [chId, msgs] of room.byChannel) {