|
|
@ -3,6 +3,7 @@ var RTCBrowserType = require("../../RTC/RTCBrowserType"); |
|
|
|
var UIUtil = require("../util/UIUtil"); |
|
|
|
var UIUtil = require("../util/UIUtil"); |
|
|
|
var UIEvents = require("../../../service/UI/UIEvents"); |
|
|
|
var UIEvents = require("../../../service/UI/UIEvents"); |
|
|
|
var xmpp = require("../../xmpp/xmpp"); |
|
|
|
var xmpp = require("../../xmpp/xmpp"); |
|
|
|
|
|
|
|
var ToolbarToggler = require("../toolbars/ToolbarToggler"); |
|
|
|
|
|
|
|
|
|
|
|
// FIXME: With Temasys we have to re-select everytime
|
|
|
|
// FIXME: With Temasys we have to re-select everytime
|
|
|
|
//var video = $('#largeVideo');
|
|
|
|
//var video = $('#largeVideo');
|
|
|
@ -12,9 +13,45 @@ var currentVideoHeight = null; |
|
|
|
// By default we use camera
|
|
|
|
// By default we use camera
|
|
|
|
var getVideoSize = getCameraVideoSize; |
|
|
|
var getVideoSize = getCameraVideoSize; |
|
|
|
var getVideoPosition = getCameraVideoPosition; |
|
|
|
var getVideoPosition = getCameraVideoPosition; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* The small video instance that is displayed in the large video |
|
|
|
|
|
|
|
* @type {SmallVideo} |
|
|
|
|
|
|
|
*/ |
|
|
|
var currentSmallVideo = null; |
|
|
|
var currentSmallVideo = null; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Indicates whether the large video is enabled. |
|
|
|
|
|
|
|
* @type {boolean} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
var isEnabled = true; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Current large video state. |
|
|
|
|
|
|
|
* Possible values - video, prezi or etherpad. |
|
|
|
|
|
|
|
* @type {string} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
var state = "video"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the html element associated with the passed state of large video |
|
|
|
|
|
|
|
* @param state the state. |
|
|
|
|
|
|
|
* @returns {JQuery|*|jQuery|HTMLElement} the container. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
function getContainerByState(state) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var selector = null; |
|
|
|
|
|
|
|
switch (state) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case "video": |
|
|
|
|
|
|
|
selector = "#largeVideo"; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case "etherpad": |
|
|
|
|
|
|
|
selector = "#etherpad>iframe"; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case "prezi": |
|
|
|
|
|
|
|
selector = "#presentation>iframe"; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return (selector !== null)? $(selector) : null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Sets the size and position of the given video element. |
|
|
|
* Sets the size and position of the given video element. |
|
|
@ -204,6 +241,10 @@ function updateActiveSpeakerAvatarSrc() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Change the video source of the large video. |
|
|
|
|
|
|
|
* @param isVisible |
|
|
|
|
|
|
|
*/ |
|
|
|
function changeVideo(isVisible) { |
|
|
|
function changeVideo(isVisible) { |
|
|
|
|
|
|
|
|
|
|
|
if (!currentSmallVideo) { |
|
|
|
if (!currentSmallVideo) { |
|
|
@ -248,11 +289,66 @@ function changeVideo(isVisible) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates the html elements for the large video. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
function createLargeVideoHTML() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var html = '<div id="largeVideoContainer" class="videocontainer">'; |
|
|
|
|
|
|
|
html += '<div id="presentation"></div>' + |
|
|
|
|
|
|
|
'<div id="etherpad"></div>' + |
|
|
|
|
|
|
|
'<a target="_new"><div class="watermark leftwatermark"></div></a>' + |
|
|
|
|
|
|
|
'<a target="_new"><div class="watermark rightwatermark"></div></a>' + |
|
|
|
|
|
|
|
'<a class="poweredby" href="http://jitsi.org" target="_new" >' + |
|
|
|
|
|
|
|
'<span data-i18n="poweredby"></span> jitsi.org' + |
|
|
|
|
|
|
|
'</a>'+ |
|
|
|
|
|
|
|
'<div id="activeSpeaker">' + |
|
|
|
|
|
|
|
'<img id="activeSpeakerAvatar" src=""/>' + |
|
|
|
|
|
|
|
'<canvas id="activeSpeakerAudioLevel"></canvas>' + |
|
|
|
|
|
|
|
'</div>' + |
|
|
|
|
|
|
|
'<video id="largeVideo" autoplay oncontextmenu="return false;"></video>'; |
|
|
|
|
|
|
|
html += '</div>'; |
|
|
|
|
|
|
|
$(html).prependTo("#videospace"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (interfaceConfig.SHOW_JITSI_WATERMARK) { |
|
|
|
|
|
|
|
var leftWatermarkDiv |
|
|
|
|
|
|
|
= $("#largeVideoContainer div[class='watermark leftwatermark']"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
leftWatermarkDiv.css({display: 'block'}); |
|
|
|
|
|
|
|
leftWatermarkDiv.parent().get(0).href |
|
|
|
|
|
|
|
= interfaceConfig.JITSI_WATERMARK_LINK; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (interfaceConfig.SHOW_BRAND_WATERMARK) { |
|
|
|
|
|
|
|
var rightWatermarkDiv |
|
|
|
|
|
|
|
= $("#largeVideoContainer div[class='watermark rightwatermark']"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rightWatermarkDiv.css({display: 'block'}); |
|
|
|
|
|
|
|
rightWatermarkDiv.parent().get(0).href |
|
|
|
|
|
|
|
= interfaceConfig.BRAND_WATERMARK_LINK; |
|
|
|
|
|
|
|
rightWatermarkDiv.get(0).style.backgroundImage |
|
|
|
|
|
|
|
= "url(images/rightwatermark.png)"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (interfaceConfig.SHOW_POWERED_BY) { |
|
|
|
|
|
|
|
$("#largeVideoContainer>a[class='poweredby']").css({display: 'block'}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!RTCBrowserType.isIExplorer()) { |
|
|
|
|
|
|
|
$('#largeVideo').volume = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var LargeVideo = { |
|
|
|
var LargeVideo = { |
|
|
|
|
|
|
|
|
|
|
|
init: function (VideoLayout, emitter) { |
|
|
|
init: function (VideoLayout, emitter) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
createLargeVideoHTML(); |
|
|
|
|
|
|
|
|
|
|
|
this.VideoLayout = VideoLayout; |
|
|
|
this.VideoLayout = VideoLayout; |
|
|
|
this.eventEmitter = emitter; |
|
|
|
this.eventEmitter = emitter; |
|
|
|
|
|
|
|
this.eventEmitter.emit(UIEvents.LARGEVIDEO_INIT); |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
// Listen for large video size updates
|
|
|
|
// Listen for large video size updates
|
|
|
|
var largeVideo = $('#largeVideo')[0]; |
|
|
|
var largeVideo = $('#largeVideo')[0]; |
|
|
@ -285,6 +381,8 @@ var LargeVideo = { |
|
|
|
* Updates the large video with the given new video source. |
|
|
|
* Updates the large video with the given new video source. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
updateLargeVideo: function (resourceJid, forceUpdate) { |
|
|
|
updateLargeVideo: function (resourceJid, forceUpdate) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
var newSmallVideo = this.VideoLayout.getSmallVideo(resourceJid); |
|
|
|
var newSmallVideo = this.VideoLayout.getSmallVideo(resourceJid); |
|
|
|
console.log('hover in ' + resourceJid + ', video: ', newSmallVideo); |
|
|
|
console.log('hover in ' + resourceJid + ', video: ', newSmallVideo); |
|
|
|
|
|
|
|
|
|
|
@ -324,6 +422,8 @@ var LargeVideo = { |
|
|
|
* Shows/hides the large video. |
|
|
|
* Shows/hides the large video. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
setLargeVideoVisible: function(isVisible) { |
|
|
|
setLargeVideoVisible: function(isVisible) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
if (isVisible) { |
|
|
|
if (isVisible) { |
|
|
|
$('#largeVideo').css({visibility: 'visible'}); |
|
|
|
$('#largeVideo').css({visibility: 'visible'}); |
|
|
|
$('.watermark').css({visibility: 'visible'}); |
|
|
|
$('.watermark').css({visibility: 'visible'}); |
|
|
@ -339,6 +439,8 @@ var LargeVideo = { |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
onVideoTypeChanged: function (jid) { |
|
|
|
onVideoTypeChanged: function (jid) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
var resourceJid = Strophe.getResourceFromJid(jid); |
|
|
|
var resourceJid = Strophe.getResourceFromJid(jid); |
|
|
|
if (LargeVideo.isCurrentlyOnLarge(resourceJid)) |
|
|
|
if (LargeVideo.isCurrentlyOnLarge(resourceJid)) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -360,6 +462,8 @@ var LargeVideo = { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
position: function (videoWidth, videoHeight, |
|
|
|
position: function (videoWidth, videoHeight, |
|
|
|
videoSpaceWidth, videoSpaceHeight, animate) { |
|
|
|
videoSpaceWidth, videoSpaceHeight, animate) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
if(!videoSpaceWidth) |
|
|
|
if(!videoSpaceWidth) |
|
|
|
videoSpaceWidth = $('#videospace').width(); |
|
|
|
videoSpaceWidth = $('#videospace').width(); |
|
|
|
if(!videoSpaceHeight) |
|
|
|
if(!videoSpaceHeight) |
|
|
@ -386,13 +490,9 @@ var LargeVideo = { |
|
|
|
largeVideoHeight, |
|
|
|
largeVideoHeight, |
|
|
|
horizontalIndent, verticalIndent, animate); |
|
|
|
horizontalIndent, verticalIndent, animate); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
isLargeVideoOnTop: function () { |
|
|
|
|
|
|
|
var Etherpad = require("../etherpad/Etherpad"); |
|
|
|
|
|
|
|
var Prezi = require("../prezi/Prezi"); |
|
|
|
|
|
|
|
return !Prezi.isPresentationVisible() && !Etherpad.isVisible(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
resize: function (animate, isVisible, completeFunction) { |
|
|
|
resize: function (animate, isVisible, completeFunction) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
var availableHeight = window.innerHeight; |
|
|
|
var availableHeight = window.innerHeight; |
|
|
|
var availableWidth = UIUtil.getAvailableVideoWidth(isVisible); |
|
|
|
var availableWidth = UIUtil.getAvailableVideoWidth(isVisible); |
|
|
|
|
|
|
|
|
|
|
@ -437,6 +537,8 @@ var LargeVideo = { |
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
resizeVideoAreaAnimated: function (isVisible, completeFunction) { |
|
|
|
resizeVideoAreaAnimated: function (isVisible, completeFunction) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
var size = this.resize(true, isVisible, completeFunction); |
|
|
|
var size = this.resize(true, isVisible, completeFunction); |
|
|
|
this.position(null, null, size[0], size[1], true); |
|
|
|
this.position(null, null, size[0], size[1], true); |
|
|
|
}, |
|
|
|
}, |
|
|
@ -444,22 +546,152 @@ var LargeVideo = { |
|
|
|
return currentSmallVideo ? currentSmallVideo.getResourceJid() : null; |
|
|
|
return currentSmallVideo ? currentSmallVideo.getResourceJid() : null; |
|
|
|
}, |
|
|
|
}, |
|
|
|
updateAvatar: function (resourceJid) { |
|
|
|
updateAvatar: function (resourceJid) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
if (resourceJid === this.getResourceJid()) { |
|
|
|
if (resourceJid === this.getResourceJid()) { |
|
|
|
updateActiveSpeakerAvatarSrc(); |
|
|
|
updateActiveSpeakerAvatarSrc(); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
showAvatar: function (resourceJid, show) { |
|
|
|
showAvatar: function (resourceJid, show) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
if(this.getResourceJid() === resourceJid |
|
|
|
if(this.getResourceJid() === resourceJid |
|
|
|
&& LargeVideo.isLargeVideoOnTop()) |
|
|
|
&& state === "video") |
|
|
|
{ |
|
|
|
{ |
|
|
|
$("#largeVideo").css("visibility", show ? "hidden" : "visible"); |
|
|
|
$("#largeVideo").css("visibility", show ? "hidden" : "visible"); |
|
|
|
$('#activeSpeaker').css("visibility", show ? "visible" : "hidden"); |
|
|
|
$('#activeSpeaker').css("visibility", show ? "visible" : "hidden"); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Disables the large video |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
disable: function () { |
|
|
|
|
|
|
|
isEnabled = false; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Enables the large video |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
enable: function () { |
|
|
|
|
|
|
|
isEnabled = true; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns true if the video is enabled. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
isEnabled: function () { |
|
|
|
|
|
|
|
return isEnabled; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Creates the iframe used by the etherpad |
|
|
|
|
|
|
|
* @param src the value for src attribute |
|
|
|
|
|
|
|
* @param onloadHandler handler executed when the iframe loads it content |
|
|
|
|
|
|
|
* @returns {HTMLElement} the iframe |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
createEtherpadIframe: function (src, onloadHandler) { |
|
|
|
|
|
|
|
if(!isEnabled) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var etherpadIFrame = document.createElement('iframe'); |
|
|
|
|
|
|
|
etherpadIFrame.src = src; |
|
|
|
|
|
|
|
etherpadIFrame.frameBorder = 0; |
|
|
|
|
|
|
|
etherpadIFrame.scrolling = "no"; |
|
|
|
|
|
|
|
etherpadIFrame.width = $('#largeVideoContainer').width() || 640; |
|
|
|
|
|
|
|
etherpadIFrame.height = $('#largeVideoContainer').height() || 480; |
|
|
|
|
|
|
|
etherpadIFrame.setAttribute('style', 'visibility: hidden;'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
document.getElementById('etherpad').appendChild(etherpadIFrame); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
etherpadIFrame.onload = onloadHandler; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return etherpadIFrame; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Changes the state of the large video. |
|
|
|
|
|
|
|
* Possible values - video, prezi, etherpad. |
|
|
|
|
|
|
|
* @param newState - the new state |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
setState: function (newState) { |
|
|
|
|
|
|
|
if(state === newState) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
var currentContainer = getContainerByState(state); |
|
|
|
|
|
|
|
if(!currentContainer) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var self = this; |
|
|
|
|
|
|
|
var oldState = state; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (newState) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case "etherpad": |
|
|
|
|
|
|
|
$('#activeSpeaker').css('visibility', 'hidden'); |
|
|
|
|
|
|
|
currentContainer.fadeOut(300, function () { |
|
|
|
|
|
|
|
if (oldState === "prezi") { |
|
|
|
|
|
|
|
currentContainer.css({opacity: '0'}); |
|
|
|
|
|
|
|
$('#reloadPresentation').css({display: 'none'}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
self.setLargeVideoVisible(false); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$('#etherpad>iframe').fadeIn(300, function () { |
|
|
|
|
|
|
|
document.body.style.background = '#eeeeee'; |
|
|
|
|
|
|
|
$('#etherpad>iframe').css({visibility: 'visible'}); |
|
|
|
|
|
|
|
$('#etherpad').css({zIndex: 2}); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case "prezi": |
|
|
|
|
|
|
|
var prezi = $('#presentation>iframe'); |
|
|
|
|
|
|
|
currentContainer.fadeOut(300, function() { |
|
|
|
|
|
|
|
document.body.style.background = 'black'; |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
prezi.fadeIn(300, function() { |
|
|
|
|
|
|
|
prezi.css({opacity:'1'}); |
|
|
|
|
|
|
|
ToolbarToggler.dockToolbar(true);//fix that
|
|
|
|
|
|
|
|
self.setLargeVideoVisible(false); |
|
|
|
|
|
|
|
$('#etherpad>iframe').css({visibility: 'hidden'}); |
|
|
|
|
|
|
|
$('#etherpad').css({zIndex: 0}); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
$('#activeSpeaker').css('visibility', 'hidden'); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "video": |
|
|
|
|
|
|
|
currentContainer.fadeOut(300, function () { |
|
|
|
|
|
|
|
$('#presentation>iframe').css({opacity:'0'}); |
|
|
|
|
|
|
|
$('#reloadPresentation').css({display:'none'}); |
|
|
|
|
|
|
|
$('#etherpad>iframe').css({visibility: 'hidden'}); |
|
|
|
|
|
|
|
$('#etherpad').css({zIndex: 0}); |
|
|
|
|
|
|
|
document.body.style.background = 'black'; |
|
|
|
|
|
|
|
ToolbarToggler.dockToolbar(false);//fix that
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
$('#largeVideo').fadeIn(300, function () { |
|
|
|
|
|
|
|
self.setLargeVideoVisible(true); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state = newState; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the current state of the large video. |
|
|
|
|
|
|
|
* @returns {string} the current state - video, prezi or etherpad. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
getState: function () { |
|
|
|
|
|
|
|
return state; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Sets hover handlers for the large video container div. |
|
|
|
|
|
|
|
* @param inHandler |
|
|
|
|
|
|
|
* @param outHandler |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
setHover: function(inHandler, outHandler) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$('#largeVideoContainer').hover(inHandler, outHandler); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = LargeVideo; |
|
|
|
module.exports = LargeVideo; |