Skip to content
This repository has been archived by the owner on Jan 18, 2023. It is now read-only.

#50 - Update the view when <video> elements are added or removed from the DOM (or when it's style or any parent style changes) #59

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions src/js/OT.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# TB.upgradeSystemRequirements()

window.OT =
timeStreamCreated: {}
checkSystemRequirements: ->
return 1
initPublisher: (one, two) ->
Expand Down
111 changes: 102 additions & 9 deletions src/js/OTHelpers.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ replaceWithVideoStream = (element, streamId, properties) ->
newElement.setAttribute( "class", "OT_root #{typeClass}" )
newElement.setAttribute( "data-streamid", streamId )
newElement.setAttribute( "data-insertMode", properties.insertMode )
newElement.style.width = properties.width+"px"
newElement.style.height = properties.height+"px"
if (typeof properties.width is 'string')
newElement.style.width = properties.width
else
newElement.style.width = properties.width+"px"
if (typeof properties.height is 'string')
newElement.style.height = properties.height
else
newElement.style.height = properties.height+"px"
newElement.style.overflow = "hidden"
newElement.style['background-color'] = "#000000"
streamElements[ streamId ] = newElement
Expand Down Expand Up @@ -78,17 +84,31 @@ OTPublisherError = (error) ->

TBUpdateObjects = ()->
console.log("JS: Objects being updated in TBUpdateObjects")
objects = document.getElementsByClassName('OT_root')

ratios = TBGetScreenRatios()
updateObject = (e, time) ->
setTimeout(() ->
ratios = TBGetScreenRatios()
streamId = e.dataset.streamid
position = getPosition(e)
zIndex = TBGetZIndex(e)
if !e.TBPosition || position.top != e.TBPosition.top || position.left != e.TBPosition.left || position.width != e.TBPosition.width || position.height != e.TBPosition.height || zIndex != e.TBZIndex
console.log("JS: Object updated with sessionId " + streamId + " updated");
e.TBPosition = position;
e.TBZIndex = zIndex;
Cordova.exec(TBSuccess, TBError, OTPlugin, "updateView", [streamId, position.top, position.left, position.width, position.height, zIndex, ratios.widthRatio, ratios.heightRatio]);
, time)
return

objects = document.getElementsByClassName('OT_root')
for e in objects
console.log("JS: Object updated")
streamId = e.dataset.streamid
console.log("JS sessionId: " + streamId )
position = getPosition(e)
Cordova.exec(TBSuccess, TBError, OTPlugin, "updateView", [streamId, position.top, position.left, position.width, position.height, TBGetZIndex(e), ratios.widthRatio, ratios.heightRatio] )
time = 0
if typeof window.angular != "undefined" || typeof window.Ionic != "undefined"
if OT.timeStreamCreated[streamId]
time = performance.now() - OT.timeStreamCreated[streamId]
delete OT.timeStreamCreated[streamId]
updateObject(e, time)
return

TBGenerateDomHelper = ->
domId = "PubSub" + Date.now()
div = document.createElement('div')
Expand Down Expand Up @@ -129,5 +149,78 @@ OTReplacePublisher = ()->
break
return

