@towns-protocol/sdk
Version:
For more details, visit the following resources:
107 lines • 4.41 kB
JavaScript
import { Observable } from '../../observable/observable';
import { RiverTimelineEvent } from '../models/timelineTypes';
import { makeTimelinesViewInterface, } from './timelinesModel';
import { toDecryptedContentErrorEvent, toDecryptedEvent, toEvent } from '../models/timelineEvent';
import { isEqual } from 'lodash-es';
import { isDMChannelStreamId } from '../../id';
export class TimelinesView extends Observable {
userId;
delegate;
eventFilter;
streamIds = new Set();
setState;
// todo invert this so we don't have to pass the whole client
constructor(userId, delegate, eventFilter = new Set([
RiverTimelineEvent.Fulfillment,
RiverTimelineEvent.KeySolicitation,
])) {
super({
timelines: {},
replacedEvents: {},
pendingReplacedEvents: {},
threadsStats: {},
threads: {},
reactions: {},
tips: {},
lastestEventByUser: {},
});
this.userId = userId;
this.delegate = delegate;
this.eventFilter = eventFilter;
this.setState = makeTimelinesViewInterface((fn) => {
this.setValue(fn(this.value));
});
}
streamInitialized(streamId, messages) {
this.streamIds.add(streamId);
const timelineEvents = messages
.map((event) => toEvent(event, this.userId))
.filter((event) => this.filterFn(streamId, event));
this.setState.appendEvents(timelineEvents, this.userId, streamId, 'initializeStream');
}
streamUpdated(streamId, change) {
const { prepended, appended, updated, confirmed } = change;
this.streamIds.add(streamId);
if (prepended) {
const events = prepended
.map((event) => toEvent(event, this.userId))
.filter((event) => this.filterFn(streamId, event));
this.setState.prependEvents(events, this.userId, streamId);
}
if (appended) {
const events = appended
.map((event) => toEvent(event, this.userId))
.filter((event) => this.filterFn(streamId, event));
this.setState.appendEvents(events, this.userId, streamId);
}
if (updated) {
const events = updated
.map((event) => toEvent(event, this.userId))
.filter((event) => this.filterFn(streamId, event));
this.setState.updateEvents(events, this.userId, streamId);
}
if (confirmed) {
const confirmations = confirmed.map((event) => ({
eventId: event.hashStr,
confirmedInBlockNum: event.miniblockNum,
confirmedEventNum: event.confirmedEventNum,
}));
this.setState.confirmEvents(confirmations, streamId);
}
}
streamEventDecrypted(streamId, eventId, decryptedContent) {
const prevEvent = this.value.timelines[streamId].find((event) => event.eventId === eventId);
if (prevEvent) {
const newEvent = toDecryptedEvent(prevEvent, decryptedContent, this.userId);
if (!isEqual(newEvent, prevEvent)) {
this.setState.updateEvent(newEvent, this.userId, streamId, eventId);
}
return newEvent;
}
return undefined;
}
streamEventDecryptedContentError(streamId, eventId, error) {
const prevEvent = this.value.timelines[streamId].find((event) => event.eventId === eventId);
if (prevEvent) {
const newEvent = toDecryptedContentErrorEvent(prevEvent, error);
if (newEvent !== prevEvent) {
this.setState.updateEvent(newEvent, this.userId, streamId, eventId);
}
}
}
streamLocalEventUpdated(streamId, localEventId, localEvent) {
this.streamIds.add(streamId);
const event = toEvent(localEvent, this.userId);
if (this.filterFn(streamId, event)) {
this.setState.updateEvent(event, this.userId, streamId, localEventId);
}
}
filterFn(streamId, event) {
if (isDMChannelStreamId(streamId) &&
this.delegate?.isDMMessageEventBlocked(event) === true) {
return false;
}
return (!this.eventFilter || !event.content?.kind || !this.eventFilter.has(event.content.kind));
}
}
//# sourceMappingURL=timelines.js.map