forked from vergnet/application-amicale
Implemented collapsible header on major lists and webviews
This commit is contained in:
parent
5d08134511
commit
c67e2fa405
9 changed files with 373 additions and 163 deletions
|
@ -51,6 +51,7 @@
|
|||
"react-native-safe-area-context": "0.7.3",
|
||||
"react-native-screens": "~2.2.0",
|
||||
"react-native-webview": "8.1.1",
|
||||
"react-navigation-collapsible": "^5.4.0",
|
||||
"react-navigation-header-buttons": "^3.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import {ActivityIndicator, withTheme} from 'react-native-paper';
|
||||
import {View} from "react-native";
|
||||
|
||||
/**
|
||||
* Component used to display a header button
|
||||
|
@ -12,17 +12,19 @@ import {View} from "react-native";
|
|||
*/
|
||||
function BasicLoadingScreen(props) {
|
||||
const {colors} = props.theme;
|
||||
let position = undefined;
|
||||
if (props.isAbsolute !== undefined && props.isAbsolute)
|
||||
position = 'absolute';
|
||||
|
||||
return (
|
||||
<View style={{
|
||||
backgroundColor: colors.background,
|
||||
position: 'absolute',
|
||||
position: position,
|
||||
top: 0,
|
||||
right: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<ActivityIndicator
|
||||
animating={true}
|
||||
|
|
|
@ -7,6 +7,7 @@ import {Snackbar} from 'react-native-paper';
|
|||
import {Animated, RefreshControl, View} from "react-native";
|
||||
import ErrorView from "../Custom/ErrorView";
|
||||
import BasicLoadingScreen from "../Custom/BasicLoadingScreen";
|
||||
import {withCollapsible} from "../../utils/withCollapsible";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
|
@ -20,6 +21,7 @@ type Props = {
|
|||
updateData: number,
|
||||
itemHeight: number | null,
|
||||
onScroll: Function,
|
||||
collapsibleStack: Object,
|
||||
}
|
||||
|
||||
type State = {
|
||||
|
@ -31,13 +33,14 @@ type State = {
|
|||
|
||||
|
||||
const MIN_REFRESH_TIME = 5 * 1000;
|
||||
|
||||
/**
|
||||
* Component used to render a SectionList with data fetched from the web
|
||||
*
|
||||
* This is a pure component, meaning it will only update if a shallow comparison of state and props is different.
|
||||
* To force the component to update, change the value of updateData.
|
||||
*/
|
||||
export default class WebSectionList extends React.PureComponent<Props, State> {
|
||||
class WebSectionList extends React.PureComponent<Props, State> {
|
||||
|
||||
static defaultProps = {
|
||||
renderSectionHeader: null,
|
||||
|
@ -171,11 +174,16 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
index
|
||||
});
|
||||
|
||||
onListScroll= (event) => {
|
||||
|
||||
};
|
||||
|
||||
render() {
|
||||
let dataset = [];
|
||||
if (this.state.fetchedData !== undefined)
|
||||
dataset = this.props.createDataset(this.state.fetchedData);
|
||||
const shouldRenderHeader = this.props.renderSectionHeader !== null;
|
||||
const {containerPaddingTop, scrollIndicatorInsetTop, onScrollWithListener} = this.props.collapsibleStack;
|
||||
return (
|
||||
<View>
|
||||
{/*$FlowFixMe*/}
|
||||
|
@ -184,6 +192,7 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
extraData={this.props.updateData}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
progressViewOffset={containerPaddingTop}
|
||||
refreshing={this.state.refreshing}
|
||||
onRefresh={this.onRefresh}
|
||||
/>
|
||||
|
@ -193,7 +202,6 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
//$FlowFixMe
|
||||
renderItem={this.props.renderItem}
|
||||
stickySectionHeadersEnabled={this.props.stickyHeader}
|
||||
contentContainerStyle={{minHeight: '100%'}}
|
||||
style={{minHeight: '100%'}}
|
||||
ListEmptyComponent={this.state.refreshing
|
||||
? <BasicLoadingScreen/>
|
||||
|
@ -204,7 +212,12 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
}
|
||||
getItemLayout={this.props.itemHeight !== null ? this.itemLayout : undefined}
|
||||
// Animations
|
||||
onScroll={this.props.onScroll}
|
||||
onScroll={onScrollWithListener(this.props.onScroll)}
|
||||
contentContainerStyle={{
|
||||
paddingTop: containerPaddingTop,
|
||||
minHeight: '100%'
|
||||
}}
|
||||
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
|
||||
/>
|
||||
<Snackbar
|
||||
visible={this.state.snackbarVisible}
|
||||
|
@ -222,3 +235,5 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withCollapsible(WebSectionList);
|
||||
|
|
|
@ -9,14 +9,18 @@ import MaterialHeaderButtons, {Item} from '../Custom/HeaderButton';
|
|||
import {HiddenItem} from "react-navigation-header-buttons";
|
||||
import {Linking} from "expo";
|
||||
import i18n from 'i18n-js';
|
||||
import {BackHandler} from "react-native";
|
||||
import {Animated, BackHandler} from "react-native";
|
||||
import {withCollapsible} from "../../utils/withCollapsible";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
url: string,
|
||||
customJS: string,
|
||||
collapsibleStack: Object,
|
||||
}
|
||||
|
||||
const AnimatedWebView = Animated.createAnimatedComponent(WebView);
|
||||
|
||||
/**
|
||||
* Class defining a webview screen.
|
||||
*/
|
||||
|
@ -63,7 +67,7 @@ class WebViewScreen extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
onBackButtonPressAndroid = () => {
|
||||
if (this.canGoBack){
|
||||
if (this.canGoBack) {
|
||||
this.onGoBackClicked();
|
||||
return true;
|
||||
}
|
||||
|
@ -112,15 +116,48 @@ class WebViewScreen extends React.PureComponent<Props> {
|
|||
*
|
||||
* @return {*}
|
||||
*/
|
||||
getRenderLoading = () => <BasicLoadingScreen/>;
|
||||
getRenderLoading = () => <BasicLoadingScreen isAbsolute={true}/>;
|
||||
|
||||
// document.getElementsByTagName('body')[0].style.paddingTop = '100px';
|
||||
|
||||
// $( 'body *' ).filter(function(){
|
||||
// var position = $(this).css('position');
|
||||
// var top = $(this).css('top');
|
||||
// if((position === 'fixed') && top !== 'auto'){
|
||||
// console.log(top);
|
||||
// $(this).css('top', 'calc(' + top + ' + 100px)');
|
||||
// console.log($(this).css('top'));
|
||||
// };
|
||||
// });
|
||||
|
||||
// document.querySelectorAll('body *').forEach(function(node){
|
||||
// var style = window.getComputedStyle(node);
|
||||
// var position = style.getPropertyValue('position');
|
||||
// var top = style.getPropertyValue('top');
|
||||
// if((position === 'fixed') && top !== 'auto'){
|
||||
// console.log(top);
|
||||
// node.style.top = 'calc(' + top + ' + 100px)';
|
||||
// console.log(node.style.top);
|
||||
// console.log(node);
|
||||
// };
|
||||
// });
|
||||
|
||||
getJavascriptPadding(padding: number) {
|
||||
return (
|
||||
"document.getElementsByTagName('body')[0].style.paddingTop = '" + padding + "px';\n" +
|
||||
"true;"
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {containerPaddingTop, onScroll} = this.props.collapsibleStack;
|
||||
const customJS = this.getJavascriptPadding(containerPaddingTop);
|
||||
return (
|
||||
<WebView
|
||||
<AnimatedWebView
|
||||
ref={this.webviewRef}
|
||||
source={{uri: this.props.url}}
|
||||
startInLoadingState={true}
|
||||
injectedJavaScript={this.props.customJS}
|
||||
injectedJavaScript={this.props.customJS + customJS}
|
||||
javaScriptEnabled={true}
|
||||
renderLoading={this.getRenderLoading}
|
||||
renderError={() => <ErrorView
|
||||
|
@ -130,9 +167,11 @@ class WebViewScreen extends React.PureComponent<Props> {
|
|||
onNavigationStateChange={navState => {
|
||||
this.canGoBack = navState.canGoBack;
|
||||
}}
|
||||
// Animations
|
||||
onScroll={onScroll}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default WebViewScreen;
|
||||
export default withCollapsible(WebViewScreen);
|
||||
|
|
|
@ -26,6 +26,8 @@ import {AmicaleWebsiteScreen} from "../screens/Websites/AmicaleWebsiteScreen";
|
|||
import {TutorInsaWebsiteScreen} from "../screens/Websites/TutorInsaWebsiteScreen";
|
||||
import {WiketudWebsiteScreen} from "../screens/Websites/WiketudWebsiteScreen";
|
||||
import {ElusEtudiantsWebsiteScreen} from "../screens/Websites/ElusEtudiantsWebsiteScreen";
|
||||
import {createCollapsibleStack} from "react-navigation-collapsible";
|
||||
import {useTheme} from "react-native-paper";
|
||||
|
||||
const defaultScreenOptions = {
|
||||
gestureEnabled: true,
|
||||
|
@ -106,23 +108,33 @@ function SettingsStackComponent() {
|
|||
const SelfMenuStack = createStackNavigator();
|
||||
|
||||
function SelfMenuStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<SelfMenuStack.Navigator
|
||||
initialRouteName="self-menu"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<SelfMenuStack.Screen
|
||||
name="self-menu"
|
||||
component={SelfMenuScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.menuSelf'),
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<SelfMenuStack.Screen
|
||||
name="self-menu"
|
||||
component={SelfMenuScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.menuSelf'),
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: true,
|
||||
}
|
||||
)}
|
||||
</SelfMenuStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
@ -130,23 +142,33 @@ function SelfMenuStackComponent() {
|
|||
const AvailableRoomStack = createStackNavigator();
|
||||
|
||||
function AvailableRoomStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<AvailableRoomStack.Navigator
|
||||
initialRouteName="available-rooms"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<AvailableRoomStack.Screen
|
||||
name="available-rooms"
|
||||
component={AvailableRoomScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.availableRooms'),
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<AvailableRoomStack.Screen
|
||||
name="available-rooms"
|
||||
component={AvailableRoomScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.availableRooms'),
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: false, // native driver does not work with webview
|
||||
}
|
||||
)}
|
||||
</AvailableRoomStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
@ -154,23 +176,33 @@ function AvailableRoomStackComponent() {
|
|||
const BibStack = createStackNavigator();
|
||||
|
||||
function BibStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<BibStack.Navigator
|
||||
initialRouteName="bib"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<BibStack.Screen
|
||||
name="bib"
|
||||
component={BibScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.bib'),
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<BibStack.Screen
|
||||
name="bib"
|
||||
component={BibScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.bib'),
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: false, // native driver does not work with webview
|
||||
}
|
||||
)}
|
||||
</BibStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
@ -178,23 +210,33 @@ function BibStackComponent() {
|
|||
const AmicaleWebsiteStack = createStackNavigator();
|
||||
|
||||
function AmicaleWebsiteStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<AmicaleWebsiteStack.Navigator
|
||||
initialRouteName="amicale-website"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<AmicaleWebsiteStack.Screen
|
||||
name="amicale-website"
|
||||
component={AmicaleWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Amicale",
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<AmicaleWebsiteStack.Screen
|
||||
name="amicale-website"
|
||||
component={AmicaleWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Amicale",
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: false, // native driver does not work with webview
|
||||
}
|
||||
)}
|
||||
</AmicaleWebsiteStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
@ -202,23 +244,33 @@ function AmicaleWebsiteStackComponent() {
|
|||
const ElusEtudiantsStack = createStackNavigator();
|
||||
|
||||
function ElusEtudiantsStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<ElusEtudiantsStack.Navigator
|
||||
initialRouteName="elus-etudiants"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<ElusEtudiantsStack.Screen
|
||||
name="elus-etudiants"
|
||||
component={ElusEtudiantsWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Élus Étudiants",
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<ElusEtudiantsStack.Screen
|
||||
name="elus-etudiants"
|
||||
component={ElusEtudiantsWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Élus Étudiants",
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: false, // native driver does not work with webview
|
||||
}
|
||||
)}
|
||||
</ElusEtudiantsStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
@ -226,23 +278,33 @@ function ElusEtudiantsStackComponent() {
|
|||
const WiketudStack = createStackNavigator();
|
||||
|
||||
function WiketudStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<WiketudStack.Navigator
|
||||
initialRouteName="wiketud"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<WiketudStack.Screen
|
||||
name="wiketud"
|
||||
component={WiketudWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Wiketud",
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<WiketudStack.Screen
|
||||
name="wiketud"
|
||||
component={WiketudWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Wiketud",
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: false, // native driver does not work with webview
|
||||
}
|
||||
)}
|
||||
</WiketudStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
@ -250,29 +312,38 @@ function WiketudStackComponent() {
|
|||
const TutorInsaStack = createStackNavigator();
|
||||
|
||||
function TutorInsaStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<TutorInsaStack.Navigator
|
||||
initialRouteName="tutorinsa"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<TutorInsaStack.Screen
|
||||
name="tutorinsa"
|
||||
component={TutorInsaWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Tutor'INSA",
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<TutorInsaStack.Screen
|
||||
name="tutorinsa"
|
||||
component={TutorInsaWebsiteScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: "Tutor'INSA",
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: false, // native driver does not work with webview
|
||||
}
|
||||
)}
|
||||
</TutorInsaStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const TetrisStack = createStackNavigator();
|
||||
|
||||
function TetrisStackComponent() {
|
||||
|
@ -408,23 +479,33 @@ function AmicaleContactStackComponent() {
|
|||
const ClubStack = createStackNavigator();
|
||||
|
||||
function ClubStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<ClubStack.Navigator
|
||||
initialRouteName={"club-list"}
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<ClubStack.Screen
|
||||
name="club-list"
|
||||
component={ClubListScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('clubs.clubList'),
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<ClubStack.Screen
|
||||
name="club-list"
|
||||
component={ClubListScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('clubs.clubList'),
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: true,
|
||||
}
|
||||
)}
|
||||
<ClubStack.Screen
|
||||
name="club-information"
|
||||
component={ClubDisplayScreen}
|
||||
|
|
|
@ -13,12 +13,13 @@ import ProximoAboutScreen from "../screens/Proximo/ProximoAboutScreen";
|
|||
import PlanexScreen from '../screens/Websites/PlanexScreen';
|
||||
import {MaterialCommunityIcons} from "@expo/vector-icons";
|
||||
import AsyncStorageManager from "../managers/AsyncStorageManager";
|
||||
import {withTheme} from 'react-native-paper';
|
||||
import {useTheme, withTheme} from 'react-native-paper';
|
||||
import i18n from "i18n-js";
|
||||
import ClubDisplayScreen from "../screens/Amicale/Clubs/ClubDisplayScreen";
|
||||
import ScannerScreen from "../screens/ScannerScreen";
|
||||
import MaterialHeaderButtons, {Item} from "../components/Custom/HeaderButton";
|
||||
import FeedItemScreen from "../screens/FeedItemScreen";
|
||||
import {createCollapsibleStack} from "react-navigation-collapsible";
|
||||
|
||||
|
||||
const TAB_ICONS = {
|
||||
|
@ -46,30 +47,49 @@ function getDrawerButton(navigation: Object) {
|
|||
const ProximoStack = createStackNavigator();
|
||||
|
||||
function ProximoStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<ProximoStack.Navigator
|
||||
initialRouteName="index"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<ProximoStack.Screen
|
||||
name="index"
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: 'Proximo',
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
component={ProximoMainScreen}
|
||||
/>
|
||||
<ProximoStack.Screen
|
||||
name="proximo-list"
|
||||
options={{
|
||||
title: i18n.t('screens.proximoArticles')
|
||||
}}
|
||||
component={ProximoListScreen}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<ProximoStack.Screen
|
||||
name="index"
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: 'Proximo',
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
component={ProximoMainScreen}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: true,
|
||||
}
|
||||
)}
|
||||
{createCollapsibleStack(
|
||||
<ProximoStack.Screen
|
||||
name="proximo-list"
|
||||
options={{
|
||||
title: i18n.t('screens.proximoArticles'),
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
}
|
||||
}}
|
||||
component={ProximoListScreen}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: true,
|
||||
}
|
||||
)}
|
||||
<ProximoStack.Screen
|
||||
name="proximo-about"
|
||||
component={ProximoAboutScreen}
|
||||
|
@ -85,23 +105,33 @@ function ProximoStackComponent() {
|
|||
const ProxiwashStack = createStackNavigator();
|
||||
|
||||
function ProxiwashStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<ProxiwashStack.Navigator
|
||||
initialRouteName="index"
|
||||
headerMode='float'
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<ProxiwashStack.Screen
|
||||
name="index"
|
||||
component={ProxiwashScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.proxiwash'),
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<ProxiwashStack.Screen
|
||||
name="index"
|
||||
component={ProxiwashScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.proxiwash'),
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: true,
|
||||
}
|
||||
)}
|
||||
<ProxiwashStack.Screen
|
||||
name="proxiwash-about"
|
||||
component={ProxiwashAboutScreen}
|
||||
|
@ -117,6 +147,7 @@ function ProxiwashStackComponent() {
|
|||
const PlanningStack = createStackNavigator();
|
||||
|
||||
function PlanningStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<PlanningStack.Navigator
|
||||
initialRouteName="index"
|
||||
|
@ -152,25 +183,34 @@ function HomeStackComponent(initialRoute: string | null, defaultData: Object) {
|
|||
let data;
|
||||
if (initialRoute !== null)
|
||||
data = {data: defaultData, nextScreen: initialRoute, shouldOpen: true};
|
||||
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<HomeStack.Navigator
|
||||
initialRouteName={"index"}
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<HomeStack.Screen
|
||||
name="index"
|
||||
component={HomeScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.home'),
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
initialParams={data}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<HomeStack.Screen
|
||||
name="index"
|
||||
component={HomeScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: i18n.t('screens.home'),
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
initialParams={data}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: true,
|
||||
}
|
||||
)}
|
||||
<HomeStack.Screen
|
||||
name="home-planning-information"
|
||||
component={PlanningDisplayScreen}
|
||||
|
@ -216,23 +256,33 @@ function HomeStackComponent(initialRoute: string | null, defaultData: Object) {
|
|||
const PlanexStack = createStackNavigator();
|
||||
|
||||
function PlanexStackComponent() {
|
||||
const {colors} = useTheme();
|
||||
return (
|
||||
<PlanexStack.Navigator
|
||||
initialRouteName="index"
|
||||
headerMode="float"
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<PlanexStack.Screen
|
||||
name="index"
|
||||
component={PlanexScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: 'Planex',
|
||||
headerLeft: openDrawer
|
||||
};
|
||||
}}
|
||||
/>
|
||||
{createCollapsibleStack(
|
||||
<PlanexStack.Screen
|
||||
name="index"
|
||||
component={PlanexScreen}
|
||||
options={({navigation}) => {
|
||||
const openDrawer = getDrawerButton.bind(this, navigation);
|
||||
return {
|
||||
title: 'Planex',
|
||||
headerLeft: openDrawer,
|
||||
headerStyle: {
|
||||
backgroundColor: colors.surface,
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
collapsedColor: 'transparent',
|
||||
useNativeDriver: false, // native driver does not work with webview
|
||||
}
|
||||
)}
|
||||
</PlanexStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {FlatList, Platform} from "react-native";
|
||||
import {Animated, Platform} from "react-native";
|
||||
import {Chip, Searchbar, withTheme} from 'react-native-paper';
|
||||
import AuthenticatedScreen from "../../../components/Amicale/AuthenticatedScreen";
|
||||
import i18n from "i18n-js";
|
||||
|
@ -9,10 +9,12 @@ import ClubListItem from "../../../components/Lists/ClubListItem";
|
|||
import {isItemInCategoryFilter, stringMatchQuery} from "../../../utils/Search";
|
||||
import ClubListHeader from "../../../components/Lists/ClubListHeader";
|
||||
import MaterialHeaderButtons, {Item} from "../../../components/Custom/HeaderButton";
|
||||
import {withCollapsible} from "../../../utils/withCollapsible";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
theme: Object,
|
||||
collapsibleStack: Object,
|
||||
}
|
||||
|
||||
type State = {
|
||||
|
@ -94,9 +96,10 @@ class ClubListScreen extends React.Component<Props, State> {
|
|||
|
||||
getScreen = (data: Object) => {
|
||||
this.categories = data[0].categories;
|
||||
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
|
||||
return (
|
||||
//$FlowFixMe
|
||||
<FlatList
|
||||
<Animated.FlatList
|
||||
data={data[0].clubs}
|
||||
keyExtractor={this.keyExtractor}
|
||||
renderItem={this.getRenderItem}
|
||||
|
@ -104,6 +107,10 @@ class ClubListScreen extends React.Component<Props, State> {
|
|||
// Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
|
||||
removeClippedSubviews={true}
|
||||
getItemLayout={this.itemLayout}
|
||||
// Animations
|
||||
onScroll={onScroll}
|
||||
contentContainerStyle={{paddingTop: containerPaddingTop}}
|
||||
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
|
||||
/>
|
||||
)
|
||||
};
|
||||
|
@ -208,4 +215,4 @@ class ClubListScreen extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
export default withTheme(ClubListScreen);
|
||||
export default withCollapsible(withTheme(ClubListScreen));
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {FlatList, Image, Platform, ScrollView, View} from "react-native";
|
||||
import {Animated, Image, Platform, ScrollView, View} from "react-native";
|
||||
import i18n from "i18n-js";
|
||||
import CustomModal from "../../components/Custom/CustomModal";
|
||||
import {RadioButton, Searchbar, Subheading, Text, Title, withTheme} from "react-native-paper";
|
||||
import {stringMatchQuery} from "../../utils/Search";
|
||||
import ProximoListItem from "../../components/Lists/ProximoListItem";
|
||||
import MaterialHeaderButtons, {Item} from "../../components/Custom/HeaderButton";
|
||||
import {withCollapsible} from "../../utils/withCollapsible";
|
||||
|
||||
function sortPrice(a, b) {
|
||||
return a.price - b.price;
|
||||
|
@ -39,6 +40,7 @@ type Props = {
|
|||
navigation: Object,
|
||||
route: Object,
|
||||
theme: Object,
|
||||
collapsibleStack: Object,
|
||||
}
|
||||
|
||||
type State = {
|
||||
|
@ -295,6 +297,7 @@ class ProximoListScreen extends React.Component<Props, State> {
|
|||
itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
|
||||
|
||||
render() {
|
||||
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
|
||||
return (
|
||||
<View style={{
|
||||
height: '100%'
|
||||
|
@ -303,7 +306,7 @@ class ProximoListScreen extends React.Component<Props, State> {
|
|||
{this.state.modalCurrentDisplayItem}
|
||||
</CustomModal>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
<Animated.FlatList
|
||||
data={this.listData}
|
||||
extraData={this.state.currentSearchString + this.state.currentSortMode}
|
||||
keyExtractor={this.keyExtractor}
|
||||
|
@ -312,10 +315,14 @@ class ProximoListScreen extends React.Component<Props, State> {
|
|||
removeClippedSubviews={true}
|
||||
getItemLayout={this.itemLayout}
|
||||
initialNumToRender={10}
|
||||
// Animations
|
||||
onScroll={onScroll}
|
||||
contentContainerStyle={{paddingTop: containerPaddingTop}}
|
||||
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(ProximoListScreen);
|
||||
export default withCollapsible(withTheme(ProximoListScreen));
|
||||
|
|
8
src/utils/withCollapsible.js
Normal file
8
src/utils/withCollapsible.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import React from 'react';
|
||||
import {useCollapsibleStack} from "react-navigation-collapsible";
|
||||
|
||||
export const withCollapsible = (Component: any) => {
|
||||
return (props: any) => {
|
||||
return <Component collapsibleStack={useCollapsibleStack()} {...props} />;
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue