Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

URLHandler.js 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // @flow
  2. import {Linking} from 'react-native';
  3. export type ParsedUrlDataType = {
  4. route: string,
  5. data: {[key: string]: string},
  6. };
  7. export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
  8. type RawParsedUrlDataType = {
  9. path: string,
  10. queryParams: {[key: string]: string},
  11. };
  12. /**
  13. * Class use to handle depp links scanned or clicked.
  14. */
  15. export default class URLHandler {
  16. static SCHEME = 'campus-insat://'; // Urls beginning with this string will be opened in the app
  17. static CLUB_INFO_URL_PATH = 'club';
  18. static EVENT_INFO_URL_PATH = 'event';
  19. static CLUB_INFO_ROUTE = 'club-information';
  20. static EVENT_INFO_ROUTE = 'planning-information';
  21. onInitialURLParsed: ParsedUrlCallbackType;
  22. onDetectURL: ParsedUrlCallbackType;
  23. constructor(
  24. onInitialURLParsed: ParsedUrlCallbackType,
  25. onDetectURL: ParsedUrlCallbackType,
  26. ) {
  27. this.onInitialURLParsed = onInitialURLParsed;
  28. this.onDetectURL = onDetectURL;
  29. }
  30. /**
  31. * Parses the given url to retrieve the corresponding app path and associated arguments.
  32. *
  33. * @param url The url to parse
  34. * @returns {{path: string, queryParams: {}}}
  35. */
  36. static parseUrl(url: string): RawParsedUrlDataType | null {
  37. let parsedData: RawParsedUrlDataType | null = null;
  38. const urlNoScheme = url.replace(URLHandler.SCHEME, '');
  39. if (urlNoScheme != null) {
  40. const params = {};
  41. const [path, fullParamsString] = urlNoScheme.split('?');
  42. if (fullParamsString != null) {
  43. const paramsStringArray = fullParamsString.split('&');
  44. paramsStringArray.forEach((paramString: string) => {
  45. const [key, value] = paramString.split('=');
  46. if (value != null) {
  47. params[key] = value;
  48. }
  49. });
  50. }
  51. if (path != null) parsedData = {path, queryParams: params};
  52. }
  53. return parsedData;
  54. }
  55. /**
  56. * Gets routing data corresponding to the given url.
  57. * If the url does not match any existing route, null will be returned.
  58. *
  59. * @param rawParsedUrlData The data just parsed
  60. * @returns {null}
  61. */
  62. static getUrlData(
  63. rawParsedUrlData: RawParsedUrlDataType | null,
  64. ): ParsedUrlDataType | null {
  65. let parsedData: null | ParsedUrlDataType = null;
  66. if (rawParsedUrlData != null) {
  67. const {path} = rawParsedUrlData;
  68. const {queryParams} = rawParsedUrlData;
  69. if (URLHandler.isClubInformationLink(path))
  70. parsedData = URLHandler.generateClubInformationData(queryParams);
  71. else if (URLHandler.isPlanningInformationLink(path))
  72. parsedData = URLHandler.generatePlanningInformationData(queryParams);
  73. }
  74. return parsedData;
  75. }
  76. /**
  77. * Checks if the given url is in a valid format
  78. *
  79. * @param url The url to check
  80. * @returns {boolean}
  81. */
  82. static isUrlValid(url: string): boolean {
  83. return this.getUrlData(URLHandler.parseUrl(url)) !== null;
  84. }
  85. /**
  86. * Check if the given path links to the club information screen
  87. *
  88. * @param path The url to check
  89. * @returns {boolean}
  90. */
  91. static isClubInformationLink(path: string): boolean {
  92. return path === URLHandler.CLUB_INFO_URL_PATH;
  93. }
  94. /**
  95. * Check if the given path links to the planning information screen
  96. *
  97. * @param path The url to check
  98. * @returns {boolean}
  99. */
  100. static isPlanningInformationLink(path: string): boolean {
  101. return path === URLHandler.EVENT_INFO_URL_PATH;
  102. }
  103. /**
  104. * Generates data formatted for the club information screen from the url parameters.
  105. *
  106. * @param params Url parameters to convert
  107. * @returns {null|{route: string, data: {clubId: number}}}
  108. */
  109. static generateClubInformationData(params: {
  110. [key: string]: string,
  111. }): ParsedUrlDataType | null {
  112. if (params.id != null) {
  113. const id = parseInt(params.id, 10);
  114. if (!Number.isNaN(id))
  115. return {
  116. route: URLHandler.CLUB_INFO_ROUTE,
  117. data: {clubId: id.toString()},
  118. };
  119. }
  120. return null;
  121. }
  122. /**
  123. * Generates data formatted for the planning information screen from the url parameters.
  124. *
  125. * @param params Url parameters to convert
  126. * @returns {null|{route: string, data: {clubId: number}}}
  127. */
  128. static generatePlanningInformationData(params: {
  129. [key: string]: string,
  130. }): ParsedUrlDataType | null {
  131. if (params.id != null) {
  132. const id = parseInt(params.id, 10);
  133. if (!Number.isNaN(id)) {
  134. return {
  135. route: URLHandler.EVENT_INFO_ROUTE,
  136. data: {eventId: id.toString()},
  137. };
  138. }
  139. }
  140. return null;
  141. }
  142. /**
  143. * Starts listening to events.
  144. *
  145. * There are 2 types of event.
  146. *
  147. * A classic event, triggered while the app is active.
  148. * An initial event, called when the app was opened by clicking on a link
  149. *
  150. */
  151. listen() {
  152. Linking.addEventListener('url', this.onUrl);
  153. Linking.getInitialURL().then(this.onInitialUrl);
  154. }
  155. /**
  156. * Gets data from the given url and calls the classic callback with it.
  157. *
  158. * @param url The url detected
  159. */
  160. onUrl = ({url}: {url: string}) => {
  161. if (url != null) {
  162. const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
  163. if (data != null) this.onDetectURL(data);
  164. }
  165. };
  166. /**
  167. * Gets data from the given url and calls the initial callback with it.
  168. *
  169. * @param url The url detected
  170. */
  171. onInitialUrl = (url: ?string) => {
  172. if (url != null) {
  173. const data = URLHandler.getUrlData(URLHandler.parseUrl(url));
  174. if (data != null) this.onInitialURLParsed(data);
  175. }
  176. };
  177. }