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.
@@ -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,wBAubE"}
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,CAehB,CAAC"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-simple-epub-reader",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Simple ePub renderer for React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -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 htmlTemplateName = useMemo(
170
- () => src.split('/').pop()?.replace('.epub', '.html') || 'index.html',
171
- [src]
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
- const epubFileName = useMemo(
175
- () => src.split('/').pop() || 'book.epub',
176
- [src]
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 (isLoading || !templateUri) {
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;