From 02eb95b59b7d3e91a455412aad79ca955b509f43 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 7 Feb 2023 17:04:18 -0600 Subject: [PATCH] make settings use rxjs --- .vscode/settings.json | 3 ++ src/app.tsx | 7 ----- src/components/post.tsx | 7 +++-- src/hooks/use-subject.ts | 11 +++++++ src/providers/index.tsx | 5 +-- src/providers/relay-provider.tsx | 52 ------------------------------- src/services/relays/relay-pool.ts | 5 +-- src/services/settings.ts | 42 +++++++++++++++++-------- src/services/user-metadata.ts | 4 +-- src/types/nostr-event.ts | 5 ++- src/views/global/index.tsx | 5 +-- src/views/settings.tsx | 27 +++++++++++++--- src/views/user/posts.tsx | 8 ++--- 13 files changed, 88 insertions(+), 93 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/hooks/use-subject.ts delete mode 100644 src/providers/relay-provider.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..97216df83 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["Chakra", "nostr", "pubkeys"] +} diff --git a/src/app.tsx b/src/app.tsx index 317bc32f7..9e376f79f 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,19 +1,12 @@ -import React from "react"; -import { Spinner } from "@chakra-ui/react"; import { Route, Routes } from "react-router-dom"; import { HomeView } from "./views/home"; import { UserView } from "./views/user"; import { ErrorBoundary } from "./components/error-boundary"; import { SettingsView } from "./views/settings"; import { GlobalView } from "./views/global"; -import { useRelays } from "./providers/relay-provider"; import { Page } from "./components/page"; export const App = () => { - const { loading } = useRelays(); - - if (loading) return ; - return ( diff --git a/src/components/post.tsx b/src/components/post.tsx index 2f32b9817..c899951e2 100644 --- a/src/components/post.tsx +++ b/src/components/post.tsx @@ -19,12 +19,15 @@ import moment from "moment"; import { PostModal } from "./post-modal"; import { NostrEvent } from "../types/nostr-event"; import { useUserMetadata } from "../hooks/use-user-metadata"; +import useSubject from "../hooks/use-subject"; +import settings from "../services/settings"; export type PostProps = { event: NostrEvent; }; export const Post = React.memo(({ event }: PostProps) => { const { isOpen, onClose, onOpen } = useDisclosure(); + const corsProxy = useSubject(settings.corsProxy); const userMetadata = useUserMetadata(event.pubkey); const isLong = event.content.length > 800; @@ -35,8 +38,8 @@ export const Post = React.memo(({ event }: PostProps) => { diff --git a/src/hooks/use-subject.ts b/src/hooks/use-subject.ts new file mode 100644 index 000000000..cb0e56cda --- /dev/null +++ b/src/hooks/use-subject.ts @@ -0,0 +1,11 @@ +import { useObservable } from "react-use"; +import { BehaviorSubject, Subject } from "rxjs"; + +function useSubject(subject: BehaviorSubject): T; +function useSubject(subject: Subject): T | undefined { + if (subject instanceof BehaviorSubject) { + return useObservable(subject, subject.getValue()); + } else return useObservable(subject); +} + +export default useSubject; diff --git a/src/providers/index.tsx b/src/providers/index.tsx index 9cf4f2ff2..bbef4e0b9 100644 --- a/src/providers/index.tsx +++ b/src/providers/index.tsx @@ -1,13 +1,10 @@ import React from "react"; import { ChakraProvider } from "@chakra-ui/react"; -import { RelaysProvider } from "./relay-provider"; import { HashRouter } from "react-router-dom"; import theme from "../theme"; export const Providers = ({ children }: { children: React.ReactNode }) => ( - - {children} - + {children} ); diff --git a/src/providers/relay-provider.tsx b/src/providers/relay-provider.tsx deleted file mode 100644 index 088a1479c..000000000 --- a/src/providers/relay-provider.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { - createContext, - useCallback, - useContext, - useEffect, - useState, -} from "react"; -import settingsService from "../services/settings"; - -const relaysContext = createContext({ - relays: [] as string[], - loading: true, - overwriteRelays: (urls: string[]) => {}, -}); - -export function useRelays() { - return useContext(relaysContext); -} - -export const RelaysProvider = ({ children }: { children: React.ReactNode }) => { - const [relays, setRelays] = useState([]); - const [loading, setLoading] = useState(true); - - const update = useCallback(async () => { - setRelays(await settingsService.getRelays()); - setLoading(false); - }, [setRelays]); - - const overwriteRelays = useCallback( - async (urls: string[]) => { - if (urls) await settingsService.setRelays(urls); - await update(); - }, - [update] - ); - - useEffect(() => { - update(); - }, [update]); - - return ( - - {children} - - ); -}; diff --git a/src/services/relays/relay-pool.ts b/src/services/relays/relay-pool.ts index 722c012c6..757eb021d 100644 --- a/src/services/relays/relay-pool.ts +++ b/src/services/relays/relay-pool.ts @@ -1,6 +1,6 @@ import { Subject } from "rxjs"; +import settings from "../settings"; import { Relay } from "./relay"; -import settingsService from "../settings"; export class RelayPool { relays = new Map(); @@ -72,8 +72,9 @@ if (import.meta.env.DEV) { window.relayPool = relayPool; } +// TODO: move this somewhere where it makes sense setTimeout(async () => { - const urls = await settingsService.getRelays(); + const urls = settings.relays.getValue(); for (const url of urls) { relayPool.requestRelay(url); diff --git a/src/services/settings.ts b/src/services/settings.ts index d8fb826c8..f0832aac5 100644 --- a/src/services/settings.ts +++ b/src/services/settings.ts @@ -1,20 +1,36 @@ +import { BehaviorSubject } from "rxjs"; import db from "./db"; -export async function getRelays(): Promise { - return await db.get("settings", "relays"); -} -export async function setRelays(relays: string[] = []) { - await db.put("settings", relays, "relays"); +function log(message: string) { + console.log(`Settings: ${message}`); } -const settingsService = { - getRelays, - setRelays, +const settings = { + relays: new BehaviorSubject([]), + corsProxy: new BehaviorSubject(""), }; -if (import.meta.env.DEV) { - // @ts-ignore - window.settingsService = settingsService; -} +async function loadSettings() { + let loading = true; + const relays = await db.get("settings", "relays"); + if (relays) settings.relays.next(relays); + settings.relays.subscribe((newUrls) => { + if (loading) return; + log("saving relay urls"); + db.put("settings", newUrls, "relays"); + }); -export default settingsService; + const corsProxy = await db.get("settings", "cors-proxy"); + if (corsProxy) settings.corsProxy.next(corsProxy); + settings.corsProxy.subscribe((newUrl) => { + if (loading) return; + log("saving cors-proxy url"); + db.put("settings", newUrl, "cors-proxy"); + }); + + loading = false; + log("loaded"); +} +await loadSettings(); + +export default settings; diff --git a/src/services/user-metadata.ts b/src/services/user-metadata.ts index 9938ef979..53361aeb6 100644 --- a/src/services/user-metadata.ts +++ b/src/services/user-metadata.ts @@ -1,7 +1,7 @@ import { BehaviorSubject } from "rxjs"; import { Kind0ParsedContent } from "../types/nostr-event"; import db from "./db"; -import settingsService from "./settings"; +import settings from "./settings"; import { Subscription } from "./subscriptions"; class UserMetadata { @@ -89,7 +89,7 @@ class UserMetadata { } } -const userMetadata = new UserMetadata(await settingsService.getRelays()); +const userMetadata = new UserMetadata(settings.relays.getValue()); if (import.meta.env.DEV) { // @ts-ignore diff --git a/src/types/nostr-event.ts b/src/types/nostr-event.ts index 836eec21c..855493d3d 100644 --- a/src/types/nostr-event.ts +++ b/src/types/nostr-event.ts @@ -13,5 +13,8 @@ export type IncomingNostrEvent = | ["NOTICE", string]; export type Kind0ParsedContent = { - name: string; + name?: string; + display_name?: string; + about?: string; + picture?: string; }; diff --git a/src/views/global/index.tsx b/src/views/global/index.tsx index ca5281e5b..d48d93c6e 100644 --- a/src/views/global/index.tsx +++ b/src/views/global/index.tsx @@ -1,13 +1,14 @@ import React, { useEffect, useState } from "react"; import { SkeletonText } from "@chakra-ui/react"; import { useSubscription } from "../../hooks/use-subscription"; -import { useRelays } from "../../providers/relay-provider"; import { Post } from "../../components/post"; import moment from "moment/moment"; import { NostrEvent } from "../../types/nostr-event"; +import settings from "../../services/settings"; +import useSubject from "../../hooks/use-subject"; export const GlobalView = () => { - const { relays } = useRelays(); + const relays = useSubject(settings.relays); const [events, setEvents] = useState>({}); const sub = useSubscription( diff --git a/src/views/settings.tsx b/src/views/settings.tsx index 81ba9480b..18c9266c5 100644 --- a/src/views/settings.tsx +++ b/src/views/settings.tsx @@ -3,15 +3,19 @@ import { FormControl, FormHelperText, FormLabel, + Input, Stack, Textarea, } from "@chakra-ui/react"; -import React, { SyntheticEvent, useState } from "react"; -import { useRelays } from "../providers/relay-provider"; +import { SyntheticEvent, useState } from "react"; +import useSubject from "../hooks/use-subject"; +import settings from "../services/settings"; export const SettingsView = () => { - const { relays, overwriteRelays } = useRelays(); + const relays = useSubject(settings.relays); + // const corsProxy = useSubject(settings.corsProxy); const [relayUrls, setRelayUrls] = useState(relays.join("\n")); + // const [newCorsProxy, setNewCorsProxy] = useState(corsProxy); const handleSubmit = async (event: SyntheticEvent) => { event.preventDefault(); @@ -21,12 +25,18 @@ export const SettingsView = () => { .map((url) => url.trim()); if (newRelays.length > 0) { - await overwriteRelays(newRelays); + settings.relays.next(newRelays); } + + // try { + // const corsUrl = new URL("https://cors.rdfriedl.com").toString(); + // settings.corsProxy.next(corsUrl); + // } catch (e) {} }; const resetForm = async () => { setRelayUrls(relays.join("\n")); + // setNewCorsProxy(corsProxy); }; return ( @@ -43,6 +53,15 @@ export const SettingsView = () => { /> One relay per line + {/* + CORS Proxy + setNewCorsProxy(e.target.value)} + required + /> + One relay per line + */} diff --git a/src/views/user/posts.tsx b/src/views/user/posts.tsx index 40af684f3..cf313fe0c 100644 --- a/src/views/user/posts.tsx +++ b/src/views/user/posts.tsx @@ -1,17 +1,17 @@ import React, { useEffect, useState } from "react"; import { SkeletonText } from "@chakra-ui/react"; -import settingsService from "../../services/settings"; import { useSubscription } from "../../hooks/use-subscription"; import { Post } from "../../components/post"; import { NostrEvent } from "../../types/nostr-event"; - -const relayUrls = await settingsService.getRelays(); +import settings from "../../services/settings"; +import useSubject from "../../hooks/use-subject"; export const UserPostsTab = ({ pubkey }: { pubkey: string }) => { + const relays = useSubject(settings.relays); const [events, setEvents] = useState>({}); const sub = useSubscription( - relayUrls, + relays, { authors: [pubkey], kinds: [1] }, `${pubkey} posts` );