react-native-safe-area-context#SafeAreaView JavaScript Examples

The following examples show how to use react-native-safe-area-context#SafeAreaView. 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: index.js    From musicont with MIT License 6 votes vote down vote up
Index = ({ songs }) => {
	const [assets] = useAssets([require('../../assets/icons/hamburger.png'), require('../../assets/icons/search.png')]);
	const [drawer, setDrawer] = useState(false);

	return (
		<Drawer active={drawer} current="recent" onItemPressed={() => setDrawer(false)}>
			<SafeAreaView style={styles.container}>
				<Header
					options={{
						left: {
							children: drawer ? <Icon name="x" color="#C4C4C4" /> : <Image source={require('../../assets/icons/hamburger.png')} resizeMode="contain" />,
							onPress: () => setDrawer(!drawer),
						},
						middle: {
							show: true,
							text: 'Recently Played',
						},
						right: {
							show: false,
						},
					}}
				/>
				<View style={styles.sections}>
					{songs && songs.length > 0 ? (
						<Section.MusicList audios={songs} indicator={false} useIndex={true} />
					) : (
						<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
							<Text style={{ fontSize: 24, fontWeight: 'bold', color: 'rgba(0, 0, 0, .3)' }}>No recent yet!</Text>
						</View>
					)}
				</View>
			</SafeAreaView>
		</Drawer>
	);
}
Example #2
Source File: HomeScreen.js    From WhatsApp-Clone with MIT License 6 votes vote down vote up
HomeScreen = ({children, style, navigation, ...rest}) => {
  useEffect(() => {
    registerStateChangeListener();
    sendPageLoadStatus()

    return () => {
      // Clean up the subscription
      unRgisterStateChangeListener()
    };
  }, []);

  function registerStateChangeListener() {
    AppState.addEventListener('change', handleAppStateChange);
  }

  function unRgisterStateChangeListener() {
    AppState.removeEventListener('change', handleAppStateChange);
  } 

  return (
    <SafeAreaView style={DEFAULT_STYLES.container}>
      <View style={DEFAULT_STYLES.container}>
        {/* <Header hasTabs style={styles.headerStyle}> */}
        <HomeHeader navigation={navigation} />
        {/* </Header> */}
        <TabView navigation={navigation} />
      </View>
    </SafeAreaView>
  );
}
Example #3
Source File: index.js    From MediBuddy with MIT License 6 votes vote down vote up
Footer = () => (
  <SafeAreaView>
    <Divider />
    <View style={styles.footer}>
      <View style={{ flex: 1 }}>
        <Button
          style={styles.btn}
          labelStyle={styles.cancel}
          mode="text"
          onPress={() => console.log('Pressed')}>
          Cancel
        </Button>
      </View>
      <View style={{ flex: 1 }}>
        <Button
          style={styles.btn}
          labelStyle={styles.ok}
          mode="text"
          onPress={() => console.log('Pressed')}>
          Reschedule
        </Button>
      </View>
    </View>
  </SafeAreaView>
)
Example #4
Source File: Leaderboard.js    From redis-examples with MIT License 6 votes vote down vote up
render() {
    const {navigate} = this.props.navigation;
    this.height = Math.round(Dimensions.get('screen').height);
    this.width = Math.round(Dimensions.get('screen').width);
    return (
      <SafeAreaView
        style={{
          width: this.width,
          height: this.height,
          flex: 1,
          alignItems: 'center'
        }}>
        <StatusBar
        backgroundColor="#f4511e"/>
        <View
        style={{
          height:this.height,
          width: this.width
        }}>
        <FlatList
          style={{
            flex: 1,
            flexDirection: 'column',
          }}
          renderItem={() => this.renderPlayerItems()}
          data={[{bos: 'boş', key: 'key'}]}
          refreshing={true}></FlatList>
        </View>
      </SafeAreaView>
    );
  }
Example #5
Source File: App.js    From redis-examples with MIT License 6 votes vote down vote up
render(){
  this.height = Math.round(Dimensions.get('screen').height);
  this.width = Math.round(Dimensions.get('screen').width);
  return (
    <SafeAreaView style={{
      width: this.width,
      height: this.height,
      flex: 1,
      alignItems: 'center'}}>
      <StatusBar
      backgroundColor="#f4511e"/>
    </SafeAreaView>
  );
}
Example #6
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 #7
Source File: index.js    From musicont with MIT License 6 votes vote down vote up
Index = ({ songs }) => {
	const [assets] = useAssets([require('../../assets/icons/hamburger.png'), require('../../assets/icons/search.png')]);
	const [drawer, setDrawer] = useState(false);

	return (
		<Drawer active={drawer} current="songs" onItemPressed={() => setDrawer(false)}>
			<SafeAreaView style={styles.container}>
				<Header
					options={{
						left: {
							children: drawer ? <Icon name="x" color="#C4C4C4" /> : <Image source={require('../../assets/icons/hamburger.png')} resizeMode="contain" />,
							onPress: () => setDrawer(!drawer),
						},
						middle: {
							show: true,
							text: 'All Songs',
						},
						right: {
							show: false,
						},
					}}
				/>
				<View style={styles.sections}>
					<Section.MusicList audios={songs} indicator={false} />
				</View>
			</SafeAreaView>
		</Drawer>
	);
}
Example #8
Source File: index.js    From musicont with MIT License 6 votes vote down vote up
Index = () => {
	const [assets] = useAssets([require('../../assets/icons/hamburger.png'), require('../../assets/icons/search.png')]);
	const [drawer, setDrawer] = useState(false);

	return (
		<Drawer active={drawer} current="home" onItemPressed={() => setDrawer(false)}>
			<SafeAreaView style={styles.container}>
				<Header
					options={{
						left: {
							children: drawer ? <Icon name="x" color="#C4C4C4" /> : <Image source={require('../../assets/icons/hamburger.png')} resizeMode="contain" />,
							onPress: () => setDrawer(!drawer),
						},
					}}
				/>
				<View style={styles.sections}>
					<Section.Explore />
					<Section.Recent style={{ marginTop: 30 }} />
					<Section.Playlist style={{ marginTop: 30 }} />
				</View>
				<Footer />
			</SafeAreaView>
		</Drawer>
	);
}
Example #9
Source File: index.js    From musicont with MIT License 6 votes vote down vote up
Index = ({ songs }) => {
	const [assets] = useAssets([require('../../assets/icons/hamburger.png'), require('../../assets/icons/search.png')]);
	const [drawer, setDrawer] = useState(false);

	return (
		<Drawer active={drawer} current="favourite" onItemPressed={() => setDrawer(false)}>
			<SafeAreaView style={styles.container}>
				<Header
					options={{
						left: {
							children: drawer ? <Icon name="x" color="#C4C4C4" /> : <Image source={require('../../assets/icons/hamburger.png')} resizeMode="contain" />,
							onPress: () => setDrawer(!drawer),
						},
						middle: {
							show: true,
							text: 'My Favourites',
						},
						right: {
							show: false,
						},
					}}
				/>
				<View style={styles.sections}>
					{songs && songs.length > 0 ? (
						<Section.MusicList audios={songs} indicator={false} useIndex={true} />
					) : (
						<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
							<Text style={{ fontSize: 24, fontWeight: 'bold', color: 'rgba(0, 0, 0, .3)' }}>No favourite yet!</Text>
						</View>
					)}
				</View>
			</SafeAreaView>
		</Drawer>
	);
}
Example #10
Source File: ProfileScreen.js    From hero with MIT License 6 votes vote down vote up
ProfileScreen = () => {
  return (
    <SafeAreaView style={styles.appContainer}>
      <StatusBar
        translucent
        backgroundColor="transparent"
        barStyle="dark-content"
      />
      <View style={styles.header}>
        <Text style={styles.appTitle}>profile</Text>
      </View>
      <View style={styles.footer}>
        <Text style={styles.p}>Designed by Gino Lee Swanepoel</Text>
        <Text style={styles.p}>in React Native</Text>
      </View>
    </SafeAreaView>
  );
}
Example #11
Source File: Subscribe.js    From actual with MIT License 6 votes vote down vote up
export function Subscribe({ route, navigation, getUserData, createBudget }) {
  let { email, userId, key } = route.params || {};

  let textStyle = [
    styles.text,
    { fontSize: 17, lineHeight: 25, color: 'white' }
  ];

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <KeyboardAvoidingView>
        {/* <StatusBar barStyle="light-content" /> */}
        <Header navigation={navigation} buttons={['back']} />
        <Stack justify="center" style={{ flex: 1, padding: 20 }} spacing={8}>
          <View>
            <Text style={textStyle}>
              You{"'"}re almost there. You need to subscribe to gain access to
              Actual. No charges will be made for 1 month.
            </Text>
          </View>

          <View style={{ alignItems: 'center' }}>
            <Text style={[textStyle, { fontWeight: '700', marginBottom: 5 }]}>
              Start with a 1 month free trial.
            </Text>
            <AccountButton
              navigation={navigation}
              userData={{ id: userId, key, email }}
              darkMode={true}
              useDummyPurchaser={true}
            />
          </View>
        </Stack>
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
}
Example #12
Source File: index.js    From actual with MIT License 5 votes vote down vote up
render() {
    const {
      currentMonth,
      bounds,
      editMode,
      initialized,
      showBudgetDetails
    } = this.state;
    const {
      categories,
      categoryGroups,
      prefs,
      budgetType,
      navigation,
      applyBudgetAction
    } = this.props;
    let numberFormat = prefs.numberFormat || 'comma-dot';

    if (!categoryGroups || !initialized) {
      return (
        <View
          style={{
            flex: 1,
            backgroundColor: 'white',
            alignItems: 'center',
            justifyContent: 'center'
          }}
        >
          <AnimatedLoading width={25} height={25} />
        </View>
      );
    }

    return (
      <SafeAreaView
        edges={['top']}
        style={{ flex: 1, backgroundColor: colors.p5 }}
      >
        <FocusAwareStatusBar barStyle="light-content" />
        <SyncRefresh onSync={this.sync}>
          {({ refreshing, onRefresh }) => (
            <BudgetTable
              // This key forces the whole table rerender when the number
              // format changes
              key={numberFormat}
              categories={categories}
              categoryGroups={categoryGroups}
              type={budgetType}
              month={currentMonth}
              monthBounds={bounds}
              editMode={editMode}
              navigation={navigation}
              refreshControl={
                <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
              }
              onEditMode={flag => this.setState({ editMode: flag })}
              onShowBudgetDetails={this.onShowBudgetDetails}
              onPrevMonth={this.onPrevMonth}
              onNextMonth={this.onNextMonth}
              onAddCategory={this.onAddCategory}
              onReorderCategory={this.onReorderCategory}
              onReorderGroup={this.onReorderGroup}
              onOpenActionSheet={this.onOpenActionSheet}
              onBudgetAction={applyBudgetAction}
            />
          )}
        </SyncRefresh>

        {showBudgetDetails && (
          <BudgetSummary
            month={currentMonth}
            onClose={() => this.setState({ showBudgetDetails: false })}
          />
        )}
      </SafeAreaView>
    );
  }
