diff options
Diffstat (limited to 'src/view/screens')
-rw-r--r-- | src/view/screens/Contacts.tsx | 5 | ||||
-rw-r--r-- | src/view/screens/Home.tsx | 53 | ||||
-rw-r--r-- | src/view/screens/Login.tsx | 12 | ||||
-rw-r--r-- | src/view/screens/NotFound.tsx | 8 | ||||
-rw-r--r-- | src/view/screens/Profile.tsx | 8 | ||||
-rw-r--r-- | src/view/screens/Search.tsx | 3 |
6 files changed, 53 insertions, 36 deletions
diff --git a/src/view/screens/Contacts.tsx b/src/view/screens/Contacts.tsx index 8de56d79a..b22e52fe5 100644 --- a/src/view/screens/Contacts.tsx +++ b/src/view/screens/Contacts.tsx @@ -25,7 +25,9 @@ export const Contacts = ({navIdx, visible, params}: ScreenParams) => { return ( <View> <View style={styles.section}> - <Text style={styles.title}>Contacts</Text> + <Text testID="contactsTitle" style={styles.title}> + Contacts + </Text> </View> <View style={styles.section}> <View style={styles.searchContainer}> @@ -35,6 +37,7 @@ export const Contacts = ({navIdx, visible, params}: ScreenParams) => { style={styles.searchIcon} /> <TextInput + testID="contactsTextInput" ref={inputRef} value={searchText} style={styles.searchInput} diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index d5fe7f1f9..9800c6846 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react' +import React, {useEffect} from 'react' import {StyleSheet, TouchableOpacity, View} from 'react-native' import {observer} from 'mobx-react-lite' import useAppState from 'react-native-appstate-hook' @@ -24,48 +24,48 @@ export const Home = observer(function Home({ const store = useStores() const onMainScroll = useOnMainScroll(store) const safeAreaInsets = useSafeAreaInsets() - const [hasSetup, setHasSetup] = useState<boolean>(false) + const [wasVisible, setWasVisible] = React.useState<boolean>(false) const {appState} = useAppState({ onForeground: () => doPoll(true), }) - const doPoll = (knownActive = false) => { - if ((!knownActive && appState !== 'active') || !visible) { - return - } - if (store.me.mainFeed.isLoading) { - return - } - store.log.debug('Polling home feed') - store.me.mainFeed.checkForLatest().catch(e => { - store.log.error('Failed to poll feed', e) - }) - } + const doPoll = React.useCallback( + (knownActive = false) => { + if ((!knownActive && appState !== 'active') || !visible) { + return + } + if (store.me.mainFeed.isLoading) { + return + } + store.log.debug('Polling home feed') + store.me.mainFeed.checkForLatest().catch(e => { + store.log.error('Failed to poll feed', e) + }) + }, + [appState, visible, store], + ) useEffect(() => { - let aborted = false const pollInterval = setInterval(() => doPoll(), 15e3) if (!visible) { + setWasVisible(false) + return + } else if (wasVisible) { return } + setWasVisible(true) - if (hasSetup) { - store.log.debug('Updating home feed') + store.nav.setTitle(navIdx, 'Home') + store.log.debug('Updating home feed') + if (store.me.mainFeed.hasContent) { store.me.mainFeed.update() - doPoll() } else { - store.nav.setTitle(navIdx, 'Home') - store.log.debug('Fetching home feed') - store.me.mainFeed.setup().then(() => { - if (aborted) return - setHasSetup(true) - }) + store.me.mainFeed.setup() } return () => { clearInterval(pollInterval) - aborted = true } - }, [visible, store]) + }, [visible, store, navIdx, doPoll, wasVisible]) const onPressCompose = () => { store.shell.openComposer({}) @@ -82,6 +82,7 @@ export const Home = observer(function Home({ <View style={s.flex1}> <ViewHeader title="Bluesky" subtitle="Private Beta" canGoBack={false} /> <Feed + testID="homeFeed" key="default" feed={store.me.mainFeed} scrollElRef={scrollElRef} diff --git a/src/view/screens/Login.tsx b/src/view/screens/Login.tsx index 0315e287e..8363dbfe0 100644 --- a/src/view/screens/Login.tsx +++ b/src/view/screens/Login.tsx @@ -35,8 +35,11 @@ const SigninOrCreateAccount = ({ <Text style={styles.title}>Bluesky</Text> <Text style={styles.subtitle}>[ private beta ]</Text> </View> - <View style={s.flex1}> - <TouchableOpacity style={styles.btn} onPress={onPressCreateAccount}> + <View testID="signinOrCreateAccount" style={s.flex1}> + <TouchableOpacity + testID="createAccountButton" + style={styles.btn} + onPress={onPressCreateAccount}> <Text style={styles.btnLabel}>Create a new account</Text> </TouchableOpacity> <View style={styles.or}> @@ -60,7 +63,10 @@ const SigninOrCreateAccount = ({ </Svg> <Text style={styles.orLabel}>or</Text> </View> - <TouchableOpacity style={styles.btn} onPress={onPressSignin}> + <TouchableOpacity + testID="signInButton" + style={styles.btn} + onPress={onPressSignin}> <Text style={styles.btnLabel}>Sign in</Text> </TouchableOpacity> </View> diff --git a/src/view/screens/NotFound.tsx b/src/view/screens/NotFound.tsx index 3591b696c..79477fa9b 100644 --- a/src/view/screens/NotFound.tsx +++ b/src/view/screens/NotFound.tsx @@ -7,7 +7,7 @@ import {useStores} from '../../state' export const NotFound = () => { const stores = useStores() return ( - <View> + <View testID="notFoundView"> <ViewHeader title="Page not found" /> <View style={{ @@ -16,7 +16,11 @@ export const NotFound = () => { paddingTop: 100, }}> <Text style={{fontSize: 40, fontWeight: 'bold'}}>Page not found</Text> - <Button title="Home" onPress={() => stores.nav.navigate('/')} /> + <Button + testID="navigateHomeButton" + title="Home" + onPress={() => stores.nav.navigate('/')} + /> </View> </View> ) diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index c89c2ad13..64bb4f042 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useState, useMemo} from 'react' +import React, {useEffect, useState} from 'react' import {ActivityIndicator, StyleSheet, View} from 'react-native' import {observer} from 'mobx-react-lite' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' @@ -30,7 +30,7 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => { const store = useStores() const onMainScroll = useOnMainScroll(store) const [hasSetup, setHasSetup] = useState<boolean>(false) - const uiState = useMemo( + const uiState = React.useMemo( () => new ProfileUiModel(store, {user: params.name}), [params.user], ) @@ -201,6 +201,7 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => { ? () => ( <> <FontAwesomeIcon + testID="shouldAdminButton" icon="user-xmark" style={[s.mr5]} size={14} @@ -242,10 +243,11 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => { const title = uiState.profile.displayName || uiState.profile.handle || params.name return ( - <View style={styles.container}> + <View testID="profileView" style={styles.container}> <ViewHeader title={title} /> {uiState.profile.hasError ? ( <ErrorScreen + testID="profileErrorScreen" title="Failed to load profile" message={`There was an issue when attempting to load ${params.name}`} details={uiState.profile.error} diff --git a/src/view/screens/Search.tsx b/src/view/screens/Search.tsx index d9d933b7e..5844aa11d 100644 --- a/src/view/screens/Search.tsx +++ b/src/view/screens/Search.tsx @@ -57,6 +57,7 @@ export const Search = ({navIdx, visible, params}: ScreenParams) => { <View style={[pal.view, pal.border, styles.inputContainer]}> <MagnifyingGlassIcon style={[pal.text, styles.inputIcon]} /> <TextInput + testID="searchTextInput" ref={textInput} placeholder="Type your query here..." placeholderTextColor={pal.colors.textLight} @@ -68,7 +69,7 @@ export const Search = ({navIdx, visible, params}: ScreenParams) => { </View> <View style={styles.outputContainer}> {query ? ( - <ScrollView onScroll={Keyboard.dismiss}> + <ScrollView testID="searchScrollView" onScroll={Keyboard.dismiss}> {autocompleteView.searchRes.map((item, i) => ( <TouchableOpacity key={i} |