mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-21 14:09:17 +02:00
slight changes to timeline loader
This commit is contained in:
@@ -72,6 +72,7 @@ I would recomend you use a browser extension like [Alby](https://getalby.com/) o
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
- Update TimelineLoader to connect to each relay individually so it better track the latest events
|
||||||
- Create notifications service that keeps track of read notifications. (show unread count in sidenav)
|
- Create notifications service that keeps track of read notifications. (show unread count in sidenav)
|
||||||
- Rebuild relays view to show relay info and settings NIP-11
|
- Rebuild relays view to show relay info and settings NIP-11
|
||||||
- filter list of followers by users the user has blocked/reported (stops bots/spammers from showing up at followers)
|
- filter list of followers by users the user has blocked/reported (stops bots/spammers from showing up at followers)
|
||||||
@@ -81,8 +82,6 @@ I would recomend you use a browser extension like [Alby](https://getalby.com/) o
|
|||||||
- make app a valid web share target https://developer.chrome.com/articles/web-share-target/
|
- make app a valid web share target https://developer.chrome.com/articles/web-share-target/
|
||||||
- handle image share
|
- handle image share
|
||||||
- implement NIP-56 and blocking
|
- implement NIP-56 and blocking
|
||||||
- allow user to select relay or following list when fetching replies (default to my relays + following?)
|
|
||||||
- massive thread note1dapvuu8fl09yjtg2gyr2h6nypaffl2sq0aj5raz86463qk5kpyzqlxvtc3
|
|
||||||
- Improve link previews https://github.com/pengx17/logseq-plugin-link-preview/blob/master/src/use-link-preview-metadata.tsx
|
- Improve link previews https://github.com/pengx17/logseq-plugin-link-preview/blob/master/src/use-link-preview-metadata.tsx
|
||||||
- Support `magnet:` links
|
- Support `magnet:` links
|
||||||
- in-browser video player? https://webtorrent.io/
|
- in-browser video player? https://webtorrent.io/
|
||||||
|
@@ -3,44 +3,40 @@ import { NostrEvent } from "../types/nostr-event";
|
|||||||
import { NostrQuery } from "../types/nostr-query";
|
import { NostrQuery } from "../types/nostr-query";
|
||||||
import { NostrRequest } from "./nostr-request";
|
import { NostrRequest } from "./nostr-request";
|
||||||
import { NostrMultiSubscription } from "./nostr-multi-subscription";
|
import { NostrMultiSubscription } from "./nostr-multi-subscription";
|
||||||
import Subject, { PersistentSubject } from "./subject";
|
import { PersistentSubject } from "./subject";
|
||||||
|
import { utils } from "nostr-tools";
|
||||||
export type NostrQueryWithStart = NostrQuery & { since: number };
|
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
name?: string;
|
name?: string;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
|
startLimit: number;
|
||||||
};
|
};
|
||||||
export type TimelineLoaderOptions = Partial<Options>;
|
export type TimelineLoaderOptions = Partial<Options>;
|
||||||
|
|
||||||
export class TimelineLoader {
|
export class TimelineLoader {
|
||||||
relays: string[];
|
relays: string[];
|
||||||
query: NostrQueryWithStart;
|
query: NostrQuery;
|
||||||
events = new PersistentSubject<NostrEvent[]>([]);
|
events = new PersistentSubject<NostrEvent[]>([]);
|
||||||
loading = new PersistentSubject(false);
|
loading = new PersistentSubject(false);
|
||||||
page = new PersistentSubject(0);
|
page = new PersistentSubject(0);
|
||||||
|
|
||||||
private eventDir = new Map<string, NostrEvent>();
|
private seenEvents = new Set<string>();
|
||||||
private subscription: NostrMultiSubscription;
|
private subscription: NostrMultiSubscription;
|
||||||
private opts: Options = { pageSize: moment.duration(1, "hour").asSeconds() };
|
private opts: Options = { pageSize: moment.duration(1, "hour").asSeconds(), startLimit: 10 };
|
||||||
|
|
||||||
constructor(relays: string[], query: NostrQueryWithStart, opts?: TimelineLoaderOptions) {
|
|
||||||
if (!query.since) throw new Error('Timeline requires "since" to be set in query');
|
|
||||||
|
|
||||||
|
constructor(relays: string[], query: NostrQuery, opts?: TimelineLoaderOptions) {
|
||||||
this.relays = relays;
|
this.relays = relays;
|
||||||
this.query = query;
|
|
||||||
Object.assign(this.opts, opts);
|
Object.assign(this.opts, opts);
|
||||||
|
this.query = { ...query, limit: this.opts.startLimit };
|
||||||
|
|
||||||
this.subscription = new NostrMultiSubscription(relays, query, opts?.name);
|
this.subscription = new NostrMultiSubscription(relays, query, opts?.name);
|
||||||
|
|
||||||
this.subscription.onEvent.subscribe(this.handleEvent.bind(this));
|
this.subscription.onEvent.subscribe(this.handleEvent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
setQuery(query: NostrQueryWithStart) {
|
setQuery(query: NostrQuery) {
|
||||||
if (!query.since) throw new Error('Timeline requires "since" to be set in query');
|
this.query = { ...query, limit: this.opts.startLimit };
|
||||||
|
this.subscription.setQuery(this.query);
|
||||||
this.query = query;
|
|
||||||
this.subscription.setQuery(query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setRelays(relays: string[]) {
|
setRelays(relays: string[]) {
|
||||||
@@ -49,15 +45,15 @@ export class TimelineLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleEvent(event: NostrEvent) {
|
private handleEvent(event: NostrEvent) {
|
||||||
if (!this.eventDir.has(event.id)) {
|
if (!this.seenEvents.has(event.id)) {
|
||||||
this.eventDir.set(event.id, event);
|
this.seenEvents.add(event.id);
|
||||||
this.events.next(Array.from(this.eventDir.values()).sort((a, b) => b.created_at - a.created_at));
|
this.events.next(utils.insertEventIntoDescendingList(Array.from(this.events.value), event));
|
||||||
if (this.loading.value) this.loading.next(false);
|
if (this.loading.value) this.loading.next(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPageDates(page: number) {
|
private getPageDates(page: number) {
|
||||||
const start = this.query.since;
|
const start = this.events.value[0]?.created_at ?? moment().unix();
|
||||||
const until = start - page * this.opts.pageSize;
|
const until = start - page * this.opts.pageSize;
|
||||||
const since = until - this.opts.pageSize;
|
const since = until - this.opts.pageSize;
|
||||||
|
|
||||||
@@ -84,7 +80,7 @@ export class TimelineLoader {
|
|||||||
|
|
||||||
forgetEvents() {
|
forgetEvents() {
|
||||||
this.events.next([]);
|
this.events.next([]);
|
||||||
this.eventDir.clear();
|
this.seenEvents.clear();
|
||||||
this.subscription.forgetEvents();
|
this.subscription.forgetEvents();
|
||||||
}
|
}
|
||||||
open() {
|
open() {
|
||||||
|
@@ -2,9 +2,11 @@ import { RelayConfig } from "../classes/relay";
|
|||||||
import { safeRelayUrl } from "./url";
|
import { safeRelayUrl } from "./url";
|
||||||
|
|
||||||
export function normalizeRelayConfigs(relays: RelayConfig[]) {
|
export function normalizeRelayConfigs(relays: RelayConfig[]) {
|
||||||
|
const seen: string[] = [];
|
||||||
return relays.reduce((newArr, r) => {
|
return relays.reduce((newArr, r) => {
|
||||||
const safeUrl = safeRelayUrl(r.url);
|
const safeUrl = safeRelayUrl(r.url);
|
||||||
if (safeUrl) {
|
if (safeUrl && !seen.includes(safeUrl)) {
|
||||||
|
seen.push(safeUrl);
|
||||||
newArr.push({ ...r, url: safeUrl });
|
newArr.push({ ...r, url: safeUrl });
|
||||||
}
|
}
|
||||||
return newArr;
|
return newArr;
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
import { useCallback, useEffect, useRef } from "react";
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
import { useUnmount } from "react-use";
|
import { useUnmount } from "react-use";
|
||||||
import { NostrQueryWithStart, TimelineLoader, TimelineLoaderOptions } from "../classes/timeline-loader";
|
import { TimelineLoader, TimelineLoaderOptions } from "../classes/timeline-loader";
|
||||||
|
import { NostrQuery } from "../types/nostr-query";
|
||||||
import useSubject from "./use-subject";
|
import useSubject from "./use-subject";
|
||||||
|
|
||||||
type Options = TimelineLoaderOptions & {
|
type Options = TimelineLoaderOptions & {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useTimelineLoader(key: string, relays: string[], query: NostrQueryWithStart, opts?: Options) {
|
export function useTimelineLoader(key: string, relays: string[], query: NostrQuery, opts?: Options) {
|
||||||
if (opts && !opts.name) opts.name = key;
|
if (opts && !opts.name) opts.name = key;
|
||||||
|
|
||||||
const ref = useRef<TimelineLoader | null>(null);
|
const ref = useRef<TimelineLoader | null>(null);
|
||||||
|
@@ -25,7 +25,7 @@ export default function GlobalTab() {
|
|||||||
const { events, loading, loadMore, loader } = useTimelineLoader(
|
const { events, loading, loadMore, loader } = useTimelineLoader(
|
||||||
`global`,
|
`global`,
|
||||||
selectedRelay ? [selectedRelay] : availableRelays,
|
selectedRelay ? [selectedRelay] : availableRelays,
|
||||||
{ kinds: [1], since: moment().unix() },
|
{ kinds: [1] },
|
||||||
{ pageSize: moment.duration(5, "minutes").asSeconds() }
|
{ pageSize: moment.duration(5, "minutes").asSeconds() }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -45,7 +45,6 @@ const NotificationsView = () => {
|
|||||||
{
|
{
|
||||||
"#p": [account.pubkey],
|
"#p": [account.pubkey],
|
||||||
kinds: [1],
|
kinds: [1],
|
||||||
since: moment().subtract(1, "day").unix(),
|
|
||||||
},
|
},
|
||||||
{ pageSize: moment.duration(1, "day").asSeconds() }
|
{ pageSize: moment.duration(1, "day").asSeconds() }
|
||||||
);
|
);
|
||||||
|
@@ -34,16 +34,16 @@ const UserNotesTab = () => {
|
|||||||
.filter((r) => r.mode & RelayMode.WRITE)
|
.filter((r) => r.mode & RelayMode.WRITE)
|
||||||
.map((r) => r.url);
|
.map((r) => r.url);
|
||||||
// merge the users relays with client relays
|
// merge the users relays with client relays
|
||||||
const mergedRelays = useReadRelayUrls(userRelays);
|
const readRelays = useReadRelayUrls();
|
||||||
// find the top 4
|
// find the top 4
|
||||||
const relays = relayScoreboardService.getRankedRelays(mergedRelays).slice(0, 4);
|
const relays = relayScoreboardService.getRankedRelays(userRelays.length === 0 ? readRelays : userRelays).slice(0, 4);
|
||||||
|
|
||||||
const { isOpen: showReplies, onToggle: toggleReplies } = useDisclosure();
|
const { isOpen: showReplies, onToggle: toggleReplies } = useDisclosure();
|
||||||
|
|
||||||
const { events, loading, loadMore } = useTimelineLoader(
|
const { events, loading, loadMore } = useTimelineLoader(
|
||||||
`${pubkey}-notes`,
|
`${pubkey}-notes`,
|
||||||
relays,
|
relays,
|
||||||
{ authors: [pubkey], kinds: [1], since: moment().subtract(1, "day").unix() },
|
{ authors: [pubkey], kinds: [1] },
|
||||||
{ pageSize: moment.duration(1, "day").asSeconds() }
|
{ pageSize: moment.duration(1, "day").asSeconds() }
|
||||||
);
|
);
|
||||||
const timeline = showReplies ? events : events.filter(isNote);
|
const timeline = showReplies ? events : events.filter(isNote);
|
||||||
|
Reference in New Issue
Block a user