Example #13
Source File: BudgetList.js    From actual with MIT License 5 votes vote down vote up
render() {
    let {
      navigation,
      files,
      loadAllFiles,
      getUserData,
      showActionSheetWithOptions,
      keyId
    } = this.props;

    return (
      <SafeAreaView edges={['bottom']} style={{ flex: 1 }}>
        <Modal
          title="Select a file"
          backgroundColor="white"
          allowScrolling={false}
          showOverlay={false}
          edges={['top']}
          rightButton={
            <RefreshButton
              onRefresh={() => {
                getUserData();
                loadAllFiles();
              }}
            />
          }
        >
          {/* <StatusBar barStyle="light-content" /> */}
          <FlatList
            data={files}
            ListEmptyComponent={EmptyMessage}
            renderItem={({ item: file }) => (
              <File
                file={file}
                showActionSheetWithOptions={showActionSheetWithOptions}
                onSelect={() => {
                  if (file.state === 'broken') {
                    showBrokenMessage(file, showActionSheetWithOptions, () =>
                      this.onDelete(file)
                    );
                  } else if (file.state === 'remote') {
                    this.props.downloadBudget(file.cloudFileId);
                  } else {
                    this.props.loadBudget(file.id);
                  }
                }}
                onDelete={this.onDelete}
              />
            )}
            keyExtractor={item => item.id}
            style={{ flex: 1 }}
          />
          <View
            style={{
              alignItems: 'center',
              marginHorizontal: 10,
              marginVertical: 15,
              flexDirection: 'row'
            }}
          >
            <Button primary style={{ flex: 1 }} onPress={() => this.onCreate()}>
              New file
            </Button>
          </View>
        </Modal>
        <UserButton
          navigation={navigation}
          keyId={keyId}
          onLogOut={() => {
            iap.resetUser();
            this.props.signOut();
          }}
        />
      </SafeAreaView>
    );
  }
Example #14
Source File: index.js    From musicont with MIT License 5 votes vote down vote up
Index = ({ songs, playlists, navigation }) => {
	const [assets] = useAssets([require('../../assets/icons/hamburger.png'), require('../../assets/icons/search.png')]);
	const [drawer, setDrawer] = useState(false);

	return (
		<Drawer active={drawer} current="playlist" onItemPressed={() => setDrawer(false)}>
			<SafeAreaView style={styles.container}>
				<Header
					options={{
						left: {
							children: drawer ? <Icon name="x" color="#C4C4C4" /> : <Image source={require('../../assets/icons/hamburger.png')} resizeMode="contain" />,
							onPress: () => setDrawer(!drawer),
						},
						middle: {
							show: true,
							text: 'Playlists',
						},
						right: {
							show: false,
						},
					}}
				/>
				{playlists && playlists?.length > 0 ? (
					<ScrollView style={{ flex: 1 }} contentContainerStyle={styles.sections} showsVerticalScrollIndicator={false}>
						{playlists.map((playlist, key) => (
							<Card.Playlist
								key={key}
								style={styles.item}
								overlayStyle={{ height: 200 }}
								imageURL={songs[playlist?.songs[0]]?.img}
								title={playlist?.name}
								subtitle={`${playlist?.songs.length} Songs`}
								onPress={() => {
									const playlistIndex = playlists.findIndex((i) => i?.name.toLowerCase() === playlist?.name.toLowerCase());
									navigation.push(SCREENS.PLAYLIST, { playlistIndex });
								}}
							/>
						))}
					</ScrollView>
				) : (
					<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
						<Text style={{ fontSize: 24, fontWeight: 'bold', color: 'rgba(0, 0, 0, .3)' }}>No playlists yet!</Text>
					</View>
				)}
			</SafeAreaView>
		</Drawer>
	);
}
Example #15
Source File: index.js    From musicont with MIT License 5 votes vote down vote up
Index = ({ songs }) => {
	const { goBack } = useNavigation();
	const [audios, setAudios] = useState([]);
	const [search, setSearch] = useState('');

	const handleInput = (val) => {
		const value = val.replace('  ', ' ');
		setSearch(value);
		if (value.length > 3) {
			const results = songs.filter((song) => {
				let regex = new RegExp(value, 'ig');
				return regex.exec(song?.title) || regex.exec(song?.author);
			});

			setAudios(results);
		} else {
			setAudios([]);
		}
	};

	return (
		<>
			<StatusBar style="dark" />
			<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
				<SafeAreaView style={styles.container}>
					<View style={styles.header}>
						<View style={styles.input}>
							<Icon name="search" color="#FFF" />
							<TextInput style={styles.textInput} onChangeText={handleInput} value={search} returnKeyType="search" placeholder="Search..." />
						</View>
						<TouchableOpacity style={styles.btn} onPress={() => goBack()}>
							<Text style={styles.btnTxt}>Cancel</Text>
						</TouchableOpacity>
					</View>
					<View style={styles.result}>
						{audios.length > 0 ? (
							<Section.MusicList audios={audios} />
						) : (
							<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
								<Text style={{ fontSize: 24, fontWeight: 'bold', color: 'rgba(0, 0, 0, .3)' }}>Search something...</Text>
							</View>
						)}
					</View>
				</SafeAreaView>
			</TouchableWithoutFeedback>
		</>
	);
}
Example #16
Source File: Login.js    From actual with MIT License 5 votes vote down vote up
function Login({ navigation, createBudget }) {
  let [email, setEmail] = useState('');
  let [loading, setLoading] = useState(false);
  let [error, setError] = useState(null);

  async function sendCode() {
    setLoading(true);
    setError(null);
    let { error } = await send('subscribe-send-email-code', { email });
    setLoading(false);

    if (error) {
      setError(getErrorMessage(error));
    } else {
      navigation.navigate('Confirm', { email });
    }
  }

  let textStyle = [
    styles.text,
    { fontSize: 17, lineHeight: 25, color: 'white' }
  ];

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <KeyboardAvoidingView>
        <TransitionView navigation={navigation}>
          {/* <StatusBar barStyle="light-content" /> */}

          <Header
            navigation={navigation}
            buttons={['back', 'demo']}
            loadDemoBudget={() => {
              send('track', { name: 'app:create-demo' });
              createBudget({ demoMode: true });
            }}
          />

          <Stack justify="center" style={{ flex: 1, padding: 20 }} spacing={5}>
            <View>
              <Text style={textStyle}>
                <Text style={{ fontWeight: '700' }}>Sign in.</Text> We
                {"'"}
                ll email you a code that you can use to log in. You only need to
                do this once. Right now, the mobile app works best as a
                companion to the desktop app.
              </Text>
            </View>

            <SingleInput
              title="Email"
              value={email}
              loading={loading}
              error={error}
              inputProps={{
                keyboardType: 'email-address',
                placeholder: '[email protected]'
              }}
              onChange={setEmail}
              onSubmit={sendCode}
            />
          </Stack>
        </TransitionView>
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
}
Example #17
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 #18
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 #19
Source File: App.js    From filen-mobile with GNU Affero General Public License v3.0 4 votes vote down vote up
App = memo(() => {
    const [isLoggedIn, setIsLoggedIn] = useMMKVBoolean("isLoggedIn", storage)
    const setDimensions = useStore(useCallback(state => state.setDimensions))
    const [darkMode, setDarkMode] = useMMKVBoolean("darkMode", storage)
    const [setupDone, setSetupDone] = useState(false)
    const [currentScreenName, setCurrentScreenName] = useState("MainScreen")
    const setCurrentRoutes = useStore(useCallback(state => state.setCurrentRoutes))
    const toastBottomOffset = useStore(useCallback(state => state.toastBottomOffset))
    const toastTopOffset = useStore(useCallback(state => state.toastTopOffset))
    const setNetInfo = useStore(useCallback(state => state.setNetInfo))
    const showNavigationAnimation = useStore(useCallback(state => state.showNavigationAnimation))
    const [userId, setUserId] = useMMKVNumber("userId", storage)
    const [cameraUploadEnabled, setCameraUploadEnabled] = useMMKVBoolean("cameraUploadEnabled:" + userId, storage)
    const setBiometricAuthScreenState = useStore(useCallback(state => state.setBiometricAuthScreenState))
    const setCurrentShareItems = useStore(useCallback(state => state.setCurrentShareItems))
    const setAppState = useStore(useCallback(state => state.setAppState))
    const [lang, setLang] = useMMKVString("lang", storage)
    const [nodeJSAlive, setNodeJSAlive] = useState(true)
    const setContentHeight = useStore(useCallback(state => state.setContentHeight))
    const isDeviceReady = useStore(useCallback(state => state.isDeviceReady))
    const [startOnCloudScreen, setStartOnCloudScreen] = useMMKVBoolean("startOnCloudScreen:" + userId, storage)
    const [userSelectedTheme, setUserSelectedTheme] = useMMKVString("userSelectedTheme", storage)
    const [currentDimensions, setCurrentDimensions] = useState({ window: Dimensions.get("window"), screen: Dimensions.get("screen") })

    const handleShare = useCallback(async (items) => {
        if(!items){
            return false
        }

        if(typeof items !== "undefined"){
            if(typeof items.data !== "undefined"){
                if(items.data !== null){
                    if(items.data.length > 0){
                        await new Promise((resolve) => {
                            const wait = BackgroundTimer.setInterval(() => {
                                if(typeof navigationRef !== "undefined"){
                                    const navState = navigationRef.getState()

                                    if(typeof navState !== "undefined"){
                                        if(typeof navState.routes !== "undefined"){
                                            if(navState.routes.filter(route => route.name == "SetupScreen" || route.name == "BiometricAuthScreen" || route.name == "LoginScreen").length == 0){
                                                if(storage.getBoolean("isLoggedIn")){
                                                    BackgroundTimer.clearInterval(wait)
    
                                                    return resolve()
                                                }
                                            }
                                        }
                                    }
                                }
                            }, 250)
                        })

                        let containsValidItems = true

                        if(Platform.OS == "android"){
                            if(Array.isArray(items.data)){
                                for(let i = 0; i < items.data.length; i++){
                                    if(items.data[i].indexOf("file://") == -1 && items.data[i].indexOf("content://") == -1){
                                        containsValidItems = false
                                    }
                                }
                            }
                            else{
                                if(items.data.indexOf("file://") == -1 && items.data.indexOf("content://") == -1){
                                    containsValidItems = false
                                }
                            }
                        }
                        else{
                            for(let i = 0; i < items.data.length; i++){
                                if(items.data[i].data.indexOf("file://") == -1 && items.data[i].data.indexOf("content://") == -1){
                                    containsValidItems = false
                                }
                            }
                        }

                        if(containsValidItems){
                            setCurrentShareItems(items)
                            showToast({ type: "upload" })
                        }
                        else{
                            showToast({ message: i18n(lang, "shareMenuInvalidType") })
                        }
                    }
                }
            }
        }
    })

    const initBackgroundFetch = useCallback(() => {
        BackgroundFetch.configure({
            minimumFetchInterval: 15,
            requiredNetworkType: BackgroundFetch.NETWORK_TYPE_ANY,
            stopOnTerminate: false,
            startOnBoot: true,
            enableHeadless: false
        }, (taskId) => {
            console.log("[" + Platform.OS + "] BG fetch running:", taskId)

            const waitForInit = (callback) => {
                const timeout = (+new Date() + 15000)

                const wait = BackgroundTimer.setInterval(() => {
                    if(timeout > (+new Date())){
                        if(isLoggedIn && cameraUploadEnabled && setupDone && isDeviceReady){
                            BackgroundTimer.clearInterval(wait)

                            return callback(false)
                        }
                    }
                    else{
                        BackgroundTimer.clearInterval(wait)

                        return callback(true)
                    }
                }, 10)
            }

            waitForInit((timedOut) => {
                if(timedOut){
                    console.log("[" + Platform.OS + "] BG fetch timed out:", taskId)

                    BackgroundFetch.finish(taskId)
                }
                else{
                    runCameraUpload({
                        runOnce: true,
                        maxQueue: 1,
                        callback: () => {
                            console.log("[" + Platform.OS + "] BG fetch done:", taskId)
    
                            BackgroundFetch.finish(taskId)
                        }
                    })
                }
            })
        }, (taskId) => {
            console.log("[" + Platform.OS + "] BG fetch timeout:", taskId)

            BackgroundFetch.finish(taskId)
        }).then((status) => {
            console.log("[" + Platform.OS + "] BG fetch init status:", status)
        }).catch((err) => {
            console.log("[" + Platform.OS + "] BG fetch init error:", err)
        })
    })

    const setAppearance = useCallback(() => {
        BackgroundTimer.setTimeout(() => {
            if(typeof userSelectedTheme == "string" && userSelectedTheme.length > 1){
                if(userSelectedTheme == "dark"){
                    setDarkMode(true)
                    setStatusBarStyle(true)
                }
                else{
                    setDarkMode(false)
                    setStatusBarStyle(false)
                }
            }
            else{
                if(Appearance.getColorScheme() == "dark"){
                    setDarkMode(true)
                    setStatusBarStyle(true)
                }
                else{
                    setDarkMode(false)
                    setStatusBarStyle(false)
                }
            }
        }, 1000) // We use a timeout due to the RN appearance event listener firing both "dark" and "light" on app resume which causes the screen to flash for a second
    })

    useEffect(() => {
        if(isLoggedIn && cameraUploadEnabled && setupDone){
            runCameraUpload({
                maxQueue: 10,
                runOnce: false,
                callback: undefined
            })
        }
    }, [isLoggedIn, cameraUploadEnabled, setupDone])

    useEffect(() => {
        initBackgroundFetch()

        //global.nodeThread.pingPong(() => {
        //    setNodeJSAlive(false)
        //})

        NetInfo.fetch().then((state) => {
            setNetInfo(state)
        }).catch((err) => {
            console.log(err)
        })

        //BackgroundTimer.start()

        const appStateListener = AppState.addEventListener("change", (nextAppState) => {
            setAppState(nextAppState)

            if(nextAppState == "background"){
                if(Math.floor(+new Date()) > storage.getNumber("biometricPinAuthTimeout:" + userId) && storage.getBoolean("biometricPinAuth:" + userId)){
                    setBiometricAuthScreenState("auth")

                    storage.set("biometricPinAuthTimeout:" + userId, (Math.floor(+new Date()) + 500000))
                    
                    navigationRef.current.dispatch(StackActions.push("BiometricAuthScreen"))
                }
            }

            if(nextAppState == "active"){
                checkAppVersion({ navigation: navigationRef })
            }
        })

        const netInfoListener = NetInfo.addEventListener((state) => {
            setNetInfo(state)
        })

        const dimensionsListener = Dimensions.addEventListener("change", ({ window, screen }) => {
            setDimensions({ window, screen })
            setCurrentDimensions({ window, screen })
        })

        const navigationRefListener = navigationRef.addListener("state", (event) => {
            if(typeof event.data !== "undefined"){
                if(typeof event.data.state !== "undefined"){
                    if(typeof event.data.state.routes !== "undefined"){
                        //console.log("Current Screen:", event.data.state.routes[event.data.state.routes.length - 1].name, event.data.state.routes[event.data.state.routes.length - 1].params)

                        setCurrentScreenName(event.data.state.routes[event.data.state.routes.length - 1].name)
                        setCurrentRoutes(event.data.state.routes)
                    }
                }
            }
        })

        ShareMenu.getInitialShare(handleShare)

        const shareMenuListener = ShareMenu.addNewShareListener(handleShare)

        setAppearance()

        const appearanceListener = Appearance.addChangeListener(() => {
            setAppearance()
        })

        if(isLoggedIn && !setupDone){
            setup({ navigation: navigationRef }).then(() => {
                setSetupDone(true)

                if(storage.getBoolean("biometricPinAuth:" + userId)){
                    setBiometricAuthScreenState("auth")

                    storage.set("biometricPinAuthTimeout:" + userId, (Math.floor(+new Date()) + 500000))
                    
                    navigationRef.current.dispatch(StackActions.push("BiometricAuthScreen"))
                }
                else{
                    navigationRef.current.dispatch(CommonActions.reset({
                        index: 0,
                        routes: [
                            {
                                name: "MainScreen",
                                params: {
                                    parent: startOnCloudScreen ? (storage.getBoolean("defaultDriveOnly:" + userId) ? storage.getString("defaultDriveUUID:" + userId) : "base") : "recents"
                                }
                            }
                        ]
                    }))
                }
            }).catch((err) => {
                console.log(err)
    
                if(typeof storage.getString("masterKeys") == "string" && typeof storage.getString("apiKey") == "string" && typeof storage.getString("privateKey") == "string" && typeof storage.getString("publicKey") == "string" && typeof storage.getNumber("userId") == "number"){
                    if(storage.getString("masterKeys").length > 16 && storage.getString("apiKey").length > 16 && storage.getString("privateKey").length > 16 && storage.getString("publicKey").length > 16 && storage.getNumber("userId") !== 0){
                        setSetupDone(true)

                        if(storage.getBoolean("biometricPinAuth:" + userId)){
                            setBiometricAuthScreenState("auth")

                            storage.set("biometricPinAuthTimeout:" + userId, (Math.floor(+new Date()) + 500000))
                            
                            navigationRef.current.dispatch(StackActions.push("BiometricAuthScreen"))
                        }
                        else{
                            navigationRef.current.dispatch(CommonActions.reset({
                                index: 0,
                                routes: [
                                    {
                                        name: "MainScreen",
                                        params: {
                                            parent: startOnCloudScreen ? (storage.getBoolean("defaultDriveOnly:" + userId) ? storage.getString("defaultDriveUUID:" + userId) : "base") : "recents"
                                        }
                                    }
                                ]
                            }))
                        }
                    }
                    else{
                        setSetupDone(false)

                        showToast({ message: i18n(lang, "appSetupNotPossible") })
                    }
                }
                else{
                    setSetupDone(false)

                    showToast({ message: i18n(lang, "appSetupNotPossible") })
                }
            })
        }

        // Reset on app launch
        storage.set("cameraUploadRunning", false)

        return () => {
            dimensionsListener.remove()
            shareMenuListener.remove()
            navigationRef.removeListener(navigationRefListener)
            navigationRefListener()
            appearanceListener.remove()
            netInfoListener()
            appStateListener.remove()
        }
    }, [])

  	return (
        <>
            <NavigationContainer ref={navigationRef}>
                <Fragment>
                    <SafeAreaProvider style={{
                        backgroundColor: darkMode ? "black" : "white",
                    }}>
                        <SafeAreaView mode="padding" style={{
                            backgroundColor: currentScreenName == "ImageViewerScreen" ? "black" : (darkMode ? "black" : "white"),
                            paddingTop: Platform.OS == "android" ? 5 : 5,
                            height: "100%",
                            width: "100%"
                        }}>
                            <View style={{
                                width: currentScreenName == "ImageViewerScreen" ? currentDimensions.screen.width : "100%",
                                height: currentScreenName == "ImageViewerScreen" ? currentDimensions.screen.height : "100%",
                                backgroundColor: darkMode ? "black" : "white"
                            }} onLayout={(e) => setContentHeight(e.nativeEvent.layout.height)}>
                                {
                                    nodeJSAlive ? (
                                        <>
                                            <Stack.Navigator initialRouteName={isLoggedIn ? (setupDone ? "MainScreen" : "SetupScreen") : "LoginScreen"} screenOptions={{
                                                contentStyle: {
                                                    backgroundColor: darkMode ? "black" : "white"
                                                },
                                                headerStyle: {
                                                    backgroundColor: darkMode ? "black" : "white"
                                                },
                                                headerShown: false,
                                                animation: showNavigationAnimation ? "default" : "none"
                                            }}>
                                                <Stack.Screen name="SetupScreen" component={SetupScreen} options={{
                                                    title: "SetupScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="LoginScreen" options={{
                                                    title: "LoginScreen"
                                                }}>{(props) => <LoginScreen {...props} setSetupDone={setSetupDone} />}</Stack.Screen>
                                                <Stack.Screen name="RegisterScreen" component={RegisterScreen} options={{
                                                    title: "RegisterScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="ForgotPasswordScreen" component={ForgotPasswordScreen} options={{
                                                    title: "ForgotPasswordScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="ResendConfirmationScreen" component={ResendConfirmationScreen} options={{
                                                    title: "ResendConfirmationScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="MainScreen" initialParams={{ parent: startOnCloudScreen ? (storage.getBoolean("defaultDriveOnly:" + userId) ? storage.getString("defaultDriveUUID:" + userId) : "base") : "recents" }} component={MainScreen} options={{
                                                    title: "MainScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="SettingsScreen" component={SettingsScreen} options={{
                                                    title: "SettingsScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="TransfersScreen" component={TransfersScreen} options={{
                                                    title: "TransfersScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="CameraUploadScreen" component={CameraUploadScreen} options={{
                                                    title: "CameraUploadScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="BiometricAuthScreen" component={BiometricAuthScreen} options={{
                                                    title: "BiometricAuthScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="LanguageScreen" component={LanguageScreen} options={{
                                                    title: "LanguageScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="SettingsAdvancedScreen" component={SettingsAdvancedScreen} options={{
                                                    title: "SettingsAdvancedScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="SettingsAccountScreen" component={SettingsAccountScreen} options={{
                                                    title: "SettingsAccountScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="EventsScreen" component={EventsScreen} options={{
                                                    title: "EventsScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="EventsInfoScreen" component={EventsInfoScreen} options={{
                                                    title: "EventsInfoScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="GDPRScreen" component={GDPRScreen} options={{
                                                    title: "GDPRScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="InviteScreen" component={InviteScreen} options={{
                                                    title: "InviteScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="TwoFactorScreen" component={TwoFactorScreen} options={{
                                                    title: "TwoFactorScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="ChangeEmailPasswordScreen" component={ChangeEmailPasswordScreen} options={{
                                                    title: "ChangeEmailPasswordScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="TextEditorScreen" component={TextEditorScreen} options={{
                                                    title: "TextEditorScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="UpdateScreen" component={UpdateScreen} options={{
                                                    title: "UpdateScreen"
                                                }}></Stack.Screen>
                                                <Stack.Screen name="ImageViewerScreen" component={ImageViewerScreen} options={{
                                                    title: "ImageViewerScreen",
                                                    presentation: "fullScreenModal"
                                                }}></Stack.Screen>
                                            </Stack.Navigator>
                                            <>
                                                {
                                                    setupDone && isLoggedIn && ["MainScreen", "SettingsScreen", "TransfersScreen", "CameraUploadScreen", "EventsScreen", "EventsInfoScreen", "SettingsAdvancedScreen", "SettingsAccountScreen", "LanguageScreen", "GDPRScreen", "InviteScreen", "TwoFactorScreen", "ChangeEmailPasswordScreen"].includes(currentScreenName) && (
                                                        <View style={{
                                                            position: "relative",
                                                            width: "100%",
                                                            bottom: 0,
                                                            height: 50
                                                        }}>
                                                            <BottomBar navigation={navigationRef} currentScreenName={currentScreenName} />
                                                        </View>
                                                    )
                                                }
                                            </>
                                        </>
                                    ) : (
                                        <View style={{
                                            width: "100%",
                                            height: "100%",
                                            justifyContent: "center",
                                            alignItems: "center"
                                        }}>
                                            <Ionicon name="information-circle-outline" size={70} color={darkMode ? "white" : "black"} />
                                            <Text style={{
                                                color: darkMode ? "white" : "black",
                                                marginTop: 5,
                                                width: "70%",
                                                textAlign: "center"
                                            }}>
                                                {i18n(lang, "nodeJSProcessDied")}
                                            </Text>
                                        </View>
                                    )
                                }
                                {
                                    nodeJSAlive && (
                                        <>
                                            <TransfersIndicator navigation={navigationRef} />
                                            <TopBarActionSheet navigation={navigationRef} />
                                            <BottomBarAddActionSheet navigation={navigationRef} />
                                            <ItemActionSheet navigation={navigationRef} />
                                            <FolderColorActionSheet navigation={navigationRef} />
                                            <PublicLinkActionSheet navigation={navigationRef} />
                                            <ShareActionSheet navigation={navigationRef} />
                                            <FileVersionsActionSheet navigation={navigationRef} />
                                            <ProfilePictureActionSheet navigation={navigationRef} />
                                            <SortByActionSheet navigation={navigationRef} />
                                        </>
                                    )
                                }
                            </View>
                        </SafeAreaView>
                    </SafeAreaProvider>
                    {
                        nodeJSAlive && (
                            <>
                                <Disable2FATwoFactorDialog navigation={navigationRef} />
                                <DeleteAccountTwoFactorDialog navigation={navigationRef} />
                                <RedeemCodeDialog navigation={navigationRef} />
                                <ConfirmStopSharingDialog navigation={navigationRef} />
                                <ConfirmRemoveFromSharedInDialog navigation={navigationRef} />
                                <ConfirmPermanentDeleteDialog navigation={navigationRef} />
                                <RenameDialog navigation={navigationRef} />
                                <CreateFolderDialog navigation={navigationRef} />
                                <CreateTextFileDialog navigation={navigationRef} />
                                <BulkShareDialog navigation={navigationRef} />
                                <FullscreenLoadingModal navigation={navigationRef} />
                            </>
                        )
                    }
                </Fragment>
            </NavigationContainer>
            <Toast
                ref={(ref) => global.toast = ref}
                offsetBottom={toastBottomOffset}
                offsetTop={toastTopOffset}
                pointerEvents="box-none"
                style={{
                    zIndex: 99999
                }}
            />
        </>
    )
})
Example #20
Source File: CharacterScreen.js    From hero with MIT License 4 votes vote down vote up
CharacterScreen = ({ route, navigation }) => {
  const {
    hero,
    image,
    publisher,
    comicPicture,
    summary,
    firstIssue,
    firstIssueURL,
  } = route.params;

  let publisherLogo = null;
  let logoShape = null;
  //   let firstIssueID = null;

  if (publisher === "Marvel Comics" || publisher === "Marvel") {
    publisherLogo = require(`../assets/images/Marvel-Logo.jpg`);
    logoShape = styles.publisherLogoRectangle;
  } else if (publisher === "DC Comics") {
    publisherLogo = require(`../assets/images/DC-Logo.png`);
    logoShape = styles.publisherLogoSquare;
  }

  const activeLightboxProps = {
    resizeMode: "contain",
    marginHorizontal: 20,
    flex: 1,
    width: null,
  };

  //   if (comicPicture) {
  //     comicPictureURL = require(comicPicture);
  //   }

  function searchComic(firstComic) {
    fetch(
      `https://comicvine.gamespot.com/api/characters/?api_key=${apiComic.key}&sort=deck:desc&filter=name:${hero.name}&format=json`
    )
      .then((res) => {
        if (res.status === 404) {
          throw new Error("I didn't find this hero. Please try again!");
        } else {
          return res.json();
        }
      })

      .then((result) => {
        console.log("====================================");
        console.log("NEW SEARCH");
        console.log("====================================");
        console.log(result.results);
      });
  }

  function searchFirstComic() {
    fetch(
      `https://comicvine.gamespot.com/api/issue/4000-${firstIssue.id}/?api_key=${apiComic.key}&format=json`
    )
      .then((res) => {
        if (res.status === 404) {
          throw new Error("I didn't find this hero. Please try again!");
        } else {
          return res.json();
        }
      })

      .then((result) => {
        console.log("FIRST ISSUE DETAILS");
        console.log(result.results.image.original_url);
        // comicPicture = require(result.results[0].image.original_url);
        // summary = result.results[0].deck;
      });
  }

  //   useEffect(() => {
  //     // console.log(publisherVine);
  //     // searchComic(hero.biography["first-appearance"]);
  //     //   searchFirstComic();
  //   }, []);

  return (
    <View style={styles.appContainer}>
      <StatusBar
        translucent
        backgroundColor="transparent"
        barStyle="dark-content"
      />
      <SafeAreaView
        style={{ flex: 1, backgroundColor: "transparent" }}
        forceInset={{ top: "always" }}
      >
        <Header title={""} backbutton={true} navigation={navigation} />
        <Image source={image} style={styles.heroImage} />
        <LinearGradient
          colors={["#ffffff00", COLORS.beige]}
          style={styles.bottomFade}
          locations={[0.3, 1]}
        />
        <View style={styles.heroInfoContainer}>
          <View style={styles.heroTitleContainer}>
            <Text style={styles.heroTitle}>{hero.name}</Text>
            <View style={styles.heroHeader}>
              <Text style={{ ...styles.h4, marginLeft: 3, fontSize: 16 }}>
                {hero.biography["full-name"]}
              </Text>
              <Image source={publisherLogo} style={logoShape} />
            </View>
          </View>
          <Divider
            orientation="horizontal"
            width={3}
            style={{ ...styles.divider, marginBottom: 0 }}
            color={COLORS.navy}
          />
          <ScrollView
            style={{ height: 340 }}
            contentContainerStyle={{
              width: "100%",
              paddingBottom: 40,
              marginTop: 10,
            }}
            showsVerticalScrollIndicator={false}
          >
            <Text
              style={{
                ...styles.p,
                fontSize: 12,
                marginBottom: 20,
                lineHeight: 18,
              }}
            >
              {summary}
            </Text>
            {/********** STATS DETAILS ***************/}
            <View
              style={{
                flexDirection: "row",
                flexWrap: "wrap",
                justifyContent: "space-around",
                alignItems: "center",
                // backgroundColor: COLORS.grey,
                borderRadius: 20,
                // padding: 10,
                marginBottom: 10,
              }}
            >
              <View
                style={{
                  alignItems: "center",
                  justifyContent: "center",
                  padding: 5,
                }}
              >
                <AnimatedCircularProgress
                  size={60}
                  width={10}
                  duration={2000}
                  backgroundWidth={8}
                  rotation={-124}
                  arcSweepAngle={250}
                  fill={Number(hero.powerstats.intelligence)}
                  tintColor={COLORS.red}
                  tintColorSecondary={COLORS.green}
                  // onAnimationComplete={() => console.log("onAnimationComplete")}
                  backgroundColor={COLORS.navy}
                  padding={0}
                  lineCap={"round"}
                  // renderCap={({ center }) => (
                  //   <Circle cx={center.x} cy={center.y} r="10" fill="blue" />
                  // )}
                >
                  {(fill) => (
                    <Text
                      style={{
                        ...styles.p,
                        fontFamily: "Flame-Regular",
                        left: 1,
                      }}
                    >
                      {Math.floor(fill)}
                    </Text>
                  )}
                </AnimatedCircularProgress>
                <Text
                  style={{
                    ...styles.p,
                    fontFamily: "Flame-Regular",
                    fontSize: 10,
                    marginTop: -10,
                  }}
                >
                  Intelligence
                </Text>
              </View>
              <View
                style={{
                  alignItems: "center",
                  justifyContent: "center",
                  padding: 5,
                }}
              >
                <AnimatedCircularProgress
                  size={60}
                  width={10}
                  duration={2000}
                  backgroundWidth={8}
                  rotation={-124}
                  arcSweepAngle={250}
                  fill={Number(hero.powerstats.strength)}
                  tintColor={COLORS.red}
                  tintColorSecondary={COLORS.green}
                  // onAnimationComplete={() => console.log("onAnimationComplete")}
                  backgroundColor={COLORS.navy}
                  padding={0}
                  lineCap={"round"}
                  // renderCap={({ center }) => (
                  //   <Circle cx={center.x} cy={center.y} r="10" fill="blue" />
                  // )}
                >
                  {(fill) => (
                    <Text
                      style={{
                        ...styles.p,
                        fontFamily: "Flame-Regular",
                        left: 1,
                      }}
                    >
                      {Math.floor(fill)}
                    </Text>
                  )}
                </AnimatedCircularProgress>
                <Text
                  style={{
                    ...styles.p,
                    fontFamily: "Flame-Regular",
                    fontSize: 10,
                    marginTop: -10,
                  }}
                >
                  Strength
                </Text>
              </View>
              <View
                style={{
                  alignItems: "center",
                  justifyContent: "center",
                  padding: 5,
                }}
              >
                <AnimatedCircularProgress
                  size={60}
                  width={10}
                  duration={2000}
                  backgroundWidth={8}
                  rotation={-124}
                  arcSweepAngle={250}
                  fill={Number(hero.powerstats.speed)}
                  tintColor={COLORS.red}
                  tintColorSecondary={COLORS.green}
                  // onAnimationComplete={() => console.log("onAnimationComplete")}
                  backgroundColor={COLORS.navy}
                  padding={0}
                  lineCap={"round"}
                  // renderCap={({ center }) => (
                  //   <Circle cx={center.x} cy={center.y} r="10" fill="blue" />
                  // )}
                >
                  {(fill) => (
                    <Text
                      style={{
                        ...styles.p,
                        fontFamily: "Flame-Regular",
                        left: 1,
                      }}
                    >
                      {Math.floor(fill)}
                    </Text>
                  )}
                </AnimatedCircularProgress>
                <Text
                  style={{
                    ...styles.p,
                    fontFamily: "Flame-Regular",
                    fontSize: 10,
                    marginTop: -10,
                  }}
                >
                  Speed
                </Text>
              </View>
              <View
                style={{
                  alignItems: "center",
                  justifyContent: "center",
                  padding: 5,
                }}
              >
                <AnimatedCircularProgress
                  size={60}
                  width={10}
                  duration={2000}
                  backgroundWidth={8}
                  rotation={-124}
                  arcSweepAngle={250}
                  fill={Number(hero.powerstats.durability)}
                  tintColor={COLORS.red}
                  tintColorSecondary={COLORS.green}
                  // onAnimationComplete={() => console.log("onAnimationComplete")}
                  backgroundColor={COLORS.navy}
                  padding={0}
                  lineCap={"round"}
                  // renderCap={({ center }) => (
                  //   <Circle cx={center.x} cy={center.y} r="10" fill="blue" />
                  // )}
                >
                  {(fill) => (
                    <Text
                      style={{
                        ...styles.p,
                        fontFamily: "Flame-Regular",
                        left: 1,
                      }}
                    >
                      {Math.floor(fill)}
                    </Text>
                  )}
                </AnimatedCircularProgress>
                <Text
                  style={{
                    ...styles.p,
                    fontFamily: "Flame-Regular",
                    fontSize: 10,
                    marginTop: -10,
                  }}
                >
                  Durability
                </Text>
              </View>
              <View
                style={{
                  alignItems: "center",
                  justifyContent: "center",
                  padding: 5,
                }}
              >
                <AnimatedCircularProgress
                  size={60}
                  width={10}
                  duration={2000}
                  backgroundWidth={8}
                  rotation={-124}
                  arcSweepAngle={250}
                  fill={Number(hero.powerstats.power)}
                  tintColor={COLORS.red}
                  tintColorSecondary={COLORS.green}
                  // onAnimationComplete={() => console.log("onAnimationComplete")}
                  backgroundColor={COLORS.navy}
                  padding={0}
                  lineCap={"round"}
                  // renderCap={({ center }) => (
                  //   <Circle cx={center.x} cy={center.y} r="10" fill="blue" />
                  // )}
                >
                  {(fill) => (
                    <Text
                      style={{
                        ...styles.p,
                        fontFamily: "Flame-Regular",
                        left: 1,
                      }}
                    >
                      {Math.floor(fill)}
                    </Text>
                  )}
                </AnimatedCircularProgress>
                <Text
                  style={{
                    ...styles.p,
                    fontFamily: "Flame-Regular",
                    fontSize: 10,
                    marginTop: -10,
                  }}
                >
                  Power
                </Text>
              </View>
              <View
                style={{
                  alignItems: "center",
                  justifyContent: "center",
                  padding: 5,
                }}
              >
                <AnimatedCircularProgress
                  size={60}
                  width={10}
                  duration={2000}
                  backgroundWidth={8}
                  rotation={-124}
                  arcSweepAngle={250}
                  fill={Number(hero.powerstats.combat)}
                  tintColor={COLORS.red}
                  tintColorSecondary={COLORS.green}
                  // onAnimationComplete={() => console.log("onAnimationComplete")}
                  backgroundColor={COLORS.navy}
                  padding={0}
                  lineCap={"round"}
                  // renderCap={({ center }) => (
                  //   <Circle cx={center.x} cy={center.y} r="10" fill="blue" />
                  // )}
                >
                  {(fill) => (
                    <Text
                      style={{
                        ...styles.p,
                        fontFamily: "Flame-Regular",
                        left: 1,
                      }}
                    >
                      {Math.floor(fill)}
                    </Text>
                  )}
                </AnimatedCircularProgress>
                <Text
                  style={{
                    ...styles.p,
                    fontFamily: "Flame-Regular",
                    fontSize: 10,
                    marginTop: -10,
                  }}
                >
                  Combat
                </Text>
              </View>
            </View>
            {/********** BIOGRAPHY DETAILS ***************/}
            <View style={styles.heroDetailsContainer}>
              <Text style={{ ...styles.h2 }}>Biography</Text>
              <Divider
                orientation="horizontal"
                width={2}
                inset={true}
                style={styles.divider}
                color={COLORS.navy}
              />
              {Object.entries(hero.biography).map(([key, value, index]) => {
                // console.log(`${key}: ${value}`);

                let str = value.toString();

                if (
                  key != "full-name" &&
                  key != "place-of-birth" &&
                  key != "first-appearance" &&
                  key != "alter-egos" &&
                  "No alter egos found."
                ) {
                  str = str.replace(/,|;\s*(?![^()]*\))/g, "\n\u2022 ");
                }

                return (
                  <View
                    key={index}
                    style={{
                      flexDirection:
                        key == "aliases" || key == "alter-egos"
                          ? "column"
                          : "row",
                      justifyContent: "space-between",
                      alignItems: "flex-start",
                      flexWrap: "wrap",
                      marginBottom: 5,
                    }}
                  >
                    <Text style={styles.h4}>{key}:</Text>

                    {str.split(`/,[s]*/g, ", "`).map((value) => (
                      <Text
                        style={{ ...styles.p, textTransform: "capitalize" }}
                      >
                        {key == "alter-egos" || key == "aliases"
                          ? "\u2022 " + value
                          : value && value == "-"
                          ? "unknown"
                          : value}
                      </Text>
                    ))}
                  </View>
                );
              })}
            </View>
            {/********** COMIC PICTURE ***************/}
            <View style={styles.comicPictureContainer}>
              {firstIssueURL ? (
                <Lightbox
                  // renderHeader={() => {
                  //   return (
                  //     <View
                  //       style={{
                  //         justifyContent: "center",
                  //         alignItems: "flex-start",
                  //         paddingHorizontal: 15,
                  //         top: 70,
                  //       }}
                  //     >
                  //       <Text
                  //         style={{ ...styles.heroTitle, color: COLORS.beige }}
                  //       >
                  //         First Issue
                  //       </Text>
                  //     </View>
                  //   );
                  // }}
                  activeProps={activeLightboxProps}
                >
                  <Image
                    source={{
                      uri: firstIssueURL,
                    }}
                    style={styles.comicPicture}
                  />
                </Lightbox>
              ) : (
                <Text style={styles.h4}>NO PICTURE</Text>
              )}
            </View>
            {/********** APPEARANCE DETAILS ***************/}
            <View style={styles.heroDetailsContainer}>
              <Text style={{ ...styles.h2 }}>Appearence</Text>
              <Divider
                orientation="horizontal"
                width={2}
                inset={true}
                style={styles.divider}
                color={COLORS.navy}
              />
              {Object.entries(hero.appearance).map(([key, value, index]) => {
                // console.log(`${key}: ${value}`);
                const str = value.toString();
                return (
                  <View
                    key={index}
                    style={{
                      flexDirection: "row",
                      justifyContent: "space-between",
                      alignItems: "stretch",
                      flexWrap: "wrap",
                    }}
                  >
                    <Text style={styles.h4}>{key}:</Text>
                    <Text style={{ ...styles.p, marginTop: -2 }}>
                      {str
                        .split(`/,[s]*/g, ", "`)
                        .map((value) =>
                          str.includes(",") ? (
                            <Text>{value.replace(/,(?=[^\s])/g, ", ")}</Text>
                          ) : (
                            <Text>{value}</Text>
                          )
                        )}
                    </Text>
                  </View>
                );
              })}
            </View>
            {/********** WORK DETAILS ***************/}
            <View style={styles.heroDetailsContainer}>
              <Text style={{ ...styles.h2 }}>Work</Text>
              <Divider
                orientation="horizontal"
                width={2}
                inset={true}
                style={styles.divider}
                color={COLORS.navy}
              />
              {Object.entries(hero.work).map(([key, value, index]) => {
                // console.log(`${key}: ${value}`);
                let str = value;

                if (key != "base") {
                  str = str.replace(/,|;\s*(?![^()]*\))/g, "\n\u2022 ");
                }

                return (
                  <View
                    key={index}
                    style={{
                      flexDirection: key == "base" ? "row" : "column",
                      justifyContent: "space-between",
                      alignItems: key == "base" ? "stretch" : "flex-start",
                      flexWrap: "wrap",
                      marginBottom: 5,
                    }}
                  >
                    <Text style={{ ...styles.h4, marginBottom: 4 }}>
                      {key}:
                    </Text>

                    {str.split(`/,[s]*/g, ", "`).map((value) => (
                      <Text
                        style={{
                          ...styles.p,
                          textTransform: "capitalize",
                          lineHeight: key == "occupation" ? 20 : 0,
                          marginTop: -2,
                        }}
                      >
                        {key == "base"
                          ? value
                          : "\u2022 " + value && value != "-"
                          ? "\u2022 " + value
                          : "unknown"}
                      </Text>
                    ))}
                  </View>
                );
              })}
            </View>
            {/********** CONNECTIONS DETAILS ***************/}
            <View style={styles.heroDetailsContainer}>
              <Text style={{ ...styles.h2 }}>Connections</Text>
              <Divider
                orientation="horizontal"
                width={2}
                inset={true}
                style={styles.divider}
                color={COLORS.navy}
              />
              {Object.entries(hero.connections).map(([key, value, index]) => {
                // console.log(`${key}: ${value}`);
                let str = value.toString();
                if (key == "group-affiliation") {
                  str = value.replace(/,|;\s*(?![^()]*\))/g, "\n\u2022 ");
                } else {
                  str = value.replace(/,|;\s*(?![^()]*\))/g, "\n\u2022 ");
                }
                // const firstLetter = str.charAt(0).toUpperCase() + str.slice(1);
                return (
                  <View
                    key={index}
                    style={{
                      flexDirection: "column",
                      justifyContent: "space-between",
                      alignItems: "flex-start",
                      flexWrap: "wrap",
                      marginBottom: 5,
                    }}
                  >
                    <Text style={styles.h4}>{key}:</Text>

                    {str.split(`/,[s]*/g, ", "`).map((value) => (
                      <Text
                        style={{
                          ...styles.p,
                          textTransform: "capitalize",
                          lineHeight: 24,
                        }}
                      >
                        {value != "-" ? "\u2022 " + value : "unknown"}
                      </Text>
                    ))}
                  </View>
                );
              })}
            </View>
          </ScrollView>
          <LinearGradient
            colors={["#ffffff00", COLORS.beige]}
            style={styles.bottomFadeInfo}
            locations={[0.8, 1]}
            pointerEvents={"none"}
          />
        </View>
      </SafeAreaView>
    </View>
  );
}
Example #21
Source File: App.js    From redis-examples with MIT License 4 votes vote down vote up
render(){
    this.height = Math.round(Dimensions.get('screen').height);
    this.width = Math.round(Dimensions.get('screen').width);
    return (
      <SafeAreaView style={{
        width: this.width,
        height: this.height,
        flex: 1,
        alignItems: 'center'}}>
        <StatusBar
        backgroundColor="#f4511e"/>
        <View style={{height: this.height/8}} />
        <View
          style={{
            flex:1,
            width: this.width,
            alignItems: 'center',
            justifyContent: 'center',
          }}>
          <View
            style={{
              flex:1,
              width: this.width,
              alignItems: 'center',
              justifyContent: 'center',
            }}>
            <TextInput
              spellCheck={false}
              autoCorrect={false}
              placeholderTextColor="rgba(0,0,0,0.4)"
              placeholder={"First name"}
              style={{
                width: this.width*7/10,
                borderColor: 'purple',
                borderWidth: 1,
                borderRadius: 8
              }}
              onChangeText={(text) =>
                this.setState({firstname: text})
              }></TextInput>
          </View>
          <View
            style={{
              flex:1,
              width: this.width,
              alignItems: 'center',
              justifyContent: 'center',
            }}>
            <TextInput
              spellCheck={false}
              autoCorrect={false}
              placeholderTextColor="rgba(0,0,0,0.4)"
              placeholder={"Last name"}
              style={{
                width: this.width*7/10,
                borderColor: 'purple',
                borderWidth: 1,
                borderRadius: 8
              }}
              onChangeText={(text) =>
                this.setState({lastname: text})
              }></TextInput>
          </View>
          <View
            style={{
              flex:1,
              width: this.width,
              alignItems: 'center',
              justifyContent: 'center',
            }}>
            <TextInput
              spellCheck={false}
              autoCorrect={false}
              placeholderTextColor="rgba(0,0,0,0.4)"
              placeholder={"Score"}
              style={{
                width: this.width*7/10,
                borderColor: 'purple',
                borderWidth: 1,
                borderRadius: 8
              }}
              onChangeText={(text) =>
                this.setState({score: text})
              }></TextInput>
          </View>
        </View>
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center'}}>
          <TouchableHighlight
            style={{backgroundColor: "green", alignItems: 'center', borderColor: "green",
            borderRadius: 8, borderWidth: 1, paddingVertical: 10, paddingHorizontal: 20}}
            onPress={() =>{this.addScore()}}>
            <Text style={{color:"white"}}>Submit Score</Text>
          </TouchableHighlight>
        </View>
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center'}}>
          <TouchableHighlight
            style={{backgroundColor: "#2196F3", alignItems: 'center', borderColor: "#2196F3",
            borderRadius: 8, borderWidth: 1, paddingVertical: 10, paddingHorizontal: 20}}
            onPress={() =>{this.props.navigation.navigate('Leaderboard')}}>
            <Text style={{color:"white"}}>Go to Leaderboard</Text>
          </TouchableHighlight>
        </View>
      </SafeAreaView>
    );
  }
