123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- /*
- * 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 {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: {[key: string]: string} = {};
- 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 | null) => {
- if (url != null) {
- const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
- if (data != null) {
- this.onInitialURLParsed(data);
- }
- }
- };
- }
|