react-native-simple-epub-reader 0.1.0

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.
Files changed (90) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +37 -0
  3. package/lib/module/components/GestureHandler/index.js +39 -0
  4. package/lib/module/components/GestureHandler/index.js.map +1 -0
  5. package/lib/module/components/Reader.js +207 -0
  6. package/lib/module/components/Reader.js.map +1 -0
  7. package/lib/module/constants/template.js +402 -0
  8. package/lib/module/constants/template.js.map +1 -0
  9. package/lib/module/constants/theme.js +43 -0
  10. package/lib/module/constants/theme.js.map +1 -0
  11. package/lib/module/context/ReaderContext.js +213 -0
  12. package/lib/module/context/ReaderContext.js.map +1 -0
  13. package/lib/module/context/types.js +4 -0
  14. package/lib/module/context/types.js.map +1 -0
  15. package/lib/module/helpers/downloadEpub.js +17 -0
  16. package/lib/module/helpers/downloadEpub.js.map +1 -0
  17. package/lib/module/helpers/loadScripts.js +21 -0
  18. package/lib/module/helpers/loadScripts.js.map +1 -0
  19. package/lib/module/helpers/saveTemplateToFile.js +21 -0
  20. package/lib/module/helpers/saveTemplateToFile.js.map +1 -0
  21. package/lib/module/helpers/webViewInjectFunctions.js +14 -0
  22. package/lib/module/helpers/webViewInjectFunctions.js.map +1 -0
  23. package/lib/module/hooks/useInjectWebviewVariables.js +20 -0
  24. package/lib/module/hooks/useInjectWebviewVariables.js.map +1 -0
  25. package/lib/module/hooks/useReaderState.js +117 -0
  26. package/lib/module/hooks/useReaderState.js.map +1 -0
  27. package/lib/module/index.js +6 -0
  28. package/lib/module/index.js.map +1 -0
  29. package/lib/module/package.json +1 -0
  30. package/lib/module/scripts/epub.js +14326 -0
  31. package/lib/module/scripts/epub.js.map +1 -0
  32. package/lib/module/scripts/jszip.js +6646 -0
  33. package/lib/module/scripts/jszip.js.map +1 -0
  34. package/lib/module/types/index.js +14 -0
  35. package/lib/module/types/index.js.map +1 -0
  36. package/lib/module/types/state.types.js +23 -0
  37. package/lib/module/types/state.types.js.map +1 -0
  38. package/lib/typescript/package.json +1 -0
  39. package/lib/typescript/src/components/GestureHandler/index.d.ts +5 -0
  40. package/lib/typescript/src/components/GestureHandler/index.d.ts.map +1 -0
  41. package/lib/typescript/src/components/Reader.d.ts +4 -0
  42. package/lib/typescript/src/components/Reader.d.ts.map +1 -0
  43. package/lib/typescript/src/constants/template.d.ts +3 -0
  44. package/lib/typescript/src/constants/template.d.ts.map +1 -0
  45. package/lib/typescript/src/constants/theme.d.ts +3 -0
  46. package/lib/typescript/src/constants/theme.d.ts.map +1 -0
  47. package/lib/typescript/src/context/ReaderContext.d.ts +7 -0
  48. package/lib/typescript/src/context/ReaderContext.d.ts.map +1 -0
  49. package/lib/typescript/src/context/types.d.ts +60 -0
  50. package/lib/typescript/src/context/types.d.ts.map +1 -0
  51. package/lib/typescript/src/helpers/downloadEpub.d.ts +2 -0
  52. package/lib/typescript/src/helpers/downloadEpub.d.ts.map +1 -0
  53. package/lib/typescript/src/helpers/loadScripts.d.ts +2 -0
  54. package/lib/typescript/src/helpers/loadScripts.d.ts.map +1 -0
  55. package/lib/typescript/src/helpers/saveTemplateToFile.d.ts +3 -0
  56. package/lib/typescript/src/helpers/saveTemplateToFile.d.ts.map +1 -0
  57. package/lib/typescript/src/helpers/webViewInjectFunctions.d.ts +4 -0
  58. package/lib/typescript/src/helpers/webViewInjectFunctions.d.ts.map +1 -0
  59. package/lib/typescript/src/hooks/useInjectWebviewVariables.d.ts +12 -0
  60. package/lib/typescript/src/hooks/useInjectWebviewVariables.d.ts.map +1 -0
  61. package/lib/typescript/src/hooks/useReaderState.d.ts +6 -0
  62. package/lib/typescript/src/hooks/useReaderState.d.ts.map +1 -0
  63. package/lib/typescript/src/index.d.ts +4 -0
  64. package/lib/typescript/src/index.d.ts.map +1 -0
  65. package/lib/typescript/src/scripts/epub.d.ts +3 -0
  66. package/lib/typescript/src/scripts/epub.d.ts.map +1 -0
  67. package/lib/typescript/src/scripts/jszip.d.ts +3 -0
  68. package/lib/typescript/src/scripts/jszip.d.ts.map +1 -0
  69. package/lib/typescript/src/types/index.d.ts +72 -0
  70. package/lib/typescript/src/types/index.d.ts.map +1 -0
  71. package/lib/typescript/src/types/state.types.d.ts +83 -0
  72. package/lib/typescript/src/types/state.types.d.ts.map +1 -0
  73. package/package.json +171 -0
  74. package/src/components/GestureHandler/index.tsx +63 -0
  75. package/src/components/Reader.tsx +262 -0
  76. package/src/constants/template.ts +399 -0
  77. package/src/constants/theme.ts +42 -0
  78. package/src/context/ReaderContext.tsx +265 -0
  79. package/src/context/types.ts +62 -0
  80. package/src/helpers/downloadEpub.ts +21 -0
  81. package/src/helpers/loadScripts.ts +22 -0
  82. package/src/helpers/saveTemplateToFile.ts +20 -0
  83. package/src/helpers/webViewInjectFunctions.ts +18 -0
  84. package/src/hooks/useInjectWebviewVariables.ts +51 -0
  85. package/src/hooks/useReaderState.ts +118 -0
  86. package/src/index.tsx +3 -0
  87. package/src/scripts/epub.ts +14323 -0
  88. package/src/scripts/jszip.ts +6643 -0
  89. package/src/types/index.ts +83 -0
  90. package/src/types/state.types.ts +86 -0
