mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-19 05:45:01 -04:00
[MOB-114] Improve Media View thumbnails and coming soon alerts (#2626)
* improve thumbs of media view, coming soon state for settings routes, and debug bg color change * alert for lock in sidebar dropdown * formatting * Move Coming Soon Alert to it's own component So, it makes life easier if we need to change wording later. * autoformat --------- Co-authored-by: Arnab Chakraborty <11457760+Rocky43007@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import { ModalRef } from '../layout/Modal';
|
||||
import CreateLibraryModal from '../modal/CreateLibraryModal';
|
||||
import ImportModalLibrary from '../modal/ImportLibraryModal';
|
||||
import { Divider } from '../primitive/Divider';
|
||||
import { FeatureUnavailableAlert } from '../primitive/FeatureUnavailableAlert';
|
||||
|
||||
const DrawerLibraryManager = () => {
|
||||
const [dropdownClosed, setDropdownClosed] = useState(true);
|
||||
@@ -117,8 +118,8 @@ const DrawerLibraryManager = () => {
|
||||
</View>
|
||||
</Pressable>
|
||||
{/* Lock */}
|
||||
<Pressable onPress={() => Alert.alert('TODO')}>
|
||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px]`}>
|
||||
<Pressable onPress={() => FeatureUnavailableAlert()}>
|
||||
<View style={tw`flex flex-row items-center px-1.5 py-[8px] opacity-50`}>
|
||||
<Lock size={18} weight="bold" color="white" style={tw`mr-2`} />
|
||||
<Text style={tw`text-sm font-semibold text-white`}>Lock</Text>
|
||||
</View>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useNavigation } from '@react-navigation/native';
|
||||
import { FlashList } from '@shopify/flash-list';
|
||||
import { UseInfiniteQueryResult } from '@tanstack/react-query';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
import { ActivityIndicator, Pressable } from 'react-native';
|
||||
import { ActivityIndicator, Pressable, View } from 'react-native';
|
||||
import FileViewer from 'react-native-file-viewer';
|
||||
import {
|
||||
getIndexedItemFilePath,
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
type ExplorerItem
|
||||
} from '@sd/client';
|
||||
import Layout from '~/constants/Layout';
|
||||
import { twStyle } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack';
|
||||
import { useExplorerStore } from '~/stores/explorerStore';
|
||||
import { useActionsModalStore } from '~/stores/modalStore';
|
||||
@@ -130,7 +130,8 @@ const Explorer = (props: Props) => {
|
||||
</Pressable>
|
||||
)}
|
||||
contentContainerStyle={twStyle(
|
||||
store.layoutMode !== 'media' ? 'px-2 py-5' : 'px-0'
|
||||
store.layoutMode !== 'media' ? 'px-2 pt-5' : 'px-0',
|
||||
store.layoutMode === 'grid' && 'pt-9'
|
||||
)}
|
||||
extraData={store.layoutMode}
|
||||
estimatedItemSize={
|
||||
@@ -142,6 +143,7 @@ const Explorer = (props: Props) => {
|
||||
? Layout.window.width / store.mediaColumns
|
||||
: 100
|
||||
}
|
||||
// ItemSeparatorComponent={() => <View style={tw`p-10`}/>}
|
||||
onEndReached={() => props.loadMore?.()}
|
||||
onEndReachedThreshold={0.6}
|
||||
ListFooterComponent={
|
||||
|
||||
@@ -12,7 +12,6 @@ type FileMediaProps = {
|
||||
|
||||
const FileMedia = ({ data }: FileMediaProps) => {
|
||||
const gridItemSize = Layout.window.width / getExplorerStore().mediaColumns;
|
||||
const isAndroid = Platform.OS === 'android';
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -21,7 +20,7 @@ const FileMedia = ({ data }: FileMediaProps) => {
|
||||
height: gridItemSize
|
||||
})}
|
||||
>
|
||||
<FileThumb fixedSize size={isAndroid ? 95 : 97} data={data} />
|
||||
<FileThumb mediaView data={data} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from '@sd/client';
|
||||
import { flattenThumbnailKey, useExplorerStore } from '~/stores/explorerStore';
|
||||
|
||||
import { tw } from '../../lib/tailwind';
|
||||
import { twStyle } from '../../lib/tailwind';
|
||||
|
||||
// NOTE: `file://` is required for Android to load local files!
|
||||
export const getThumbnailUrlByThumbKey = (thumbKey: ThumbKey) => {
|
||||
@@ -23,13 +23,17 @@ export const getThumbnailUrlByThumbKey = (thumbKey: ThumbKey) => {
|
||||
|
||||
const FileThumbWrapper = ({
|
||||
children,
|
||||
mediaView = false,
|
||||
size = 1,
|
||||
fixedSize = false
|
||||
}: PropsWithChildren<{ size: number; fixedSize: boolean }>) => (
|
||||
}: PropsWithChildren<{ size: number; fixedSize: boolean; mediaView: boolean }>) => (
|
||||
<View
|
||||
style={[
|
||||
tw`items-center justify-center`,
|
||||
{ width: fixedSize ? size : 80 * size, height: fixedSize ? size : 80 * size }
|
||||
twStyle(`items-center justify-center`, mediaView && `p-0.1 w-full flex-1 `),
|
||||
!mediaView && {
|
||||
width: fixedSize ? size : 70 * size,
|
||||
height: fixedSize ? size : 70 * size
|
||||
}
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
@@ -70,6 +74,7 @@ type FileThumbProps = {
|
||||
data: ExplorerItem;
|
||||
size?: number;
|
||||
fixedSize?: boolean;
|
||||
mediaView?: boolean;
|
||||
// loadOriginal?: boolean;
|
||||
};
|
||||
|
||||
@@ -77,8 +82,14 @@ type FileThumbProps = {
|
||||
* @param data This is the ExplorerItem object
|
||||
* @param size This is multiplier for calculating icon size
|
||||
* @param fixedSize If set to true, the icon will have fixed size
|
||||
* @param mediaView If set to true - file thumbs will adjust their sizing accordingly
|
||||
*/
|
||||
export default function FileThumb({ size = 1, fixedSize = false, ...props }: FileThumbProps) {
|
||||
export default function FileThumb({
|
||||
size = 1,
|
||||
fixedSize = false,
|
||||
mediaView = false,
|
||||
...props
|
||||
}: FileThumbProps) {
|
||||
const itemData = useExplorerItemData(props.data);
|
||||
const locationData = getItemLocation(props.data);
|
||||
|
||||
@@ -118,7 +129,7 @@ export default function FileThumb({ size = 1, fixedSize = false, ...props }: Fil
|
||||
}, [itemData, thumbType]);
|
||||
|
||||
return (
|
||||
<FileThumbWrapper fixedSize={fixedSize} size={size}>
|
||||
<FileThumbWrapper mediaView={mediaView} fixedSize={fixedSize} size={size}>
|
||||
{(() => {
|
||||
if (src == null) return null;
|
||||
let source = null;
|
||||
@@ -133,8 +144,9 @@ export default function FileThumb({ size = 1, fixedSize = false, ...props }: Fil
|
||||
cachePolicy="memory-disk"
|
||||
source={source}
|
||||
style={{
|
||||
width: fixedSize ? size : 70 * size,
|
||||
height: fixedSize ? size : 70 * size
|
||||
flex: !mediaView ? undefined : 1,
|
||||
width: !mediaView ? (fixedSize ? size : 70 * size) : '100%',
|
||||
height: !mediaView ? (fixedSize ? size : 70 * size) : '100%'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Alert } from 'react-native';
|
||||
|
||||
export function FeatureUnavailableAlert() {
|
||||
return Alert.alert(
|
||||
'Coming soon',
|
||||
'This feature is not available right now. Please check back later.',
|
||||
[
|
||||
{
|
||||
text: 'Close'
|
||||
}
|
||||
],
|
||||
{
|
||||
userInterfaceStyle: 'dark'
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
import { CaretRight, Icon } from 'phosphor-react-native';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import { Alert, Pressable, Text, View } from 'react-native';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
|
||||
import { FeatureUnavailableAlert } from '../primitive/FeatureUnavailableAlert';
|
||||
|
||||
type SettingsItemProps = {
|
||||
title: string;
|
||||
onPress?: () => void;
|
||||
leftIcon?: Icon;
|
||||
rightArea?: React.ReactNode;
|
||||
comingSoon?: boolean;
|
||||
rounded?: 'top' | 'bottom';
|
||||
};
|
||||
|
||||
@@ -22,18 +25,27 @@ export function SettingsItem(props: SettingsItemProps) {
|
||||
? 'border-b border-r border-l'
|
||||
: 'border-l border-r';
|
||||
return (
|
||||
<Pressable onPress={props.onPress}>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
if (props.comingSoon) return FeatureUnavailableAlert();
|
||||
return props.onPress?.();
|
||||
}}
|
||||
>
|
||||
<View style={twStyle(' border-app-cardborder bg-app-card', borderRounded, border)}>
|
||||
<View style={tw`h-auto flex-row items-center`}>
|
||||
{props.leftIcon && (
|
||||
<View
|
||||
style={tw`ml-4 mr-5 h-8 w-8 items-center justify-center rounded-full border border-app-lightborder bg-app-button`}
|
||||
style={twStyle(
|
||||
`ml-4 mr-5 h-8 w-8 items-center justify-center rounded-full border border-app-lightborder bg-app-button`,
|
||||
props.comingSoon && 'opacity-50'
|
||||
)}
|
||||
>
|
||||
{props.leftIcon({ size: 20, color: tw.color('ink-dull') })}
|
||||
</View>
|
||||
)}
|
||||
<View
|
||||
style={twStyle(
|
||||
props.comingSoon && 'opacity-50',
|
||||
`flex-1 flex-row items-center justify-between border-b py-4`,
|
||||
borderRounded !== 'rounded-b-md'
|
||||
? 'border-app-cardborder'
|
||||
|
||||
@@ -28,6 +28,7 @@ type SectionType = {
|
||||
title: string;
|
||||
icon: Icon;
|
||||
navigateTo: keyof SettingsStackParamList;
|
||||
comingSoon?: boolean;
|
||||
rounded?: 'top' | 'bottom';
|
||||
}[];
|
||||
};
|
||||
@@ -49,19 +50,22 @@ const sections: (debugState: DebugState) => SectionType[] = (debugState) => [
|
||||
},
|
||||
{
|
||||
icon: PaintBrush,
|
||||
comingSoon: true,
|
||||
navigateTo: 'AppearanceSettings',
|
||||
title: 'Appearance'
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
navigateTo: 'PrivacySettings',
|
||||
comingSoon: true,
|
||||
title: 'Privacy'
|
||||
},
|
||||
{
|
||||
icon: PuzzlePiece,
|
||||
navigateTo: 'ExtensionsSettings',
|
||||
title: 'Extensions',
|
||||
rounded: 'bottom'
|
||||
rounded: 'bottom',
|
||||
comingSoon: true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -82,6 +86,7 @@ const sections: (debugState: DebugState) => SectionType[] = (debugState) => [
|
||||
{
|
||||
icon: ShareNetwork,
|
||||
navigateTo: 'NodesSettings',
|
||||
comingSoon: true,
|
||||
title: 'Nodes'
|
||||
},
|
||||
{
|
||||
@@ -159,6 +164,7 @@ export default function SettingsScreen({ navigation }: SettingsStackScreenProps<
|
||||
sections={sections(debugState)}
|
||||
renderItem={({ item }) => (
|
||||
<SettingsItem
|
||||
comingSoon={item.comingSoon}
|
||||
title={item.title}
|
||||
leftIcon={item.icon}
|
||||
onPress={() => navigation.navigate(item.navigateTo as any)}
|
||||
|
||||
@@ -24,7 +24,7 @@ const DebugScreen = ({ navigation }: SettingsStackScreenProps<'Debug'>) => {
|
||||
|
||||
return (
|
||||
<View style={tw`flex-1 p-4`}>
|
||||
<Card style={tw`gap-y-4 bg-app-box`}>
|
||||
<Card style={tw`gap-y-4`}>
|
||||
<Text style={tw`font-semibold text-ink`}>Debug</Text>
|
||||
<Button onPress={() => (debugState.rspcLogger = !debugState.rspcLogger)}>
|
||||
<Text style={tw`text-ink`}>Toggle rspc logger</Text>
|
||||
|
||||
Reference in New Issue
Block a user