OTObserveVideoContainer = (() ->
videoContainerObserver = new MutationObserver((mutations) ->
for mutation in mutations
if mutation.attributeName == 'style' || mutation.attributeName == 'class'
TBUpdateObjects();
)
return (videoContainer) ->
# If already observed, just update, else observe.
if(videoContainer._OTObserved)
TBUpdateObjects(videoContainer)
else
videoContainer._OTObserved = true;
videoContainerObserver.observe(videoContainer, {
# Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.
childList: false
# Set to true if mutations to target's attributes are to be observed.
attributes: true
# Set to true if mutations to target's data are to be observed.
characterData: false
# Set to true if mutations to not just target, but also target's descendants are to be observed.
subtree: true
# Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.
attributeOldValue: false
# Set to true if characterData is set to true and target's data before the mutation needs to be recorded.
characterDataOldValue: false
# Set to an array of attribute local names (without namespace) if not all attribute mutations need to be observed.
attributeFilter: ['style', 'class']
})
)()
OTDomObserver = new MutationObserver((mutations) ->
getVideoContainer = (node) ->
if typeof node.querySelector != 'function'
return

videoElement = node.querySelector('video')
if videoElement
while (videoElement = videoElement.parentNode) && !videoElement.hasAttribute('data-streamid')
continue
return videoElement
return false

checkNewNode = (node) ->
videoContainer = getVideoContainer(node)
if videoContainer
OTObserveVideoContainer(videoContainer)

checkRemovedNode = (node) ->
# Stand-in, if we want to trigger things in the future(like emitting events).
return

for mutation in mutations
# Check if its attributes that have changed(including children).
if mutation.type == 'attributes'
videoContainer = getVideoContainer(mutation.target)
if videoContainer
TBUpdateObjects()
continue

# Check if there has been addition or deletion of nodes.
if mutation.type != 'childList'
continue

# Check added nodes.
for node in mutation.addedNodes
checkNewNode(node)

# Check removed nodes.
for node in mutation.removedNodes
checkRemovedNode(node)

return
)

pdebug = (msg, data) ->
console.log "JS Lib: #{msg} - ", data
17 changes: 12 additions & 5 deletions src/js/OTPublisher.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class TBPublisher
constructor: (one, two) ->
@sanitizeInputs(one, two)
pdebug "creating publisher", {}
position = getPosition(@pubElement)
@position = getPosition(@pubElement)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this line changes position to this.position lines 36 and 37 should also change to position to this.position.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 37 and 37 have been changed to use the @position

name=""
publishAudio="true"
publishVideo="true"
Expand Down Expand Up @@ -58,15 +58,22 @@ class TBPublisher
width = DefaultWidth
height = DefaultHeight
replaceWithVideoStream(@pubElement, PublisherStreamId, {width:width, height:height, insertMode:insertMode})
position = getPosition(@pubElement)
TBUpdateObjects()
# If element is not yet in body, set it to 0 and then the observer will set it properly.
if !document.body.contains(@pubElement)
width = 0;
height = 0;
@position = getPosition(@pubElement)
OT.getHelper().eventing(@)
Cordova.exec(TBSuccess, TBError, OTPlugin, "initPublisher", [name, position.top, position.left, width, height, zIndex, publishAudio, publishVideo, cameraName, ratios.widthRatio, ratios.heightRatio, audioFallbackEnabled, audioBitrate, audioSource, videoSource, frameRate, resolution] )
Cordova.exec(TBSuccess, TBError, OTPlugin, "initPublisher", [name, @position.top, @position.left, width, height, zIndex, publishAudio, publishVideo, cameraName, ratios.widthRatio, ratios.heightRatio, audioFallbackEnabled, audioBitrate, audioSource, videoSource, frameRate, resolution] )
Cordova.exec(@eventReceived, TBSuccess, OTPlugin, "addEvent", ["publisherEvents"] )
setSession: (session) =>
@session = session
eventReceived: (response) =>
@[response.eventType](response.data)
pdebug "publisher event received", response
if typeof @[response.eventType] == "function"
@[response.eventType](response.data)
else
pdebug "No method found for EventType: '" + response.eventType + "'";
streamCreated: (event) =>
@stream = new TBStream( event.stream, @session.sessionConnected )
streamEvent = new TBEvent("streamCreated")
Expand Down
29 changes: 25 additions & 4 deletions src/js/OTSession.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ class TBSession
element = @publisher.pubElement
if(element)
@resetElement(element)
TBUpdateObjects()
return Cordova.exec(TBSuccess, TBError, OTPlugin, "unpublish", [] )
unsubscribe: (subscriber) ->
console.log("JS: Unsubscribe")
Expand All @@ -130,7 +129,6 @@ class TBSession
if(element)
@resetElement(element)
delete( streamElements[ elementId ] )
TBUpdateObjects()
return Cordova.exec(TBSuccess, TBError, OTPlugin, "unsubscribe", [subscriber.streamId] )

