From c87db85815d84ddf907d0a1d26226a2ab911181b Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Mon, 11 Mar 2024 12:24:51 +0000 Subject: mobile: An ugly yet functional signin workflow --- packages/mobile/lib/providers.tsx | 5 +++- packages/mobile/lib/settings.ts | 28 +++++++------------- packages/mobile/lib/storage-state.ts | 50 ++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 packages/mobile/lib/storage-state.ts (limited to 'packages/mobile/lib') diff --git a/packages/mobile/lib/providers.tsx b/packages/mobile/lib/providers.tsx index d5638da8..394bad28 100644 --- a/packages/mobile/lib/providers.tsx +++ b/packages/mobile/lib/providers.tsx @@ -14,7 +14,10 @@ function getTRPCClient(address: string) { async headers() { const settings = await getAppSettings(); return { - Authorization: settings ? `Bearer ${settings.apiKey}` : undefined, + Authorization: + settings && settings.apiKey + ? `Bearer ${settings.apiKey}` + : undefined, }; }, transformer: superjson, diff --git a/packages/mobile/lib/settings.ts b/packages/mobile/lib/settings.ts index 85296cfa..21f40528 100644 --- a/packages/mobile/lib/settings.ts +++ b/packages/mobile/lib/settings.ts @@ -1,33 +1,23 @@ import * as SecureStore from "expo-secure-store"; -import { useEffect, useState } from "react"; + +import { useStorageState } from "./storage-state"; const SETTING_NAME = "settings"; export type Settings = { - apiKey: string; + apiKey?: string; address: string; }; export default function useAppSettings() { - const [settings, setSettings] = useState({ - apiKey: "", - address: "", - }); - - useEffect(() => { - SecureStore.setItemAsync(SETTING_NAME, JSON.stringify(settings)); - }, [settings]); + let [[isLoading, settings], setSettings] = + useStorageState(SETTING_NAME); - useEffect(() => { - SecureStore.getItemAsync(SETTING_NAME).then((val) => { - if (!val) { - return; - } - setSettings(JSON.parse(val)); - }); - }, []); + settings ||= { + address: "https://demo.hoarder.app", + }; - return { settings, setSettings }; + return { settings, setSettings, isLoading }; } export async function getAppSettings() { diff --git a/packages/mobile/lib/storage-state.ts b/packages/mobile/lib/storage-state.ts new file mode 100644 index 00000000..09917c79 --- /dev/null +++ b/packages/mobile/lib/storage-state.ts @@ -0,0 +1,50 @@ +import * as SecureStore from "expo-secure-store"; +import * as React from "react"; + +type UseStateHook = [[boolean, T | null], (value: T | null) => void]; + +function useAsyncState( + initialValue: [boolean, T | null] = [true, null], +): UseStateHook { + return React.useReducer( + ( + state: [boolean, T | null], + action: T | null = null, + ): [boolean, T | null] => [false, action], + initialValue, + ) as UseStateHook; +} + +export async function setStorageItemAsync(key: string, value: string | null) { + if (value == null) { + await SecureStore.deleteItemAsync(key); + } else { + await SecureStore.setItemAsync(key, value); + } +} + +export function useStorageState(key: string): UseStateHook { + // Public + const [state, setState] = useAsyncState(); + + // Get + React.useEffect(() => { + SecureStore.getItemAsync(key).then((value) => { + if (!value) { + return null; + } + setState(JSON.parse(value)); + }); + }, [key]); + + // Set + const setValue = React.useCallback( + (value: T | null) => { + setState(value); + setStorageItemAsync(key, JSON.stringify(value)); + }, + [key], + ); + + return [state, setValue]; +} -- cgit v1.2.3-70-g09d2