mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-19 12:00:32 +02:00
some cleanup
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
import { Menu, MenuButton, MenuList, IconButton, MenuListProps, MenuButtonProps } from "@chakra-ui/react";
|
import { Menu, MenuButton, MenuList, IconButton, MenuListProps, IconButtonProps } from "@chakra-ui/react";
|
||||||
import { MoreIcon } from "./icons";
|
import { MoreIcon } from "./icons";
|
||||||
|
|
||||||
export type MenuIconButtonProps = MenuButtonProps & {
|
export type MenuIconButtonProps = IconButtonProps & {
|
||||||
children: MenuListProps["children"];
|
children: MenuListProps["children"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MenuIconButton = ({ children, ...props }: MenuIconButtonProps) => (
|
export const MenuIconButton = ({ children, ...props }: MenuIconButtonProps) => (
|
||||||
<Menu isLazy>
|
<Menu isLazy>
|
||||||
<MenuButton as={IconButton} icon={<MoreIcon />} aria-label="view raw" title="view raw" size="xs" {...props} />
|
<MenuButton as={IconButton} icon={<MoreIcon />} {...props} />
|
||||||
<MenuList>{children}</MenuList>
|
<MenuList>{children}</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
@@ -69,28 +69,30 @@ export const Note = React.memo(({ event, maxHeight }: NoteProps) => {
|
|||||||
</CardBody>
|
</CardBody>
|
||||||
<CardFooter padding="2" display="flex" gap="2">
|
<CardFooter padding="2" display="flex" gap="2">
|
||||||
<IconButton
|
<IconButton
|
||||||
|
variant="link"
|
||||||
icon={<ReplyIcon />}
|
icon={<ReplyIcon />}
|
||||||
title="Reply"
|
title="Reply"
|
||||||
aria-label="Reply"
|
aria-label="Reply"
|
||||||
onClick={reply}
|
onClick={reply}
|
||||||
size="xs"
|
size="sm"
|
||||||
isDisabled={account.readonly}
|
isDisabled={account.readonly}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
variant="link"
|
||||||
icon={<ShareIcon />}
|
icon={<ShareIcon />}
|
||||||
onClick={share}
|
onClick={share}
|
||||||
aria-label="Share Note"
|
aria-label="Share Note"
|
||||||
title="Share Note"
|
title="Share Note"
|
||||||
size="xs"
|
size="sm"
|
||||||
isDisabled={account.readonly}
|
isDisabled={account.readonly}
|
||||||
/>
|
/>
|
||||||
<ButtonGroup size="xs" isAttached>
|
<ButtonGroup size="sm" variant="link">
|
||||||
<NoteZapButton note={event} size="xs" />
|
<NoteZapButton note={event} size="sm" />
|
||||||
<NoteLikeButton note={event} size="xs" />
|
<NoteLikeButton note={event} size="sm" />
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<Box flexGrow={1} />
|
<Box flexGrow={1} />
|
||||||
<NoteRelays event={event} size="xs" />
|
<NoteRelays event={event} size="sm" variant="link" />
|
||||||
<NoteMenu event={event} />
|
<NoteMenu event={event} size="sm" variant="link" aria-label="More Options" />
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
@@ -12,13 +12,13 @@ import { useCopyToClipboard } from "react-use";
|
|||||||
|
|
||||||
import { Bech32Prefix, normalizeToBech32 } from "../../helpers/nip-19";
|
import { Bech32Prefix, normalizeToBech32 } from "../../helpers/nip-19";
|
||||||
import { NostrEvent } from "../../types/nostr-event";
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
import { MenuIconButton } from "../menu-icon-button";
|
import { MenuIconButton, MenuIconButtonProps } from "../menu-icon-button";
|
||||||
|
|
||||||
import { ClipboardIcon, CodeIcon, LikeIcon } from "../icons";
|
import { ClipboardIcon, CodeIcon, LikeIcon } from "../icons";
|
||||||
import { getReferences } from "../../helpers/nostr-event";
|
import { getReferences } from "../../helpers/nostr-event";
|
||||||
import NoteReactionsModal from "./note-reactions-modal";
|
import NoteReactionsModal from "./note-reactions-modal";
|
||||||
|
|
||||||
export const NoteMenu = ({ event }: { event: NostrEvent }) => {
|
export const NoteMenu = ({ event, ...props }: { event: NostrEvent } & Omit<MenuIconButtonProps, "children">) => {
|
||||||
const infoModal = useDisclosure();
|
const infoModal = useDisclosure();
|
||||||
const reactionsModal = useDisclosure();
|
const reactionsModal = useDisclosure();
|
||||||
const [_clipboardState, copyToClipboard] = useCopyToClipboard();
|
const [_clipboardState, copyToClipboard] = useCopyToClipboard();
|
||||||
@@ -26,7 +26,7 @@ export const NoteMenu = ({ event }: { event: NostrEvent }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuIconButton>
|
<MenuIconButton {...props}>
|
||||||
<MenuItem onClick={reactionsModal.onOpen} icon={<LikeIcon />}>
|
<MenuItem onClick={reactionsModal.onOpen} icon={<LikeIcon />}>
|
||||||
Reactions
|
Reactions
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
@@ -51,7 +51,7 @@ export const NoteRelays = memo(({ event, ...props }: NoteRelaysProps) => {
|
|||||||
return (
|
return (
|
||||||
<Popover isLazy>
|
<Popover isLazy>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<IconButton title="Note Relays" icon={<RelayIcon />} size={props.size ?? "sm"} aria-label="Note Relays" />
|
<IconButton title="Note Relays" icon={<RelayIcon />} aria-label="Note Relays" {...props} />
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent>
|
||||||
<PopoverArrow />
|
<PopoverArrow />
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
import { useCurrentAccount } from "./use-current-account";
|
|
||||||
|
|
||||||
/** @deprecated */
|
|
||||||
export function useReadonlyMode() {
|
|
||||||
const account = useCurrentAccount();
|
|
||||||
return account.readonly;
|
|
||||||
}
|
|
@@ -85,7 +85,7 @@ class ClientRelayService {
|
|||||||
await results.onComplete;
|
await results.onComplete;
|
||||||
|
|
||||||
// pass new event to the user relay service
|
// pass new event to the user relay service
|
||||||
userRelaysService.handleEvent(event);
|
userRelaysService.receiveEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
getWriteUrls() {
|
getWriteUrls() {
|
||||||
|
@@ -35,7 +35,6 @@ async function fetchIdentity(address: string) {
|
|||||||
const { name, domain } = parseAddress(address);
|
const { name, domain } = parseAddress(address);
|
||||||
if (!name || !domain) throw new Error("invalid address");
|
if (!name || !domain) throw new Error("invalid address");
|
||||||
|
|
||||||
try {
|
|
||||||
const json = await fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)
|
const json = await fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)
|
||||||
.then((res) => res.json() as Promise<IdentityJson>)
|
.then((res) => res.json() as Promise<IdentityJson>)
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
@@ -58,7 +57,6 @@ async function fetchIdentity(address: string) {
|
|||||||
await addToCache(domain, json);
|
await addToCache(domain, json);
|
||||||
|
|
||||||
return getIdentityFromJson(name, domain, json);
|
return getIdentityFromJson(name, domain, json);
|
||||||
} catch (e) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addToCache(domain: string, json: IdentityJson) {
|
async function addToCache(domain: string, json: IdentityJson) {
|
||||||
|
@@ -5,9 +5,12 @@ import { Kind0ParsedContent, parseKind0Event } from "../helpers/user-metadata";
|
|||||||
import { SuperMap } from "../classes/super-map";
|
import { SuperMap } from "../classes/super-map";
|
||||||
import Subject from "../classes/subject";
|
import Subject from "../classes/subject";
|
||||||
|
|
||||||
class UserMetadataService extends CachedPubkeyEventRequester {
|
class UserMetadataService {
|
||||||
|
requester: CachedPubkeyEventRequester;
|
||||||
constructor() {
|
constructor() {
|
||||||
super(0, "user-metadata");
|
this.requester = new CachedPubkeyEventRequester(0, "user-metadata");
|
||||||
|
this.requester.readCache = this.readCache;
|
||||||
|
this.requester.writeCache = this.writeCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
readCache(pubkey: string) {
|
readCache(pubkey: string) {
|
||||||
@@ -20,13 +23,18 @@ class UserMetadataService extends CachedPubkeyEventRequester {
|
|||||||
private parsedSubjects = new SuperMap<string, Subject<Kind0ParsedContent>>(() => new Subject<Kind0ParsedContent>());
|
private parsedSubjects = new SuperMap<string, Subject<Kind0ParsedContent>>(() => new Subject<Kind0ParsedContent>());
|
||||||
requestMetadata(pubkey: string, relays: string[], alwaysRequest = false) {
|
requestMetadata(pubkey: string, relays: string[], alwaysRequest = false) {
|
||||||
const sub = this.parsedSubjects.get(pubkey);
|
const sub = this.parsedSubjects.get(pubkey);
|
||||||
|
const requestSub = this.requester.requestEvent(pubkey, relays, alwaysRequest);
|
||||||
const requestSub = this.requestEvent(pubkey, relays, alwaysRequest);
|
|
||||||
|
|
||||||
sub.connectWithHandler(requestSub, (event, next) => next(parseKind0Event(event)));
|
sub.connectWithHandler(requestSub, (event, next) => next(parseKind0Event(event)));
|
||||||
|
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receiveEvent(event: NostrEvent) {
|
||||||
|
this.requester.handleEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.requester.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const userMetadataService = new UserMetadataService();
|
const userMetadataService = new UserMetadataService();
|
||||||
@@ -35,9 +43,4 @@ setInterval(() => {
|
|||||||
userMetadataService.update();
|
userMetadataService.update();
|
||||||
}, 1000 * 2);
|
}, 1000 * 2);
|
||||||
|
|
||||||
if (import.meta.env.DEV) {
|
|
||||||
// @ts-ignore
|
|
||||||
window.userMetadataService = userMetadataService;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default userMetadataService;
|
export default userMetadataService;
|
||||||
|
@@ -20,9 +20,12 @@ function parseRelaysEvent(event: NostrEvent): UserRelays {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserRelaysService extends CachedPubkeyEventRequester {
|
class UserRelaysService {
|
||||||
|
requester: CachedPubkeyEventRequester;
|
||||||
constructor() {
|
constructor() {
|
||||||
super(10002, "user-relays");
|
this.requester = new CachedPubkeyEventRequester(10002, "user-relays");
|
||||||
|
this.requester.readCache = this.readCache;
|
||||||
|
this.requester.writeCache = this.writeCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
readCache(pubkey: string) {
|
readCache(pubkey: string) {
|
||||||
@@ -32,16 +35,21 @@ class UserRelaysService extends CachedPubkeyEventRequester {
|
|||||||
return db.put("userRelays", event);
|
return db.put("userRelays", event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private parsedSubjects = new SuperMap<string, Subject<UserRelays>>(() => new Subject<UserRelays>());
|
private subjects = new SuperMap<string, Subject<UserRelays>>(() => new Subject<UserRelays>());
|
||||||
requestRelays(pubkey: string, relays: string[], alwaysRequest = false) {
|
requestRelays(pubkey: string, relays: string[], alwaysRequest = false) {
|
||||||
const sub = this.parsedSubjects.get(pubkey);
|
const sub = this.subjects.get(pubkey);
|
||||||
|
const requestSub = this.requester.requestEvent(pubkey, relays, alwaysRequest);
|
||||||
const requestSub = this.requestEvent(pubkey, relays, alwaysRequest);
|
|
||||||
|
|
||||||
sub.connectWithHandler(requestSub, (event, next) => next(parseRelaysEvent(event)));
|
sub.connectWithHandler(requestSub, (event, next) => next(parseRelaysEvent(event)));
|
||||||
|
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receiveEvent(event: NostrEvent) {
|
||||||
|
this.requester.handleEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.requester.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const userRelaysService = new UserRelaysService();
|
const userRelaysService = new UserRelaysService();
|
||||||
|
@@ -118,10 +118,14 @@ const MetadataForm = ({ defaultValues, onSubmit }: MetadataFormProps) => {
|
|||||||
minLength: 5,
|
minLength: 5,
|
||||||
validate: async (address) => {
|
validate: async (address) => {
|
||||||
if (!address) return true;
|
if (!address) return true;
|
||||||
if (!address.includes("@")) return "invalid address";
|
if (!address.includes("@")) return "Invalid address";
|
||||||
|
try {
|
||||||
const id = await dnsIdentityService.getIdentity(address);
|
const id = await dnsIdentityService.getIdentity(address);
|
||||||
if (!id) return "cant find NIP-05 ID";
|
if (!id) return "Cant find NIP-05 ID";
|
||||||
if (id.pubkey !== account.pubkey) return "Pubkey dose not match";
|
if (id.pubkey !== account.pubkey) return "Pubkey dose not match";
|
||||||
|
} catch (e) {
|
||||||
|
return "Failed to fetch ID";
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
@@ -224,7 +228,7 @@ export const ProfileEditView = () => {
|
|||||||
|
|
||||||
const event = await signingService.requestSignature(draft, account);
|
const event = await signingService.requestSignature(draft, account);
|
||||||
const results = nostrPostAction(writeRelays, event);
|
const results = nostrPostAction(writeRelays, event);
|
||||||
userMetadataService.handleEvent(event);
|
userMetadataService.receiveEvent(event);
|
||||||
|
|
||||||
await results.onComplete;
|
await results.onComplete;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@@ -35,8 +35,8 @@ export default function Header({ pubkey }: { pubkey: string }) {
|
|||||||
<UserDnsIdentityIcon pubkey={pubkey} />
|
<UserDnsIdentityIcon pubkey={pubkey} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex gap="2">
|
<Flex gap="2">
|
||||||
<UserTipButton pubkey={pubkey} size="xs" />
|
<UserTipButton pubkey={pubkey} size="sm" variant="link" />
|
||||||
<UserProfileMenu pubkey={pubkey} />
|
<UserProfileMenu pubkey={pubkey} aria-label="More Options" size="sm" variant="link" />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
{!metadata ? <SkeletonText /> : <Text>{metadata?.about}</Text>}
|
{!metadata ? <SkeletonText /> : <Text>{metadata?.about}</Text>}
|
||||||
|
Reference in New Issue
Block a user