diff options
| author | Mohamed Bassem <me@mbassem.com> | 2024-03-19 00:33:11 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-19 00:33:11 +0000 |
| commit | 785a5b574992296e187a66412dd42f7b4a686353 (patch) | |
| tree | 64b608927cc63d7494395f639636fd4b36e5a977 /apps/mobile/app | |
| parent | 549520919c482e72cdf7adae5ba852d1b6cbe5aa (diff) | |
| download | karakeep-785a5b574992296e187a66412dd42f7b4a686353.tar.zst | |
Feature: Add support for uploading images and automatically inferring their tags (#2)
* feature: Experimental support for asset uploads
* feature(web): Add new bookmark type asset
* feature: Add support for automatically tagging images
* fix: Add support for image assets in preview page
* use next Image for fetching the images
* Fix auth and error codes in the route handlers
* Add support for image uploads on mobile
* Fix typing of upload requests
* Remove the ugly dragging box
* Bump mobile version to 1.3
* Change the editor card placeholder to mention uploading images
* Fix a typo
* Change ios icon for photo library
* Silence typescript error
Diffstat (limited to 'apps/mobile/app')
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/index.tsx | 36 | ||||
| -rw-r--r-- | apps/mobile/app/sharing.tsx | 34 |
2 files changed, 62 insertions, 8 deletions
diff --git a/apps/mobile/app/dashboard/(tabs)/index.tsx b/apps/mobile/app/dashboard/(tabs)/index.tsx index 7f70af6b..a840ca93 100644 --- a/apps/mobile/app/dashboard/(tabs)/index.tsx +++ b/apps/mobile/app/dashboard/(tabs)/index.tsx @@ -1,21 +1,45 @@ import { Platform, SafeAreaView, View } from "react-native"; import * as Haptics from "expo-haptics"; +import * as ImagePicker from "expo-image-picker"; import { useRouter } from "expo-router"; import BookmarkList from "@/components/bookmarks/BookmarkList"; import PageTitle from "@/components/ui/PageTitle"; +import useAppSettings from "@/lib/settings"; +import { useUploadAsset } from "@/lib/upload"; import { MenuView } from "@react-native-menu/menu"; import { SquarePen } from "lucide-react-native"; +import { useToast } from "@/components/ui/Toast"; function HeaderRight() { + const {toast} = useToast(); const router = useRouter(); + const { settings } = useAppSettings(); + const { uploadAsset } = useUploadAsset(settings, { + onError: (e) => { + toast({message: e, variant: "destructive"}); + }, + }); return ( <MenuView - onPressAction={({ nativeEvent }) => { + onPressAction={async ({ nativeEvent }) => { Haptics.selectionAsync(); if (nativeEvent.event === "note") { router.navigate("dashboard/add-note"); } else if (nativeEvent.event === "link") { router.navigate("dashboard/add-link"); + } else if (nativeEvent.event === "library") { + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + quality: 0, + allowsMultipleSelection: false, + }); + if (!result.canceled) { + uploadAsset({ + type: result.assets[0].mimeType ?? "", + name: result.assets[0].fileName ?? "", + uri: result.assets[0].uri, + }); + } } }} actions={[ @@ -31,10 +55,18 @@ function HeaderRight() { id: "note", title: "New Note", image: Platform.select({ - ios: "note", + ios: "note.text", android: "ic_menu_note", }), }, + { + id: "library", + title: "Photo Library", + image: Platform.select({ + ios: "photo", + android: "ic_menu_photo", + }), + }, ]} shouldOpenOnLongPress={false} > diff --git a/apps/mobile/app/sharing.tsx b/apps/mobile/app/sharing.tsx index e8b0ad09..2f9dbb27 100644 --- a/apps/mobile/app/sharing.tsx +++ b/apps/mobile/app/sharing.tsx @@ -2,8 +2,11 @@ import { useEffect, useState } from "react"; import { Text, View } from "react-native"; import { Link, useRouter } from "expo-router"; import { useShareIntentContext } from "expo-share-intent"; +import useAppSettings from "@/lib/settings"; import { api } from "@/lib/trpc"; +import { useUploadAsset } from "@/lib/upload"; import { z } from "zod"; +import type { ZBookmark } from "@hoarder/trpc/types/bookmarks"; type Mode = | { type: "idle" } @@ -11,12 +14,28 @@ type Mode = | { type: "error" }; function SaveBookmark({ setMode }: { setMode: (mode: Mode) => void }) { - const { hasShareIntent, shareIntent, resetShareIntent } = useShareIntentContext(); + const onSaved = (d: ZBookmark) => { + invalidateAllBookmarks(); + setMode({ type: "success", bookmarkId: d.id }); + }; + + const { hasShareIntent, shareIntent, resetShareIntent } = + useShareIntentContext(); + const { settings, isLoading } = useAppSettings(); + const { uploadAsset } = useUploadAsset(settings, { + onSuccess: onSaved, + onError: () => { + setMode({ type: "error" }); + }, + }); const invalidateAllBookmarks = api.useUtils().bookmarks.getBookmarks.invalidate; useEffect(() => { + if (isLoading) { + return; + } if (!isPending && shareIntent?.text) { const val = z.string().url(); if (val.safeParse(shareIntent.text).success) { @@ -25,17 +44,20 @@ function SaveBookmark({ setMode }: { setMode: (mode: Mode) => void }) { } else { mutate({ type: "text", text: shareIntent.text }); } + } else if (!isPending && shareIntent?.files) { + uploadAsset({ + type: shareIntent.files[0].type, + name: shareIntent.files[0].fileName ?? "", + uri: shareIntent.files[0].path, + }); } if (hasShareIntent) { resetShareIntent(); } - }, []); + }, [isLoading]); const { mutate, isPending } = api.bookmarks.createBookmark.useMutation({ - onSuccess: (d) => { - invalidateAllBookmarks(); - setMode({ type: "success", bookmarkId: d.id }); - }, + onSuccess: onSaved, onError: () => { setMode({ type: "error" }); }, |
