rebuild tools view

This commit is contained in:
hzrd149
2023-11-27 17:19:23 -06:00
parent 5b0ab0a1a8
commit c8ee526adf
7 changed files with 203 additions and 172 deletions

View File

@@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Rebuild tools view

View File

@@ -1,11 +1,4 @@
import { import { MouseEventHandler, MutableRefObject, forwardRef, useCallback, useMemo, useRef } from "react";
MouseEventHandler,
MutableRefObject,
forwardRef,
useCallback,
useMemo,
useRef,
} from "react";
import { Image, ImageProps, Link, LinkProps } from "@chakra-ui/react"; import { Image, ImageProps, Link, LinkProps } from "@chakra-ui/react";
import appSettings from "../../services/settings/app-settings"; import appSettings from "../../services/settings/app-settings";

View File

@@ -22,56 +22,57 @@ export default function LightningSettings() {
return ( return (
<AccordionItem> <AccordionItem>
{({ isExpanded }) => (<> {({ isExpanded }) => (
<h2> <>
<AccordionButton fontSize="xl"> <h2>
<LightningIcon mr="2" /> <AccordionButton fontSize="xl">
<Box as="span" flex="1" textAlign="left"> <LightningIcon mr="2" />
Lightning <Box as="span" flex="1" textAlign="left">
</Box> Lightning
<AccordionIcon /> </Box>
</AccordionButton> <AccordionIcon />
</h2> </AccordionButton>
<AccordionPanel> </h2>
<Flex direction="column" gap="4"> <AccordionPanel>
{isExpanded && <Button />} <Flex direction="column" gap="4">
<FormControl> {isExpanded && <Button />}
<Flex alignItems="center"> <FormControl>
<FormLabel htmlFor="autoPayWithWebLN" mb="0"> <Flex alignItems="center">
Auto pay with WebLN <FormLabel htmlFor="autoPayWithWebLN" mb="0">
</FormLabel> Auto pay with WebLN
<Switch id="autoPayWithWebLN" {...register("autoPayWithWebLN")} /> </FormLabel>
<Switch id="autoPayWithWebLN" {...register("autoPayWithWebLN")} />
</Flex>
<FormHelperText>
<span>Enabled: Attempt to automatically pay with WebLN if its available</span>
</FormHelperText>
</FormControl>
<FormControl>
<FormLabel htmlFor="customZapAmounts" mb="0">
Zap Amounts
</FormLabel>
<Input
id="customZapAmounts"
autoComplete="off"
{...register("customZapAmounts", {
validate: (v) => {
if (!/^[\d,]*$/.test(v)) return "Must be a list of comma separated numbers";
return true;
},
})}
/>
{formState.errors.customZapAmounts && (
<FormErrorMessage>{formState.errors.customZapAmounts.message}</FormErrorMessage>
)}
<FormHelperText>
<span>Comma separated list of custom zap amounts</span>
</FormHelperText>
</FormControl>
</Flex> </Flex>
</AccordionPanel>
<FormHelperText> </>
<span>Enabled: Attempt to automatically pay with WebLN if its available</span>
</FormHelperText>
</FormControl>
<FormControl>
<FormLabel htmlFor="customZapAmounts" mb="0">
Zap Amounts
</FormLabel>
<Input
id="customZapAmounts"
autoComplete="off"
{...register("customZapAmounts", {
validate: (v) => {
if (!/^[\d,]*$/.test(v)) return "Must be a list of comma separated numbers";
return true;
},
})}
/>
{formState.errors.customZapAmounts && (
<FormErrorMessage>{formState.errors.customZapAmounts.message}</FormErrorMessage>
)}
<FormHelperText>
<span>Comma separated list of custom zap amounts</span>
</FormHelperText>
</FormControl>
</Flex>
</AccordionPanel>
</>
)} )}
</AccordionItem> </AccordionItem>
); );

View File

@@ -1,4 +1,4 @@
import { Flex } from "@chakra-ui/react"; import { Button, Flex } from "@chakra-ui/react";
import { memo, useRef } from "react"; import { memo, useRef } from "react";
import { Kind } from "nostr-tools"; import { Kind } from "nostr-tools";
@@ -12,6 +12,8 @@ import IntersectionObserverProvider, { useRegisterIntersectionEntity } from "../
import useSubject from "../../hooks/use-subject"; import useSubject from "../../hooks/use-subject";
import EmbeddedDM from "../../components/embed-event/event-types/embedded-dm"; import EmbeddedDM from "../../components/embed-event/event-types/embedded-dm";
import { NostrEvent } from "../../types/nostr-event"; import { NostrEvent } from "../../types/nostr-event";
import { ChevronLeftIcon } from "../../components/icons";
import { useNavigate } from "react-router-dom";
const DirectMessage = memo(({ dm }: { dm: NostrEvent }) => { const DirectMessage = memo(({ dm }: { dm: NostrEvent }) => {
const ref = useRef<HTMLDivElement | null>(null); const ref = useRef<HTMLDivElement | null>(null);
@@ -25,6 +27,7 @@ const DirectMessage = memo(({ dm }: { dm: NostrEvent }) => {
}); });
export function DMFeedPage() { export function DMFeedPage() {
const navigate = useNavigate();
const { listId, filter } = usePeopleListContext(); const { listId, filter } = usePeopleListContext();
const readRelays = useReadRelayUrls(); const readRelays = useReadRelayUrls();
@@ -48,6 +51,9 @@ export function DMFeedPage() {
return ( return (
<VerticalPageLayout> <VerticalPageLayout>
<Flex gap="2"> <Flex gap="2">
<Button leftIcon={<ChevronLeftIcon />} onClick={() => navigate(-1)}>
Back
</Button>
<PeopleListSelection /> <PeopleListSelection />
</Flex> </Flex>
<IntersectionObserverProvider callback={callback}> <IntersectionObserverProvider callback={callback}>

View File

@@ -1,105 +1,114 @@
import { Button, Divider, Flex, Heading, Image, Link } from "@chakra-ui/react"; import {
Button,
Card,
CardHeader,
ComponentWithAs,
Flex,
Heading,
IconProps,
Image,
Link,
LinkBox,
} from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom"; import { Link as RouterLink } from "react-router-dom";
import { ExternalLinkIcon, LiveStreamIcon, MapIcon, ToolsIcon } from "../../components/icons";
import VerticalPageLayout from "../../components/vertical-page-layout";
import { ConnectedRelays } from "../../components/connected-relays";
import { DirectMessagesIcon, ExternalLinkIcon, LiveStreamIcon, MapIcon, MuteIcon } from "../../components/icons";
import VerticalPageLayout from "../../components/vertical-page-layout";
import ShieldOff from "../../components/icons/shield-off";
import HoverLinkOverlay from "../../components/hover-link-overlay";
import Users01 from "../../components/icons/users-01";
import PackageSearch from "../../components/icons/package-search";
function InternalLink({
to,
icon: Icon,
children,
}: {
to?: string;
icon: ComponentWithAs<"svg", IconProps>;
children: string;
}) {
return (
<Card as={LinkBox} alignItems="center" p="4" gap="4" minW="40">
<Icon boxSize={10} />
<CardHeader p="0">
<Heading size="md">
<HoverLinkOverlay as={RouterLink} to={to}>
{children}
</HoverLinkOverlay>
</Heading>
</CardHeader>
</Card>
);
}
function ExternalLink({ href, image, children }: { href?: string; image: string; children: string }) {
return (
<Card as={LinkBox} alignItems="center" p="4" gap="4" minW="40">
<Image src={image} h="10" />
<CardHeader p="0">
<Heading size="md">
<HoverLinkOverlay as={Link} href={href} isExternal>
{children}
</HoverLinkOverlay>
</Heading>
</CardHeader>
</Card>
);
}
export default function ToolsHomeView() { export default function ToolsHomeView() {
return ( return (
<VerticalPageLayout> <VerticalPageLayout>
<Heading> <Heading>Tools</Heading>
<ToolsIcon /> Tools
</Heading>
<Divider />
<Flex wrap="wrap" gap="4"> <Flex wrap="wrap" gap="4">
<Button as={RouterLink} to="/tools/content-discovery"> <InternalLink to="/tools/content-discovery" icon={PackageSearch}>
Content Discovery DVM Discovery DVM
</Button> </InternalLink>
<Button as={RouterLink} to="/tools/network"> <InternalLink to="/tools/network" icon={Users01}>
Contact network User Network
</Button> </InternalLink>
<Button as={RouterLink} to="/tools/network-mute-graph"> <InternalLink to="/tools/network-mute-graph" icon={MuteIcon}>
Contacts Mute Graph Mute Graph
</Button> </InternalLink>
<Button as={RouterLink} to="/tools/network-dm-graph"> <InternalLink to="/tools/network-dm-graph" icon={DirectMessagesIcon}>
Contacts DM Graph DM Graph
</Button> </InternalLink>
<Button as={RouterLink} to="/tools/dm-feed"> <InternalLink to="/tools/dm-feed" icon={ShieldOff}>
DM Feed DM Feed
</Button> </InternalLink>
<Button as={RouterLink} to="/map" leftIcon={<MapIcon />}> <InternalLink to="/map" icon={MapIcon}>
Map Map
</Button> </InternalLink>
<Button as={RouterLink} to="/tools/stream-moderation" leftIcon={<LiveStreamIcon />}> <InternalLink to="/tools/stream-moderation" icon={LiveStreamIcon}>
Stream Moderation Stream Moderation
</Button> </InternalLink>
<ConnectedRelays />
</Flex> </Flex>
<Heading size="lg" mt="4"> <Heading size="lg" mt="4">
Third party tools Third party tools
</Heading> </Heading>
<Divider />
<Flex wrap="wrap" gap="4"> <Flex wrap="wrap" gap="4">
<Button <ExternalLink href="https://w3.do/" image="https://w3.do/favicon.ico">
as={Link}
href="https://w3.do/"
isExternal
target="_blank"
leftIcon={<Image src="https://w3.do/favicon.ico" h="1.5em" />}
>
URL Shortener URL Shortener
</Button> </ExternalLink>
<Button <ExternalLink href="https://nak.nostr.com/" image="https://nak.nostr.com/favicon.ico">
as={Link}
href="https://nak.nostr.com/"
isExternal
target="_blank"
leftIcon={<Image src="https://nak.nostr.com/favicon.ico" h="1.5em" />}
>
nostr army knife nostr army knife
</Button> </ExternalLink>
<Button <ExternalLink href="https://nostr-delete.vercel.app/" image="https://nostr-delete.vercel.app/favicon.png">
as={Link}
href="https://nostr-delete.vercel.app/"
isExternal
target="_blank"
leftIcon={<ExternalLinkIcon />}
>
Nostr Event Deletion Nostr Event Deletion
</Button> </ExternalLink>
<Button <ExternalLink href="https://nostrdebug.com/" image="https://nostrdebug.com/favicon.ico">
as={Link}
href="https://nostrdebug.com/"
isExternal
target="_blank"
leftIcon={<Image src="https://nostrdebug.com/favicon.ico" h="1.5em" />}
>
Nostr Debug Nostr Debug
</Button> </ExternalLink>
<Button <ExternalLink href="https://metadata.nostr.com/" image="https://metadata.nostr.com/img/git.png">
as={Link}
href="https://metadata.nostr.com/"
isExternal
target="_blank"
leftIcon={<Image src="https://metadata.nostr.com/img/git.png" h="1.5em" />}
>
Nostr Profile Manager Nostr Profile Manager
</Button> </ExternalLink>
<Button <ExternalLink
as={Link}
href="https://www.nostrapps.com/" href="https://www.nostrapps.com/"
isExternal image="https://uploads-ssl.webflow.com/641d0d46d5c124ac928a6027/64b1dd06d59d8f1e530d2926_32x32.png"
target="_blank"
leftIcon={
<Image
src="https://uploads-ssl.webflow.com/641d0d46d5c124ac928a6027/64b1dd06d59d8f1e530d2926_32x32.png"
h="1.5em"
/>
}
> >
Nostr Apps Nostr Apps
</Button> </ExternalLink>
</Flex> </Flex>
</VerticalPageLayout> </VerticalPageLayout>
); );

View File

@@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { Box, Flex, Input, Text } from "@chakra-ui/react"; import { Box, Button, Flex, Input, Text } from "@chakra-ui/react";
import AutoSizer from "react-virtualized-auto-sizer"; import AutoSizer from "react-virtualized-auto-sizer";
import ForceGraph, { LinkObject, NodeObject } from "react-force-graph-3d"; import ForceGraph, { LinkObject, NodeObject } from "react-force-graph-3d";
import { Kind } from "nostr-tools"; import { Kind } from "nostr-tools";
@@ -28,10 +28,13 @@ import RelaySelectionProvider, { useRelaySelectionContext } from "../../provider
import RelaySelectionButton from "../../components/relay-selection/relay-selection-button"; import RelaySelectionButton from "../../components/relay-selection/relay-selection-button";
import { useDebounce } from "react-use"; import { useDebounce } from "react-use";
import useSubject from "../../hooks/use-subject"; import useSubject from "../../hooks/use-subject";
import { ChevronLeftIcon } from "../../components/icons";
import { useNavigate } from "react-router-dom";
type NodeType = { id: string; image?: string; name?: string }; type NodeType = { id: string; image?: string; name?: string };
function NetworkDMGraphPage() { function NetworkDMGraphPage() {
const navigate = useNavigate();
const account = useCurrentAccount()!; const account = useCurrentAccount()!;
const { relays } = useRelaySelectionContext(); const { relays } = useRelaySelectionContext();
@@ -110,6 +113,9 @@ function NetworkDMGraphPage() {
return ( return (
<Flex direction="column" gap="2" h="full" pt="2"> <Flex direction="column" gap="2" h="full" pt="2">
<Flex gap="2" alignItems="center"> <Flex gap="2" alignItems="center">
<Button leftIcon={<ChevronLeftIcon />} onClick={() => navigate(-1)}>
Back
</Button>
<Input <Input
type="datetime-local" type="datetime-local"
maxW="sm" maxW="sm"

View File

@@ -1,5 +1,5 @@
import { useMemo, useRef } from "react"; import { useMemo, useRef } from "react";
import { Box } from "@chakra-ui/react"; import { Box, Button, Flex, Text } from "@chakra-ui/react";
import AutoSizer from "react-virtualized-auto-sizer"; import AutoSizer from "react-virtualized-auto-sizer";
import ForceGraph, { LinkObject, NodeObject } from "react-force-graph-3d"; import ForceGraph, { LinkObject, NodeObject } from "react-force-graph-3d";
import { import {
@@ -22,6 +22,8 @@ import { useReadRelayUrls } from "../../hooks/use-client-relays";
import replaceableEventLoaderService from "../../services/replaceable-event-requester"; import replaceableEventLoaderService from "../../services/replaceable-event-requester";
import useSubjects from "../../hooks/use-subjects"; import useSubjects from "../../hooks/use-subjects";
import { useUserMetadata } from "../../hooks/use-user-metadata"; import { useUserMetadata } from "../../hooks/use-user-metadata";
import { useNavigate } from "react-router-dom";
import { ChevronLeftIcon } from "../../components/icons";
export function useUsersMuteLists(pubkeys: string[], additionalRelays: string[] = []) { export function useUsersMuteLists(pubkeys: string[], additionalRelays: string[] = []) {
const readRelays = useReadRelayUrls(additionalRelays); const readRelays = useReadRelayUrls(additionalRelays);
@@ -34,6 +36,7 @@ export function useUsersMuteLists(pubkeys: string[], additionalRelays: string[]
type NodeType = { id: string; image?: string; name?: string }; type NodeType = { id: string; image?: string; name?: string };
function NetworkGraphPage() { function NetworkGraphPage() {
const navigate = useNavigate();
const account = useCurrentAccount()!; const account = useCurrentAccount()!;
const selfMetadata = useUserMetadata(account.pubkey); const selfMetadata = useUserMetadata(account.pubkey);
@@ -82,44 +85,52 @@ function NetworkGraphPage() {
}, [contacts, usersMuteLists, usersMetadata, selfMetadata]); }, [contacts, usersMuteLists, usersMetadata, selfMetadata]);
return ( return (
<Box overflow="hidden" flex={1}> <Flex direction="column" gap="2" h="full" pt="2">
<AutoSizer> <Flex gap="2" alignItems="center">
{({ height, width }) => ( <Button leftIcon={<ChevronLeftIcon />} onClick={() => navigate(-1)}>
<ForceGraph<NodeType> Back
graphData={graphData} </Button>
enableNodeDrag={false} <Text>Showing how many of your contacts are muting each other</Text>
width={width} </Flex>
height={height} <Box overflow="hidden" flex={1}>
linkDirectionalArrowLength={3.5} <AutoSizer>
linkDirectionalArrowRelPos={1} {({ height, width }) => (
linkCurvature={0.25} <ForceGraph<NodeType>
nodeThreeObject={(node: NodeType) => { graphData={graphData}
if (!node.image) { enableNodeDrag={false}
return new Mesh(new SphereGeometry(5, 12, 6), new MeshBasicMaterial({ color: 0xaa0f0f })); width={width}
} height={height}
linkDirectionalArrowLength={3.5}
linkDirectionalArrowRelPos={1}
linkCurvature={0.25}
nodeThreeObject={(node: NodeType) => {
if (!node.image) {
return new Mesh(new SphereGeometry(5, 12, 6), new MeshBasicMaterial({ color: 0xaa0f0f }));
}
const group = new Group(); const group = new Group();
const imgTexture = new TextureLoader().load(node.image); const imgTexture = new TextureLoader().load(node.image);
imgTexture.colorSpace = SRGBColorSpace; imgTexture.colorSpace = SRGBColorSpace;
const material = new SpriteMaterial({ map: imgTexture }); const material = new SpriteMaterial({ map: imgTexture });
const sprite = new Sprite(material); const sprite = new Sprite(material);
sprite.scale.set(10, 10, 10); sprite.scale.set(10, 10, 10);
group.children.push(sprite); group.children.push(sprite);
// if (node.name) { // if (node.name) {
// const text = new SpriteText(node.name, 8, "ffffff"); // const text = new SpriteText(node.name, 8, "ffffff");
// text.position.set(0, 0, 16); // text.position.set(0, 0, 16);
// group.children.push(text); // group.children.push(text);
// } // }
return sprite; return sprite;
}} }}
/> />
)} )}
</AutoSizer> </AutoSizer>
</Box> </Box>
</Flex>
); );
} }