Compare commits

..

No commits in common. "fe24fce8829adab7b40cd0ebd7df8f75ea3b8146" and "f70a289cdfae130eaba679a246e339a6994cd149" have entirely different histories.

11 changed files with 110 additions and 58 deletions

View file

@ -52,6 +52,7 @@
"react-native-safe-area-context": "0.7.3", "react-native-safe-area-context": "0.7.3",
"react-native-screens": "~2.2.0", "react-native-screens": "~2.2.0",
"react-native-webview": "8.1.1", "react-native-webview": "8.1.1",
"react-navigation-collapsible": "^5.4.0",
"react-navigation-header-buttons": "^3.0.5" "react-navigation-header-buttons": "^3.0.5"
}, },
"devDependencies": { "devDependencies": {

View file

@ -8,17 +8,18 @@ import * as Touchable from "react-native/Libraries/Components/Touchable/Touchabl
const MaterialHeaderButton = (props: Object) => ( const MaterialHeaderButton = (props: Object) => (
<HeaderButton <HeaderButton
{...props}
IconComponent={MaterialCommunityIcons} IconComponent={MaterialCommunityIcons}
iconSize={26} iconSize={26}
color={props.theme.colors.text} color={props.theme.colors.text}
background={Touchable.Ripple(props.theme.colors.ripple, true)} background={Touchable.Ripple(props.theme.colors.ripple, true)}
{...props}
/> />
); );
const MaterialHeaderButtons = (props: Object) => { const MaterialHeaderButtons = (props: Object) => {
return ( return (
<HeaderButtons <HeaderButtons
{...props}
HeaderButtonComponent={withTheme(MaterialHeaderButton)} HeaderButtonComponent={withTheme(MaterialHeaderButton)}
OverflowIcon={ OverflowIcon={
<MaterialCommunityIcons <MaterialCommunityIcons
@ -27,7 +28,6 @@ const MaterialHeaderButtons = (props: Object) => {
color={props.theme.colors.text} color={props.theme.colors.text}
/> />
} }
{...props}
/> />
); );
}; };

View file

@ -6,14 +6,19 @@ import BasicLoadingScreen from "../Custom/BasicLoadingScreen";
import ErrorView from "../Custom/ErrorView"; import ErrorView from "../Custom/ErrorView";
import {ERROR_TYPE} from "../../utils/WebData"; import {ERROR_TYPE} from "../../utils/WebData";
import MaterialHeaderButtons, {Item} from '../Custom/HeaderButton'; import MaterialHeaderButtons, {Item} from '../Custom/HeaderButton';
import {HiddenItem} from "react-navigation-header-buttons";
import {Linking} from "expo";
import i18n from 'i18n-js';
type Props = { type Props = {
navigation: Object, navigation: Object,
data: Array<{
url: string, url: string,
customJS: string, icon: string,
name: string,
customJS: string
}>,
headerTitle: string,
hasHeaderBackButton: boolean,
hasSideMenu: boolean,
hasFooter: boolean,
} }
/** /**
@ -22,7 +27,9 @@ type Props = {
class WebViewScreen extends React.PureComponent<Props> { class WebViewScreen extends React.PureComponent<Props> {
static defaultProps = { static defaultProps = {
customJS: '', hasBackButton: false,
hasSideMenu: true,
hasFooter: true,
}; };
webviewRef: Object; webviewRef: Object;
@ -50,22 +57,7 @@ class WebViewScreen extends React.PureComponent<Props> {
getRefreshButton() { getRefreshButton() {
return ( return (
<MaterialHeaderButtons> <MaterialHeaderButtons>
<Item <Item title="refresh" iconName="refresh" onPress={this.onRefreshClicked}/>
title="refresh"
iconName="refresh"
onPress={this.onRefreshClicked}/>
<HiddenItem
title={i18n.t("general.goBack")}
iconName="arrow-left"
onPress={this.onGoBackClicked}/>
<HiddenItem
title={i18n.t("general.goForward")}
iconName="arrow-right"
onPress={this.onGoForwardClicked}/>
<HiddenItem
title={i18n.t("general.openInBrowser")}
iconName="web"
onPress={this.onOpenClicked}/>
</MaterialHeaderButtons> </MaterialHeaderButtons>
); );
}; };
@ -74,10 +66,6 @@ class WebViewScreen extends React.PureComponent<Props> {
* Callback to use when refresh button is clicked. Reloads the webview. * Callback to use when refresh button is clicked. Reloads the webview.
*/ */
onRefreshClicked = () => this.webviewRef.current.reload(); onRefreshClicked = () => this.webviewRef.current.reload();
onGoBackClicked = () => this.webviewRef.current.goBack();
onGoForwardClicked = () => this.webviewRef.current.goForward();
onOpenClicked = () => Linking.openURL(this.props.url);
/** /**
* Gets the loading indicator * Gets the loading indicator
@ -90,9 +78,13 @@ class WebViewScreen extends React.PureComponent<Props> {
return ( return (
<WebView <WebView
ref={this.webviewRef} ref={this.webviewRef}
source={{uri: this.props.url}} source={{uri: this.props.data[0]['url']}}
style={{
width: '100%',
height: '100%',
}}
startInLoadingState={true} startInLoadingState={true}
injectedJavaScript={this.props.customJS} injectedJavaScript={this.props.data[0]['customJS']}
javaScriptEnabled={true} javaScriptEnabled={true}
renderLoading={this.getRenderLoading} renderLoading={this.getRenderLoading}
renderError={() => <ErrorView renderError={() => <ErrorView

View file

@ -13,12 +13,12 @@ import ProximoAboutScreen from "../screens/Proximo/ProximoAboutScreen";
import PlanexScreen from '../screens/Websites/PlanexScreen'; import PlanexScreen from '../screens/Websites/PlanexScreen';
import {MaterialCommunityIcons} from "@expo/vector-icons"; import {MaterialCommunityIcons} from "@expo/vector-icons";
import AsyncStorageManager from "../managers/AsyncStorageManager"; import AsyncStorageManager from "../managers/AsyncStorageManager";
import {withTheme} from 'react-native-paper'; import {useTheme, withTheme} from 'react-native-paper';
import i18n from "i18n-js"; import i18n from "i18n-js";
import ClubDisplayScreen from "../screens/Amicale/Clubs/ClubDisplayScreen"; import ClubDisplayScreen from "../screens/Amicale/Clubs/ClubDisplayScreen";
import ScannerScreen from "../screens/ScannerScreen"; import ScannerScreen from "../screens/ScannerScreen";
import MaterialHeaderButtons, {Item} from "../components/Custom/HeaderButton"; import MaterialHeaderButtons, {Item} from "../components/Custom/HeaderButton";
import {createCollapsibleStack} from 'react-navigation-collapsible';
const TAB_ICONS = { const TAB_ICONS = {
home: 'triangle', home: 'triangle',
@ -44,7 +44,9 @@ function getDrawerButton(navigation: Object) {
const ProximoStack = createStackNavigator(); const ProximoStack = createStackNavigator();
function ProximoStackComponent() { function ProximoStackComponent(props: Object) {
const {colors} = useTheme();
return ( return (
<ProximoStack.Navigator <ProximoStack.Navigator
initialRouteName="index" initialRouteName="index"
@ -62,13 +64,19 @@ function ProximoStackComponent() {
}} }}
component={ProximoMainScreen} component={ProximoMainScreen}
/> />
{createCollapsibleStack(
<ProximoStack.Screen <ProximoStack.Screen
name="proximo-list" name="proximo-list"
options={{ options={{
title: i18n.t('screens.proximoArticles') title: i18n.t('screens.proximoArticles')
}} }}
component={ProximoListScreen} component={ProximoListScreen}
/> />,
{
collapsedColor: colors.surface,
useNativeDriver: true /* Optional, default: true */,
}
)}
<ProximoStack.Screen <ProximoStack.Screen
name="proximo-about" name="proximo-about"
component={ProximoAboutScreen} component={ProximoAboutScreen}

View file

@ -1,13 +1,16 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {FlatList, Image, Platform, ScrollView, View} from "react-native"; import {Animated, FlatList, Image, Platform, ScrollView, View} from "react-native";
import i18n from "i18n-js"; import i18n from "i18n-js";
import CustomModal from "../../components/Custom/CustomModal"; import CustomModal from "../../components/Custom/CustomModal";
import {RadioButton, Searchbar, Subheading, Text, Title, withTheme} from "react-native-paper"; import {RadioButton, Searchbar, Subheading, Text, Title, withTheme} from "react-native-paper";
import {stringMatchQuery} from "../../utils/Search"; import {stringMatchQuery} from "../../utils/Search";
import ProximoListItem from "../../components/Lists/ProximoListItem"; import ProximoListItem from "../../components/Lists/ProximoListItem";
import MaterialHeaderButtons, {Item} from "../../components/Custom/HeaderButton"; import MaterialHeaderButtons, {Item} from "../../components/Custom/HeaderButton";
import {withCollapsible} from "../../utils/withCollapsible";
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
function sortPrice(a, b) { function sortPrice(a, b) {
return a.price - b.price; return a.price - b.price;
@ -39,6 +42,7 @@ type Props = {
navigation: Object, navigation: Object,
route: Object, route: Object,
theme: Object, theme: Object,
collapsibleStack: Object,
} }
type State = { type State = {
@ -322,7 +326,9 @@ class ProximoListScreen extends React.Component<Props, State> {
itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index}); itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
render() { render() {
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
return ( return (
<View style={{ <View style={{
height: '100%' height: '100%'
@ -331,7 +337,7 @@ class ProximoListScreen extends React.Component<Props, State> {
{this.state.modalCurrentDisplayItem} {this.state.modalCurrentDisplayItem}
</CustomModal> </CustomModal>
{/*$FlowFixMe*/} {/*$FlowFixMe*/}
<FlatList <AnimatedFlatList
data={this.listData} data={this.listData}
extraData={this.state.currentSearchString + this.state.currentSortMode} extraData={this.state.currentSearchString + this.state.currentSortMode}
keyExtractor={this.keyExtractor} keyExtractor={this.keyExtractor}
@ -340,10 +346,14 @@ class ProximoListScreen extends React.Component<Props, State> {
removeClippedSubviews={true} removeClippedSubviews={true}
getItemLayout={this.itemLayout} getItemLayout={this.itemLayout}
initialNumToRender={10} initialNumToRender={10}
// Animations
onScroll={onScroll}
contentContainerStyle={{paddingTop: containerPaddingTop}}
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
/> />
</View> </View>
); );
} }
} }
export default withTheme(ProximoListScreen); export default withCollapsible(withTheme(ProximoListScreen));

View file

@ -2,6 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import WebViewScreen from "../../components/Screens/WebViewScreen"; import WebViewScreen from "../../components/Screens/WebViewScreen";
import i18n from "i18n-js";
type Props = { type Props = {
navigation: Object, navigation: Object,
@ -38,9 +39,25 @@ export default class AvailableRoomScreen extends React.Component<Props> {
return ( return (
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
url={ROOM_URL} data={[
customJS={this.customInjectedJS} {
customInjectedJS={this.customInjectedJS}/> url: ROOM_URL,
icon: 'file-document-outline',
name: i18n.t('availableRoomScreen.normalRoom'),
customJS: this.customInjectedJS
},
{
url: PC_URL,
icon: 'monitor',
name: i18n.t('availableRoomScreen.computerRoom'),
customJS: this.customInjectedJS
},
]}
customInjectedJS={this.customInjectedJS}
headerTitle={i18n.t('screens.availableRooms')}
hasHeaderBackButton={true}
hasSideMenu={false}
hasFooter={false}/>
); );
} }
} }

View file

@ -2,6 +2,7 @@
import * as React from 'react'; import * as React from 'react';
import WebViewScreen from "../../components/Screens/WebViewScreen"; import WebViewScreen from "../../components/Screens/WebViewScreen";
import i18n from "i18n-js";
type Props = { type Props = {
navigation: Object, navigation: Object,
@ -49,8 +50,19 @@ export default class AvailableRoomScreen extends React.Component<Props> {
return ( return (
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
url={BIB_URL} data={[
customJS={this.customBibInjectedJS}/> {
url: BIB_URL,
icon: 'book',
name: i18n.t('availableRoomScreen.bibRoom'),
customJS: this.customBibInjectedJS
},
]}
customInjectedJS={this.customInjectedJS}
headerTitle={i18n.t('screens.availableRooms')}
hasHeaderBackButton={true}
hasSideMenu={false}
hasFooter={false}/>
); );
} }
} }

View file

@ -165,8 +165,18 @@ export default class PlanexScreen extends React.Component<Props, State> {
</Banner> </Banner>
<WebViewScreen <WebViewScreen
navigation={nav} navigation={nav}
url={PLANEX_URL} data={[
customJS={this.customInjectedJS}/> {
url: PLANEX_URL,
icon: '',
name: '',
customJS: this.customInjectedJS
},
]}
customInjectedJS={this.customInjectedJS}
headerTitle={'Planex'}
hasHeaderBackButton={false}
hasFooter={false}/>
</View> </View>
); );
} }

View 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} />;
};
};

View file

@ -345,10 +345,7 @@
"general": { "general": {
"loading": "Loading...", "loading": "Loading...",
"retry": "Retry", "retry": "Retry",
"networkError": "Unable to contact servers. Make sure you are connected to Internet.", "networkError": "Unable to contact servers. Make sure you are connected to Internet."
"goBack": "Go Back",
"goForward": "Go Forward",
"openInBrowser": "Open in Browser"
}, },
"date": { "date": {
"daysOfWeek": { "daysOfWeek": {

View file

@ -345,10 +345,7 @@
"general": { "general": {
"loading": "Chargement...", "loading": "Chargement...",
"retry": "Réessayer", "retry": "Réessayer",
"networkError": "Impossible de contacter les serveurs. Assurez-vous d'être connecté à internet.", "networkError": "Impossible de contacter les serveurs. Assurez-vous d'être connecté à internet."
"goBack": "Suivant",
"goForward": "Précédent",
"openInBrowser": "Ouvrir dans le navigateur"
}, },
"date": { "date": {
"daysOfWeek": { "daysOfWeek": {