mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-04 05:15:09 -04:00
Merge branch 'main' of github.com:spacedriveapp/spacedrive into eng-1828-migration-to-new-cloud-api-system
This commit is contained in:
27
apps/mobile/src/hooks/useEnableDrawer.ts
Normal file
27
apps/mobile/src/hooks/useEnableDrawer.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
/**
|
||||
* This hook enables the drawer swipe gesture when the screen is focused and disables it when the screen is blurred.
|
||||
*/
|
||||
|
||||
export function useEnableDrawer(): void {
|
||||
const navigation = useNavigation();
|
||||
useEffect(() => {
|
||||
const tabNavigator = navigation.getParent(); // This is the TabNavigator
|
||||
const drawerNavigator = tabNavigator?.getParent(); // This is the DrawerNavigator
|
||||
|
||||
const unsubscribeFocus = navigation.addListener('focus', () => {
|
||||
drawerNavigator?.setOptions({ swipeEnabled: true });
|
||||
});
|
||||
|
||||
const unsubscribeBlur = navigation.addListener('blur', () => {
|
||||
drawerNavigator?.setOptions({ swipeEnabled: false });
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribeFocus();
|
||||
unsubscribeBlur();
|
||||
};
|
||||
}, [navigation]);
|
||||
}
|
||||
@@ -16,6 +16,7 @@ export default function DrawerNavigator() {
|
||||
initialRouteName="Home"
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
swipeEnabled: false,
|
||||
drawerStyle: {
|
||||
backgroundColor: tw.color('app-darkBox'),
|
||||
width: '70%',
|
||||
|
||||
@@ -10,7 +10,12 @@ const Stack = createNativeStackNavigator<SearchStackParamList>();
|
||||
|
||||
export default function SearchStack() {
|
||||
return (
|
||||
<Stack.Navigator initialRouteName="Search">
|
||||
<Stack.Navigator
|
||||
screenOptions={{
|
||||
fullScreenGestureEnabled: true
|
||||
}}
|
||||
initialRouteName="Search"
|
||||
>
|
||||
<Stack.Screen
|
||||
name="Search"
|
||||
component={SearchScreen}
|
||||
|
||||
@@ -118,40 +118,42 @@ export default function TabNavigator() {
|
||||
tabBarInactiveTintColor: tw.color('ink/50')
|
||||
}}
|
||||
>
|
||||
{TabScreens.map((screen, index) => (
|
||||
<Tab.Screen
|
||||
key={screen.name + index}
|
||||
name={screen.name}
|
||||
component={screen.component}
|
||||
options={({ navigation }) => ({
|
||||
tabBarLabel: screen.label,
|
||||
tabBarLabelStyle: screen.labelStyle,
|
||||
/**
|
||||
* TouchableWithoutFeedback is used to prevent Android ripple effect
|
||||
* State is being used to control the animation and make Rive work
|
||||
* Tab.Screen listeners are needed because if a user taps on the tab text only, the animation won't play
|
||||
* This may be revisited in the future to update accordingly
|
||||
*/
|
||||
tabBarIcon: () => (
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => {
|
||||
navigation.navigate(screen.name);
|
||||
setActiveIndex(index);
|
||||
}}
|
||||
>
|
||||
{screen.icon}
|
||||
</TouchableWithoutFeedback>
|
||||
),
|
||||
tabBarTestID: screen.testID
|
||||
})}
|
||||
listeners={() => ({
|
||||
focus: () => {
|
||||
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
||||
setActiveIndex(index);
|
||||
}
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
{TabScreens.map((screen, index) => {
|
||||
return (
|
||||
<Tab.Screen
|
||||
key={screen.name + index}
|
||||
name={screen.name}
|
||||
component={screen.component}
|
||||
options={({ navigation }) => ({
|
||||
tabBarLabel: screen.label,
|
||||
tabBarLabelStyle: screen.labelStyle,
|
||||
/**
|
||||
* TouchableWithoutFeedback is used to prevent Android ripple effect
|
||||
* State is being used to control the animation and make Rive work
|
||||
* Tab.Screen listeners are needed because if a user taps on the tab text only, the animation won't play
|
||||
* This may be revisited in the future to update accordingly
|
||||
*/
|
||||
tabBarIcon: () => (
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => {
|
||||
navigation.navigate(screen.name);
|
||||
setActiveIndex(index);
|
||||
}}
|
||||
>
|
||||
{screen.icon}
|
||||
</TouchableWithoutFeedback>
|
||||
),
|
||||
tabBarTestID: screen.testID
|
||||
})}
|
||||
listeners={() => ({
|
||||
focus: () => {
|
||||
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
||||
setActiveIndex(index);
|
||||
}
|
||||
})}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Tab.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,12 @@ const Stack = createNativeStackNavigator<BrowseStackParamList>();
|
||||
|
||||
export default function BrowseStack() {
|
||||
return (
|
||||
<Stack.Navigator initialRouteName="Browse">
|
||||
<Stack.Navigator
|
||||
screenOptions={{
|
||||
fullScreenGestureEnabled: true
|
||||
}}
|
||||
initialRouteName="Browse"
|
||||
>
|
||||
<Stack.Screen
|
||||
name="Browse"
|
||||
component={BrowseScreen}
|
||||
|
||||
@@ -11,7 +11,12 @@ const Stack = createNativeStackNavigator<OverviewStackParamList>();
|
||||
|
||||
export default function OverviewStack() {
|
||||
return (
|
||||
<Stack.Navigator initialRouteName="Overview">
|
||||
<Stack.Navigator
|
||||
screenOptions={{
|
||||
fullScreenGestureEnabled: true
|
||||
}}
|
||||
initialRouteName="Overview"
|
||||
>
|
||||
<Stack.Screen
|
||||
name="Overview"
|
||||
component={OverviewScreen}
|
||||
|
||||
@@ -36,7 +36,12 @@ export type User = {
|
||||
|
||||
export default function SettingsStack() {
|
||||
return (
|
||||
<Stack.Navigator initialRouteName="Settings">
|
||||
<Stack.Navigator
|
||||
screenOptions={{
|
||||
fullScreenGestureEnabled: true
|
||||
}}
|
||||
initialRouteName="Settings"
|
||||
>
|
||||
<Stack.Screen
|
||||
name="Settings"
|
||||
component={SettingsScreen}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import BrowseLocations from '~/components/browse/BrowseLocations';
|
||||
import BrowseTags from '~/components/browse/BrowseTags';
|
||||
import ScreenContainer from '~/components/layout/ScreenContainer';
|
||||
import { useEnableDrawer } from '~/hooks/useEnableDrawer';
|
||||
|
||||
export default function BrowseScreen() {
|
||||
useEnableDrawer();
|
||||
return (
|
||||
<ScreenContainer>
|
||||
{/* <BrowseCategories /> */}
|
||||
|
||||
@@ -16,9 +16,10 @@ import { useSearchStore } from '~/stores/searchStore';
|
||||
|
||||
interface Props {
|
||||
viewStyle?: 'grid' | 'list';
|
||||
navToSettings?: boolean; // on press, navigate to settings
|
||||
}
|
||||
|
||||
export default function LocationsScreen({ viewStyle }: Props) {
|
||||
export default function LocationsScreen({ viewStyle, navToSettings }: Props) {
|
||||
const locationsQuery = useLibraryQuery(['locations.list']);
|
||||
const locations = locationsQuery.data;
|
||||
const { search } = useSearchStore();
|
||||
@@ -67,12 +68,18 @@ export default function LocationsScreen({ viewStyle }: Props) {
|
||||
numColumns={viewStyle === 'grid' ? 3 : 1}
|
||||
renderItem={({ item }) => (
|
||||
<LocationItem
|
||||
onPress={() =>
|
||||
onPress={() => {
|
||||
if (navToSettings) {
|
||||
return navigation.navigate('SettingsStack', {
|
||||
screen: 'EditLocationSettings',
|
||||
params: { id: item.id }
|
||||
});
|
||||
}
|
||||
navigation.navigate('BrowseStack', {
|
||||
screen: 'Location',
|
||||
params: { id: item.id }
|
||||
})
|
||||
}
|
||||
});
|
||||
}}
|
||||
editLocation={() =>
|
||||
navigation.navigate('SettingsStack', {
|
||||
screen: 'EditLocationSettings',
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Text } from 'react-native';
|
||||
import { Icon } from '~/components/icons/Icon';
|
||||
import ScreenContainer from '~/components/layout/ScreenContainer';
|
||||
import { useEnableDrawer } from '~/hooks/useEnableDrawer';
|
||||
import { tw } from '~/lib/tailwind';
|
||||
import { NetworkStackScreenProps } from '~/navigation/tabs/NetworkStack';
|
||||
|
||||
export default function NetworkScreen({ navigation }: NetworkStackScreenProps<'Network'>) {
|
||||
useEnableDrawer();
|
||||
return (
|
||||
<ScreenContainer scrollview={false} style={tw`items-center justify-center gap-0`}>
|
||||
<Icon name="Globe" size={128} />
|
||||
|
||||
@@ -5,6 +5,7 @@ import Cloud from '~/components/overview/Cloud';
|
||||
import Devices from '~/components/overview/Devices';
|
||||
import Locations from '~/components/overview/Locations';
|
||||
import OverviewStats from '~/components/overview/OverviewStats';
|
||||
import { useEnableDrawer } from '~/hooks/useEnableDrawer';
|
||||
|
||||
const EMPTY_STATISTICS = {
|
||||
id: 0,
|
||||
@@ -26,6 +27,7 @@ export default function OverviewScreen() {
|
||||
|
||||
// Running the query here so the data is already available for settings screen
|
||||
useLibraryQuery(['sync.enabled']);
|
||||
useEnableDrawer();
|
||||
|
||||
return (
|
||||
<ScreenContainer>
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Platform, SectionList, Text, TouchableWithoutFeedback, View } from 'rea
|
||||
import { DebugState, useDebugState, useDebugStateEnabler, useLibraryQuery } from '@sd/client';
|
||||
import ScreenContainer from '~/components/layout/ScreenContainer';
|
||||
import { SettingsItem } from '~/components/settings/SettingsItem';
|
||||
import { useEnableDrawer } from '~/hooks/useEnableDrawer';
|
||||
import { tw, twStyle } from '~/lib/tailwind';
|
||||
import {
|
||||
SettingsStackParamList,
|
||||
@@ -200,6 +201,8 @@ export default function SettingsScreen({ navigation }: SettingsStackScreenProps<
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [navigation]);
|
||||
|
||||
useEnableDrawer();
|
||||
|
||||
return (
|
||||
<ScreenContainer tabHeight={false} style={tw`gap-0 px-5 py-0`}>
|
||||
<SectionList
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import LocationsScreen from '~/screens/browse/Locations';
|
||||
|
||||
const LocationSettingsScreen = () => {
|
||||
return <LocationsScreen viewStyle="list" />;
|
||||
return <LocationsScreen navToSettings viewStyle="list" />;
|
||||
};
|
||||
|
||||
export default LocationSettingsScreen;
|
||||
|
||||
@@ -63,7 +63,7 @@ export const OpenQuickView = () => {
|
||||
|
||||
return (
|
||||
<ContextMenu.Item
|
||||
label={t('quick_view')}
|
||||
label={t('quick_preview')}
|
||||
keybind={keybind([], [' '])}
|
||||
onClick={() => (getQuickPreviewStore().open = true)}
|
||||
/>
|
||||
|
||||
@@ -395,6 +395,7 @@ export const SingleItemMetadata = ({ item }: { item: ExplorerItem }) => {
|
||||
<DropdownMenu.Root
|
||||
trigger={<PlaceholderPill>{t('add_tag')}</PlaceholderPill>}
|
||||
side="left"
|
||||
className="z-[101]"
|
||||
sideOffset={5}
|
||||
alignOffset={-10}
|
||||
>
|
||||
|
||||
@@ -19,7 +19,7 @@ export const ColorPicker = <T extends FieldValues>({ className, ...props }: Prop
|
||||
style={{ backgroundColor: field.value }}
|
||||
/>
|
||||
}
|
||||
className="p-3"
|
||||
className="relative z-[110] p-3"
|
||||
sideOffset={5}
|
||||
>
|
||||
<HexColorPicker color={field.value} onChange={field.onChange} />
|
||||
|
||||
@@ -261,14 +261,14 @@ export function Dialog<S extends FieldValues>({
|
||||
show ? (
|
||||
<RDialog.Portal forceMount>
|
||||
<AnimatedDialogOverlay
|
||||
className="z-49 fixed inset-0 m-px grid place-items-center overflow-y-auto rounded-xl bg-app/50"
|
||||
className="fixed inset-0 z-[102] m-px grid place-items-center overflow-y-auto rounded-xl bg-app/50"
|
||||
style={{
|
||||
opacity: styles.opacity
|
||||
}}
|
||||
/>
|
||||
|
||||
<AnimatedDialogContent
|
||||
className="!pointer-events-none fixed inset-0 z-50 grid place-items-center overflow-y-auto"
|
||||
className="!pointer-events-none fixed inset-0 z-[103] grid place-items-center overflow-y-auto"
|
||||
style={styles}
|
||||
onInteractOutside={(e) =>
|
||||
props.ignoreClickOutside && e.preventDefault()
|
||||
|
||||
Reference in New Issue
Block a user