diff options
Diffstat (limited to 'js/reader.js')
-rw-r--r-- | js/reader.js | 274 |
1 files changed, 213 insertions, 61 deletions
diff --git a/js/reader.js b/js/reader.js index 87c6458..8d65d8e 100644 --- a/js/reader.js +++ b/js/reader.js @@ -10,6 +10,9 @@ const MIN_LENGTH_TO_JUSTIFY = 32; /* characters */ const LOCATION_DIVISOR = 10; const PAGE_RESET_PROGRESS = -1; +const CACHE_PREFIX = 'epube'; +const CACHE_NAME = CACHE_PREFIX + '-v3'; + Promise.allSettled = Promise.allSettled || ((promises) => Promise.all( promises.map((p) => p .then((value) => ({ @@ -101,6 +104,7 @@ const Reader = { Reader.applyTheme(); + // TODO: rework promise chain to async/await return localforage.getItem(Reader.cacheId()).then(function(item) { if (!item) { console.log('requesting bookinfo...') @@ -281,20 +285,25 @@ const Reader = { const base_url = window.location.href.match(/^.*\//)[0]; - const fonts_css = typeof EpubeApp != "undefined" ? "/assets/android.css" : base_url + "/lib/fonts/fonts.css"; - $(contents.document.head).append($(`<link type="text/css" rel="stylesheet" media="screen" href="${fonts_css}" />`)); + if (typeof EpubeApp != "undefined") { + $(contents.document.head).append($(`<link type="text/css" rel="stylesheet" media="screen" href="/assets/android.css" />`)); + } else { + $(contents.document.head) + .append($("<style type='text/css'>") + .text(Reader.generateFontsCss(base_url))); + } - const res_names = [ + const script_names = [ "dist/app-libs.min.js", "dist/reader_iframe.min.js" ]; - for (let i = 0; i < res_names.length; i++) { + for (let i = 0; i < script_names.length; i++) { // we need to create script element with proper context, that is inside the iframe const elem = contents.document.createElement("script"); elem.type = 'text/javascript'; - elem.text = Reader.Loader._res_data[base_url + res_names[i]]; + elem.text = Reader.Loader._res_data[base_url + script_names[i]]; contents.document.head.appendChild(elem); } @@ -308,6 +317,7 @@ const Reader = { $(contents.document).find("body") .attr("class", typeof EpubeApp != "undefined" ? "is-epube-app" : "") .addClass("theme-" + theme); + }); $('#settings-modal').on('shown.bs.modal', async function() { @@ -787,6 +797,179 @@ const Reader = { }); }); }, + generateFontsCss: function(base_url) { + return ` + /** Calibri */ + + @font-face { + font-family: 'Calibri'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/calibriz.ttf']}); + font-style: italic; + font-weight : 700; + } + + @font-face { + font-family: 'Calibri'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/calibrib.ttf']}); + font-style: normal; + font-weight : 700; + } + + @font-face { + font-family: 'Calibri'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/calibrii.ttf']}); + font-style: italic; + font-weight : 400; + } + + @font-face { + font-family: 'Calibri'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/calibri.ttf']}); + font-style: normal; + font-weight : 400; + } + + /** Cambria */ + + @font-face { + font-family: 'Cambria'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/cambriab.ttf']}); + font-style: normal; + font-weight : 700; + } + + @font-face { + font-family: 'Cambria'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/cambriaz.ttf']}); + font-style: italic; + font-weight : 700; + } + + @font-face { + font-family: 'Cambria'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/cambriai.ttf']}); + font-style: italic; + font-weight : 400; + } + + @font-face { + font-family: 'Cambria'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/cambria.ttf']}); + font-style: normal; + font-weight : 400; + } + + /** Caecilia */ + + @font-face { + font-family: Caecilia; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/caecilia.ttf']}); + font-weight : normal; + } + + @font-face { + font-family: Caecilia; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/caeciliab.ttf']}); + font-weight : bold; + } + + @font-face { + font-family: Caecilia; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/caeciliai.ttf']}); + font-style : italic; + } + + /** Palatino */ + + @font-face { + font-family: 'Palatino'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/palab.ttf']}); + font-style: normal; + font-weight : 700; + } + + @font-face { + font-family: 'Palatino'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/palabi.ttf']}); + font-style: italic; + font-weight : 700; + } + + @font-face { + font-family: 'Palatino'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/palai.ttf']}); + font-style: italic; + font-weight : 400; + } + + @font-face { + font-family: 'Palatino'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/pala.ttf']}); + font-style: normal; + font-weight : 400; + } + + /** Consolas */ + + @font-face { + font-family: 'Consolas'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/consolab.ttf']}); + font-style: normal; + font-weight : 700; + } + + @font-face { + font-family: 'Consolas'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/consolaz.ttf']}); + font-style: italic; + font-weight : 700; + } + + @font-face { + font-family: 'Consolas'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/consolai.ttf']}); + font-style: italic; + font-weight : 400; + } + + @font-face { + font-family: 'Consolas'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/consola.ttf']}); + font-style: normal; + font-weight : 400; + } + + /** IBM Plex Mono */ + + @font-face { + font-family: 'IBM Plex Mono'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/IBMPlexMono-Bold.otf']}); + font-style: normal; + font-weight : 700; + } + + @font-face { + font-family: 'IBM Plex Mono'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/IBMPlexMono-BoldItalic.otf']}); + font-style: italic; + font-weight : 700; + } + + @font-face { + font-family: 'IBM Plex Mono'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/IBMPlexMono-TextItalic.otf']}); + font-style: italic; + font-weight : 400; + } + + @font-face { + font-family: 'IBM Plex Mono'; + src: url(${Reader.Loader._res_data[base_url + 'lib/fonts/IBMPlexMono-Text.otf']}); + font-style: normal; + font-weight : 400; + } + `; + }, flattenTocSubItems: function(entry, nest) { let rv = []; @@ -1113,75 +1296,44 @@ const Reader = { _res_data: [], init: async function() { - // we need to provide resources for reader iframe because service worker fetch() handler doesn't work inside iframes (chrome bug?) - // TODO: acquire this list dynamically somehow? - const res_names = [ - "dist/app-libs.min.js", - "dist/reader_iframe.min.js", - "dist/reader_iframe.min.css" ]; - - if (typeof EpubeApp == "undefined") - res_names.push( - "lib/fonts/fonts.css", - "lib/fonts/caeciliab.ttf", - "lib/fonts/caeciliai.ttf", - "lib/fonts/caecilia.ttf", - "lib/fonts/calibrib.ttf", - "lib/fonts/calibrii.ttf", - "lib/fonts/calibri.ttf", - "lib/fonts/calibriz.ttf", - "lib/fonts/cambriab.ttf", - "lib/fonts/cambriai.ttf", - "lib/fonts/cambria.ttf", - "lib/fonts/cambriaz.ttf", - "lib/fonts/consolab.ttf", - "lib/fonts/consolai.ttf", - "lib/fonts/consola.ttf", - "lib/fonts/consolaz.ttf", - "lib/fonts/fonts.css", - "lib/fonts/IBMPlexMono-BoldItalic.otf", - "lib/fonts/IBMPlexMono-Bold.otf", - "lib/fonts/IBMPlexMono-TextItalic.otf", - "lib/fonts/IBMPlexMono-Text.otf", - "lib/fonts/palabi.ttf", - "lib/fonts/palab.ttf", - "lib/fonts/palai.ttf", - "lib/fonts/pala.ttf" - ); + // we need to manually provide resources for reader iframe because service worker fetch() handler doesn't work inside iframes (chrome bug?) const promises = []; let load_failed = false; - res_names.forEach((res_name) => { - console.log('[loader] loading resource', res_name); - const promise = fetch(res_name, {credentials: 'same-origin'}).then(function(resp) { - if (resp.ok) { - const url = new URL(resp.url); - url.searchParams.delete("ts"); + const cache = await caches.open(CACHE_NAME); + const cache_keys = await cache.keys(); - if (resp.url.match('\\.ttf|\\.otf')) { - return resp.blob().then((blob) => { + cache_keys.forEach((req) => { + if (!req.url.match('backend\.php')) { + console.log('[loader] loading resource', req.url); + const promise = fetch(req.url).then(async (resp) => { + if (resp.ok) { + const url = new URL(resp.url); + url.searchParams.delete("ts"); + + if (resp.url.match('\\.ttf|\\.otf')) { + const blob = await resp.blob(); console.log('[loader] storing blob', url.href); Reader.Loader._res_data[url.toString()] = URL.createObjectURL(blob); - }); - } else { - return resp.text().then(function(data) { + } else { + const text = await resp.text(); console.log('[loader] storing text', url.href); - Reader.Loader._res_data[url.toString()] = data; - }) - } - } else { - console.warn('[loader] failed for resource', res_name, resp); + Reader.Loader._res_data[url.toString()] = text; + } + } else { + console.warn('[loader] failed for resource', req.url, resp); - $(".loading-message").html(`Unable to load resource.<br/><small>${res_name}</small>`); + $(".loading-message").html(`Unable to load resource.<br/><small>${req.url}</small>`); - load_failed = true; - } - }); + load_failed = true; + } + }); - promises.push(promise); + promises.push(promise); + } }); await Promise.allSettled(promises); |