@react-navigation/native#useTheme JavaScript Examples

The following examples show how to use @react-navigation/native#useTheme. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: CommentListItem.js    From reddit-clone with MIT License 6 votes vote down vote up
CommentListItem = ({ body, author, created, deleteComment }) => {
  const { colors } = useTheme()
  const { authState } = React.useContext(AuthContext)

  return (
    <View style={[styles.container, { backgroundColor: colors.bgColor }]}>
      <View style={[styles.header, { borderBottomColor: colors.border }]}>
        <Text style={[styles.authorName, { color: colors.blue }]}>{author?.username}</Text>
        <View style={styles.headerRight}>
          <Text style={[styles.dateText, { color: colors.text }]}>{moment(created).fromNow()}</Text>
          {author?.id === authState.userInfo.id && (
            <TouchableOpacity style={styles.trash} activeOpacity={0.5} onPress={deleteComment}>
              <Trash color={colors.red} width={20} height={20} />
            </TouchableOpacity>
          )}
        </View>
      </View>
      <View style={styles.body}>
        <Text style={[styles.regularFont, { color: colors.text }]}>{body}</Text>
      </View>
    </View>
  )
}
Example #2
Source File: SignModal.js    From reddit-clone with MIT License 6 votes vote down vote up
SignModal = ({ navigation }) => {
  const { colors } = useTheme()

  return (
    <TouchableWithoutFeedback onPress={() => navigation.goBack()}>
      <View as={SafeAreaView} style={styles.container}>
        <StatusBar hidden />
        <View
          style={[styles.modal, { backgroundColor: colors.background }]}
          onStartShouldSetResponder={() => true}
        >
          <View style={styles.buttonContainer}>
            <Button
              bgColor={colors.signUpButton}
              title="Sign Up"
              onPress={() => navigation.navigate('SignUp')}
            >
              <PlusCircle color={colors.white} />
            </Button>
            <Button
              bgColor={colors.signInButton}
              title="Sign In"
              onPress={() => navigation.navigate('SignIn')}
            >
              <LogIn color={colors.white} />
            </Button>
          </View>
        </View>
      </View>
    </TouchableWithoutFeedback>
  )
}
Example #3
Source File: CategoryPicker.js    From reddit-clone with MIT License 6 votes vote down vote up
CategoryPicker = ({ selectedCategory, onClick, addAll, setFieldValue, ...props }) => {
  const { colors } = useTheme()

  return (
    <View {...props}>
      <FlatList
        data={addAll ? ['all', ...categories] : categories}
        horizontal
        keyExtractor={item => item}
        renderItem={({ item }) => (
          <TouchableOpacity
            onPress={() => (onClick ? onClick(item) : setFieldValue('category', item))}
          >
            <Text
              style={[
                styles.category,
                {
                  fontWeight: item === selectedCategory ? 'bold' : 'normal',
                  borderBottomColor: item === selectedCategory ? colors.blue : 'transparent',
                  color: item === selectedCategory ? colors.blue : colors.text
                }
              ]}
            >
              {item}
            </Text>
          </TouchableOpacity>
        )}
      />
    </View>
  )
}
Example #4
Source File: Stations.js    From timetable with MIT License 6 votes vote down vote up
Stations = () => {
  const navigation = useNavigation()
  const { i18n } = useTranslation()
  const { dark } = useTheme()

  const [db, setDb] = useState({
    markers: []
  })

  useEffect(() => {
    const unsubscribe = navigation.addListener('focus', () => {
      const station = i18n.language == 'en' ? EnDb.Stops : GeDb.Stops
      setDb({ markers: station })
    })

    // Cleanup
    return unsubscribe
  }, [navigation])

  // Opens Timetable screen which takes some props from map marker
  const openTimetable = (stopId, name) => {
    navigation.navigate('Timetable', {
      stationTimetableId: stopId,
      metadata: name
    })
  }

  return (
    <View style={styles.container}>
      <Map
        markerSource={db.markers}
        onPressHandler={openTimetable}
        isDark={dark}
      />
    </View>
  )
}
Example #5
Source File: CreatePost.js    From reddit-clone with MIT License 6 votes vote down vote up
TypeSwichButton = ({ selected, onClick, type }) => {
  const { colors } = useTheme()

  return (
    <TouchableOpacity
      style={[
        styles.typeButton,
        type === 'link' ? styles.typeButtonRight : styles.typeButtonLeft,
        selected === type ? { backgroundColor: colors.blue } : '',
        { borderColor: colors.border }
      ]}
      onPress={() => onClick('type', type)}
    >
      <View>
        <Text
          style={[
            styles.typeButtonLabel,
            { color: colors.text },
            selected === type ? { color: 'white' } : ''
          ]}
        >
          {type}
        </Text>
      </View>
    </TouchableOpacity>
  )
}
Example #6
Source File: FilledButton.js    From ReactNavigationAuthenticationFlowsWithHooks with MIT License 6 votes vote down vote up
export function FilledButton({title, style, onPress}) {
  const {colors} = useTheme();

  return (
    <TouchableOpacity
      style={[styles.container, style, {backgroundColor: colors.primary}]}
      onPress={onPress}>
      <Text style={styles.text}>{title.toUpperCase()}</Text>
    </TouchableOpacity>
  );
}
Example #7
Source File: CategoryLoader.js    From reddit-clone with MIT License 6 votes vote down vote up
CategoryLoader = () => {
  const { colors } = useTheme()

  return (
    <View style={[styles.loader, { backgroundColor: colors.bgColor }]}>
      {[1, 2, 3, 4, 5].map(i => (
        <TextLoader key={i} />
      ))}
    </View>
  )
}
Example #8
Source File: Button.js    From reddit-clone with MIT License 6 votes vote down vote up
Button = ({ children, bgColor, title, ...props }) => {
  const { colors } = useTheme()

  return (
    <TouchableOpacity
      {...props}
      style={[styles.button, { backgroundColor: bgColor }]}
      activeOpacity={0.8}
    >
      {children}
      <Text style={[styles.buttonText, { color: colors.white }]}>{title}</Text>
    </TouchableOpacity>
  )
}
Example #9
Source File: TextButton.js    From ReactNavigationAuthenticationFlowsWithHooks with MIT License 6 votes vote down vote up
export function TextButton({title, style, onPress}) {
  const {colors} = useTheme();
  return (
    <TouchableOpacity style={[styles.container, style]} onPress={onPress}>
      <Text style={[styles.text, {color: colors.primary}]}>
        {title.toUpperCase()}
      </Text>
    </TouchableOpacity>
  );
}
Example #10
Source File: PostLoader.js    From reddit-clone with MIT License 6 votes vote down vote up
PostLoader = ({ ...props }) => {
  const { colors } = useTheme()

  return (
    <View style={[styles.loader, { backgroundColor: colors.bgColor }]} {...props}>
      <TextLoader style={{ width: '30%', marginTop: 10 }} />
      {[1, 2, 3].map(i => (
        <TextLoader key={i} style={{ width: '100%', marginTop: 10 }} />
      ))}
      <TextLoader style={{ width: '80%', marginTop: 10 }} />
    </View>
  )
}
Example #11
Source File: CreateComment.js    From reddit-clone with MIT License 6 votes vote down vote up
CreateComment = ({ onPress, setComment, comment, setIsFocused }) => {
  const { colors } = useTheme()
  const textInputRef = React.useRef()

  return (
    <View style={[styles.container, { backgroundColor: colors.bgColor }]}>
      <TextInput
        style={[
          styles.textInput,
          { backgroundColor: colors.background, borderColor: colors.border, color: colors.text }
        ]}
        ref={textInputRef}
        placeholder="Add a comment"
        placeholderTextColor={colors.text}
        onFocus={() => setIsFocused(true)}
        onBlur={() => setIsFocused(false)}
        onChangeText={setComment}
        maxLength={2000}
        autoCorrect={false}
        value={comment}
      />
      <TouchableOpacity
        onPress={() => {
          textInputRef.current.blur()
          onPress()
        }}
      >
        <Send color={colors.text} />
      </TouchableOpacity>
    </View>
  )
}
Example #12
Source File: CommentLoader.js    From reddit-clone with MIT License 6 votes vote down vote up
CommentLoader = ({ ...props }) => {
  const { colors } = useTheme()

  return (
    <View style={[styles.loader, { backgroundColor: colors.bgColor }]} {...props}>
      <TextLoader style={{ width: '30%', marginTop: 10 }} />
      <TextLoader style={{ width: '100%', marginTop: 10 }} />
    </View>
  )
}
Example #13
Source File: TabBar.js    From reddit-clone with MIT License 5 votes vote down vote up
function TabBar({ state, descriptors, navigation }) {
  const { authState } = React.useContext(AuthContext)
  const { colors } = useTheme()

  return (
    <View
      style={[
        styles.tabBarContainer,
        { backgroundColor: colors.bgColor, borderColor: colors.border }
      ]}
    >
      {state.routes.map((route, index) => {
        const { options } = descriptors[route.key]
        const label =
          options.tabBarLabel !== undefined
            ? options.tabBarLabel
            : options.title !== undefined
            ? options.title
            : route.name

        const isFocused = state.index === index

        const onPress = () => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
            canPreventDefault: true
          })

          if (!isFocused && !event.defaultPrevented) {
            if (authState.token) {
              navigation.navigate(route.name, {
                username: authState.userInfo.username
              })
            } else {
              navigation.navigate('SignModal')
            }
          }
        }

        return (
          <TouchableOpacity key={route.key} onPress={onPress} style={styles.button}>
            {label === 'Home' && <Home color={isFocused ? colors.blue : colors.text} />}
            {label === 'CreatePost' && <PlusSquare color={isFocused ? colors.blue : colors.text} />}
            {label === 'User' && <User color={isFocused ? colors.blue : colors.text} />}
          </TouchableOpacity>
        )
      })}
    </View>
  )
}
Example #14
Source File: User.js    From reddit-clone with MIT License 5 votes vote down vote up
User = ({ route }) => {
  const { authState } = React.useContext(AuthContext)
  const { colors } = useTheme()

  const [isLoading, setIsLoaading] = React.useState(false)
  const [userPosts, setuserPosts] = React.useState(null)

  const username = route.params?.username

  const getUserPostDetail = React.useCallback(async () => {
    setIsLoaading(true)
    const { data } = await axios.get(`user/${username || authState.userInfo.username}`)
    setuserPosts(data)
    setIsLoaading(false)
  }, [authState.userInfo.username, username])

  React.useEffect(() => {
    getUserPostDetail()
  }, [getUserPostDetail])

  const deletePost = async (postId, index) => {
    setIsLoaading(true)
    const { status } = await axios.delete(`post/${postId}`)
    if (status === 200) {
      setuserPosts(prevData => {
        prevData.splice(index, 1)
        return prevData
      })
    }
    setIsLoaading(false)
  }

  return (
    <View as={SafeAreaView} style={styles.boxCenter}>
      {userPosts ? (
        <FlatList
          data={userPosts.sort((a, b) => a.created < b.created)}
          extraData={isLoading}
          refreshing={isLoading}
          onRefresh={() => getUserPostDetail()}
          keyExtractor={item => item.id}
          ListEmptyComponent={
            <Text style={[styles.empty, { color: colors.text }]}>Ups! Not found any post!</Text>
          }
          ListHeaderComponent={<HeaderComponent username={username} postCount={userPosts.length} />}
          stickyHeaderIndices={[0]}
          ListHeaderComponentStyle={styles.headerComponentStyle}
          renderItem={({ item, index }) => (
            <Post
              index={index}
              postId={item.id}
              userId={authState.userInfo.id}
              score={item.score}
              type={item.type}
              title={item.title}
              author={item.author}
              category={item.category}
              text={item.text}
              comments={item.comments}
              created={item.created}
              url={item.url}
              votes={item.votes}
              views={item.views}
              setIsLoaading={setIsLoaading}
              setData={setuserPosts}
              deleteButton={true}
              deletePost={() => deletePost(item.id, index)}
            />
          )}
        />
      ) : (
        <>
          {[1, 2, 3, 4, 5].map(i => (
            <PostLoader key={i} />
          ))}
        </>
      )}
    </View>
  )
}
Example #15
Source File: TextLoader.js    From reddit-clone with MIT License 5 votes vote down vote up
TextLoader = ({ ...props }) => {
  const { colors } = useTheme()

  return <View style={[styles.bgLight, props.style, { backgroundColor: colors.loader }]} />
}
Example #16
Source File: Home.js    From reddit-clone with MIT License 5 votes vote down vote up
Home = () => {
  const { authState } = React.useContext(AuthContext)
  const { theme } = React.useContext(ThemeContext)
  const { colors } = useTheme()

  const [postData, setPostData] = React.useState(null)
  const [category, setCategory] = React.useState('all')
  const [isLoading, setIsLoaading] = React.useState(false)

  const getPostData = React.useCallback(async () => {
    setIsLoaading(true)
    const { data } = await axios.get(
      !category || category === 'all' ? 'posts' : `posts/${category}`
    )
    setPostData(data)
    setIsLoaading(false)
  }, [category])

  React.useEffect(() => {
    getPostData()
  }, [getPostData])

  return (
    <View as={SafeAreaView} style={styles.container}>
      <StatusBar
        barStyle={theme === 'light' ? 'dark-content' : 'light-content'}
        backgroundColor={colors.background}
      />
      {postData ? (
        <FlatList
          data={postData}
          extraData={isLoading}
          refreshing={isLoading}
          onRefresh={() => getPostData()}
          keyExtractor={item => item.id}
          ListHeaderComponent={
            <CategoryPicker selectedCategory={category} onClick={setCategory} addAll />
          }
          ListHeaderComponentStyle={[styles.categoryPicker, { backgroundColor: colors.bgColor }]}
          ListEmptyComponent={
            <Text style={[styles.empty, { color: colors.text }]}>Ups! Not found any post!</Text>
          }
          renderItem={({ item, index }) => (
            <Post
              index={index}
              postId={item.id}
              userId={authState.userInfo.id}
              score={item.score}
              type={item.type}
              title={item.title}
              author={item.author}
              category={item.category}
              text={item.text}
              comments={item.comments}
              created={item.created}
              url={item.url}
              votes={item.votes}
              views={item.views}
              setIsLoaading={setIsLoaading}
              setData={setPostData}
              deleteButton={false}
            />
          )}
        />
      ) : (
        <>
          <CategoryLoader />
          {[1, 2, 3, 4, 5].map(i => (
            <PostLoader key={i} />
          ))}
        </>
      )}
    </View>
  )
}
Example #17
Source File: User.js    From reddit-clone with MIT License 5 votes vote down vote up
HeaderComponent = ({ username, postCount }) => {
  const { signOut, authState } = React.useContext(AuthContext)
  const { theme, changeTheme } = React.useContext(ThemeContext)
  const { colors } = useTheme()
  const navigation = useNavigation()

  return (
    <View style={[styles.userInfo, { backgroundColor: colors.bgColor }]}>
      <View style={styles.infoBox}>
        <Text style={[styles.label, { color: colors.text }]}>Username</Text>
        <Text style={{ color: colors.text }}>{username ?? authState.userInfo.username}</Text>
      </View>
      <View style={styles.infoBox}>
        <Text style={[styles.label, { color: colors.text }]}>Post Count</Text>
        <Text style={{ color: colors.text }}>{postCount}</Text>
      </View>
      {username === authState.userInfo.username && (
        <>
          <View style={[styles.line, { borderColor: colors.border }]} />
          <TouchableOpacity
            onPress={() => changeTheme(theme === 'light' ? 'dark' : 'light')}
            style={styles.infoBox}
          >
            {theme === 'light' ? <Moon color={colors.icon} /> : <Sun color={colors.icon} />}
            <Text style={{ color: colors.text }}>
              {theme === 'light' ? 'Dark Mode' : 'Light Mode'}
            </Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={styles.infoBox}
            onPress={() => {
              signOut()
              navigation.navigate('Home')
            }}
          >
            <LogOut color={colors.red} />
            <Text style={{ color: colors.red }}>Logout</Text>
          </TouchableOpacity>
        </>
      )}
    </View>
  )
}
Example #18
Source File: SplashScreen.js    From ReactNavigationAuthenticationFlowsWithHooks with MIT License 5 votes vote down vote up
export function SplashScreen() {
  const {colors} = useTheme();
  return <View style={[styles.container, {backgroundColor: colors.primary}]} />;
}
Example #19
Source File: IconButton.js    From ReactNavigationAuthenticationFlowsWithHooks with MIT License 5 votes vote down vote up
export function IconButton({name, style, onPress}) {
  const {colors} = useTheme();
  return (
    <TouchableOpacity style={[styles.container, style]} onPress={onPress}>
      <Icon name={name} color={colors.primary} />
    </TouchableOpacity>
  );
}
Example #20
Source File: Heading.js    From ReactNavigationAuthenticationFlowsWithHooks with MIT License 5 votes vote down vote up
export function Heading({children, style, ...props}) {
  const {colors} = useTheme();
  return (
    <Text {...props} style={[styles.text, style, {color: colors.text}]}>
      {children}
    </Text>
  );
}
Example #21
Source File: LinesMap.js    From timetable with MIT License 5 votes vote down vote up
LinesMap = ({ route }) => {
  const { i18n } = useTranslation()
  const navigation = useNavigation()
  const { dark } = useTheme()

  const { busNumber, forward } = route.params

  /**
   * 'markerData' contains bus stations coords, Lat-Longitude!
   * 'polylineData' contains entire bus route coords,
   * which is used to display yellow polyline on the map.
   **/
  const [db, setDb] = useState({
    markerData: [],
    polylineData: []
  })

  /**
   * Request for fetching bus number route coords!
   * Based on direction that is set in the Lines Screen, whether it's forward or backward,
   * forward variable is a boolean!
   * API request sample.
   * https://xxxxxxx:xxxx/xxxxxxxxx/?route=${busNumber}&forward=${forward}
   **/

  const endPoint =
    i18n.language == 'en'
      ? `${process.env.API_LINESMAP_EN + busNumber + '&forward=' + forward}`
      : `${process.env.API_LINESMAP_GE + busNumber + '&forward=' + forward}`

  useEffect(() => {
    const unsubscribe = navigation.addListener('focus', () => {
      const controller = new AbortController()
      const signal = controller.signal

      fetch(endPoint, { signal })
        .then(res => res.json())
        .then(data => {
          setDb({
            markerData: data.Stops,
            polylineData: data.Stops.map(point => {
              return { latitude: point.Lat, longitude: point.Lon }
            })
          })
        })
        .catch(err => console.log(err))

      // Clean up
      return () => controller.abort()
    })

    // Clean up
    return unsubscribe
  }, [navigation])

  // Opens Bus station timetable screen
  const openTimetable = (stopId, name) => {
    navigation.navigate('Timetable', {
      stationTimetableId: stopId,
      metadata: name
    })
  }

  return (
    <Map
      markerSource={db.markerData}
      polylineSource={db.polylineData}
      onPressHandler={openTimetable}
      isDark={dark}
    />
  )
}
Example #22
Source File: Feedback.js    From timetable with MIT License 5 votes vote down vote up
Feedback = () => {
  const navigation = useNavigation()
  const { t } = useTranslation()
  const { theme } = useTheme()

  const sendEmailHandler = ({ name, email, message }) => {
    const data = JSON.stringify({ name, email, message }).replace(/[{}'']/g, '')

    fetch('https://api.sendgrid.com/v3/mail/send', {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        Authorization: 'Bearer ' + process.env.API_SEND_GRID_KEY
      },
      body: JSON.stringify({
        personalizations: [
          {
            to: [
              {
                email: process.env.SEND_GRID_EMAIL_TO
              }
            ],
            subject: 'Bus Timetable Feedback'
          }
        ],
        from: {
          email: process.env.SEND_GRID_EMAIL_FROM
        },
        content: [
          {
            type: 'text/plain',
            value: data
          }
        ]
      })
    })
      .then(() => {
        Alert.alert('', t('feedback.onSuccessfulSubmit'), [
          {
            text: t('feedback.cancel'),
            onPress: () => navigation.navigate('About')
          }
        ])
      })
      .catch(() => {
        Alert.alert(t('feedback.error'), t('feedback.onSubmitError'), [
          { text: t('feedback.cancel') }
        ])
      })
  }

  return (
    <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
      <View style={styles.container}>
        <Text style={[styles.info, { color: theme.text }]}>
          {t('feedback.info')}
        </Text>
        <ScrollView style={styles.form}>
          <Form
            onSubmitHandler={sendEmailHandler}
            namePlaceholder={t('feedback.namePlaceholder')}
            emailPlaceholder={t('feedback.emailPlaceholder')}
            messagePlaceholder={t('feedback.messagePlaceholder')}
            submitTitle={t('feedback.submitTitle')}
            schemaRequiredName={t('feedback.schemaRequiredName')}
            schemaRequiredEmail={t('feedback.schemaRequiredEmail')}
            schemaRequiredMessage={t('feedback.schemaRequiredMessage')}
            buttonColor={theme.buttonColor}
            buttonText={theme.buttonText}
          />
        </ScrollView>
      </View>
    </TouchableWithoutFeedback>
  )
}
Example #23
Source File: Detail.js    From curso-react-native with MIT License 4 votes vote down vote up
Detail = ({route, navigation}) => {
  const [poke, setPoke] = useState({});
  const {colors} = useTheme();
  const {pokemon, previous} = route.params;

  const colorByType = colors[poke.types?.[0].type.name];

  const recursiveEvolutionChain = (chain) => {
    const isCurrent = chain?.species.name === pokemon.name;
    return (
      <View style={styles.row}>
        <TouchableOpacity
          onPress={() => {
            if (previous === chain?.species.name) {
              navigation.goBack();
            } else if (!isCurrent) {
              navigation.push('Pokemon', {
                pokemon: chain.species,
                previous: pokemon.name,
              });
            }
          }}>
          <Text
            style={[
              styles.pokemonName,
              {
                marginHorizontal: 16,
                color: isCurrent && colors.primary,
              },
            ]}>
            {chain?.species.name}
          </Text>
        </TouchableOpacity>
        {chain?.evolves_to.length > 0 && (
          <Text style={styles.pokemonName}>></Text>
        )}
        <View>
          {chain?.evolves_to?.map((poke) => recursiveEvolutionChain(poke))}
        </View>
      </View>
    );
  };

  useEffect(() => {
    Promise.all([
      P.getPokemonByName(pokemon.name),
      P.getPokemonSpeciesByName(pokemon.name),
    ]).then(([pokemonInfo, speciesInfo]) => {
      const {types, id} = pokemonInfo;
      const {evolution_chain, flavor_text_entries} = speciesInfo;
      const description = flavor_text_entries
        .find((flavor) => flavor.language.name === 'es')
        ?.flavor_text.replace(/\n/g, ' ');
      P.resource(evolution_chain.url).then((evolutionChain) => {
        setPoke(
          Pokemon({
            ...pokemon,
            id,
            description,
            chain: evolutionChain.chain,
            types: types.sort((a, b) =>
              a.slot > b.slot ? 1 : a.slot < b.slot ? -1 : 0,
            ),
          }),
        );
      });
    });
  }, []);

  useEffect(() => {
    navigation.setOptions({
      headerStyle: {
        backgroundColor: colorByType,
      },
    });
  }, [colorByType]);

  return (
    <View style={{padding: 16}}>
      <StatusBar backgroundColor={colorByType} barStyle="light-content" />
      <View style={styles.row}>
        <Image style={{width: 180, height: 180}} source={{uri: poke.image}} />
        <View style={{paddingTop: 24}}>
          <Text style={styles.pokemonName}>
            #{poke.id} - {poke.name}
          </Text>
          <View style={styles.typesContainer}>
            {poke.types?.map((type, index) => (
              <Text
                key={index}
                style={[
                  styles.type,
                  {backgroundColor: colors[type.type.name]},
                ]}>
                {type.type.name}
              </Text>
            ))}
          </View>
        </View>
      </View>
      <Text style={{fontSize: 16}}>{poke.description}</Text>
      <Text style={{fontSize: 24, marginTop: 16}}>Cadena Evolutiva</Text>
      <ScrollView horizontal style={styles.typesContainer}>
        {recursiveEvolutionChain(poke.chain)}
      </ScrollView>
    </View>
  );
}
Example #24
Source File: Detail.js    From curso-react-native with MIT License 4 votes vote down vote up
export default function Detail({route, navigation}) {
  const [pokemon, setPokemon] = useState(route.params.pokemon);
  const [isLoading, setLoading] = useState(true);
  const {colors} = useTheme();

  const colorByType = colors[pokemon.types?.[0].type.name];

  useEffect(() => {
    Promise.all([
      P.getPokemonByName(pokemon.name),
      P.getPokemonSpeciesByName(pokemon.name).then((res) =>
        P.resource(res.evolution_chain.url).then((chain) => ({
          description: res.flavor_text_entries
            ?.find((flavor) => flavor.language.name === 'es')
            ?.flavor_text?.replace(/\n/g, ' '),
          chain: chain.chain,
        })),
      ),
    ])
      .then(([poke, evolutionChain]) => {
        setPokemon(
          Pokemon({
            ...pokemon,
            ...evolutionChain,
            ...poke,
          }),
        );
        setLoading(false);
      })
      .catch(() => {
        navigation.goBack();
      });

    // o
    // fetch(pokemon.url)
    //   .then(res => res.json())
    //   .then(response => setPokemon({...pokemon, ...response}))
  }, []);

  useEffect(() => {
    navigation.setOptions({
      headerStyle: {
        backgroundColor: colorByType,
      },
    });
  }, [colorByType]);

  const recursiveEvolutionChain = (chain) => {
    const isCurrent = chain?.species.name === pokemon.name;
    return (
      <View style={styles.row}>
        <TouchableOpacity
          onPress={() => {
            if (route.params.previous === chain?.species.name) {
              navigation.goBack();
            } else if (!isCurrent) {
              navigation.push('Pokémon', {
                pokemon: chain.species,
                previous: pokemon.name,
              });
            }
          }}>
          <Text
            style={[
              styles.name,
              {
                marginHorizontal: 16,
                color: isCurrent && colors.primary,
              },
            ]}>
            {chain?.species.name}
          </Text>
        </TouchableOpacity>
        {chain?.evolves_to.length > 0 && <Text style={styles.name}>></Text>}
        <View>
          {chain?.evolves_to?.map((poke) => recursiveEvolutionChain(poke))}
        </View>
      </View>
    );
  };

  return isLoading ? (
    <ActivityIndicator
      size={54}
      color={colors.primary}
      style={{marginTop: 36}}
    />
  ) : (
    <ScrollView contentContainerStyle={{padding: 16}}>
      <StatusBar backgroundColor={colorByType} barStyle="light-content" />
      <View style={[styles.row, {justifyContent: 'flex-start'}]}>
        <Image
          style={styles.image}
          resizeMode="contain"
          source={{
            uri: pokemon.image,
          }}
        />
        <View>
          <Text style={styles.name}>
            #{pokemon.id} - {pokemon.name}
          </Text>
          <View
            style={[
              styles.row,
              {marginRight: 8, justifyContent: 'flex-start'},
            ]}>
            {pokemon.types?.map((t) => (
              <View
                style={[
                  styles.type,
                  {
                    backgroundColor: colors[t.type.name],
                  },
                ]}>
                <Text style={{color: 'white'}}>{t.type.name}</Text>
              </View>
            ))}
          </View>
        </View>
      </View>

      <Text style={styles.description}>{pokemon.description}</Text>
      {pokemon.chain?.evolves_to.length > 0 && (
        <>
          <Text style={styles.name}>Cadena evolutiva:</Text>
          <ScrollView horizontal showsHorizontalScrollIndicator={false}>
            {recursiveEvolutionChain(pokemon.chain)}
          </ScrollView>
        </>
      )}
    </ScrollView>
  );
}
Example #25
Source File: Post.js    From reddit-clone with MIT License 4 votes vote down vote up
Post = ({
  index,
  postId,
  userId,
  score,
  type,
  title,
  author,
  category,
  text,
  comments,
  created,
  url,
  votes,
  views,
  setIsLoaading,
  setData,
  postType,
  deleteButton,
  deletePost
}) => {
  const { colors } = useTheme()
  const navigation = useNavigation()
  const { authState } = React.useContext(AuthContext)
  const route = useRoute()

  const isUpVoted = () => {
    return votes.find(v => v.user === userId)?.vote === 1
  }

  const isDownVoted = () => {
    return votes.find(v => v.user === userId)?.vote === -1
  }

  const upVote = async () => {
    setIsLoaading(true)
    const { data } = await axios.get(`post/${postId}/upvote`)
    if (postType !== 'item') {
      setData(prevData => {
        prevData[index] = data
        return prevData
      })
    } else {
      setData(data)
    }
    setIsLoaading(false)
  }

  const downVote = async () => {
    setIsLoaading(true)
    const { data } = await axios.get(`post/${postId}/downvote`)
    if (postType !== 'item') {
      setData(prevData => {
        prevData[index] = data
        return prevData
      })
    } else {
      setData(data)
    }
    setIsLoaading(false)
  }

  const unVote = async () => {
    setIsLoaading(true)
    const { data } = await axios.get(`post/${postId}/unvote`)
    if (postType !== 'item') {
      setData(prevData => {
        prevData[index] = data
        return prevData
      })
    } else {
      setData(data)
    }
    setIsLoaading(false)
  }

  return (
    <View
      as={SafeAreaView}
      style={[
        styles.container,
        { backgroundColor: colors.bgColor, borderColor: colors.postBorder }
      ]}
    >
      <View style={styles.headerContainer}>
        <View style={styles.headerLeft}>
          <Text style={[styles.regularFont, { color: colors.text }]}>{category} </Text>
          <Text
            style={[styles.italicFont, { color: colors.blue }]}
            onPress={() => navigation.navigate('User', { username: author.username })}
          >
            @{author?.username} ·{' '}
          </Text>
          <Text style={[styles.dateText, { color: colors.text }]}>{moment(created).fromNow()}</Text>
        </View>
        <View style={styles.headerRight}>
          {deleteButton && author?.id === authState.userInfo.id && (
            <TouchableOpacity style={styles.trash} activeOpacity={0.5} onPress={deletePost}>
              <Trash color={colors.red} width={20} height={20} />
            </TouchableOpacity>
          )}
        </View>
      </View>
      <Text
        style={[styles.title, { color: colors.text }]}
        onPress={() => navigation.navigate('PostDetail', { postId, category, comments })}
      >
        {title}
      </Text>
      <Text
        numberOfLines={route.name === 'PostDetail' ? 10000 : 10}
        style={[
          styles.regularFont,
          { color: colors.text },
          type === 'link' && route.name === 'PostDetail' && styles.link
        ]}
        onPress={() =>
          route.name === 'PostDetail' && type === 'link'
            ? Linking.openURL(url)
            : navigation.navigate('PostDetail', { postId, category, comments })
        }
      >
        {type === 'link' ? url : text}
      </Text>
      <View style={styles.bottomContainer}>
        <View style={styles.centerAlign}>
          <TouchableOpacity onPress={() => (isUpVoted() ? unVote() : upVote())}>
            <ArrowUp
              width={22}
              height={22}
              strokeWidth={4}
              color={isUpVoted() ? colors.green : colors.icon}
            />
          </TouchableOpacity>
          <Text style={[styles.score, { color: colors.text }]}>{score}</Text>
          <TouchableOpacity onPress={() => (isDownVoted() ? unVote() : downVote())}>
            <ArrowDown
              width={22}
              height={22}
              strokeWidth={4}
              color={isDownVoted() ? colors.red : colors.icon}
            />
          </TouchableOpacity>
        </View>
        <TouchableOpacity
          style={styles.centerAlign}
          activeOpacity={0.7}
          onPress={() => navigation.navigate('PostDetail', { postId, category, comments })}
        >
          <MessageSquare
            color={colors.icon}
            style={styles.commentIcon}
            width={20}
            height={20}
            strokeWidth={3}
          />
          <Text style={[styles.commentText, { color: colors.text }]}>{comments?.length}</Text>
        </TouchableOpacity>
        <Text style={[styles.italicFont, { color: colors.text }]}>{views} views</Text>
      </View>
    </View>
  )
}
Example #26
Source File: Timetable.js    From timetable with MIT License 4 votes vote down vote up
Timetable = ({ route }) => {
  const { t, i18n } = useTranslation()
  const { theme } = useTheme()
  // netInfo helps to check network connection status. Timeout 15s
  const netInfo = useNetInfo({ reachabilityRequestTimeout: 15 * 1000 })

  // station ID which you get from Stations screen
  const { stationTimetableId, metadata } = route.params
  const metainfo = { station: stationTimetableId, info: metadata }

  /**
   * Arrival bus list!
   * Used to get latest info.
   * API request sample.
   * https://xxxxxxx:xxxx/xxxxxxxxxxxx/?station=${stationTimetableId}
   **/

  const endPoint =
    i18n.language == 'en'
      ? `${process.env.API_TIMETABLE_EN + stationTimetableId}`
      : `${process.env.API_TIMETABLE_GE + stationTimetableId}`

  // Local Time string object
  const [localTime, setLocalTime] = useState('')

  // Stream of data
  const fetcher = (...args) => fetch(...args).then(res => res.json())

  const { data, error } = useSWR(endPoint, fetcher, {
    refreshInterval: 1000 * 10
  })

  // Bouncing animation
  const focus = new Animated.Value(0)

  Animated.loop(
    Animated.timing(focus, {
      toValue: 10,
      duration: 4000,
      easing: Easing.bounce,
      useNativeDriver: true
    })
  ).start()

  useEffect(() => {
    // Server related warning
    if (error) {
      Alert.alert(t('timetable.error'), t('timetable.server_err'), [
        { text: t('timetable.cancel') }
      ])
    }

    const interval = setInterval(() => {
      setLocalTime(
        new Date().toLocaleTimeString('en-US', { hour12: false }, 'ka-KA')
      )
    }, 1000)

    // clean up
    return () => {
      clearInterval(interval), focus.stopAnimation()
    }
  }, [])

  /**
   * Saves station ID and metainfo to local storage!
   * Checks if ID exist in storage and displays pop up warning.
   **/

  const saveFavoriteHandler = async () => {
    try {
      const result = await AsyncStorage.getItem('TestFavorite')

      if (result == null) {
        const createArray = [metainfo]

        AsyncStorage.setItem('TestFavorite', JSON.stringify(createArray))
      } else if (result !== null) {
        const array = await JSON.parse(result)
        let onAlert = false

        array.forEach(value => {
          if (value.station == stationTimetableId) {
            onAlert = true
            Alert.alert('', t('timetable.favorite'), [
              { text: t('timetable.cancel') }
            ])
          }
        })

        if (onAlert == false) {
          array.push(metainfo)
          AsyncStorage.setItem('TestFavorite', JSON.stringify(array))
        }
      }
    } catch (err) {
      Alert.alert('', err, [{ text: t('timetable.cancel') }])
    }
  }

  /**
   * Displays Local Time!
   * Shows night time if it's between 12:00AM - 6:00AM.
   * Shows delay if timetable is empty between 7:00AM - 11:00PM,
   * also for displaying delay we check network status.
   **/

  const DisplayTime = () => {
    if (parseInt(localTime) >= 7 && parseInt(localTime) <= 22) {
      return (
        <View style={styles.localTime}>
          <Text style={{ color: theme.text }}>{localTime} (GMT+4)</Text>
          <Text style={{ color: theme.text }}>{t('timetable.localTime')}</Text>
          <Text style={{ color: theme.text }}>
            {t('timetable.localTimeDelay')}
          </Text>
        </View>
      )
    } else if (
      (parseInt(localTime) >= 0 && parseInt(localTime) <= 6) ||
      parseInt(localTime) == 23
    ) {
      return (
        <View style={styles.localTime}>
          <Text style={{ color: theme.text }}>{localTime} (GMT+4)</Text>
          <Text style={{ color: theme.text }}>{t('timetable.localTime')}</Text>
          <Text style={{ color: theme.text }}>
            {t('timetable.localTimeNight')}
          </Text>
        </View>
      )
    }
  }

  // FlatList Item
  const Item = ({ title, time, bus, nowText, minText }) => {
    // Apply animation if time is below two minutes and display 'Now' instead of time.
    // Time is number it can be between 0-100: represents minutes.

    const willBeIn = () => {
      if (time <= 2 || 0) {
        return (
          <Animated.View style={{ opacity: focus }}>
            <Text style={{ color: theme.text }}>{nowText}</Text>
          </Animated.View>
        )
      } else {
        return (
          <Text style={{ color: theme.text }}>
            {time} {minText}
          </Text>
        )
      }
    }

    return (
      <View style={[styles.listItemView, { borderColor: theme.border }]}>
        <Text style={{ color: theme.text }}>{bus}</Text>
        <Text style={[styles.title, { color: theme.text }]}>{title}</Text>
        {willBeIn()}
      </View>
    )
  }

  return (
    <View style={styles.container}>
      <Text style={[styles.info, { color: theme.text }]}>
        {t('timetable.station')} {stationTimetableId}
      </Text>

      <AntDesign
        name='staro'
        color='white'
        size={30}
        style={styles.favoriteIcon}
        onPress={saveFavoriteHandler}
      />

      <View style={styles.listHeader}>
        <Text style={{ color: theme.text }}>{t('timetable.bus')}</Text>
        <Text style={{ color: theme.text }}>{t('timetable.direction')}</Text>
        <Text style={{ color: theme.text }}>{t('timetable.time')}</Text>
      </View>

      {!data ? null : (
        <FlatList
          data={data.ArrivalTime}
          renderItem={({ item }) => (
            <Item
              title={item.DestinationStopName}
              time={item.ArrivalTime}
              bus={item.RouteNumber}
              minText={t('timetable.minText')}
              nowText={t('timetable.nowText')}
            />
          )}
          keyExtractor={item => item.RouteNumber}
        />
      )}

      {!data
        ? null
        : netInfo.isConnected && data.ArrivalTime.length === 0 && DisplayTime()}
    </View>
  )
}
Example #27
Source File: CreatePost.js    From reddit-clone with MIT License 4 votes vote down vote up
CreatePost = () => {
  const { colors } = useTheme()
  const [isLoading, setIsLoading] = React.useState(false)
  const [message, setMessage] = React.useState(null)
  const fadeAnim = React.useRef(new Animated.Value(0)).current

  const fadeIn = () => {
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 2000,
      useNativeDriver: true
    }).start()

    setTimeout(() => {
      setMessage(null)
    }, 6000)
  }

  return (
    <ScrollView as={SafeAreaView} style={[styles.container, { backgroundColor: colors.bgColor }]}>
      <Formik
        initialValues={{
          type: 'text',
          category: '',
          title: '',
          url: '',
          text: ''
        }}
        onSubmit={async (values, { setStatus, resetForm }) => {
          setIsLoading(true)
          try {
            await axios.post('posts', values)
            resetForm({ ...values, type: 'text' })
            setMessage('Successfully Created!')
            fadeIn()
          } catch (error) {
            setStatus(error.response.data.message)
          }
          setIsLoading(false)
        }}
        validationSchema={Yup.object({
          type: Yup.mixed().oneOf(['text', 'link']),
          category: Yup.string().required('Required'),
          title: Yup.string()
            .required('Required')
            .max(100, 'Must be at most 100 characters long'),
          text: Yup.string().when('type', {
            is: 'text',
            then: Yup.string()
              .required('Required')
              .min(4, 'Must be at least 4 characters long')
          }),
          url: Yup.string().when('type', {
            is: 'link',
            then: Yup.string()
              .required('Required')
              .url('Invalid Url')
          })
        })}
      >
        {({
          handleChange,
          handleBlur,
          handleSubmit,
          touched,
          errors,
          status,
          values,
          setFieldValue
        }) => (
          <View>
            {message && (
              <Animated.View
                style={{
                  opacity: fadeAnim
                }}
              >
                {!!message && <Text style={styles.message}>{message}</Text>}
              </Animated.View>
            )}
            {!!status && <Text style={styles.status}>{status}</Text>}
            <View style={styles.flexRow}>
              <Text style={[styles.formLabel, { color: colors.text }]}>Type</Text>
              {touched.type && errors.type && (
                <Text style={styles.errorMessage}>{errors.type}</Text>
              )}
            </View>
            <TypeSwichContainer>
              <TypeSwichButton selected={values.type} onClick={setFieldValue} type="text" />
              <TypeSwichButton selected={values.type} onClick={setFieldValue} type="link" />
            </TypeSwichContainer>
            <View style={styles.flexRow}>
              <Text style={[styles.formLabel, { color: colors.text }]}>Category</Text>
              {touched.category && errors.category && (
                <Text style={styles.errorMessage}>{errors.category}</Text>
              )}
            </View>
            <CategoryPicker selectedCategory={values.category} setFieldValue={setFieldValue} />

            <View style={styles.flexRow}>
              <Text style={[styles.formLabel, { color: colors.text }]}>Title</Text>
              {touched.title && errors.title && (
                <Text style={styles.errorMessage}>{errors.title}</Text>
              )}
            </View>
            <TextInput
              style={[
                styles.textInput,
                { borderColor: colors.border, color: colors.text, height: 40 },
                touched.title && errors.title && { borderColor: colors.red }
              ]}
              value={values.title}
              onChangeText={handleChange('title')}
              onBlur={handleBlur('title')}
            />

            {values.type === 'link' ? (
              <>
                <View style={styles.flexRow}>
                  <Text style={[styles.formLabel, { color: colors.text }]}>Url</Text>
                  {touched.url && errors.url && (
                    <Text style={styles.errorMessage}>{errors.url}</Text>
                  )}
                </View>
                <TextInput
                  style={[
                    styles.textInput,
                    { borderColor: colors.border, color: colors.text },
                    touched.url && errors.url && { borderColor: colors.red }
                  ]}
                  multiline
                  value={values.url}
                  onChangeText={handleChange('url')}
                  onBlur={handleBlur('url')}
                />
              </>
            ) : (
              <>
                <View style={styles.flexRow}>
                  <Text style={[styles.formLabel, { color: colors.text }]}>Text</Text>
                  {touched.text && errors.text && (
                    <Text style={styles.errorMessage}>{errors.text}</Text>
                  )}
                </View>
                <TextInput
                  style={[
                    styles.textInput,
                    { borderColor: colors.border, color: colors.text },
                    touched.text && errors.text && { borderColor: colors.red }
                  ]}
                  multiline
                  value={values.text}
                  onChangeText={handleChange('text')}
                  onBlur={handleBlur('text')}
                />
              </>
            )}
            <View style={styles.buttonContainer}>
              <TouchableOpacity
                style={[styles.submitButton, { backgroundColor: colors.blue }]}
                onPress={handleSubmit}
              >
                {isLoading ? (
                  <ActivityIndicator size="small" color="white" />
                ) : (
                  <Plus color="white" />
                )}
                <Text style={styles.submitButtonText}>Create Post</Text>
              </TouchableOpacity>
            </View>
          </View>
        )}
      </Formik>
    </ScrollView>
  )
}
Example #28
Source File: SignIn.js    From reddit-clone with MIT License 4 votes vote down vote up
SignIn = ({ navigation }) => {
  const { setStorage } = React.useContext(AuthContext)
  const { colors } = useTheme()
  const [isLoading, setIsLoading] = React.useState(false)

  return (
    <KeyboardAvoidingView behavior="padding" style={{ flex: 1 }}>
      <Formik
        initialValues={{ username: '', password: '' }}
        onSubmit={async (values, { setStatus, resetForm }) => {
          setIsLoading(true)
          try {
            const { data } = await axios.post('authenticate', values)
            const { token, expiresAt, userInfo } = data
            setStorage(token, expiresAt, userInfo)
            navigation.navigate('Home')
            resetForm({})
          } catch (error) {
            setStatus(error.response.data.message)
          }
          setIsLoading(false)
        }}
        validationSchema={Yup.object({
          username: Yup.string()
            .required('Required')
            .max(32, 'Must be at most 32 characters long')
            .matches(/^[a-zA-Z0-9_-]+$/, 'Contains invalid characters'),
          password: Yup.string()
            .required('Required')
            .min(6, 'Must be at least 6 characters long')
            .max(50, 'Must be at most 50 characters long')
        })}
      >
        {({
          handleChange,
          handleBlur,
          handleSubmit,
          touched,
          errors,
          status,
          values,
          setTouched
        }) => (
          <TouchableWithoutFeedback onPress={() => navigation.goBack()}>
            <View as={SafeAreaView} style={styles.container}>
              <View
                style={[styles.modal, { backgroundColor: colors.background }]}
                onStartShouldSetResponder={() => true}
                onResponderRelease={() => setTouched(errors)}
              >
                {!!status && <Text style={styles.status}>{status}</Text>}
                {touched.username && errors.username && (
                  <Text style={styles.errorMessage}>{errors.username}</Text>
                )}
                <TextInput
                  style={[
                    styles.textInput,
                    touched.username && errors.username && { borderColor: colors.red },
                    { color: colors.text }
                  ]}
                  placeholder="Username"
                  placeholderTextColor={colors.text}
                  value={values.username}
                  autoCorrect={false}
                  onChangeText={handleChange('username')}
                  onBlur={handleBlur('username')}
                />
                {touched.password && errors.password && (
                  <Text style={styles.errorMessage}>{errors.password}</Text>
                )}
                <TextInput
                  style={[
                    styles.textInput,
                    touched.password && errors.password && { borderColor: colors.red },
                    { color: colors.text }
                  ]}
                  placeholder="Password"
                  placeholderTextColor={colors.text}
                  value={values.password}
                  onChangeText={handleChange('password')}
                  onBlur={handleBlur('password')}
                  secureTextEntry
                />
                <View style={styles.buttonContainer}>
                  <Button onPress={handleSubmit} title="Login" bgColor={colors.signInButton}>
                    {isLoading && <ActivityIndicator size="small" color="white" />}
                  </Button>
                </View>
              </View>
            </View>
          </TouchableWithoutFeedback>
        )}
      </Formik>
    </KeyboardAvoidingView>
  )
}
Example #29
Source File: Lines.js    From timetable with MIT License 4 votes vote down vote up
Lines = () => {
  const { i18n, t } = useTranslation()
  const navigation = useNavigation()
  const { theme } = useTheme()

  const [busArray, setBusArray] = useState([])

  useEffect(() => {
    const unsubscribe = navigation.addListener('focus', () => {
      setBusArray(i18n.language == 'en' ? EnBus.Bus : GeBus.Bus)
    })

    // Cleanup
    return unsubscribe
  }, [navigation])

  // FlatList Item
  const Item = ({ busNumber, stopA, stopB }) => {
    const [boolean, setBoolean] = useState(true)

    // Change direction
    const changeDirectionHandler = () => setBoolean(!boolean)

    // Bus Line start-end direction
    const direction = boolean ? (
      <TouchableOpacity
        onPress={() =>
          navigation.navigate('LinesMap', { busNumber, forward: 0 })
        }
      >
        <View style={styles.listItem}>
          <Text style={{ color: theme.text }}>{stopA}</Text>
          <Entypo name='arrow-long-right' color='#1f5c87' size={25} />
          <Text style={{ color: theme.text }}>{stopB}</Text>
        </View>
      </TouchableOpacity>
    ) : (
      <TouchableOpacity
        onPress={() =>
          navigation.navigate('LinesMap', { busNumber, forward: 1 })
        }
      >
        <View style={styles.listItem}>
          <Text style={{ color: theme.text }}>{stopB}</Text>
          <Entypo name='arrow-long-right' color='#1f5c87' size={25} />
          <Text style={{ color: theme.text }}>{stopA}</Text>
        </View>
      </TouchableOpacity>
    )

    return (
      <View>
        <View style={[styles.separator, { borderBottomColor: theme.border }]} />

        <View
          style={[
            styles.wrapBusIcon,
            {
              backgroundColor: theme.backgroundColor,
              borderColor: theme.border
            }
          ]}
        >
          <MaterialCommunityIcons
            name='bus'
            color='#1f5c87'
            size={15}
            style={styles.busIcon}
          />

          <Text style={[styles.busNumber, { color: theme.text }]}>
            {busNumber}
          </Text>
        </View>

        <Text style={[styles.from, { color: theme.text }]}>
          {t('lines.from')}
        </Text>

        {direction}

        <View style={styles.changeDirection}>
          <Button
            onPress={changeDirectionHandler}
            text={t('lines.change')}
            buttonColor={theme.buttonColor}
            textColor={theme.buttonText}
            margin={0}
            paddingVertical={4}
            fontSize={12}
          />
        </View>
      </View>
    )
  }

  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        data={busArray}
        renderItem={({ item }) => (
          <Item
            busNumber={item.RouteNumber}
            stopA={item.StopA}
            stopB={item.StopB}
          />
        )}
        keyExtractor={item => item.RouteNumber}
      />
    </SafeAreaView>
  )
}