Commit 3f4de98f authored by gergely-ujvari's avatar gergely-ujvari

Merge pull request #2066 from hypothesis/separete-host-service

Separate the Host service
parents cd9e1db1 7f6ff5b8
...@@ -17,23 +17,8 @@ class AnnotationUISync ...@@ -17,23 +17,8 @@ class AnnotationUISync
getAnnotationsByTags = (tags) -> getAnnotationsByTags = (tags) ->
tags.map(annotationSync.getAnnotationForTag, annotationSync) tags.map(annotationSync.getAnnotationForTag, annotationSync)
# Sends a message to the host frame only.
notifyHost = (message) ->
for {channel, window} in bridge.links when window is $window.parent
channel.notify(message)
break
# Send messages to host to hide/show sidebar iframe.
hide = notifyHost.bind(null, method: 'hideFrame')
show = notifyHost.bind(null, method: 'showFrame')
channelListeners = channelListeners =
back: hide
open: show
showEditor: show
showAnnotations: (ctx, tags=[]) -> showAnnotations: (ctx, tags=[]) ->
show()
annotations = getAnnotationsByTags(tags) annotations = getAnnotationsByTags(tags)
annotationUI.selectAnnotations(annotations) annotationUI.selectAnnotations(annotations)
focusAnnotations: (ctx, tags=[]) -> focusAnnotations: (ctx, tags=[]) ->
......
...@@ -82,6 +82,7 @@ configureTemplates = ['$sceDelegateProvider', ($sceDelegateProvider) -> ...@@ -82,6 +82,7 @@ configureTemplates = ['$sceDelegateProvider', ($sceDelegateProvider) ->
setupCrossFrame = ['crossframe', (crossframe) -> crossframe.connect()] setupCrossFrame = ['crossframe', (crossframe) -> crossframe.connect()]
setupHost = ['host', (host) -> ]
setupStreamer = [ setupStreamer = [
'$http', '$window', 'streamer' '$http', '$window', 'streamer'
...@@ -101,6 +102,7 @@ module = angular.module('h', imports) ...@@ -101,6 +102,7 @@ module = angular.module('h', imports)
unless mocha? # Crude method of detecting test environment. unless mocha? # Crude method of detecting test environment.
module.run(setupCrossFrame) module.run(setupCrossFrame)
module.run(setupStreamer) module.run(setupStreamer)
module.run(setupHost)
require('./vendor/annotator.auth.js') require('./vendor/annotator.auth.js')
require('./annotator/monkey') require('./annotator/monkey')
...@@ -125,6 +127,7 @@ require('./annotation-mapper-service') ...@@ -125,6 +127,7 @@ require('./annotation-mapper-service')
require('./annotation-ui-service') require('./annotation-ui-service')
require('./auth-service') require('./auth-service')
require('./cross-frame-service') require('./cross-frame-service')
require('./host-service')
require('./flash-service') require('./flash-service')
require('./permissions-service') require('./permissions-service')
require('./local-storage-service') require('./local-storage-service')
......
...@@ -258,11 +258,6 @@ module.exports = class Annotator.Guest extends Annotator ...@@ -258,11 +258,6 @@ module.exports = class Annotator.Guest extends Annotator
method: "updateAnnotations" method: "updateAnnotations"
params: (a.$$tag for a in annotations) params: (a.$$tag for a in annotations)
showEditor: (annotation) =>
@crossframe?.notify
method: "showEditor"
params: annotation.$$tag
focusAnnotations: (annotations) => focusAnnotations: (annotations) =>
@crossframe?.notify @crossframe?.notify
method: "focusAnnotations" method: "focusAnnotations"
...@@ -327,6 +322,7 @@ module.exports = class Annotator.Guest extends Annotator ...@@ -327,6 +322,7 @@ module.exports = class Annotator.Guest extends Annotator
this.toggleAnnotationSelection annotations this.toggleAnnotationSelection annotations
else else
# Tell sidebar to show the viewer for these annotations # Tell sidebar to show the viewer for these annotations
this.triggerShowFrame()
this.showAnnotations annotations this.showAnnotations annotations
# When Mousing over a highlight, tell the sidebar to focus the relevant annotations # When Mousing over a highlight, tell the sidebar to focus the relevant annotations
...@@ -370,9 +366,9 @@ module.exports = class Annotator.Guest extends Annotator ...@@ -370,9 +366,9 @@ module.exports = class Annotator.Guest extends Annotator
# Might not be needed anymore. Perhaps should just use on adderclick or perhaps new note? # Might not be needed anymore. Perhaps should just use on adderclick or perhaps new note?
addComment: -> addComment: ->
@adder.hide() @adder.hide()
annotation = this.setupAnnotation(this.createAnnotation()) this.setupAnnotation(this.createAnnotation())
Annotator.Util.getGlobal().getSelection().removeAllRanges() Annotator.Util.getGlobal().getSelection().removeAllRanges()
this.showEditor(annotation) this.triggerShowFrame()
# Open the sidebar # Open the sidebar
triggerShowFrame: -> triggerShowFrame: ->
...@@ -400,8 +396,8 @@ module.exports = class Annotator.Guest extends Annotator ...@@ -400,8 +396,8 @@ module.exports = class Annotator.Guest extends Annotator
switch event.target.dataset.action switch event.target.dataset.action
when 'highlight' when 'highlight'
this.setVisibleHighlights true this.setVisibleHighlights true
annotation = this.setupAnnotation(this.createHighlight()) this.setupAnnotation(this.createHighlight())
when 'comment' when 'comment'
annotation = this.setupAnnotation(this.createAnnotation()) this.setupAnnotation(this.createAnnotation())
this.showEditor(annotation) this.triggerShowFrame()
Annotator.Util.getGlobal().getSelection().removeAllRanges() Annotator.Util.getGlobal().getSelection().removeAllRanges()
###*
# @ngdoc service
# @name host
#
# @description
# The `host` service relays the instructions the sidebar needs to send
# to the host document. (As opposed to all guests)
# It uses the bridge service to talk to the host.
###
class HostService
this.inject = ['$window', 'bridge']
constructor: ( $window, bridge ) ->
# Sends a message to the host frame
@_notifyHost = (message) ->
for {channel, window} in bridge.links when window is $window.parent
channel.notify(message)
break
channelListeners =
back: => @hideSidebar()
open: => @showSidebar()
for own channel, listener of channelListeners
bridge.on(channel, listener)
# Tell the host to show the sidebar
showSidebar: => @_notifyHost method: 'showFrame'
# Tell the host to hide the sidebar
hideSidebar: => @_notifyHost method: 'hideFrame'
angular.module('h').service('host', HostService)
...@@ -28,11 +28,7 @@ describe 'AnnotationSync', -> ...@@ -28,11 +28,7 @@ describe 'AnnotationSync', ->
call: sandbox.stub() call: sandbox.stub()
notify: sandbox.stub() notify: sandbox.stub()
onConnect: sandbox.stub() onConnect: sandbox.stub()
links: [ links: []
{window: PARENT_WINDOW, channel: createChannel()}
{window: 'ANOTHER_WINDOW', channel: createChannel()}
{window: 'THIRD_WINDOW', channel: createChannel()}
]
# TODO: Fix this hack to remove pre-existing bound listeners. # TODO: Fix this hack to remove pre-existing bound listeners.
$rootScope.$$listeners = [] $rootScope.$$listeners = []
......
...@@ -71,56 +71,7 @@ describe 'AnnotationUISync', -> ...@@ -71,56 +71,7 @@ describe 'AnnotationUISync', ->
createAnnotationUISync() createAnnotationUISync()
assert.notCalled(channel.notify) assert.notCalled(channel.notify)
describe 'on "back" event', ->
it 'sends the "hideFrame" message to the host only', ->
createAnnotationUISync()
publish({method: 'back'})
assert.calledWith(fakeBridge.links[0].channel.notify, method: 'hideFrame')
assert.notCalled(fakeBridge.links[1].channel.notify)
assert.notCalled(fakeBridge.links[2].channel.notify)
it 'triggers a digest', ->
createAnnotationUISync()
publish({method: 'back'})
assert.called($digest)
describe 'on "open" event', ->
it 'sends the "showFrame" message to the host only', ->
createAnnotationUISync()
publish({method: 'open'})
assert.calledWith(fakeBridge.links[0].channel.notify, method: 'showFrame')
assert.notCalled(fakeBridge.links[1].channel.notify)
assert.notCalled(fakeBridge.links[2].channel.notify)
it 'triggers a digest', ->
createAnnotationUISync()
publish({method: 'open'})
assert.called($digest)
describe 'on "showEditor" event', ->
it 'sends the "showFrame" message to the host only', ->
createAnnotationUISync()
publish({method: 'showEditor'})
assert.calledWith(fakeBridge.links[0].channel.notify, method: 'showFrame')
assert.notCalled(fakeBridge.links[1].channel.notify)
assert.notCalled(fakeBridge.links[2].channel.notify)
it 'triggers a digest', ->
createAnnotationUISync()
publish({method: 'showEditor'})
assert.called($digest)
describe 'on "showAnnotations" event', -> describe 'on "showAnnotations" event', ->
it 'sends the "showFrame" message to the host only', ->
createAnnotationUISync()
publish({
method: 'showAnnotations',
params: ['tag1', 'tag2', 'tag3']
})
assert.calledWith(fakeBridge.links[0].channel.notify, method: 'showFrame')
assert.notCalled(fakeBridge.links[1].channel.notify)
assert.notCalled(fakeBridge.links[2].channel.notify)
it 'updates the annotationUI to include the shown annotations', -> it 'updates the annotationUI to include the shown annotations', ->
createAnnotationUISync() createAnnotationUISync()
publish({ publish({
......
{module, inject} = require('angular-mock')
assert = chai.assert
sinon.assert.expose assert, prefix: null
describe 'Host service', ->
sandbox = null
host = null
createChannel = -> notify: sandbox.stub()
fakeBridge = null
$digest = null
publish = null
PARENT_WINDOW = 'PARENT_WINDOW'
dumpListeners = null
before ->
require('../host-service')
beforeEach module('h')
beforeEach module ($provide) ->
sandbox = sinon.sandbox.create()
fakeWindow = parent: PARENT_WINDOW
listeners = {}
publish = ({method, params}) ->
listeners[method]('ctx', params)
fakeBridge =
ls: listeners
on: sandbox.spy (method, fn) -> listeners[method] = fn
notify: sandbox.stub()
onConnect: sandbox.stub()
links: [
{window: PARENT_WINDOW, channel: createChannel()}
{window: 'ANOTHER_WINDOW', channel: createChannel()}
{window: 'THIRD_WINDOW', channel: createChannel()}
]
$provide.value 'bridge', fakeBridge
$provide.value '$window', fakeWindow
return
afterEach ->
sandbox.restore()
beforeEach inject ($rootScope, _host_) ->
host = _host_
$digest = sandbox.stub($rootScope, '$digest')
describe 'the public API', ->
describe 'showSidebar()', ->
it 'sends the "showFrame" message to the host only', ->
host.showSidebar()
assert.calledWith(fakeBridge.links[0].channel.notify, method: 'showFrame')
assert.notCalled(fakeBridge.links[1].channel.notify)
assert.notCalled(fakeBridge.links[2].channel.notify)
describe 'hideSidebar()', ->
it 'sends the "hideFrame" message to the host only', ->
host.hideSidebar()
assert.calledWith(fakeBridge.links[0].channel.notify, method: 'hideFrame')
assert.notCalled(fakeBridge.links[1].channel.notify)
assert.notCalled(fakeBridge.links[2].channel.notify)
describe 'reacting to the bridge', ->
describe 'on "back" event', ->
it 'triggers the hideSidebar() API', ->
sandbox.spy host, "hideSidebar"
publish method: 'back'
assert.called host.hideSidebar
describe 'on "open" event', ->
it 'triggers the showSidebar() API', ->
sandbox.spy host, "showSidebar"
publish method: 'open'
assert.called host.showSidebar
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment