Commit 82b23e56 authored by Robert Knight's avatar Robert Knight

Add shortcut to toggle highlight visiblity from the guest frame

This provides a convenient way to avoid the distraction of highlights.  This is
particularly useful for screen reader users to avoid the noise of "annotation
start"/"annotation end" announcements when reading through a piece of text that
has been heavily annotated.
parent 5ff51657
import { ListenerCollection } from '../shared/listener-collection';
import { PortFinder, PortRPC } from '../shared/messaging';
import { generateHexString } from '../shared/random';
import { matchShortcut } from '../shared/shortcut';
import { Adder } from './adder';
import { TextRange } from './anchoring/text-range';
......@@ -296,6 +297,10 @@ export class Guest {
}
});
this._listeners.add(this.element, 'keydown', event => {
this._handleShortcut(event);
});
this._listeners.add(window, 'resize', () => this._repositionAdder());
}
......@@ -427,7 +432,7 @@ export class Guest {
this._sidebarRPC.on(
'setHighlightsVisible',
/** @param {boolean} showHighlights */ showHighlights => {
this.setHighlightsVisible(showHighlights);
this.setHighlightsVisible(showHighlights, false /* notifyHost */);
}
);
......@@ -766,10 +771,20 @@ export class Guest {
* Set whether highlights are visible in the document or not.
*
* @param {boolean} visible
* @param {boolean} notifyHost - Whether to notify the host frame about this
* change. This should be true unless the request to change highlight
* visibility is coming from the host frame.
*/
setHighlightsVisible(visible) {
setHighlightsVisible(visible, notifyHost = true) {
setHighlightsVisible(this.element, visible);
this._highlightsVisible = visible;
if (notifyHost) {
this._hostRPC.call('highlightsVisibleChanged', visible);
}
}
get highlightsVisible() {
return this._highlightsVisible;
}
/**
......@@ -801,4 +816,15 @@ export class Guest {
get hoveredAnnotationTags() {
return this._hoveredAnnotations;
}
/**
* Handle a potential shortcut trigger.
*
* @param {KeyboardEvent} event
*/
_handleShortcut(event) {
if (matchShortcut(event, 'Ctrl+Shift+H')) {
this.setHighlightsVisible(!this._highlightsVisible);
}
}
}
......@@ -295,6 +295,14 @@ export class Sidebar {
.forEach(rpc => rpc.call('clearSelection'));
});
guestRPC.on(
'highlightsVisibleChanged',
/** @param {boolean} visible */
visible => {
this.setHighlightsVisible(visible);
}
);
// The listener will do nothing if the sidebar doesn't have a bucket bar
// (clean theme)
const bucketBar = this.bucketBar;
......
......@@ -1414,4 +1414,32 @@ describe('Guest', () => {
assert.isTrue(guest.sideBySideActive);
});
});
describe('keyboard shortcuts', () => {
it('toggles highlights when shortcut is pressed', () => {
const guest = createGuest();
guest.setHighlightsVisible(true, false /* notifyHost */);
assert.equal(guest.highlightsVisible, true);
guest.element.dispatchEvent(
new KeyboardEvent('keydown', {
ctrlKey: true,
shiftKey: true,
key: 'h',
})
);
assert.equal(guest.highlightsVisible, false);
assert.calledWith(hostRPC().call, 'highlightsVisibleChanged', false);
guest.element.dispatchEvent(
new KeyboardEvent('keydown', {
ctrlKey: true,
shiftKey: true,
key: 'h',
})
);
assert.equal(guest.highlightsVisible, true);
assert.calledWith(hostRPC().call, 'highlightsVisibleChanged', true);
});
});
});
......@@ -318,6 +318,18 @@ describe('Sidebar', () => {
assert.neverCalledWith(guestRPC(1).call, 'clearSelection');
assert.calledWith(guestRPC(2).call, 'clearSelection');
});
it('updates state of highlights-visible button when state is changed in guest', () => {
const sidebar = createSidebar();
connectGuest(sidebar);
assert.isFalse(fakeToolbar.highlightsVisible);
emitGuestEvent('highlightsVisibleChanged', true);
assert.isTrue(fakeToolbar.highlightsVisible);
emitGuestEvent('highlightsVisibleChanged', false);
assert.isFalse(fakeToolbar.highlightsVisible);
});
});
describe('events from sidebar frame', () => {
......
......@@ -16,7 +16,13 @@ export type GuestToHostEvent =
/**
* The guest informs the host that the anchors have been changed in the main annotatable frame.
*/
| 'anchorsChanged';
| 'anchorsChanged'
/**
* Visibility of highlights was toggled from the guest frame (it can also be
* toggled from the host frame).
*/
| 'highlightsVisibleChanged';
/**
* Events that the guest sends to the sidebar
......
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