some work

This commit is contained in:
hzrd149
2023-09-07 11:27:01 -05:00
parent 9c93a3d9bf
commit bd50ab2ec7
3 changed files with 85 additions and 30 deletions

View File

@@ -48,6 +48,9 @@ export default function NavItems({ isInDrawer = false }: { isInDrawer?: boolean
<Button onClick={() => navigate("/streams")} leftIcon={<LiveStreamIcon />} justifyContent="flex-start"> <Button onClick={() => navigate("/streams")} leftIcon={<LiveStreamIcon />} justifyContent="flex-start">
Streams Streams
</Button> </Button>
<Button onClick={() => navigate("/files")} leftIcon={<FileIcon />} justifyContent="flex-start">
Files
</Button>
<Button onClick={() => navigate("/lists")} leftIcon={<ListIcon />} justifyContent="flex-start"> <Button onClick={() => navigate("/lists")} leftIcon={<ListIcon />} justifyContent="flex-start">
Lists Lists
</Button> </Button>
@@ -57,9 +60,6 @@ export default function NavItems({ isInDrawer = false }: { isInDrawer?: boolean
<Button onClick={() => navigate("/emojis")} leftIcon={<EmojiIcon />} justifyContent="flex-start"> <Button onClick={() => navigate("/emojis")} leftIcon={<EmojiIcon />} justifyContent="flex-start">
Emojis Emojis
</Button> </Button>
<Button onClick={() => navigate("/files")} leftIcon={<FileIcon />} justifyContent="flex-start">
Files
</Button>
<Button onClick={() => navigate("/map")} leftIcon={<MapIcon />} justifyContent="flex-start"> <Button onClick={() => navigate("/map")} leftIcon={<MapIcon />} justifyContent="flex-start">
Map Map
</Button> </Button>

View File

@@ -12,8 +12,14 @@ export type ParsedImageFile = {
blurhash?: string; blurhash?: string;
}; };
export function parseImageFile(event: NostrEvent): ParsedImageFile { export function getFileUrl(event: NostrEvent) {
const url = event.tags.find((t) => t[0] === "url" && t[1])?.[1]; const url = event.tags.find((t) => t[0] === "url" && t[1])?.[1];
if (!url) throw new Error("Missing url");
return url;
}
export function parseImageFile(event: NostrEvent): ParsedImageFile {
const url = getFileUrl(event);
const mimeType = event.tags.find((t) => t[0] === "m" && t[1])?.[1]; const mimeType = event.tags.find((t) => t[0] === "m" && t[1])?.[1];
const magnet = event.tags.find((t) => t[0] === "magnet" && t[1])?.[1]; const magnet = event.tags.find((t) => t[0] === "magnet" && t[1])?.[1];
const infoHash = event.tags.find((t) => t[0] === "i" && t[1])?.[1]; const infoHash = event.tags.find((t) => t[0] === "i" && t[1])?.[1];
@@ -24,7 +30,6 @@ export function parseImageFile(event: NostrEvent): ParsedImageFile {
const dimensions = event.tags.find((t) => t[0] === "dim" && t[1])?.[1]; const dimensions = event.tags.find((t) => t[0] === "dim" && t[1])?.[1];
const [width, height] = dimensions?.split("x").map((v) => parseInt(v)) ?? []; const [width, height] = dimensions?.split("x").map((v) => parseInt(v)) ?? [];
if (!url) throw new Error("missing url");
if (!mimeType) throw new Error("missing MIME Type"); if (!mimeType) throw new Error("missing MIME Type");
if (width !== undefined && height !== undefined) { if (width !== undefined && height !== undefined) {
if (!Number.isFinite(width) || !Number.isFinite(height)) throw new Error("bad dimensions"); if (!Number.isFinite(width) || !Number.isFinite(height)) throw new Error("bad dimensions");

View File

@@ -20,12 +20,19 @@ import useTimelineLoader from "../../hooks/use-timeline-loader";
import { useReadRelayUrls } from "../../hooks/use-client-relays"; import { useReadRelayUrls } from "../../hooks/use-client-relays";
import useSubject from "../../hooks/use-subject"; import useSubject from "../../hooks/use-subject";
import { NostrEvent } from "../../types/nostr-event"; import { NostrEvent } from "../../types/nostr-event";
import { parseImageFile } from "../../helpers/nostr/files"; import { getFileUrl, parseImageFile } from "../../helpers/nostr/files";
import BlurhashImage from "../../components/blurhash-image"; import BlurhashImage from "../../components/blurhash-image";
import { ErrorBoundary } from "../../components/error-boundary"; import { ErrorBoundary } from "../../components/error-boundary";
import useAppSettings from "../../hooks/use-app-settings"; import useAppSettings from "../../hooks/use-app-settings";
import { useTrusted } from "../../providers/trust"; import { TrustProvider, useTrusted } from "../../providers/trust";
import BlurredImage from "../../components/blured-image"; import BlurredImage from "../../components/blured-image";
import PeopleListProvider, { usePeopleListContext } from "../../providers/people-list-provider";
import RelaySelectionProvider, { useRelaySelectionContext } from "../../providers/relay-selection-provider";
import PeopleListSelection from "../../components/people-list-selection/people-list-selection";
import RelaySelectionButton from "../../components/relay-selection/relay-selection-button";
import { UserAvatar } from "../../components/user-avatar";
import { UserAvatarLink } from "../../components/user-avatar-link";
import { UserLink } from "../../components/user-link";
const FILE_KIND = 1063; const FILE_KIND = 1063;
const VIDEO_TYPES = ["video/mp4", "video/webm"]; const VIDEO_TYPES = ["video/mp4", "video/webm"];
@@ -40,23 +47,45 @@ function ImageFile({ event }: { event: NostrEvent }) {
const shouldBlur = settings.blurImages && !trust; const shouldBlur = settings.blurImages && !trust;
const showImage = useDisclosure(); // const showImage = useDisclosure();
if (shouldBlur && parsed.blurhash && parsed.width && parsed.height && !showImage.isOpen) { // if (shouldBlur && parsed.blurhash && parsed.width && parsed.height && !showImage.isOpen) {
const aspect = parsed.width / parsed.height; // const aspect = parsed.width / parsed.height;
// return (
// <BlurhashImage
// blurhash={parsed.blurhash}
// width={64 * aspect}
// height={64}
// onClick={showImage.onOpen}
// cursor="pointer"
// w="full"
// />
// );
// }
const ImageComponent = shouldBlur ? BlurredImage : Image;
return ( return (
<BlurhashImage <Flex direction="column" gap="2">
blurhash={parsed.blurhash} <Flex gap="2" alignItems="center">
width={64 * aspect} <UserAvatarLink pubkey={event.pubkey} size="sm" />
height={64} <UserLink pubkey={event.pubkey} fontWeight="bold" />
onClick={showImage.onOpen} </Flex>
cursor="pointer" <ImageComponent src={parsed.url} w="full" />
w="full" </Flex>
/>
); );
} }
const ImageComponent = shouldBlur ? BlurredImage : Image; function VideoFile({ event }: { event: NostrEvent }) {
return <ImageComponent src={parsed.url} w="full" />; const url = getFileUrl(event);
return (
<Flex direction="column" gap="2">
<Flex gap="2" alignItems="center">
<UserAvatarLink pubkey={event.pubkey} size="sm" />
<UserLink pubkey={event.pubkey} fontWeight="bold" />
</Flex>
<video src={url} controls />
</Flex>
);
} }
function FileType({ event }: { event: NostrEvent }) { function FileType({ event }: { event: NostrEvent }) {
@@ -65,12 +94,22 @@ function FileType({ event }: { event: NostrEvent }) {
if (!mimeType) throw new Error("missing MIME type"); if (!mimeType) throw new Error("missing MIME type");
if (IMAGE_TYPES.includes(mimeType)) { if (IMAGE_TYPES.includes(mimeType)) {
return <ImageFile event={event} />; return (
<TrustProvider trust>
<ImageFile event={event} />
</TrustProvider>
);
}
if (VIDEO_TYPES.includes(mimeType)) {
return <VideoFile event={event} />;
} }
return <Text>Unknown mine type {mimeType}</Text>; return <Text>Unknown mine type {mimeType}</Text>;
} }
export default function FilesView() { function FilesPage() {
const { listId, filter } = usePeopleListContext();
const { relays } = useRelaySelectionContext();
const [selectedTypes, setSelectedTypes] = useState<string[]>(IMAGE_TYPES); const [selectedTypes, setSelectedTypes] = useState<string[]>(IMAGE_TYPES);
const toggleType = useCallback( const toggleType = useCallback(
(type: string) => { (type: string) => {
@@ -80,22 +119,22 @@ export default function FilesView() {
} else return arr.concat(type); } else return arr.concat(type);
}); });
}, },
[setSelectedTypes] [setSelectedTypes],
); );
const relays = useReadRelayUrls();
const timeline = useTimelineLoader( const timeline = useTimelineLoader(
"files", `${listId}-files`,
relays, relays,
{ kinds: [FILE_KIND], "#m": selectedTypes }, { kinds: [FILE_KIND], "#m": selectedTypes, ...filter },
{ enabled: selectedTypes.length > 0 } { enabled: selectedTypes.length > 0 && !!filter },
); );
const events = useSubject(timeline.timeline); const events = useSubject(timeline.timeline);
return ( return (
<Flex direction="column" gap="2" p="2"> <Flex direction="column" gap="2" p="2">
<Flex> <Flex gap="2">
<PeopleListSelection />
<Popover> <Popover>
<PopoverTrigger> <PopoverTrigger>
<Button>{selectedTypes.length} Selected types</Button> <Button>{selectedTypes.length} Selected types</Button>
@@ -145,6 +184,7 @@ export default function FilesView() {
</PopoverBody> </PopoverBody>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
<RelaySelectionButton ml="auto" />
</Flex> </Flex>
<SimpleGrid minChildWidth="20rem" spacing="2"> <SimpleGrid minChildWidth="20rem" spacing="2">
@@ -158,3 +198,13 @@ export default function FilesView() {
</Flex> </Flex>
); );
} }
export default function FilesView() {
return (
<PeopleListProvider>
<RelaySelectionProvider>
<FilesPage />
</RelaySelectionProvider>
</PeopleListProvider>
);
}