remove broken torrent preview view

remove test DM windows
This commit is contained in:
hzrd149 2023-12-07 11:30:15 -06:00
parent 6d0fd9e960
commit 3a3851aa91
7 changed files with 0 additions and 369 deletions

View File

@ -62,7 +62,6 @@
"three": "^0.157.0",
"three-spritetext": "^1.8.1",
"webln": "^0.3.2",
"webtorrent": "^2.1.29",
"yet-another-react-lightbox": "^3.12.1"
},
"devDependencies": {
@ -79,7 +78,6 @@
"@types/react-dom": "^18.2.7",
"@types/three": "^0.157.2",
"@types/webscopeio__react-textarea-autocomplete": "^4.7.2",
"@types/webtorrent": "^0.109.7",
"@vitejs/plugin-react": "^4.0.4",
"camelcase": "^8.0.0",
"prettier": "^3.0.2",

View File

@ -95,7 +95,6 @@ const ChannelView = lazy(() => import("./views/channels/channel"));
const TorrentsView = lazy(() => import("./views/torrents"));
const TorrentDetailsView = lazy(() => import("./views/torrents/torrent"));
const TorrentPreviewView = lazy(() => import("./views/torrents/preview"));
const NewTorrentView = lazy(() => import("./views/torrents/new"));
const overrideReactTextareaAutocompleteStyles = css`
@ -289,10 +288,6 @@ const router = createHashRouter([
},
],
},
{
path: "torrents/:id/preview",
element: <TorrentPreviewView />,
},
{
path: "torrents",
children: [

View File

@ -1,121 +0,0 @@
import { useState } from "react";
import { Button, Card, CardBody, CardHeader, CloseButton, Flex, Heading, IconButton, useToast } from "@chakra-ui/react";
import { Kind } from "nostr-tools";
import dayjs from "dayjs";
import { useForm } from "react-hook-form";
import { ChevronDownIcon, ChevronUpIcon } from "../icons";
import UserName from "../user-name";
import MagicTextArea from "../magic-textarea";
import useTimelineLoader from "../../hooks/use-timeline-loader";
import useCurrentAccount from "../../hooks/use-current-account";
import { useReadRelayUrls, useWriteRelayUrls } from "../../hooks/use-client-relays";
import { useUserRelays } from "../../hooks/use-user-relays";
import { RelayMode } from "../../classes/relay";
import { useTimelineCurserIntersectionCallback } from "../../hooks/use-timeline-cursor-intersection-callback";
import IntersectionObserverProvider from "../../providers/intersection-observer";
import useSubject from "../../hooks/use-subject";
import MessageBlock from "../../views/dms/message-block";
import { LightboxProvider } from "../lightbox-provider";
import { useSigningContext } from "../../providers/signing-provider";
import { DraftNostrEvent } from "../../types/nostr-event";
import NostrPublishAction from "../../classes/nostr-publish-action";
import { correctContentMentions, createEmojiTags } from "../../helpers/nostr/post";
import { useContextEmojis } from "../../providers/emoji-provider";
export default function ChatWindow({ pubkey, onClose }: { pubkey: string; onClose: () => void }) {
const toast = useToast();
const account = useCurrentAccount()!;
const emojis = useContextEmojis();
const [expanded, setExpanded] = useState(true);
const usersRelays = useUserRelays(pubkey);
const readRelays = useReadRelayUrls(usersRelays.filter((c) => c.mode & RelayMode.WRITE).map((c) => c.url));
const writeRelays = useWriteRelayUrls(usersRelays.filter((c) => c.mode & RelayMode.WRITE).map((c) => c.url));
const timeline = useTimelineLoader(`${pubkey}-${account.pubkey}-messages`, readRelays, [
{ authors: [account.pubkey], kinds: [Kind.EncryptedDirectMessage], "#p": [pubkey] },
{ authors: [pubkey], kinds: [Kind.EncryptedDirectMessage], "#p": [account.pubkey] },
]);
const { handleSubmit, getValues, setValue, formState, watch, reset } = useForm({ defaultValues: { content: "" } });
watch("content");
const { requestSignature, requestEncrypt } = useSigningContext();
const submit = handleSubmit(async (values) => {
try {
if (!values.content) return;
let draft: DraftNostrEvent = {
kind: Kind.EncryptedDirectMessage,
content: values.content,
tags: [["p", pubkey]],
created_at: dayjs().unix(),
};
draft = createEmojiTags(draft, emojis);
draft.content = correctContentMentions(draft.content);
// encrypt content
draft.content = await requestEncrypt(draft.content, pubkey);
const signed = await requestSignature(draft);
const pub = new NostrPublishAction("Send DM", writeRelays, signed);
reset();
} catch (e) {
if (e instanceof Error) toast({ status: "error", description: e.message });
}
});
const messages = useSubject(timeline.timeline);
const callback = useTimelineCurserIntersectionCallback(timeline);
return (
<Card size="sm" borderRadius="md" w={expanded ? "md" : "xs"} variant="outline">
<CardHeader display="flex" gap="2" alignItems="center">
<Heading size="md" mr="8">
<UserName pubkey={pubkey} />
</Heading>
<IconButton
aria-label="Toggle Window"
onClick={() => setExpanded((v) => !v)}
variant="ghost"
icon={expanded ? <ChevronDownIcon /> : <ChevronUpIcon />}
ml="auto"
size="sm"
/>
<CloseButton onClick={onClose} />
</CardHeader>
{expanded && (
<>
<CardBody
maxH="lg"
overflowX="hidden"
overflowY="auto"
pt="0"
display="flex"
flexDirection="column-reverse"
gap="2"
>
<LightboxProvider>
<IntersectionObserverProvider callback={callback}>
{messages.map((event) => (
<MessageBlock key={event.id} events={event} />
))}
</IntersectionObserverProvider>
</LightboxProvider>
</CardBody>
<Flex as="form" onSubmit={submit} gap="2">
<MagicTextArea
isRequired
value={getValues().content}
onChange={(e) => setValue("content", e.target.value, { shouldDirty: true })}
/>
<Button type="submit" isLoading={formState.isSubmitting}>
Send
</Button>
</Flex>
</>
)}
</Card>
);
}

View File

@ -1,90 +0,0 @@
import { useEffect, useMemo, useState } from "react";
import {
Alert,
AlertIcon,
Button,
Card,
CardBody,
CardHeader,
CloseButton,
Heading,
IconButton,
Input,
InputGroup,
InputLeftElement,
} from "@chakra-ui/react";
import dayjs from "dayjs";
import { ChevronDownIcon, ChevronUpIcon, SearchIcon } from "../icons";
import useSubject from "../../hooks/use-subject";
import directMessagesService from "../../services/direct-messages";
import UserAvatar from "../user-avatar";
import UserName from "../user-name";
export default function ContactsWindow({
onClose,
onSelectPubkey,
}: {
onClose: () => void;
onSelectPubkey: (pubkey: string) => void;
}) {
const [expanded, setExpanded] = useState(true);
// TODO: find a better way to load recent contacts
const [from, setFrom] = useState(() => dayjs().subtract(2, "days").unix());
const conversations = useSubject(directMessagesService.conversations);
useEffect(() => directMessagesService.loadDateRange(from), [from]);
const sortedConversations = useMemo(() => {
return Array.from(conversations).sort((a, b) => {
const latestA = directMessagesService.getUserMessages(a).value[0]?.created_at ?? 0;
const latestB = directMessagesService.getUserMessages(b).value[0]?.created_at ?? 0;
return latestB - latestA;
});
}, [conversations]);
return (
<Card size="sm" borderRadius="md" minW={expanded ? "sm" : 0}>
<CardHeader display="flex" gap="2" alignItems="center">
<Heading size="md" mr="8">
Contacts
</Heading>
<IconButton
aria-label="Toggle Window"
onClick={() => setExpanded((v) => !v)}
variant="ghost"
icon={expanded ? <ChevronDownIcon /> : <ChevronUpIcon />}
ml="auto"
size="sm"
/>
<CloseButton onClick={onClose} />
</CardHeader>
{expanded && (
<CardBody maxH="lg" overflowX="hidden" overflowY="auto" pt="0" display="flex" flexDirection="column" gap="2">
<Alert status="warning">
<AlertIcon />
Work in progress!
</Alert>
{/* <InputGroup>
<InputLeftElement pointerEvents="none">
<SearchIcon />
</InputLeftElement>
<Input autoFocus />
</InputGroup> */}
{sortedConversations.map((pubkey) => (
<Button
key={pubkey}
leftIcon={<UserAvatar pubkey={pubkey} size="sm" />}
justifyContent="flex-start"
p="2"
variant="ghost"
onClick={() => onSelectPubkey(pubkey)}
>
<UserName pubkey={pubkey} />
</Button>
))}
</CardBody>
)}
</Card>
);
}

View File

@ -1,56 +0,0 @@
import { Flex, IconButton } from "@chakra-ui/react";
import { useCallback, useState } from "react";
import { useLocalStorage } from "react-use";
import ContactsWindow from "./contacts-window";
import { DirectMessagesIcon } from "../icons";
import ChatWindow from "./chat-window";
import useCurrentAccount from "../../hooks/use-current-account";
export default function ChatWindows() {
const account = useCurrentAccount();
const [pubkeys, setPubkeys] = useState<string[]>([]);
const [show, setShow] = useLocalStorage("show-chat-windows", false);
const openPubkey = useCallback(
(pubkey: string) => {
setPubkeys((keys) => (keys.includes(pubkey) ? keys : keys.concat(pubkey)));
},
[setPubkeys],
);
const closePubkey = useCallback(
(pubkey: string) => {
setPubkeys((keys) => keys.filter((key) => key !== pubkey));
},
[setPubkeys],
);
if (!account) {
return null;
}
if (!show) {
return (
<IconButton
icon={<DirectMessagesIcon boxSize={6} />}
aria-label="Show Contacts"
onClick={() => setShow(true)}
position="fixed"
bottom="0"
right="0"
size="lg"
zIndex={1}
/>
);
}
return (
<Flex direction="row-reverse" position="fixed" bottom="0" right="0" gap="4" alignItems="flex-end" zIndex={1}>
<ContactsWindow onClose={() => setShow(false)} onSelectPubkey={openPubkey} />
{pubkeys.map((pubkey) => (
<ChatWindow key={pubkey} pubkey={pubkey} onClose={() => closePubkey(pubkey)} />
))}
</Flex>
);
}

View File

@ -12,7 +12,6 @@ import GhostToolbar from "./ghost-toolbar";
import { useBreakpointValue } from "../../providers/breakpoint-provider";
import SearchModal from "../search-modal";
import { useLocation } from "react-router-dom";
// import ChatWindows from "../chat-windows";
export default function Layout({ children }: { children: React.ReactNode }) {
const isMobile = useBreakpointValue({ base: true, md: false });
@ -66,7 +65,6 @@ export default function Layout({ children }: { children: React.ReactNode }) {
</Flex>
{isGhost && <GhostToolbar />}
{searchModal.isOpen && <SearchModal isOpen onClose={searchModal.onClose} />}
{/* {!isMobile && <ChatWindows />} */}
</>
);
}

View File

@ -1,93 +0,0 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { Button, Code, Flex, Spinner, useForceUpdate } from "@chakra-ui/react";
import WebTorrent from "../../lib/webtorrent";
import type { Torrent } from "webtorrent";
import { safeDecode } from "../../helpers/nip19";
import useSingleEvent from "../../hooks/use-single-event";
import { ErrorBoundary } from "../../components/error-boundary";
import { getTorrentMagnetLink } from "../../helpers/nostr/torrents";
import VerticalPageLayout from "../../components/vertical-page-layout";
import { ChevronLeftIcon } from "../../components/icons";
import { NostrEvent } from "../../types/nostr-event";
const client = new WebTorrent();
// @ts-ignore
window.torrentClient = client;
function TorrentPreview({ torrent }: { torrent: Torrent; event: NostrEvent }) {
const update = useForceUpdate();
const preview = useRef<HTMLDivElement | null>(null);
useEffect(() => {
torrent.on("metadata", update);
torrent.on("ready", update);
torrent.on("done", update);
return () => {
// torrent.off("metadata", update);
};
}, [torrent]);
return (
<Flex gap="4">
<Flex direction="column">
{torrent.files.map((file) => (
<Button key={file.path}>{file.name}</Button>
))}
</Flex>
<Code as="pre">{JSON.stringify({ ready: torrent.ready, name: torrent.name }, null, 2)}</Code>
<div ref={preview} />
</Flex>
);
}
function TorrentPreviewPage({ event }: { event: NostrEvent }) {
const navigate = useNavigate();
const magnet = getTorrentMagnetLink(event);
const [torrent, setTorrent] = useState<Torrent>();
useEffect(() => {
setTorrent(
client.add(magnet, (t) => {
console.log(t);
}),
);
return () => {
client.remove(magnet);
setTorrent(undefined);
};
}, [magnet]);
return (
<VerticalPageLayout>
<Flex gap="2">
<Button leftIcon={<ChevronLeftIcon />} onClick={() => navigate(-1)}>
Back
</Button>
</Flex>
{torrent && <TorrentPreview torrent={torrent} event={event} />}
</VerticalPageLayout>
);
}
export default function TorrentPreviewView() {
const { id } = useParams() as { id: string };
const parsed = useMemo(() => {
const result = safeDecode(id);
if (!result) return;
if (result.type === "note") return { id: result.data };
if (result.type === "nevent") return result.data;
}, [id]);
const torrent = useSingleEvent(parsed?.id, parsed?.relays ?? []);
if (!torrent) return <Spinner />;
return (
<ErrorBoundary>
<TorrentPreviewPage event={torrent} />
</ErrorBoundary>
);
}