diff --git a/src/app/space/components/addHashtag.tsx b/src/app/space/components/addHashtag.tsx
new file mode 100644
index 00000000..50ca5e2e
--- /dev/null
+++ b/src/app/space/components/addHashtag.tsx
@@ -0,0 +1,174 @@
+import { Dialog, Transition } from '@headlessui/react';
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { Fragment, useState } from 'react';
+import { useForm } from 'react-hook-form';
+import { useHotkeys } from 'react-hotkeys-hook';
+
+import { createBlock } from '@libs/storage';
+
+import { CancelIcon, CommandIcon, LoaderIcon } from '@shared/icons';
+
+import { BLOCK_KINDS } from '@stores/constants';
+import { ADD_HASHTAGBLOCK_SHORTCUT } from '@stores/shortcuts';
+
+export function AddHashTagBlock() {
+ const queryClient = useQueryClient();
+
+ const [loading, setLoading] = useState(false);
+ const [isOpen, setIsOpen] = useState(false);
+
+ const openModal = () => {
+ setIsOpen(true);
+ };
+
+ const closeModal = () => {
+ setIsOpen(false);
+ };
+
+ useHotkeys(ADD_HASHTAGBLOCK_SHORTCUT, () => openModal());
+
+ const {
+ register,
+ handleSubmit,
+ reset,
+ formState: { isDirty, isValid },
+ } = useForm();
+
+ const block = useMutation({
+ mutationFn: (data: { kind: number; title: string; content: string }) => {
+ return createBlock(data.kind, data.title, data.content);
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['blocks'] });
+ },
+ });
+
+ const onSubmit = async (data: { hashtag: string }) => {
+ setLoading(true);
+
+ // mutate
+ block.mutate({
+ kind: BLOCK_KINDS.hashtag,
+ title: data.hashtag,
+ content: data.hashtag.replace('#', ''),
+ });
+
+ setLoading(false);
+ // reset form
+ reset();
+ // close modal
+ closeModal();
+ };
+
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
diff --git a/src/app/space/components/addImage.tsx b/src/app/space/components/addImage.tsx
index 4a25931b..06967381 100644
--- a/src/app/space/components/addImage.tsx
+++ b/src/app/space/components/addImage.tsx
@@ -1,24 +1,24 @@
import { Dialog, Transition } from '@headlessui/react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
-import { open } from '@tauri-apps/api/dialog';
-import { Body, fetch } from '@tauri-apps/api/http';
import { Fragment, useEffect, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useHotkeys } from 'react-hotkeys-hook';
import { createBlock } from '@libs/storage';
-import { CancelIcon, CommandIcon } from '@shared/icons';
+import { CancelIcon, CommandIcon, LoaderIcon } from '@shared/icons';
import { Image } from '@shared/image';
import { BLOCK_KINDS, DEFAULT_AVATAR } from '@stores/constants';
import { ADD_IMAGEBLOCK_SHORTCUT } from '@stores/shortcuts';
-import { createBlobFromFile } from '@utils/createBlobFromFile';
import { usePublish } from '@utils/hooks/usePublish';
+import { useImageUploader } from '@utils/hooks/useUploader';
export function AddImageBlock() {
const queryClient = useQueryClient();
+ const upload = useImageUploader();
+
const { publish } = usePublish();
const [loading, setLoading] = useState(false);
@@ -45,54 +45,6 @@ export function AddImageBlock() {
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: { kind: number; title: string; content: string }) => {
return createBlock(data.kind, data.title, data.content);
@@ -102,6 +54,13 @@ export function AddImageBlock() {
},
});
+ const uploadImage = async () => {
+ const image = await upload(null);
+ if (image.url) {
+ setImage(image.url);
+ }
+ };
+
const onSubmit = async (data: { kind: number; title: string; content: string }) => {
setLoading(true);
@@ -127,7 +86,7 @@ export function AddImageBlock() {