added upload image directly to void.cat to image picker

This commit is contained in:
Ren Amamiya
2023-04-20 17:41:23 +07:00
parent 4a013ffb33
commit df2f6b0ce7
7 changed files with 339 additions and 50 deletions

View File

@@ -1,5 +1,4 @@
import EmojiPicker from '@components/form/emojiPicker';
import ImagePicker from '@components/form/imagePicker';
import { ImagePicker } from '@components/form/imagePicker';
import { RelayContext } from '@components/relaysProvider';
import { noteContentAtom } from '@stores/note';
@@ -55,9 +54,7 @@ export default function FormBase() {
<div className="flex w-full items-center justify-between bg-zinc-800">
<div className="flex items-center gap-2 divide-x divide-zinc-700">
<ImagePicker />
<div className="flex items-center gap-2 pl-2">
<EmojiPicker />
</div>
<div className="flex items-center gap-2 pl-2"></div>
</div>
<div className="flex items-center gap-2">
<button

View File

@@ -111,7 +111,10 @@ export const FormChannel = ({ eventId }: { eventId: string | string[] }) => {
/>
<div className="absolute bottom-2 w-full px-2">
<div className="flex w-full items-center justify-between bg-zinc-800">
<div className="flex items-center gap-2 divide-x divide-zinc-700"></div>
<div className="flex items-center gap-2 divide-x divide-zinc-700">
<ImagePicker />
<div className="flex items-center gap-2 pl-2"></div>
</div>
<div className="flex items-center gap-2">
<button
onClick={() => submitEvent()}

View File

@@ -1,51 +1,79 @@
import { noteContentAtom } from '@stores/note';
import * as Popover from '@radix-ui/react-popover';
import { createBlobFromFile } from '@utils/createBlobFromFile';
import { open } from '@tauri-apps/api/dialog';
import { Body, fetch } from '@tauri-apps/api/http';
import { Plus } from 'iconoir-react';
import { useAtom } from 'jotai';
import { useSetAtom } from 'jotai';
import { useState } from 'react';
export default function ImagePicker() {
const [value, setValue] = useAtom(noteContentAtom);
const [url, setURL] = useState('');
export const ImagePicker = () => {
const [loading, setLoading] = useState(false);
const setNoteContent = useSetAtom(noteContentAtom);
const handleEnter = (e) => {
if (e.key === 'Enter') {
setValue(value + ' ' + url);
const openFileDialog = async () => {
const selected: any = await open({
multiple: false,
filters: [
{
name: 'Image',
extensions: ['png', 'jpeg', 'jpg', 'webp', 'avif'],
},
],
});
if (Array.isArray(selected)) {
// user selected multiple files
} else if (selected === null) {
// user cancelled the selection
} else {
setLoading(true);
const filename = selected.split('/').pop();
const file = await createBlobFromFile(selected);
const buf = await file.arrayBuffer();
const res: { data: { file: { id: string } } } = 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),
});
const webpImage = 'https://void.cat/d/' + res.data.file.id + '.webp';
setNoteContent((content) => content + ' ' + webpImage);
setLoading(false);
}
};
return (
<Popover.Root>
<Popover.Trigger asChild>
<button className="inline-flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-zinc-700">
<Plus width={16} height={16} className="text-zinc-400" />
</button>
</Popover.Trigger>
<Popover.Portal>
<Popover.Content
className="w-80 rounded-md bg-zinc-900/80 p-3 shadow-input shadow-black/50 ring-1 ring-zinc-800 backdrop-blur-xl will-change-[transform,opacity] data-[state=open]:data-[side=bottom]:animate-slideUpAndFade data-[state=open]:data-[side=left]:animate-slideRightAndFade data-[state=open]:data-[side=right]:animate-slideLeftAndFade data-[state=open]:data-[side=top]:animate-slideDownAndFade"
sideOffset={3}
<button
onClick={() => openFileDialog()}
className="inline-flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-zinc-700"
>
{loading ? (
<svg
className="h-4 w-4 animate-spin text-black dark:text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<div>
<div className="flex flex-col gap-1">
<label className="text-sm font-semibold text-zinc-200">Image URL</label>
<div className="relative mb-1 shrink-0 before:pointer-events-none before:absolute before:-inset-px before:rounded-[8px] before:border before:border-fuchsia-500 before:opacity-0 before:ring-1 before:ring-fuchsia-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<input
placeholder="https://..."
onKeyDown={handleEnter}
onChange={(e) => setURL(e.target.value)}
className="relative w-full rounded-lg border border-black/5 px-3 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-600"
/>
</div>
<p className="text-sm leading-none text-zinc-500">
Press <span className="rounded bg-zinc-800 px-1 py-0.5">Enter</span> to insert image
</p>
</div>
<div></div>
</div>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
) : (
<Plus width={16} height={16} className="text-zinc-400" />
)}
</button>
);
}
};