mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-27 20:17:05 +02:00
small fixes
This commit is contained in:
@@ -8,7 +8,7 @@ interface ConnectableApi<T> {
|
|||||||
connect(connectable: Connectable<T>): this;
|
connect(connectable: Connectable<T>): this;
|
||||||
disconnect(connectable: Connectable<T>): this;
|
disconnect(connectable: Connectable<T>): this;
|
||||||
}
|
}
|
||||||
type Connection<From, To = From, Prev = To> = (value: From, next: (value: To) => any, prevValue: Prev) => void;
|
export type Connection<From, To = From, Prev = To> = (value: From, next: (value: To) => any, prevValue: Prev) => void;
|
||||||
|
|
||||||
export class Subject<Value> implements Connectable<Value> {
|
export class Subject<Value> implements Connectable<Value> {
|
||||||
listeners: [ListenerFn<Value>, Object | undefined][] = [];
|
listeners: [ListenerFn<Value>, Object | undefined][] = [];
|
||||||
|
@@ -23,6 +23,10 @@ export function safeRelayUrl(relayUrl: string) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function safeRelayUrls(urls: string[]): string[] {
|
||||||
|
return urls.map(safeRelayUrl).filter(Boolean) as string[];
|
||||||
|
}
|
||||||
|
|
||||||
export function replaceDomain(url: string | URL, replacementUrl: string | URL) {
|
export function replaceDomain(url: string | URL, replacementUrl: string | URL) {
|
||||||
const newUrl = new URL(url);
|
const newUrl = new URL(url);
|
||||||
replacementUrl = convertToUrl(replacementUrl);
|
replacementUrl = convertToUrl(replacementUrl);
|
||||||
|
@@ -5,8 +5,9 @@ import { DraftNostrEvent, RTag } from "../types/nostr-event";
|
|||||||
import accountService from "./account";
|
import accountService from "./account";
|
||||||
import { RelayConfig, RelayMode } from "../classes/relay";
|
import { RelayConfig, RelayMode } from "../classes/relay";
|
||||||
import userRelaysService, { ParsedUserRelays } from "./user-relays";
|
import userRelaysService, { ParsedUserRelays } from "./user-relays";
|
||||||
import { PersistentSubject, Subject } from "../classes/subject";
|
import { Connection, PersistentSubject, Subject } from "../classes/subject";
|
||||||
import signingService from "./signing";
|
import signingService from "./signing";
|
||||||
|
import { logger } from "../helpers/debug";
|
||||||
|
|
||||||
export type RelayDirectory = Record<string, { read: boolean; write: boolean }>;
|
export type RelayDirectory = Record<string, { read: boolean; write: boolean }>;
|
||||||
|
|
||||||
@@ -18,21 +19,30 @@ const DEFAULT_RELAYS = [
|
|||||||
{ url: "wss://nos.lol", mode: RelayMode.READ },
|
{ url: "wss://nos.lol", mode: RelayMode.READ },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const userRelaysToRelayConfig: Connection<ParsedUserRelays, RelayConfig[], RelayConfig[] | undefined> = (
|
||||||
|
userRelays,
|
||||||
|
next
|
||||||
|
) => next(userRelays.relays);
|
||||||
|
|
||||||
class ClientRelayService {
|
class ClientRelayService {
|
||||||
bootstrapRelays = new Set<string>();
|
bootstrapRelays = new Set<string>();
|
||||||
relays = new PersistentSubject<RelayConfig[]>([]);
|
relays = new PersistentSubject<RelayConfig[]>([]);
|
||||||
writeRelays = new PersistentSubject<RelayConfig[]>([]);
|
writeRelays = new PersistentSubject<RelayConfig[]>([]);
|
||||||
readRelays = new PersistentSubject<RelayConfig[]>([]);
|
readRelays = new PersistentSubject<RelayConfig[]>([]);
|
||||||
|
|
||||||
|
log = logger.extend("ClientRelays");
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
let lastSubject: Subject<ParsedUserRelays> | undefined;
|
let lastSubject: Subject<ParsedUserRelays> | undefined;
|
||||||
accountService.current.subscribe((account) => {
|
accountService.current.subscribe((account) => {
|
||||||
if (!account) {
|
if (!account) {
|
||||||
|
this.log("No account, using default relays");
|
||||||
this.relays.next(DEFAULT_RELAYS);
|
this.relays.next(DEFAULT_RELAYS);
|
||||||
return;
|
return;
|
||||||
} else this.relays.next([]);
|
} else this.relays.next([]);
|
||||||
|
|
||||||
if (account.relays) {
|
if (account.relays) {
|
||||||
|
this.log("Found bootstrap relays");
|
||||||
this.bootstrapRelays.clear();
|
this.bootstrapRelays.clear();
|
||||||
for (const relay of account.relays) {
|
for (const relay of account.relays) {
|
||||||
this.bootstrapRelays.add(relay);
|
this.bootstrapRelays.add(relay);
|
||||||
@@ -40,41 +50,47 @@ class ClientRelayService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastSubject) {
|
if (lastSubject) {
|
||||||
lastSubject.unsubscribe(this.handleRelayChanged, this);
|
this.log("Disconnecting from previous user relays");
|
||||||
|
this.relays.disconnect(lastSubject);
|
||||||
lastSubject = undefined;
|
lastSubject = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the relays from cache or bootstrap relays
|
// load the relays from cache or bootstrap relays
|
||||||
|
this.log("Load users relays from cache or bootstrap relays");
|
||||||
lastSubject = userRelaysService.requestRelays(account.pubkey, Array.from(this.bootstrapRelays));
|
lastSubject = userRelaysService.requestRelays(account.pubkey, Array.from(this.bootstrapRelays));
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// double check for new relay notes
|
// double check for new relay notes
|
||||||
|
this.log("Requesting latest relays from the write relays");
|
||||||
userRelaysService.requestRelays(account.pubkey, this.getWriteUrls(), true);
|
userRelaysService.requestRelays(account.pubkey, this.getWriteUrls(), true);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
lastSubject.subscribe(this.handleRelayChanged, this);
|
this.relays.connectWithHandler(lastSubject, userRelaysToRelayConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.relays.subscribe((relays) => this.writeRelays.next(relays.filter((r) => r.mode & RelayMode.WRITE)));
|
// set the read and write relays
|
||||||
this.relays.subscribe((relays) => this.readRelays.next(relays.filter((r) => r.mode & RelayMode.READ)));
|
this.relays.subscribe((relays) => {
|
||||||
}
|
this.log("Got new relay list");
|
||||||
|
this.writeRelays.next(relays.filter((r) => r.mode & RelayMode.WRITE));
|
||||||
private handleRelayChanged(relays: ParsedUserRelays) {
|
this.readRelays.next(relays.filter((r) => r.mode & RelayMode.READ));
|
||||||
this.relays.next(relays.relays);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async addRelay(url: string, mode: RelayMode) {
|
async addRelay(url: string, mode: RelayMode) {
|
||||||
|
this.log(`Adding ${url} relay`);
|
||||||
if (!this.relays.value.some((r) => r.url === url)) {
|
if (!this.relays.value.some((r) => r.url === url)) {
|
||||||
const newRelays = [...this.relays.value, { url, mode }];
|
const newRelays = [...this.relays.value, { url, mode }];
|
||||||
await this.postUpdatedRelays(newRelays);
|
await this.postUpdatedRelays(newRelays);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async updateRelay(url: string, mode: RelayMode) {
|
async updateRelay(url: string, mode: RelayMode) {
|
||||||
|
this.log(`Updating ${url} relay`);
|
||||||
if (this.relays.value.some((r) => r.url === url)) {
|
if (this.relays.value.some((r) => r.url === url)) {
|
||||||
const newRelays = this.relays.value.map((r) => (r.url === url ? { url, mode } : r));
|
const newRelays = this.relays.value.map((r) => (r.url === url ? { url, mode } : r));
|
||||||
await this.postUpdatedRelays(newRelays);
|
await this.postUpdatedRelays(newRelays);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async removeRelay(url: string) {
|
async removeRelay(url: string) {
|
||||||
|
this.log(`Removing ${url} relay`);
|
||||||
if (this.relays.value.some((r) => r.url === url)) {
|
if (this.relays.value.some((r) => r.url === url)) {
|
||||||
const newRelays = this.relays.value.filter((r) => r.url !== url);
|
const newRelays = this.relays.value.filter((r) => r.url !== url);
|
||||||
await this.postUpdatedRelays(newRelays);
|
await this.postUpdatedRelays(newRelays);
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import createDefer, { Deferred } from "../classes/deferred";
|
import createDefer, { Deferred } from "../classes/deferred";
|
||||||
import { NostrRequest } from "../classes/nostr-request";
|
import { NostrRequest } from "../classes/nostr-request";
|
||||||
|
import { safeRelayUrl, safeRelayUrls } from "../helpers/url";
|
||||||
import { NostrEvent } from "../types/nostr-event";
|
import { NostrEvent } from "../types/nostr-event";
|
||||||
|
|
||||||
class SingleEventService {
|
class SingleEventService {
|
||||||
@@ -11,7 +12,7 @@ class SingleEventService {
|
|||||||
const event = this.eventCache.get(id);
|
const event = this.eventCache.get(id);
|
||||||
if (event) return event;
|
if (event) return event;
|
||||||
|
|
||||||
this.pending.set(id, this.pending.get(id)?.concat(relays) ?? relays);
|
this.pending.set(id, this.pending.get(id)?.concat(relays) ?? safeRelayUrls(relays));
|
||||||
const deferred = createDefer<NostrEvent>();
|
const deferred = createDefer<NostrEvent>();
|
||||||
this.pendingPromises.set(id, deferred);
|
this.pendingPromises.set(id, deferred);
|
||||||
return deferred;
|
return deferred;
|
||||||
|
@@ -29,7 +29,13 @@ class UserRelaysService {
|
|||||||
}
|
}
|
||||||
requestRelays(pubkey: string, relays: string[], alwaysRequest = false) {
|
requestRelays(pubkey: string, relays: string[], alwaysRequest = false) {
|
||||||
const sub = this.subjects.get(pubkey);
|
const sub = this.subjects.get(pubkey);
|
||||||
const requestSub = replaceableEventLoaderService.requestEvent(relays, Kind.RelayList, pubkey);
|
const requestSub = replaceableEventLoaderService.requestEvent(
|
||||||
|
relays,
|
||||||
|
Kind.RelayList,
|
||||||
|
pubkey,
|
||||||
|
undefined,
|
||||||
|
alwaysRequest
|
||||||
|
);
|
||||||
sub.connectWithHandler(requestSub, (event, next) => next(parseRelaysEvent(event)));
|
sub.connectWithHandler(requestSub, (event, next) => next(parseRelaysEvent(event)));
|
||||||
|
|
||||||
// also fetch the relays from the users contacts
|
// also fetch the relays from the users contacts
|
||||||
|
@@ -38,7 +38,7 @@ export default function RelaysView() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex direction="column" gap="2" p="2">
|
<Flex direction="column" gap="2" p="2">
|
||||||
<Flex alignItems="center" gap="2">
|
<Flex alignItems="center" gap="2" wrap="wrap">
|
||||||
<Input type="search" placeholder="search" value={search} onChange={(e) => setSearch(e.target.value)} w="auto" />
|
<Input type="search" placeholder="search" value={search} onChange={(e) => setSearch(e.target.value)} w="auto" />
|
||||||
<Switch isChecked={showAll.isOpen} onChange={showAll.onToggle}>
|
<Switch isChecked={showAll.isOpen} onChange={showAll.onToggle}>
|
||||||
Show All
|
Show All
|
||||||
|
@@ -105,7 +105,7 @@ function RelayPage({ relay }: { relay: string }) {
|
|||||||
<RelayJoinAction url={relay} />
|
<RelayJoinAction url={relay} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<RelayMetadata url={relay} />
|
<RelayMetadata url={relay} />
|
||||||
<Flex gap="2">
|
<Flex gap="2" wrap="wrap">
|
||||||
{info?.supported_nips?.map((nip) => (
|
{info?.supported_nips?.map((nip) => (
|
||||||
<NipTag key={nip} nip={nip} />
|
<NipTag key={nip} nip={nip} />
|
||||||
))}
|
))}
|
||||||
|
Reference in New Issue
Block a user