new notifications design
This commit is contained in:
39
packages/app/src/Cache/Notifications.ts
Normal file
39
packages/app/src/Cache/Notifications.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { EventKind, NostrEvent, RequestBuilder, TaggedRawEvent } from "@snort/system";
|
||||
import { RefreshFeedCache, TWithCreated } from "./RefreshFeedCache";
|
||||
import { LoginSession } from "Login";
|
||||
import { unixNow } from "SnortUtils";
|
||||
import { db } from "Db";
|
||||
|
||||
export class NotificationsCache extends RefreshFeedCache<NostrEvent> {
|
||||
#kinds = [EventKind.TextNote, EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt];
|
||||
|
||||
constructor() {
|
||||
super("notifications", db.notifications);
|
||||
}
|
||||
|
||||
buildSub(session: LoginSession, rb: RequestBuilder) {
|
||||
if (session.publicKey) {
|
||||
const newest = this.newest();
|
||||
rb.withFilter()
|
||||
.kinds(this.#kinds)
|
||||
.tag("p", [session.publicKey])
|
||||
.since(newest === 0 ? unixNow() - 60 * 60 * 24 * 30 : newest);
|
||||
}
|
||||
}
|
||||
|
||||
async onEvent(evs: readonly TaggedRawEvent[]) {
|
||||
const filtered = evs.filter(a => this.#kinds.includes(a.kind) && a.tags.some(b => b[0] === "p"));
|
||||
if (filtered.length > 0) {
|
||||
await this.bulkSet(filtered);
|
||||
this.notifyChange(filtered.map(v => this.key(v)));
|
||||
}
|
||||
}
|
||||
|
||||
key(of: TWithCreated<NostrEvent>): string {
|
||||
return of.id;
|
||||
}
|
||||
|
||||
takeSnapshot(): TWithCreated<NostrEvent>[] {
|
||||
return [...this.cache.values()];
|
||||
}
|
||||
}
|
25
packages/app/src/Cache/RefreshFeedCache.ts
Normal file
25
packages/app/src/Cache/RefreshFeedCache.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { FeedCache } from "@snort/shared";
|
||||
import { RequestBuilder, TaggedRawEvent } from "@snort/system";
|
||||
import { LoginSession } from "Login";
|
||||
|
||||
export type TWithCreated<T> = T & { created_at: number };
|
||||
|
||||
export abstract class RefreshFeedCache<T> extends FeedCache<TWithCreated<T>> {
|
||||
abstract buildSub(session: LoginSession, rb: RequestBuilder): void;
|
||||
abstract onEvent(evs: Readonly<Array<TaggedRawEvent>>): void;
|
||||
|
||||
/**
|
||||
* Get latest event
|
||||
*/
|
||||
protected newest() {
|
||||
let ret = 0;
|
||||
this.cache.forEach(v => (ret = v.created_at > ret ? v.created_at : ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
override async preload(): Promise<void> {
|
||||
await super.preload();
|
||||
// load all dms to memory
|
||||
await this.buffer([...this.onTable]);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import { EventInteractionCache } from "./EventInteractionCache";
|
||||
import { ChatCache } from "./ChatCache";
|
||||
import { Payments } from "./PaymentsCache";
|
||||
import { GiftWrapCache } from "./GiftWrapCache";
|
||||
import { NotificationsCache } from "./Notifications";
|
||||
|
||||
export const UserCache = new UserProfileCache();
|
||||
export const UserRelays = new UserRelaysCache();
|
||||
@ -11,6 +12,7 @@ export const Chats = new ChatCache();
|
||||
export const PaymentsCache = new Payments();
|
||||
export const InteractionCache = new EventInteractionCache();
|
||||
export const GiftsCache = new GiftWrapCache();
|
||||
export const Notifications = new NotificationsCache();
|
||||
|
||||
export async function preload(follows?: Array<string>) {
|
||||
const preloads = [
|
||||
@ -20,6 +22,7 @@ export async function preload(follows?: Array<string>) {
|
||||
UserRelays.preload(follows),
|
||||
RelayMetrics.preload(),
|
||||
GiftsCache.preload(),
|
||||
Notifications.preload(),
|
||||
];
|
||||
await Promise.all(preloads);
|
||||
}
|
||||
|
Reference in New Issue
Block a user