mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-02 10:03:28 +00:00
[MOB-47] Location screen and header updates (#2056)
* Location screen and header updates * use tw sizing * remove un-necessary prop * Nit: change name
This commit is contained in:
parent
58f9305965
commit
2d0c340e58
|
@ -18,6 +18,7 @@ import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack';
|
|||
import { SettingsStackScreenProps } from '~/navigation/tabs/SettingsStack';
|
||||
|
||||
import FolderIcon from '../icons/FolderIcon';
|
||||
import { Icon } from '../icons/Icon';
|
||||
import Fade from '../layout/Fade';
|
||||
import ImportModal from '../modal/ImportModal';
|
||||
import { LocationModal } from '../modal/location/LocationModal';
|
||||
|
@ -39,7 +40,7 @@ const BrowseLocationItem: React.FC<BrowseLocationItemProps> = ({
|
|||
return (
|
||||
<Pressable onPress={onPress}>
|
||||
<View
|
||||
style={tw`h-auto w-[100px] flex-col justify-center gap-3 rounded-md border border-sidebar-line/50 bg-sidebar-box p-2`}
|
||||
style={tw`h-auto w-[110px] flex-col justify-center gap-3 rounded-md border border-sidebar-line/50 bg-sidebar-box p-2`}
|
||||
>
|
||||
<View style={tw`w-full flex-col justify-between gap-1`}>
|
||||
<View style={tw`flex-row items-center justify-between`}>
|
||||
|
@ -61,7 +62,7 @@ const BrowseLocationItem: React.FC<BrowseLocationItemProps> = ({
|
|||
</Pressable>
|
||||
</View>
|
||||
<Text
|
||||
style={tw`w-full max-w-[75px] text-xs font-bold text-white`}
|
||||
style={tw`w-full max-w-[100px] text-xs font-bold text-white`}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{location.name}
|
||||
|
@ -98,14 +99,19 @@ const BrowseLocations = () => {
|
|||
return (
|
||||
<View style={tw`gap-5`}>
|
||||
<View style={tw`w-full flex-row items-center justify-between px-7`}>
|
||||
<Text style={tw`text-xl font-bold text-white`}>Locations</Text>
|
||||
<Text style={tw`text-lg font-bold text-white`}>Locations</Text>
|
||||
<View style={tw`flex-row gap-3`}>
|
||||
<Pressable
|
||||
disabled={result.data?.nodes.length === 0}
|
||||
onPress={() => {
|
||||
navigation.navigate('Locations');
|
||||
}}
|
||||
>
|
||||
<View style={tw`h-8 w-8 items-center justify-center rounded-md bg-accent`}>
|
||||
<View
|
||||
style={tw`h-8 w-8 items-center justify-center rounded-md bg-accent ${
|
||||
result.data?.nodes.length === 0 ? 'opacity-40' : 'opacity-100'
|
||||
}`}
|
||||
>
|
||||
<Eye weight="bold" size={18} style={tw`text-white`} />
|
||||
</View>
|
||||
</Pressable>
|
||||
|
@ -121,6 +127,16 @@ const BrowseLocations = () => {
|
|||
<Fade color="mobile-screen" width={30} height="100%">
|
||||
<FlatList
|
||||
data={locations}
|
||||
ListEmptyComponent={() => (
|
||||
<View
|
||||
style={tw`relative h-auto w-[85.5vw] flex-col items-center justify-center overflow-hidden rounded-md border border-dashed border-sidebar-line p-4`}
|
||||
>
|
||||
<Icon name="Folder" size={38} />
|
||||
<Text style={tw`mt-2 text-center font-medium text-ink-dull`}>
|
||||
You have no locations
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
contentContainerStyle={tw`px-7`}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
ItemSeparatorComponent={() => <View style={tw`w-2`} />}
|
||||
|
|
|
@ -8,6 +8,7 @@ import { ModalRef } from '~/components/layout/Modal';
|
|||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack';
|
||||
|
||||
import { Icon } from '../icons/Icon';
|
||||
import Fade from '../layout/Fade';
|
||||
import CreateTagModal from '../modal/tag/CreateTagModal';
|
||||
import { TagModal } from '../modal/tag/TagModal';
|
||||
|
@ -63,10 +64,14 @@ const BrowseTags = () => {
|
|||
return (
|
||||
<View style={tw`gap-5`}>
|
||||
<View style={tw`w-full flex-row items-center justify-between px-7`}>
|
||||
<Text style={tw`text-xl font-bold text-white`}>Tags</Text>
|
||||
<Text style={tw`text-lg font-bold text-white`}>Tags</Text>
|
||||
<View style={tw`flex-row gap-3`}>
|
||||
<Pressable>
|
||||
<View style={tw`h-8 w-8 items-center justify-center rounded-md bg-accent`}>
|
||||
<View
|
||||
style={tw`h-8 w-8 items-center justify-center rounded-md bg-accent ${
|
||||
tags.data?.nodes.length === 0 ? 'opacity-40' : 'opacity-100'
|
||||
}`}
|
||||
>
|
||||
<Eye weight="bold" size={18} style={tw`text-white`} />
|
||||
</View>
|
||||
</Pressable>
|
||||
|
@ -82,10 +87,22 @@ const BrowseTags = () => {
|
|||
<Fade color="mobile-screen" width={30} height="100%">
|
||||
<FlatList
|
||||
data={tagData}
|
||||
ListEmptyComponent={() => (
|
||||
<View
|
||||
style={tw`relative h-auto w-[85.5vw] flex-col items-center justify-center overflow-hidden rounded-md border border-dashed border-sidebar-line p-4`}
|
||||
>
|
||||
<Icon name="Tags" size={38} />
|
||||
<Text style={tw`mt-2 text-center font-medium text-ink-dull`}>
|
||||
You have no tags
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
renderItem={({ item }) => (
|
||||
<BrowseTagItem
|
||||
tag={item}
|
||||
onPress={() => navigation.navigate('Tag', { id: item.id })}
|
||||
onPress={() =>
|
||||
navigation.navigate('Tag', { id: item.id, color: item.color! })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={(item) => item.id.toString()}
|
||||
|
|
|
@ -29,7 +29,7 @@ const CATEGORIES_LIST = [
|
|||
const Categories = () => {
|
||||
return (
|
||||
<View style={tw`relative gap-5`}>
|
||||
<Text style={tw`px-7 text-xl font-bold text-white`}>Library</Text>
|
||||
<Text style={tw`text-lg font-bold text-white px-7`}>Library</Text>
|
||||
<Fade width={30} height="100%" color="mobile-screen">
|
||||
<ScrollView showsHorizontalScrollIndicator={false} horizontal>
|
||||
<View style={tw`flex-row gap-2 px-7`}>
|
||||
|
|
|
@ -11,7 +11,7 @@ const Jobs = () => {
|
|||
return (
|
||||
<View style={tw`gap-5`}>
|
||||
<View style={tw`w-full flex-row items-center justify-between px-7`}>
|
||||
<Text style={tw`text-xl font-bold text-white`}>Jobs</Text>
|
||||
<Text style={tw`text-lg font-bold text-white`}>Jobs</Text>
|
||||
</View>
|
||||
<Fade color="mobile-screen" height="100%" width={30}>
|
||||
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
||||
|
@ -45,7 +45,7 @@ const Job = ({ progress, message, error }: JobProps) => {
|
|||
: tw.color('accent');
|
||||
return (
|
||||
<View
|
||||
style={tw`h-auto w-[310px] flex-col rounded-md border border-sidebar-line/50 bg-sidebar-box`}
|
||||
style={tw`h-[170px] w-[310px] flex-col rounded-md border border-sidebar-line/50 bg-sidebar-box`}
|
||||
>
|
||||
<View
|
||||
style={tw`w-full flex-row items-center justify-between rounded-t-md border-b border-sidebar-line/80 bg-mobile-header/50 px-5 py-2`}
|
||||
|
@ -56,7 +56,7 @@ const Job = ({ progress, message, error }: JobProps) => {
|
|||
</View>
|
||||
<DotsThreeOutlineVertical weight="fill" size={20} color={tw.color('ink-faint')} />
|
||||
</View>
|
||||
<View style={tw`mx-auto flex-1 flex-row items-center justify-between gap-5 px-5 py-2`}>
|
||||
<View style={tw`mx-auto flex-1 flex-row items-center justify-between gap-5 px-5 py-3`}>
|
||||
<AnimatedCircularProgress
|
||||
size={80}
|
||||
width={7}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { useNavigation } from '@react-navigation/native';
|
||||
import { FlashList } from '@shopify/flash-list';
|
||||
import { Rows, SquaresFour } from 'phosphor-react-native';
|
||||
import { AnimatePresence, MotiView } from 'moti';
|
||||
import { MonitorPlay, Rows, SlidersHorizontal, SquaresFour } from 'phosphor-react-native';
|
||||
import { useState } from 'react';
|
||||
import { Pressable, View } from 'react-native';
|
||||
import { isPath, type ExplorerItem } from '@sd/client';
|
||||
import SortByMenu from '~/components/menu/SortByMenu';
|
||||
import Layout from '~/constants/Layout';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack';
|
||||
import { getExplorerStore } from '~/stores/explorerStore';
|
||||
import { ExplorerLayoutMode, getExplorerStore, useExplorerStore } from '~/stores/explorerStore';
|
||||
import { useActionsModalStore } from '~/stores/modalStore';
|
||||
|
||||
import FileItem from './FileItem';
|
||||
|
@ -20,10 +20,10 @@ type ExplorerProps = {
|
|||
|
||||
const Explorer = ({ items }: ExplorerProps) => {
|
||||
const navigation = useNavigation<BrowseStackScreenProps<'Location'>['navigation']>();
|
||||
const explorerStore = useExplorerStore();
|
||||
const [layoutMode, setLayoutMode] = useState<ExplorerLayoutMode>(getExplorerStore().layoutMode);
|
||||
|
||||
const [layoutMode, setLayoutMode] = useState<'grid' | 'list'>(getExplorerStore().layoutMode);
|
||||
|
||||
function changeLayoutMode(kind: 'grid' | 'list') {
|
||||
function changeLayoutMode(kind: ExplorerLayoutMode) {
|
||||
// We need to keep layoutMode as a state to make sure flash-list re-renders.
|
||||
setLayoutMode(kind);
|
||||
getExplorerStore().layoutMode = kind;
|
||||
|
@ -44,13 +44,30 @@ const Explorer = ({ items }: ExplorerProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<View style={tw`flex-1`}>
|
||||
<View style={tw`flex-1 bg-mobile-screen`}>
|
||||
{/* Header */}
|
||||
<View style={tw`flex flex-row items-center justify-between p-3`}>
|
||||
<View style={tw`flex flex-row items-center justify-between`}>
|
||||
{/* Sort By */}
|
||||
<SortByMenu />
|
||||
{/* <SortByMenu /> */}
|
||||
<AnimatePresence>
|
||||
{explorerStore.toggleMenu && (
|
||||
<MotiView
|
||||
from={{ translateY: -70 }}
|
||||
animate={{ translateY: 0 }}
|
||||
transition={{ type: 'timing', duration: 300 }}
|
||||
exit={{ translateY: -70 }}
|
||||
>
|
||||
<ExplorerMenu
|
||||
changeLayoutMode={(kind: ExplorerLayoutMode) => {
|
||||
changeLayoutMode(kind);
|
||||
}}
|
||||
layoutMode={layoutMode}
|
||||
/>
|
||||
</MotiView>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
{/* Layout (Grid/List) */}
|
||||
{layoutMode === 'grid' ? (
|
||||
{/* {layoutMode === 'grid' ? (
|
||||
<Pressable onPress={() => changeLayoutMode('list')}>
|
||||
<SquaresFour color={tw.color('ink')} size={23} />
|
||||
</Pressable>
|
||||
|
@ -58,7 +75,7 @@ const Explorer = ({ items }: ExplorerProps) => {
|
|||
<Pressable onPress={() => changeLayoutMode('grid')}>
|
||||
<Rows color={tw.color('ink')} size={23} />
|
||||
</Pressable>
|
||||
)}
|
||||
)} */}
|
||||
</View>
|
||||
{/* Items */}
|
||||
{items && (
|
||||
|
@ -94,4 +111,39 @@ const Explorer = ({ items }: ExplorerProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
interface ExplorerMenuProps {
|
||||
layoutMode: ExplorerLayoutMode;
|
||||
changeLayoutMode: (kind: ExplorerLayoutMode) => void;
|
||||
}
|
||||
|
||||
const ExplorerMenu = ({ layoutMode, changeLayoutMode }: ExplorerMenuProps) => {
|
||||
return (
|
||||
<View
|
||||
style={tw`w-screen flex-row justify-between border-b border-app-line/50 bg-mobile-header px-7 py-4`}
|
||||
>
|
||||
<View style={tw`flex-row gap-3`}>
|
||||
<Pressable onPress={() => changeLayoutMode('grid')}>
|
||||
<SquaresFour
|
||||
color={tw.color(layoutMode === 'grid' ? 'text-accent' : 'text-ink-dull')}
|
||||
size={23}
|
||||
/>
|
||||
</Pressable>
|
||||
<Pressable onPress={() => changeLayoutMode('list')}>
|
||||
<Rows
|
||||
color={tw.color(layoutMode === 'list' ? 'text-accent' : 'text-ink-dull')}
|
||||
size={23}
|
||||
/>
|
||||
</Pressable>
|
||||
<Pressable onPress={() => changeLayoutMode('media')}>
|
||||
<MonitorPlay
|
||||
color={tw.color(layoutMode === 'media' ? 'text-accent' : 'text-ink-dull')}
|
||||
size={23}
|
||||
/>
|
||||
</Pressable>
|
||||
</View>
|
||||
<SlidersHorizontal style={tw`text-ink-dull`} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Explorer;
|
||||
|
|
|
@ -1,24 +1,48 @@
|
|||
import { useNavigation } from '@react-navigation/native';
|
||||
import { ArrowLeft, MagnifyingGlass } from 'phosphor-react-native';
|
||||
import { StackHeaderProps } from '@react-navigation/stack';
|
||||
import { ArrowLeft, DotsThreeOutline, MagnifyingGlass } from 'phosphor-react-native';
|
||||
import { lazy } from 'react';
|
||||
import { Pressable, Text, View } from 'react-native';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import { getExplorerStore, useExplorerStore } from '~/stores/explorerStore';
|
||||
|
||||
import { Icon } from '../icons/Icon';
|
||||
|
||||
//Not all pages use these components - so we lazy load for performance
|
||||
const BrowseLibraryManager = lazy(() => import('../browse/DrawerLibraryManager'));
|
||||
const Search = lazy(() => import('../inputs/Search'));
|
||||
|
||||
interface Props {
|
||||
type HeaderProps = {
|
||||
title?: string; //title of the page
|
||||
showLibrary?: boolean; //show the library manager
|
||||
searchType?: 'explorer' | 'location'; //Temporary
|
||||
navBack?: boolean; //navigate back to the previous screen
|
||||
}
|
||||
headerKind?: 'default' | 'location' | 'tag'; //kind of header
|
||||
route?: never;
|
||||
routeTitle?: never;
|
||||
};
|
||||
|
||||
//you can pass in a routeTitle only if route is passed in
|
||||
type Props =
|
||||
| HeaderProps
|
||||
| ({
|
||||
route: StackHeaderProps;
|
||||
routeTitle?: boolean;
|
||||
} & Omit<HeaderProps, 'route' | 'routeTitle'>);
|
||||
|
||||
// Default header with search bar and button to open drawer
|
||||
export default function Header({ title, showLibrary, searchType, navBack }: Props) {
|
||||
export default function Header({
|
||||
title,
|
||||
showLibrary,
|
||||
searchType,
|
||||
navBack,
|
||||
route,
|
||||
routeTitle,
|
||||
headerKind = 'default'
|
||||
}: Props) {
|
||||
const navigation = useNavigation();
|
||||
|
||||
const explorerStore = useExplorerStore();
|
||||
const routeParams = route?.route.params as any;
|
||||
const SearchType = () => {
|
||||
switch (searchType) {
|
||||
case 'explorer':
|
||||
|
@ -29,6 +53,22 @@ export default function Header({ title, showLibrary, searchType, navBack }: Prop
|
|||
return null;
|
||||
}
|
||||
};
|
||||
const HeaderIconKind = () => {
|
||||
switch (headerKind) {
|
||||
case 'location':
|
||||
return <Icon size={32} name="Folder" />;
|
||||
case 'tag':
|
||||
return (
|
||||
<View
|
||||
style={twStyle('h-6 w-6 rounded-full', {
|
||||
backgroundColor: routeParams.color
|
||||
})}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={tw`relative h-auto w-full border-b border-app-line/50 bg-mobile-header pt-10`}>
|
||||
|
@ -44,16 +84,41 @@ export default function Header({ title, showLibrary, searchType, navBack }: Prop
|
|||
<ArrowLeft size={23} color={tw.color('ink')} />
|
||||
</Pressable>
|
||||
)}
|
||||
<Text style={tw`text-[24px] font-bold text-white`}>{title}</Text>
|
||||
<View style={tw`flex-row items-center gap-2`}>
|
||||
<HeaderIconKind />
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
style={tw`max-w-[190px] text-lg font-bold text-white`}
|
||||
>
|
||||
{title || (routeTitle && route?.options.title)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={tw`flex-row items-center gap-3`}>
|
||||
<Pressable onPress={() => navigation.navigate('Search')}>
|
||||
<MagnifyingGlass
|
||||
size={20}
|
||||
weight="bold"
|
||||
color={tw.color('text-zinc-300')}
|
||||
/>
|
||||
</Pressable>
|
||||
{(headerKind === 'location' || headerKind === 'tag') && (
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
getExplorerStore().toggleMenu = !explorerStore.toggleMenu;
|
||||
}}
|
||||
>
|
||||
<DotsThreeOutline
|
||||
size={24}
|
||||
color={tw.color(
|
||||
explorerStore.toggleMenu ? 'text-accent' : 'text-zinc-300'
|
||||
)}
|
||||
/>
|
||||
</Pressable>
|
||||
)}
|
||||
</View>
|
||||
<Pressable onPress={() => navigation.navigate('Search')}>
|
||||
<MagnifyingGlass
|
||||
size={20}
|
||||
weight="bold"
|
||||
color={tw.color('text-zinc-300')}
|
||||
/>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
{showLibrary && <BrowseLibraryManager style="mt-4" />}
|
||||
{searchType && <SearchType />}
|
||||
</View>
|
||||
|
|
|
@ -34,8 +34,10 @@ export function SettingsItem(props: SettingsItemProps) {
|
|||
)}
|
||||
<View
|
||||
style={twStyle(
|
||||
`flex-1 flex-row items-center justify-between py-4`,
|
||||
borderRounded !== 'rounded-b-md' && 'border-b border-app-input'
|
||||
`flex-1 flex-row items-center justify-between border-b py-4`,
|
||||
borderRounded !== 'rounded-b-md'
|
||||
? 'border-app-input'
|
||||
: 'border-transparent'
|
||||
)}
|
||||
>
|
||||
<Text style={tw`text-sm font-medium text-ink`}>{props.title}</Text>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { CompositeScreenProps } from '@react-navigation/native';
|
||||
import { createStackNavigator, StackScreenProps } from '@react-navigation/stack';
|
||||
import { ArrowLeft } from 'phosphor-react-native';
|
||||
import Header from '~/components/header/Header';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import BrowseScreen from '~/screens/browse';
|
||||
|
@ -32,8 +31,8 @@ export default function BrowseStack() {
|
|||
name="Location"
|
||||
component={LocationScreen}
|
||||
options={{
|
||||
headerBackImage: () => (
|
||||
<ArrowLeft size={23} color={tw.color('ink')} style={tw`ml-2`} />
|
||||
header: (route) => (
|
||||
<Header route={route} headerKind="location" routeTitle navBack />
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
@ -48,9 +47,7 @@ export default function BrowseStack() {
|
|||
name="Tag"
|
||||
component={TagScreen}
|
||||
options={{
|
||||
headerBackImage: () => (
|
||||
<ArrowLeft size={23} color={tw.color('ink')} style={tw`ml-2`} />
|
||||
)
|
||||
header: (route) => <Header routeTitle route={route} headerKind="tag" navBack />
|
||||
}}
|
||||
/>
|
||||
</Stack.Navigator>
|
||||
|
@ -61,7 +58,7 @@ export type BrowseStackParamList = {
|
|||
Browse: undefined;
|
||||
Location: { id: number; path?: string };
|
||||
Locations: undefined;
|
||||
Tag: { id: number };
|
||||
Tag: { id: number; color: string };
|
||||
};
|
||||
|
||||
export type BrowseStackScreenProps<Screen extends keyof BrowseStackParamList> =
|
||||
|
|
|
@ -105,7 +105,7 @@ const LocationItem: React.FC<LocationItemProps> = ({
|
|||
/>
|
||||
</View>
|
||||
<Text
|
||||
style={tw`w-auto max-w-[160px] truncate text-sm font-bold text-white`}
|
||||
style={tw`w-auto max-w-[160px] text-sm font-bold text-white`}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{location.name}
|
||||
|
@ -114,7 +114,7 @@ const LocationItem: React.FC<LocationItemProps> = ({
|
|||
<View style={tw`flex-row items-center gap-3`}>
|
||||
<View style={tw`rounded-md bg-app-input p-1.5`}>
|
||||
<Text
|
||||
style={tw`truncate text-left text-xs font-bold text-ink-dull`}
|
||||
style={tw`text-left text-xs font-bold text-ink-dull`}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{`${byteSize(location.size_in_bytes)}`}
|
||||
|
|
|
@ -23,7 +23,7 @@ export default function BrowseScreen() {
|
|||
const height = useBottomTabBarHeight();
|
||||
return (
|
||||
<ScrollView style={twStyle('flex-1 bg-mobile-screen', { marginBottom: height })}>
|
||||
<View style={twStyle('justify-between gap-3 py-5')}>
|
||||
<View style={twStyle('justify-between gap-6 py-5')}>
|
||||
{/*Categories*/}
|
||||
<Categories />
|
||||
{/* Locations */}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { resetStore } from '@sd/client';
|
||||
import { proxy, useSnapshot } from 'valtio';
|
||||
import { proxySet } from 'valtio/utils';
|
||||
import { resetStore } from '@sd/client';
|
||||
|
||||
// TODO: Add "media"
|
||||
export type ExplorerLayoutMode = 'list' | 'grid';
|
||||
export type ExplorerLayoutMode = 'list' | 'grid' | "media"
|
||||
|
||||
export type ExplorerKind = 'Location' | 'Tag' | 'Space';
|
||||
|
||||
|
@ -11,6 +11,7 @@ const state = {
|
|||
locationId: null as number | null,
|
||||
path: '',
|
||||
layoutMode: 'grid' as ExplorerLayoutMode,
|
||||
toggleMenu: false as boolean,
|
||||
// Using gridNumColumns instead of fixed size. We dynamically calculate the item size.
|
||||
gridNumColumns: 3,
|
||||
listItemSize: 65,
|
||||
|
|
Loading…
Reference in a new issue