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.

functions.js 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // @flow
  2. import moment from 'moment';
  3. import { i18next } from '../base/i18n';
  4. import { parseURIString } from '../base/util';
  5. import { RECENT_URL_STORAGE } from './constants';
  6. /**
  7. * MomentJS uses static language bundle loading, so in order to support dynamic
  8. * language selection in the app we need to load all bundles that we support in
  9. * the app.
  10. * FIXME: If we decide to support MomentJS in other features as well we may need
  11. * to move this import and the lenient matcher to the i18n feature.
  12. */
  13. require('moment/locale/bg');
  14. require('moment/locale/de');
  15. require('moment/locale/eo');
  16. require('moment/locale/es');
  17. require('moment/locale/fr');
  18. require('moment/locale/hy-am');
  19. require('moment/locale/it');
  20. require('moment/locale/nb');
  21. // OC is not available. Please submit OC translation to the MomentJS project.
  22. require('moment/locale/pl');
  23. require('moment/locale/pt');
  24. require('moment/locale/pt-br');
  25. require('moment/locale/ru');
  26. require('moment/locale/sk');
  27. require('moment/locale/sl');
  28. require('moment/locale/sv');
  29. require('moment/locale/tr');
  30. require('moment/locale/zh-cn');
  31. /**
  32. * Retreives the recent room list and generates all the data needed to be
  33. * displayed.
  34. *
  35. * @returns {Promise} The {@code Promise} to be resolved when the list is
  36. * available.
  37. */
  38. export function getRecentRooms(): Promise<Array<Object>> {
  39. return new Promise((resolve, reject) =>
  40. window.localStorage._getItemAsync(RECENT_URL_STORAGE).then(
  41. /* onFulfilled */ recentURLs => {
  42. const recentRoomDS = [];
  43. if (recentURLs) {
  44. // We init the locale on every list render, so then it
  45. // changes immediately if a language change happens in the
  46. // app.
  47. const locale = _getSupportedLocale();
  48. for (const e of JSON.parse(recentURLs)) {
  49. const location = parseURIString(e.conference);
  50. if (location && location.room && location.hostname) {
  51. recentRoomDS.push({
  52. baseURL:
  53. `${location.protocol}//${location.host}`,
  54. conference: e.conference,
  55. conferenceDuration: e.conferenceDuration,
  56. conferenceDurationString:
  57. _getDurationString(
  58. e.conferenceDuration,
  59. locale
  60. ),
  61. dateString: _getDateString(e.date, locale),
  62. dateTimeStamp: e.date,
  63. initials: _getInitials(location.room),
  64. room: location.room,
  65. serverName: location.hostname
  66. });
  67. }
  68. }
  69. }
  70. resolve(recentRoomDS.reverse());
  71. },
  72. /* onRejected */ reject)
  73. );
  74. }
  75. /**
  76. * Retreives the recent URL list as a list of objects.
  77. *
  78. * @returns {Array} The list of already stored recent URLs.
  79. */
  80. export function getRecentURLs() {
  81. const recentURLs = window.localStorage.getItem(RECENT_URL_STORAGE);
  82. return recentURLs ? JSON.parse(recentURLs) : [];
  83. }
  84. /**
  85. * Updates the recent URL list.
  86. *
  87. * @param {Array} recentURLs - The new URL list.
  88. * @returns {void}
  89. */
  90. export function updateRecentURLs(recentURLs: Array<Object>) {
  91. window.localStorage.setItem(
  92. RECENT_URL_STORAGE,
  93. JSON.stringify(recentURLs)
  94. );
  95. }
  96. /**
  97. * Returns a well formatted date string to be displayed in the list.
  98. *
  99. * @param {number} dateTimeStamp - The UTC timestamp to be converted to String.
  100. * @param {string} locale - The locale to init the formatter with. Note: This
  101. * locale must be supported by the formatter so ensure this prerequisite before
  102. * invoking the function.
  103. * @private
  104. * @returns {string}
  105. */
  106. function _getDateString(dateTimeStamp: number, locale: string) {
  107. const date = new Date(dateTimeStamp);
  108. const m = _getLocalizedFormatter(date, locale);
  109. if (date.toDateString() === new Date().toDateString()) {
  110. // The date is today, we use fromNow format.
  111. return m.fromNow();
  112. }
  113. return m.format('lll');
  114. }
  115. /**
  116. * Returns a well formatted duration string to be displayed as the conference
  117. * length.
  118. *
  119. * @param {number} duration - The duration in MS.
  120. * @param {string} locale - The locale to init the formatter with. Note: This
  121. * locale must be supported by the formatter so ensure this prerequisite before
  122. * invoking the function.
  123. * @private
  124. * @returns {string}
  125. */
  126. function _getDurationString(duration: number, locale: string) {
  127. return _getLocalizedFormatter(duration, locale)
  128. .humanize();
  129. }
  130. /**
  131. * Returns the initials supposed to be used based on the room name.
  132. *
  133. * @param {string} room - The room name.
  134. * @private
  135. * @returns {string}
  136. */
  137. function _getInitials(room: string) {
  138. return room && room.charAt(0) ? room.charAt(0).toUpperCase() : '?';
  139. }
  140. /**
  141. * Returns a localized date formatter initialized with the
  142. * provided date (@code Date) or duration (@code Number).
  143. *
  144. * @private
  145. * @param {Date | number} dateToFormat - The date or duration to format.
  146. * @param {string} locale - The locale to init the formatter with. Note: This
  147. * locale must be supported by the formatter so ensure this prerequisite before
  148. * invoking the function.
  149. * @returns {Object}
  150. */
  151. function _getLocalizedFormatter(dateToFormat: Date | number, locale: string) {
  152. if (typeof dateToFormat === 'number') {
  153. return moment.duration(dateToFormat).locale(locale);
  154. }
  155. return moment(dateToFormat).locale(locale);
  156. }
  157. /**
  158. * A lenient locale matcher to match language and dialect if possible.
  159. *
  160. * @private
  161. * @returns {string}
  162. */
  163. function _getSupportedLocale() {
  164. const i18nLocale = i18next.language;
  165. let supportedLocale;
  166. if (i18nLocale) {
  167. const localeRegexp = new RegExp('^([a-z]{2,2})(-)*([a-z]{2,2})*$');
  168. const localeResult = localeRegexp.exec(i18nLocale.toLowerCase());
  169. if (localeResult) {
  170. const currentLocaleRegexp
  171. = new RegExp(
  172. `^${localeResult[1]}(-)*${`(${localeResult[3]})*` || ''}`);
  173. supportedLocale
  174. = moment.locales().find(lang => currentLocaleRegexp.exec(lang));
  175. }
  176. }
  177. return supportedLocale || 'en';
  178. }