@moustafahelmi/react-native-quran-app 1.4.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 (131) hide show
  1. package/.bundle/config +2 -0
  2. package/.eslintrc.js +4 -0
  3. package/.prettierrc.js +7 -0
  4. package/.watchmanconfig +1 -0
  5. package/App.tsx +23 -0
  6. package/Gemfile +9 -0
  7. package/Gemfile.lock +105 -0
  8. package/MIGRATION.md +163 -0
  9. package/README.md +210 -0
  10. package/ReactotronConfig.js +7 -0
  11. package/__tests__/App.test.tsx +17 -0
  12. package/android/app/build.gradle +118 -0
  13. package/android/app/debug.keystore +0 -0
  14. package/android/app/proguard-rules.pro +10 -0
  15. package/android/app/src/debug/AndroidManifest.xml +9 -0
  16. package/android/app/src/main/AndroidManifest.xml +25 -0
  17. package/android/app/src/main/assets/fonts/Cairo.ttf +0 -0
  18. package/android/app/src/main/assets/fonts/QCF_BSML.ttf +0 -0
  19. package/android/app/src/main/assets/fonts/QCF_P001.ttf +0 -0
  20. package/android/app/src/main/java/com/quranapp/MainActivity.kt +22 -0
  21. package/android/app/src/main/java/com/quranapp/MainApplication.kt +43 -0
  22. package/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  23. package/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  24. package/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  25. package/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  26. package/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  27. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  28. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  29. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  30. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  31. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  32. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  33. package/android/app/src/main/res/values/strings.xml +3 -0
  34. package/android/app/src/main/res/values/styles.xml +9 -0
  35. package/android/build.gradle +21 -0
  36. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  37. package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  38. package/android/gradle.properties +41 -0
  39. package/android/gradlew +249 -0
  40. package/android/gradlew.bat +92 -0
  41. package/android/link-assets-manifest.json +17 -0
  42. package/android/settings.gradle +4 -0
  43. package/app.json +4 -0
  44. package/babel.config.js +3 -0
  45. package/index.js +11 -0
  46. package/ios/.xcode.env +11 -0
  47. package/ios/Podfile +40 -0
  48. package/ios/Podfile.lock +1460 -0
  49. package/ios/QuranApp/AppDelegate.h +6 -0
  50. package/ios/QuranApp/AppDelegate.mm +31 -0
  51. package/ios/QuranApp/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  52. package/ios/QuranApp/Images.xcassets/Contents.json +6 -0
  53. package/ios/QuranApp/Info.plist +57 -0
  54. package/ios/QuranApp/LaunchScreen.storyboard +47 -0
  55. package/ios/QuranApp/PrivacyInfo.xcprivacy +38 -0
  56. package/ios/QuranApp/main.m +10 -0
  57. package/ios/QuranApp.xcodeproj/project.pbxproj +729 -0
  58. package/ios/QuranApp.xcodeproj/xcshareddata/xcschemes/QuranApp.xcscheme +88 -0
  59. package/ios/QuranApp.xcworkspace/contents.xcworkspacedata +10 -0
  60. package/ios/QuranAppTests/Info.plist +24 -0
  61. package/ios/QuranAppTests/QuranAppTests.m +66 -0
  62. package/ios/link-assets-manifest.json +17 -0
  63. package/jest.config.js +3 -0
  64. package/metro.config.js +11 -0
  65. package/package.json +54 -0
  66. package/react-native.config.js +7 -0
  67. package/screenshots/1.png +0 -0
  68. package/screenshots/2.png +0 -0
  69. package/screenshots/3.png +0 -0
  70. package/screenshots/4.png +0 -0
  71. package/screenshots/5.png +0 -0
  72. package/src/assets/fonts/Cairo.ttf +0 -0
  73. package/src/assets/fonts/QCF_BSML.ttf +0 -0
  74. package/src/assets/fonts/QCF_P001.ttf +0 -0
  75. package/src/assets/images/bookmark.png +0 -0
  76. package/src/assets/images/close.png +0 -0
  77. package/src/assets/images/copy.png +0 -0
  78. package/src/assets/images/down-chevron.png +0 -0
  79. package/src/assets/images/mushafFrame.png +0 -0
  80. package/src/assets/images/pause.png +0 -0
  81. package/src/assets/images/play-button.png +0 -0
  82. package/src/assets/images/play.svg +16 -0
  83. package/src/assets/images/playNext.png +0 -0
  84. package/src/assets/images/surahNameFrame.png +0 -0
  85. package/src/common/chapters.ts +1346 -0
  86. package/src/common/constants.ts +27 -0
  87. package/src/common/images.ts +13 -0
  88. package/src/common/index.ts +8 -0
  89. package/src/common/juzs.ts +411 -0
  90. package/src/common/priorityPages.ts +46 -0
  91. package/src/common/themes.ts +7 -0
  92. package/src/components/index.ts +3 -0
  93. package/src/components/lists/index.ts +3 -0
  94. package/src/components/lists/pageVersesList.tsx +220 -0
  95. package/src/components/lists/verseLinesWordsList.tsx +90 -0
  96. package/src/components/modals/index.ts +3 -0
  97. package/src/components/modals/optionsModal.tsx +126 -0
  98. package/src/components/modals/recitersModal.tsx +118 -0
  99. package/src/components/sections/audioPlayer.tsx +185 -0
  100. package/src/components/sections/audioPlayerControls.tsx +100 -0
  101. package/src/components/sections/index.ts +4 -0
  102. package/src/components/sections/loader.tsx +33 -0
  103. package/src/helpers/index.ts +1 -0
  104. package/src/helpers/quranHelpers.tsx +17 -0
  105. package/src/hooks/apis/index.ts +10 -0
  106. package/src/hooks/apis/useGetChapterAudio.ts +111 -0
  107. package/src/hooks/apis/useGetChapterByPage.ts +166 -0
  108. package/src/hooks/apis/useGetChapterLookup.ts +31 -0
  109. package/src/hooks/apis/useGetReciters.ts +44 -0
  110. package/src/hooks/controllers/index.ts +25 -0
  111. package/src/hooks/controllers/useAudioPlayerController.tsx +63 -0
  112. package/src/hooks/controllers/useOptionsModalController.ts +99 -0
  113. package/src/hooks/controllers/usePageFontFileController.ts +255 -0
  114. package/src/hooks/controllers/usePageLineController.ts +108 -0
  115. package/src/hooks/helpers/index.ts +6 -0
  116. package/src/hooks/helpers/useQuranFontPreloader.ts +225 -0
  117. package/src/hooks/index.ts +3 -0
  118. package/src/index.ts +5 -0
  119. package/src/layouts/bismillahText.tsx +18 -0
  120. package/src/layouts/index.ts +4 -0
  121. package/src/layouts/quranChapterHeader.tsx +49 -0
  122. package/src/layouts/quranPageLayout.tsx +178 -0
  123. package/src/types/global.d.ts +7 -0
  124. package/src/types/index.ts +212 -0
  125. package/src/utils/axiosInstance.ts +7 -0
  126. package/src/utils/fileHandlers.ts +96 -0
  127. package/src/utils/handleBeforeAndAfterCurrentVerse.ts +41 -0
  128. package/src/utils/index.ts +6 -0
  129. package/src/utils/matrics.ts +37 -0
  130. package/tsconfig.json +3 -0
  131. package/videos/1.gif +0 -0
