diff options
| -rw-r--r-- | apps/mobile/lib/upload.ts | 32 | ||||
| -rw-r--r-- | apps/mobile/package.json | 1 | ||||
| -rw-r--r-- | pnpm-lock.yaml | 25 |
3 files changed, 42 insertions, 16 deletions
diff --git a/apps/mobile/lib/upload.ts b/apps/mobile/lib/upload.ts index b31faa90..715119b1 100644 --- a/apps/mobile/lib/upload.ts +++ b/apps/mobile/lib/upload.ts @@ -1,3 +1,4 @@ +import ReactNativeBlobUtil from "react-native-blob-util"; import { useMutation } from "@tanstack/react-query"; import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks"; @@ -36,23 +37,24 @@ export function useUploadAsset( const { mutate: uploadAsset, isPending: isUploading } = useMutation({ mutationFn: async (file: { type: string; name: string; uri: string }) => { - const formData = new FormData(); - // @ts-expect-error This is a valid api in react native - formData.append("file", { - uri: file.uri, - name: file.name, - type: file.type, - }); - const resp = await fetch(`${settings.address}/api/assets`, { - method: "POST", - body: formData, - headers: { + // There's a bug in the native FormData implementation (https://github.com/facebook/react-native/issues/44737) + // that will only get fixed in react native 0.77. Using the BlobUtil implementation for now. + const resp = await ReactNativeBlobUtil.fetch( + "POST", + `${settings.address}/api/assets`, + { Authorization: `Bearer ${settings.apiKey}`, + "Content-Type": "multipart/form-data", }, - }); - if (!resp.ok) { - throw new Error(await resp.text()); - } + [ + { + name: "file", + filename: file.name, + type: file.type, + data: ReactNativeBlobUtil.wrap(file.uri.replace("file://", "")), + }, + ], + ); return zUploadResponseSchema.parse(await resp.json()); }, onSuccess: (resp) => { diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 2634bdd7..016531f1 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -44,6 +44,7 @@ "react": "^18.3.1", "react-native": "0.76.3", "react-native-awesome-slider": "^2.5.3", + "react-native-blob-util": "^0.21.2", "react-native-gesture-handler": "~2.21.2", "react-native-image-viewing": "^0.2.2", "react-native-markdown-display": "^7.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a677c7d6..7fdfac1d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -378,6 +378,9 @@ importers: react-native-awesome-slider: specifier: ^2.5.3 version: 2.5.3(react-native-gesture-handler@2.21.2(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1))(react-native-reanimated@3.16.2(@babel/core@7.26.0)(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1) + react-native-blob-util: + specifier: ^0.21.2 + version: 0.21.2(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1) react-native-gesture-handler: specifier: ~2.21.2 version: 2.21.2(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1) @@ -5677,6 +5680,9 @@ packages: bare-path@2.1.0: resolution: {integrity: sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==} + base-64@0.1.0: + resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -11398,6 +11404,12 @@ packages: react-native-gesture-handler: '>=2.0.0' react-native-reanimated: '>=3.0.0' + react-native-blob-util@0.21.2: + resolution: {integrity: sha512-4DsF+zzBEJmLww12PsUjwqjSaUrz7gdL5MeduSRn9fv5M8GLRIk5WHcgc7n+fzorGhbbL9QtB/QLTL6dMKjYUw==} + peerDependencies: + react: '*' + react-native: '*' + react-native-css-interop@0.1.22: resolution: {integrity: sha512-Mu01e+H9G+fxSWvwtgWlF5MJBJC4VszTCBXopIpeR171lbeBInHb8aHqoqRPxmJpi3xIHryzqKFOJYAdk7PBxg==} engines: {node: '>=18'} @@ -20199,6 +20211,9 @@ snapshots: dev: false optional: true + base-64@0.1.0: + dev: false + base64-js@1.5.1: dev: false @@ -26918,7 +26933,7 @@ snapshots: path-scurry@1.10.1: dependencies: lru-cache: 10.2.0 - minipass: 7.0.4 + minipass: 7.1.2 dev: false path-scurry@1.11.1: @@ -27928,6 +27943,14 @@ snapshots: react-native-reanimated: 3.16.2(@babel/core@7.26.0)(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1) dev: false + react-native-blob-util@0.21.2(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1): + dependencies: + base-64: 0.1.0 + glob: 10.4.5 + react: 18.3.1 + react-native: 0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1) + dev: false + react-native-css-interop@0.1.22(react-native-reanimated@3.16.2(@babel/core@7.26.0)(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1))(react-native-safe-area-context@4.12.0(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1))(react-native-svg@15.8.0(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1))(react-native@0.76.3(@babel/core@7.26.0)(@babel/preset-env@7.24.0(@babel/core@7.26.0))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.1): dependencies: '@babel/helper-module-imports': 7.25.9 |
