mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-13 06:09:42 +02:00
make settings use rxjs
This commit is contained in:
parent
012466383d
commit
02eb95b59b
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"cSpell.words": ["Chakra", "nostr", "pubkeys"]
|
||||
}
|
@ -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 <Spinner size="xl" />;
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<Routes>
|
||||
|
@ -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) => {
|
||||
<HStack spacing="4">
|
||||
<Flex flex="1" gap="4" alignItems="center" flexWrap="wrap">
|
||||
<Avatar
|
||||
name={userMetadata?.name}
|
||||
src="https://bit.ly/sage-adebayo"
|
||||
name={userMetadata?.display_name ?? userMetadata?.name}
|
||||
src={userMetadata?.picture}
|
||||
/>
|
||||
|
||||
<Box>
|
||||
|
11
src/hooks/use-subject.ts
Normal file
11
src/hooks/use-subject.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { useObservable } from "react-use";
|
||||
import { BehaviorSubject, Subject } from "rxjs";
|
||||
|
||||
function useSubject<T>(subject: BehaviorSubject<T>): T;
|
||||
function useSubject<T>(subject: Subject<T>): T | undefined {
|
||||
if (subject instanceof BehaviorSubject) {
|
||||
return useObservable(subject, subject.getValue());
|
||||
} else return useObservable(subject);
|
||||
}
|
||||
|
||||
export default useSubject;
|
@ -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 }) => (
|
||||
<ChakraProvider theme={theme}>
|
||||
<HashRouter>
|
||||
<RelaysProvider>{children}</RelaysProvider>
|
||||
</HashRouter>
|
||||
<HashRouter>{children}</HashRouter>
|
||||
</ChakraProvider>
|
||||
);
|
||||
|
@ -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<string[]>([]);
|
||||
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 (
|
||||
<relaysContext.Provider
|
||||
value={{
|
||||
relays,
|
||||
loading,
|
||||
overwriteRelays,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</relaysContext.Provider>
|
||||
);
|
||||
};
|
@ -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<string, Relay>();
|
||||
@ -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);
|
||||
|
@ -1,20 +1,36 @@
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import db from "./db";
|
||||
|
||||
export async function getRelays(): Promise<string[]> {
|
||||
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<string[]>([]),
|
||||
corsProxy: new BehaviorSubject<string>(""),
|
||||
};
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
|
@ -13,5 +13,8 @@ export type IncomingNostrEvent =
|
||||
| ["NOTICE", string];
|
||||
|
||||
export type Kind0ParsedContent = {
|
||||
name: string;
|
||||
name?: string;
|
||||
display_name?: string;
|
||||
about?: string;
|
||||
picture?: string;
|
||||
};
|
||||
|
@ -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<Record<string, NostrEvent>>({});
|
||||
|
||||
const sub = useSubscription(
|
||||
|
@ -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<HTMLFormElement>) => {
|
||||
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 = () => {
|
||||
/>
|
||||
<FormHelperText>One relay per line</FormHelperText>
|
||||
</FormControl>
|
||||
{/* <FormControl>
|
||||
<FormLabel>CORS Proxy</FormLabel>
|
||||
<Input
|
||||
value={newCorsProxy}
|
||||
onChange={(e) => setNewCorsProxy(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<FormHelperText>One relay per line</FormHelperText>
|
||||
</FormControl> */}
|
||||
<Stack direction="row" spacing={4}>
|
||||
<Button onClick={resetForm}>Reset</Button>
|
||||
<Button type="submit">Save</Button>
|
||||
|
@ -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<Record<string, NostrEvent>>({});
|
||||
|
||||
const sub = useSubscription(
|
||||
relayUrls,
|
||||
relays,
|
||||
{ authors: [pubkey], kinds: [1] },
|
||||
`${pubkey} posts`
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user