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.3KB

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