@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.
- package/.bundle/config +2 -0
- package/.eslintrc.js +4 -0
- package/.prettierrc.js +7 -0
- package/.watchmanconfig +1 -0
- package/App.tsx +23 -0
- package/Gemfile +9 -0
- package/Gemfile.lock +105 -0
- package/MIGRATION.md +163 -0
- package/README.md +210 -0
- package/ReactotronConfig.js +7 -0
- package/__tests__/App.test.tsx +17 -0
- package/android/app/build.gradle +118 -0
- package/android/app/debug.keystore +0 -0
- package/android/app/proguard-rules.pro +10 -0
- package/android/app/src/debug/AndroidManifest.xml +9 -0
- package/android/app/src/main/AndroidManifest.xml +25 -0
- package/android/app/src/main/assets/fonts/Cairo.ttf +0 -0
- package/android/app/src/main/assets/fonts/QCF_BSML.ttf +0 -0
- package/android/app/src/main/assets/fonts/QCF_P001.ttf +0 -0
- package/android/app/src/main/java/com/quranapp/MainActivity.kt +22 -0
- package/android/app/src/main/java/com/quranapp/MainApplication.kt +43 -0
- package/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/values/strings.xml +3 -0
- package/android/app/src/main/res/values/styles.xml +9 -0
- package/android/build.gradle +21 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/android/gradle.properties +41 -0
- package/android/gradlew +249 -0
- package/android/gradlew.bat +92 -0
- package/android/link-assets-manifest.json +17 -0
- package/android/settings.gradle +4 -0
- package/app.json +4 -0
- package/babel.config.js +3 -0
- package/index.js +11 -0
- package/ios/.xcode.env +11 -0
- package/ios/Podfile +40 -0
- package/ios/Podfile.lock +1460 -0
- package/ios/QuranApp/AppDelegate.h +6 -0
- package/ios/QuranApp/AppDelegate.mm +31 -0
- package/ios/QuranApp/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/ios/QuranApp/Images.xcassets/Contents.json +6 -0
- package/ios/QuranApp/Info.plist +57 -0
- package/ios/QuranApp/LaunchScreen.storyboard +47 -0
- package/ios/QuranApp/PrivacyInfo.xcprivacy +38 -0
- package/ios/QuranApp/main.m +10 -0
- package/ios/QuranApp.xcodeproj/project.pbxproj +729 -0
- package/ios/QuranApp.xcodeproj/xcshareddata/xcschemes/QuranApp.xcscheme +88 -0
- package/ios/QuranApp.xcworkspace/contents.xcworkspacedata +10 -0
- package/ios/QuranAppTests/Info.plist +24 -0
- package/ios/QuranAppTests/QuranAppTests.m +66 -0
- package/ios/link-assets-manifest.json +17 -0
- package/jest.config.js +3 -0
- package/metro.config.js +11 -0
- package/package.json +54 -0
- package/react-native.config.js +7 -0
- package/screenshots/1.png +0 -0
- package/screenshots/2.png +0 -0
- package/screenshots/3.png +0 -0
- package/screenshots/4.png +0 -0
- package/screenshots/5.png +0 -0
- package/src/assets/fonts/Cairo.ttf +0 -0
- package/src/assets/fonts/QCF_BSML.ttf +0 -0
- package/src/assets/fonts/QCF_P001.ttf +0 -0
- package/src/assets/images/bookmark.png +0 -0
- package/src/assets/images/close.png +0 -0
- package/src/assets/images/copy.png +0 -0
- package/src/assets/images/down-chevron.png +0 -0
- package/src/assets/images/mushafFrame.png +0 -0
- package/src/assets/images/pause.png +0 -0
- package/src/assets/images/play-button.png +0 -0
- package/src/assets/images/play.svg +16 -0
- package/src/assets/images/playNext.png +0 -0
- package/src/assets/images/surahNameFrame.png +0 -0
- package/src/common/chapters.ts +1346 -0
- package/src/common/constants.ts +27 -0
- package/src/common/images.ts +13 -0
- package/src/common/index.ts +8 -0
- package/src/common/juzs.ts +411 -0
- package/src/common/priorityPages.ts +46 -0
- package/src/common/themes.ts +7 -0
- package/src/components/index.ts +3 -0
- package/src/components/lists/index.ts +3 -0
- package/src/components/lists/pageVersesList.tsx +220 -0
- package/src/components/lists/verseLinesWordsList.tsx +90 -0
- package/src/components/modals/index.ts +3 -0
- package/src/components/modals/optionsModal.tsx +126 -0
- package/src/components/modals/recitersModal.tsx +118 -0
- package/src/components/sections/audioPlayer.tsx +185 -0
- package/src/components/sections/audioPlayerControls.tsx +100 -0
- package/src/components/sections/index.ts +4 -0
- package/src/components/sections/loader.tsx +33 -0
- package/src/helpers/index.ts +1 -0
- package/src/helpers/quranHelpers.tsx +17 -0
- package/src/hooks/apis/index.ts +10 -0
- package/src/hooks/apis/useGetChapterAudio.ts +111 -0
- package/src/hooks/apis/useGetChapterByPage.ts +166 -0
- package/src/hooks/apis/useGetChapterLookup.ts +31 -0
- package/src/hooks/apis/useGetReciters.ts +44 -0
- package/src/hooks/controllers/index.ts +25 -0
- package/src/hooks/controllers/useAudioPlayerController.tsx +63 -0
- package/src/hooks/controllers/useOptionsModalController.ts +99 -0
- package/src/hooks/controllers/usePageFontFileController.ts +255 -0
- package/src/hooks/controllers/usePageLineController.ts +108 -0
- package/src/hooks/helpers/index.ts +6 -0
- package/src/hooks/helpers/useQuranFontPreloader.ts +225 -0
- package/src/hooks/index.ts +3 -0
- package/src/index.ts +5 -0
- package/src/layouts/bismillahText.tsx +18 -0
- package/src/layouts/index.ts +4 -0
- package/src/layouts/quranChapterHeader.tsx +49 -0
- package/src/layouts/quranPageLayout.tsx +178 -0
- package/src/types/global.d.ts +7 -0
- package/src/types/index.ts +212 -0
- package/src/utils/axiosInstance.ts +7 -0
- package/src/utils/fileHandlers.ts +96 -0
- package/src/utils/handleBeforeAndAfterCurrentVerse.ts +41 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/matrics.ts +37 -0
- package/tsconfig.json +3 -0
- 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;
|
package/src/index.ts
ADDED
|
@@ -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,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,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
|
+
}
|