Compare commits
2 commits
300558ac56
...
4d0df7a5b7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d0df7a5b7 | ||
|
|
b8e7272d2c |
11 changed files with 401 additions and 412 deletions
|
|
@ -22,7 +22,7 @@ import {TouchableRipple, useTheme} from 'react-native-paper';
|
||||||
import {Dimensions, Image, View} from 'react-native';
|
import {Dimensions, Image, View} from 'react-native';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
image: string;
|
image?: string | number;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
};
|
};
|
||||||
|
|
@ -51,13 +51,17 @@ function DashboardEditPreviewItem(props: PropsType) {
|
||||||
width: itemSize,
|
width: itemSize,
|
||||||
height: itemSize,
|
height: itemSize,
|
||||||
}}>
|
}}>
|
||||||
<Image
|
{props.image ? (
|
||||||
source={{uri: props.image}}
|
<Image
|
||||||
style={{
|
source={
|
||||||
width: '100%',
|
typeof props.image === 'string' ? {uri: props.image} : props.image
|
||||||
height: '100%',
|
}
|
||||||
}}
|
style={{
|
||||||
/>
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</TouchableRipple>
|
</TouchableRipple>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -21,36 +21,22 @@ import * as React from 'react';
|
||||||
import {Animated} from 'react-native';
|
import {Animated} from 'react-native';
|
||||||
import {withTheme} from 'react-native-paper';
|
import {withTheme} from 'react-native-paper';
|
||||||
import {Collapsible} from 'react-navigation-collapsible';
|
import {Collapsible} from 'react-navigation-collapsible';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
|
||||||
import TabIcon from './TabIcon';
|
import TabIcon from './TabIcon';
|
||||||
import TabHomeIcon from './TabHomeIcon';
|
import TabHomeIcon from './TabHomeIcon';
|
||||||
|
import {BottomTabBarProps} from '@react-navigation/bottom-tabs';
|
||||||
|
import {NavigationState} from '@react-navigation/native';
|
||||||
|
import {
|
||||||
|
PartialState,
|
||||||
|
Route,
|
||||||
|
} from '@react-navigation/routers/lib/typescript/src/types';
|
||||||
|
|
||||||
type RouteType = {
|
type RouteType = Route<string> & {
|
||||||
name: string;
|
state?: NavigationState | PartialState<NavigationState>;
|
||||||
key: string;
|
|
||||||
params: {collapsible: Collapsible};
|
|
||||||
state: {
|
|
||||||
index: number;
|
|
||||||
routes: Array<RouteType>;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type PropsType = {
|
interface PropsType extends BottomTabBarProps {
|
||||||
state: {
|
|
||||||
index: number;
|
|
||||||
routes: Array<RouteType>;
|
|
||||||
};
|
|
||||||
descriptors: {
|
|
||||||
[key: string]: {
|
|
||||||
options: {
|
|
||||||
tabBarLabel: string;
|
|
||||||
title: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
navigation: StackNavigationProp<any>;
|
|
||||||
theme: ReactNativePaper.Theme;
|
theme: ReactNativePaper.Theme;
|
||||||
};
|
}
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
translateY: any;
|
translateY: any;
|
||||||
|
|
@ -164,7 +150,7 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
|
||||||
onLongPress={onLongPress}
|
onLongPress={onLongPress}
|
||||||
icon={this.getTabBarIcon(route, isFocused)}
|
icon={this.getTabBarIcon(route, isFocused)}
|
||||||
color={color}
|
color={color}
|
||||||
label={label}
|
label={label as string}
|
||||||
focused={isFocused}
|
focused={isFocused}
|
||||||
extraData={state.index > index}
|
extraData={state.index > index}
|
||||||
key={route.key}
|
key={route.key}
|
||||||
|
|
@ -193,9 +179,12 @@ class CustomTabBar extends React.Component<PropsType, StateType> {
|
||||||
if (isFocused) {
|
if (isFocused) {
|
||||||
const stackState = route.state;
|
const stackState = route.state;
|
||||||
const stackRoute =
|
const stackRoute =
|
||||||
stackState != null ? stackState.routes[stackState.index] : null;
|
stackState && stackState.index
|
||||||
const params: {collapsible: Collapsible} | null =
|
? stackState.routes[stackState.index]
|
||||||
stackRoute != null ? stackRoute.params : null;
|
: null;
|
||||||
|
const params: {collapsible: Collapsible} | null | undefined = stackRoute
|
||||||
|
? (stackRoute.params as {collapsible: Collapsible})
|
||||||
|
: null;
|
||||||
const collapsible = params != null ? params.collapsible : null;
|
const collapsible = params != null ? params.collapsible : null;
|
||||||
if (collapsible != null) {
|
if (collapsible != null) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {createStackNavigator, TransitionPresets} from '@react-navigation/stack';
|
import {createStackNavigator, TransitionPresets} from '@react-navigation/stack';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
|
|
@ -40,18 +38,63 @@ import ClubListScreen from '../screens/Amicale/Clubs/ClubListScreen';
|
||||||
import ClubAboutScreen from '../screens/Amicale/Clubs/ClubAboutScreen';
|
import ClubAboutScreen from '../screens/Amicale/Clubs/ClubAboutScreen';
|
||||||
import ClubDisplayScreen from '../screens/Amicale/Clubs/ClubDisplayScreen';
|
import ClubDisplayScreen from '../screens/Amicale/Clubs/ClubDisplayScreen';
|
||||||
import {
|
import {
|
||||||
createScreenCollapsibleStack,
|
CreateScreenCollapsibleStack,
|
||||||
getWebsiteStack,
|
getWebsiteStack,
|
||||||
} from '../utils/CollapsibleUtils';
|
} from '../utils/CollapsibleUtils';
|
||||||
import BugReportScreen from '../screens/Other/FeedbackScreen';
|
import BugReportScreen from '../screens/Other/FeedbackScreen';
|
||||||
import WebsiteScreen from '../screens/Services/WebsiteScreen';
|
import WebsiteScreen from '../screens/Services/WebsiteScreen';
|
||||||
import EquipmentScreen from '../screens/Amicale/Equipment/EquipmentListScreen';
|
import EquipmentScreen, {
|
||||||
|
DeviceType,
|
||||||
|
} from '../screens/Amicale/Equipment/EquipmentListScreen';
|
||||||
import EquipmentLendScreen from '../screens/Amicale/Equipment/EquipmentRentScreen';
|
import EquipmentLendScreen from '../screens/Amicale/Equipment/EquipmentRentScreen';
|
||||||
import EquipmentConfirmScreen from '../screens/Amicale/Equipment/EquipmentConfirmScreen';
|
import EquipmentConfirmScreen from '../screens/Amicale/Equipment/EquipmentConfirmScreen';
|
||||||
import DashboardEditScreen from '../screens/Other/Settings/DashboardEditScreen';
|
import DashboardEditScreen from '../screens/Other/Settings/DashboardEditScreen';
|
||||||
import GameStartScreen from '../screens/Game/screens/GameStartScreen';
|
import GameStartScreen from '../screens/Game/screens/GameStartScreen';
|
||||||
import ImageGalleryScreen from '../screens/Media/ImageGalleryScreen';
|
import ImageGalleryScreen from '../screens/Media/ImageGalleryScreen';
|
||||||
|
|
||||||
|
export enum MainRoutes {
|
||||||
|
Main = 'main',
|
||||||
|
Gallery = 'gallery',
|
||||||
|
Settings = 'settings',
|
||||||
|
DashboardEdit = 'dashboard-edit',
|
||||||
|
About = 'about',
|
||||||
|
Dependencies = 'dependencies',
|
||||||
|
Debug = 'debug',
|
||||||
|
GameStart = 'game-start',
|
||||||
|
GameMain = 'game-main',
|
||||||
|
Login = 'login',
|
||||||
|
SelfMenu = 'self-menu',
|
||||||
|
Proximo = 'proximo',
|
||||||
|
ProximoList = 'proximo-list',
|
||||||
|
ProximoAbout = 'proximo-about',
|
||||||
|
Profile = 'profile',
|
||||||
|
ClubList = 'club-list',
|
||||||
|
ClubInformation = 'club-information',
|
||||||
|
ClubAbout = 'club-about',
|
||||||
|
EquipmentList = 'equipment-list',
|
||||||
|
EquipmentRent = 'equipment-rent',
|
||||||
|
EquipmentConfirm = 'equipment-confirm',
|
||||||
|
Vote = 'vote',
|
||||||
|
Feedback = 'feedback',
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefaultParams = {[key in MainRoutes]: object | undefined};
|
||||||
|
|
||||||
|
export interface FullParamsList extends DefaultParams {
|
||||||
|
login: {nextScreen: string};
|
||||||
|
'equipment-confirm': {
|
||||||
|
item?: DeviceType;
|
||||||
|
dates: [string, string];
|
||||||
|
};
|
||||||
|
'equipment-rent': {item?: DeviceType};
|
||||||
|
gallery: {images: Array<{url: string}>};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't know why but TS is complaining without this
|
||||||
|
// See: https://stackoverflow.com/questions/63652687/interface-does-not-satisfy-the-constraint-recordstring-object-undefined
|
||||||
|
export type MainStackParamsList = FullParamsList &
|
||||||
|
Record<string, object | undefined>;
|
||||||
|
|
||||||
const modalTransition =
|
const modalTransition =
|
||||||
Platform.OS === 'ios'
|
Platform.OS === 'ios'
|
||||||
? TransitionPresets.ModalPresentationIOS
|
? TransitionPresets.ModalPresentationIOS
|
||||||
|
|
@ -63,19 +106,17 @@ const defaultScreenOptions = {
|
||||||
...TransitionPresets.SlideFromRightIOS,
|
...TransitionPresets.SlideFromRightIOS,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MainStack = createStackNavigator();
|
const MainStack = createStackNavigator<MainStackParamsList>();
|
||||||
|
|
||||||
function MainStackComponent(props: {
|
function MainStackComponent(props: {createTabNavigator: () => JSX.Element}) {
|
||||||
createTabNavigator: () => React.Node,
|
|
||||||
}): React.Node {
|
|
||||||
const {createTabNavigator} = props;
|
const {createTabNavigator} = props;
|
||||||
return (
|
return (
|
||||||
<MainStack.Navigator
|
<MainStack.Navigator
|
||||||
initialRouteName="main"
|
initialRouteName={MainRoutes.Main}
|
||||||
headerMode="screen"
|
headerMode="screen"
|
||||||
screenOptions={defaultScreenOptions}>
|
screenOptions={defaultScreenOptions}>
|
||||||
<MainStack.Screen
|
<MainStack.Screen
|
||||||
name="main"
|
name={MainRoutes.Main}
|
||||||
component={createTabNavigator}
|
component={createTabNavigator}
|
||||||
options={{
|
options={{
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
|
|
@ -83,62 +124,62 @@ function MainStackComponent(props: {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<MainStack.Screen
|
<MainStack.Screen
|
||||||
name="gallery"
|
name={MainRoutes.Gallery}
|
||||||
component={ImageGalleryScreen}
|
component={ImageGalleryScreen}
|
||||||
options={{
|
options={{
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
...modalTransition,
|
...modalTransition,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'settings',
|
MainRoutes.Settings,
|
||||||
MainStack,
|
MainStack,
|
||||||
SettingsScreen,
|
SettingsScreen,
|
||||||
i18n.t('screens.settings.title'),
|
i18n.t('screens.settings.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'dashboard-edit',
|
MainRoutes.DashboardEdit,
|
||||||
MainStack,
|
MainStack,
|
||||||
DashboardEditScreen,
|
DashboardEditScreen,
|
||||||
i18n.t('screens.settings.dashboardEdit.title'),
|
i18n.t('screens.settings.dashboardEdit.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'about',
|
MainRoutes.About,
|
||||||
MainStack,
|
MainStack,
|
||||||
AboutScreen,
|
AboutScreen,
|
||||||
i18n.t('screens.about.title'),
|
i18n.t('screens.about.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'dependencies',
|
MainRoutes.Dependencies,
|
||||||
MainStack,
|
MainStack,
|
||||||
AboutDependenciesScreen,
|
AboutDependenciesScreen,
|
||||||
i18n.t('screens.about.libs'),
|
i18n.t('screens.about.libs'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'debug',
|
MainRoutes.Debug,
|
||||||
MainStack,
|
MainStack,
|
||||||
DebugScreen,
|
DebugScreen,
|
||||||
i18n.t('screens.about.debug'),
|
i18n.t('screens.about.debug'),
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'game-start',
|
MainRoutes.GameStart,
|
||||||
MainStack,
|
MainStack,
|
||||||
GameStartScreen,
|
GameStartScreen,
|
||||||
i18n.t('screens.game.title'),
|
i18n.t('screens.game.title'),
|
||||||
true,
|
true,
|
||||||
null,
|
undefined,
|
||||||
'transparent',
|
'transparent',
|
||||||
)}
|
)}
|
||||||
<MainStack.Screen
|
<MainStack.Screen
|
||||||
name="game-main"
|
name={MainRoutes.GameMain}
|
||||||
component={GameMainScreen}
|
component={GameMainScreen}
|
||||||
options={{
|
options={{
|
||||||
title: i18n.t('screens.game.title'),
|
title: i18n.t('screens.game.title'),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'login',
|
MainRoutes.Login,
|
||||||
MainStack,
|
MainStack,
|
||||||
LoginScreen,
|
LoginScreen,
|
||||||
i18n.t('screens.login.title'),
|
i18n.t('screens.login.title'),
|
||||||
|
|
@ -148,26 +189,26 @@ function MainStackComponent(props: {
|
||||||
)}
|
)}
|
||||||
{getWebsiteStack('website', MainStack, WebsiteScreen, '')}
|
{getWebsiteStack('website', MainStack, WebsiteScreen, '')}
|
||||||
|
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'self-menu',
|
MainRoutes.SelfMenu,
|
||||||
MainStack,
|
MainStack,
|
||||||
SelfMenuScreen,
|
SelfMenuScreen,
|
||||||
i18n.t('screens.menu.title'),
|
i18n.t('screens.menu.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'proximo',
|
MainRoutes.Proximo,
|
||||||
MainStack,
|
MainStack,
|
||||||
ProximoMainScreen,
|
ProximoMainScreen,
|
||||||
i18n.t('screens.proximo.title'),
|
i18n.t('screens.proximo.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'proximo-list',
|
MainRoutes.ProximoList,
|
||||||
MainStack,
|
MainStack,
|
||||||
ProximoListScreen,
|
ProximoListScreen,
|
||||||
i18n.t('screens.proximo.articleList'),
|
i18n.t('screens.proximo.articleList'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'proximo-about',
|
MainRoutes.ProximoAbout,
|
||||||
MainStack,
|
MainStack,
|
||||||
ProximoAboutScreen,
|
ProximoAboutScreen,
|
||||||
i18n.t('screens.proximo.title'),
|
i18n.t('screens.proximo.title'),
|
||||||
|
|
@ -175,60 +216,60 @@ function MainStackComponent(props: {
|
||||||
{...modalTransition},
|
{...modalTransition},
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'profile',
|
MainRoutes.Profile,
|
||||||
MainStack,
|
MainStack,
|
||||||
ProfileScreen,
|
ProfileScreen,
|
||||||
i18n.t('screens.profile.title'),
|
i18n.t('screens.profile.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'club-list',
|
MainRoutes.ClubList,
|
||||||
MainStack,
|
MainStack,
|
||||||
ClubListScreen,
|
ClubListScreen,
|
||||||
i18n.t('screens.clubs.title'),
|
i18n.t('screens.clubs.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'club-information',
|
MainRoutes.ClubInformation,
|
||||||
MainStack,
|
MainStack,
|
||||||
ClubDisplayScreen,
|
ClubDisplayScreen,
|
||||||
i18n.t('screens.clubs.details'),
|
i18n.t('screens.clubs.details'),
|
||||||
true,
|
true,
|
||||||
{...modalTransition},
|
{...modalTransition},
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'club-about',
|
MainRoutes.ClubAbout,
|
||||||
MainStack,
|
MainStack,
|
||||||
ClubAboutScreen,
|
ClubAboutScreen,
|
||||||
i18n.t('screens.clubs.title'),
|
i18n.t('screens.clubs.title'),
|
||||||
true,
|
true,
|
||||||
{...modalTransition},
|
{...modalTransition},
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'equipment-list',
|
MainRoutes.EquipmentList,
|
||||||
MainStack,
|
MainStack,
|
||||||
EquipmentScreen,
|
EquipmentScreen,
|
||||||
i18n.t('screens.equipment.title'),
|
i18n.t('screens.equipment.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'equipment-rent',
|
MainRoutes.EquipmentRent,
|
||||||
MainStack,
|
MainStack,
|
||||||
EquipmentLendScreen,
|
EquipmentLendScreen,
|
||||||
i18n.t('screens.equipment.book'),
|
i18n.t('screens.equipment.book'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'equipment-confirm',
|
MainRoutes.EquipmentConfirm,
|
||||||
MainStack,
|
MainStack,
|
||||||
EquipmentConfirmScreen,
|
EquipmentConfirmScreen,
|
||||||
i18n.t('screens.equipment.confirm'),
|
i18n.t('screens.equipment.confirm'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'vote',
|
MainRoutes.Vote,
|
||||||
MainStack,
|
MainStack,
|
||||||
VoteScreen,
|
VoteScreen,
|
||||||
i18n.t('screens.vote.title'),
|
i18n.t('screens.vote.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'feedback',
|
MainRoutes.Feedback,
|
||||||
MainStack,
|
MainStack,
|
||||||
BugReportScreen,
|
BugReportScreen,
|
||||||
i18n.t('screens.feedback.title'),
|
i18n.t('screens.feedback.title'),
|
||||||
|
|
@ -238,25 +279,10 @@ function MainStackComponent(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
defaultHomeRoute: string | null,
|
defaultHomeRoute: string | null;
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
defaultHomeData: {[key: string]: string};
|
||||||
defaultHomeData: {[key: string]: string},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class MainNavigator extends React.Component<PropsType> {
|
export default function MainNavigator(props: PropsType) {
|
||||||
createTabNavigator: () => React.Node;
|
return <MainStackComponent createTabNavigator={() => TabNavigator(props)} />;
|
||||||
|
|
||||||
constructor(props: PropsType) {
|
|
||||||
super(props);
|
|
||||||
this.createTabNavigator = (): React.Node => (
|
|
||||||
<TabNavigator
|
|
||||||
defaultHomeRoute={props.defaultHomeRoute}
|
|
||||||
defaultHomeData={props.defaultHomeData}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): React.Node {
|
|
||||||
return <MainStackComponent createTabNavigator={this.createTabNavigator} />;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {createStackNavigator, TransitionPresets} from '@react-navigation/stack';
|
import {createStackNavigator, TransitionPresets} from '@react-navigation/stack';
|
||||||
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
|
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
|
||||||
|
|
@ -44,7 +42,7 @@ import WebsitesHomeScreen from '../screens/Services/ServicesScreen';
|
||||||
import ServicesSectionScreen from '../screens/Services/ServicesSectionScreen';
|
import ServicesSectionScreen from '../screens/Services/ServicesSectionScreen';
|
||||||
import AmicaleContactScreen from '../screens/Amicale/AmicaleContactScreen';
|
import AmicaleContactScreen from '../screens/Amicale/AmicaleContactScreen';
|
||||||
import {
|
import {
|
||||||
createScreenCollapsibleStack,
|
CreateScreenCollapsibleStack,
|
||||||
getWebsiteStack,
|
getWebsiteStack,
|
||||||
} from '../utils/CollapsibleUtils';
|
} from '../utils/CollapsibleUtils';
|
||||||
import Mascot, {MASCOT_STYLE} from '../components/Mascot/Mascot';
|
import Mascot, {MASCOT_STYLE} from '../components/Mascot/Mascot';
|
||||||
|
|
@ -62,25 +60,25 @@ const defaultScreenOptions = {
|
||||||
|
|
||||||
const ServicesStack = createStackNavigator();
|
const ServicesStack = createStackNavigator();
|
||||||
|
|
||||||
function ServicesStackComponent(): React.Node {
|
function ServicesStackComponent() {
|
||||||
return (
|
return (
|
||||||
<ServicesStack.Navigator
|
<ServicesStack.Navigator
|
||||||
initialRouteName="index"
|
initialRouteName="index"
|
||||||
headerMode="screen"
|
headerMode="screen"
|
||||||
screenOptions={defaultScreenOptions}>
|
screenOptions={defaultScreenOptions}>
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'index',
|
'index',
|
||||||
ServicesStack,
|
ServicesStack,
|
||||||
WebsitesHomeScreen,
|
WebsitesHomeScreen,
|
||||||
i18n.t('screens.services.title'),
|
i18n.t('screens.services.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'services-section',
|
'services-section',
|
||||||
ServicesStack,
|
ServicesStack,
|
||||||
ServicesSectionScreen,
|
ServicesSectionScreen,
|
||||||
'SECTION',
|
'SECTION',
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'amicale-contact',
|
'amicale-contact',
|
||||||
ServicesStack,
|
ServicesStack,
|
||||||
AmicaleContactScreen,
|
AmicaleContactScreen,
|
||||||
|
|
@ -92,19 +90,19 @@ function ServicesStackComponent(): React.Node {
|
||||||
|
|
||||||
const ProxiwashStack = createStackNavigator();
|
const ProxiwashStack = createStackNavigator();
|
||||||
|
|
||||||
function ProxiwashStackComponent(): React.Node {
|
function ProxiwashStackComponent() {
|
||||||
return (
|
return (
|
||||||
<ProxiwashStack.Navigator
|
<ProxiwashStack.Navigator
|
||||||
initialRouteName="index"
|
initialRouteName="index"
|
||||||
headerMode="screen"
|
headerMode="screen"
|
||||||
screenOptions={defaultScreenOptions}>
|
screenOptions={defaultScreenOptions}>
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'index',
|
'index',
|
||||||
ProxiwashStack,
|
ProxiwashStack,
|
||||||
ProxiwashScreen,
|
ProxiwashScreen,
|
||||||
i18n.t('screens.proxiwash.title'),
|
i18n.t('screens.proxiwash.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'proxiwash-about',
|
'proxiwash-about',
|
||||||
ProxiwashStack,
|
ProxiwashStack,
|
||||||
ProxiwashAboutScreen,
|
ProxiwashAboutScreen,
|
||||||
|
|
@ -116,7 +114,7 @@ function ProxiwashStackComponent(): React.Node {
|
||||||
|
|
||||||
const PlanningStack = createStackNavigator();
|
const PlanningStack = createStackNavigator();
|
||||||
|
|
||||||
function PlanningStackComponent(): React.Node {
|
function PlanningStackComponent() {
|
||||||
return (
|
return (
|
||||||
<PlanningStack.Navigator
|
<PlanningStack.Navigator
|
||||||
initialRouteName="index"
|
initialRouteName="index"
|
||||||
|
|
@ -127,7 +125,7 @@ function PlanningStackComponent(): React.Node {
|
||||||
component={PlanningScreen}
|
component={PlanningScreen}
|
||||||
options={{title: i18n.t('screens.planning.title')}}
|
options={{title: i18n.t('screens.planning.title')}}
|
||||||
/>
|
/>
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'planning-information',
|
'planning-information',
|
||||||
PlanningStack,
|
PlanningStack,
|
||||||
PlanningDisplayScreen,
|
PlanningDisplayScreen,
|
||||||
|
|
@ -142,10 +140,11 @@ const HomeStack = createStackNavigator();
|
||||||
function HomeStackComponent(
|
function HomeStackComponent(
|
||||||
initialRoute: string | null,
|
initialRoute: string | null,
|
||||||
defaultData: {[key: string]: string},
|
defaultData: {[key: string]: string},
|
||||||
): React.Node {
|
) {
|
||||||
let params;
|
let params;
|
||||||
if (initialRoute != null)
|
if (initialRoute != null) {
|
||||||
params = {data: defaultData, nextScreen: initialRoute, shouldOpen: true};
|
params = {data: defaultData, nextScreen: initialRoute, shouldOpen: true};
|
||||||
|
}
|
||||||
const {colors} = useTheme();
|
const {colors} = useTheme();
|
||||||
return (
|
return (
|
||||||
<HomeStack.Navigator
|
<HomeStack.Navigator
|
||||||
|
|
@ -161,7 +160,7 @@ function HomeStackComponent(
|
||||||
headerStyle: {
|
headerStyle: {
|
||||||
backgroundColor: colors.surface,
|
backgroundColor: colors.surface,
|
||||||
},
|
},
|
||||||
headerTitle: (): React.Node => (
|
headerTitle: () => (
|
||||||
<View style={{flexDirection: 'row'}}>
|
<View style={{flexDirection: 'row'}}>
|
||||||
<Mascot
|
<Mascot
|
||||||
style={{
|
style={{
|
||||||
|
|
@ -203,19 +202,19 @@ function HomeStackComponent(
|
||||||
options={{title: i18n.t('screens.scanner.title')}}
|
options={{title: i18n.t('screens.scanner.title')}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'club-information',
|
'club-information',
|
||||||
HomeStack,
|
HomeStack,
|
||||||
ClubDisplayScreen,
|
ClubDisplayScreen,
|
||||||
i18n.t('screens.clubs.details'),
|
i18n.t('screens.clubs.details'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'feed-information',
|
'feed-information',
|
||||||
HomeStack,
|
HomeStack,
|
||||||
FeedItemScreen,
|
FeedItemScreen,
|
||||||
i18n.t('screens.home.feed'),
|
i18n.t('screens.home.feed'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'planning-information',
|
'planning-information',
|
||||||
HomeStack,
|
HomeStack,
|
||||||
PlanningDisplayScreen,
|
PlanningDisplayScreen,
|
||||||
|
|
@ -227,7 +226,7 @@ function HomeStackComponent(
|
||||||
|
|
||||||
const PlanexStack = createStackNavigator();
|
const PlanexStack = createStackNavigator();
|
||||||
|
|
||||||
function PlanexStackComponent(): React.Node {
|
function PlanexStackComponent() {
|
||||||
return (
|
return (
|
||||||
<PlanexStack.Navigator
|
<PlanexStack.Navigator
|
||||||
initialRouteName="index"
|
initialRouteName="index"
|
||||||
|
|
@ -239,7 +238,7 @@ function PlanexStackComponent(): React.Node {
|
||||||
PlanexScreen,
|
PlanexScreen,
|
||||||
i18n.t('screens.planex.title'),
|
i18n.t('screens.planex.title'),
|
||||||
)}
|
)}
|
||||||
{createScreenCollapsibleStack(
|
{CreateScreenCollapsibleStack(
|
||||||
'group-select',
|
'group-select',
|
||||||
PlanexStack,
|
PlanexStack,
|
||||||
GroupSelectionScreen,
|
GroupSelectionScreen,
|
||||||
|
|
@ -252,60 +251,49 @@ function PlanexStackComponent(): React.Node {
|
||||||
const Tab = createBottomTabNavigator();
|
const Tab = createBottomTabNavigator();
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
defaultHomeRoute: string | null,
|
defaultHomeRoute: string | null;
|
||||||
defaultHomeData: {[key: string]: string},
|
defaultHomeData: {[key: string]: string};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class TabNavigator extends React.Component<PropsType> {
|
export default function TabNavigator(props: PropsType) {
|
||||||
createHomeStackComponent: () => React.Node;
|
let defaultRoute = 'home';
|
||||||
|
if (!props.defaultHomeRoute) {
|
||||||
defaultRoute: string;
|
defaultRoute = AsyncStorageManager.getString(
|
||||||
|
AsyncStorageManager.PREFERENCES.defaultStartScreen.key,
|
||||||
constructor(props: PropsType) {
|
).toLowerCase();
|
||||||
super(props);
|
|
||||||
if (props.defaultHomeRoute != null) this.defaultRoute = 'home';
|
|
||||||
else
|
|
||||||
this.defaultRoute = AsyncStorageManager.getString(
|
|
||||||
AsyncStorageManager.PREFERENCES.defaultStartScreen.key,
|
|
||||||
).toLowerCase();
|
|
||||||
this.createHomeStackComponent = (): React.Node =>
|
|
||||||
HomeStackComponent(props.defaultHomeRoute, props.defaultHomeData);
|
|
||||||
}
|
}
|
||||||
|
const createHomeStackComponent = () =>
|
||||||
|
HomeStackComponent(props.defaultHomeRoute, props.defaultHomeData);
|
||||||
|
|
||||||
render(): React.Node {
|
return (
|
||||||
return (
|
<Tab.Navigator
|
||||||
<Tab.Navigator
|
initialRouteName={defaultRoute}
|
||||||
initialRouteName={this.defaultRoute}
|
tabBar={(tabProps) => <CustomTabBar {...tabProps} />}>
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
<Tab.Screen
|
||||||
tabBar={(props: {...}): React.Node => <CustomTabBar {...props} />}>
|
name="services"
|
||||||
<Tab.Screen
|
component={ServicesStackComponent}
|
||||||
name="services"
|
options={{title: i18n.t('screens.services.title')}}
|
||||||
option
|
/>
|
||||||
component={ServicesStackComponent}
|
<Tab.Screen
|
||||||
options={{title: i18n.t('screens.services.title')}}
|
name="proxiwash"
|
||||||
/>
|
component={ProxiwashStackComponent}
|
||||||
<Tab.Screen
|
options={{title: i18n.t('screens.proxiwash.title')}}
|
||||||
name="proxiwash"
|
/>
|
||||||
component={ProxiwashStackComponent}
|
<Tab.Screen
|
||||||
options={{title: i18n.t('screens.proxiwash.title')}}
|
name="home"
|
||||||
/>
|
component={createHomeStackComponent}
|
||||||
<Tab.Screen
|
options={{title: i18n.t('screens.home.title')}}
|
||||||
name="home"
|
/>
|
||||||
component={this.createHomeStackComponent}
|
<Tab.Screen
|
||||||
options={{title: i18n.t('screens.home.title')}}
|
name="planning"
|
||||||
/>
|
component={PlanningStackComponent}
|
||||||
<Tab.Screen
|
options={{title: i18n.t('screens.planning.title')}}
|
||||||
name="planning"
|
/>
|
||||||
component={PlanningStackComponent}
|
<Tab.Screen
|
||||||
options={{title: i18n.t('screens.planning.title')}}
|
name="planex"
|
||||||
/>
|
component={PlanexStackComponent}
|
||||||
|
options={{title: i18n.t('screens.planex.title')}}
|
||||||
<Tab.Screen
|
/>
|
||||||
name="planex"
|
</Tab.Navigator>
|
||||||
component={PlanexStackComponent}
|
);
|
||||||
options={{title: i18n.t('screens.planex.title')}}
|
|
||||||
/>
|
|
||||||
</Tab.Navigator>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -50,11 +50,11 @@ const LIST_ITEM_HEIGHT = 64;
|
||||||
/**
|
/**
|
||||||
* Class defining a screen showing the list of libraries used by the app, taken from package.json
|
* Class defining a screen showing the list of libraries used by the app, taken from package.json
|
||||||
*/
|
*/
|
||||||
export default class AboutDependenciesScreen extends React.Component<null> {
|
export default class AboutDependenciesScreen extends React.Component<{}> {
|
||||||
data: Array<ListItemType>;
|
data: Array<ListItemType>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(null);
|
super({});
|
||||||
this.data = generateListFromObject(packageJson.dependencies);
|
this.data = generateListFromObject(packageJson.dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,12 @@ type DatasetItemType = {
|
||||||
/**
|
/**
|
||||||
* Class defining a planning event information page.
|
* Class defining a planning event information page.
|
||||||
*/
|
*/
|
||||||
class AmicaleContactScreen extends React.Component<null> {
|
class AmicaleContactScreen extends React.Component<{}> {
|
||||||
// Dataset containing information about contacts
|
// Dataset containing information about contacts
|
||||||
CONTACT_DATASET: Array<DatasetItemType>;
|
CONTACT_DATASET: Array<DatasetItemType>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(null);
|
super({});
|
||||||
this.CONTACT_DATASET = [
|
this.CONTACT_DATASET = [
|
||||||
{
|
{
|
||||||
name: i18n.t('screens.amicaleAbout.roles.interSchools'),
|
name: i18n.t('screens.amicaleAbout.roles.interSchools'),
|
||||||
|
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
|
|
||||||
*
|
|
||||||
* This file is part of Campus INSAT.
|
|
||||||
*
|
|
||||||
* Campus INSAT is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Campus INSAT is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
|
||||||
import {Avatar, Button, Card, Paragraph, withTheme} from 'react-native-paper';
|
|
||||||
import i18n from 'i18n-js';
|
|
||||||
import {Linking, View} from 'react-native';
|
|
||||||
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
|
|
||||||
import type {CardTitleIconPropsType} from '../../constants/PaperStyles';
|
|
||||||
|
|
||||||
const links = {
|
|
||||||
bugsGit: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/',
|
|
||||||
trello: 'https://trello.com/b/RMej49Uq/application-campus-insa',
|
|
||||||
facebook: 'https://www.facebook.com/campus.insat',
|
|
||||||
feedbackMail: `mailto:app@amicale-insat.fr?subject=[FEEDBACK] Application CAMPUS
|
|
||||||
&body=Coucou Arnaud j'ai du feedback\n\n\n\nBien cordialement.`,
|
|
||||||
feedbackDiscord: 'https://discord.gg/W8MeTec',
|
|
||||||
};
|
|
||||||
|
|
||||||
class FeedbackScreen extends React.Component<null> {
|
|
||||||
/**
|
|
||||||
* Gets link buttons
|
|
||||||
*
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
static getButtons(isFeedback: boolean): React.Node {
|
|
||||||
return (
|
|
||||||
<Card.Actions
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
}}>
|
|
||||||
{isFeedback ? (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
flexDirection: 'row',
|
|
||||||
width: '100%',
|
|
||||||
}}>
|
|
||||||
<Button
|
|
||||||
icon="email"
|
|
||||||
mode="contained"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.feedbackMail);
|
|
||||||
}}>
|
|
||||||
MAIL
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
icon="facebook"
|
|
||||||
mode="contained"
|
|
||||||
color="#2e88fe"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.facebook);
|
|
||||||
}}>
|
|
||||||
Facebook
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
icon="discord"
|
|
||||||
mode="contained"
|
|
||||||
color="#7289da"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.feedbackDiscord);
|
|
||||||
}}>
|
|
||||||
Discord
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
flexDirection: 'row',
|
|
||||||
width: '100%',
|
|
||||||
}}>
|
|
||||||
<Button
|
|
||||||
icon="git"
|
|
||||||
mode="contained"
|
|
||||||
color="#609927"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.bugsGit);
|
|
||||||
}}>
|
|
||||||
GITETUD
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
icon="calendar"
|
|
||||||
mode="contained"
|
|
||||||
color="#026AA7"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.trello);
|
|
||||||
}}>
|
|
||||||
TRELLO
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</Card.Actions>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): React.Node {
|
|
||||||
return (
|
|
||||||
<CollapsibleScrollView style={{padding: 5}}>
|
|
||||||
<Card>
|
|
||||||
<Card.Title
|
|
||||||
title={i18n.t('screens.feedback.feedback')}
|
|
||||||
subtitle={i18n.t('screens.feedback.feedbackSubtitle')}
|
|
||||||
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
|
||||||
<Avatar.Icon size={iconProps.size} icon="comment" />
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Card.Content>
|
|
||||||
<Paragraph>
|
|
||||||
{i18n.t('screens.feedback.feedbackDescription')}
|
|
||||||
</Paragraph>
|
|
||||||
</Card.Content>
|
|
||||||
{FeedbackScreen.getButtons(true)}
|
|
||||||
<Card.Title
|
|
||||||
title={i18n.t('screens.feedback.contribute')}
|
|
||||||
subtitle={i18n.t('screens.feedback.contributeSubtitle')}
|
|
||||||
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
|
||||||
<Avatar.Icon size={iconProps.size} icon="handshake" />
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Card.Content>
|
|
||||||
<Paragraph>
|
|
||||||
{i18n.t('screens.feedback.contributeDescription')}
|
|
||||||
</Paragraph>
|
|
||||||
</Card.Content>
|
|
||||||
{FeedbackScreen.getButtons(false)}
|
|
||||||
</Card>
|
|
||||||
</CollapsibleScrollView>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withTheme(FeedbackScreen);
|
|
||||||
169
src/screens/Other/FeedbackScreen.tsx
Normal file
169
src/screens/Other/FeedbackScreen.tsx
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
|
||||||
|
*
|
||||||
|
* This file is part of Campus INSAT.
|
||||||
|
*
|
||||||
|
* Campus INSAT is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Campus INSAT is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import {Avatar, Button, Card, Paragraph, withTheme} from 'react-native-paper';
|
||||||
|
import i18n from 'i18n-js';
|
||||||
|
import {Linking, View} from 'react-native';
|
||||||
|
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
|
||||||
|
|
||||||
|
const links = {
|
||||||
|
bugsGit: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/',
|
||||||
|
trello: 'https://trello.com/b/RMej49Uq/application-campus-insa',
|
||||||
|
facebook: 'https://www.facebook.com/campus.insat',
|
||||||
|
feedbackMail: `mailto:app@amicale-insat.fr?subject=[FEEDBACK] Application CAMPUS
|
||||||
|
&body=Coucou Arnaud j'ai du feedback\n\n\n\nBien cordialement.`,
|
||||||
|
feedbackDiscord: 'https://discord.gg/W8MeTec',
|
||||||
|
};
|
||||||
|
|
||||||
|
function getButtons(isFeedback: boolean) {
|
||||||
|
return (
|
||||||
|
<Card.Actions
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
}}>
|
||||||
|
{isFeedback ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
flexDirection: 'row',
|
||||||
|
width: '100%',
|
||||||
|
}}>
|
||||||
|
<Button
|
||||||
|
icon="email"
|
||||||
|
mode="contained"
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: 5,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Linking.openURL(links.feedbackMail);
|
||||||
|
}}>
|
||||||
|
MAIL
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
icon="facebook"
|
||||||
|
mode="contained"
|
||||||
|
color="#2e88fe"
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: 5,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Linking.openURL(links.facebook);
|
||||||
|
}}>
|
||||||
|
Facebook
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
icon="discord"
|
||||||
|
mode="contained"
|
||||||
|
color="#7289da"
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: 5,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Linking.openURL(links.feedbackDiscord);
|
||||||
|
}}>
|
||||||
|
Discord
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
flexDirection: 'row',
|
||||||
|
width: '100%',
|
||||||
|
}}>
|
||||||
|
<Button
|
||||||
|
icon="git"
|
||||||
|
mode="contained"
|
||||||
|
color="#609927"
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: 5,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Linking.openURL(links.bugsGit);
|
||||||
|
}}>
|
||||||
|
GITETUD
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
icon="calendar"
|
||||||
|
mode="contained"
|
||||||
|
color="#026AA7"
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: 5,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Linking.openURL(links.trello);
|
||||||
|
}}>
|
||||||
|
TRELLO
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</Card.Actions>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FeedbackScreen() {
|
||||||
|
return (
|
||||||
|
<CollapsibleScrollView style={{padding: 5}}>
|
||||||
|
<Card>
|
||||||
|
<Card.Title
|
||||||
|
title={i18n.t('screens.feedback.feedback')}
|
||||||
|
subtitle={i18n.t('screens.feedback.feedbackSubtitle')}
|
||||||
|
left={(iconProps) => (
|
||||||
|
<Avatar.Icon size={iconProps.size} icon="comment" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Card.Content>
|
||||||
|
<Paragraph>
|
||||||
|
{i18n.t('screens.feedback.feedbackDescription')}
|
||||||
|
</Paragraph>
|
||||||
|
</Card.Content>
|
||||||
|
{getButtons(true)}
|
||||||
|
<Card.Title
|
||||||
|
title={i18n.t('screens.feedback.contribute')}
|
||||||
|
subtitle={i18n.t('screens.feedback.contributeSubtitle')}
|
||||||
|
left={(iconProps) => (
|
||||||
|
<Avatar.Icon size={iconProps.size} icon="handshake" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Card.Content>
|
||||||
|
<Paragraph>
|
||||||
|
{i18n.t('screens.feedback.contributeDescription')}
|
||||||
|
</Paragraph>
|
||||||
|
</Card.Content>
|
||||||
|
{getButtons(false)}
|
||||||
|
</Card>
|
||||||
|
</CollapsibleScrollView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTheme(FeedbackScreen);
|
||||||
|
|
@ -17,11 +17,9 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
import {StackNavigationProp} from '@react-navigation/stack';
|
||||||
import {Button, Card, Paragraph, withTheme} from 'react-native-paper';
|
import {Button, Card, Paragraph} from 'react-native-paper';
|
||||||
import {FlatList} from 'react-native';
|
import {FlatList} from 'react-native';
|
||||||
import {View} from 'react-native-animatable';
|
import {View} from 'react-native-animatable';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
|
|
@ -30,20 +28,19 @@ import type {
|
||||||
ServiceItemType,
|
ServiceItemType,
|
||||||
} from '../../../managers/ServicesManager';
|
} from '../../../managers/ServicesManager';
|
||||||
import DashboardManager from '../../../managers/DashboardManager';
|
import DashboardManager from '../../../managers/DashboardManager';
|
||||||
import DashboardItem from '../../../components/Home/EventDashboardItem';
|
|
||||||
import DashboardEditAccordion from '../../../components/Lists/DashboardEdit/DashboardEditAccordion';
|
import DashboardEditAccordion from '../../../components/Lists/DashboardEdit/DashboardEditAccordion';
|
||||||
import DashboardEditPreviewItem from '../../../components/Lists/DashboardEdit/DashboardEditPreviewItem';
|
import DashboardEditPreviewItem from '../../../components/Lists/DashboardEdit/DashboardEditPreviewItem';
|
||||||
import AsyncStorageManager from '../../../managers/AsyncStorageManager';
|
import AsyncStorageManager from '../../../managers/AsyncStorageManager';
|
||||||
import CollapsibleFlatList from '../../../components/Collapsible/CollapsibleFlatList';
|
import CollapsibleFlatList from '../../../components/Collapsible/CollapsibleFlatList';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
navigation: StackNavigationProp,
|
navigation: StackNavigationProp<any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
currentDashboard: Array<ServiceItemType | null>,
|
currentDashboard: Array<ServiceItemType | null>;
|
||||||
currentDashboardIdList: Array<string>,
|
currentDashboardIdList: Array<string>;
|
||||||
activeItem: number,
|
activeItem: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -75,13 +72,13 @@ class DashboardEditScreen extends React.Component<PropsType, StateType> {
|
||||||
item,
|
item,
|
||||||
index,
|
index,
|
||||||
}: {
|
}: {
|
||||||
item: DashboardItem,
|
item: ServiceItemType | null;
|
||||||
index: number,
|
index: number;
|
||||||
}): React.Node => {
|
}) => {
|
||||||
const {activeItem} = this.state;
|
const {activeItem} = this.state;
|
||||||
return (
|
return (
|
||||||
<DashboardEditPreviewItem
|
<DashboardEditPreviewItem
|
||||||
image={item.image}
|
image={item?.image}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
this.setState({activeItem: index});
|
this.setState({activeItem: index});
|
||||||
}}
|
}}
|
||||||
|
|
@ -90,7 +87,7 @@ class DashboardEditScreen extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
getDashboard(content: Array<DashboardItem>): React.Node {
|
getDashboard(content: Array<ServiceItemType | null>) {
|
||||||
return (
|
return (
|
||||||
<FlatList
|
<FlatList
|
||||||
data={content}
|
data={content}
|
||||||
|
|
@ -106,7 +103,7 @@ class DashboardEditScreen extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRenderItem = ({item}: {item: ServiceCategoryType}): React.Node => {
|
getRenderItem = ({item}: {item: ServiceCategoryType}) => {
|
||||||
const {currentDashboardIdList} = this.state;
|
const {currentDashboardIdList} = this.state;
|
||||||
return (
|
return (
|
||||||
<DashboardEditAccordion
|
<DashboardEditAccordion
|
||||||
|
|
@ -117,7 +114,7 @@ class DashboardEditScreen extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
getListHeader(): React.Node {
|
getListHeader() {
|
||||||
const {currentDashboard} = this.state;
|
const {currentDashboard} = this.state;
|
||||||
return (
|
return (
|
||||||
<Card style={{margin: 5}}>
|
<Card style={{margin: 5}}>
|
||||||
|
|
@ -170,7 +167,7 @@ class DashboardEditScreen extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
return (
|
return (
|
||||||
<CollapsibleFlatList
|
<CollapsibleFlatList
|
||||||
data={this.content}
|
data={this.content}
|
||||||
|
|
@ -182,4 +179,4 @@ class DashboardEditScreen extends React.Component<PropsType, StateType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withTheme(DashboardEditScreen);
|
export default DashboardEditScreen;
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {View} from 'react-native';
|
import {View} from 'react-native';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
|
|
@ -32,24 +30,22 @@ import {
|
||||||
} from 'react-native-paper';
|
} from 'react-native-paper';
|
||||||
import {Appearance} from 'react-native-appearance';
|
import {Appearance} from 'react-native-appearance';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
import {StackNavigationProp} from '@react-navigation/stack';
|
||||||
import type {CustomThemeType} from '../../../managers/ThemeManager';
|
|
||||||
import ThemeManager from '../../../managers/ThemeManager';
|
import ThemeManager from '../../../managers/ThemeManager';
|
||||||
import AsyncStorageManager from '../../../managers/AsyncStorageManager';
|
import AsyncStorageManager from '../../../managers/AsyncStorageManager';
|
||||||
import CustomSlider from '../../../components/Overrides/CustomSlider';
|
import CustomSlider from '../../../components/Overrides/CustomSlider';
|
||||||
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
|
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
|
||||||
import type {ListIconPropsType} from '../../../constants/PaperStyles';
|
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
navigation: StackNavigationProp,
|
navigation: StackNavigationProp<any>;
|
||||||
theme: CustomThemeType,
|
theme: ReactNativePaper.Theme;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
nightMode: boolean,
|
nightMode: boolean;
|
||||||
nightModeFollowSystem: boolean,
|
nightModeFollowSystem: boolean;
|
||||||
startScreenPickerSelected: string,
|
startScreenPickerSelected: string;
|
||||||
selectedWash: string,
|
selectedWash: string;
|
||||||
isDebugUnlocked: boolean,
|
isDebugUnlocked: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,14 +57,15 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
/**
|
/**
|
||||||
* Loads user preferences into state
|
* Loads user preferences into state
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor(props: PropsType) {
|
||||||
super();
|
super(props);
|
||||||
const notifReminder = AsyncStorageManager.getString(
|
const notifReminder = AsyncStorageManager.getString(
|
||||||
AsyncStorageManager.PREFERENCES.proxiwashNotifications.key,
|
AsyncStorageManager.PREFERENCES.proxiwashNotifications.key,
|
||||||
);
|
);
|
||||||
this.savedNotificationReminder = parseInt(notifReminder, 10);
|
this.savedNotificationReminder = parseInt(notifReminder, 10);
|
||||||
if (Number.isNaN(this.savedNotificationReminder))
|
if (Number.isNaN(this.savedNotificationReminder)) {
|
||||||
this.savedNotificationReminder = 0;
|
this.savedNotificationReminder = 0;
|
||||||
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
nightMode: ThemeManager.getNightMode(),
|
nightMode: ThemeManager.getNightMode(),
|
||||||
|
|
@ -120,7 +117,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
*
|
*
|
||||||
* @returns {React.Node}
|
* @returns {React.Node}
|
||||||
*/
|
*/
|
||||||
getProxiwashNotifPicker(): React.Node {
|
getProxiwashNotifPicker() {
|
||||||
const {theme} = this.props;
|
const {theme} = this.props;
|
||||||
return (
|
return (
|
||||||
<CustomSlider
|
<CustomSlider
|
||||||
|
|
@ -141,7 +138,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
*
|
*
|
||||||
* @returns {React.Node}
|
* @returns {React.Node}
|
||||||
*/
|
*/
|
||||||
getProxiwashChangePicker(): React.Node {
|
getProxiwashChangePicker() {
|
||||||
const {selectedWash} = this.state;
|
const {selectedWash} = this.state;
|
||||||
return (
|
return (
|
||||||
<RadioButton.Group
|
<RadioButton.Group
|
||||||
|
|
@ -164,7 +161,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
*
|
*
|
||||||
* @returns {React.Node}
|
* @returns {React.Node}
|
||||||
*/
|
*/
|
||||||
getStartScreenPicker(): React.Node {
|
getStartScreenPicker() {
|
||||||
const {startScreenPickerSelected} = this.state;
|
const {startScreenPickerSelected} = this.state;
|
||||||
return (
|
return (
|
||||||
<ToggleButton.Row
|
<ToggleButton.Row
|
||||||
|
|
@ -220,17 +217,15 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
title: string,
|
title: string,
|
||||||
subtitle: string,
|
subtitle: string,
|
||||||
state: boolean,
|
state: boolean,
|
||||||
): React.Node {
|
) {
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<List.Item
|
||||||
title={title}
|
title={title}
|
||||||
description={subtitle}
|
description={subtitle}
|
||||||
left={(props: ListIconPropsType): React.Node => (
|
left={(props) => (
|
||||||
<List.Icon color={props.color} style={props.style} icon={icon} />
|
<List.Icon color={props.color} style={props.style} icon={icon} />
|
||||||
)}
|
)}
|
||||||
right={(): React.Node => (
|
right={() => <Switch value={state} onValueChange={onPressCallback} />}
|
||||||
<Switch value={state} onValueChange={onPressCallback} />
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -241,7 +236,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
title: string,
|
title: string,
|
||||||
subtitle: string,
|
subtitle: string,
|
||||||
onLongPress?: () => void,
|
onLongPress?: () => void,
|
||||||
): React.Node {
|
) {
|
||||||
const {navigation} = this.props;
|
const {navigation} = this.props;
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<List.Item
|
||||||
|
|
@ -250,10 +245,10 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
navigation.navigate(route);
|
navigation.navigate(route);
|
||||||
}}
|
}}
|
||||||
left={(props: ListIconPropsType): React.Node => (
|
left={(props) => (
|
||||||
<List.Icon color={props.color} style={props.style} icon={icon} />
|
<List.Icon color={props.color} style={props.style} icon={icon} />
|
||||||
)}
|
)}
|
||||||
right={(props: ListIconPropsType): React.Node => (
|
right={(props) => (
|
||||||
<List.Icon
|
<List.Icon
|
||||||
color={props.color}
|
color={props.color}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
|
|
@ -291,7 +286,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {nightModeFollowSystem, nightMode, isDebugUnlocked} = this.state;
|
const {nightModeFollowSystem, nightMode, isDebugUnlocked} = this.state;
|
||||||
return (
|
return (
|
||||||
<CollapsibleScrollView>
|
<CollapsibleScrollView>
|
||||||
|
|
@ -322,7 +317,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
<List.Item
|
<List.Item
|
||||||
title={i18n.t('screens.settings.startScreen')}
|
title={i18n.t('screens.settings.startScreen')}
|
||||||
description={i18n.t('screens.settings.startScreenSub')}
|
description={i18n.t('screens.settings.startScreenSub')}
|
||||||
left={(props: ListIconPropsType): React.Node => (
|
left={(props) => (
|
||||||
<List.Icon
|
<List.Icon
|
||||||
color={props.color}
|
color={props.color}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
|
|
@ -345,7 +340,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
<List.Item
|
<List.Item
|
||||||
title={i18n.t('screens.settings.proxiwashNotifReminder')}
|
title={i18n.t('screens.settings.proxiwashNotifReminder')}
|
||||||
description={i18n.t('screens.settings.proxiwashNotifReminderSub')}
|
description={i18n.t('screens.settings.proxiwashNotifReminderSub')}
|
||||||
left={(props: ListIconPropsType): React.Node => (
|
left={(props) => (
|
||||||
<List.Icon
|
<List.Icon
|
||||||
color={props.color}
|
color={props.color}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
|
|
@ -359,7 +354,7 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
|
||||||
<List.Item
|
<List.Item
|
||||||
title={i18n.t('screens.settings.proxiwashChangeWash')}
|
title={i18n.t('screens.settings.proxiwashChangeWash')}
|
||||||
description={i18n.t('screens.settings.proxiwashChangeWashSub')}
|
description={i18n.t('screens.settings.proxiwashChangeWashSub')}
|
||||||
left={(props: ListIconPropsType): React.Node => (
|
left={(props) => (
|
||||||
<List.Icon
|
<List.Icon
|
||||||
color={props.color}
|
color={props.color}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
|
|
@ -21,7 +21,7 @@ import * as React from 'react';
|
||||||
import {useTheme} from 'react-native-paper';
|
import {useTheme} from 'react-native-paper';
|
||||||
import {createCollapsibleStack} from 'react-navigation-collapsible';
|
import {createCollapsibleStack} from 'react-navigation-collapsible';
|
||||||
import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
|
import StackNavigator, {StackNavigationOptions} from '@react-navigation/stack';
|
||||||
import {StackNavigationState} from '@react-navigation/native';
|
import {StackNavigationState, TypedNavigator} from '@react-navigation/native';
|
||||||
import {StackNavigationEventMap} from '@react-navigation/stack/lib/typescript/src/types';
|
import {StackNavigationEventMap} from '@react-navigation/stack/lib/typescript/src/types';
|
||||||
|
|
||||||
type StackNavigatorType = import('@react-navigation/native').TypedNavigator<
|
type StackNavigatorType = import('@react-navigation/native').TypedNavigator<
|
||||||
|
|
@ -50,7 +50,7 @@ type StackNavigatorType = import('@react-navigation/native').TypedNavigator<
|
||||||
*/
|
*/
|
||||||
export function CreateScreenCollapsibleStack(
|
export function CreateScreenCollapsibleStack(
|
||||||
name: string,
|
name: string,
|
||||||
Stack: StackNavigatorType,
|
Stack: TypedNavigator<any, any, any, any, any>,
|
||||||
component: React.ComponentType<any>,
|
component: React.ComponentType<any>,
|
||||||
title: string,
|
title: string,
|
||||||
useNativeDriver: boolean = true,
|
useNativeDriver: boolean = true,
|
||||||
|
|
@ -91,7 +91,7 @@ export function CreateScreenCollapsibleStack(
|
||||||
*/
|
*/
|
||||||
export function getWebsiteStack(
|
export function getWebsiteStack(
|
||||||
name: string,
|
name: string,
|
||||||
Stack: StackNavigatorType,
|
Stack: TypedNavigator<any, any, any, any, any>,
|
||||||
component: React.ComponentType<any>,
|
component: React.ComponentType<any>,
|
||||||
title: string,
|
title: string,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue