Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate ResumePlugin to BookReaderPlugin #1375

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
47 changes: 36 additions & 11 deletions src/BookReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
BookReader.PLUGINS = {
/** @type {typeof import('./plugins/plugin.archive_analytics.js').ArchiveAnalyticsPlugin | null}*/
archiveAnalytics: null,
/** @type {typeof import('./plugins/plugin.autoplay.js').AutoplayPlugin | null}*/
autoplay: null,
/** @type {typeof import('./plugins/plugin.resume.js').ResumePlugin | null}*/
resume: null,
/** @type {typeof import('./plugins/plugin.text_selection.js').TextSelectionPlugin | null}*/
textSelection: null,
};
Expand Down Expand Up @@ -168,11 +172,7 @@
this.displayedIndices = [];

this.animating = false;
this.flipSpeed = typeof options.flipSpeed === 'number' ? options.flipSpeed : {
'fast': 200,
'slow': 600,
}[options.flipSpeed] || 400;
this.flipDelay = options.flipDelay;
this.flipSpeed = utils.parseAnimationSpeed(options.flipSpeed) || 400;

/**
* Represents the first displayed index
Expand Down Expand Up @@ -261,6 +261,8 @@
// Construct the usual suspects first to get type hints
this._plugins = {
archiveAnalytics: BookReader.PLUGINS.archiveAnalytics ? new BookReader.PLUGINS.archiveAnalytics(this) : null,
autoplay: BookReader.PLUGINS.autoplay ? new BookReader.PLUGINS.autoplay(this) : null,
resume: BookReader.PLUGINS.resume ? new BookReader.PLUGINS.resume(this) : null,
textSelection: BookReader.PLUGINS.textSelection ? new BookReader.PLUGINS.textSelection(this) : null,
};

Expand Down Expand Up @@ -399,9 +401,9 @@
}

// Check for Resume plugin
if (this.options.enablePageResume) {
if (this._plugins.resume?.options.enabled) {
// Check cookies
const val = this.getResumeValue();
const val = this._plugins.resume.getResumeValue();
if (val !== null) {
// If page index different from default
if (params.index !== val) {
Expand Down Expand Up @@ -1343,24 +1345,42 @@
}
};

BookReader.prototype.next = function({triggerStop = true} = {}) {
/**
* @param {object} options
* @param {boolean} [options.triggerStop = true]
* @param {number | 'fast' | 'slow'} [options.flipSpeed]
*/
BookReader.prototype.next = function({
triggerStop = true,
flipSpeed = null,
} = {}) {

Check warning on line 1356 in src/BookReader.js

View check run for this annotation

Codecov / codecov/patch

src/BookReader.js#L1354-L1356

Added lines #L1354 - L1356 were not covered by tests
if (this.constMode2up == this.mode) {
if (triggerStop) this.trigger(BookReader.eventNames.stop);
this._modes.mode2Up.mode2UpLit.flipAnimation('next');
flipSpeed = utils.parseAnimationSpeed(flipSpeed) || this.flipSpeed;
this._modes.mode2Up.mode2UpLit.flipAnimation('next', {flipSpeed});

Check warning on line 1360 in src/BookReader.js

View check run for this annotation

Codecov / codecov/patch

src/BookReader.js#L1360

Added line #L1360 was not covered by tests
} else {
if (this.firstIndex < this.book.getNumLeafs() - 1) {
this.jumpToIndex(this.firstIndex + 1);
}
}
};

