bu koddaki bazı fonsiyonları farklı sayfalara taşıyıp dışarıdan çekelim:
import React, { useEffect, useState, useRef, useCallback, useMemo } from 'react';
import { View, StyleSheet, Text, FlatList, Image, TouchableOpacity, ActivityIndicator, BackHandler } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import WordExplanationBox from './WordExplanationBox';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as Font from 'expo-font';
import { useThemeAndLanguage } from '../utils/ThemeAndLanguageContext';
import { BottomSheetModal, BottomSheetModalProvider, BottomSheetScrollView } from '@gorhom/bottom-sheet';
import QuizScreen from './QuizScreen';
import { doc, getDoc } from 'firebase/firestore';
import { db } from '../utils/firebase';
import { useFocusEffect } from '@react-navigation/native';
import { useVocabulary } from './VocabularyContext';
import PropTypes from 'prop-types';
import ToggleHeartButton from './heart';

const ARABIC_FONTS = {
  'Scheherazade': require('../../assets/fonts/scheherazade.ttf'),
  'Adobe Arabic': require('../../assets/fonts/adobearabic.ttf'),
  'Amiri': require('../../assets/fonts/amiri.ttf'),
  'Noto Naskh Arabic': require('../../assets/fonts/noto.ttf'),
};
const STORAGE_KEY = '@user_words';
const Word = React.memo(({ word, onPress, style, isKnown }) => (
  <TouchableOpacity onPress={() => onPress(word)}>
    <Text style={[style, isKnown && styles.knownWord]}>{word}</Text>
  </TouchableOpacity>
));
Word.propTypes = {
  word: PropTypes.string.isRequired,
  onPress: PropTypes.func.isRequired,
  style: PropTypes.object,
  isKnown: PropTypes.bool,
};
const Sentence = React.memo(({ sentenceObj, selectedSentence, handleSentenceButtonPress, handleWordPress, fontSize, theme, arabicFont, knownWords }) => {
  if (sentenceObj.type === 'image') {
    return (
      <Image 
        source={{ uri: sentenceObj.content }} 
        style={[styles.imageStyle]} 
      />
    );
  }
  const isHeaderOrSubHeader = sentenceObj.type === 'header' || sentenceObj.type === 'subheader';
  return (
    <View style={[
      styles.sentenceContainer, 
      selectedSentence === sentenceObj.content && styles.selectedSentence,
 isHeaderOrSubHeader && (sentenceObj.type === 'header' ? styles.headerContainer : styles.subHeaderContainer),
    {
      borderRightColor: sentenceObj.type === 'header' ? theme.primaryColor : theme.secondaryColor
    }    ]}>
      <TouchableOpacity style={styles.explanationButton} onPress={() => handleSentenceButtonPress(sentenceObj.content)}>
        <Ionicons name="open" size={24} color={theme.primaryColor} />
      </TouchableOpacity>
      <View style={styles.arabicTextWrapper}>
        {sentenceObj.content.split(' ').map((word, wordIndex) => (
          <Word
            key={`${sentenceObj.id}-${wordIndex}`}
            word={word}
            onPress={handleWordPress}
            style={[
              styles.descriptionArabic,
              {
                fontSize: isHeaderOrSubHeader ? fontSize * 1.6 : fontSize * 1.4,
                color: theme.textColor,
                fontFamily: arabicFont,
               }
            ]}
            isKnown={knownWords.has(word)}
          />
        ))}
      </View>
    </View>
  );
});
Sentence.propTypes = {
  sentenceObj: PropTypes.shape({
    type: PropTypes.string,
    content: PropTypes.string,
    id: PropTypes.string,
  }).isRequired,
  selectedSentence: PropTypes.string,
  handleSentenceButtonPress: PropTypes.func.isRequired,
  handleWordPress: PropTypes.func.isRequired,
  fontSize: PropTypes.number.isRequired,
  theme: PropTypes.object.isRequired,
  arabicFont: PropTypes.string.isRequired,
  knownWords: PropTypes.instanceOf(Set).isRequired,
};

