From a86f0d0f340f9257f3c54d2e9679ef059a333559 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Fri, 9 Oct 2020 10:09:42 +0000 Subject: [PATCH 1/3] Add paged reading mode --- public/js/reader.js | 111 +++++++++++++++++++++++++++++++++++--- src/views/reader.html.ecr | 97 ++++++++++++++++++++++----------- 2 files changed, 171 insertions(+), 37 deletions(-) diff --git a/public/js/reader.js b/public/js/reader.js index 479cd08..ac5b92a 100644 --- a/public/js/reader.js +++ b/public/js/reader.js @@ -5,12 +5,68 @@ let longPages = false; $(() => { getPages(); + const storedMode = localStorage.getItem('mode') || 'continuous'; + + setProp('mode', storedMode); + updateMode(storedMode, page); + $('#mode-select').val(storedMode); + $('#page-select').change(() => { const p = parseInt($('#page-select').val()); toPage(p); }); + + $('#mode-select').change(() => { + const mode = $('#mode-select').val(); + const curIdx = parseInt($('#page-select').val()); + + updateMode(mode, curIdx); + }); }); +$(window).resize(() => { + const mode = getProp('mode'); + if (mode === 'continuous') return; + + const wideScreen = $(window).width() > $(window).height(); + const propMode = wideScreen ? 'height' : 'width'; + setProp('mode', propMode); +}); + +/** + * Update the reader mode + * + * @function updateMode + * @param {string} mode - The mode. Can be one of the followings: + * {'continuous', 'paged', 'height', 'width'} + * @param {number} targetPage - The one-based index of the target page + */ +const updateMode = (mode, targetPage) => { + localStorage.setItem('mode', mode); + + // The mode to be put into the `mode` prop. It can't be `screen` + let propMode = mode; + + if (mode === 'paged') { + const wideScreen = $(window).width() > $(window).height(); + propMode = wideScreen ? 'height' : 'width'; + } + + setProp('mode', propMode); + + if (mode === 'continuous') { + waitForPage(items.length, () => { + setupScroller(); + }); + } + + waitForPage(targetPage, () => { + setTimeout(() => { + toPage(targetPage); + }, 100); + }); +}; + /** * Set an alpine.js property * @@ -22,6 +78,17 @@ const setProp = (key, prop) => { $('#root').get(0).__x.$data[key] = prop; }; +/** + * Get an alpine.js property + * + * @function getProp + * @param {string} key - Key of the data property + * @return {*} The data property + */ +const getProp = (key) => { + return $('#root').get(0).__x.$data[key]; +}; + /** * Get dimension of the pages in the entry from the API and update the view */ @@ -50,11 +117,6 @@ const getPages = () => { setProp('items', items); setProp('loading', false); - - waitForPage(items.length, () => { - toPage(page); - setupScroller(); - }); }) .catch(e => { const errMsg = `Failed to get the page dimensions. ${e}`; @@ -71,7 +133,15 @@ const getPages = () => { * @param {number} idx - One-based index of the page */ const toPage = (idx) => { - $(`#${idx}`).get(0).scrollIntoView(true); + const mode = getProp('mode'); + if (mode === 'continuous') { + $(`#${idx}`).get(0).scrollIntoView(true); + } else { + if (idx >= 1 && idx <= items.length) { + setProp('curItem', items[idx - 1]); + } + } + replaceHistory(idx); UIkit.modal($('#modal-sections')).hide(); }; @@ -137,6 +207,8 @@ const replaceHistory = (idx) => { * @function setupScroller */ const setupScroller = () => { + const mode = getProp('mode'); + if (mode !== 'continuous') return; $('#root img').each((idx, el) => { $(el).on('inview', (event, inView) => { if (inView) { @@ -193,3 +265,30 @@ const nextEntry = (nextUrl) => { redirect(nextUrl); }); }; + +/** + * Show the next or the previous page + * + * @function flipPage + * @param {bool} isNext - Whether we are going to the next page + */ +const flipPage = (isNext) => { + const curItem = getProp('curItem'); + const idx = parseInt(curItem.id); + const delta = isNext ? 1 : -1; + const newIdx = idx + delta; + + toPage(newIdx); + + if (isNext) + setProp('flipAnimation', 'right'); + else + setProp('flipAnimation', 'left'); + + setTimeout(() => { + setProp('flipAnimation', null); + }, 500); + + replaceHistory(newIdx); + saveProgress(newIdx); +}; diff --git a/src/views/reader.html.ecr b/src/views/reader.html.ecr index a8983a0..b1acde8 100644 --- a/src/views/reader.html.ecr +++ b/src/views/reader.html.ecr @@ -3,41 +3,67 @@ <%= render_component "head" %> - -
+ +
+
-
-
-
-

-
-
-
- - <%- if next_entry_url -%> - - <%- else -%> - - <%- end -%> +
+
+

+ +
+
+ + <%- if next_entry_url -%> + + <%- else -%> + + <%- end -%> +
+ +
+ + + +
+
+
+ +
- +
+
+ +
+ +
+