constructor: (@apiKey, @sessionId) ->
Expand Down Expand Up @@ -166,7 +164,11 @@ class TBSession
# event listeners
# todo - other events: connectionCreated, connectionDestroyed, signal?, streamPropertyChanged, signal:type?
eventReceived: (response) =>
@[response.eventType](response.data)
pdebug "session event received", response
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this line, we don't need to log these events

if typeof @[response.eventType] == "function"
@[response.eventType](response.data)
else
pdebug "No method found for EventType: '" + response.eventType + "'";
connectionCreated: (event) =>
connection = new TBConnection( event.connection )
connectionEvent = new TBEvent("connectionCreated")
Expand All @@ -183,12 +185,31 @@ class TBSession
delete( @connections[ connection.connectionId] )
return @
sessionConnected: (event) =>
pdebug "sessionConnectedHandler", event
OTDomObserver.observe(document, {
# Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.
childList: true
# Set to true if mutations to target's attributes are to be observed.
attributes: true
# Set to true if mutations to target's data are to be observed.
characterData: false
# Set to true if mutations to not just target, but also target's descendants are to be observed.
subtree: true
# Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.
attributeOldValue: false
# Set to true if characterData is set to true and target's data before the mutation needs to be recorded.
characterDataOldValue: false
# Set to an array of attribute local names (without namespace) if not all attribute mutations need to be observed.
attributeFilter: ['style', 'class']
})
@dispatchEvent(new TBEvent("sessionConnected"))
@connection = new TBConnection( event.connection )
@connections[event.connection.connectionId] = @connection
event = null
return @
sessionDisconnected: (event) =>
pdebug "sessionDisconnected event", event
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this, we do not need to log this event.

OTDomObserver.disconnect()
@alreadyPublishing = false
sessionDisconnectedEvent = new TBEvent("sessionDisconnected")
sessionDisconnectedEvent.reason = event.reason
Expand All @@ -206,6 +227,7 @@ class TBSession
streamCreated: (event) =>
stream = new TBStream( event.stream, @connections[event.stream.connectionId] )
@streams[ stream.streamId ] = stream
OT.timeStreamCreated[stream.streamId] = performance.now()
streamEvent = new TBEvent("streamCreated")
streamEvent.stream = stream
#streamEvent = new TBEvent( {stream: stream } )
Expand All @@ -223,7 +245,6 @@ class TBSession
if(element)
@resetElement(element)
delete( streamElements[ stream.streamId ] )
TBUpdateObjects()
delete( @streams[ stream.streamId ] )
return @
streamPropertyChanged: (event) ->
Expand Down
10 changes: 9 additions & 1 deletion src/js/OTSubscriber.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,22 @@ class TBSubscriber
width = DefaultWidth
height = DefaultHeight
obj = replaceWithVideoStream(@element, stream.streamId, {width:width, height:height, insertMode:insertMode})
# If element is not yet in body, set it to 0 and then the observer will set it properly.
if !document.body.contains(@element)
width = 0;
height = 0;
position = getPosition(@element)
ratios = TBGetScreenRatios()
OT.getHelper().eventing(@)
Cordova.exec(TBSuccess, TBError, OTPlugin, "subscribe", [stream.streamId, position.top, position.left, width, height, zIndex, subscribeToAudio, subscribeToVideo, ratios.widthRatio, ratios.heightRatio] )
Cordova.exec(@eventReceived, TBSuccess, OTPlugin, "addEvent", ["subscriberEvents"] )

eventReceived: (response) =>
@[response.eventType](response.data)
pdebug "subscriber event received", response
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this because this causes issues with stats events which are fired constantly. We don't need to log to the console each time we receive this event.

if typeof @[response.eventType] == "function"
@[response.eventType](response.data)
else
pdebug "No method found for EventType: '" + response.eventType + "'";
connected: (event) =>
streamEvent = new TBEvent("connected")
streamEvent.stream = event.streamId
Expand Down
Loading