export default function ReadStoryScreen({ route, navigation }) {
  const { story, storyId } = route.params;
  const [fontSize, setFontSize] = useState(18);
  const [selectedWord, setSelectedWord] = useState(null);
  const [selectedSentence, setSelectedSentence] = useState(null);
  const [loading, setLoading] = useState(true);
  const [cachedStory, setCachedStory] = useState(null);
  const [hasQuiz, setHasQuiz] = useState(false);
  const bottomSheetModalRef = useRef(null);
  const settingsBottomSheetModalRef = useRef(null);
  const quizBottomSheetModalRef = useRef(null);
  const { locale, theme, arabicFont, setFontFamily, t } = useThemeAndLanguage();
  const [activeModal, setActiveModal] = useState(null);
  const [knownWords, setKnownWords] = useState(new Set());
  const { vocabulary, isLoggedIn, userId} = useVocabulary();


  const increaseFontSize = useCallback(() => setFontSize(prevSize => prevSize + 2), []);
  const decreaseFontSize = useCallback(() => setFontSize(prevSize => prevSize - 2), []);

  const closeAllModals = useCallback(() => {
    bottomSheetModalRef.current?.dismiss();
    settingsBottomSheetModalRef.current?.dismiss();
    quizBottomSheetModalRef.current?.dismiss();
    setActiveModal(null);
  }, []);

  const openSettingsModal = useCallback(() => {
    settingsBottomSheetModalRef.current?.present();
    setActiveModal('settings');
  }, []);

  const openQuizModal = useCallback(() => {
    quizBottomSheetModalRef.current?.present();
    setActiveModal('quiz');
  }, []);

  const handleWordPress = useCallback((word) => {
    setSelectedWord(word);
    setSelectedSentence(null);
    bottomSheetModalRef.current?.present();
    setActiveModal('word');
  }, []);

  const handleSentenceButtonPress = useCallback((sentence) => {
    setSelectedSentence(sentence);
    setSelectedWord(null);
    bottomSheetModalRef.current?.present();
    setActiveModal('sentence');
  }, []);

  const loadFonts = useCallback(async () => {
    await Font.loadAsync(ARABIC_FONTS);
  }, []);

  const fetchStoryFromFirestore = useCallback(async (id) => {
    const storyDocRef = doc(db, 'stories', id);
    const storyDoc = await getDoc(storyDocRef);
    return storyDoc.exists() ? { id: storyDoc.id, ...storyDoc.data() } : null;
  }, []);

  const fetchStory = useCallback(async () => {
    try {
      let storyData;
      if (story) {
        storyData = story;
      } else if (storyId) {
        const cachedData = await AsyncStorage.getItem(`story-${storyId}`);
        if (cachedData) {
          storyData = JSON.parse(cachedData);
        } else {
          storyData = await fetchStoryFromFirestore(storyId);
          if (storyData) {
            await AsyncStorage.setItem(`story-${storyId}`, JSON.stringify(storyData));
          }
        }
      }

      if (storyData) {
        setCachedStory(storyData);
        setHasQuiz(storyData.test_questions && storyData.test_questions.length > 0);
      }
    } catch (error) {
      console.error('Error fetching story:', error);
    } finally {
      setLoading(false);
    }
  }, [story, storyId, fetchStoryFromFirestore]);

  const fetchKnownWords = useCallback(async () => {
    if (!isLoggedIn) {
      setKnownWords(new Set());
      return;
    }

    try {
      const cachedWords = await AsyncStorage.getItem(STORAGE_KEY);
      if (cachedWords) {
        const wordsArray = JSON.parse(cachedWords);
        setKnownWords(new Set(wordsArray.map(word => word.word)));
      }
    } catch (error) {
      console.error('Error fetching known words:', error);
    }
  }, [isLoggedIn]);

  useEffect(() => {
    const initialize = async () => {
      await loadFonts();
      await fetchStory();
      await fetchKnownWords();
    };

    initialize();
  }, [loadFonts, fetchStory, fetchKnownWords]);

  useEffect(() => {
    if (cachedStory) {
      const storyTitle = locale === 'tr' ? cachedStory.storytitleturkish : cachedStory.storytitleenglish;
      const truncatedTitle = storyTitle.length > 23 ? `${storyTitle.substring(0, 23)}...` : storyTitle;

      navigation.setOptions({
        title: truncatedTitle,
        headerStyle: { backgroundColor: theme.lighterCardBackgroundColor },
        headerTintColor: theme.textColor,
        headerTitleStyle: { color: theme.textColor, fontWeight: 'bold' },
        headerRight: () => (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
  <ToggleHeartButton storyId={cachedStory.id} initialHeartCount={cachedStory.hearts} />
  <TouchableOpacity onPress={openSettingsModal} style={styles.fontSizeControl}>
    <Ionicons name="settings-outline" size={24} color={theme.textColor} />
  </TouchableOpacity>
</View>


          
        ),
      });
    }
  }, [navigation, cachedStory, theme, locale, openSettingsModal]);

  useFocusEffect(
    useCallback(() => {
      const onBackPress = () => {
        if (activeModal) {
          closeAllModals();
          return true;
        }
        return false;
      };

      BackHandler.addEventListener('hardwareBackPress', onBackPress);

      return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress);
    }, [activeModal, closeAllModals])
  );

  const renderSentence = useCallback(({ item: sentenceObj }) => (
    <Sentence
      sentenceObj={sentenceObj}
      selectedSentence={selectedSentence}
      handleSentenceButtonPress={handleSentenceButtonPress}
      handleWordPress={handleWordPress}
      fontSize={fontSize}
      theme={theme}
      arabicFont={arabicFont}
      knownWords={knownWords}
    />
  ), [selectedSentence, handleSentenceButtonPress, handleWordPress, fontSize, theme, arabicFont, knownWords]);

  const memoizedData = useMemo(() => cachedStory?.sentences || [], [cachedStory]);

  const keyExtractor = useCallback((item) => item.id.toString(), []);

  useEffect(() => {
    const updatedKnownWords = new Set(vocabulary.map(word => word.word));
    setKnownWords(updatedKnownWords);
  }, [vocabulary]);

  if (loading) {
    return (
      <View style={[styles.loadingContainer, { backgroundColor: theme.backgroundColorForWordBox }]}>
        <ActivityIndicator size="large" color={theme.primaryColor} />
      </View>
    );
  }

  if (!cachedStory) {
    return (
      <View style={[styles.loadingContainer, { backgroundColor: theme.backgroundColorForWordBox }]}>
        <Text style={{ color: theme.textColor }}>{t('storyNotFound')}</Text>
      </View>
    );
  }

  return (
    <BottomSheetModalProvider>
      <View style={[styles.container, { backgroundColor: theme.backgroundColorForWordBox }]}>
        <FlatList
          data={memoizedData}
          renderItem={renderSentence}
          keyExtractor={keyExtractor}
          ListHeaderComponent={() => (
            <>
              <Image source={{ uri: cachedStory.thumbnail }} style={styles.thumbnail} />
              <View style={styles.content}>
                <View style={styles.header}>
                  <Text style={[styles.titleArabic, { color: theme.textColor, fontFamily: arabicFont }]}>{cachedStory.storytitlearabic}</Text>
                  <Text style={[styles.titleTurkish, { color: theme.secondaryColor }]}>
                    {locale === 'tr' ? cachedStory.storytitleturkish : cachedStory.storytitleenglish}
                  </Text>
                </View>
              </View>
            </>
          )}
          initialNumToRender={10}
          maxToRenderPerBatch={5}
          windowSize={10}
        />

        {hasQuiz && (
          <TouchableOpacity
            style={[styles.quizButton, { backgroundColor: theme.primaryColor }]}
            onPress={openQuizModal}
          >
            <Text style={styles.quizButtonText}>{t('startQuiz')}</Text>
          </TouchableOpacity>
        )}

<BottomSheetModal
          ref={bottomSheetModalRef}
          index={0}
          snapPoints={['45%', '90%']}
          handleStyle={{ backgroundColor: theme.backgroundColorForWordBox }}
          onDismiss={() => setActiveModal(null)}
        >
          <BottomSheetScrollView contentContainerStyle={styles.bottomSheetContent}>
            <WordExplanationBox
              word={selectedWord || selectedSentence}
              storyId={cachedStory.id}
              onClose={() => bottomSheetModalRef.current?.dismiss()}
            />
          </BottomSheetScrollView>
        </BottomSheetModal>

        <BottomSheetModal
          ref={settingsBottomSheetModalRef}
          index={0}
          snapPoints={['85%']}
          handleStyle={{ backgroundColor: theme.backgroundColorForWordBox }}
          onDismiss={() => setActiveModal(null)}
        >
          <BottomSheetScrollView 
            contentContainerStyle={[
              styles.settingsContent,
              { backgroundColor: theme.backgroundColorForWordBox }
            ]}
          >
            <View style={styles.exampleCard}>
              <Text style={[styles.exampleText, { fontSize: fontSize * 1.4, fontFamily: arabicFont }]}>
                (هذا مثال على الكتابة بالعربية)
              </Text>
            </View>
            
            <View style={styles.fontSizeControls}>
              <TouchableOpacity onPress={increaseFontSize} style={styles.fontSizeButton}>
                <Ionicons name="add-circle-outline" size={40} color={theme.primaryColor} />
                <Text style={styles.fontSizeButtonText}>{t('increaseFontSize')}</Text>
              </TouchableOpacity>
              <TouchableOpacity onPress={decreaseFontSize} style={styles.fontSizeButton}>
                <Ionicons name="remove-circle-outline" size={40} color={theme.primaryColor} />
                <Text style={styles.fontSizeButtonText}>{t('decreaseFontSize')}</Text>
              </TouchableOpacity>
            </View>
            
            <View style={styles.fontOptionsContainer}>
              {Object.keys(ARABIC_FONTS).map((font) => (
                <TouchableOpacity
                  key={font}
                  style={styles.fontOption}
                  onPress={() => setFontFamily(font)}
                >
                  <Text style={styles.fontOptionText}>{font}</Text>
                  <Text style={[styles.fontOptionSample, { fontFamily: font }]}>
                    (اقرأ العربية)
                  </Text>
                </TouchableOpacity>
              ))}
            </View>
          </BottomSheetScrollView>
        </BottomSheetModal>

        {hasQuiz && (
          <BottomSheetModal
            ref={quizBottomSheetModalRef}
            index={0}
            snapPoints={['90%']}
            handleStyle={{ backgroundColor: theme.backgroundColorForWordBox }}
            onDismiss={() => setActiveModal(null)}
          >
            <QuizScreen
              story={cachedStory}
              onClose={() => {
                quizBottomSheetModalRef.current?.dismiss();
                setActiveModal(null);
              }}
            />
          </BottomSheetModal>
        )}
      </View>
          </BottomSheetModalProvider>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  knownWord: {
    backgroundColor: 'rgba(0, 255, 0, 0.1)',
    borderRadius: 10,
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  thumbnail: {
    width: '100%',
    aspectRatio:1/1, 
      },
  content: {
    padding: 16,
  },
  header: {
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
  },
  titleArabic: {
    fontSize: 26,
  },
  titleTurkish: {
    fontSize: 20,
    marginTop: 4,
    textAlign: 'center',
  },
  headerRight: {
    flexDirection: 'row',
    alignItems: 'center',
    marginRight: 10,
  },
  fontSizeControl: {
    marginHorizontal: 5,
  },
  sentenceContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 8,
    paddingLeft: 10,
  },
  explanationButton: {
    marginRight: 2,
  },
  arabicTextWrapper: {
    flex: 1,
    flexDirection: 'row-reverse',
    flexWrap: 'wrap',
    paddingRight: 15,
  },
  descriptionArabic: {
    marginLeft: 2,
    padding: 2,
  },
  selectedSentence: {
    backgroundColor: 'rgba(255, 215, 0, 0.3)',
  },
  settingsContent: {
    flexGrow: 1,
    paddingBottom: 20,
  },
  fontExampleContainer: {
    alignItems: 'center',
    marginBottom: 20,
  },
  exampleLabel: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  exampleBox: {
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 10,
    padding: 10,
    width: '80%',
    alignItems: 'center',
    backgroundColor: 'white',
    elevation: 4,
  },
  fontSizeControls: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginVertical: 25,
    paddingHorizontal: 25,
    width: '80%',
    alignSelf: 'center',
  },
  fontSizeControl: {
    alignItems: 'center',
    padding: 10,
  },
  fontSizeControlText: {
    marginTop: 5,
    fontSize: 14,
    color: 'gray',
  },
  selectFontLabel: {
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 10,
  },
  fontGrid: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'space-around',
    marginTop: 20,
    width: '80%',
    alignSelf: 'center',
  },
  fontOptionGridItem: {
    width: '45%',
    padding: 5,
    marginBottom: 20,
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 10,
    alignItems: 'center',
    backgroundColor: 'white',
    elevation: 4,
  },
  fontOptionText: {
    fontSize: 16,
    marginBottom: 5,
    textAlign: 'center',
  },
  quizButton: {
 display: 'flex', // Flexbox ile genişliği içeriğe göre yap
  justifyContent: 'center', // İçeriği ortala
  alignItems: 'center', // İçeriği dikeyde ortala
    padding: 10,
  },
  quizButtonText: {
    color: 'white',
    fontWeight: 'bold',
  },
  bottomSheetContent: {
    flexGrow: 1,
  },
  settingsContent: {
    flexGrow: 1,
    paddingHorizontal: 20,
    paddingBottom: 20,
    alignItems: 'center',
  },
  exampleCard: {
    backgroundColor: 'white',
    borderRadius: 10,
    padding: 15,
    marginVertical: 20,
    width: '90%',
    alignItems: 'center',
    elevation: 4,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
  },
  exampleText: {
    textAlign: 'center',
  },
  fontSizeControls: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    width: '100%',
    marginBottom: 20,
  },
  fontSizeButton: {
    alignItems: 'center',
  },
  fontSizeButtonText: {
    marginTop: 5,
    fontSize: 12,
    color: 'gray',
    textAlign: 'center',
  },
  fontOptionsContainer: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'space-between',
    width: '100%',
  },
  fontOption: {
    width: '48%',
    backgroundColor: 'white',
    borderRadius: 10,
    padding: 10,
    marginBottom: 15,
    alignItems: 'center',
    elevation: 2,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.22,
    shadowRadius: 2.22,
  },
  fontOptionText: {
    fontSize: 16,
    marginBottom: 5,
  },
  fontOptionSample: {
    fontSize: 18,
  },
headerContainer: {
  marginVertical: 10,
  backgroundColor: 'rgba(0, 0, 0, 0.03)',
  borderRightWidth: 5,
  width: '97%',  // Genişliği biraz küçülttük

},
subHeaderContainer: {
  marginVertical: 10,
  backgroundColor: 'rgba(0, 0, 0, 0.03)',
  borderRightWidth: 3,
  width: '97%', 
},
imageStyle: {
  width: "90%",
  alignSelf: "center", // Ortalamak için bunu ekledik
  marginBottom: 10,
  aspectRatio: 1 / 1, // Oranı sabit tutmak için ekledik
elevation:1,
borderRadius:15,
},
});