Example #22
Source File: Confirm.js    From actual with MIT License 4 votes vote down vote up
function Confirm({ route, navigation, getUserData, loginUser, createBudget }) {
  let [code, setCode] = useState('');
  let [loading, setLoading] = useState(false);
  let [error, setError] = useState(null);

  let { signingUp } = route.params || {};

  async function onConfirm() {
    let { email } = route.params || {};
    setLoading(true);

    let { confirmed, error, userId, key, validSubscription } = await send(
      'subscribe-confirm',
      { email, code }
    );

    if (error) {
      setLoading(false);
      setError(getErrorMessage(error));
    } else if (!confirmed) {
      setLoading(false);
      setError(getErrorMessage('not-confirmed'));
    } else if (!validSubscription) {
      if (Platform.OS === 'ios') {
        // Eagerly load in the offerings (otherwise the subscribe button
        // shows a loading state which is weird)
        await setupPurchases({ id: userId, email: email });
        await getOfferings();

        setLoading(false);
        navigation.navigate('Subscribe', { email, userId, key });
      } else {
        // This is a "half-created" account, right now on Android we
        // don't fix it here, we just tell the user. This is super
        // rare - only happens if a user on iOS creates an account but
        // doesn't subscribe, and then tries to log in on Android with
        // that account
        alert(
          'An error occurred loading your account. Please contact [email protected] for support'
        );
        setLoading(false);
      }
    } else {
      setLoading(false);

      // This will load the user in the backend and rerender the app
      // in the logged in state
      loginUser(userId, key);

      if (global.SentryClient) {
        global.SentryClient.setUser({
          id: userId,
          ip_address: '{{auto}}'
        });
      }
    }
  }

  let textStyle = [
    styles.text,
    { fontSize: 17, lineHeight: 25, color: 'white' }
  ];

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <KeyboardAvoidingView>
        <TransitionView navigation={navigation}>
          <Header
            navigation={navigation}
            buttons={['back', 'demo']}
            loadDemoBudget={() => createBudget({ demoMode: true })}
          />

          <Stack justify="center" style={{ flex: 1, padding: 20 }} spacing={5}>
            <View>
              {signingUp ? (
                <Text style={textStyle}>
                  Enter the code you got in your email to activate your account:
                </Text>
              ) : (
                <Text style={textStyle}>
                  Enter the code you got in your email:
                </Text>
              )}
            </View>

            <SingleInput
              title="Code"
              value={code}
              loading={loading}
              error={error}
              inputProps={{ keyboardType: 'numeric' }}
              onChange={setCode}
              onSubmit={onConfirm}
            />
          </Stack>
        </TransitionView>
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
}
Example #23
Source File: index.js    From tcap-mobile with GNU General Public License v3.0 4 votes vote down vote up
render() {
      return (
          <SafeAreaView style={styles.wrapper}>
              <StatusBarColor
                  backgroundColor={Colors.primary_bg}
                  barStyle="light-content"
              />
              {!this.state.disableBackButton && (
                  <View style={styles.backButtonWrapper}>
                      <TouchableOpacity
                          onPress={this.navigateBack}
                          style={styles.backButton}>
                          <Icon
                              color={Colors.title}
                              name={'angle-left'}
                              size={24}
                              style={{alignSelf: 'center'}}
                          />
                      </TouchableOpacity>
                  </View>
              )}
              <View style={styles.container}>
                  {this.state.mode === PIN_SCREEN_MODE.LOGIN_PIN && (
                      <View style={styles.recoverButtonWrapper}>
                          <TouchableOpacity
                              onPress={this.navigateToRecoverAccount.bind(this)}>
                              <Text style={styles.recoverAccount}>Recover Account</Text>
                          </TouchableOpacity>
                      </View>
                  )}
                  <View style={styles.headerContainer}>
                      <View style={styles.titleWrapper}>
                          <Text style={styles.title}>{this.getTitle()}</Text>
                      </View>
                      <View style={styles.pinWrapper}>
                          <View style={this.getCircleStyle(1)} />
                          <View style={this.getCircleStyle(2)} />
                          <View style={this.getCircleStyle(3)} />
                          <View style={this.getCircleStyle(4)} />
                          <View style={this.getCircleStyle(5)} />
                          <View style={this.getCircleStyle(6)} />
                      </View>
                  </View>
              </View>
              <View style={styles.keyPadContainer}>
                  <Image
                      source={require('../../../../assets/images/backgrounds/pin-pattern.png')}
                      style={styles.keyPadImage}
                  />
                  <View style={styles.keyPadWrapper}>
                      <View style={styles.keyRow}>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('1')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>1</Text>
                          </TouchableOpacity>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('2')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>2</Text>
                          </TouchableOpacity>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('3')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>3</Text>
                          </TouchableOpacity>
                      </View>
                      <View style={styles.keyRow}>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('4')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>4</Text>
                          </TouchableOpacity>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('5')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>5</Text>
                          </TouchableOpacity>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('6')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>6</Text>
                          </TouchableOpacity>
                      </View>
                      <View style={styles.keyRow}>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('7')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>7</Text>
                          </TouchableOpacity>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('8')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>8</Text>
                          </TouchableOpacity>
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('9')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>9</Text>
                          </TouchableOpacity>
                      </View>
                      <View style={styles.keyRow}>
                          <View style={styles.key} />
                          <TouchableOpacity
                              onPress={() => this.onButtonPress('0')}
                              style={styles.key}>
                              <Text style={styles.keyStyle}>0</Text>
                          </TouchableOpacity>
                          <TouchableOpacity
                              onPress={this.deleteKeyPress}
                              style={styles.key}>
                              <Icon
                                  color="#fff"
                                  name={'backspace'}
                                  size={22}
                                  style={{alignSelf: 'center'}}
                              />
                          </TouchableOpacity>
                      </View>
                  </View>
              </View>
              <LoadingIndicator
                  message={this.state.loadingMessage}
                  visible={this.state.isLoading}
              />
              <ErrorDialog
                  message={this.state.errorMessage}
                  onDismiss={() => {
                      this.setState({showError: false});
                  }}
                  title={this.state.errorTitle}
                  visible={this.state.showError}
              />
          </SafeAreaView>
      );
  }
