diff --git a/db/citizen.js b/db/citizen.js index fa6cf0e6..49bdc671 100644 --- a/db/citizen.js +++ b/db/citizen.js @@ -68,12 +68,14 @@ export class PrivateCitizenDB extends BaseHyperbeeDB { const release = await this.lock(`notifications-idx:${change.url}`) try { + let itemCreatedAt switch (change.keyParsed.schemaId) { case 'ctzn.network/follow': // following me? if (change.value.subject.dbUrl !== myUrl) { return false } + itemCreatedAt = new Date(change.value.createdAt) break case 'ctzn.network/comment': { // self-post reply on my content? @@ -84,6 +86,7 @@ export class PrivateCitizenDB extends BaseHyperbeeDB { || change.value.reply.parent?.dbUrl.startsWith(myUrl) ) if (!onMyPost) return + itemCreatedAt = new Date(change.value.createdAt) break } case 'ctzn.network/vote': @@ -91,12 +94,14 @@ export class PrivateCitizenDB extends BaseHyperbeeDB { if (!change.value.subject.dbUrl.startsWith(myUrl)) { return false } + itemCreatedAt = new Date(change.value.createdAt) break } - await this.notificationsIdx.put(mlts(), { + const createdAt = new Date() + await this.notificationsIdx.put(mlts(Math.min(createdAt, itemCreatedAt || createdAt)), { itemUrl: constructEntryUrl(db.url, change.keyParsed.schemaId, change.keyParsed.key), - createdAt: (new Date()).toISOString() + createdAt: createdAt.toISOString() }) } finally { release() diff --git a/db/community.js b/db/community.js index d82daf35..acfc2d8b 100644 --- a/db/community.js +++ b/db/community.js @@ -47,27 +47,32 @@ export class PublicCommunityDB extends BaseHyperbeeDB { const pend = perf.measure(`publicCommunityDb:notifications-indexer`) const release = await this.lock(`notifications-idx:${change.url}`) - const createKey = url => `${hyperUrlToKeyStr(url)}:${mlts()}` + const createdAt = new Date() const notification = { itemUrl: constructEntryUrl(db.url, change.keyParsed.schemaId, change.keyParsed.key), - createdAt: (new Date()).toISOString() + createdAt: createdAt.toISOString() + } + const createKey = (url, itemCreatedAt) => { + return `${hyperUrlToKeyStr(url)}:${mlts(Math.min(createdAt, itemCreatedAt || createdAt))}` } try { switch (change.keyParsed.schemaId) { case 'ctzn.network/follow': if (change.value.subject.dbUrl !== db.url) { - await this.notificationsIdx.put(createKey(change.value.subject.dbUrl), notification) + let itemCreatedAt = new Date(change.value.createdAt) + await this.notificationsIdx.put(createKey(change.value.subject.dbUrl, itemCreatedAt), notification) } break case 'ctzn.network/comment': { // reply to content in my community? if (!change.value.reply) return // not a reply if (change.value.community?.userId !== this.userId) return // not in our community + let itemCreatedAt = new Date(change.value.createdAt) if (!change.value.reply.root.dbUrl.startsWith(db.url)) { - await this.notificationsIdx.put(createKey(change.value.reply.root.dbUrl), notification) + await this.notificationsIdx.put(createKey(change.value.reply.root.dbUrl, itemCreatedAt), notification) } if (change.value.reply.parent && !change.value.reply.parent.dbUrl.startsWith(db.url)) { - await this.notificationsIdx.put(createKey(change.value.reply.parent.dbUrl), notification) + await this.notificationsIdx.put(createKey(change.value.reply.parent.dbUrl, itemCreatedAt), notification) } break } @@ -85,7 +90,8 @@ export class PublicCommunityDB extends BaseHyperbeeDB { if (subject.entry?.value?.community?.userId !== this.userId) { return // subject is not in our community } - await this.notificationsIdx.put(createKey(change.value.subject.dbUrl), notification) + let itemCreatedAt = new Date(change.value.createdAt) + await this.notificationsIdx.put(createKey(change.value.subject.dbUrl, itemCreatedAt), notification) break } } finally { diff --git a/db/util.js b/db/util.js index 9297e5ee..1b4ba0c1 100644 --- a/db/util.js +++ b/db/util.js @@ -177,7 +177,14 @@ async function fetchNotificationsInner (userInfo, {after, before, limit} = {}) { notificationEntries = notificationEntries.filter((entry, index) => { return notificationEntries.findIndex(entry2 => entry2.value.itemUrl === entry.value.itemUrl) === index }) - notificationEntries.sort((a, b) => b.value.createdAt.localeCompare(a.value.createdAt)) + notificationEntries.sort((a, b) => { + let akey = a.key.includes(':') ? a.key.split(':')[1] : a.key + let bkey = b.key.includes(':') ? b.key.split(':')[1] : b.key + return bkey.localeCompare(akey) + }) + if (notificationEntries.length > limit) { + notificationEntries = notificationEntries.slice(0, limit) + } return notificationEntries }