forked from vergnet/application-amicale
Fix eslint errors
First files rewritten to match the new eslint config
This commit is contained in:
parent
b596f68abe
commit
be1f61b671
4 changed files with 415 additions and 381 deletions
369
App.js
369
App.js
|
@ -1,210 +1,211 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {LogBox, Platform, SafeAreaView, StatusBar, View} from 'react-native';
|
||||
import LocaleManager from './src/managers/LocaleManager';
|
||||
import AsyncStorageManager from "./src/managers/AsyncStorageManager";
|
||||
import CustomIntroSlider from "./src/components/Overrides/CustomIntroSlider";
|
||||
import type {CustomTheme} from "./src/managers/ThemeManager";
|
||||
import ThemeManager from './src/managers/ThemeManager';
|
||||
import {LogBox, Platform, SafeAreaView, View} from 'react-native';
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import MainNavigator from './src/navigation/MainNavigator';
|
||||
import {Provider as PaperProvider} from 'react-native-paper';
|
||||
import AprilFoolsManager from "./src/managers/AprilFoolsManager";
|
||||
import Update from "./src/constants/Update";
|
||||
import ConnectionManager from "./src/managers/ConnectionManager";
|
||||
import URLHandler from "./src/utils/URLHandler";
|
||||
import {setSafeBounceHeight} from "react-navigation-collapsible";
|
||||
import SplashScreen from 'react-native-splash-screen'
|
||||
import {OverflowMenuProvider} from "react-navigation-header-buttons";
|
||||
import {setSafeBounceHeight} from 'react-navigation-collapsible';
|
||||
import SplashScreen from 'react-native-splash-screen';
|
||||
import {OverflowMenuProvider} from 'react-navigation-header-buttons';
|
||||
import LocaleManager from './src/managers/LocaleManager';
|
||||
import AsyncStorageManager from './src/managers/AsyncStorageManager';
|
||||
import CustomIntroSlider from './src/components/Overrides/CustomIntroSlider';
|
||||
import type {CustomTheme} from './src/managers/ThemeManager';
|
||||
import ThemeManager from './src/managers/ThemeManager';
|
||||
import MainNavigator from './src/navigation/MainNavigator';
|
||||
import AprilFoolsManager from './src/managers/AprilFoolsManager';
|
||||
import Update from './src/constants/Update';
|
||||
import ConnectionManager from './src/managers/ConnectionManager';
|
||||
import type {ParsedUrlDataType} from './src/utils/URLHandler';
|
||||
import URLHandler from './src/utils/URLHandler';
|
||||
import {setupStatusBar} from './src/utils/Utils';
|
||||
|
||||
// Native optimizations https://reactnavigation.org/docs/react-native-screens
|
||||
// Crashes app when navigating away from webview on android 9+
|
||||
// enableScreens(true);
|
||||
|
||||
|
||||
LogBox.ignoreLogs([ // collapsible headers cause this warning, just ignore as it is not an issue
|
||||
'Non-serializable values were found in the navigation state',
|
||||
'Cannot update a component from inside the function body of a different component',
|
||||
LogBox.ignoreLogs([
|
||||
// collapsible headers cause this warning, just ignore as it is not an issue
|
||||
'Non-serializable values were found in the navigation state',
|
||||
'Cannot update a component from inside the function body of a different component',
|
||||
]);
|
||||
|
||||
type Props = {};
|
||||
|
||||
type State = {
|
||||
isLoading: boolean,
|
||||
showIntro: boolean,
|
||||
showUpdate: boolean,
|
||||
showAprilFools: boolean,
|
||||
currentTheme: CustomTheme | null,
|
||||
type StateType = {
|
||||
isLoading: boolean,
|
||||
showIntro: boolean,
|
||||
showUpdate: boolean,
|
||||
showAprilFools: boolean,
|
||||
currentTheme: CustomTheme | null,
|
||||
};
|
||||
|
||||
export default class App extends React.Component<Props, State> {
|
||||
export default class App extends React.Component<null, StateType> {
|
||||
navigatorRef: {current: null | NavigationContainer};
|
||||
|
||||
state = {
|
||||
isLoading: true,
|
||||
showIntro: true,
|
||||
showUpdate: true,
|
||||
showAprilFools: false,
|
||||
currentTheme: null,
|
||||
defaultHomeRoute: string | null;
|
||||
|
||||
defaultHomeData: {[key: string]: string};
|
||||
|
||||
urlHandler: URLHandler;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
isLoading: true,
|
||||
showIntro: true,
|
||||
showUpdate: true,
|
||||
showAprilFools: false,
|
||||
currentTheme: null,
|
||||
};
|
||||
LocaleManager.initTranslations();
|
||||
this.navigatorRef = React.createRef();
|
||||
this.defaultHomeRoute = null;
|
||||
this.defaultHomeData = {};
|
||||
this.urlHandler = new URLHandler(this.onInitialURLParsed, this.onDetectURL);
|
||||
this.urlHandler.listen();
|
||||
setSafeBounceHeight(Platform.OS === 'ios' ? 100 : 20);
|
||||
this.loadAssetsAsync().finally(() => {
|
||||
this.onLoadFinished();
|
||||
});
|
||||
}
|
||||
|
||||
navigatorRef: { current: null | NavigationContainer };
|
||||
/**
|
||||
* The app has been started by an url, and it has been parsed.
|
||||
* Set a new default start route based on the data parsed.
|
||||
*
|
||||
* @param parsedData The data parsed from the url
|
||||
*/
|
||||
onInitialURLParsed = (parsedData: ParsedUrlDataType) => {
|
||||
this.defaultHomeRoute = parsedData.route;
|
||||
this.defaultHomeData = parsedData.data;
|
||||
};
|
||||
|
||||
defaultHomeRoute: string | null;
|
||||
defaultHomeData: { [key: string]: any }
|
||||
|
||||
createDrawerNavigator: () => React.Node;
|
||||
|
||||
urlHandler: URLHandler;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
LocaleManager.initTranslations();
|
||||
this.navigatorRef = React.createRef();
|
||||
this.defaultHomeRoute = null;
|
||||
this.defaultHomeData = {};
|
||||
this.urlHandler = new URLHandler(this.onInitialURLParsed, this.onDetectURL);
|
||||
this.urlHandler.listen();
|
||||
setSafeBounceHeight(Platform.OS === 'ios' ? 100 : 20);
|
||||
this.loadAssetsAsync().then(() => {
|
||||
this.onLoadFinished();
|
||||
});
|
||||
/**
|
||||
* An url has been opened and parsed while the app was active.
|
||||
* Redirect the user to the screen according to parsed data.
|
||||
*
|
||||
* @param parsedData The data parsed from the url
|
||||
*/
|
||||
onDetectURL = (parsedData: ParsedUrlDataType) => {
|
||||
// Navigate to nested navigator and pass data to the index screen
|
||||
const nav = this.navigatorRef.current;
|
||||
if (nav != null) {
|
||||
nav.navigate('home', {
|
||||
screen: 'index',
|
||||
params: {nextScreen: parsedData.route, data: parsedData.data},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The app has been started by an url, and it has been parsed.
|
||||
* Set a new default start route based on the data parsed.
|
||||
*
|
||||
* @param parsedData The data parsed from the url
|
||||
*/
|
||||
onInitialURLParsed = (parsedData: { route: string, data: { [key: string]: any } }) => {
|
||||
this.defaultHomeRoute = parsedData.route;
|
||||
this.defaultHomeData = parsedData.data;
|
||||
};
|
||||
/**
|
||||
* Updates the current theme
|
||||
*/
|
||||
onUpdateTheme = () => {
|
||||
this.setState({
|
||||
currentTheme: ThemeManager.getCurrentTheme(),
|
||||
});
|
||||
setupStatusBar();
|
||||
};
|
||||
|
||||
/**
|
||||
* An url has been opened and parsed while the app was active.
|
||||
* Redirect the user to the screen according to parsed data.
|
||||
*
|
||||
* @param parsedData The data parsed from the url
|
||||
*/
|
||||
onDetectURL = (parsedData: { route: string, data: { [key: string]: any } }) => {
|
||||
// Navigate to nested navigator and pass data to the index screen
|
||||
if (this.navigatorRef.current != null) {
|
||||
this.navigatorRef.current.navigate('home', {
|
||||
screen: 'index',
|
||||
params: {nextScreen: parsedData.route, data: parsedData.data}
|
||||
});
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Callback when user ends the intro. Save in preferences to avoid showing back the introSlides
|
||||
*/
|
||||
onIntroDone = () => {
|
||||
this.setState({
|
||||
showIntro: false,
|
||||
showUpdate: false,
|
||||
showAprilFools: false,
|
||||
});
|
||||
AsyncStorageManager.set(
|
||||
AsyncStorageManager.PREFERENCES.showIntro.key,
|
||||
false,
|
||||
);
|
||||
AsyncStorageManager.set(
|
||||
AsyncStorageManager.PREFERENCES.updateNumber.key,
|
||||
Update.number,
|
||||
);
|
||||
AsyncStorageManager.set(
|
||||
AsyncStorageManager.PREFERENCES.showAprilFoolsStart.key,
|
||||
false,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the current theme
|
||||
*/
|
||||
onUpdateTheme = () => {
|
||||
this.setState({
|
||||
currentTheme: ThemeManager.getCurrentTheme()
|
||||
});
|
||||
this.setupStatusBar();
|
||||
};
|
||||
/**
|
||||
* Async loading is done, finish processing startup data
|
||||
*/
|
||||
onLoadFinished() {
|
||||
// Only show intro if this is the first time starting the app
|
||||
ThemeManager.getInstance().setUpdateThemeCallback(this.onUpdateTheme);
|
||||
// Status bar goes dark if set too fast on ios
|
||||
if (Platform.OS === 'ios') setTimeout(setupStatusBar, 1000);
|
||||
else setupStatusBar();
|
||||
|
||||
/**
|
||||
* Updates status bar content color if on iOS only,
|
||||
* as the android status bar is always set to black.
|
||||
*/
|
||||
setupStatusBar() {
|
||||
if (ThemeManager.getNightMode()) {
|
||||
StatusBar.setBarStyle('light-content', true);
|
||||
} else {
|
||||
StatusBar.setBarStyle('dark-content', true);
|
||||
}
|
||||
if (Platform.OS === "android")
|
||||
StatusBar.setBackgroundColor(ThemeManager.getCurrentTheme().colors.surface, true);
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
currentTheme: ThemeManager.getCurrentTheme(),
|
||||
showIntro: AsyncStorageManager.getBool(
|
||||
AsyncStorageManager.PREFERENCES.showIntro.key,
|
||||
),
|
||||
showUpdate:
|
||||
AsyncStorageManager.getNumber(
|
||||
AsyncStorageManager.PREFERENCES.updateNumber.key,
|
||||
) !== Update.number,
|
||||
showAprilFools:
|
||||
AprilFoolsManager.getInstance().isAprilFoolsEnabled() &&
|
||||
AsyncStorageManager.getBool(
|
||||
AsyncStorageManager.PREFERENCES.showAprilFoolsStart.key,
|
||||
),
|
||||
});
|
||||
SplashScreen.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads every async data
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
loadAssetsAsync = async () => {
|
||||
await AsyncStorageManager.getInstance().loadPreferences();
|
||||
await ConnectionManager.getInstance().recoverLogin();
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the app based on loading state
|
||||
*/
|
||||
render(): React.Node {
|
||||
const {state} = this;
|
||||
if (state.isLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback when user ends the intro. Save in preferences to avoid showing back the introSlides
|
||||
*/
|
||||
onIntroDone = () => {
|
||||
this.setState({
|
||||
showIntro: false,
|
||||
showUpdate: false,
|
||||
showAprilFools: false,
|
||||
});
|
||||
AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.showIntro.key, false);
|
||||
AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.updateNumber.key, Update.number);
|
||||
AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.showAprilFoolsStart.key, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads every async data
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
loadAssetsAsync = async () => {
|
||||
await AsyncStorageManager.getInstance().loadPreferences();
|
||||
try {
|
||||
await ConnectionManager.getInstance().recoverLogin();
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async loading is done, finish processing startup data
|
||||
*/
|
||||
onLoadFinished() {
|
||||
// Only show intro if this is the first time starting the app
|
||||
this.createDrawerNavigator = () => <MainNavigator
|
||||
defaultHomeRoute={this.defaultHomeRoute}
|
||||
defaultHomeData={this.defaultHomeData}
|
||||
/>;
|
||||
ThemeManager.getInstance().setUpdateThemeCallback(this.onUpdateTheme);
|
||||
// Status bar goes dark if set too fast on ios
|
||||
if (Platform.OS === 'ios')
|
||||
setTimeout(this.setupStatusBar, 1000);
|
||||
else
|
||||
this.setupStatusBar();
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
currentTheme: ThemeManager.getCurrentTheme(),
|
||||
showIntro: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.showIntro.key),
|
||||
showUpdate: AsyncStorageManager.getNumber(AsyncStorageManager.PREFERENCES.updateNumber.key)
|
||||
!== Update.number,
|
||||
showAprilFools: AprilFoolsManager.getInstance().isAprilFoolsEnabled()
|
||||
&& AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.showAprilFoolsStart.key),
|
||||
});
|
||||
SplashScreen.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the app based on loading state
|
||||
*/
|
||||
render() {
|
||||
if (this.state.isLoading) {
|
||||
return null;
|
||||
} else if (this.state.showIntro || this.state.showUpdate || this.state.showAprilFools) {
|
||||
return <CustomIntroSlider
|
||||
onDone={this.onIntroDone}
|
||||
isUpdate={this.state.showUpdate && !this.state.showIntro}
|
||||
isAprilFools={this.state.showAprilFools && !this.state.showIntro}
|
||||
/>;
|
||||
} else {
|
||||
return (
|
||||
<PaperProvider theme={this.state.currentTheme}>
|
||||
<OverflowMenuProvider>
|
||||
<View style={{backgroundColor: ThemeManager.getCurrentTheme().colors.background, flex: 1}}>
|
||||
<SafeAreaView style={{flex: 1}}>
|
||||
<NavigationContainer theme={this.state.currentTheme} ref={this.navigatorRef}>
|
||||
<MainNavigator
|
||||
defaultHomeRoute={this.defaultHomeRoute}
|
||||
defaultHomeData={this.defaultHomeData}
|
||||
/>
|
||||
</NavigationContainer>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
</OverflowMenuProvider>
|
||||
</PaperProvider>
|
||||
);
|
||||
}
|
||||
if (state.showIntro || state.showUpdate || state.showAprilFools) {
|
||||
return (
|
||||
<CustomIntroSlider
|
||||
onDone={this.onIntroDone}
|
||||
isUpdate={state.showUpdate && !state.showIntro}
|
||||
isAprilFools={state.showAprilFools && !state.showIntro}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<PaperProvider theme={state.currentTheme}>
|
||||
<OverflowMenuProvider>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: ThemeManager.getCurrentTheme().colors.background,
|
||||
flex: 1,
|
||||
}}>
|
||||
<SafeAreaView style={{flex: 1}}>
|
||||
<NavigationContainer
|
||||
theme={state.currentTheme}
|
||||
ref={this.navigatorRef}>
|
||||
<MainNavigator
|
||||
defaultHomeRoute={this.defaultHomeRoute}
|
||||
defaultHomeData={this.defaultHomeData}
|
||||
/>
|
||||
</NavigationContainer>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
</OverflowMenuProvider>
|
||||
</PaperProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
// @flow
|
||||
|
||||
import type {ServiceItem} from "./ServicesManager";
|
||||
import ServicesManager from "./ServicesManager";
|
||||
import {StackNavigationProp} from "@react-navigation/stack";
|
||||
import {getSublistWithIds} from "../utils/Utils";
|
||||
import AsyncStorageManager from "./AsyncStorageManager";
|
||||
|
||||
import type {ServiceItem} from './ServicesManager';
|
||||
import ServicesManager from './ServicesManager';
|
||||
import {getSublistWithIds} from '../utils/Utils';
|
||||
import AsyncStorageManager from './AsyncStorageManager';
|
||||
|
||||
export default class DashboardManager extends ServicesManager {
|
||||
|
||||
constructor(nav: StackNavigationProp) {
|
||||
super(nav)
|
||||
}
|
||||
|
||||
getCurrentDashboard(): Array<ServiceItem> {
|
||||
const dashboardIdList = AsyncStorageManager
|
||||
.getObject(AsyncStorageManager.PREFERENCES.dashboardItems.key);
|
||||
const allDatasets = [
|
||||
...this.amicaleDataset,
|
||||
...this.studentsDataset,
|
||||
...this.insaDataset,
|
||||
...this.specialDataset,
|
||||
];
|
||||
return getSublistWithIds(dashboardIdList, allDatasets);
|
||||
}
|
||||
getCurrentDashboard(): Array<ServiceItem | null> {
|
||||
const dashboardIdList = AsyncStorageManager.getObject(
|
||||
AsyncStorageManager.PREFERENCES.dashboardItems.key,
|
||||
);
|
||||
const allDatasets = [
|
||||
...this.amicaleDataset,
|
||||
...this.studentsDataset,
|
||||
...this.insaDataset,
|
||||
...this.specialDataset,
|
||||
];
|
||||
return getSublistWithIds(dashboardIdList, allDatasets);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,174 +2,199 @@
|
|||
|
||||
import {Linking} from 'react-native';
|
||||
|
||||
export type ParsedUrlDataType = {
|
||||
route: string,
|
||||
data: {[key: string]: string},
|
||||
};
|
||||
|
||||
export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
|
||||
|
||||
type RawParsedUrlDataType = {
|
||||
path: string,
|
||||
queryParams: {[key: string]: string},
|
||||
};
|
||||
|
||||
/**
|
||||
* Class use to handle depp links scanned or clicked.
|
||||
*/
|
||||
export default class URLHandler {
|
||||
static SCHEME = 'campus-insat://'; // Urls beginning with this string will be opened in the app
|
||||
|
||||
static SCHEME = "campus-insat://"; // Urls beginning with this string will be opened in the app
|
||||
static CLUB_INFO_URL_PATH = 'club';
|
||||
|
||||
static CLUB_INFO_URL_PATH = "club";
|
||||
static EVENT_INFO_URL_PATH = "event";
|
||||
static EVENT_INFO_URL_PATH = 'event';
|
||||
|
||||
static CLUB_INFO_ROUTE = "club-information";
|
||||
static EVENT_INFO_ROUTE = "planning-information";
|
||||
static CLUB_INFO_ROUTE = 'club-information';
|
||||
|
||||
onInitialURLParsed: Function;
|
||||
onDetectURL: Function;
|
||||
static EVENT_INFO_ROUTE = 'planning-information';
|
||||
|
||||
constructor(onInitialURLParsed: Function, onDetectURL: Function) {
|
||||
this.onInitialURLParsed = onInitialURLParsed;
|
||||
this.onDetectURL = onDetectURL;
|
||||
onInitialURLParsed: ParsedUrlCallbackType;
|
||||
|
||||
onDetectURL: ParsedUrlCallbackType;
|
||||
|
||||
constructor(
|
||||
onInitialURLParsed: ParsedUrlCallbackType,
|
||||
onDetectURL: ParsedUrlCallbackType,
|
||||
) {
|
||||
this.onInitialURLParsed = onInitialURLParsed;
|
||||
this.onDetectURL = onDetectURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given url to retrieve the corresponding app path and associated arguments.
|
||||
*
|
||||
* @param url The url to parse
|
||||
* @returns {{path: string, queryParams: {}}}
|
||||
*/
|
||||
static parseUrl(url: string): RawParsedUrlDataType | null {
|
||||
let parsedData: RawParsedUrlDataType | null = null;
|
||||
const urlNoScheme = url.replace(URLHandler.SCHEME, '');
|
||||
if (urlNoScheme != null) {
|
||||
const params = {};
|
||||
const [path, fullParamsString] = urlNoScheme.split('?');
|
||||
if (fullParamsString != null) {
|
||||
const paramsStringArray = fullParamsString.split('&');
|
||||
paramsStringArray.forEach((paramString: string) => {
|
||||
const [key, value] = paramString.split('=');
|
||||
if (value != null) {
|
||||
params[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (path != null) parsedData = {path, queryParams: params};
|
||||
}
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets routing data corresponding to the given url.
|
||||
* If the url does not match any existing route, null will be returned.
|
||||
*
|
||||
* @param rawParsedUrlData The data just parsed
|
||||
* @returns {null}
|
||||
*/
|
||||
static getUrlData(
|
||||
rawParsedUrlData: RawParsedUrlDataType | null,
|
||||
): ParsedUrlDataType | null {
|
||||
let parsedData: null | ParsedUrlDataType = null;
|
||||
if (rawParsedUrlData != null) {
|
||||
const {path} = rawParsedUrlData;
|
||||
const {queryParams} = rawParsedUrlData;
|
||||
if (URLHandler.isClubInformationLink(path))
|
||||
parsedData = URLHandler.generateClubInformationData(queryParams);
|
||||
else if (URLHandler.isPlanningInformationLink(path))
|
||||
parsedData = URLHandler.generatePlanningInformationData(queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given url to retrieve the corresponding app path and associated arguments.
|
||||
*
|
||||
* @param url The url to parse
|
||||
* @returns {{path: string, queryParams: {}}}
|
||||
*/
|
||||
static parseUrl(url: string) {
|
||||
let params = {};
|
||||
let path = "";
|
||||
let temp = url.replace(URLHandler.SCHEME, "");
|
||||
if (temp != null) {
|
||||
let array = temp.split("?");
|
||||
if (array != null && array.length > 0) {
|
||||
path = array[0];
|
||||
}
|
||||
if (array != null && array.length > 1) {
|
||||
let tempParams = array[1].split("&");
|
||||
for (let i = 0; i < tempParams.length; i++) {
|
||||
let paramsArray = tempParams[i].split("=");
|
||||
if (paramsArray.length > 1) {
|
||||
params[paramsArray[0]] = paramsArray[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {path: path, queryParams: params};
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given url is in a valid format
|
||||
*
|
||||
* @param url The url to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isUrlValid(url: string): boolean {
|
||||
return this.getUrlData(URLHandler.parseUrl(url)) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path links to the club information screen
|
||||
*
|
||||
* @param path The url to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isClubInformationLink(path: string): boolean {
|
||||
return path === URLHandler.CLUB_INFO_URL_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path links to the planning information screen
|
||||
*
|
||||
* @param path The url to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isPlanningInformationLink(path: string): boolean {
|
||||
return path === URLHandler.EVENT_INFO_URL_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates data formatted for the club information screen from the url parameters.
|
||||
*
|
||||
* @param params Url parameters to convert
|
||||
* @returns {null|{route: string, data: {clubId: number}}}
|
||||
*/
|
||||
static generateClubInformationData(params: {
|
||||
[key: string]: string,
|
||||
}): ParsedUrlDataType | null {
|
||||
if (params.id != null) {
|
||||
const id = parseInt(params.id, 10);
|
||||
if (!Number.isNaN(id))
|
||||
return {
|
||||
route: URLHandler.CLUB_INFO_ROUTE,
|
||||
data: {clubId: id.toString()},
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets routing data corresponding to the given url.
|
||||
* If the url does not match any existing route, null will be returned.
|
||||
*
|
||||
* @param path Url path
|
||||
* @param queryParams Url parameters
|
||||
* @returns {null}
|
||||
*/
|
||||
static getUrlData({path, queryParams}: { path: string, queryParams: { [key: string]: string } }) {
|
||||
let data = null;
|
||||
if (path !== null) {
|
||||
if (URLHandler.isClubInformationLink(path))
|
||||
data = URLHandler.generateClubInformationData(queryParams);
|
||||
else if (URLHandler.isPlanningInformationLink(path))
|
||||
data = URLHandler.generatePlanningInformationData(queryParams);
|
||||
}
|
||||
return data;
|
||||
/**
|
||||
* Generates data formatted for the planning information screen from the url parameters.
|
||||
*
|
||||
* @param params Url parameters to convert
|
||||
* @returns {null|{route: string, data: {clubId: number}}}
|
||||
*/
|
||||
static generatePlanningInformationData(params: {
|
||||
[key: string]: string,
|
||||
}): ParsedUrlDataType | null {
|
||||
if (params.id != null) {
|
||||
const id = parseInt(params.id, 10);
|
||||
if (!Number.isNaN(id)) {
|
||||
return {
|
||||
route: URLHandler.EVENT_INFO_ROUTE,
|
||||
data: {eventId: id.toString()},
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given url is in a valid format
|
||||
*
|
||||
* @param url The url to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isUrlValid(url: string) {
|
||||
return this.getUrlData(URLHandler.parseUrl(url)) !== null;
|
||||
/**
|
||||
* Starts listening to events.
|
||||
*
|
||||
* There are 2 types of event.
|
||||
*
|
||||
* A classic event, triggered while the app is active.
|
||||
* An initial event, called when the app was opened by clicking on a link
|
||||
*
|
||||
*/
|
||||
listen() {
|
||||
Linking.addEventListener('url', this.onUrl);
|
||||
Linking.getInitialURL().then(this.onInitialUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data from the given url and calls the classic callback with it.
|
||||
*
|
||||
* @param url The url detected
|
||||
*/
|
||||
onUrl = ({url}: {url: string}) => {
|
||||
if (url != null) {
|
||||
const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||
if (data != null) this.onDetectURL(data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the given path links to the club information screen
|
||||
*
|
||||
* @param path The url to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isClubInformationLink(path: string) {
|
||||
return path === URLHandler.CLUB_INFO_URL_PATH;
|
||||
/**
|
||||
* Gets data from the given url and calls the initial callback with it.
|
||||
*
|
||||
* @param url The url detected
|
||||
*/
|
||||
onInitialUrl = (url: ?string) => {
|
||||
if (url != null) {
|
||||
const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||
if (data != null) this.onInitialURLParsed(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given path links to the planning information screen
|
||||
*
|
||||
* @param path The url to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static isPlanningInformationLink(path: string) {
|
||||
return path === URLHandler.EVENT_INFO_URL_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates data formatted for the club information screen from the url parameters.
|
||||
*
|
||||
* @param params Url parameters to convert
|
||||
* @returns {null|{route: string, data: {clubId: number}}}
|
||||
*/
|
||||
static generateClubInformationData(params: Object): Object | null {
|
||||
if (params !== undefined && params.id !== undefined) {
|
||||
let id = parseInt(params.id);
|
||||
if (!isNaN(id)) {
|
||||
return {route: URLHandler.CLUB_INFO_ROUTE, data: {clubId: id}};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates data formatted for the planning information screen from the url parameters.
|
||||
*
|
||||
* @param params Url parameters to convert
|
||||
* @returns {null|{route: string, data: {clubId: number}}}
|
||||
*/
|
||||
static generatePlanningInformationData(params: Object): Object | null {
|
||||
if (params !== undefined && params.id !== undefined) {
|
||||
let id = parseInt(params.id);
|
||||
if (!isNaN(id)) {
|
||||
return {route: URLHandler.EVENT_INFO_ROUTE, data: {eventId: id}};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts listening to events.
|
||||
*
|
||||
* There are 2 types of event.
|
||||
*
|
||||
* A classic event, triggered while the app is active.
|
||||
* An initial event, called when the app was opened by clicking on a link
|
||||
*
|
||||
*/
|
||||
listen() {
|
||||
Linking.addEventListener('url', this.onUrl);
|
||||
Linking.getInitialURL().then(this.onInitialUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data from the given url and calls the classic callback with it.
|
||||
*
|
||||
* @param url The url detected
|
||||
*/
|
||||
onUrl = ({url}: { url: string }) => {
|
||||
if (url != null) {
|
||||
let data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||
if (data !== null)
|
||||
this.onDetectURL(data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets data from the given url and calls the initial callback with it.
|
||||
*
|
||||
* @param url The url detected
|
||||
*/
|
||||
onInitialUrl = (url: ?string) => {
|
||||
if (url != null) {
|
||||
let data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||
if (data !== null)
|
||||
this.onInitialURLParsed(data);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import {Platform, StatusBar} from 'react-native';
|
||||
import ThemeManager from '../managers/ThemeManager';
|
||||
|
||||
/**
|
||||
* Gets a sublist of the given list with items of the given ids only
|
||||
|
@ -10,28 +12,40 @@
|
|||
* @param originalList The original list
|
||||
* @returns {[]}
|
||||
*/
|
||||
export function getSublistWithIds(
|
||||
idList: Array<string>,
|
||||
originalList: Array<{ key: string, [key: string]: any }>
|
||||
): Array<{ key: string, [key: string]: any }> {
|
||||
let subList = [];
|
||||
for (let i = 0; i < subList.length; i++) {
|
||||
subList.push(null);
|
||||
export function getSublistWithIds<T>(
|
||||
idList: Array<string>,
|
||||
originalList: Array<{key: string, ...T}>,
|
||||
): Array<{key: string, ...T} | null> {
|
||||
const subList = [];
|
||||
for (let i = 0; i < idList.length; i += 1) {
|
||||
subList.push(null);
|
||||
}
|
||||
let itemsAdded = 0;
|
||||
for (let i = 0; i < originalList.length; i += 1) {
|
||||
const item = originalList[i];
|
||||
if (idList.includes(item.key)) {
|
||||
subList[idList.indexOf(item.key)] = item;
|
||||
itemsAdded += 1;
|
||||
if (itemsAdded === idList.length) break;
|
||||
}
|
||||
let itemsAdded = 0;
|
||||
for (let i = 0; i < originalList.length; i++) {
|
||||
const item = originalList[i];
|
||||
if (idList.includes(item.key)) {
|
||||
subList[idList.indexOf(item.key)] = item;
|
||||
itemsAdded++;
|
||||
if (itemsAdded === idList.length)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < subList.length; i++) {
|
||||
if (subList[i] == null)
|
||||
subList.splice(i, 1);
|
||||
}
|
||||
|
||||
return subList;
|
||||
}
|
||||
return subList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates status bar content color if on iOS only,
|
||||
* as the android status bar is always set to black.
|
||||
*/
|
||||
export function setupStatusBar() {
|
||||
if (ThemeManager.getNightMode()) {
|
||||
StatusBar.setBarStyle('light-content', true);
|
||||
} else {
|
||||
StatusBar.setBarStyle('dark-content', true);
|
||||
}
|
||||
if (Platform.OS === 'android') {
|
||||
StatusBar.setBackgroundColor(
|
||||
ThemeManager.getCurrentTheme().colors.surface,
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue