@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,220 @@
1
+ import React, {useRef, useState} from 'react';
2
+ import {
3
+ Dimensions,
4
+ ImageBackground,
5
+ StyleSheet,
6
+ Text,
7
+ TouchableOpacity,
8
+ View,
9
+ } from 'react-native';
10
+ import {
11
+ ALFATIHA_CHAPTER_ID,
12
+ ALTAWBA_CHAPTER_ID,
13
+ COLORS,
14
+ FONT_FAMILY,
15
+ IMAGES,
16
+ } from '../../common';
17
+ import {_renderChapterName} from '../../helpers';
18
+ import {BismillahText, QuranPageHeader} from '../../layouts';
19
+ import {
20
+ IModalRef,
21
+ IPageVersesList,
22
+ ISelectedVerseLocation,
23
+ QuranTypesEnums,
24
+ } from '../../types';
25
+ import {
26
+ handleVersesBeforeAndAfterCurrentVerse,
27
+ hp,
28
+ verticalScale,
29
+ } from '../../utils';
30
+ import {OptionsModal} from '../modals';
31
+ import VerseLinesWordsList from './verseLinesWordsList';
32
+ const {width} = Dimensions.get('window');
33
+
34
+ const PageVersesList = (props: IPageVersesList) => {
35
+ const {
36
+ pageVersesToDisplay,
37
+ audioPlayerRef,
38
+ selectedVerse,
39
+ setSelectedVerse,
40
+ onContainerPress,
41
+ showBismllah,
42
+ pageNumber,
43
+ juzNumber,
44
+ setVersesBeforeAndAfterCurrentVerse,
45
+ originalVerse,
46
+ onBookMarkedVerse,
47
+ backgroundImage,
48
+ chapterId,
49
+ quranPageContainerStyle,
50
+ resizeImageBackgroundMode,
51
+ showChapterName,
52
+ selectionColor,
53
+ autoCompleteAudioAfterPlayingVerse,
54
+ type,
55
+ surahNameFrameImage,
56
+ } = props;
57
+ const optionsModalRef = useRef<IModalRef>();
58
+ const [selectedVerseLocation, setSelectedVerseLocation] =
59
+ useState<ISelectedVerseLocation>();
60
+
61
+ const onVersePress = (location: ISelectedVerseLocation) => {
62
+ optionsModalRef?.current?.openModal();
63
+ setSelectedVerseLocation(location);
64
+ };
65
+ const closeOptionsModal = () => {
66
+ optionsModalRef?.current?.closeModal();
67
+ };
68
+ const handlePlayPress = () => {
69
+ closeOptionsModal();
70
+ audioPlayerRef?.current?.setShowPlayerHandler(true);
71
+ handleVersesBeforeAndAfterCurrentVerse({
72
+ selectedVerse,
73
+ setVersesBeforeAndAfterCurrentVerse,
74
+ originalVerse,
75
+ });
76
+ };
77
+ const pageLinesCount = pageVersesToDisplay?.length;
78
+ return (
79
+ <View style={styles.containerView}>
80
+ <ImageBackground
81
+ source={backgroundImage ?? IMAGES.mushafFrame}
82
+ style={[{height: '100%', width: '100%'}, quranPageContainerStyle]}
83
+ resizeMode={resizeImageBackgroundMode ?? 'cover'}>
84
+ <TouchableOpacity
85
+ style={styles.containerBtn}
86
+ activeOpacity={1}
87
+ onPress={onContainerPress}>
88
+ <View
89
+ style={{
90
+ marginTop: 10,
91
+ }}
92
+ />
93
+ {pageVersesToDisplay?.map(item => (
94
+ <React.Fragment key={`${item?.lineNumber}`}>
95
+ {item?.isFirstLine && (
96
+ <QuranPageHeader
97
+ chapterId={item?.chapter_id}
98
+ surahNameFrameImage={
99
+ surahNameFrameImage ?? IMAGES.surahNameFrame
100
+ }
101
+ />
102
+ )}
103
+ {item?.isFirstLine &&
104
+ item?.chapter_id != ALTAWBA_CHAPTER_ID &&
105
+ item?.chapter_id != ALFATIHA_CHAPTER_ID && <BismillahText />}
106
+ <View
107
+ style={{flex: pageLinesCount && pageLinesCount >= 10 ? 1 : 0}}>
108
+ <VerseLinesWordsList
109
+ isCentered={
110
+ item?.page_number === 1 || item?.page_number === 2
111
+ }
112
+ item={item as any}
113
+ selectedVerse={selectedVerse}
114
+ seSelectedVerse={setSelectedVerse}
115
+ setSelectedVerseLocation={onVersePress}
116
+ selectionColor={selectionColor}
117
+ pageNumber={item?.page_number}
118
+ />
119
+ </View>
120
+ </React.Fragment>
121
+ ))}
122
+ <OptionsModal
123
+ ref={optionsModalRef}
124
+ selectedVerseLocation={selectedVerseLocation}
125
+ selectedVerse={selectedVerse}
126
+ seSelectedVerse={setSelectedVerse}
127
+ handlePlayPress={handlePlayPress}
128
+ selectedReciter={audioPlayerRef?.current?._renderSelelctedReciter()}
129
+ onBookMarkedVerse={onBookMarkedVerse}
130
+ chapterId={chapterId}
131
+ autoCompleteAudioAfterPlayingVerse={
132
+ autoCompleteAudioAfterPlayingVerse
133
+ }
134
+ />
135
+
136
+ <View style={styles.pageNumberContainer}>
137
+ <View style={styles.pageNumberView}>
138
+ <Text style={styles.txt}>{pageNumber}</Text>
139
+ </View>
140
+ </View>
141
+ <View style={styles.juzNumberContainer}>
142
+ <View style={styles.juzNumberCircle}>
143
+ <Text style={styles.txt}>الجزء {juzNumber}</Text>
144
+ </View>
145
+ {(!showChapterName || type === QuranTypesEnums.juz) && (
146
+ <View style={styles.juzNumberCircle}>
147
+ <Text style={[styles.txt, {fontFamily: FONT_FAMILY.BISMLLAH}]}>
148
+ {_renderChapterName(chapterId)}
149
+ </Text>
150
+ </View>
151
+ )}
152
+ </View>
153
+ </TouchableOpacity>
154
+ </ImageBackground>
155
+ </View>
156
+ );
157
+ };
158
+ export default PageVersesList;
159
+
160
+ const styles = StyleSheet.create({
161
+ containerView: {
162
+ width,
163
+ alignItems: 'center',
164
+ justifyContent: 'center',
165
+ backgroundColor: COLORS.white,
166
+ },
167
+ pageNumberView: {
168
+ width: 40,
169
+ height: 40,
170
+ borderRadius: 40 / 2,
171
+ backgroundColor: COLORS.light,
172
+ alignItems: 'center',
173
+ justifyContent: 'center',
174
+ },
175
+ pageNumberContainer: {
176
+ position: 'absolute',
177
+ bottom: verticalScale(10),
178
+ right: 0,
179
+ width: '100%',
180
+ height: 10,
181
+ alignItems: 'center',
182
+ justifyContent: 'center',
183
+ },
184
+ surahNameContainer: {
185
+ width: '90%',
186
+ alignItems: 'center',
187
+ justifyContent: 'center',
188
+ alignSelf: 'center',
189
+ marginVertical: hp('2%'),
190
+ },
191
+ juzNumberContainer: {
192
+ position: 'absolute',
193
+ width: '100%',
194
+ top: 0,
195
+ flexDirection: 'row',
196
+ justifyContent: 'space-between',
197
+ paddingHorizontal: 5,
198
+ },
199
+ juzNumberCircle: {
200
+ alignSelf: 'flex-start',
201
+ backgroundColor: COLORS.light,
202
+ paddingHorizontal: 10,
203
+ borderRadius: 10,
204
+ },
205
+ txt: {fontFamily: FONT_FAMILY.CAIRO, fontSize: 15},
206
+ containerBtn: {
207
+ flex: 1,
208
+ width: '100%',
209
+ alignItems: 'center',
210
+ paddingTop: hp('2%'),
211
+ paddingBottom: hp('5%'),
212
+ },
213
+ mushafFrameImage: {
214
+ height: '100%',
215
+ width: '100%',
216
+ position: 'absolute',
217
+ zIndex: -2,
218
+ alignSelf: 'center',
219
+ },
220
+ });
@@ -0,0 +1,90 @@
1
+ import {
2
+ ColorValue,
3
+ GestureResponderEvent,
4
+ I18nManager,
5
+ Text,
6
+ TouchableOpacity,
7
+ View,
8
+ } from 'react-native';
9
+ import {RFValue} from 'react-native-responsive-fontsize';
10
+ import {ISelectedVerseLocation, ISurahVerse, IVerseWord} from '../../types';
11
+ import {COLORS} from '../../common';
12
+ import {usePageFontFileController} from '../../hooks';
13
+ import {getChapterCodeV1} from '../../helpers';
14
+ interface IProps {
15
+ item: ISurahVerse;
16
+ isCentered: boolean;
17
+ selectedVerse: ISurahVerse;
18
+ seSelectedVerse: (value: ISurahVerse) => void;
19
+ setSelectedVerseLocation: (value: ISelectedVerseLocation) => void;
20
+ selectionColor?: ColorValue;
21
+ pageNumber: number | undefined;
22
+ }
23
+ const VerseLinesWordsList = ({
24
+ item,
25
+ isCentered,
26
+ seSelectedVerse,
27
+ selectedVerse,
28
+ setSelectedVerseLocation,
29
+ selectionColor,
30
+ pageNumber,
31
+ }: IProps) => {
32
+ const {_fontFileFormatGenerator} = usePageFontFileController();
33
+
34
+ const verseWordSelected = (
35
+ event: GestureResponderEvent,
36
+ item: IVerseWord,
37
+ ) => {
38
+ const {pageY, pageX} = event.nativeEvent;
39
+ const chapterCodeV1 = getChapterCodeV1(item?.verseData?.chapter_id);
40
+ seSelectedVerse({
41
+ ...item?.verseData,
42
+ chapter_code_v1: chapterCodeV1,
43
+ verse_font_famliy: pageNumber ? _fontFileFormatGenerator(pageNumber) : '',
44
+ });
45
+ setSelectedVerseLocation({
46
+ itemLocationY: pageY,
47
+ itemLocationX: pageX,
48
+ });
49
+ };
50
+ return (
51
+ <View
52
+ style={{
53
+ flexDirection: I18nManager.isRTL ? 'row' : 'row-reverse',
54
+ justifyContent: isCentered ? undefined : 'space-between',
55
+ alignItems: 'center',
56
+ width: '85%',
57
+ alignSelf: 'center',
58
+ }}>
59
+ {item?.words?.map(innerItem => {
60
+ // isVerseNumber: refers to ayah number form in mushaf
61
+ const isVerseNumber = innerItem?.char_type_name == 'end';
62
+ const isWordVerseSelected =
63
+ innerItem?.verseData?.id == selectedVerse?.id && !isVerseNumber;
64
+
65
+ return (
66
+ <TouchableOpacity
67
+ activeOpacity={1}
68
+ key={`${innerItem?.id}`}
69
+ onPress={event => {
70
+ verseWordSelected(event, innerItem);
71
+ }}>
72
+ <Text
73
+ adjustsFontSizeToFit
74
+ style={{
75
+ fontFamily: _fontFileFormatGenerator(innerItem?.page_number),
76
+ fontSize: isCentered ? 35 : RFValue(16),
77
+ backgroundColor: isWordVerseSelected
78
+ ? selectionColor ?? COLORS.light
79
+ : 'transparent',
80
+ }}>
81
+ {innerItem?.code_v1}
82
+ </Text>
83
+ </TouchableOpacity>
84
+ );
85
+ })}
86
+ </View>
87
+ );
88
+ };
89
+
90
+ export default VerseLinesWordsList;
@@ -0,0 +1,3 @@
1
+ import OptionsModal from './optionsModal';
2
+ import RecitersModal from './recitersModal';
3
+ export {OptionsModal, RecitersModal};
@@ -0,0 +1,126 @@
1
+ import {forwardRef, useImperativeHandle, useState} from 'react';
2
+ import {
3
+ Image,
4
+ Modal,
5
+ SafeAreaView,
6
+ StyleSheet,
7
+ TouchableOpacity,
8
+ View,
9
+ } from 'react-native';
10
+ import {IOptionsModal} from '../../types';
11
+ import {COLORS} from '../../common';
12
+ import IMAGES from '../../common/images';
13
+ import {useOptionsModalController} from '../../hooks';
14
+ import {Loader} from '../sections';
15
+
16
+ const OptionsModal = (props: IOptionsModal, ref: any) => {
17
+ const {
18
+ selectedVerseLocation,
19
+ selectedVerse,
20
+ seSelectedVerse,
21
+ handlePlayPress,
22
+ selectedReciter,
23
+ onBookMarkedVerse,
24
+ chapterId,
25
+ autoCompleteAudioAfterPlayingVerse,
26
+ } = props;
27
+ const [isVisible, setIsVisible] = useState(false);
28
+
29
+ const {
30
+ _renderOptionContainerPosition,
31
+ OPTION_CONTAINER_WIDTH,
32
+ onPlayerPress,
33
+ copyVerseToClipBoard,
34
+ onRequestClose,
35
+ isVersePositionLoading,
36
+ } = useOptionsModalController({
37
+ selectedVerseLocation,
38
+ selectedVerse,
39
+ selectedReciter,
40
+ handlePlayPress,
41
+ setIsVisible,
42
+ seSelectedVerse,
43
+ });
44
+ const closeModal = () => {
45
+ setIsVisible(false);
46
+ };
47
+ useImperativeHandle(ref, () => ({
48
+ openModal() {
49
+ setIsVisible(true);
50
+ },
51
+ closeModal() {
52
+ closeModal();
53
+ },
54
+ }));
55
+
56
+ const transform = [
57
+ {translateY: _renderOptionContainerPosition()?.translateY},
58
+ {
59
+ translateX: _renderOptionContainerPosition()?.translateX,
60
+ },
61
+ ];
62
+
63
+ return (
64
+ <Modal visible={isVisible} transparent onRequestClose={onRequestClose}>
65
+ <SafeAreaView style={{flex: 1}}>
66
+ <TouchableOpacity
67
+ onPress={onRequestClose}
68
+ style={{flex: 1, backgroundColor: COLORS.lightBackground}}>
69
+ <View
70
+ style={[
71
+ styles.optionViewContainer,
72
+ {
73
+ width: OPTION_CONTAINER_WIDTH,
74
+ transform,
75
+ height: 50,
76
+ } as any,
77
+ ]}>
78
+ <TouchableOpacity
79
+ onPress={() =>
80
+ onPlayerPress({
81
+ reciterId: selectedReciter?.id as number,
82
+ verse_key: selectedVerse?.verse_key,
83
+ handlePlayPress,
84
+ chapterId,
85
+ autoCompleteAudioAfterPlayingVerse,
86
+ })
87
+ }>
88
+ {isVersePositionLoading ? (
89
+ <Loader />
90
+ ) : (
91
+ <Image source={IMAGES.playIcon} style={styles.icon} />
92
+ )}
93
+ </TouchableOpacity>
94
+ <TouchableOpacity onPress={copyVerseToClipBoard}>
95
+ <Image source={IMAGES.copyIcon} style={styles.icon} />
96
+ </TouchableOpacity>
97
+ <TouchableOpacity
98
+ onPress={() => {
99
+ if (onBookMarkedVerse) onBookMarkedVerse(selectedVerse);
100
+ closeModal();
101
+ }}>
102
+ <Image source={IMAGES.bookmark} style={styles.icon} />
103
+ </TouchableOpacity>
104
+ </View>
105
+ </TouchableOpacity>
106
+ </SafeAreaView>
107
+ </Modal>
108
+ );
109
+ };
110
+
111
+ export default forwardRef(OptionsModal);
112
+
113
+ const styles = StyleSheet.create({
114
+ optionViewContainer: {
115
+ backgroundColor: 'white',
116
+ borderRadius: 10,
117
+ flexDirection: 'row',
118
+ alignItems: 'center',
119
+ paddingHorizontal: 10,
120
+ },
121
+ icon: {
122
+ width: 20,
123
+ height: 20,
124
+ marginLeft: 15,
125
+ },
126
+ });
@@ -0,0 +1,118 @@
1
+ import {forwardRef, useImperativeHandle, useState} from 'react';
2
+ import {
3
+ Dimensions,
4
+ FlatList,
5
+ Image,
6
+ Modal,
7
+ SafeAreaView,
8
+ StyleSheet,
9
+ Text,
10
+ TouchableOpacity,
11
+ View,
12
+ } from 'react-native';
13
+ import {COLORS, IMAGES} from '../../common';
14
+ import {IReciter, ISurahVerse} from '../../types';
15
+ import {useGetChapterAudio} from '../../hooks';
16
+ const {height} = Dimensions.get('screen');
17
+ interface IProps {
18
+ allReciter: IReciter[];
19
+ selectedReciter: IReciter | undefined;
20
+ setSelectedReciter: (value: IReciter) => void;
21
+ chapterId: number;
22
+ selectedVerse: ISurahVerse;
23
+ autoCompleteAudioAfterPlayingVerse?: boolean;
24
+ }
25
+ const RecitersModal = (props: IProps, ref: any) => {
26
+ const {
27
+ allReciter,
28
+ selectedReciter,
29
+ setSelectedReciter,
30
+ chapterId,
31
+ selectedVerse,
32
+ autoCompleteAudioAfterPlayingVerse,
33
+ } = props;
34
+ const [isVisible, setIsVisible] = useState(false);
35
+ const {getChapterAudionUrl} = useGetChapterAudio();
36
+ useImperativeHandle(ref, () => ({
37
+ openModal() {
38
+ setIsVisible(true);
39
+ },
40
+ closeModal() {
41
+ setIsVisible(false);
42
+ },
43
+ }));
44
+ const closeModal = () => {
45
+ setIsVisible(false);
46
+ };
47
+ const onSelectReciter = (item: IReciter) => {
48
+ getChapterAudionUrl({
49
+ reciterId: item?.id,
50
+ chapterId,
51
+ verse_key: selectedVerse?.verse_key,
52
+ autoCompleteAudioAfterPlayingVerse,
53
+ });
54
+ closeModal();
55
+ setSelectedReciter(item);
56
+ };
57
+ return (
58
+ <Modal visible={isVisible} transparent onRequestClose={closeModal}>
59
+ <SafeAreaView style={{flex: 1}}>
60
+ <View style={styles.container}>
61
+ <TouchableOpacity style={{flex: 1}} onPress={closeModal} />
62
+ <View style={styles.smallContainer}>
63
+ <TouchableOpacity style={styles.closeIconBtn} onPress={closeModal}>
64
+ <Image source={IMAGES.close} style={styles.closeIcon} />
65
+ </TouchableOpacity>
66
+ <FlatList
67
+ data={allReciter}
68
+ renderItem={({item}) => (
69
+ <TouchableOpacity
70
+ onPress={() => onSelectReciter(item)}
71
+ style={[
72
+ styles.content,
73
+ {
74
+ backgroundColor:
75
+ selectedReciter?.id === item?.id
76
+ ? COLORS.light
77
+ : 'white',
78
+ },
79
+ ]}>
80
+ <Text>{item?.name}</Text>
81
+ </TouchableOpacity>
82
+ )}
83
+ />
84
+ </View>
85
+ </View>
86
+ </SafeAreaView>
87
+ </Modal>
88
+ );
89
+ };
90
+
91
+ export default forwardRef(RecitersModal);
92
+
93
+ const styles = StyleSheet.create({
94
+ container: {
95
+ flex: 1,
96
+ backgroundColor: COLORS.lightBackground,
97
+ justifyContent: 'flex-end',
98
+ },
99
+ content: {
100
+ width: '100%',
101
+ alignSelf: 'center',
102
+ alignItems: 'flex-start',
103
+ padding: 15,
104
+ borderColor: COLORS.light,
105
+ borderWidth: 1,
106
+ borderRadius: 10,
107
+ marginVertical: 5,
108
+ },
109
+ smallContainer: {
110
+ borderTopLeftRadius: 10,
111
+ borderTopRightRadius: 10,
112
+ backgroundColor: 'white',
113
+ padding: 10,
114
+ maxHeight: height - 300,
115
+ },
116
+ closeIconBtn: {alignSelf: 'flex-end', marginVertical: 5},
117
+ closeIcon: {width: 25, height: 25},
118
+ });