application-amicale/src/utils/URLHandler.js
Arnaud Vergnet be1f61b671 Fix eslint errors
First files rewritten to match the new eslint config
2020-08-01 20:59:59 +02:00

200 lines
5.4 KiB
JavaScript

// @flow
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 CLUB_INFO_URL_PATH = 'club';
static EVENT_INFO_URL_PATH = 'event';
static CLUB_INFO_ROUTE = 'club-information';
static EVENT_INFO_ROUTE = 'planning-information';
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);
}
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;
}
/**
* 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;
}
/**
* 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);
}
};
/**
* 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);
}
};
}