Commit df10f49e authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Add customizable side-by-side mode to HTMLIntegration

parent 6aeeed8c
...@@ -5,6 +5,7 @@ import type { ...@@ -5,6 +5,7 @@ import type {
FeatureFlags, FeatureFlags,
Integration, Integration,
SidebarLayout, SidebarLayout,
SideBySideOptions,
} from '../../types/annotator'; } from '../../types/annotator';
import type { Selector } from '../../types/api'; import type { Selector } from '../../types/api';
import { anchor, describe } from '../anchoring/html'; import { anchor, describe } from '../anchoring/html';
...@@ -36,8 +37,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration { ...@@ -36,8 +37,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration {
private _htmlMeta: HTMLMetadata; private _htmlMeta: HTMLMetadata;
private _prevURI: string; private _prevURI: string;
/** Whether to attempt to resize the document to fit alongside sidebar. */ /** Controls how we resize the document to fit alongside sidebar. */
private _sideBySideEnabled: boolean; private _sideBySideOptions: SideBySideOptions;
private _sideBySideFlagEnabled: boolean;
/** /**
* Whether the document is currently being resized to fit alongside an * Whether the document is currently being resized to fit alongside an
...@@ -53,9 +55,11 @@ export class HTMLIntegration extends TinyEmitter implements Integration { ...@@ -53,9 +55,11 @@ export class HTMLIntegration extends TinyEmitter implements Integration {
constructor({ constructor({
features, features,
container = document.body, container = document.body,
sideBySideOptions,
}: { }: {
features: FeatureFlags; features: FeatureFlags;
container?: HTMLElement; container?: HTMLElement;
sideBySideOptions?: SideBySideOptions;
}) { }) {
super(); super();
...@@ -65,7 +69,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration { ...@@ -65,7 +69,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration {
this._htmlMeta = new HTMLMetadata(); this._htmlMeta = new HTMLMetadata();
this._prevURI = this._htmlMeta.uri(); this._prevURI = this._htmlMeta.uri();
this._sideBySideEnabled = this.features.flagEnabled('html_side_by_side'); this._sideBySideFlagEnabled =
this.features.flagEnabled('html_side_by_side');
this._sideBySideOptions = sideBySideOptions ?? { mode: 'auto' };
this._sideBySideActive = false; this._sideBySideActive = false;
this._lastLayout = null; this._lastLayout = null;
...@@ -92,9 +98,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration { ...@@ -92,9 +98,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration {
}); });
this._flagsChanged = () => { this._flagsChanged = () => {
const sideBySide = features.flagEnabled('html_side_by_side'); const sideBySideEnabled = features.flagEnabled('html_side_by_side');
if (sideBySide !== this._sideBySideEnabled) { if (sideBySideEnabled !== this._sideBySideFlagEnabled) {
this._sideBySideEnabled = sideBySide; this._sideBySideFlagEnabled = sideBySideEnabled;
// `fitSideBySide` is normally called by Guest when the sidebar layout // `fitSideBySide` is normally called by Guest when the sidebar layout
// changes. When the feature flag changes, we need to re-run the method. // changes. When the feature flag changes, we need to re-run the method.
...@@ -156,7 +162,8 @@ export class HTMLIntegration extends TinyEmitter implements Integration { ...@@ -156,7 +162,8 @@ export class HTMLIntegration extends TinyEmitter implements Integration {
const maximumWidthToFit = window.innerWidth - layout.width; const maximumWidthToFit = window.innerWidth - layout.width;
const active = const active =
this._sideBySideEnabled && this._sideBySideFlagEnabled &&
this._sideBySideOptions.mode === 'auto' &&
layout.expanded && layout.expanded &&
maximumWidthToFit >= MIN_HTML_WIDTH; maximumWidthToFit >= MIN_HTML_WIDTH;
......
...@@ -64,8 +64,8 @@ describe('HTMLIntegration', () => { ...@@ -64,8 +64,8 @@ describe('HTMLIntegration', () => {
$imports.$restore(); $imports.$restore();
}); });
function createIntegration() { function createIntegration(sideBySideOptions) {
return new HTMLIntegration({ features }); return new HTMLIntegration({ features, sideBySideOptions });
} }
it('implements `anchor` and `destroy` using HTML anchoring', async () => { it('implements `anchor` and `destroy` using HTML anchoring', async () => {
...@@ -380,6 +380,18 @@ describe('HTMLIntegration', () => { ...@@ -380,6 +380,18 @@ describe('HTMLIntegration', () => {
features.update({ html_side_by_side: false }); features.update({ html_side_by_side: false });
assert.isFalse(isSideBySideActive()); assert.isFalse(isSideBySideActive());
}); });
it('manual side-by-side is not changed by enabled feature flag', () => {
features.update({ html_side_by_side: true });
const integration = createIntegration({ mode: 'manual' });
integration.fitSideBySide({ expanded: true, width: sidebarWidth });
assert.isFalse(isSideBySideActive());
// Even if the feature flag is enabled, side-by-side stays disabled/manual
features.update({ html_side_by_side: true });
assert.isFalse(isSideBySideActive());
});
}); });
describe('#getMetadata', () => { describe('#getMetadata', () => {
......
...@@ -336,3 +336,16 @@ export type DocumentInfo = { ...@@ -336,3 +336,16 @@ export type DocumentInfo = {
*/ */
persistent: boolean; persistent: boolean;
}; };
/**
* `auto`: The client will decide if side-by-side is enabled. If enabled, it
* will apply some heuristics to determine how the content is affected.
* This is default value.
* `manual`: The host app wants to manually take full control of side-by-side,
* effectively disabling the logic in client.
*/
export type SideBySideMode = 'auto' | 'manual';
export type SideBySideOptions = {
mode: SideBySideMode;
};
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