Add AddItem page base

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-07-10 10:25:38 +03:00
parent ab6aa76fa2
commit f64588b17c
9 changed files with 888 additions and 129 deletions

877
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,6 @@
"dependencies": { "dependencies": {
"@react-native-async-storage/async-storage": "^1.19.0", "@react-native-async-storage/async-storage": "^1.19.0",
"@react-navigation/bottom-tabs": "^6.5.8", "@react-navigation/bottom-tabs": "^6.5.8",
"@react-navigation/drawer": "^6.6.3",
"@react-navigation/native": "^6.1.7", "@react-navigation/native": "^6.1.7",
"@react-navigation/native-stack": "^6.9.13", "@react-navigation/native-stack": "^6.9.13",
"@realm/react": "^0.5.1", "@realm/react": "^0.5.1",
@@ -36,6 +35,7 @@
"@babel/core": "^7.20.0", "@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0", "@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0", "@babel/runtime": "^7.20.0",
"@jest/globals": "^29.6.1",
"@react-native/eslint-config": "^0.72.2", "@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.7", "@react-native/metro-config": "^0.72.7",
"@tsconfig/react-native": "^3.0.2", "@tsconfig/react-native": "^3.0.2",
@@ -44,7 +44,10 @@
"@types/react": "^18.2.14", "@types/react": "^18.2.14",
"@types/react-native-vector-icons": "^6.4.13", "@types/react-native-vector-icons": "^6.4.13",
"@types/react-test-renderer": "^18.0.0", "@types/react-test-renderer": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"babel-jest": "^29.2.1", "babel-jest": "^29.2.1",
"depcheck": "^1.4.3",
"eslint": "^8.44.0", "eslint": "^8.44.0",
"eslint-plugin-jest": "^27.2.2", "eslint-plugin-jest": "^27.2.2",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",

View File

@@ -1,8 +1,9 @@
import * as React from 'react'; import * as React from 'react';
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { FAB, Portal } from 'react-native-paper'; import { FAB, Portal } from 'react-native-paper';
import { noOp } from '../constants';
import { verticalScale } from '../styles'; import { verticalScale } from '../styles';
import { ParamListBase, useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
fab: { fab: {
@@ -10,40 +11,42 @@ const styles = StyleSheet.create({
}, },
}); });
const FloatingActionButton = () => { const FloatingActionButton = ({ visible }: { visible?: boolean }) => {
const [state, setState] = React.useState(false); const [state, setState] = React.useState(false);
const { navigate } =
useNavigation<NativeStackNavigationProp<ParamListBase>>();
return ( return (
<Portal> <Portal>
<FAB.Group <FAB.Group
open={state} open={state}
visible visible={visible ?? true}
icon={state ? 'image' : 'plus'} icon={state ? 'image' : 'plus'}
actions={[ actions={[
{ {
icon: 'tag', icon: 'tag',
label: 'Tag', label: 'Tag',
onPress: () => noOp, onPress: () => navigate('Add Item'),
}, },
{ {
icon: 'note-text', icon: 'note-text',
label: 'Text', label: 'Text',
onPress: () => noOp, onPress: () => navigate('Add Item'),
}, },
{ {
icon: 'microphone', icon: 'microphone',
label: 'Audio', label: 'Audio',
onPress: () => noOp, onPress: () => navigate('Add Item'),
}, },
{ {
icon: 'image-album', icon: 'image-album',
label: 'Album', label: 'Album',
onPress: () => noOp, onPress: () => navigate('Add Item'),
}, },
]} ]}
onStateChange={({ open }) => setState(open)} onStateChange={({ open }) => setState(open)}
onPress={() => { onPress={() => {
if (state) noOp; if (state) navigate('Add Item');
}} }}
style={styles.fab} style={styles.fab}
/> />

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, { ReactNode } from 'react';
import { StyleProp, View, ViewStyle } from 'react-native'; import { StyleProp, View, ViewStyle } from 'react-native';
import { useTheme } from 'react-native-paper'; import { useTheme } from 'react-native-paper';
import styles from '../styles'; import styles from '../styles';
@@ -8,7 +8,7 @@ const PaddedView = ({
style, style,
centered, centered,
}: { }: {
children: React.ReactNode; children: ReactNode;
style?: StyleProp<ViewStyle>; style?: StyleProp<ViewStyle>;
centered?: boolean; centered?: boolean;
}) => { }) => {

View File

@@ -1 +1 @@
export { useSettings, SettingsProvider } from './settings'; export { SettingsProvider, useSettings } from './settings';

View File

@@ -1,4 +1,10 @@
import React, { createContext, useContext, useState, useEffect } from 'react'; import React, {
createContext,
useContext,
useState,
useEffect,
ReactNode,
} from 'react';
import { Settings } from '../types'; import { Settings } from '../types';
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
import { LoadingView } from '../components'; import { LoadingView } from '../components';
@@ -19,9 +25,7 @@ const SettingsContext = createContext<SettingsContextType | undefined>(
undefined, undefined,
); );
const SettingsProvider: React.FC<{ children: React.ReactNode }> = ({ function SettingsProvider({ children }: { children: ReactNode }) {
children,
}) => {
const [settings, setSettings] = useState<Settings>({ const [settings, setSettings] = useState<Settings>({
storageUri: '', storageUri: '',
}); });
@@ -51,7 +55,9 @@ const SettingsProvider: React.FC<{ children: React.ReactNode }> = ({
if (storageUri !== '') { if (storageUri !== '') {
const permissions = await getPersistedUriPermissions(); const permissions = await getPersistedUriPermissions();
if ( if (
!permissions.some(permission => storageUri.startsWith(permission + '/')) !permissions.some(permission =>
storageUri.startsWith(permission + '/'),
)
) { ) {
storageUri = ''; storageUri = '';
} }
@@ -100,7 +106,7 @@ const SettingsProvider: React.FC<{ children: React.ReactNode }> = ({
)} )}
</SettingsContext.Provider> </SettingsContext.Provider>
); );
}; }
const useSettings = (): SettingsContextType => { const useSettings = (): SettingsContextType => {
const context = useContext(SettingsContext); const context = useContext(SettingsContext);

View File

@@ -5,32 +5,20 @@ import {
} from '@react-navigation/native'; } from '@react-navigation/native';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5'; import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { BottomNavigation, useTheme } from 'react-native-paper'; import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Home, Search, Tags, Settings } from './screens'; import { BottomNavigation, Portal, useTheme } from 'react-native-paper';
import { FloatingActionButton } from './components'; import { Home, Search, Tags, Settings, AddItem } from './screens';
import { horizontalScale } from './styles'; import { horizontalScale } from './styles';
import { FloatingActionButton } from './components';
function NavigationContainer() { function TabNavigator() {
const TabNavigator = createBottomTabNavigator(); const TabNavigatorBase = createBottomTabNavigator();
const theme = useTheme(); const [fabVisible, setFabVisible] = React.useState(true);
const [showFab, setShowFab] = React.useState(true);
return ( return (
<> <>
<NavigationContainerBase <Portal.Host>
theme={{ <TabNavigatorBase.Navigator
dark: theme.dark,
colors: {
primary: theme.colors.primary,
background: theme.colors.background,
card: theme.colors.surface,
text: theme.colors.onSurface,
border: theme.colors.outline,
notification: theme.colors.error,
},
}}>
<TabNavigator.Navigator
screenOptions={{ screenOptions={{
headerShown: false, headerShown: false,
}} }}
@@ -52,7 +40,9 @@ function NavigationContainer() {
target: state.key, target: state.key,
}); });
} }
setShowFab(route.name !== 'Settings'); route.name === 'Settings'
? setFabVisible(false)
: setFabVisible(true);
}} }}
renderIcon={({ route, focused, color }) => { renderIcon={({ route, focused, color }) => {
const { options } = descriptors[route.key]; const { options } = descriptors[route.key];
@@ -70,7 +60,7 @@ function NavigationContainer() {
}} }}
/> />
)}> )}>
<TabNavigator.Screen <TabNavigatorBase.Screen
name="Home" name="Home"
component={Home} component={Home}
options={{ options={{
@@ -79,7 +69,7 @@ function NavigationContainer() {
), ),
}} }}
/> />
<TabNavigator.Screen <TabNavigatorBase.Screen
name="Search" name="Search"
component={Search} component={Search}
options={{ options={{
@@ -88,7 +78,7 @@ function NavigationContainer() {
), ),
}} }}
/> />
<TabNavigator.Screen <TabNavigatorBase.Screen
name="Tags" name="Tags"
component={Tags} component={Tags}
options={{ options={{
@@ -97,7 +87,7 @@ function NavigationContainer() {
), ),
}} }}
/> />
<TabNavigator.Screen <TabNavigatorBase.Screen
name="Settings" name="Settings"
component={Settings} component={Settings}
options={{ options={{
@@ -106,11 +96,40 @@ function NavigationContainer() {
), ),
}} }}
/> />
</TabNavigator.Navigator> </TabNavigatorBase.Navigator>
</NavigationContainerBase> <FloatingActionButton visible={fabVisible} />
{showFab && <FloatingActionButton />} </Portal.Host>
</> </>
); );
} }
function NavigationContainer() {
const StackNavigatorBase = createNativeStackNavigator();
const theme = useTheme();
return (
<NavigationContainerBase
theme={{
dark: theme.dark,
colors: {
primary: theme.colors.primary,
background: theme.colors.background,
card: theme.colors.surface,
text: theme.colors.onSurface,
border: theme.colors.outline,
notification: theme.colors.error,
},
}}>
<StackNavigatorBase.Navigator screenOptions={{ headerShown: false }}>
<StackNavigatorBase.Screen name="Main" component={TabNavigator} />
<StackNavigatorBase.Screen
name="Add Item"
component={AddItem}
options={{ animation: 'slide_from_bottom' }}
/>
</StackNavigatorBase.Navigator>
</NavigationContainerBase>
);
}
export default NavigationContainer; export default NavigationContainer;

14
src/screens/addItem.tsx Normal file
View File

@@ -0,0 +1,14 @@
import React from 'react';
import { Text } from 'react-native-paper';
import { PaddedView } from '../components';
const AddItem = () => {
return (
<PaddedView centered>
<Text>Add Item</Text>
</PaddedView>
);
};
export default AddItem;

View File

@@ -1,3 +1,4 @@
export { default as AddItem } from './addItem';
export { default as Home } from './home'; export { default as Home } from './home';
export { default as Search } from './search'; export { default as Search } from './search';
export { default as Tags } from './tags'; export { default as Tags } from './tags';