diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5e44a6bb..e74ab193 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2777,6 +2777,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3828,6 +3838,7 @@ dependencies = [ "js-sys", "log", "mime", + "mime_guess", "native-tls", "once_cell", "percent-encoding", @@ -5543,6 +5554,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.13" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b08fcb19..c106c822 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -35,6 +35,7 @@ tauri = { version = "1.4.0", features = [ "window-center", "dialog-all", "macos-private-api", + "http-multipart", ] } tauri-plugin-sql = { git = "hhttps://github.com/tauri-apps/plugins-workspace", branch = "v1", features = [ "sqlite", diff --git a/src/shared/composer/composer.tsx b/src/shared/composer/composer.tsx index ff12d3ab..5c0cd53f 100644 --- a/src/shared/composer/composer.tsx +++ b/src/shared/composer/composer.tsx @@ -7,8 +7,8 @@ import { convert } from 'html-to-text'; import { useState } from 'react'; import { twMerge } from 'tailwind-merge'; -import { MentionPopup } from '@shared/composer'; -import { CancelIcon, LoaderIcon, MediaIcon } from '@shared/icons'; +import { MediaUploader, MentionPopup } from '@shared/composer'; +import { CancelIcon, LoaderIcon } from '@shared/icons'; import { MentionNote } from '@shared/notes'; import { useComposer } from '@stores/composer'; @@ -20,7 +20,7 @@ export function Composer() { const [loading, setLoading] = useState(false); const [reply, clearReply] = useComposer((state) => [state.reply, state.clearReply]); - const { publish, upload } = useNostr(); + const { publish } = useNostr(); const expand = useComposer((state) => state.expand); const editor = useEditor({ @@ -46,14 +46,6 @@ export function Composer() { }, }); - const uploadImage = async (file?: string) => { - const image = await upload(file, true); - if (image.url) { - editor.commands.setImage({ src: image.url }); - editor.commands.createParagraphNear(); - } - }; - const submit = async () => { try { setLoading(true); @@ -148,14 +140,7 @@ export function Composer() {
- +
+ ); +} diff --git a/src/utils/createBlobFromFile.ts b/src/utils/createBlobFromFile.ts index ada1bff3..2f508776 100644 --- a/src/utils/createBlobFromFile.ts +++ b/src/utils/createBlobFromFile.ts @@ -1,6 +1,8 @@ import { readBinaryFile } from '@tauri-apps/api/fs'; -export async function createBlobFromFile(path: string): Promise { +export async function createBlobFromFile(path: string): Promise { const file = await readBinaryFile(path); - return new Blob([file]); + const blob = new Blob([file]); + const arr = new Uint8Array(await blob.arrayBuffer()); + return arr; } diff --git a/src/utils/hooks/useNostr.ts b/src/utils/hooks/useNostr.ts index 52284652..35b42a4f 100644 --- a/src/utils/hooks/useNostr.ts +++ b/src/utils/hooks/useNostr.ts @@ -1,4 +1,3 @@ -import { magnetDecode } from '@ctrl/magnet-link'; import { NDKEvent, NDKFilter, @@ -9,7 +8,7 @@ import { } from '@nostr-dev-kit/ndk'; import { ndkAdapter } from '@nostr-fetch/adapter-ndk'; import { message, open } from '@tauri-apps/api/dialog'; -import { VoidApi } from '@void-cat/api'; +import { Body, fetch } from '@tauri-apps/api/http'; import { LRUCache } from 'lru-cache'; import { NostrFetcher } from 'nostr-fetch'; import { nip19 } from 'nostr-tools'; @@ -22,7 +21,7 @@ import { useStronghold } from '@stores/stronghold'; import { createBlobFromFile } from '@utils/createBlobFromFile'; import { nHoursAgo } from '@utils/date'; -import { NDKEventWithReplies } from '@utils/types'; +import { NDKEventWithReplies, NostrBuildResponse } from '@utils/types'; export function useNostr() { const { ndk, relayUrls } = useNDK(); @@ -330,9 +329,8 @@ export function useNostr() { const upload = async (file: null | string, nip94?: boolean) => { try { - const voidcat = new VoidApi('https://void.cat'); - let filepath = file; + if (!file) { const selected = await open({ multiple: false, @@ -369,32 +367,37 @@ export function useNostr() { const filename = filepath.split('/').pop(); const filetype = filename.split('.').pop(); - const blob = await createBlobFromFile(filepath); - const uploader = voidcat.getUploader(blob); - - // upload file - const res = await uploader.upload(); + const fileData = await createBlobFromFile(filepath); + const res: NostrBuildResponse = await fetch( + 'https://nostr.build/api/v2/upload/files', + { + method: 'POST', + timeout: 30, + headers: { 'Content-Type': 'multipart/form-data' }, + body: Body.form({ + fileData: { + file: fileData, + mime: `image/${filetype}`, + fileName: filename, + }, + }), + } + ); if (res.ok) { - const url = - res.file?.metadata?.url ?? `https://void.cat/d/${res.file?.id}.${filetype}`; + const data = res.data.data[0]; + const url = data.url; if (nip94) { const tags = [ ['url', url], - ['x', res.file?.metadata?.digest ?? ''], - ['m', res.file?.metadata?.mimeType ?? 'application/octet-stream'], - ['size', res.file?.metadata?.size.toString() ?? '0'], + ['x', data.sha256 ?? ''], + ['m', data.mime ?? 'application/octet-stream'], + ['size', data.size.toString() ?? '0'], + ['dim', `${data.dimensions.width}x${data.dimensions.height}` ?? '0'], + ['blurhash', data.blurhash ?? ''], ]; - if (res.file?.metadata?.magnetLink) { - tags.push(['magnet', res.file.metadata.magnetLink]); - const parsedMagnet = magnetDecode(res.file.metadata.magnetLink); - if (parsedMagnet?.infoHash) { - tags.push(['i', parsedMagnet?.infoHash]); - } - } - await publish({ content: '', kind: 1063, tags: tags }); } diff --git a/src/utils/types.d.ts b/src/utils/types.d.ts index bab45a61..80543cda 100644 --- a/src/utils/types.d.ts +++ b/src/utils/types.d.ts @@ -1,4 +1,5 @@ import { NDKEvent, NDKUserProfile } from '@nostr-dev-kit/ndk'; +import { Response } from '@tauri-apps/api/http'; export interface RichContent { parsed: string; @@ -88,3 +89,23 @@ export interface Opengraph { export interface NDKEventWithReplies extends NDKEvent { replies: Array; } + +export interface NostrBuildResponse extends Response { + ok: boolean; + data: { + message: string; + status: string; + data: Array<{ + blurhash: string; + dimensions: { + width: number; + height: number; + }; + mime: string; + name: string; + sha256: string; + size: number; + url: string; + }>; + }; +}