BookReader.prototype.prev = function({triggerStop = true} = {}) {
/**
* @param {object} options
* @param {boolean} [options.triggerStop = true]
* @param {number | 'fast' | 'slow'} [options.flipSpeed]
*/
BookReader.prototype.prev = function({
triggerStop = true,
flipSpeed = null,
} = {}) {
const isOnFrontPage = this.firstIndex < 1;
if (isOnFrontPage) return;

if (this.constMode2up == this.mode) {
if (triggerStop) this.trigger(BookReader.eventNames.stop);
this._modes.mode2Up.mode2UpLit.flipAnimation('prev');
flipSpeed = utils.parseAnimationSpeed(flipSpeed) || this.flipSpeed;
this._modes.mode2Up.mode2UpLit.flipAnimation('prev', {flipSpeed});
} else {
if (this.firstIndex >= 1) {
this.jumpToIndex(this.firstIndex - 1);
Expand Down Expand Up @@ -1545,6 +1565,11 @@
self.$('.BRnavCntl').animate({opacity:.75},250);
}
});

// Call _bindNavigationHandlers on the plugins
for (const plugin of Object.values(this._plugins)) {
plugin._bindNavigationHandlers();
}
};

/**************************/
Expand Down
5 changes: 3 additions & 2 deletions src/BookReader/Mode2UpLit.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,13 +493,14 @@
/**
* @param {'left' | 'right' | 'next' | 'prev' | PageIndex | PageModel | {left: PageModel | null, right: PageModel | null}} nextSpread
*/
async flipAnimation(nextSpread, { animate = true } = {}) {
async flipAnimation(nextSpread, { animate = true, flipSpeed = this.flipSpeed } = {}) {

Check warning on line 496 in src/BookReader/Mode2UpLit.js

View check run for this annotation

Codecov / codecov/patch

src/BookReader/Mode2UpLit.js#L496

Added line #L496 was not covered by tests
const curSpread = (this.pageLeft || this.pageRight)?.spread;
if (!curSpread) {
// Nothings been actually rendered yet! Will be corrected during initFirstRender
return;
}

flipSpeed = flipSpeed || this.flipSpeed; // Handle null
nextSpread = this.parseNextSpread(nextSpread);
if (this.activeFlip || !nextSpread) return;

Expand Down Expand Up @@ -559,7 +560,7 @@

/** @type {KeyframeAnimationOptions} */
const animationStyle = {
duration: this.flipSpeed + this.activeFlip.pagesFlippingCount,
duration: flipSpeed + this.activeFlip.pagesFlippingCount,
easing: 'ease-in',
fill: 'none',
};
Expand Down
4 changes: 4 additions & 0 deletions src/BookReader/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ export const DEFAULT_OPTIONS = {
plugins: {
/** @type {import('../plugins/plugin.archive_analytics.js').ArchiveAnalyticsPlugin['options']}*/
archiveAnalytics: null,
/** @type {import('../plugins/plugin.autoplay.js').AutoplayPlugin['options']}*/
autoplay: null,
/** @type {import('../plugins/plugin.resume.js').ResumePlugin['options']} */
resume: null,
/** @type {import('../plugins/plugin.text_selection.js').TextSelectionPlugin['options']} */
textSelection: null,
},
Expand Down
10 changes: 10 additions & 0 deletions src/BookReader/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,13 @@ export function promisifyEvent(target, eventType) {
export function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}

/**
* @param {number | 'fast' | 'slow' | string} speed
* Parsing of the jquery animation speed; see https://api.jquery.com/animate/
*/
export function parseAnimationSpeed(speed) {
if (speed === 'slow') return 600;
if (speed === 'fast') return 200;
return parseInt(speed, 10);
}
3 changes: 3 additions & 0 deletions src/BookReaderPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ export class BookReaderPlugin {
*/
_configurePageContainer(pageContainer) {
}

/** @abstract @protected */
_bindNavigationHandlers() {}
}
200 changes: 98 additions & 102 deletions src/plugins/plugin.autoplay.js
Original file line number Diff line number Diff line change
@@ -1,128 +1,124 @@
/*global BookReader */
// @ts-check
import { EVENTS } from "../BookReader/events";
import { parseAnimationSpeed } from "../BookReader/utils";
import { BookReaderPlugin } from "../BookReaderPlugin";

/**
* Plugin which adds an autoplay feature. Useful for kiosk situations.
*/
jQuery.extend(BookReader.defaultOptions, {
enableAutoPlayPlugin: true,
});

/**
* @override BookReader.setup
*/
BookReader.prototype.setup = (function(super_) {
return function (options) {
super_.call(this, options);

this.autoTimer = null;
this.flipDelay = 5000;
};
})(BookReader.prototype.setup);
export class AutoplayPlugin extends BookReaderPlugin {
options = {
enabled: true,
/**
* @type {number | 'fast' | 'slow'}
* How quickly the flip animation should run.
**/
flipSpeed: 1500,
/** How long to pause on each page between flips */
flipDelay: 5000,
/** Allow controlling the autoflip/speed/delay from the url */
urlParams: true,
}

/**
* @override BookReader.init
*/
BookReader.prototype.init = (function(super_) {
return function (options) {
super_.call(this, options);
timer = null;

if (!this.options.enableAutoPlayPlugin) return;
/** @override */
init() {
if (!this.options.enabled) return;

this.bind(BookReader.eventNames.stop, () => this.autoStop());
this.br.bind(EVENTS.stop, () => this.stop());

const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('autoflip') === '1') {
this.autoToggle();
if (this.options.urlParams) {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('flipSpeed')) {
this.options.flipSpeed = parseAnimationSpeed(urlParams.get('flipSpeed')) || this.options.flipSpeed;
}
if (urlParams.get('flipDelay')) {
this.options.flipDelay = parseAnimationSpeed(urlParams.get('flipDelay')) || this.options.flipDelay;
}
if (urlParams.get('autoflip') === '1') {
this.toggle();

Check warning on line 40 in src/plugins/plugin.autoplay.js

View check run for this annotation

Codecov / codecov/patch

src/plugins/plugin.autoplay.js#L40

Added line #L40 was not covered by tests
}
}
};
})(BookReader.prototype.init);

/**
* @override BookReader.bindNavigationHandlers
*/
BookReader.prototype.bindNavigationHandlers = (function(super_) {
return function() {
super_.call(this);
}

if (!this.options.enableAutoPlayPlugin) return;
/** @override */
_bindNavigationHandlers() {
if (!this.options.enabled) return;

const jIcons = this.$('.BRicon');
const jIcons = this.br.$('.BRicon');

jIcons.filter('.play').click(() => {
this.autoToggle();
jIcons.filter('.play').on('click', () => {
this.toggle();

Check warning on line 52 in src/plugins/plugin.autoplay.js

View check run for this annotation

Codecov / codecov/patch

src/plugins/plugin.autoplay.js#L52

Added line #L52 was not covered by tests
return false;
});

jIcons.filter('.pause').click(() => {
this.autoToggle();
jIcons.filter('.pause').on('click', () => {
this.toggle();

Check warning on line 57 in src/plugins/plugin.autoplay.js

View check run for this annotation

Codecov / codecov/patch

src/plugins/plugin.autoplay.js#L57

Added line #L57 was not covered by tests
return false;
});
};
})(BookReader.prototype.bindNavigationHandlers);

/**
* Starts autoplay mode
* @param {object} overrides
* @param {number} overrides.flipSpeed
* @param {number} overrides.flipDelay
*/
BookReader.prototype.autoToggle = function(overrides) {
if (!this.options.enableAutoPlayPlugin) return;

const options = $.extend({
flipSpeed: this.flipSpeed,
flipDelay: this.flipDelay,
}, overrides);

this.flipSpeed = typeof options.flipSpeed === "number" ? options.flipSpeed : this.flipSpeed;
this.flipDelay = typeof options.flipDelay === "number" ? options.flipDelay : this.flipDelay;
this.trigger(BookReader.eventNames.stop);

let bComingFrom1up = false;
if (this.constMode2up != this.mode) {
bComingFrom1up = true;
this.switchMode(this.constMode2up);
}

if (null == this.autoTimer) {
// $$$ Draw events currently cause layout problems when they occur during animation.
// There is a specific problem when changing from 1-up immediately to autoplay in RTL so
// we workaround for now by not triggering immediate animation in that case.
// See https://bugs.launchpad.net/gnubook/+bug/328327
if (('rl' == this.pageProgression) && bComingFrom1up) {
// don't flip immediately -- wait until timer fires
} else {
// flip immediately
this.next({ triggerStop: false });
/**
* Starts autoplay mode
* @param {object} overrides
* @param {number} overrides.flipSpeed
* @param {number} overrides.flipDelay
*/
toggle(overrides = null) {
if (!this.options.enabled) return;

Object.assign(this.options, overrides);
this.br.trigger(EVENTS.stop);

let bComingFrom1up = false;
if (this.br.constMode2up != this.br.mode) {
bComingFrom1up = true;
this.br.switchMode(this.br.constMode2up);
}

this.$('.play').hide();
this.$('.pause').show();
this.autoTimer = setInterval(() => {
if (this.animating) return;

if (Math.max(this.twoPage.currentIndexL, this.twoPage.currentIndexR) >= this.book.getNumLeafs() - 1) {
this.prev({ triggerStop: false }); // $$$ really what we want?
if (null == this.timer) {
// $$$ Draw events currently cause layout problems when they occur during animation.
// There is a specific problem when changing from 1-up immediately to autoplay in RTL so
// we workaround for now by not triggering immediate animation in that case.
// See https://bugs.launchpad.net/gnubook/+bug/328327
if (('rl' == this.br.pageProgression) && bComingFrom1up) {
// don't flip immediately -- wait until timer fires
} else {
this.next({ triggerStop: false });
// flip immediately
this.br.next({ triggerStop: false, flipSpeed: this.options.flipSpeed });
}
}, this.flipDelay);
} else {
this.autoStop();

this.br.$('.play').hide();
this.br.$('.pause').show();
this.timer = setInterval(() => {
if (this.br.animating) return;

if (Math.max(this.br.twoPage.currentIndexL, this.br.twoPage.currentIndexR) >= this.br.book.getNumLeafs() - 1) {
this.br.prev({ triggerStop: false, flipSpeed: this.options.flipSpeed }); // $$$ really what we want?

Check warning on line 98 in src/plugins/plugin.autoplay.js

View check run for this annotation

Codecov / codecov/patch

src/plugins/plugin.autoplay.js#L98

Added line #L98 was not covered by tests
} else {
this.br.next({ triggerStop: false, flipSpeed: this.options.flipSpeed });

Check warning on line 100 in src/plugins/plugin.autoplay.js

View check run for this annotation

Codecov / codecov/patch

src/plugins/plugin.autoplay.js#L100

Added line #L100 was not covered by tests
}
}, parseAnimationSpeed(this.options.flipDelay));
} else {
this.stop();

Check warning on line 104 in src/plugins/plugin.autoplay.js

View check run for this annotation

Codecov / codecov/patch

src/plugins/plugin.autoplay.js#L104

Added line #L104 was not covered by tests
}
}
};

/**
* Stop autoplay mode, allowing animations to finish
*/
BookReader.prototype.autoStop = function() {
if (!this.options.enableAutoPlayPlugin) return;

if (null != this.autoTimer) {
clearInterval(this.autoTimer);
this.flipSpeed = 'fast';
this.$('.pause').hide();
this.$('.play').show();
this.autoTimer = null;
/**
* Stop autoplay mode, allowing animations to finish
*/
stop() {
if (!this.options.enabled) return;

if (null != this.timer) {
clearInterval(this.timer);
this.br.$('.pause').hide();
this.br.$('.play').show();
this.timer = null;

Check warning on line 118 in src/plugins/plugin.autoplay.js

View check run for this annotation

Codecov / codecov/patch

src/plugins/plugin.autoplay.js#L115-L118

Added lines #L115 - L118 were not covered by tests
}
}
};
}

const BookReader = /** @type {typeof import('../BookReader').default} */(window.BookReader);
BookReader?.registerPlugin('autoplay', AutoplayPlugin);
Loading