react-native-simple-epub-reader 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/module/components/Reader.js +36 -13
- package/lib/module/components/Reader.js.map +1 -1
- package/lib/module/constants/template.js +214 -255
- package/lib/module/constants/template.js.map +1 -1
- package/lib/module/helpers/downloadEpub.js +8 -1
- package/lib/module/helpers/downloadEpub.js.map +1 -1
- package/lib/typescript/src/components/Reader.d.ts.map +1 -1
- package/lib/typescript/src/constants/template.d.ts +1 -1
- package/lib/typescript/src/constants/template.d.ts.map +1 -1
- package/lib/typescript/src/helpers/downloadEpub.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Reader.tsx +42 -16
- package/src/constants/template.ts +214 -255
- package/src/helpers/downloadEpub.ts +9 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare const _default: "\n<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>EPUB.js</title>\n <script id=\"jszip\"></script>\n <script id=\"epubjs\"></script>\n\n <style type=\"text/css\">\n body {\n margin: 0;\n background-color: #211f26;\n }\n\n #viewer {\n height: 100vh;\n width: 100vw;\n overflow: hidden !important;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n [ref='epubjs-mk-balloon'] {\n background: url('data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPScxLjEnIHhtbG5zPSdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycgeG1sbnM6eGxpbms9J2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnIHg9JzBweCcgeT0nMHB4JyB2aWV3Qm94PScwIDAgNzUgNzUnPjxnIGZpbGw9JyNCREJEQkQnIGlkPSdidWJibGUnPjxwYXRoIGNsYXNzPSdzdDAnIGQ9J00zNy41LDkuNEMxOS42LDkuNCw1LDIwLjUsNSwzNC4zYzAsNS45LDIuNywxMS4zLDcuMSwxNS42TDkuNiw2NS42bDE5LTcuM2MyLjgsMC42LDUuOCwwLjksOC45LDAuOSBDNTUuNSw1OS4yLDcwLDQ4LjEsNzAsMzQuM0M3MCwyMC41LDU1LjQsOS40LDM3LjUsOS40eicvPjwvZz48L3N2Zz4=')\n no-repeat;\n width: 20px;\n height: 20px;\n cursor: pointer;\n margin-left: 0;\n }\n\n [ref='epubjs-mk-heart'] {\n background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOUlEQVR4nLWUTWgTURDH14Oe9JiPNqFNujvvzdsm3bdvPxKMFUEPag/iwdaD3j1JDymlCMXiqUeRHvWgFRQUxKPirUU8eFARvCnUj7QXP7DiJtk8easJjRjzIQ784bEz82Pe7MzTtP9tpmnu8UbNpOM4uzvFKF+3GM1BHHIAbwjA7xyY5AaGPuCarZtHmzGcsGM+YevKp2JUrAN4XeW2wSxKMy6wrSkKtbsiJZ96SfnAGZbl8bG6DawhdLwqAK9xYI25XLaufCrmjkjJKQpVF3DLzrDRFtAHXJ9hUNsoxOTH8hn5afGcrBRjkR66w3I/0GoJaPWRO9T63tRGISanmVHzgK1FMBvGmSr/iZeUn5fL8svlRbl5aKQt6bGXjPQ7bKefA5MOIahZOpsuAQmUY3t1pWNSN5WABtwwT2kW4Mki0OqgoMov+YA1rrMTmk3IhCr3hd/5St303EtEV54Yw5xq4y4PcHOFt/etH12xRqQHWFGsn/MFuHAQaPCmGO8b9roQl5OEBpaB862xoZTuc4F+uJDLhv0CF/LZ0DPoe9M097YNNwd2hAMLb9rpnmGrdlr1LrQJO/zH9bMMnBWA4X0n1RV2T6TU6oUc2Pm/vQ0aN/CSAKzfFp0rvWWnI5gNbEnrxWwD59UOL+UzjXc7ftTbYlxezGca0X4Dm+sJ1jQO7LgA/Hoa9eCln5Cv/IQ8i3ogAL+pZdAGMYcQdAGfHSAkmCQkUOc8pXQgWNPUgysAl5XU+Z9gg9gPaBjV+CGbZVoAAAAASUVORK5CYII=')\n no-repeat;\n width: 20px;\n height: 20px;\n cursor: pointer;\n margin-left: 0;\n }\n </style>\n </head>\n\n <body oncopy=\"return false;\" oncut=\"return false;\">\n <div id=\"viewer\"></div>\n\n <script>\n let book;\n let rendition;\n\n const type = window.type;\n const file = window.book;\n const theme = window.theme;\n const initialLocations = window.locations;\n const enableSelection = window.enable_selection;\n const allowScriptedContent = window.allowScriptedContent || false;\n const allowPopups = window.allowPopups || false;\n\n if (!file) {\n const reactNativeWebview =\n window.ReactNativeWebView !== undefined &&\n window.ReactNativeWebView !== null\n ? window.ReactNativeWebView\n : window;\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onDisplayError',\n reason: 'Book file is missing',\n })\n );\n }\n\n if (type === 'epub' || type === 'opf' || type === 'binary') {\n book = ePub(file);\n } else if (type === 'base64') {\n book = ePub(file, { encoding: 'base64' });\n } else {\n const reactNativeWebview =\n window.ReactNativeWebView !== undefined &&\n window.ReactNativeWebView !== null\n ? window.ReactNativeWebView\n : window;\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onDisplayError',\n reason: 'Missing or invalid file type',\n })\n );\n }\n\n rendition = book.renderTo('viewer', {\n width: '100%',\n height: '100%',\n manager: 'default',\n flow: 'auto',\n snap: undefined,\n spread: undefined,\n fullsize: undefined,\n allowPopups: allowPopups,\n allowScriptedContent: allowScriptedContent,\n });\n\n const reactNativeWebview =\n window.ReactNativeWebView !== undefined &&\n window.ReactNativeWebView !== null\n ? window.ReactNativeWebView\n : window;\n reactNativeWebview.postMessage(JSON.stringify({ type: 'onStarted' }));\n\n function flatten(chapters) {\n return [].concat.apply(\n [],\n chapters.map((chapter) =>\n [].concat.apply([chapter], flatten(chapter.subitems))\n )\n );\n }\n\n function getCfiFromHref(book, href) {\n const [_, id] = href.split('#');\n let section =\n book.spine.get(href.split('/')[1]) ||\n book.spine.get(href) ||\n book.spine.get(href.split('/').slice(1).join('/'));\n\n const el = id\n ? section.document.getElementById(id)\n : section.document.body;\n return section.cfiFromElement(el);\n }\n\n function getChapter(location) {\n const locationHref = location.start.href;\n\n let match = flatten(book.navigation.toc)\n .filter((chapter) => {\n return book.canonical(chapter.href).includes(locationHref);\n }, null)\n .reduce((result, chapter) => {\n const locationAfterChapter =\n ePub.CFI.prototype.compare(\n location.start.cfi,\n getCfiFromHref(book, chapter.href)\n ) > 0;\n return locationAfterChapter ? chapter : result;\n }, null);\n\n return match;\n }\n\n const makeRangeCfi = (a, b) => {\n const CFI = new ePub.CFI();\n const start = CFI.parse(a),\n end = CFI.parse(b);\n const cfi = {\n range: true,\n base: start.base,\n path: {\n steps: [],\n terminal: null,\n },\n start: start.path,\n end: end.path,\n };\n const len = cfi.start.steps.length;\n for (let i = 0; i < len; i++) {\n if (CFI.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {\n if (i == len - 1) {\n // Last step is equal, check terminals\n if (cfi.start.terminal === cfi.end.terminal) {\n // CFI's are equal\n cfi.path.steps.push(cfi.start.steps[i]);\n // Not a range\n cfi.range = false;\n }\n } else cfi.path.steps.push(cfi.start.steps[i]);\n } else break;\n }\n cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length);\n cfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length);\n\n return (\n 'epubcfi(' +\n CFI.segmentString(cfi.base) +\n '!' +\n CFI.segmentString(cfi.path) +\n ',' +\n CFI.segmentString(cfi.start) +\n ',' +\n CFI.segmentString(cfi.end) +\n ')'\n );\n };\n\n if (!enableSelection) {\n rendition.themes.default({\n body: {\n '-webkit-touch-callout': 'none' /* iOS Safari */,\n '-webkit-user-select': 'none' /* Safari */,\n '-khtml-user-select': 'none' /* Konqueror HTML */,\n '-moz-user-select': 'none' /* Firefox */,\n '-ms-user-select': 'none' /* Internet Explorer/Edge */,\n 'user-select': 'none',\n },\n });\n }\n\n book.ready\n .then(function () {\n if (initialLocations) {\n book.locations.load(initialLocations);\n }\n return rendition.display();\n })\n .then(function () {\n var currentLocation = rendition.currentLocation();\n\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onReady',\n totalLocations: book.locations.total,\n currentLocation: currentLocation,\n progress: currentLocation?.start?.cfi\n ? book.locations.percentageFromCfi(currentLocation.start.cfi)\n : 0,\n })\n );\n\n if (initialLocations) {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onLocationsReady',\n epubKey: book.key(),\n locations: initialLocations,\n totalLocations: book.locations.total,\n currentLocation: currentLocation,\n progress: currentLocation?.start?.cfi\n ? book.locations.percentageFromCfi(currentLocation.start.cfi)\n : 0,\n })\n );\n return Promise.resolve();\n }\n\n return book.locations\n .generate(1600)\n .then(function () {\n var generatedLocation =\n rendition.currentLocation() || currentLocation;\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onLocationsReady',\n epubKey: book.key(),\n locations: book.locations.save(),\n totalLocations: book.locations.total,\n currentLocation: generatedLocation,\n progress: generatedLocation?.start?.cfi\n ? book.locations.percentageFromCfi(\n generatedLocation.start.cfi\n )\n : 0,\n })\n );\n })\n .catch(function () {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onLocationsReady',\n epubKey: book.key(),\n locations: [],\n totalLocations: book.locations.total,\n currentLocation: currentLocation,\n progress: 0,\n })\n );\n });\n\n book\n .coverUrl()\n .then(async (url) => {\n var reader = new FileReader();\n reader.onload = (res) => {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'meta',\n metadata: {\n cover: reader.result,\n author: book.package.metadata.creator,\n title: book.package.metadata.title,\n description: book.package.metadata.description,\n language: book.package.metadata.language,\n publisher: book.package.metadata.publisher,\n rights: book.package.metadata.rights,\n },\n })\n );\n };\n reader.readAsDataURL(await fetch(url).then((res) => res.blob()));\n })\n .catch(() => {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'meta',\n metadata: {\n cover: undefined,\n author: book.package.metadata.creator,\n title: book.package.metadata.title,\n description: book.package.metadata.description,\n language: book.package.metadata.language,\n publisher: book.package.metadata.publisher,\n rights: book.package.metadata.rights,\n },\n })\n );\n });\n\n book.loaded.navigation.then(function (item) {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onNavigationLoaded',\n toc: item.toc,\n landmarks: item.landmarks,\n })\n );\n });\n })\n .catch(function (err) {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onDisplayError',\n reason: err.message || err.toString(),\n })\n );\n });\n\n let isAnimating = false;\n const originalNext = rendition.next.bind(rendition);\n const originalPrev = rendition.prev.bind(rendition);\n\n rendition.next = function () {\n if (isAnimating) return;\n isAnimating = true;\n\n const container = rendition.manager.container;\n container.style.transition = 'opacity 0.2s ease-out';\n container.style.opacity = '0.4';\n\n setTimeout(() => {\n originalNext();\n setTimeout(() => {\n container.style.opacity = '1';\n setTimeout(() => {\n container.style.transition = '';\n isAnimating = false;\n }, 200);\n }, 50);\n }, 100);\n };\n\n rendition.prev = function () {\n if (isAnimating) return;\n isAnimating = true;\n\n const container = rendition.manager.container;\n container.style.transition = 'opacity 0.2s ease-out';\n container.style.opacity = '0.4';\n\n setTimeout(() => {\n originalPrev();\n setTimeout(() => {\n container.style.opacity = '1';\n setTimeout(() => {\n container.style.transition = '';\n isAnimating = false;\n }, 200);\n }, 50);\n }, 100);\n };\n\n rendition.on('started', () => {\n rendition.themes.register({ theme: theme });\n rendition.themes.select('theme');\n });\n\n rendition.on('relocated', function (location) {\n var percent = book.locations.percentageFromCfi(location.start.cfi);\n var percentage = Math.floor(percent * 100);\n var chapter = getChapter(location);\n\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onLocationChange',\n totalLocations: book.locations.total,\n currentLocation: location,\n progress: percentage,\n currentSection: chapter,\n })\n );\n\n if (location.atStart) {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onBeginning',\n })\n );\n }\n\n if (location.atEnd) {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onFinish',\n })\n );\n }\n });\n\n rendition.on('rendered', function (section) {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onRendered',\n section: section,\n currentSection: book.navigation.get(section.href),\n })\n );\n });\n\n rendition.on('layout', function (layout) {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: 'onLayout',\n layout: layout,\n })\n );\n });\n </script>\n </body>\n</html>\n";
|
|
1
|
+
declare const _default: "\n<!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>EPUB.js</title>\n <script id=\"jszip\"></script>\n <script id=\"epubjs\"></script>\n\n <style type=\"text/css\">\n body {\n margin: 0;\n background-color: #211F26;\n }\n\n #viewer {\n height: 100vh;\n width: 100vw;\n overflow: hidden !important;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n [ref=\"epubjs-mk-balloon\"] {\n background: url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPScxLjEnIHhtbG5zPSdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycgeG1sbnM6eGxpbms9J2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnIHg9JzBweCcgeT0nMHB4JyB2aWV3Qm94PScwIDAgNzUgNzUnPjxnIGZpbGw9JyNCREJEQkQnIGlkPSdidWJibGUnPjxwYXRoIGNsYXNzPSdzdDAnIGQ9J00zNy41LDkuNEMxOS42LDkuNCw1LDIwLjUsNSwzNC4zYzAsNS45LDIuNywxMS4zLDcuMSwxNS42TDkuNiw2NS42bDE5LTcuM2MyLjgsMC42LDUuOCwwLjksOC45LDAuOSBDNTUuNSw1OS4yLDcwLDQ4LjEsNzAsMzQuM0M3MCwyMC41LDU1LjQsOS40LDM3LjUsOS40eicvPjwvZz48L3N2Zz4=\") no-repeat;\n width: 20px;\n height: 20px;\n cursor: pointer;\n margin-left: 0;\n }\n\n [ref=\"epubjs-mk-heart\"] {\n background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOUlEQVR4nLWUTWgTURDH14Oe9JiPNqFNujvvzdsm3bdvPxKMFUEPag/iwdaD3j1JDymlCMXiqUeRHvWgFRQUxKPirUU8eFARvCnUj7QXP7DiJtk8easJjRjzIQ784bEz82Pe7MzTtP9tpmnu8UbNpOM4uzvFKF+3GM1BHHIAbwjA7xyY5AaGPuCarZtHmzGcsGM+YevKp2JUrAN4XeW2wSxKMy6wrSkKtbsiJZ96SfnAGZbl8bG6DawhdLwqAK9xYI25XLaufCrmjkjJKQpVF3DLzrDRFtAHXJ9hUNsoxOTH8hn5afGcrBRjkR66w3I/0GoJaPWRO9T63tRGISanmVHzgK1FMBvGmSr/iZeUn5fL8svlRbl5aKQt6bGXjPQ7bKefA5MOIahZOpsuAQmUY3t1pWNSN5WABtwwT2kW4Mki0OqgoMov+YA1rrMTmk3IhCr3hd/5St303EtEV54Yw5xq4y4PcHOFt/etH12xRqQHWFGsn/MFuHAQaPCmGO8b9roQl5OEBpaB862xoZTuc4F+uJDLhv0CF/LZ0DPoe9M097YNNwd2hAMLb9rpnmGrdlr1LrQJO/zH9bMMnBWA4X0n1RV2T6TU6oUc2Pm/vQ0aN/CSAKzfFp0rvWWnI5gNbEnrxWwD59UOL+UzjXc7ftTbYlxezGca0X4Dm+sJ1jQO7LgA/Hoa9eCln5Cv/IQ8i3ogAL+pZdAGMYcQdAGfHSAkmCQkUOc8pXQgWNPUgysAl5XU+Z9gg9gPaBjV+CGbZVoAAAAASUVORK5CYII=\") no-repeat;\n width: 20px;\n height: 20px;\n cursor: pointer;\n margin-left: 0;\n }\n </style>\n </head>\n\n <body oncopy='return false' oncut='return false'>\n <div id=\"viewer\"></div>\n\n <script>\n let book;\n let rendition;\n\n const type = window.type;\n const file = window.book;\n const theme = window.theme;\n const initialLocations = window.locations;\n const enableSelection = window.enable_selection;\n const allowScriptedContent = window.allowScriptedContent || false;\n const allowPopups = window.allowPopups || false;\n\n if (!file) {\n const reactNativeWebview = window.ReactNativeWebView !== undefined && window.ReactNativeWebView !== null ? window.ReactNativeWebView : window;\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onDisplayError\",\n reason: \"Book file is missing\"\n }));\n }\n\n if (type === 'epub' || type === 'opf' || type === 'binary') {\n book = ePub(file);\n } else if (type === 'base64') {\n book = ePub(file, { encoding: \"base64\" });\n } else {\n const reactNativeWebview = window.ReactNativeWebView !== undefined && window.ReactNativeWebView !== null ? window.ReactNativeWebView : window;\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onDisplayError\",\n reason: \"Missing or invalid file type\"\n }));\n }\n\n rendition = book.renderTo(\"viewer\", {\n width: \"100%\",\n height: \"100%\",\n manager: \"default\",\n flow: \"auto\",\n snap: undefined,\n spread: undefined,\n fullsize: undefined,\n allowPopups: allowPopups,\n allowScriptedContent: allowScriptedContent\n });\n \n const reactNativeWebview = window.ReactNativeWebView !== undefined && window.ReactNativeWebView!== null ? window.ReactNativeWebView: window;\n reactNativeWebview.postMessage(JSON.stringify({ type: \"onStarted\" }));\n\n function flatten(chapters) {\n return [].concat.apply([], chapters.map((chapter) => [].concat.apply([chapter], flatten(chapter.subitems))));\n }\n\n function getCfiFromHref(book, href) {\n const [_, id] = href.split('#')\n let section = book.spine.get(href.split('/')[1]) || book.spine.get(href) || book.spine.get(href.split('/').slice(1).join('/'))\n\n const el = (id ? section.document.getElementById(id) : section.document.body)\n return section.cfiFromElement(el)\n }\n\n function getChapter(location) {\n const locationHref = location.start.href\n\n let match = flatten(book.navigation.toc)\n .filter((chapter) => {\n return book.canonical(chapter.href).includes(locationHref)\n }, null)\n .reduce((result, chapter) => {\n const locationAfterChapter = ePub.CFI.prototype.compare(location.start.cfi, getCfiFromHref(book, chapter.href)) > 0\n return locationAfterChapter ? chapter : result\n }, null);\n\n return match;\n };\n\n const makeRangeCfi = (a, b) => {\n const CFI = new ePub.CFI()\n const start = CFI.parse(a), end = CFI.parse(b)\n const cfi = {\n range: true,\n base: start.base,\n path: {\n steps: [],\n terminal: null\n },\n start: start.path,\n end: end.path\n }\n const len = cfi.start.steps.length\n for (let i = 0; i < len; i++) {\n if (CFI.equalStep(cfi.start.steps[i], cfi.end.steps[i])) {\n if (i == len - 1) {\n // Last step is equal, check terminals\n if (cfi.start.terminal === cfi.end.terminal) {\n // CFI's are equal\n cfi.path.steps.push(cfi.start.steps[i])\n // Not a range\n cfi.range = false\n }\n } else cfi.path.steps.push(cfi.start.steps[i])\n } else break\n }\n cfi.start.steps = cfi.start.steps.slice(cfi.path.steps.length)\n cfi.end.steps = cfi.end.steps.slice(cfi.path.steps.length)\n\n return 'epubcfi(' + CFI.segmentString(cfi.base)\n + '!' + CFI.segmentString(cfi.path)\n + ',' + CFI.segmentString(cfi.start)\n + ',' + CFI.segmentString(cfi.end)\n + ')'\n }\n\n if (!enableSelection) {\n rendition.themes.default({\n 'body': {\n '-webkit-touch-callout': 'none', /* iOS Safari */\n '-webkit-user-select': 'none', /* Safari */\n '-khtml-user-select': 'none', /* Konqueror HTML */\n '-moz-user-select': 'none', /* Firefox */\n '-ms-user-select': 'none', /* Internet Explorer/Edge */\n 'user-select': 'none'\n }\n });\n }\n\n book.ready\n .then(function () {\n if (initialLocations) {\n book.locations.load(initialLocations);\n }\n return rendition.display();\n })\n .then(function () {\n var currentLocation = rendition.currentLocation();\n\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onReady\",\n totalLocations: book.locations.total,\n currentLocation: currentLocation,\n progress: currentLocation?.start?.cfi\n ? book.locations.percentageFromCfi(currentLocation.start.cfi)\n : 0,\n }));\n\n if (initialLocations) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onLocationsReady\",\n epubKey: book.key(),\n locations: initialLocations,\n totalLocations: book.locations.total,\n currentLocation: currentLocation,\n progress: currentLocation?.start?.cfi\n ? book.locations.percentageFromCfi(currentLocation.start.cfi)\n : 0,\n }));\n return Promise.resolve();\n }\n\n return book.locations.generate(1600).then(function () {\n var generatedLocation = rendition.currentLocation() || currentLocation;\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onLocationsReady\",\n epubKey: book.key(),\n locations: book.locations.save(),\n totalLocations: book.locations.total,\n currentLocation: generatedLocation,\n progress: generatedLocation?.start?.cfi\n ? book.locations.percentageFromCfi(generatedLocation.start.cfi)\n : 0,\n }));\n }).catch(function () {\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onLocationsReady\",\n epubKey: book.key(),\n locations: [],\n totalLocations: book.locations.total,\n currentLocation: currentLocation,\n progress: 0,\n }));\n });\n\n book\n .coverUrl()\n .then(async (url) => {\n var reader = new FileReader();\n reader.onload = (res) => {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: \"meta\",\n metadata: {\n cover: reader.result,\n author: book.package.metadata.creator,\n title: book.package.metadata.title,\n description: book.package.metadata.description,\n language: book.package.metadata.language,\n publisher: book.package.metadata.publisher,\n rights: book.package.metadata.rights,\n },\n })\n );\n };\n reader.readAsDataURL(await fetch(url).then((res) => res.blob()));\n })\n .catch(() => {\n reactNativeWebview.postMessage(\n JSON.stringify({\n type: \"meta\",\n metadata: {\n cover: undefined,\n author: book.package.metadata.creator,\n title: book.package.metadata.title,\n description: book.package.metadata.description,\n language: book.package.metadata.language,\n publisher: book.package.metadata.publisher,\n rights: book.package.metadata.rights,\n },\n })\n );\n });\n\n book.loaded.navigation.then(function (item) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: 'onNavigationLoaded',\n toc: item.toc,\n landmarks: item.landmarks\n }));\n });\n })\n .catch(function (err) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onDisplayError\",\n reason: err.message || err.toString()\n }));\n });\n\n let isAnimating = false;\n const originalNext = rendition.next.bind(rendition);\n const originalPrev = rendition.prev.bind(rendition);\n\n rendition.next = function() {\n if (isAnimating) return;\n isAnimating = true;\n \n const container = rendition.manager.container;\n container.style.transition = 'opacity 0.2s ease-out';\n container.style.opacity = '0.4';\n \n setTimeout(() => {\n originalNext();\n setTimeout(() => {\n container.style.opacity = '1';\n setTimeout(() => {\n container.style.transition = '';\n isAnimating = false;\n }, 200);\n }, 50);\n }, 100);\n };\n\n rendition.prev = function() {\n if (isAnimating) return;\n isAnimating = true;\n \n const container = rendition.manager.container;\n container.style.transition = 'opacity 0.2s ease-out';\n container.style.opacity = '0.4';\n \n setTimeout(() => {\n originalPrev();\n setTimeout(() => {\n container.style.opacity = '1';\n setTimeout(() => {\n container.style.transition = '';\n isAnimating = false;\n }, 200);\n }, 50);\n }, 100);\n };\n\n rendition.on('started', () => {\n rendition.themes.register({ theme: theme });\n rendition.themes.select('theme');\n });\n\n rendition.on(\"relocated\", function (location) {\n var percent = book.locations.percentageFromCfi(location.start.cfi);\n var percentage = Math.floor(percent * 100);\n var chapter = getChapter(location);\n\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onLocationChange\",\n totalLocations: book.locations.total,\n currentLocation: location,\n progress: percentage,\n currentSection: chapter,\n }));\n\n if (location.atStart) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onBeginning\",\n }));\n }\n\n if (location.atEnd) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: \"onFinish\",\n }));\n }\n });\n\n rendition.on(\"orientationchange\", function (orientation) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: 'onOrientationChange',\n orientation: orientation\n }));\n });\n\n rendition.on(\"rendered\", function (section) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: 'onRendered',\n section: section,\n currentSection: book.navigation.get(section.href),\n }));\n });\n\n rendition.on(\"layout\", function (layout) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: 'onLayout',\n layout: layout,\n }));\n });\n\n rendition.on(\"selected\", function (cfiRange, contents) {\n book.getRange(cfiRange).then(function (range) {\n if (range) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: 'onSelected',\n cfiRange: cfiRange,\n text: range.toString(),\n }));\n }\n });\n });\n\n rendition.on(\"resized\", function (layout) {\n reactNativeWebview.postMessage(JSON.stringify({\n type: 'onResized',\n layout: layout,\n }));\n });\n </script>\n </body>\n</html>\n";
|
|
2
2
|
export default _default;
|
|
3
3
|
//# sourceMappingURL=template.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../../src/constants/template.ts"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../../src/constants/template.ts"],"names":[],"mappings":";AAAA,wBA8YE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloadEpub.d.ts","sourceRoot":"","sources":["../../../../src/helpers/downloadEpub.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,GACvB,KAAK,MAAM,EACX,UAAU,MAAM,KACf,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"downloadEpub.d.ts","sourceRoot":"","sources":["../../../../src/helpers/downloadEpub.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,GACvB,KAAK,MAAM,EACX,UAAU,MAAM,KACf,OAAO,CAAC,MAAM,CAuBhB,CAAC"}
|
package/package.json
CHANGED
|
@@ -38,7 +38,7 @@ const Reader = ({
|
|
|
38
38
|
onWebViewMessage,
|
|
39
39
|
}: ReaderProps) => {
|
|
40
40
|
const [templateUri, setTemplateUri] = useState<string>('');
|
|
41
|
-
const [isReaderReady, setIsReaderReady] = useState(false);
|
|
41
|
+
// const [isReaderReady, setIsReaderReady] = useState(false);
|
|
42
42
|
|
|
43
43
|
const {
|
|
44
44
|
registerBook,
|
|
@@ -108,7 +108,7 @@ const Reader = ({
|
|
|
108
108
|
|
|
109
109
|
return onLocationsReady(props.epubKey, parsedEvent.locations);
|
|
110
110
|
case 'onReady':
|
|
111
|
-
setIsReaderReady(true);
|
|
111
|
+
// setIsReaderReady(true);
|
|
112
112
|
setIsLoading(false);
|
|
113
113
|
if (initialLocation) {
|
|
114
114
|
goToLocation(initialLocation);
|
|
@@ -139,13 +139,13 @@ const Reader = ({
|
|
|
139
139
|
};
|
|
140
140
|
|
|
141
141
|
const handleOnSwipeLeft = () => {
|
|
142
|
-
if (!isReaderReady) return;
|
|
142
|
+
// if (!isReaderReady) return;
|
|
143
143
|
onSwipeLeft?.();
|
|
144
144
|
goNext();
|
|
145
145
|
};
|
|
146
146
|
|
|
147
147
|
const handleOnSwipeRight = () => {
|
|
148
|
-
if (!isReaderReady) return;
|
|
148
|
+
// if (!isReaderReady) return;
|
|
149
149
|
onSwipeRight?.();
|
|
150
150
|
goPrevious();
|
|
151
151
|
};
|
|
@@ -153,7 +153,7 @@ const Reader = ({
|
|
|
153
153
|
const handleOnPinch = (
|
|
154
154
|
e: GestureUpdateEvent<PinchGestureHandlerEventPayload>
|
|
155
155
|
) => {
|
|
156
|
-
if (!isReaderReady) return;
|
|
156
|
+
// if (!isReaderReady) return;
|
|
157
157
|
|
|
158
158
|
const fontSizeValue = parseInt(fontSize.replace('pt', ''), 10);
|
|
159
159
|
|
|
@@ -166,14 +166,23 @@ const Reader = ({
|
|
|
166
166
|
onPinch?.(e);
|
|
167
167
|
};
|
|
168
168
|
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
[
|
|
172
|
-
|
|
169
|
+
const epubFileName = useMemo(() => {
|
|
170
|
+
const splited = src.split('/').pop() || 'book.epub';
|
|
171
|
+
const cleanName = splited.split('?')[0] || 'book.epub';
|
|
172
|
+
const decoded = decodeURIComponent(cleanName)
|
|
173
|
+
.replace(' ', '_')
|
|
174
|
+
.replace(',', '_')
|
|
175
|
+
.replace(/[^a-zA-Z0-9._-]/g, '');
|
|
173
176
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
return decoded;
|
|
178
|
+
}, [src]);
|
|
179
|
+
|
|
180
|
+
const htmlTemplateName = useMemo(
|
|
181
|
+
() =>
|
|
182
|
+
epubFileName
|
|
183
|
+
.replace('.epub', '-template.html')
|
|
184
|
+
.replace('.zip', '-template.html'),
|
|
185
|
+
[epubFileName]
|
|
177
186
|
);
|
|
178
187
|
|
|
179
188
|
const handleBookRef = useCallback(
|
|
@@ -192,7 +201,7 @@ const Reader = ({
|
|
|
192
201
|
const prepareReader = async () => {
|
|
193
202
|
try {
|
|
194
203
|
setIsLoading(true);
|
|
195
|
-
setIsReaderReady(false);
|
|
204
|
+
// setIsReaderReady(false);
|
|
196
205
|
setTemplateUri('');
|
|
197
206
|
|
|
198
207
|
const [, jszip, epubjs] = await loadScripts();
|
|
@@ -235,7 +244,7 @@ const Reader = ({
|
|
|
235
244
|
setIsLoading,
|
|
236
245
|
]);
|
|
237
246
|
|
|
238
|
-
if (
|
|
247
|
+
if (!templateUri) {
|
|
239
248
|
return LoaderComponent ? (
|
|
240
249
|
<LoaderComponent />
|
|
241
250
|
) : (
|
|
@@ -247,7 +256,7 @@ const Reader = ({
|
|
|
247
256
|
}
|
|
248
257
|
|
|
249
258
|
return (
|
|
250
|
-
|
|
259
|
+
<View style={styles.container}>
|
|
251
260
|
<GestureHandler
|
|
252
261
|
onSwipeLeft={handleOnSwipeLeft}
|
|
253
262
|
onSwipeRight={handleOnSwipeRight}
|
|
@@ -272,7 +281,19 @@ const Reader = ({
|
|
|
272
281
|
style={styles.container}
|
|
273
282
|
/>
|
|
274
283
|
</GestureHandler>
|
|
275
|
-
|
|
284
|
+
|
|
285
|
+
{isLoading &&
|
|
286
|
+
(LoaderComponent ? (
|
|
287
|
+
<View style={styles.loaderOverlay}>
|
|
288
|
+
<LoaderComponent />
|
|
289
|
+
</View>
|
|
290
|
+
) : (
|
|
291
|
+
<View style={styles.loaderOverlay}>
|
|
292
|
+
<ActivityIndicator size="large" />
|
|
293
|
+
<Text>Przygotowuję książkę...</Text>
|
|
294
|
+
</View>
|
|
295
|
+
))}
|
|
296
|
+
</View>
|
|
276
297
|
);
|
|
277
298
|
};
|
|
278
299
|
|
|
@@ -285,6 +306,11 @@ const styles = StyleSheet.create({
|
|
|
285
306
|
justifyContent: 'center',
|
|
286
307
|
alignItems: 'center',
|
|
287
308
|
},
|
|
309
|
+
loaderOverlay: {
|
|
310
|
+
...StyleSheet.absoluteFillObject,
|
|
311
|
+
justifyContent: 'center',
|
|
312
|
+
alignItems: 'center',
|
|
313
|
+
},
|
|
288
314
|
});
|
|
289
315
|
|
|
290
316
|
export default Reader;
|