UNPKG

@epubjs-react-native/core

Version:

A digital book reader in .opf .epub format for react native using epub.js library inside a webview.

448 lines (447 loc) 13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.View = View; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeWebview = require("react-native-webview"); var _context = require("./context"); var _OpeningBook = require("./utils/OpeningBook"); var _internalEvents = _interopRequireDefault(require("./utils/internalEvents.util")); var _GestureHandler = require("./utils/GestureHandler"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function View({ templateUri, allowedUris, onStarted = () => {}, onReady = () => {}, onDisplayError = () => {}, onResized = () => {}, onLocationChange = () => {}, onRendered = () => {}, onSearch = () => {}, onLocationsReady = () => {}, onSelected = () => {}, onPressAnnotation = () => {}, onOrientationChange = () => {}, onLayout = () => {}, onNavigationLoaded = () => {}, onBeginning = () => {}, onFinish = () => {}, onPress = () => {}, onSingleTap = () => {}, onDoublePress = () => {}, onDoubleTap = () => {}, onLongPress = () => {}, width, height, initialLocation, enableSwipe = true, onSwipeLeft = () => {}, onSwipeRight = () => {}, onSwipeUp = () => {}, onSwipeDown = () => {}, defaultTheme = _context.defaultTheme, renderOpeningBookComponent = () => /*#__PURE__*/_react.default.createElement(_OpeningBook.OpeningBook, { width: width, height: height, backgroundColor: defaultTheme.body.background }), openingBookComponentContainerStyle = { width: width || _reactNative.Dimensions.get('screen').width, height: height || _reactNative.Dimensions.get('screen').height }, onPressExternalLink, menuItems, onAddAnnotation = () => {}, onChangeAnnotations = () => {}, initialAnnotations, onAddBookmark = () => {}, onRemoveBookmark = () => {}, onUpdateBookmark = () => {}, onChangeBookmarks = () => {}, onIsBookmarked = () => {}, initialBookmarks, injectedJavascript, getInjectionJavascriptFn, onWebViewMessage, waitForLocationsReady = false, keepScrollOffsetOnLocationChange, flow, onChangeSection = () => {} }) { const { registerBook, setTotalLocations, setCurrentLocation, setMeta, setProgress, setLocations, setAtStart, setAtEnd, goNext, goPrevious, isRendering, setIsRendering, goToLocation, changeTheme, setKey, setSearchResults, theme, removeSelection, setAnnotations, setInitialAnnotations, section, setSection, setToc, setLandmarks, setBookmarks, bookmarks, setIsBookmarked, currentLocation: currLoc, setIsSearching, setFlow } = (0, _react.useContext)(_context.ReaderContext); const book = (0, _react.useRef)(null); const [selectedText, setSelectedText] = (0, _react.useState)({ cfiRange: '', cfiRangeText: '' }); (0, _react.useEffect)(() => { setFlow(flow || 'auto'); }, [flow, setFlow]); (0, _react.useEffect)(() => { if (getInjectionJavascriptFn && book.current) { getInjectionJavascriptFn(book.current.injectJavaScript); } }, [getInjectionJavascriptFn]); const handleChangeIsBookmarked = (items, currentLoc = currLoc) => { const isBookmarked = items.some(bookmark => bookmark.location.start.cfi === currentLoc?.start.cfi && bookmark.location.end.cfi === currentLoc?.end.cfi); setIsBookmarked(isBookmarked); onIsBookmarked(isBookmarked); }; const onMessage = event => { const parsedEvent = JSON.parse(event.nativeEvent.data); const { type } = parsedEvent; if (!_internalEvents.default.includes(type) && onWebViewMessage) { return onWebViewMessage(parsedEvent); } delete parsedEvent.type; if (type === 'meta') { const { metadata } = parsedEvent; setMeta(metadata); } if (type === 'onStarted') { setIsRendering(true); changeTheme(defaultTheme); return onStarted(); } if (type === 'onReady') { const { totalLocations, currentLocation, progress } = parsedEvent; if (!waitForLocationsReady) { setIsRendering(false); } if (initialAnnotations) { setInitialAnnotations(initialAnnotations); } if (initialLocation) { goToLocation(initialLocation); } if (injectedJavascript) { book.current?.injectJavaScript(injectedJavascript); } return onReady(totalLocations, currentLocation, progress); } if (type === 'onDisplayError') { const { reason } = parsedEvent; setIsRendering(false); return onDisplayError(reason); } if (type === 'onResized') { const { layout } = parsedEvent; return onResized(layout); } if (type === 'onLocationChange') { const { totalLocations, currentLocation, progress, currentSection } = parsedEvent; setTotalLocations(totalLocations); setCurrentLocation(currentLocation); setProgress(progress); setSection(currentSection); if (section?.href !== currentSection?.href) { onChangeSection(currentSection); } handleChangeIsBookmarked(bookmarks, currentLocation); if (currentLocation.atStart) setAtStart(true);else if (currentLocation.atEnd) setAtEnd(true);else { setAtStart(false); setAtEnd(false); } return onLocationChange(totalLocations, currentLocation, progress, currentSection); } if (type === 'onSearch') { const { results, totalResults } = parsedEvent; setSearchResults({ results, totalResults }); setIsSearching(false); return onSearch(results, totalResults); } if (type === 'onLocationsReady') { const { epubKey, totalLocations, currentLocation, progress } = parsedEvent; setLocations(parsedEvent.locations); setKey(epubKey); setTotalLocations(totalLocations); setCurrentLocation(currentLocation); setProgress(progress); if (waitForLocationsReady) { setIsRendering(false); } return onLocationsReady(epubKey, parsedEvent.locations); } if (type === 'onSelected') { const { cfiRange, text } = parsedEvent; setSelectedText({ cfiRange, cfiRangeText: text }); return onSelected(text, cfiRange); } if (type === 'onOrientationChange') { const { orientation } = parsedEvent; return onOrientationChange(orientation); } if (type === 'onBeginning') { setAtStart(true); return onBeginning(); } if (type === 'onFinish') { setAtEnd(true); return onFinish(); } if (type === 'onRendered') { const { currentSection } = parsedEvent; return onRendered(parsedEvent.section, currentSection); } if (type === 'onLayout') { const { layout } = parsedEvent; return onLayout(layout); } if (type === 'onNavigationLoaded') { const { toc, landmarks } = parsedEvent; setToc(toc); setLandmarks(landmarks); return onNavigationLoaded({ toc, landmarks }); } if (type === 'onAddAnnotation') { const { annotation } = parsedEvent; return onAddAnnotation(annotation); } if (type === 'onChangeAnnotations') { const { annotations } = parsedEvent; setAnnotations(annotations); return onChangeAnnotations(annotations); } if (type === 'onSetInitialAnnotations') { const { annotations } = parsedEvent; setAnnotations(annotations); return () => {}; } if (type === 'onPressAnnotation') { const { annotation } = parsedEvent; return onPressAnnotation(annotation); } if (type === 'onAddBookmark') { const { bookmark } = parsedEvent; setBookmarks([...bookmarks, bookmark]); onAddBookmark(bookmark); handleChangeIsBookmarked([...bookmarks, bookmark]); return onChangeBookmarks([...bookmarks, bookmark]); } if (type === 'onRemoveBookmark') { const { bookmark } = parsedEvent; onRemoveBookmark(bookmark); handleChangeIsBookmarked(bookmarks.filter(({ id }) => id !== bookmark.id)); return onChangeBookmarks(bookmarks.filter(({ id }) => id !== bookmark.id)); } if (type === 'onRemoveBookmarks') { handleChangeIsBookmarked([]); return onChangeBookmarks([]); } if (type === 'onUpdateBookmark') { const { bookmark } = parsedEvent; const Bookmarks = bookmarks; const index = Bookmarks.findIndex(item => item.id === bookmark.id); Bookmarks[index] = bookmark; onUpdateBookmark(bookmark); handleChangeIsBookmarked(Bookmarks); return onChangeBookmarks(Bookmarks); } return () => {}; }; const handleOnCustomMenuSelection = event => { menuItems?.forEach(item => { if (event.nativeEvent.label === item.label) { const removeSelectionMenu = item.action(selectedText.cfiRange, selectedText.cfiRangeText); if (removeSelectionMenu) { removeSelection(); } } }); }; const handleOnShouldStartLoadWithRequest = request => { if (!isRendering && request.mainDocumentURL && request.url !== request.mainDocumentURL) { goToLocation(request.url.replace(request.mainDocumentURL, '')); } if ((request.url.includes('mailto:') || request.url.includes('tel:')) && onPressExternalLink) { onPressExternalLink(request.url); } return true; }; (0, _react.useEffect)(() => { if (initialBookmarks) { setBookmarks(initialBookmarks); } }, [initialBookmarks, setBookmarks]); (0, _react.useEffect)(() => { if (book.current) registerBook(book.current); }, [registerBook]); return /*#__PURE__*/_react.default.createElement(_GestureHandler.GestureHandler, { width: width, height: height, onSingleTap: () => { onPress(); onSingleTap(); }, onDoubleTap: () => { onDoublePress(); onDoubleTap(); }, onLongPress: onLongPress, onSwipeLeft: () => { if (enableSwipe) { goNext({ keepScrollOffset: keepScrollOffsetOnLocationChange }); onSwipeLeft(); } }, onSwipeRight: () => { if (enableSwipe) { goPrevious({ keepScrollOffset: keepScrollOffsetOnLocationChange }); onSwipeRight(); } }, onSwipeUp: () => { if (enableSwipe) { onSwipeUp(); } }, onSwipeDown: () => { if (enableSwipe) { onSwipeDown(); } } }, isRendering && /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { ...openingBookComponentContainerStyle, position: 'absolute', zIndex: 2 } }, renderOpeningBookComponent()), /*#__PURE__*/_react.default.createElement(_reactNativeWebview.WebView, { ref: book, source: { uri: templateUri }, showsVerticalScrollIndicator: false, javaScriptEnabled: true, originWhitelist: ['*'], scrollEnabled: false, mixedContentMode: "compatibility", onMessage: onMessage, menuItems: menuItems?.map((item, key) => ({ label: item.label, key: key.toString() })), onCustomMenuSelection: handleOnCustomMenuSelection, allowingReadAccessToURL: allowedUris, allowUniversalAccessFromFileURLs: true, allowFileAccessFromFileURLs: true, allowFileAccess: true, javaScriptCanOpenWindowsAutomatically: true, onOpenWindow: event => { event.preventDefault(); if (onPressExternalLink) { onPressExternalLink(event.nativeEvent.targetUrl); } }, onShouldStartLoadWithRequest: handleOnShouldStartLoadWithRequest, style: { width, backgroundColor: theme.body.background, height } })); }