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.

Recording.js 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /* global APP, $, config, interfaceConfig */
  2. /*
  3. * Copyright @ 2015 Atlassian Pty Ltd
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. import UIEvents from "../../../service/UI/UIEvents";
  18. import UIUtil from '../util/UIUtil';
  19. /**
  20. * Recording.
  21. */
  22. let recordingToaster = null;
  23. function _isRecordingButtonEnabled() {
  24. return interfaceConfig.TOOLBAR_BUTTONS.indexOf("recording") !== -1
  25. && config.enableRecording;
  26. }
  27. /**
  28. * Request live stream token from the user.
  29. * @returns {Promise}
  30. */
  31. function _requestLiveStreamId() {
  32. let msg = APP.translation.generateTranslationHTML("dialog.liveStreaming");
  33. let token = APP.translation.translateString("dialog.streamKey");
  34. return new Promise(function (resolve, reject) {
  35. APP.UI.messageHandler.openTwoButtonDialog(
  36. null, null, null,
  37. `<h2>${msg}</h2>
  38. <input name="streamId" type="text"
  39. data-i18n="[placeholder]dialog.streamKey"
  40. placeholder="${token}" autofocus>`,
  41. false, "dialog.startLiveStreaming",
  42. function (e, v, m, f) {
  43. if (v && f.streamId) {
  44. resolve(UIUtil.escapeHtml(f.streamId));
  45. } else {
  46. reject();
  47. }
  48. },
  49. null,
  50. function () { },
  51. ':input:first'
  52. );
  53. });
  54. }
  55. /**
  56. * Request recording token from the user.
  57. * @returns {Promise}
  58. */
  59. function _requestRecordingToken () {
  60. let msg = APP.translation.generateTranslationHTML("dialog.recordingToken");
  61. let token = APP.translation.translateString("dialog.token");
  62. return new Promise(function (resolve, reject) {
  63. APP.UI.messageHandler.openTwoButtonDialog(
  64. null, null, null,
  65. `<h2>${msg}</h2>
  66. <input name="recordingToken" type="text"
  67. data-i18n="[placeholder]dialog.token"
  68. placeholder="${token}" autofocus>`,
  69. false, "dialog.Save",
  70. function (e, v, m, f) {
  71. if (v && f.recordingToken) {
  72. resolve(UIUtil.escapeHtml(f.recordingToken));
  73. } else {
  74. reject();
  75. }
  76. },
  77. null,
  78. function () { },
  79. ':input:first'
  80. );
  81. });
  82. }
  83. function _showStopRecordingPrompt (recordingType) {
  84. var title;
  85. var message;
  86. var buttonKey;
  87. if (recordingType === "jibri") {
  88. title = "dialog.liveStreaming";
  89. message = "dialog.stopStreamingWarning";
  90. buttonKey = "dialog.stopLiveStreaming";
  91. }
  92. else {
  93. title = "dialog.recording";
  94. message = "dialog.stopRecordingWarning";
  95. buttonKey = "dialog.stopRecording";
  96. }
  97. return new Promise(function (resolve, reject) {
  98. APP.UI.messageHandler.openTwoButtonDialog(
  99. title,
  100. null,
  101. message,
  102. null,
  103. false,
  104. buttonKey,
  105. function(e,v,m,f) {
  106. if (v) {
  107. resolve();
  108. } else {
  109. reject();
  110. }
  111. }
  112. );
  113. });
  114. }
  115. function moveToCorner(selector, move) {
  116. let moveToCornerClass = "moveToCorner";
  117. if (move && !selector.hasClass(moveToCornerClass))
  118. selector.addClass(moveToCornerClass);
  119. else
  120. selector.removeClass(moveToCornerClass);
  121. }
  122. var Recording = {
  123. /**
  124. * Initializes the recording UI.
  125. */
  126. init (emitter, recordingType) {
  127. this.eventEmitter = emitter;
  128. this.initRecordingButton(recordingType);
  129. },
  130. initRecordingButton(recordingType) {
  131. let selector = $('#toolbar_button_record');
  132. if (recordingType === 'jibri') {
  133. this.baseClass = "fa fa-play-circle";
  134. this.recordingOnKey = "liveStreaming.on";
  135. this.recordingOffKey = "liveStreaming.off";
  136. this.recordingPendingKey = "liveStreaming.pending";
  137. this.failedToStartKey = "liveStreaming.failedToStart";
  138. }
  139. else {
  140. this.baseClass = "icon-recEnable";
  141. this.recordingOnKey = "recording.on";
  142. this.recordingOffKey = "recording.off";
  143. this.recordingPendingKey = "recording.pending";
  144. this.failedToStartKey = "recording.failedToStart";
  145. }
  146. selector.addClass(this.baseClass);
  147. var self = this;
  148. selector.click(function () {
  149. console.log("BUTTON CLICKED", self.currentState);
  150. switch (self.currentState) {
  151. case "on": {
  152. _showStopRecordingPrompt(recordingType).then(() =>
  153. self.eventEmitter.emit(UIEvents.RECORDING_TOGGLED));
  154. }
  155. break;
  156. case "available":
  157. case "off": {
  158. if (recordingType === 'jibri')
  159. _requestLiveStreamId().then((streamId) => {
  160. self.eventEmitter.emit( UIEvents.RECORDING_TOGGLED,
  161. {streamId: streamId});
  162. });
  163. else {
  164. if (self.predefinedToken) {
  165. self.eventEmitter.emit( UIEvents.RECORDING_TOGGLED,
  166. {token: self.predefinedToken});
  167. return;
  168. }
  169. _requestRecordingToken().then((token) => {
  170. self.eventEmitter.emit( UIEvents.RECORDING_TOGGLED,
  171. {token: token});
  172. });
  173. }
  174. }
  175. break;
  176. default: {
  177. APP.UI.messageHandler.openMessageDialog(
  178. "dialog.liveStreaming",
  179. "liveStreaming.unavailable"
  180. );
  181. }
  182. }
  183. });
  184. },
  185. // Shows or hides the 'recording' button.
  186. showRecordingButton (show) {
  187. if (_isRecordingButtonEnabled() && show) {
  188. $('#toolbar_button_record').css({display: "inline-block"});
  189. } else {
  190. $('#toolbar_button_record').css({display: "none"});
  191. }
  192. },
  193. updateRecordingState(recordingState) {
  194. // If there's no state change, we ignore the update.
  195. if (this.currentState === recordingState)
  196. return;
  197. this.setRecordingButtonState(recordingState);
  198. },
  199. // Sets the state of the recording button
  200. setRecordingButtonState (recordingState) {
  201. let buttonSelector = $('#toolbar_button_record');
  202. let labelSelector = $('#recordingLabel');
  203. // TODO: handle recording state=available
  204. if (recordingState === 'on') {
  205. buttonSelector.removeClass(this.baseClass);
  206. buttonSelector.addClass(this.baseClass + " active");
  207. labelSelector.attr("data-i18n", this.recordingOnKey);
  208. moveToCorner(labelSelector, true, 3000);
  209. labelSelector
  210. .text(APP.translation.translateString(this.recordingOnKey));
  211. } else if (recordingState === 'off'
  212. || recordingState === 'unavailable') {
  213. // We don't want to do any changes if this is
  214. // an availability change.
  215. if (this.currentState === "available"
  216. || this.currentState === "unavailable")
  217. return;
  218. buttonSelector.removeClass(this.baseClass + " active");
  219. buttonSelector.addClass(this.baseClass);
  220. moveToCorner(labelSelector, false);
  221. let messageKey;
  222. if (this.currentState === "pending")
  223. messageKey = this.failedToStartKey;
  224. else
  225. messageKey = this.recordingOffKey;
  226. labelSelector.attr("data-i18n", messageKey);
  227. labelSelector.text(APP.translation.translateString(messageKey));
  228. setTimeout(function(){
  229. $('#recordingLabel').css({display: "none"});
  230. }, 5000);
  231. }
  232. else if (recordingState === 'pending') {
  233. buttonSelector.removeClass(this.baseClass + " active");
  234. buttonSelector.addClass(this.baseClass);
  235. moveToCorner(labelSelector, false);
  236. labelSelector
  237. .attr("data-i18n", this.recordingPendingKey);
  238. labelSelector
  239. .text(APP.translation.translateString(
  240. this.recordingPendingKey));
  241. }
  242. this.currentState = recordingState;
  243. if (!labelSelector.is(":visible"))
  244. labelSelector.css({display: "inline-block"});
  245. },
  246. // checks whether recording is enabled and whether we have params
  247. // to start automatically recording
  248. checkAutoRecord () {
  249. if (_isRecordingButtonEnabled && config.autoRecord) {
  250. this.predefinedToken = UIUtil.escapeHtml(config.autoRecordToken);
  251. this.eventEmitter.emit(UIEvents.RECORDING_TOGGLED,
  252. this.predefinedToken);
  253. }
  254. }
  255. };
  256. export default Recording;