Example #24
Source File: SignUp.js    From reddit-clone with MIT License 4 votes vote down vote up
SignUp = ({ 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: '', passwordConfirmation: '' }}
        onSubmit={async (values, { setStatus, resetForm }) => {
          try {
            const { data } = await axios.post('signup', values)
            const { token, expiresAt, userInfo } = data
            setStorage(token, expiresAt, userInfo)
            navigation.navigate('Home')
            resetForm({})
          } catch (error) {
            setStatus(error.response.data.message)
          }
        }}
        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'),
          passwordConfirmation: Yup.string().oneOf(
            [Yup.ref('password'), null],
            'Passwords must match'
          )
        })}
      >
        {({
          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}
                  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
                />
                {touched.passwordConfirmation && errors.passwordConfirmation && (
                  <Text style={styles.errorMessage}>{errors.passwordConfirmation}</Text>
                )}
                <TextInput
                  style={[
                    styles.textInput,
                    touched.passwordConfirmation &&
                      errors.passwordConfirmation && {
                        borderColor: colors.red
                      },
                    { color: colors.text }
                  ]}
                  placeholder="Confirm Password"
                  placeholderTextColor={colors.text}
                  value={values.passwordConfirmation}
                  onChangeText={handleChange('passwordConfirmation')}
                  onBlur={handleBlur('passwordConfirmation')}
                  secureTextEntry
                />
                <View style={styles.buttonContainer}>
                  <Button
                    onPress={handleSubmit}
                    title="Create Account"
                    bgColor={colors.signUpButton}
                  >
                    {isLoading && <ActivityIndicator size="small" color="white" />}
                  </Button>
                </View>
              </View>
            </View>
          </TouchableWithoutFeedback>
        )}
      </Formik>
    </KeyboardAvoidingView>
  )
}
Example #25
Source File: Intro.js    From actual with MIT License 4 votes vote down vote up
render() {
    let { navigation, createBudget } = this.props;
    let { selectedFeature } = this.state;

    //let textStyle = [styles.text, { color: 'white' }];

    return (
      <SafeAreaView style={{ flex: 1 }}>
        <TransitionView navigation={navigation}>
          <View
            style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}
          >
            <ScalableImage
              source={Icon}
              width={35}
              style={{ marginBottom: 20, marginTop: 30 }}
            />

            <View style={{ height: 240 }}>
              <ScrollView
                ref={el => (this.scrollView = el)}
                pagingEnabled={true}
                horizontal={true}
                showsHorizontalScrollIndicator={false}
                onScrollBeginDrag={this.onScrollBegin}
                onScrollEndDrag={this.onScrollEnd}
                onMomentumScrollEnd={this.onMomentumScrollEnd}
              >
                <View
                  style={{
                    flexDirection: 'row',
                    alignItems: 'center',
                    flex: 0
                  }}
                >
                  <Feature
                    title="Welcome to Actual"
                    subtitle={
                      <Text>
                        Actual is a privacy-focused app that lets you track your
                        finances without all the fuss. Create your own budgeting
                        workflows quickly and discover your spending habits.{' '}
                        <ExternalLink href="https://actualbudget.com/">
                          Learn more
                        </ExternalLink>
                      </Text>
                    }
                  />
                  <Feature
                    title="Powerful budgeting made simple"
                    subtitle="Based on tried and true methods, our budgeting system is based off of your real income instead of made up numbers."
                  />
                  <Feature
                    title="The fastest way to manage transactions"
                    subtitle="Breeze through your transactions and update them easily with a streamlined, minimal interface."
                  />
                  <Feature
                    title="A privacy-focused approach"
                    subtitle="All of your data exists locally and is always available. We only upload your data to our servers when syncing across devices, and we encrypt it so even we can't read it."
                  />
                </View>
              </ScrollView>
              <View style={{ alignItems: 'center' }}>
                <View
                  style={{
                    flexDirection: 'row',
                    justifyContent: 'space-between',
                    width: 45
                  }}
                >
                  <SlideshowIndicator selected={selectedFeature === 0} />
                  <SlideshowIndicator selected={selectedFeature === 1} />
                  <SlideshowIndicator selected={selectedFeature === 2} />
                  <SlideshowIndicator selected={selectedFeature === 3} />
                </View>
              </View>
            </View>
          </View>

          <View
            style={{
              marginHorizontal: 50,
              marginBottom: 15,
              justifyContent: 'flex-end'
            }}
          >
            <Button
              primary
              style={{ marginBottom: 10, backgroundColor: 'white' }}
              contentStyle={{ borderWidth: 0 }}
              textStyle={{ fontSize: 17, color: colors.n1 }}
              onPress={() => {
                navigation.navigate('SubscribeEmail');
              }}
            >
              Get started
            </Button>
            <Button
              style={{
                marginBottom: 10,
                backgroundColor: 'rgba(180, 180, 180, .15)'
              }}
              contentStyle={{ borderWidth: 0 }}
              textStyle={{ fontSize: 17, color: 'white' }}
              onPress={() => {
                navigation.navigate('Login');
              }}
            >
              Log in
            </Button>
          </View>
          <Button
            bare
            textStyle={{ fontWeight: 'bold', fontSize: 15, color: 'white' }}
            style={{ padding: 10, alignSelf: 'center' }}
            onPress={() => createBudget({ demoMode: true })}
          >
            Try demo
          </Button>
        </TransitionView>
      </SafeAreaView>
    );
  }