@@ -0,0 +1,72 @@
1
+ import type { GestureUpdateEvent, PinchGestureHandlerEventPayload } from 'react-native-gesture-handler';
2
+ export interface LocationChangeData {
3
+ totalLocations: number;
4
+ currentLocation: Location;
5
+ progress: number;
6
+ currentSection: Section | null;
7
+ }
8
+ export type Location = {
9
+ atStart?: boolean;
10
+ atEnd?: boolean;
11
+ end: {
12
+ cfi: ePubCfi;
13
+ displayed: {
14
+ page: number;
15
+ total: number;
16
+ };
17
+ href: string;
18
+ index: number;
19
+ location: number;
20
+ percentage: number;
21
+ };
22
+ start: {
23
+ cfi: ePubCfi;
24
+ displayed: {
25
+ page: number;
26
+ total: number;
27
+ };
28
+ href: string;
29
+ index: number;
30
+ location: number;
31
+ percentage: number;
32
+ };
33
+ };
34
+ export type Section = {
35
+ id: string;
36
+ href: string;
37
+ label: string;
38
+ parent?: any;
39
+ subitems: any[];
40
+ };
41
+ /**
42
+ * @example
43
+ * ````
44
+ * epubcfi(/6/6!/4/2,/2/2/1:0,/4[q1]/2/14/2/1:14)
45
+ * ````
46
+ */
47
+ export type ePubCfi = string;
48
+ export declare enum SourceType {
49
+ EPUB = "epub"
50
+ }
51
+ export type Theme = {
52
+ [key: string]: {
53
+ [key: string]: string;
54
+ };
55
+ };
56
+ export interface GestureHandlerProps {
57
+ onSwipeLeft?: () => void;
58
+ onSwipeRight?: () => void;
59
+ onTap?: () => void;
60
+ onPinch?: (e: GestureUpdateEvent<PinchGestureHandlerEventPayload>) => void;
61
+ }
62
+ export type ReaderProps = {
63
+ src: string;
64
+ initialLocation?: string;
65
+ onLocationChange?: (data: LocationChangeData) => void;
66
+ onLocationsReady?: (epubKey: string, locations: ePubCfi[]) => void;
67
+ onFinish?: () => void;
68
+ onBeginning?: () => void;
69
+ LoaderComponent?: React.ComponentType;
70
+ } & GestureHandlerProps;
71
+ export type Flow = 'paginated' | 'scrolled-doc';
72
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,+BAA+B,EAChC,MAAM,8BAA8B,CAAC;AAEtC,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,QAAQ,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE;QACH,GAAG,EAAE,OAAO,CAAC;QACb,SAAS,EAAE;YACT,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,KAAK,EAAE;QACL,GAAG,EAAE,OAAO,CAAC;QACb,SAAS,EAAE;YACT,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,GAAG,EAAE,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,oBAAY,UAAU;IACpB,IAAI,SAAS;CACd;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,CAAC;CACH,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,+BAA+B,CAAC,KAAK,IAAI,CAAC;CAC5E;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtD,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,eAAe,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CACvC,GAAG,mBAAmB,CAAC;AAExB,MAAM,MAAM,IAAI,GAAG,WAAW,GAAG,cAAc,CAAC"}
@@ -0,0 +1,83 @@
1
+ import type { ePubCfi, Flow, Location, Section, Theme } from './index';
2
+ export declare enum Actions {
3
+ CHANGE_FONT_SIZE = "CHANGE_FONT_SIZE",
4
+ SET_AT_START = "SET_AT_START",
5
+ SET_AT_END = "SET_AT_END",
6
+ SET_KEY = "SET_KEY",
7
+ SET_TOTAL_LOCATIONS = "SET_TOTAL_LOCATIONS",
8
+ SET_CURRENT_LOCATION = "SET_CURRENT_LOCATION",
9
+ SET_META = "SET_META",
10
+ SET_PROGRESS = "SET_PROGRESS",
11
+ SET_LOCATIONS = "SET_LOCATIONS",
12
+ SET_IS_LOADING = "SET_IS_LOADING",
13
+ SET_IS_RENDERING = "SET_IS_RENDERING",
14
+ SET_SECTION = "SET_SECTION",
15
+ SET_TOC = "SET_TOC",
16
+ SET_LANDMARKS = "SET_LANDMARKS",
17
+ SET_FLOW = "SET_FLOW",
18
+ CHANGE_THEME = "CHANGE_THEME",
19
+ CHANGE_FONT_FAMILY = "CHANGE_FONT_FAMILY"
20
+ }
21
+ type BookPayload = {
22
+ [Actions.CHANGE_THEME]: Theme;
23
+ [Actions.CHANGE_FONT_SIZE]: string;
24
+ [Actions.SET_AT_START]: boolean;
25
+ [Actions.SET_AT_END]: boolean;
26
+ [Actions.SET_KEY]: string;
27
+ [Actions.SET_TOTAL_LOCATIONS]: number;
28
+ [Actions.SET_CURRENT_LOCATION]: Location;
29
+ [Actions.SET_META]: {
30
+ cover: string | ArrayBuffer | null | undefined;
31
+ author: string;
32
+ title: string;
33
+ description: string;
34
+ language: string;
35
+ publisher: string;
36
+ rights: string;
37
+ };
38
+ [Actions.SET_PROGRESS]: number;
39
+ [Actions.SET_LOCATIONS]: ePubCfi[];
40
+ [Actions.SET_IS_LOADING]: boolean;
41
+ [Actions.SET_IS_RENDERING]: boolean;
42
+ [Actions.SET_SECTION]: Section | null;
43
+ [Actions.SET_FLOW]: Flow;
44
+ [Actions.CHANGE_FONT_FAMILY]: string;
45
+ };
46
+ type ActionMap<M extends {
47
+ [index: string]: unknown;
48
+ }> = {
49
+ [Key in keyof M]: M[Key] extends undefined ? {
50
+ type: Key;
51
+ } : {
52
+ type: Key;
53
+ payload: M[Key];
54
+ };
55
+ };
56
+ export type BookActions = ActionMap<BookPayload>[keyof ActionMap<BookPayload>];
57
+ export type InitialState = {
58
+ theme: Theme;
59
+ fontFamily: string;
60
+ fontSize: string;
61
+ atStart: boolean;
62
+ atEnd: boolean;
63
+ key: string;
64
+ totalLocations: number;
65
+ currentLocation: Location | null;
66
+ meta: {
67
+ cover: string | ArrayBuffer | null | undefined;
68
+ author: string;
69
+ title: string;
70
+ description: string;
71
+ language: string;
72
+ publisher: string;
73
+ rights: string;
74
+ };
75
+ progress: number;
76
+ locations: ePubCfi[];
77
+ isLoading: boolean;
78
+ isRendering: boolean;
79
+ section: Section | null;
80
+ flow: Flow;
81
+ };
82
+ export {};
83
+ //# sourceMappingURL=state.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.types.d.ts","sourceRoot":"","sources":["../../../../src/types/state.types.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,171 @@
1
+ {
2
+ "name": "react-native-simple-epub-reader",
3
+ "version": "0.1.0",
4
+ "description": "Simple ePub renderer for React Native",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "watch": "bob build --watch",
36
+ "example": "yarn workspace react-native-simple-epub-reader-example",
37
+ "clean": "del-cli lib",
38
+ "prepare": "bob build",
39
+ "typecheck": "tsc",
40
+ "test": "jest",
41
+ "release": "release-it --only-version",
42
+ "lint": "eslint \"**/*.{js,ts,tsx}\""
43
+ },
44
+ "keywords": [
45
+ "react-native",
46
+ "ios",
47
+ "android"
48
+ ],
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/marcinradzik81-ui/react-native-simple-epub-reader.git"
52
+ },
53
+ "author": "Marcin Radzik <marcinradzik81@gmail.com> (https://github.com/marcinradzik81-ui)",
54
+ "license": "MIT",
55
+ "bugs": {
56
+ "url": "https://github.com/marcinradzik81-ui/react-native-simple-epub-reader/issues"
57
+ },
58
+ "homepage": "https://github.com/marcinradzik81-ui/react-native-simple-epub-reader#readme",
59
+ "publishConfig": {
60
+ "registry": "https://registry.npmjs.org/"
61
+ },
62
+ "devDependencies": {
63
+ "@commitlint/config-conventional": "^20.5.0",
64
+ "@eslint/compat": "^2.0.3",
65
+ "@eslint/eslintrc": "^3.3.5",
66
+ "@eslint/js": "^10.0.1",
67
+ "@jest/globals": "^30.0.0",
68
+ "@react-native/babel-preset": "0.85.0",
69
+ "@react-native/eslint-config": "0.85.0",
70
+ "@react-native/jest-preset": "0.85.0",
71
+ "@release-it/conventional-changelog": "^10.0.6",
72
+ "@types/react": "^19.2.0",
73
+ "commitlint": "^20.5.0",
74
+ "del-cli": "^7.0.0",
75
+ "eslint": "^9.39.4",
76
+ "eslint-config-prettier": "^10.1.8",
77
+ "eslint-plugin-ft-flow": "^3.0.11",
78
+ "eslint-plugin-prettier": "^5.5.5",
79
+ "expo-file-system": "^55.0.16",
80
+ "jest": "^30.3.0",
81
+ "lefthook": "^2.1.4",
82
+ "prettier": "^3.8.1",
83
+ "react": "19.1.0",
84
+ "react-native": "0.81.5",
85
+ "react-native-builder-bob": "^0.41.0",
86
+ "react-native-gesture-handler": "^2.31.1",
87
+ "react-native-webview": "^13.16.1",
88
+ "release-it": "^19.2.4",
89
+ "turbo": "^2.8.21",
90
+ "typescript": "^6.0.2"
91
+ },
92
+ "peerDependencies": {
93
+ "expo-file-system": "*",
94
+ "react": "*",
95
+ "react-native": "*",
96
+ "react-native-gesture-handler": "*",
97
+ "react-native-webview": "*",
98
+ "@expo/vector-icons": "*"
99
+ },
100
+ "workspaces": [
101
+ "example"
102
+ ],
103
+ "packageManager": "yarn@4.11.0",
104
+ "react-native-builder-bob": {
105
+ "source": "src",
106
+ "output": "lib",
107
+ "targets": [
108
+ [
109
+ "module",
110
+ {
111
+ "esm": true
112
+ }
113
+ ],
114
+ [
115
+ "typescript",
116
+ {
117
+ "project": "tsconfig.build.json"
118
+ }
119
+ ]
120
+ ]
121
+ },
122
+ "jest": {
123
+ "preset": "@react-native/jest-preset",
124
+ "modulePathIgnorePatterns": [
125
+ "<rootDir>/example/node_modules",
126
+ "<rootDir>/lib/"
127
+ ]
128
+ },
129
+ "commitlint": {
130
+ "extends": [
131
+ "@commitlint/config-conventional"
132
+ ]
133
+ },
134
+ "release-it": {
135
+ "git": {
136
+ "commitMessage": "chore: release ${version}",
137
+ "tagName": "v${version}"
138
+ },
139
+ "npm": {
140
+ "publish": true
141
+ },
142
+ "github": {
143
+ "release": true
144
+ },
145
+ "plugins": {
146
+ "@release-it/conventional-changelog": {
147
+ "preset": {
148
+ "name": "angular"
149
+ }
150
+ }
151
+ }
152
+ },
153
+ "prettier": {
154
+ "quoteProps": "consistent",
155
+ "singleQuote": true,
156
+ "tabWidth": 2,
157
+ "trailingComma": "es5",
158
+ "useTabs": false
159
+ },
160
+ "create-react-native-library": {
161
+ "type": "library",
162
+ "languages": "js",
163
+ "tools": [
164
+ "jest",
165
+ "lefthook",
166
+ "release-it",
167
+ "eslint"
168
+ ],
169
+ "version": "0.61.0"
170
+ }
171
+ }
@@ -0,0 +1,63 @@
1
+ import type { FC, PropsWithChildren } from 'react';
2
+
3
+ import {
4
+ Directions,
5
+ Gesture,
6
+ GestureDetector,
7
+ GestureHandlerRootView,
8
+ } from 'react-native-gesture-handler';
9
+ import type { GestureHandlerProps } from '../../types';
10
+
11
+ const GestureHandler: FC<PropsWithChildren<GestureHandlerProps>> = ({
12
+ children,
13
+ onSwipeLeft,
14
+ onSwipeRight,
15
+ onTap,
16
+ onPinch,
17
+ }) => {
18
+ const swipeLeftGesture = Gesture.Fling()
19
+ .runOnJS(true)
20
+ .direction(Directions.LEFT)
21
+ .onEnd(() => {
22
+ onSwipeLeft?.();
23
+ });
24
+
25
+ const swipeRightGesture = Gesture.Fling()
26
+ .runOnJS(true)
27
+ .direction(Directions.RIGHT)
28
+ .onEnd(() => {
29
+ onSwipeRight?.();
30
+ });
31
+
32
+ const tapGesture = Gesture.Tap()
33
+ .runOnJS(true)
34
+ .maxDuration(250)
35
+ .onStart(() => {
36
+ onTap?.();
37
+ });
38
+
39
+ const pinchGesture = Gesture.Pinch()
40
+ .runOnJS(true)
41
+ .onUpdate((e) => {
42
+ onPinch?.(e);
43
+ });
44
+
45
+ const combinedGesture = Gesture.Race(
46
+ Gesture.Exclusive(swipeLeftGesture, swipeRightGesture),
47
+ tapGesture,
48
+ pinchGesture
49
+ );
50
+ return (
51
+ <GestureHandlerRootView style={styles.container}>
52
+ <GestureDetector gesture={combinedGesture}>{children}</GestureDetector>
53
+ </GestureHandlerRootView>
54
+ );
55
+ };
56
+
57
+ const styles = {
58
+ container: {
59
+ flex: 1,
60
+ },
61
+ };
62
+
63
+ export default GestureHandler;
@@ -0,0 +1,262 @@
1
+ import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
2
+ import { SourceType, type ReaderProps } from '../types';
3
+ import {
4
+ useCallback,
5
+ useContext,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ } from 'react';
11
+ import { loadScripts } from '../helpers/loadScripts';
12
+ import { saveTemplateToFile } from '../helpers/saveTemplateToFile';
13
+ import { downloadEpub } from '../helpers/downloadEpub';
14
+ import { Paths } from 'expo-file-system';
15
+ import { useInjectWebViewVariables } from '../hooks/useInjectWebviewVariables';
16
+ import WebView from 'react-native-webview';
17
+ import GestureHandler from './GestureHandler';
18
+ import { defaultTheme as initialTheme } from '../constants/theme';
19
+ import { ReaderContext } from '../context/ReaderContext';
20
+ import type {
21
+ GestureUpdateEvent,
22
+ PinchGestureHandlerEventPayload,
23
+ } from 'react-native-gesture-handler';
24
+
25
+ const Reader = ({
26
+ src,
27
+ onTap,
28
+ onSwipeLeft,
29
+ onSwipeRight,
30
+ initialLocation,
31
+ onLocationsReady = () => {},
32
+ onLocationChange = () => {},
33
+ onFinish = () => {},
34
+ onBeginning = () => {},
35
+ onPinch = () => {},
36
+ LoaderComponent,
37
+ }: ReaderProps) => {
38
+ const [templateUri, setTemplateUri] = useState<string>('');
39
+
40
+ const {
41
+ registerBook,
42
+ goNext,
43
+ goPrevious,
44
+ setMeta,
45
+ setLocations,
46
+ setTotalLocations,
47
+ setCurrentLocation,
48
+ setProgress,
49
+ goToLocation,
50
+ setAtEnd,
51
+ setAtStart,
52
+ fontSize,
53
+ changeFontSize,
54
+ setIsLoading,
55
+ isLoading,
56
+ } = useContext(ReaderContext);
57
+
58
+ const { injectWebViewVariables } = useInjectWebViewVariables();
59
+ const bookRef = useRef<WebView | null>(null);
60
+
61
+ const onMessage = (event: any) => {
62
+ const parsedEvent = JSON.parse(event.nativeEvent.data);
63
+
64
+ switch (parsedEvent.type) {
65
+ case 'onLocationChange':
66
+ const { totalLocations, currentLocation, progress, currentSection } =
67
+ parsedEvent;
68
+
69
+ if (currentLocation.atStart) setAtStart(true);
70
+ else if (currentLocation.atEnd) setAtEnd(true);
71
+ else {
72
+ setAtStart(false);
73
+ setAtEnd(false);
74
+ }
75
+
76
+ onLocationChange?.({
77
+ totalLocations,
78
+ currentLocation,
79
+ progress,
80
+ currentSection,
81
+ });
82
+ break;
83
+ case 'meta':
84
+ const { metadata } = parsedEvent;
85
+ setMeta(metadata);
86
+ break;
87
+ case 'onLocationsReady':
88
+ const props = parsedEvent;
89
+ setLocations(parsedEvent.locations);
90
+ setTotalLocations(props.totalLocations);
91
+ setCurrentLocation(props.currentLocation);
92
+ setProgress(props.progress);
93
+
94
+ return onLocationsReady(props.epubKey, parsedEvent.locations);
95
+ case 'onReady':
96
+ if (initialLocation) {
97
+ goToLocation(initialLocation);
98
+ }
99
+ break;
100
+
101
+ case 'onBeginning':
102
+ setAtStart(true);
103
+
104
+ return onBeginning();
105
+
106
+ case 'onFinish':
107
+ setAtEnd(true);
108
+
109
+ return onFinish();
110
+
111
+ default:
112
+ console.warn('Unknown message type:', parsedEvent.type);
113
+ }
114
+ };
115
+
116
+ const handleOnTap = () => {
117
+ onTap?.();
118
+ };
119
+
120
+ const handleOnSwipeLeft = () => {
121
+ onSwipeLeft?.();
122
+ goNext();
123
+ };
124
+
125
+ const handleOnSwipeRight = () => {
126
+ onSwipeRight?.();
127
+ goPrevious();
128
+ };
129
+
130
+ const handleOnPinch = (
131
+ e: GestureUpdateEvent<PinchGestureHandlerEventPayload>
132
+ ) => {
133
+ const fontSizeValue = parseInt(fontSize.replace('pt', ''), 10);
134
+
135
+ const scaleValue = e.scale > 1 ? e.scale * 0.5 : e.scale;
136
+
137
+ const newFontSize = fontSizeValue * scaleValue;
138
+
139
+ const clampedFontSize = Math.min(Math.max(newFontSize, 6), 32);
140
+ changeFontSize(`${clampedFontSize}pt`);
141
+ onPinch?.(e);
142
+ };
143
+
144
+ const htmlTemplateName = useMemo(
145
+ () => src.split('/').pop()?.replace('.epub', '.html') || 'index.html',
146
+ [src]
147
+ );
148
+
149
+ const epubFileName = useMemo(
150
+ () => src.split('/').pop() || 'book.epub',
151
+ [src]
152
+ );
153
+
154
+ const handleBookRef = useCallback(
155
+ (instance: WebView | null) => {
156
+ bookRef.current = instance;
157
+ if (instance) {
158
+ registerBook(instance);
159
+ }
160
+ },
161
+ [registerBook]
162
+ );
163
+
164
+ useEffect(() => {
165
+ let isMounted = true;
166
+
167
+ const prepareReader = async () => {
168
+ try {
169
+ setIsLoading(true);
170
+
171
+ const [, jszip, epubjs] = await loadScripts();
172
+
173
+ if (!jszip || !epubjs) throw new Error('Failed to load scripts');
174
+
175
+ const localEpubUri = await downloadEpub(src, epubFileName);
176
+
177
+ const generatedTemplate = injectWebViewVariables({
178
+ jszip,
179
+ epubjs,
180
+ type: SourceType.EPUB,
181
+ allowScriptedContent: true,
182
+ book: localEpubUri,
183
+ theme: initialTheme,
184
+ });
185
+
186
+ const uri = saveTemplateToFile(generatedTemplate, htmlTemplateName);
187
+
188
+ if (isMounted) {
189
+ setTemplateUri(uri);
190
+ }
191
+ } catch (error) {
192
+ console.error('Reader Error:', error);
193
+ } finally {
194
+ if (isMounted) setIsLoading(false);
195
+ }
196
+ };
197
+
198
+ prepareReader();
199
+ return () => {
200
+ isMounted = false;
201
+ };
202
+ }, [
203
+ src,
204
+ htmlTemplateName,
205
+ epubFileName,
206
+ injectWebViewVariables,
207
+ setIsLoading,
208
+ ]);
209
+
210
+ if (isLoading) {
211
+ return LoaderComponent ? (
212
+ <LoaderComponent />
213
+ ) : (
214
+ <View style={styles.loaderContainer}>
215
+ <ActivityIndicator size="large" />
216
+ <Text>Przygotowuję książkę...</Text>
217
+ </View>
218
+ );
219
+ }
220
+
221
+ return (
222
+ <>
223
+ <GestureHandler
224
+ onSwipeLeft={handleOnSwipeLeft}
225
+ onSwipeRight={handleOnSwipeRight}
226
+ onTap={handleOnTap}
227
+ onPinch={handleOnPinch}
228
+ >
229
+ <WebView
230
+ pointerEvents="none"
231
+ ref={handleBookRef}
232
+ source={{ uri: templateUri }}
233
+ showsVerticalScrollIndicator={false}
234
+ javaScriptEnabled
235
+ originWhitelist={['*']}
236
+ scrollEnabled={false}
237
+ mixedContentMode="compatibility"
238
+ allowingReadAccessToURL={Paths.document.uri}
239
+ allowUniversalAccessFromFileURLs
240
+ allowFileAccessFromFileURLs
241
+ allowFileAccess
242
+ javaScriptCanOpenWindowsAutomatically
243
+ onMessage={onMessage}
244
+ style={styles.container}
245
+ />
246
+ </GestureHandler>
247
+ </>
248
+ );
249
+ };
250
+
251
+ const styles = StyleSheet.create({
252
+ container: {
253
+ flex: 1,
254
+ },
255
+ loaderContainer: {
256
+ flex: 1,
257
+ justifyContent: 'center',
258
+ alignItems: 'center',
259
+ },
260
+ });
261
+
262
+ export default Reader;