Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 44 additions & 6 deletions navigator/src/epub/frame/FramePoolManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class FramePoolManager {
private readonly injector: Injector | null = null;
private readonly contentProtectionConfig: IContentProtectionConfig;
private readonly keyboardPeripheralsConfig: IKeyboardPeripheralsConfig;
private updateSequence = 0;

constructor(
container: HTMLElement,
Expand Down Expand Up @@ -77,6 +78,7 @@ export class FramePoolManager {
}

async update(pub: Publication, locator: Locator, modules: ModuleName[], force=false) {
const updateSequence = ++this.updateSequence;
let i = this.positions.findIndex(l => l.locations.position === locator.locations.position);
if(i < 0) throw Error(`Locator not found in position list: ${locator.locations.position} > ${this.positions.reduce<number>((acc, l) => l.locations.position || 0 > acc ? l.locations.position || 0 : acc, 0) }`);
const newHref = this.positions[i].href;
Expand Down Expand Up @@ -181,20 +183,56 @@ export class FramePoolManager {
await Promise.all(creation.map(href => creator(href)));
} catch (error) {
reject(error);
return;
}

if (updateSequence !== this.updateSequence) {
resolve();
return;
}

// Update current frame
const newFrame = this.pool.get(newHref)!;
const newFrame = this.pool.get(newHref);
if (!newFrame) {
resolve();
return;
}

if(newFrame?.source !== this._currentFrame?.source || force) {
await this._currentFrame?.hide(); // Hide current frame. It's possible it no longer even exists in the DOM at this point
if(newFrame) // If user is speeding through the publication, this can get destroyed
await newFrame.load(modules); // In order to ensure modules match the latest configuration

// Resolve if there is a concurrent update that has started since this one began
if (updateSequence !== this.updateSequence) {
resolve();
return;
}

// If user is speeding through the publication, this can get destroyed
const currentFrame = this.pool.get(newHref);
if (!currentFrame) {
resolve();
return;
}

await currentFrame.load(modules); // In order to ensure modules match the latest configuration

// Resolve if there is a concurrent update that has started since this one began
if (updateSequence !== this.updateSequence) {
resolve();
return;
}

// Check if it was destroyed, again
const latestFrame = this.pool.get(newHref);
if (!latestFrame) {
resolve();
return;
}

// Update progression if necessary and show the new frame
if(newFrame) // If user is speeding through the publication, this can get destroyed
await newFrame.show(locator.locations.progression); // Show/activate new frame
await latestFrame.show(locator.locations.progression); // Show/activate new frame

this._currentFrame = newFrame;
this._currentFrame = latestFrame;

// Safari retains focus on the hidden iframe; transfer it to the new
// frame only if no meaningful element in the parent document owns focus.
Expand Down