From df10f49e59334011a6492594ab088fa25c3a0fd5 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Thu, 6 Jul 2023 09:49:41 +0200 Subject: [PATCH] Add customizable side-by-side mode to HTMLIntegration --- src/annotator/integrations/html.ts | 21 +++++++++++++------- src/annotator/integrations/test/html-test.js | 16 +++++++++++++-- src/types/annotator.ts | 13 ++++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/annotator/integrations/html.ts b/src/annotator/integrations/html.ts index e6c29a20e32..576e7d5f030 100644 --- a/src/annotator/integrations/html.ts +++ b/src/annotator/integrations/html.ts @@ -5,6 +5,7 @@ import type { FeatureFlags, Integration, SidebarLayout, + SideBySideOptions, } from '../../types/annotator'; import type { Selector } from '../../types/api'; import { anchor, describe } from '../anchoring/html'; @@ -36,8 +37,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration { private _htmlMeta: HTMLMetadata; private _prevURI: string; - /** Whether to attempt to resize the document to fit alongside sidebar. */ - private _sideBySideEnabled: boolean; + /** Controls how we resize the document to fit alongside sidebar. */ + private _sideBySideOptions: SideBySideOptions; + private _sideBySideFlagEnabled: boolean; /** * Whether the document is currently being resized to fit alongside an @@ -53,9 +55,11 @@ export class HTMLIntegration extends TinyEmitter implements Integration { constructor({ features, container = document.body, + sideBySideOptions, }: { features: FeatureFlags; container?: HTMLElement; + sideBySideOptions?: SideBySideOptions; }) { super(); @@ -65,7 +69,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration { this._htmlMeta = new HTMLMetadata(); 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._lastLayout = null; @@ -92,9 +98,9 @@ export class HTMLIntegration extends TinyEmitter implements Integration { }); this._flagsChanged = () => { - const sideBySide = features.flagEnabled('html_side_by_side'); - if (sideBySide !== this._sideBySideEnabled) { - this._sideBySideEnabled = sideBySide; + const sideBySideEnabled = features.flagEnabled('html_side_by_side'); + if (sideBySideEnabled !== this._sideBySideFlagEnabled) { + this._sideBySideFlagEnabled = sideBySideEnabled; // `fitSideBySide` is normally called by Guest when the sidebar layout // changes. When the feature flag changes, we need to re-run the method. @@ -156,7 +162,8 @@ export class HTMLIntegration extends TinyEmitter implements Integration { const maximumWidthToFit = window.innerWidth - layout.width; const active = - this._sideBySideEnabled && + this._sideBySideFlagEnabled && + this._sideBySideOptions.mode === 'auto' && layout.expanded && maximumWidthToFit >= MIN_HTML_WIDTH; diff --git a/src/annotator/integrations/test/html-test.js b/src/annotator/integrations/test/html-test.js index 54ba8e567d1..405bbf67adc 100644 --- a/src/annotator/integrations/test/html-test.js +++ b/src/annotator/integrations/test/html-test.js @@ -64,8 +64,8 @@ describe('HTMLIntegration', () => { $imports.$restore(); }); - function createIntegration() { - return new HTMLIntegration({ features }); + function createIntegration(sideBySideOptions) { + return new HTMLIntegration({ features, sideBySideOptions }); } it('implements `anchor` and `destroy` using HTML anchoring', async () => { @@ -380,6 +380,18 @@ describe('HTMLIntegration', () => { features.update({ html_side_by_side: false }); 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', () => { diff --git a/src/types/annotator.ts b/src/types/annotator.ts index d44690a1bda..2106c686503 100644 --- a/src/types/annotator.ts +++ b/src/types/annotator.ts @@ -336,3 +336,16 @@ export type DocumentInfo = { */ 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; +};