From 5624054f1e060c786efdd5406b723651e5c1e383 Mon Sep 17 00:00:00 2001 From: Utku <74243531+utkubakir@users.noreply.github.com> Date: Fri, 19 Apr 2024 03:55:50 -0400 Subject: [PATCH] Mobile cleanup & improvements (#2362) clean up & improvements --- .../components/browse/BrowseCategories.tsx | 2 +- apps/mobile/src/components/browse/Jobs.tsx | 2 +- .../src/components/browse/ListLibraryItem.tsx | 4 +- .../components/context/OnboardingContext.tsx | 2 +- .../src/components/explorer/Explorer.tsx | 68 ++++-------------- apps/mobile/src/components/explorer/Menu.tsx | 41 ----------- .../src/components/explorer/menu/Menu.tsx | 72 +++++++++++++++++++ .../{ => explorer}/menu/SortByMenu.tsx | 6 +- apps/mobile/src/components/job/JobGroup.tsx | 13 +--- .../mobile/src/components/primitive/Toast.tsx | 42 +++++++---- apps/mobile/src/components/tags/ListTag.tsx | 6 +- apps/mobile/src/screens/browse/Browse.tsx | 16 ----- apps/mobile/src/screens/browse/Tags.tsx | 3 +- .../settings/library/EditLocationSettings.tsx | 2 +- .../library/LibraryGeneralSettings.tsx | 2 +- apps/mobile/src/stores/explorerStore.ts | 19 +++-- apps/mobile/src/stores/modalStore.ts | 11 +-- apps/mobile/src/stores/searchStore.ts | 11 ++- 18 files changed, 151 insertions(+), 171 deletions(-) delete mode 100644 apps/mobile/src/components/explorer/Menu.tsx create mode 100644 apps/mobile/src/components/explorer/menu/Menu.tsx rename apps/mobile/src/components/{ => explorer}/menu/SortByMenu.tsx (91%) diff --git a/apps/mobile/src/components/browse/BrowseCategories.tsx b/apps/mobile/src/components/browse/BrowseCategories.tsx index 39ab1a7bb..a6524daf6 100644 --- a/apps/mobile/src/components/browse/BrowseCategories.tsx +++ b/apps/mobile/src/components/browse/BrowseCategories.tsx @@ -18,7 +18,7 @@ import { Button } from '../primitive/Button'; import LibraryItem from './LibraryItem'; const iconStyle = tw`text-ink-faint`; -const iconSize = 28; +const iconSize = 24; export const CATEGORIES_LIST = [ { name: 'Albums', icon: }, { name: 'Places', icon: }, diff --git a/apps/mobile/src/components/browse/Jobs.tsx b/apps/mobile/src/components/browse/Jobs.tsx index d599fd8c8..86b58185f 100644 --- a/apps/mobile/src/components/browse/Jobs.tsx +++ b/apps/mobile/src/components/browse/Jobs.tsx @@ -12,7 +12,7 @@ const Jobs = () => { return ( - Jobs + Active Jobs diff --git a/apps/mobile/src/components/browse/ListLibraryItem.tsx b/apps/mobile/src/components/browse/ListLibraryItem.tsx index 22db21b1e..f937c9a16 100644 --- a/apps/mobile/src/components/browse/ListLibraryItem.tsx +++ b/apps/mobile/src/components/browse/ListLibraryItem.tsx @@ -12,9 +12,9 @@ interface CategoryProps { const ListLibraryItem = ({ name, icon }: CategoryProps) => { return ( - + {icon} - {name} + {name} { // Switch to the new library currentLibraryStore.id = library.uuid; } catch (e) { - toast({ type: 'error', text: 'Failed to create library' }); + toast.error('Failed to create library'); resetOnboardingStore(); navigation.navigate('GetStarted'); } diff --git a/apps/mobile/src/components/explorer/Explorer.tsx b/apps/mobile/src/components/explorer/Explorer.tsx index 7ac69fa76..e9ba6ae4d 100644 --- a/apps/mobile/src/components/explorer/Explorer.tsx +++ b/apps/mobile/src/components/explorer/Explorer.tsx @@ -1,20 +1,18 @@ import { useNavigation } from '@react-navigation/native'; import { FlashList } from '@shopify/flash-list'; import { UseInfiniteQueryResult } from '@tanstack/react-query'; -import { AnimatePresence, MotiView } from 'moti'; -import { useState } from 'react'; import { ActivityIndicator, Pressable } from 'react-native'; import { isPath, SearchData, type ExplorerItem } from '@sd/client'; import Layout from '~/constants/Layout'; import { tw } from '~/lib/tailwind'; import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack'; -import { ExplorerLayoutMode, getExplorerStore, useExplorerStore } from '~/stores/explorerStore'; +import { useExplorerStore } from '~/stores/explorerStore'; import { useActionsModalStore } from '~/stores/modalStore'; import ScreenContainer from '../layout/ScreenContainer'; import FileItem from './FileItem'; import FileRow from './FileRow'; -import Menu from './Menu'; +import Menu from './menu/Menu'; type ExplorerProps = { tabHeight?: boolean; @@ -27,14 +25,8 @@ type ExplorerProps = { const Explorer = (props: ExplorerProps) => { const navigation = useNavigation['navigation']>(); - const explorerStore = useExplorerStore(); - const [layoutMode, setLayoutMode] = useState(getExplorerStore().layoutMode); - function changeLayoutMode(kind: ExplorerLayoutMode) { - // We need to keep layoutMode as a state to make sure flash-list re-renders. - setLayoutMode(kind); - getExplorerStore().layoutMode = kind; - } + const store = useExplorerStore(); const { modalRef, setData } = useActionsModalStore(); @@ -52,45 +44,11 @@ const Explorer = (props: ExplorerProps) => { return ( - {/* Header */} - {/* Sort By */} - {/* */} - - {explorerStore.toggleMenu && ( - - { - changeLayoutMode(kind); - }} - layoutMode={layoutMode} - /> - - )} - - {/* Layout (Grid/List) */} - {/* {layoutMode === 'grid' ? ( - changeLayoutMode('list')}> - - - ) : ( - changeLayoutMode('grid')}> - - - )} */} + {/* Items */} item.type === 'NonIndexedPath' @@ -101,15 +59,19 @@ const Explorer = (props: ExplorerProps) => { } renderItem={({ item }) => ( handlePress(item)}> - {layoutMode === 'grid' ? : } + {store.layoutMode === 'grid' ? ( + + ) : ( + + )} )} contentContainerStyle={tw`px-2 py-5`} - extraData={layoutMode} + extraData={store.layoutMode} estimatedItemSize={ - layoutMode === 'grid' - ? Layout.window.width / getExplorerStore().gridNumColumns - : getExplorerStore().listItemSize + store.layoutMode === 'grid' + ? Layout.window.width / store.gridNumColumns + : store.listItemSize } onEndReached={() => props.loadMore?.()} onEndReachedThreshold={0.6} diff --git a/apps/mobile/src/components/explorer/Menu.tsx b/apps/mobile/src/components/explorer/Menu.tsx deleted file mode 100644 index a6e2082f8..000000000 --- a/apps/mobile/src/components/explorer/Menu.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { MonitorPlay, Rows, SlidersHorizontal, SquaresFour } from 'phosphor-react-native'; -import { Pressable, View } from 'react-native'; -import { tw } from '~/lib/tailwind'; -import { ExplorerLayoutMode } from '~/stores/explorerStore'; - -interface MenuProps { - layoutMode: ExplorerLayoutMode; - changeLayoutMode: (kind: ExplorerLayoutMode) => void; -} - -const Menu = ({ layoutMode, changeLayoutMode }: MenuProps) => { - return ( - - - changeLayoutMode('grid')}> - - - changeLayoutMode('list')}> - - - changeLayoutMode('media')}> - - - - - - ); -}; - -export default Menu; diff --git a/apps/mobile/src/components/explorer/menu/Menu.tsx b/apps/mobile/src/components/explorer/menu/Menu.tsx new file mode 100644 index 000000000..76e090d6c --- /dev/null +++ b/apps/mobile/src/components/explorer/menu/Menu.tsx @@ -0,0 +1,72 @@ +import { AnimatePresence, MotiView } from 'moti'; +import { MonitorPlay, Rows, SlidersHorizontal, SquaresFour } from 'phosphor-react-native'; +import { Pressable, View } from 'react-native'; +import { toast } from '~/components/primitive/Toast'; +import { tw } from '~/lib/tailwind'; +import { getExplorerStore, useExplorerStore } from '~/stores/explorerStore'; + +import SortByMenu from './SortByMenu'; + +const Menu = () => { + const store = useExplorerStore(); + + return ( + + {store.toggleMenu && ( + + + + (getExplorerStore().layoutMode = 'grid')}> + + + (getExplorerStore().layoutMode = 'list')}> + + + toast.error('Media view is not available yet...')} + // onPress={() => (getExplorerStore().layoutMode = 'media')} + > + + + + + + + )} + + ); +}; +export default Menu; diff --git a/apps/mobile/src/components/menu/SortByMenu.tsx b/apps/mobile/src/components/explorer/menu/SortByMenu.tsx similarity index 91% rename from apps/mobile/src/components/menu/SortByMenu.tsx rename to apps/mobile/src/components/explorer/menu/SortByMenu.tsx index 5f6d135ad..650dcd807 100644 --- a/apps/mobile/src/components/menu/SortByMenu.tsx +++ b/apps/mobile/src/components/explorer/menu/SortByMenu.tsx @@ -15,8 +15,8 @@ const sortOptions = { type SortByType = keyof typeof sortOptions; -const ArrowUpIcon = () => ; -const ArrowDownIcon = () => ; +const ArrowUpIcon = () => ; +const ArrowDownIcon = () => ; const SortByMenu = () => { const [sortBy, setSortBy] = useState('name'); @@ -26,7 +26,7 @@ const SortByMenu = () => { - {sortOptions[sortBy]} + {sortOptions[sortBy]} {sortDirection === 'asc' ? : } } diff --git a/apps/mobile/src/components/job/JobGroup.tsx b/apps/mobile/src/components/job/JobGroup.tsx index 60c6ae893..811bcae85 100644 --- a/apps/mobile/src/components/job/JobGroup.tsx +++ b/apps/mobile/src/components/job/JobGroup.tsx @@ -150,19 +150,10 @@ const toastErrorSuccess = ( ) => { return { onError: () => { - errorMessage && - toast({ - type: 'error', - text: errorMessage - }); + errorMessage && toast.error(errorMessage); }, onSuccess: () => { - successMessage && - toast({ - type: 'success', - text: successMessage - }), - successCallBack?.(); + successMessage && toast.success(successMessage), successCallBack?.(); } }; }; diff --git a/apps/mobile/src/components/primitive/Toast.tsx b/apps/mobile/src/components/primitive/Toast.tsx index ab2cc2355..a22fc0d83 100644 --- a/apps/mobile/src/components/primitive/Toast.tsx +++ b/apps/mobile/src/components/primitive/Toast.tsx @@ -3,25 +3,25 @@ import { Text, View } from 'react-native'; import Toast, { ToastConfig } from 'react-native-toast-message'; import { tw } from '~/lib/tailwind'; -// TODO: -// - Expand toast on press to show full message if it's too long -// - Add a onPress option -// - Add leading icon & trailing icon +const baseStyles = 'w-[340px] flex-row overflow-hidden rounded-md border p-3 shadow-lg'; const toastConfig: ToastConfig = { success: ({ text1, ...rest }) => ( - + {text1} ), error: ({ text1, ...rest }) => ( - + + + {text1} + + + ), + info: ({ text1, ...rest }) => ( + {text1} @@ -29,8 +29,26 @@ const toastConfig: ToastConfig = { ) }; -function toast({ text, type }: { type: 'success' | 'error' | 'info'; text: string }) { - Toast.show({ type, text1: text, visibilityTime: 3000, topOffset: 60 }); +function showToast({ text, type }: { type: 'success' | 'error' | 'info'; text: string }) { + const visibilityTime = 3000; + const topOffset = 60; + Toast.show({ type, text1: text, visibilityTime, topOffset }); } +const toast: { + success: (text: string) => void; + error: (text: string) => void; + info: (text: string) => void; +} = { + success: function (text: string): void { + showToast({ text, type: 'success' }); + }, + error: function (text: string): void { + showToast({ text, type: 'error' }); + }, + info: function (text: string): void { + showToast({ text, type: 'info' }); + } +}; + export { Toast, toast, toastConfig }; diff --git a/apps/mobile/src/components/tags/ListTag.tsx b/apps/mobile/src/components/tags/ListTag.tsx index 5b2e11859..625d35353 100644 --- a/apps/mobile/src/components/tags/ListTag.tsx +++ b/apps/mobile/src/components/tags/ListTag.tsx @@ -22,9 +22,7 @@ const ListTag = ({ tag, tagStyle }: ListTagProps) => { containerStyle={tw`rounded-md border border-app-cardborder bg-app-card p-3`} enableTrackpadTwoFingerGesture renderRightActions={(progress, _, swipeable) => ( - <> - - + )} > @@ -41,7 +39,7 @@ const ListTag = ({ tag, tagStyle }: ListTagProps) => { {tag.name} - swipeRef.current?.openRight()}> + swipeRef.current?.openRight()}> - ) : ( - - ); -} export default function BrowseScreen() { return ( @@ -24,7 +9,6 @@ export default function BrowseScreen() { - ); } diff --git a/apps/mobile/src/screens/browse/Tags.tsx b/apps/mobile/src/screens/browse/Tags.tsx index 50e694d89..476cc4fef 100644 --- a/apps/mobile/src/screens/browse/Tags.tsx +++ b/apps/mobile/src/screens/browse/Tags.tsx @@ -18,12 +18,13 @@ interface Props { } export default function TagsScreen({ viewStyle = 'list' }: Props) { - const tags = useLibraryQuery(['tags.list']); const navigation = useNavigation['navigation']>(); const modalRef = useRef(null); + const tags = useLibraryQuery(['tags.list']); useNodes(tags.data?.nodes); const tagData = useCache(tags.data?.items); + return ( { form.reset(form.getValues()); queryClient.invalidateQueries(['locations.list']); - toast({ type: 'success', text: 'Location updated!' }); + toast.success('Location updated!'); // TODO: navigate back & reset input focus! } }); diff --git a/apps/mobile/src/screens/settings/library/LibraryGeneralSettings.tsx b/apps/mobile/src/screens/settings/library/LibraryGeneralSettings.tsx index d423426a7..e849d0382 100644 --- a/apps/mobile/src/screens/settings/library/LibraryGeneralSettings.tsx +++ b/apps/mobile/src/screens/settings/library/LibraryGeneralSettings.tsx @@ -34,7 +34,7 @@ const LibraryGeneralSettingsScreen = (_: SettingsStackScreenProps<'LibraryGenera useAutoForm(form, (value) => { editLibrary({ description: value.description, name: value.name, id: library.uuid }); // console.log('Updated', value); - toast({ type: 'success', text: 'Library updated!' }); + toast.success('Library updated!'); }); return ( diff --git a/apps/mobile/src/stores/explorerStore.ts b/apps/mobile/src/stores/explorerStore.ts index 365930946..cf1a61ba8 100644 --- a/apps/mobile/src/stores/explorerStore.ts +++ b/apps/mobile/src/stores/explorerStore.ts @@ -25,23 +25,20 @@ export function flattenThumbnailKey(thumbKey: string[]) { return thumbKey.join('/'); } -const explorerStore = proxy({ +const store = proxy({ ...state, - reset: () => resetStore(explorerStore, state), + reset: () => resetStore(store, state), addNewThumbnail: (thumbKey: string[]) => { - explorerStore.newThumbnails.add(flattenThumbnailKey(thumbKey)); + store.newThumbnails.add(flattenThumbnailKey(thumbKey)); }, // this should be done when the explorer query is refreshed // prevents memory leak resetNewThumbnails: () => { - explorerStore.newThumbnails.clear(); + store.newThumbnails.clear(); } }); -export function useExplorerStore() { - return useSnapshot(explorerStore); -} - -export function getExplorerStore() { - return explorerStore; -} +/** for reading */ +export const useExplorerStore = () => useSnapshot(store); +/** for writing */ +export const getExplorerStore = () => store; diff --git a/apps/mobile/src/stores/modalStore.ts b/apps/mobile/src/stores/modalStore.ts index c3e332e59..12d46c2cb 100644 --- a/apps/mobile/src/stores/modalStore.ts +++ b/apps/mobile/src/stores/modalStore.ts @@ -3,14 +3,15 @@ import { proxy, ref, useSnapshot } from 'valtio'; import { ExplorerItem } from '@sd/client'; import { ModalRef } from '~/components/layout/Modal'; -export const actionsModalStore = proxy({ +const store = proxy({ modalRef: ref(createRef()), data: null as ExplorerItem | null, setData: (data: ExplorerItem) => { - actionsModalStore.data = data; + store.data = data; } }); -export function useActionsModalStore() { - return useSnapshot(actionsModalStore); -} +/** for reading */ +export const useActionsModalStore = () => useSnapshot(store); +/** for writing */ +export const getActionsModalStore = () => store; diff --git a/apps/mobile/src/stores/searchStore.ts b/apps/mobile/src/stores/searchStore.ts index cffa96f60..92e20001a 100644 --- a/apps/mobile/src/stores/searchStore.ts +++ b/apps/mobile/src/stores/searchStore.ts @@ -161,10 +161,7 @@ const searchStore = proxy< } }); -export function useSearchStore() { - return useSnapshot(searchStore); -} - -export function getSearchStore() { - return searchStore; -} +/** for reading */ +export const useSearchStore = () => useSnapshot(searchStore); +/** for writing */ +export const getSearchStore = () => searchStore;