added upload image directly to void.cat to image picker
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user