Example #26
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 #27
Source File: PostDetail.js    From reddit-clone with MIT License 4 votes vote down vote up
PostDetail = ({ route, navigation }) => {
  const { authState } = React.useContext(AuthContext)
  const flatListRef = React.useRef()

  const [post, setPost] = React.useState(null)
  const [isLoading, setIsLoaading] = React.useState(false)
  const [comment, setComment] = React.useState('')
  const [isFocused, setIsFocused] = React.useState(null)

  const { postId } = route.params
  const { comments } = route.params

  const getPostData = React.useCallback(async () => {
    setIsLoaading(true)
    const { data } = await axios.get(`post/${postId}`)
    setPost(data)
    setIsLoaading(false)
  }, [postId])

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

  React.useEffect(() => {
    isFocused && flatListRef.current.scrollToOffset({ animated: true, offset: 0 })
  }, [isFocused])

  const createComment = async () => {
    const { data } = await axios.post(`/post/${postId}`, {
      comment
    })
    setPost(data)
    setComment('')
  }

  const deleteComment = async commentId => {
    setIsLoaading(true)
    const { data } = await axios.delete(`/post/${postId}/${commentId}`)
    setPost(data)
    setIsLoaading(false)
  }

  const deletePost = async postId => {
    setIsLoaading(true)
    const { status } = await axios.delete(`post/${postId}`)
    if (status === 200) {
      navigation.push('Home')
    }
    setIsLoaading(false)
  }

  return (
    <View as={SafeAreaView} style={styles.container}>
      {post ? (
        <>
          <FlatList
            ref={flatListRef}
            data={post.comments.sort((a, b) => a.created < b.created)}
            refreshing={isLoading}
            onRefresh={() => getPostData()}
            keyExtractor={item => item.id}
            ListHeaderComponent={
              <Post
                postId={post.id}
                userId={authState.userInfo.id}
                score={post.score}
                type={post.type}
                title={post.title}
                author={post.author}
                category={post.category}
                text={post.text}
                comments={post.comments}
                created={post.created}
                url={post.url}
                votes={post.votes}
                views={post.views}
                setIsLoaading={setIsLoaading}
                setData={setPost}
                postType="item"
                deleteButton={true}
                deletePost={() => deletePost(post.id)}
              />
            }
            ListHeaderComponentStyle={styles.headerComponentStyle}
            renderItem={({ item, index }) => (
              <CommentListItem
                body={item.body}
                author={item.author}
                created={item.created}
                deleteComment={() => deleteComment(item.id)}
              />
            )}
          />
          {authState.token && (
            <CreateComment
              onPress={createComment}
              setComment={setComment}
              setIsFocused={setIsFocused}
              comment={comment}
            />
          )}
        </>
      ) : (
        <>
          <PostLoader />
          {comments.map(i => (
            <CommentLoader key={i.id} />
          ))}
        </>
      )}
    </View>
  )
}
Example #28
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 #29
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>
  )
}