diff options
| author | MohamedBassem <me@mbassem.com> | 2024-08-26 21:33:01 +0300 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-08-26 21:33:01 +0300 |
| commit | fdf055ae222ac2063fa87759479018248657fd63 (patch) | |
| tree | 686d5d921ae42f9108dbfa9faf00a9d10006f94f /apps/mobile | |
| parent | 140554021e83ca375845584f8d7e5e476434f1c0 (diff) | |
| download | karakeep-fdf055ae222ac2063fa87759479018248657fd63.tar.zst | |
feature(mobile): Allow configuring uploaded image quality in the mobile app
Diffstat (limited to 'apps/mobile')
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/index.tsx | 2 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/settings.tsx | 42 | ||||
| -rw-r--r-- | apps/mobile/components/ui/PageTitle.tsx | 13 | ||||
| -rw-r--r-- | apps/mobile/lib/settings.ts | 18 | ||||
| -rw-r--r-- | apps/mobile/package.json | 1 |
5 files changed, 64 insertions, 12 deletions
diff --git a/apps/mobile/app/dashboard/(tabs)/index.tsx b/apps/mobile/app/dashboard/(tabs)/index.tsx index dc9871e7..bd7ce3ea 100644 --- a/apps/mobile/app/dashboard/(tabs)/index.tsx +++ b/apps/mobile/app/dashboard/(tabs)/index.tsx @@ -34,7 +34,7 @@ function HeaderRight({ } else if (nativeEvent.event === "library") { const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, - quality: 0, + quality: settings.imageQuality, allowsMultipleSelection: false, }); if (!result.canceled) { diff --git a/apps/mobile/app/dashboard/(tabs)/settings.tsx b/apps/mobile/app/dashboard/(tabs)/settings.tsx index 73d1b42d..18d3d243 100644 --- a/apps/mobile/app/dashboard/(tabs)/settings.tsx +++ b/apps/mobile/app/dashboard/(tabs)/settings.tsx @@ -1,6 +1,10 @@ +import { useEffect } from "react"; import { Text, View } from "react-native"; +import { Slider } from "react-native-awesome-slider"; +import { useSharedValue } from "react-native-reanimated"; import { Button } from "@/components/ui/Button"; import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; +import { Divider } from "@/components/ui/Divider"; import PageTitle from "@/components/ui/PageTitle"; import { useSession } from "@/lib/session"; import useAppSettings from "@/lib/settings"; @@ -8,7 +12,19 @@ import { api } from "@/lib/trpc"; export default function Dashboard() { const { logout } = useSession(); - const { settings, isLoading: isSettingsLoading } = useAppSettings(); + const { + settings, + setSettings, + isLoading: isSettingsLoading, + } = useAppSettings(); + + const imageQuality = useSharedValue(0); + const imageQualityMin = useSharedValue(0); + const imageQualityMax = useSharedValue(100); + + useEffect(() => { + imageQuality.value = settings.imageQuality * 100; + }, [settings]); const { data, error, isLoading } = api.users.whoami.useQuery(); @@ -30,8 +46,30 @@ export default function Dashboard() { {isLoading ? "Loading ..." : data?.email} </Text> </View> - <Button className="w-full" label="Log Out" onPress={logout} /> + <Divider orientation="horizontal" /> + <Text className="w-full p-1 text-2xl font-bold text-foreground"> + Upload Settings + </Text> + <View className="flex w-full flex-row items-center justify-between gap-8 rounded-lg bg-white px-4 py-2 dark:bg-accent"> + <Text className="text-lg text-accent-foreground">Image Quality</Text> + <View className="flex flex-1 flex-row items-center justify-center gap-2"> + <Text className="text-foreground"> + {settings.imageQuality * 100}% + </Text> + <Slider + onSlidingComplete={(value) => + setSettings({ + ...settings, + imageQuality: Math.round(value) / 100, + }) + } + progress={imageQuality} + minimumValue={imageQualityMin} + maximumValue={imageQualityMax} + /> + </View> + </View> </View> </CustomSafeAreaView> ); diff --git a/apps/mobile/components/ui/PageTitle.tsx b/apps/mobile/components/ui/PageTitle.tsx index 1c1543ce..dc712379 100644 --- a/apps/mobile/components/ui/PageTitle.tsx +++ b/apps/mobile/components/ui/PageTitle.tsx @@ -1,7 +1,16 @@ import { Text } from "react-native"; +import { cx } from "class-variance-authority"; -export default function PageTitle({ title }: { title: string }) { +export default function PageTitle({ + title, + className, +}: { + title: string; + className?: string; +}) { return ( - <Text className="p-4 text-4xl font-bold text-foreground">{title}</Text> + <Text className={cx("p-4 text-4xl font-bold text-foreground", className)}> + {title} + </Text> ); } diff --git a/apps/mobile/lib/settings.ts b/apps/mobile/lib/settings.ts index efb5593a..085f4f01 100644 --- a/apps/mobile/lib/settings.ts +++ b/apps/mobile/lib/settings.ts @@ -1,13 +1,17 @@ import * as SecureStore from "expo-secure-store"; +import { z } from "zod"; import { create } from "zustand"; const SETTING_NAME = "settings"; -export interface Settings { - apiKey?: string; - apiKeyId?: string; - address: string; -} +const zSettingsSchema = z.object({ + apiKey: z.string().optional(), + apiKeyId: z.string().optional(), + address: z.string(), + imageQuality: z.number().optional().default(0.2), +}); + +export type Settings = z.infer<typeof zSettingsSchema>; interface AppSettingsState { settings: { isLoading: boolean; settings: Settings }; @@ -18,7 +22,7 @@ interface AppSettingsState { const useSettings = create<AppSettingsState>((set, get) => ({ settings: { isLoading: true, - settings: { address: "" }, + settings: { address: "", imageQuality: 0.2 }, }, setSettings: async (settings) => { await SecureStore.setItemAsync(SETTING_NAME, JSON.stringify(settings)); @@ -36,7 +40,7 @@ const useSettings = create<AppSettingsState>((set, get) => ({ return; } // TODO Wipe the state if invalid - const parsed = JSON.parse(strVal) as Settings; + const parsed = zSettingsSchema.parse(JSON.parse(strVal)); set((_state) => ({ settings: { isLoading: false, settings: parsed } })); }, })); diff --git a/apps/mobile/package.json b/apps/mobile/package.json index da8ef432..6519692e 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -42,6 +42,7 @@ "nativewind": "^4.0.1", "react": "^18.2.0", "react-native": "0.73.4", + "react-native-awesome-slider": "^2.5.3", "react-native-gesture-handler": "~2.14.0", "react-native-markdown-display": "^7.0.2", "react-native-reanimated": "^3.8.0", |
