選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

app.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /* global $, config, getRoomName, loggingConfig, JitsiMeetJS */
  2. /* application specific logic */
  3. const logger = require("jitsi-meet-logger").getLogger(__filename);
  4. import "babel-polyfill";
  5. import "jquery";
  6. import "jquery-contextmenu";
  7. import "jquery-ui";
  8. import "strophe";
  9. import "strophe-disco";
  10. import "strophe-caps";
  11. import "jQuery-Impromptu";
  12. import "autosize";
  13. import 'aui';
  14. import 'aui-experimental';
  15. import 'aui-css';
  16. import 'aui-experimental-css';
  17. window.toastr = require("toastr");
  18. const Logger = require("jitsi-meet-logger");
  19. const LogCollector = Logger.LogCollector;
  20. import JitsiMeetLogStorage from "./modules/util/JitsiMeetLogStorage";
  21. import URLProcessor from "./modules/config/URLProcessor";
  22. import {
  23. generateRoomWithoutSeparator
  24. } from './react/features/base/util/roomnameGenerator';
  25. import UI from "./modules/UI/UI";
  26. import settings from "./modules/settings/Settings";
  27. import conference from './conference';
  28. import ConferenceUrl from './modules/URL/ConferenceUrl';
  29. import API from './modules/API/API';
  30. import UIEvents from './service/UI/UIEvents';
  31. import getTokenData from "./modules/tokendata/TokenData";
  32. import translation from "./modules/translation/translation";
  33. const ConferenceEvents = JitsiMeetJS.events.conference;
  34. /**
  35. * Tries to push history state with the following parameters:
  36. * 'VideoChat', `Room: ${roomName}`, URL. If fail, prints the error and returns
  37. * it.
  38. */
  39. function pushHistoryState(roomName, URL) {
  40. try {
  41. window.history.pushState(
  42. 'VideoChat', `Room: ${roomName}`, URL
  43. );
  44. } catch (e) {
  45. logger.warn("Push history state failed with parameters:",
  46. 'VideoChat', `Room: ${roomName}`, URL, e);
  47. return e;
  48. }
  49. return null;
  50. }
  51. /**
  52. * Replaces current history state(replaces the URL displayed by the browser).
  53. * @param {string} newUrl the URL string which is to be displayed by the browser
  54. * to the user.
  55. */
  56. function replaceHistoryState (newUrl) {
  57. if (window.history
  58. && typeof window.history.replaceState === 'function') {
  59. window.history.replaceState({}, document.title, newUrl);
  60. }
  61. }
  62. /**
  63. * Builds and returns the room name.
  64. */
  65. function buildRoomName () {
  66. let roomName = getRoomName();
  67. if(!roomName) {
  68. let word = generateRoomWithoutSeparator();
  69. roomName = word.toLowerCase();
  70. let historyURL = window.location.href + word;
  71. //Trying to push state with current URL + roomName
  72. pushHistoryState(word, historyURL);
  73. }
  74. return roomName;
  75. }
  76. /**
  77. * Adjusts the logging levels.
  78. * @private
  79. */
  80. function configureLoggingLevels () {
  81. // NOTE The library Logger is separated from the app loggers, so the levels
  82. // have to be set in two places
  83. // Set default logging level
  84. const defaultLogLevel
  85. = loggingConfig.defaultLogLevel || JitsiMeetJS.logLevels.TRACE;
  86. Logger.setLogLevel(defaultLogLevel);
  87. JitsiMeetJS.setLogLevel(defaultLogLevel);
  88. // NOTE console was used on purpose here to go around the logging
  89. // and always print the default logging level to the console
  90. console.info("Default logging level set to: " + defaultLogLevel);
  91. // Set log level for each logger
  92. if (loggingConfig) {
  93. Object.keys(loggingConfig).forEach(function(loggerName) {
  94. if ('defaultLogLevel' !== loggerName) {
  95. const level = loggingConfig[loggerName];
  96. Logger.setLogLevelById(level, loggerName);
  97. JitsiMeetJS.setLogLevelById(level, loggerName);
  98. }
  99. });
  100. }
  101. }
  102. const APP = {
  103. // Used by do_external_connect.js if we receive the attach data after
  104. // connect was already executed. status property can be "initialized",
  105. // "ready" or "connecting". We are interested in "ready" status only which
  106. // means that connect was executed but we have to wait for the attach data.
  107. // In status "ready" handler property will be set to a function that will
  108. // finish the connect process when the attach data or error is received.
  109. connect: {
  110. status: "initialized",
  111. handler: null
  112. },
  113. // Used for automated performance tests
  114. connectionTimes: {
  115. "index.loaded": window.indexLoadedTime
  116. },
  117. UI,
  118. settings,
  119. conference,
  120. translation,
  121. /**
  122. * The log collector which captures JS console logs for this app.
  123. * @type {LogCollector}
  124. */
  125. logCollector: null,
  126. /**
  127. * Indicates if the log collector has been started (it will not be started
  128. * if the welcome page is displayed).
  129. */
  130. logCollectorStarted : false,
  131. /**
  132. * After the APP has been initialized provides utility methods for dealing
  133. * with the conference room URL(address).
  134. * @type ConferenceUrl
  135. */
  136. ConferenceUrl : null,
  137. connection: null,
  138. API,
  139. init () {
  140. this.initLogging();
  141. this.keyboardshortcut =
  142. require("./modules/keyboardshortcut/keyboardshortcut");
  143. this.configFetch = require("./modules/config/HttpConfigFetch");
  144. this.tokenData = getTokenData();
  145. },
  146. initLogging () {
  147. // Adjust logging level
  148. configureLoggingLevels();
  149. // Create the LogCollector and register it as the global log transport.
  150. // It is done early to capture as much logs as possible. Captured logs
  151. // will be cached, before the JitsiMeetLogStorage gets ready (statistics
  152. // module is initialized).
  153. if (!this.logCollector && !loggingConfig.disableLogCollector) {
  154. this.logCollector = new LogCollector(new JitsiMeetLogStorage());
  155. Logger.addGlobalTransport(this.logCollector);
  156. JitsiMeetJS.addGlobalLogTransport(this.logCollector);
  157. }
  158. }
  159. };
  160. /**
  161. * If JWT token data it will be used for local user settings
  162. */
  163. function setTokenData() {
  164. let localUser = APP.tokenData.caller;
  165. if(localUser) {
  166. APP.settings.setEmail((localUser.getEmail() || "").trim(), true);
  167. APP.settings.setAvatarUrl((localUser.getAvatarUrl() || "").trim());
  168. APP.settings.setDisplayName((localUser.getName() || "").trim(), true);
  169. }
  170. }
  171. function init() {
  172. setTokenData();
  173. // Initialize the conference URL handler
  174. APP.ConferenceUrl = new ConferenceUrl(window.location);
  175. // Clean up the URL displayed by the browser
  176. replaceHistoryState(APP.ConferenceUrl.getInviteUrl());
  177. // TODO The execution of the mobile app starts from react/index.native.js.
  178. // Similarly, the execution of the Web app should start from
  179. // react/index.web.js for the sake of consistency and ease of understanding.
  180. // Temporarily though because we are at the beginning of introducing React
  181. // into the Web app, allow the execution of the Web app to start from app.js
  182. // in order to reduce the complexity of the beginning step.
  183. require('./react');
  184. const isUIReady = APP.UI.start();
  185. if (isUIReady) {
  186. APP.conference.init({roomName: buildRoomName()}).then(() => {
  187. if (APP.logCollector) {
  188. // Start the LogCollector's periodic "store logs" task only if
  189. // we're in the conference and not on the welcome page. This is
  190. // determined by the value of "isUIReady" const above.
  191. APP.logCollector.start();
  192. APP.logCollectorStarted = true;
  193. // Make an attempt to flush in case a lot of logs have been
  194. // cached, before the collector was started.
  195. APP.logCollector.flush();
  196. // This event listener will flush the logs, before
  197. // the statistics module (CallStats) is stopped.
  198. //
  199. // NOTE The LogCollector is not stopped, because this event can
  200. // be triggered multiple times during single conference
  201. // (whenever statistics module is stopped). That includes
  202. // the case when Jicofo terminates the single person left in the
  203. // room. It will then restart the media session when someone
  204. // eventually join the room which will start the stats again.
  205. APP.conference.addConferenceListener(
  206. ConferenceEvents.BEFORE_STATISTICS_DISPOSED,
  207. () => {
  208. if (APP.logCollector) {
  209. APP.logCollector.flush();
  210. }
  211. }
  212. );
  213. }
  214. APP.UI.initConference();
  215. APP.UI.addListener(UIEvents.LANG_CHANGED, language => {
  216. APP.translation.setLanguage(language);
  217. APP.settings.setLanguage(language);
  218. });
  219. APP.keyboardshortcut.init();
  220. }).catch(err => {
  221. APP.UI.hideRingOverLay();
  222. APP.API.notifyConferenceLeft(APP.conference.roomName);
  223. logger.error(err);
  224. });
  225. }
  226. }
  227. /**
  228. * If we have an HTTP endpoint for getting config.json configured we're going to
  229. * read it and override properties from config.js and interfaceConfig.js.
  230. * If there is no endpoint we'll just continue with initialization.
  231. * Keep in mind that if the endpoint has been configured and we fail to obtain
  232. * the config for any reason then the conference won't start and error message
  233. * will be displayed to the user.
  234. */
  235. function obtainConfigAndInit() {
  236. let roomName = APP.conference.roomName;
  237. if (config.configLocation) {
  238. APP.configFetch.obtainConfig(
  239. config.configLocation, roomName,
  240. // Get config result callback
  241. function(success, error) {
  242. if (success) {
  243. var now = APP.connectionTimes["configuration.fetched"] =
  244. window.performance.now();
  245. logger.log("(TIME) configuration fetched:\t", now);
  246. init();
  247. } else {
  248. // Show obtain config error,
  249. // pass the error object for report
  250. APP.UI.messageHandler.openReportDialog(
  251. null, "dialog.connectError", error);
  252. }
  253. });
  254. } else {
  255. require("./modules/config/BoshAddressChoice").chooseAddress(
  256. config, roomName);
  257. init();
  258. }
  259. }
  260. $(document).ready(function () {
  261. var now = APP.connectionTimes["document.ready"] = window.performance.now();
  262. logger.log("(TIME) document ready:\t", now);
  263. URLProcessor.setConfigParametersFromUrl();
  264. APP.init();
  265. APP.translation.init(settings.getLanguage());
  266. APP.API.init(APP.tokenData.externalAPISettings);
  267. obtainConfigAndInit();
  268. });
  269. $(window).bind('beforeunload', function () {
  270. // Stop the LogCollector
  271. if (APP.logCollectorStarted) {
  272. APP.logCollector.stop();
  273. APP.logCollectorStarted = false;
  274. }
  275. APP.API.dispose();
  276. });
  277. module.exports = APP;