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
102 changes: 95 additions & 7 deletions src/js/OTHelpers.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,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 +143,79 @@ 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']
})
)()
MutationObserver = MutationObserver || WebKitMutationObserver
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
21 changes: 14 additions & 7 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 All @@ -33,8 +33,8 @@ class TBPublisher
resolution = "640X480"
insertMode = "replace"
if @properties?
width = @properties.width ? position.width
height = @properties.height ? position.height
width = @properties.width ? @position.width
height = @properties.height ? @position.height
name = @properties.name ? ""
cameraName = @properties.cameraName ? "front"
audioFallbackEnabled = @properties.audioFallbackEnabled ? audioFallbackEnabled
Expand All @@ -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
27 changes: 23 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,10 @@ class TBSession
# event listeners
# todo - other events: connectionCreated, connectionDestroyed, signal?, streamPropertyChanged, signal:type?
eventReceived: (response) =>
@[response.eventType](response.data)
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 +184,30 @@ 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) =>
OTDomObserver.disconnect()
@alreadyPublishing = false
sessionDisconnectedEvent = new TBEvent("sessionDisconnected")
sessionDisconnectedEvent.reason = event.reason
Expand All @@ -206,6 +225,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 +243,6 @@ class TBSession
if(element)
@resetElement(element)
delete( streamElements[ stream.streamId ] )
TBUpdateObjects()
delete( @streams[ stream.streamId ] )
return @
streamPropertyChanged: (event) ->
Expand Down
9 changes: 8 additions & 1 deletion src/js/OTSubscriber.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,21 @@ 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)
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