import { Dialog, Transition } from "@headlessui/react"; import { createBlock } from "@libs/storage"; import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk"; import { CancelIcon, CommandIcon } from "@shared/icons"; import { Image } from "@shared/image"; import { RelayContext } from "@shared/relayProvider"; import { DEFAULT_AVATAR } from "@stores/constants"; import { ADD_IMAGEBLOCK_SHORTCUT } from "@stores/shortcuts"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { open } from "@tauri-apps/api/dialog"; import { Body, fetch } from "@tauri-apps/api/http"; import { createBlobFromFile } from "@utils/createBlobFromFile"; import { dateToUnix } from "@utils/date"; import { useAccount } from "@utils/hooks/useAccount"; import { Fragment, useContext, useEffect, useRef, useState } from "react"; import { useForm } from "react-hook-form"; import { useHotkeys } from "react-hotkeys-hook"; export function AddImageBlock() { const ndk = useContext(RelayContext); const queryClient = useQueryClient(); const [loading, setLoading] = useState(false); const [isOpen, setIsOpen] = useState(false); const [image, setImage] = useState(""); const { account } = useAccount(); const tags = useRef(null); const openModal = () => { setIsOpen(true); }; const closeModal = () => { setIsOpen(false); }; useHotkeys(ADD_IMAGEBLOCK_SHORTCUT, () => openModal()); const { register, handleSubmit, reset, setValue, formState: { isDirty, isValid }, } = useForm(); const openFileDialog = async () => { const selected: any = await open({ multiple: false, filters: [ { name: "Image", extensions: ["png", "jpeg", "jpg"], }, ], }); if (Array.isArray(selected)) { // user selected multiple files } else if (selected === null) { // user cancelled the selection } else { const filename = selected.split("/").pop(); const file = await createBlobFromFile(selected); const buf = await file.arrayBuffer(); const res: any = await fetch("https://void.cat/upload?cli=false", { method: "POST", timeout: 5, headers: { accept: "*/*", "Content-Type": "application/octet-stream", "V-Filename": filename, "V-Description": "Upload from https://lume.nu", "V-Strip-Metadata": "true", }, body: Body.bytes(buf), }); if (res.ok) { const imageURL = `https://void.cat/d/${res.data.file.id}.webp`; tags.current = [ ["url", imageURL], ["m", res.data.file.metadata.mimeType], ["x", res.data.file.metadata.digest], ["size", res.data.file.metadata.size], ["magnet", res.data.file.metadata.magnetLink], ]; setImage(imageURL); } } }; const block = useMutation({ mutationFn: (data: any) => { return createBlock(data.kind, data.title, data.content); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["blocks"] }); }, }); const onSubmit = (data: any) => { setLoading(true); const signer = new NDKPrivateKeySigner(account.privkey); ndk.signer = signer; const event = new NDKEvent(ndk); // build event event.content = data.title; event.kind = 1063; event.created_at = dateToUnix(); event.pubkey = account.pubkey; event.tags = tags.current; // publish event event.publish(); // mutate block.mutate({ kind: 0, title: data.title, content: data.content }); setLoading(false); // reset form reset(); // close modal closeModal(); }; useEffect(() => { setValue("content", image); }, [setValue, image]); return ( <> openModal()} className="inline-flex w-56 h-9 items-center justify-start gap-2.5 rounded-md px-2.5" > I New image block Create image block Pin your favorite image to Space then you can view every time that you use Lume, your image will be broadcast to Nostr Relay as well Title * Picture openFileDialog()} type="button" className="inline-flex h-6 items-center justify-center rounded bg-zinc-900 px-3 text-sm font-medium text-zinc-300 ring-1 ring-zinc-800 hover:bg-zinc-800" > Upload {loading ? ( Loading ) : ( "Confirm" )} > ); }