@@ -0,0 +1,225 @@
1
+ import { useEffect, useState, useRef } from 'react';
2
+ import AsyncStorage from '@react-native-async-storage/async-storage';
3
+ import { downloadMultiplePageFonts } from '../controllers/usePageFontFileController';
4
+
5
+ interface UseQuranFontPreloaderOptions {
6
+ /**
7
+ * Array of page numbers to preload
8
+ */
9
+ pages: number[];
10
+
11
+ /**
12
+ * Base URL for font downloads
13
+ */
14
+ quranFontApi: string;
15
+
16
+ /**
17
+ * Whether to start preloading automatically on mount
18
+ */
19
+ autoStart?: boolean;
20
+
21
+ /**
22
+ * Cache key for tracking completion
23
+ */
24
+ cacheKey?: string;
25
+
26
+ /**
27
+ * Cache version for invalidation
28
+ */
29
+ cacheVersion?: string;
30
+
31
+ /**
32
+ * Max concurrent downloads
33
+ */
34
+ concurrentDownloads?: number;
35
+ }
36
+
37
+ interface PreloadProgress {
38
+ current: number;
39
+ total: number;
40
+ percentage: number;
41
+ lastPage: number;
42
+ }
43
+
44
+ interface UseQuranFontPreloaderResult {
45
+ /**
46
+ * Whether preloading is in progress
47
+ */
48
+ isPreloading: boolean;
49
+
50
+ /**
51
+ * Whether preload has completed successfully
52
+ */
53
+ isCompleted: boolean;
54
+
55
+ /**
56
+ * Current progress
57
+ */
58
+ progress: PreloadProgress;
59
+
60
+ /**
61
+ * Any error that occurred
62
+ */
63
+ error: Error | null;
64
+
65
+ /**
66
+ * Start preloading manually
67
+ */
68
+ startPreload: () => Promise<void>;
69
+
70
+ /**
71
+ * Reset preload status (clears cache flag)
72
+ */
73
+ resetPreload: () => Promise<void>;
74
+ }
75
+
76
+ /**
77
+ * React hook for preloading Quran fonts in the background
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const { isPreloading, progress } = useQuranFontPreloader({
82
+ * pages: PRIORITY_PAGES,
83
+ * quranFontApi: 'https://raw.githubusercontent.com/...',
84
+ * autoStart: true,
85
+ * });
86
+ *
87
+ * if (isPreloading) {
88
+ * console.log(`Loading: ${progress.percentage}%`);
89
+ * }
90
+ * ```
91
+ */
92
+ export const useQuranFontPreloader = (
93
+ options: UseQuranFontPreloaderOptions
94
+ ): UseQuranFontPreloaderResult => {
95
+ const {
96
+ pages,
97
+ quranFontApi,
98
+ autoStart = true,
99
+ cacheKey = 'quran_fonts_preload',
100
+ cacheVersion = '1.0',
101
+ concurrentDownloads = 5,
102
+ } = options;
103
+
104
+ const [isPreloading, setIsPreloading] = useState(false);
105
+ const [isCompleted, setIsCompleted] = useState(false);
106
+ const [progress, setProgress] = useState<PreloadProgress>({
107
+ current: 0,
108
+ total: pages.length,
109
+ percentage: 0,
110
+ lastPage: 0,
111
+ });
112
+ const [error, setError] = useState<Error | null>(null);
113
+ const hasStartedRef = useRef(false);
114
+
115
+ const versionKey = `${cacheKey}_version`;
116
+
117
+ const checkIfAlreadyPreloaded = async (): Promise<boolean> => {
118
+ try {
119
+ const completed = await AsyncStorage.getItem(cacheKey);
120
+ const storedVersion = await AsyncStorage.getItem(versionKey);
121
+ return completed === 'true' && storedVersion === cacheVersion;
122
+ } catch (error) {
123
+ console.error('Error checking preload status:', error);
124
+ return false;
125
+ }
126
+ };
127
+
128
+ const markAsCompleted = async () => {
129
+ try {
130
+ await AsyncStorage.setItem(cacheKey, 'true');
131
+ await AsyncStorage.setItem(versionKey, cacheVersion);
132
+ } catch (error) {
133
+ console.error('Error marking as completed:', error);
134
+ }
135
+ };
136
+
137
+ const resetPreload = async () => {
138
+ try {
139
+ await AsyncStorage.removeItem(cacheKey);
140
+ await AsyncStorage.removeItem(versionKey);
141
+ setIsCompleted(false);
142
+ setProgress({
143
+ current: 0,
144
+ total: pages.length,
145
+ percentage: 0,
146
+ lastPage: 0,
147
+ });
148
+ console.log('🔄 Preload status reset');
149
+ } catch (error) {
150
+ console.error('Error resetting preload:', error);
151
+ }
152
+ };
153
+
154
+ const startPreload = async () => {
155
+ if (hasStartedRef.current) {
156
+ console.log('Preload already in progress');
157
+ return;
158
+ }
159
+
160
+ // Check if already completed
161
+ const alreadyPreloaded = await checkIfAlreadyPreloaded();
162
+ if (alreadyPreloaded) {
163
+ console.log('✅ Fonts already preloaded');
164
+ setIsCompleted(true);
165
+ return;
166
+ }
167
+
168
+ hasStartedRef.current = true;
169
+ setIsPreloading(true);
170
+ setError(null);
171
+
172
+ console.log(`🚀 Starting Quran font preload: ${pages.length} pages`);
173
+
174
+ try {
175
+ const results = await downloadMultiplePageFonts(
176
+ pages,
177
+ quranFontApi,
178
+ (current, total, page) => {
179
+ const percentage = Math.round((current / total) * 100);
180
+ setProgress({
181
+ current,
182
+ total,
183
+ percentage,
184
+ lastPage: page,
185
+ });
186
+ },
187
+ concurrentDownloads
188
+ );
189
+
190
+ const successful = results.filter(r => r.success).length;
191
+
192
+ if (successful === pages.length) {
193
+ await markAsCompleted();
194
+ setIsCompleted(true);
195
+ console.log('✅ Quran font preload completed successfully');
196
+ } else {
197
+ const failed = pages.length - successful;
198
+ console.warn(`⚠️ Preload completed with ${failed} failures`);
199
+ }
200
+ } catch (err) {
201
+ console.error('❌ Preload error:', err);
202
+ setError(err as Error);
203
+ } finally {
204
+ setIsPreloading(false);
205
+ hasStartedRef.current = false;
206
+ }
207
+ };
208
+
209
+ useEffect(() => {
210
+ if (autoStart && !hasStartedRef.current) {
211
+ startPreload();
212
+ }
213
+ }, [autoStart]);
214
+
215
+ return {
216
+ isPreloading,
217
+ isCompleted,
218
+ progress,
219
+ error,
220
+ startPreload,
221
+ resetPreload,
222
+ };
223
+ };
224
+
225
+ export default useQuranFontPreloader;
@@ -0,0 +1,3 @@
1
+ export * from './apis';
2
+ export * from './controllers';
3
+ export * from './helpers';
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './layouts';
2
+ export * from './helpers';
3
+ export * from './types';
4
+ export * from './hooks';
5
+ export * from './common';
@@ -0,0 +1,18 @@
1
+ import {Text, View} from 'react-native';
2
+ import {FONT_FAMILY, basmalah} from '../common';
3
+
4
+ const BismillahText = () => {
5
+ return (
6
+ <View
7
+ style={{
8
+ width: '90%',
9
+ alignItems: 'center',
10
+ }}>
11
+ <Text style={{fontFamily: FONT_FAMILY.BISMLLAH, fontSize: 25}}>
12
+ {basmalah}
13
+ </Text>
14
+ </View>
15
+ );
16
+ };
17
+
18
+ export default BismillahText;
@@ -0,0 +1,4 @@
1
+ import QuranPageLayout from './quranPageLayout';
2
+ import QuranPageHeader from './quranChapterHeader';
3
+ import BismillahText from './bismillahText';
4
+ export {QuranPageLayout, QuranPageHeader, BismillahText};
@@ -0,0 +1,49 @@
1
+ import {Image, ImageSourcePropType, StyleSheet, Text, View} from 'react-native';
2
+ import {FONT_FAMILY} from '../common';
3
+ import {_renderChapterName} from '../helpers';
4
+ interface IProps {
5
+ chapterId: number;
6
+ surahNameFrameImage: ImageSourcePropType;
7
+ }
8
+
9
+ const QuranChapterHeader = ({chapterId, surahNameFrameImage}: IProps) => {
10
+ return (
11
+ <View style={styles.surahNameContainer}>
12
+ <Image
13
+ source={surahNameFrameImage}
14
+ style={styles.surahName}
15
+ resizeMode="contain"
16
+ />
17
+ <View style={styles.row}>
18
+ <Text style={styles.txt}>{_renderChapterName(chapterId)}</Text>
19
+ </View>
20
+ </View>
21
+ );
22
+ };
23
+
24
+ export default QuranChapterHeader;
25
+
26
+ const styles = StyleSheet.create({
27
+ surahNameContainer: {
28
+ width: '90%',
29
+ alignItems: 'center',
30
+ justifyContent: 'center',
31
+ alignSelf: 'center',
32
+ },
33
+ surahName: {
34
+ width: '100%',
35
+ height: 50,
36
+ },
37
+ txt: {
38
+ fontFamily: FONT_FAMILY.BISMLLAH,
39
+ fontSize: 30,
40
+ },
41
+ row: {
42
+ top: 1,
43
+ position: 'absolute',
44
+ },
45
+ juzNumberContainer: {
46
+ alignItems: 'center',
47
+ justifyContent: 'center',
48
+ },
49
+ });
@@ -0,0 +1,178 @@
1
+ import {useEffect, useMemo, useRef, useState} from 'react';
2
+ import {FlatList, I18nManager, SafeAreaView, View} from 'react-native';
3
+ import TrackPlayer from 'react-native-track-player';
4
+ import {
5
+ IAudioPlayerRef,
6
+ IChapterVerses,
7
+ IQuranPageLayout,
8
+ ISurahVerse,
9
+ IVersesBeforeAndAfterCurrentVerse,
10
+ QuranTypesEnums,
11
+ } from '../types';
12
+ import {AudioPlayer, Loader, PageVersesList} from '../components';
13
+ import {useGetChapterByPage, useGetChapterLookup} from '../hooks';
14
+ import useGetReciters from '../hooks/apis/useGetReciters';
15
+ import {ALFATIHA_CHAPTER_ID, ALTAWBA_CHAPTER_ID} from '../common';
16
+
17
+ const QuranPageLayout = ({
18
+ chapterId = 1,
19
+ type = QuranTypesEnums.chapter,
20
+ QURAN_FONTS_API,
21
+ showSlider,
22
+ selectedBookedMarkedVerse,
23
+ onBookMarkedVerse,
24
+ backgroundImage,
25
+ surahNameFrameImage,
26
+ resizeImageBackgroundMode,
27
+ quranPageContainerStyle,
28
+ selectionColor,
29
+ autoCompleteAudioAfterPlayingVerse,
30
+ }: IQuranPageLayout) => {
31
+ const flatlistRef = useRef<any>();
32
+ const {chapterLookUp} = useGetChapterLookup({
33
+ chapterId,
34
+ type,
35
+ });
36
+ const {chapterVerses, isLoading, chapterProgress} = useGetChapterByPage({
37
+ chapterLookUp,
38
+ chapterId,
39
+ type,
40
+ QURAN_FONTS_API: QURAN_FONTS_API,
41
+ });
42
+ const {allReciters} = useGetReciters({chapterId, type});
43
+ const audioPlayerRef = useRef<IAudioPlayerRef>();
44
+ const [selectedVerse, setSelectedVerse] = useState<ISurahVerse>(
45
+ {} as ISurahVerse,
46
+ );
47
+ const [
48
+ versesBeforeAndAfterCurrentVerse,
49
+ setVersesBeforeAndAfterCurrentVerse,
50
+ ] = useState<IVersesBeforeAndAfterCurrentVerse>(
51
+ {} as IVersesBeforeAndAfterCurrentVerse,
52
+ );
53
+ const onContainerPress = () => {
54
+ audioPlayerRef?.current?.setShowPlayerHandler(
55
+ !audioPlayerRef?.current?.isPlayerShown(),
56
+ );
57
+ };
58
+ const originalVerse = useMemo(
59
+ () =>
60
+ chapterVerses?.find(
61
+ (item: IChapterVerses) =>
62
+ item?.page_number == selectedVerse?.page_number,
63
+ )?.originalVerses as ISurahVerse[],
64
+ [selectedVerse],
65
+ );
66
+
67
+ useEffect(() => {
68
+ TrackPlayer.setupPlayer();
69
+ }, []);
70
+ useEffect(() => {
71
+ if (!isLoading && selectedBookedMarkedVerse) {
72
+ setSelectedVerse(selectedBookedMarkedVerse);
73
+ scrollToPageIndex();
74
+ }
75
+ }, [isLoading]);
76
+ const scrollToPageIndex = () => {
77
+ let selectedBookMarkedVerseIndex = chapterVerses?.findIndex(
78
+ item => item?.page_number == selectedBookedMarkedVerse?.page_number,
79
+ );
80
+ selectedBookMarkedVerseIndex = I18nManager.isRTL
81
+ ? chapterVerses?.length - 1 - selectedBookMarkedVerseIndex
82
+ : selectedBookMarkedVerseIndex;
83
+ setTimeout(() => {
84
+ flatlistRef?.current?.scrollToIndex({
85
+ index: selectedBookMarkedVerseIndex,
86
+ animated: true,
87
+ });
88
+ }, 1000);
89
+ };
90
+ return (
91
+ <SafeAreaView
92
+ style={{
93
+ flex: 1,
94
+ alignItems: 'center',
95
+ justifyContent: 'center',
96
+ }}>
97
+ <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
98
+ {isLoading ? (
99
+ <Loader chapterProgress={chapterProgress} showTxt />
100
+ ) : (
101
+ <FlatList
102
+ ref={flatlistRef}
103
+ data={chapterVerses}
104
+ contentContainerStyle={{
105
+ alignItems: 'center',
106
+ justifyContent: 'center',
107
+ }}
108
+ pagingEnabled
109
+ horizontal
110
+ showsHorizontalScrollIndicator={false}
111
+ renderItem={({item, index}) => (
112
+ <PageVersesList
113
+ type={type}
114
+ pageVersesToDisplay={item?.verses}
115
+ audioPlayerRef={audioPlayerRef}
116
+ selectedVerse={selectedVerse}
117
+ setSelectedVerse={setSelectedVerse}
118
+ setVersesBeforeAndAfterCurrentVerse={
119
+ setVersesBeforeAndAfterCurrentVerse
120
+ }
121
+ onContainerPress={onContainerPress}
122
+ chapterId={item?.chapter_id}
123
+ showChapterName={index === 0 || item?.isFirstChapterPage}
124
+ showBismllah={
125
+ (item?.chapter_id != ALTAWBA_CHAPTER_ID &&
126
+ index === 0 &&
127
+ item?.chapter_id != ALFATIHA_CHAPTER_ID) ||
128
+ (item?.isFirstChapterPage &&
129
+ item?.chapter_id != ALTAWBA_CHAPTER_ID)
130
+ }
131
+ pageNumber={item?.page_number}
132
+ juzNumber={item?.juz_number}
133
+ originalVerse={item?.originalVerses}
134
+ onBookMarkedVerse={onBookMarkedVerse}
135
+ backgroundImage={backgroundImage}
136
+ surahNameFrameImage={surahNameFrameImage}
137
+ resizeImageBackgroundMode={resizeImageBackgroundMode}
138
+ quranPageContainerStyle={quranPageContainerStyle}
139
+ selectionColor={selectionColor}
140
+ autoCompleteAudioAfterPlayingVerse={
141
+ autoCompleteAudioAfterPlayingVerse
142
+ }
143
+ />
144
+ )}
145
+ onScrollToIndexFailed={info => {
146
+ // to handle if there is a failure when scrollToIndex
147
+ const wait = new Promise(resolve => setTimeout(resolve, 500));
148
+ wait.then(() => {
149
+ flatlistRef.current?.scrollToIndex({
150
+ index: info.index,
151
+ animated: true,
152
+ });
153
+ });
154
+ }}
155
+ />
156
+ )}
157
+ <AudioPlayer
158
+ ref={audioPlayerRef}
159
+ chapterId={selectedVerse?.chapter_id ?? chapterId}
160
+ setSelectedVerse={setSelectedVerse}
161
+ selectedVerse={selectedVerse}
162
+ allReciter={allReciters}
163
+ versesBeforeAndAfterCurrentVerse={versesBeforeAndAfterCurrentVerse}
164
+ setVersesBeforeAndAfterCurrentVerse={
165
+ setVersesBeforeAndAfterCurrentVerse
166
+ }
167
+ originalVerse={originalVerse}
168
+ showSlider={showSlider}
169
+ autoCompleteAudioAfterPlayingVerse={
170
+ autoCompleteAudioAfterPlayingVerse
171
+ }
172
+ />
173
+ </View>
174
+ </SafeAreaView>
175
+ );
176
+ };
177
+
178
+ export default QuranPageLayout;
@@ -0,0 +1,7 @@
1
+ declare module 'react-native-dynamic-fonts' {
2
+ export const loadFont: (
3
+ targetFont: string,
4
+ base64: string,
5
+ fontExtension: string,
6
+ ) => Promise;
7
+ }
@@ -0,0 +1,212 @@
1
+ import {MutableRefObject, ReactNode} from 'react';
2
+ import {
3
+ ColorValue,
4
+ ImageResizeMode,
5
+ ImageSourcePropType,
6
+ StyleProp,
7
+ ViewStyle,
8
+ } from 'react-native';
9
+
10
+ export interface IChapterLookUp {
11
+ page_number: string;
12
+ page_range: {
13
+ from: string;
14
+ to: string;
15
+ first_verse_key: string;
16
+ last_verse_key: string;
17
+ };
18
+ }
19
+
20
+ export interface ISurahVerse {
21
+ id: number;
22
+ verse_key: string;
23
+ hizb_number: number;
24
+ rub_el_hizb_number: number;
25
+ ruku_number: number;
26
+ manzil_number: number;
27
+ sajdah_number: null;
28
+ text_uthmani: string;
29
+ chapter_id: number;
30
+ text_imlaei_simple: string;
31
+ page_number: number;
32
+ juz_number: number;
33
+ words: IVerseWord[];
34
+ chapter_code_v1: number;
35
+ verse_font_famliy: string;
36
+ verse_number: number;
37
+ }
38
+
39
+ export interface IVerseWord {
40
+ id: number;
41
+ position: number;
42
+ audio_url: string;
43
+ verse_key: string;
44
+ verse_id: number;
45
+ location: string;
46
+ text_uthmani: string;
47
+ qpc_uthmani_hafs: string;
48
+ code_v1: string;
49
+ code_v2: string;
50
+ char_type_name: string;
51
+ page_number: number;
52
+ line_number: number;
53
+ text: string;
54
+ verseData: any;
55
+ }
56
+
57
+ export interface IPageVeseseObject {
58
+ page_number: number;
59
+ verses: ISurahVerse[];
60
+ }
61
+
62
+ interface IVerseDataInWord extends IVerseWord {
63
+ verseData: ISurahVerse;
64
+ }
65
+ export interface ILineNumber {
66
+ lineNumber: number;
67
+ words: IVerseDataInWord[];
68
+ wordCodeV1?: string;
69
+ page_number?: number;
70
+ isFirstLine?: boolean;
71
+ chapter_id: number;
72
+ }
73
+
74
+ export interface IChapterVerses {
75
+ verses: ILineNumber[] | undefined;
76
+ page_number: number;
77
+ juz_number: number;
78
+ originalVerses: ISurahVerse[];
79
+ chapter_id: number;
80
+ isFirstChapterPage: boolean;
81
+ }
82
+
83
+ export interface ISelectedVerseLocation {
84
+ itemLocationY: number;
85
+ itemLocationX: number;
86
+ }
87
+ export interface IQuranChapters {
88
+ revelationPlace: string;
89
+ transliteratedName: string;
90
+ versesCount: number;
91
+ translatedName: string;
92
+ slug: string;
93
+ hasBasmalah?: boolean;
94
+ code_v1: number;
95
+ firstPage: number;
96
+ lastPage?: number;
97
+ id: number;
98
+ type: string;
99
+ }
100
+
101
+ export interface IReciter {
102
+ id: number;
103
+ reciter_id: number;
104
+ name: string;
105
+ }
106
+
107
+ export interface IAudioPlayerRef {
108
+ setShowPlayerHandler: (value: boolean) => void;
109
+ _renderSelelctedReciter: () => IReciter;
110
+ isPlayerShown: () => boolean;
111
+ }
112
+
113
+ export interface IModalRef {
114
+ openModal: () => void;
115
+ closeModal: () => void;
116
+ }
117
+
118
+ export interface IOptionsModal {
119
+ selectedVerseLocation: ISelectedVerseLocation | undefined;
120
+ selectedVerse: ISurahVerse;
121
+ seSelectedVerse: (verse: ISurahVerse) => void;
122
+ handlePlayPress: () => void;
123
+ selectedReciter: IReciter | undefined;
124
+ onBookMarkedVerse?: (verse: ISurahVerse) => void;
125
+ chapterId: number;
126
+ autoCompleteAudioAfterPlayingVerse?: boolean;
127
+ }
128
+
129
+ export interface IPageVersesListRef {
130
+ setSelectedVerseHandler: (verse: ISurahVerse) => void | undefined;
131
+ }
132
+
133
+ export interface IVersesBeforeAndAfterCurrentVerse {
134
+ beforeCurrentVerse: ISurahVerse | null;
135
+ afterCurrentVerse: ISurahVerse | null;
136
+ }
137
+
138
+ export interface IPageVersesList {
139
+ setSelectedVerse: (value: ISurahVerse) => void;
140
+ selectedVerse: ISurahVerse;
141
+ pageVersesToDisplay: ILineNumber[] | undefined;
142
+ audioPlayerRef: MutableRefObject<IAudioPlayerRef | undefined>;
143
+ onContainerPress: () => void;
144
+ chapterId: number;
145
+ showChapterName: boolean;
146
+ showBismllah: boolean;
147
+ pageNumber: number;
148
+ juzNumber: number;
149
+ setVersesBeforeAndAfterCurrentVerse: (
150
+ value: IVersesBeforeAndAfterCurrentVerse,
151
+ ) => void;
152
+ originalVerse: ISurahVerse[];
153
+ onBookMarkedVerse?: (verse: ISurahVerse) => void;
154
+ backgroundImage?: ImageSourcePropType;
155
+ surahNameFrameImage?: ImageSourcePropType;
156
+ quranPageContainerStyle?: StyleProp<ViewStyle>;
157
+ resizeImageBackgroundMode?: ImageResizeMode;
158
+ selectionColor?: ColorValue;
159
+ autoCompleteAudioAfterPlayingVerse?: boolean;
160
+ type: QuranTypesEnums;
161
+ }
162
+
163
+ export interface IQuranPageLayout {
164
+ chapterId: number;
165
+ type?: QuranTypesEnums;
166
+ chapterHeader?: ReactNode;
167
+ QURAN_FONTS_API: string;
168
+ showSlider?: boolean;
169
+ selectedBookedMarkedVerse?: ISurahVerse;
170
+ onBookMarkedVerse?: (verse: ISurahVerse) => void;
171
+ backgroundImage?: ImageSourcePropType;
172
+ surahNameFrameImage?: ImageSourcePropType;
173
+ resizeImageBackgroundMode?: ImageResizeMode;
174
+ quranPageContainerStyle?: StyleProp<ViewStyle>;
175
+ selectionColor?: ColorValue;
176
+ autoCompleteAudioAfterPlayingVerse?: boolean;
177
+ }
178
+
179
+ export enum QuranTypesEnums {
180
+ chapter = 'chapter',
181
+ juz = 'juz',
182
+ }
183
+
184
+ export interface IQuranJuzs {
185
+ id: number;
186
+ juz_number: number;
187
+ verse_mapping: any;
188
+ first_verse_id: number;
189
+ last_verse_id: number;
190
+ verses_count: number;
191
+ }
192
+
193
+ // Font preloading types
194
+ export interface IFontDownloadResult {
195
+ success: boolean;
196
+ page: number;
197
+ cached: boolean;
198
+ error?: any;
199
+ }
200
+
201
+ export interface IFontCacheStats {
202
+ totalCached: number;
203
+ cachedPages: number[];
204
+ totalSizeBytes: number;
205
+ }
206
+
207
+ export interface IPreloadProgress {
208
+ current: number;
209
+ total: number;
210
+ percentage: number;
211
+ lastPage: number;
212
+ }