make event store class award of replaceable events

This commit is contained in:
hzrd149
2023-10-12 11:44:36 -05:00
parent 5b8ff3eab7
commit bfc28c097b
4 changed files with 39 additions and 11 deletions

View File

@@ -1,5 +1,6 @@
import { getEventUID } from "../helpers/nostr/events"; import { getEventUID, isReplaceable } from "../helpers/nostr/events";
import { NostrEvent } from "../types/nostr-event"; import replaceableEventLoaderService from "../services/replaceable-event-requester";
import { NostrEvent, isDTag } from "../types/nostr-event";
import Subject from "./subject"; import Subject from "./subject";
export type EventFilter = (event: NostrEvent, store: EventStore) => boolean; export type EventFilter = (event: NostrEvent, store: EventStore) => boolean;
@@ -20,7 +21,8 @@ export default class EventStore {
onDelete = new Subject<string>(undefined, false); onDelete = new Subject<string>(undefined, false);
onClear = new Subject(undefined, false); onClear = new Subject(undefined, false);
addEvent(event: NostrEvent) { private replaceableEventSubs = new Map<string, Subject<NostrEvent>>();
private handleEvent(event: NostrEvent) {
const id = getEventUID(event); const id = getEventUID(event);
const existing = this.events.get(id); const existing = this.events.get(id);
if (!existing || event.created_at > existing.created_at) { if (!existing || event.created_at > existing.created_at) {
@@ -28,6 +30,21 @@ export default class EventStore {
this.onEvent.next(event); this.onEvent.next(event);
} }
} }
addEvent(event: NostrEvent) {
const id = getEventUID(event);
this.handleEvent(event);
if (isReplaceable(event.kind)) {
// pass the event on
replaceableEventLoaderService.handleEvent(event);
// subscribe to any future changes
const sub = replaceableEventLoaderService.getEvent(event.kind, event.pubkey, event.tags.find(isDTag)?.[1]);
sub.subscribe(this.handleEvent, this);
this.replaceableEventSubs.set(id, sub);
}
}
getEvent(id: string) { getEvent(id: string) {
return this.events.get(id); return this.events.get(id);
} }
@@ -36,11 +53,23 @@ export default class EventStore {
this.events.delete(id); this.events.delete(id);
this.onDelete.next(id); this.onDelete.next(id);
} }
if (this.replaceableEventSubs.has(id)) {
this.replaceableEventSubs.get(id)?.unsubscribe(this.handleEvent, this);
this.replaceableEventSubs.delete(id);
}
} }
clear() { clear() {
this.events.clear(); this.events.clear();
this.onClear.next(undefined); this.onClear.next(undefined);
for (const [_, sub] of this.replaceableEventSubs) {
sub.unsubscribe(this.handleEvent, this);
}
}
cleanup() {
this.clear();
} }
connect(other: EventStore) { connect(other: EventStore) {

View File

@@ -278,6 +278,7 @@ export default class TimelineLoader {
cleanup() { cleanup() {
this.close(); this.close();
this.removeLoaders(); this.removeLoaders();
this.events.cleanup();
deleteEventService.stream.unsubscribe(this.handleDeleteEvent, this); deleteEventService.stream.unsubscribe(this.handleDeleteEvent, this);
} }

View File

@@ -37,7 +37,7 @@ export default function NoteZapButton({ event, allowComment, showEventPreview, .
<> <>
{total > 0 ? ( {total > 0 ? (
<Button <Button
leftIcon={<LightningIcon />} leftIcon={<LightningIcon verticalAlign="sub" />}
aria-label="Zap Note" aria-label="Zap Note"
title="Zap Note" title="Zap Note"
colorScheme={hasZapped ? "primary" : undefined} colorScheme={hasZapped ? "primary" : undefined}
@@ -49,7 +49,7 @@ export default function NoteZapButton({ event, allowComment, showEventPreview, .
</Button> </Button>
) : ( ) : (
<IconButton <IconButton
icon={<LightningIcon />} icon={<LightningIcon verticalAlign="sub" />}
aria-label="Zap Note" aria-label="Zap Note"
title="Zap Note" title="Zap Note"
{...props} {...props}

View File

@@ -1,12 +1,10 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import { Kind, nip19 } from "nostr-tools"; import { nip19 } from "nostr-tools";
import { getEventRelays } from "../../services/event-relays"; import { ATag, DraftNostrEvent, isDTag, isETag, isPTag, NostrEvent, RTag, Tag } from "../../types/nostr-event";
import { ATag, DraftNostrEvent, ETag, isETag, isPTag, NostrEvent, RTag, Tag } from "../../types/nostr-event";
import { RelayConfig, RelayMode } from "../../classes/relay"; import { RelayConfig, RelayMode } from "../../classes/relay";
import { getMatchNostrLink } from "../regexp"; import { getMatchNostrLink } from "../regexp";
import relayScoreboardService from "../../services/relay-scoreboard"; import type { AddressPointer } from "nostr-tools/lib/nip19";
import type { AddressPointer, EventPointer } from "nostr-tools/lib/nip19";
export function truncatedId(str: string, keep = 6) { export function truncatedId(str: string, keep = 6) {
if (str.length < keep * 2 + 3) return str; if (str.length < keep * 2 + 3) return str;
@@ -150,7 +148,7 @@ export function parseRTag(tag: RTag): RelayConfig {
} }
export function getEventCoordinate(event: NostrEvent) { export function getEventCoordinate(event: NostrEvent) {
const d = event.tags.find((t) => t[0] === "d")?.[1]; const d = event.tags.find(isDTag)?.[1];
return d ? `${event.kind}:${event.pubkey}:${d}` : `${event.kind}:${event.pubkey}`; return d ? `${event.kind}:${event.pubkey}:${d}` : `${event.kind}:${event.pubkey}`;
} }
export function pointerToATag(pointer: AddressPointer): ATag { export function pointerToATag(pointer: AddressPointer): ATag {