Ensure the UI always renders, even in bad network conditions (close #6)

This commit is contained in:
Paul Frazee 2022-12-05 13:25:04 -06:00
parent 59363181e1
commit f27e32e54c
13 changed files with 259 additions and 72 deletions

View file

@ -1,14 +1,21 @@
import React from 'react'
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
import {observer} from 'mobx-react-lite'
import {
ActivityIndicator,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {colors} from '../../lib/styles'
import {s, colors} from '../../lib/styles'
import {MagnifyingGlassIcon} from '../../lib/icons'
import {useStores} from '../../../state'
const HITSLOP = {left: 10, top: 10, right: 10, bottom: 10}
const BACK_HITSLOP = {left: 10, top: 10, right: 30, bottom: 10}
export function ViewHeader({
export const ViewHeader = observer(function ViewHeader({
title,
subtitle,
onPost,
@ -27,43 +34,91 @@ export function ViewHeader({
const onPressSearch = () => {
store.nav.navigate(`/search`)
}
const onPressReconnect = () => {
store.session.connect().catch(e => {
// log for debugging but ignore otherwise
console.log(e)
})
}
return (
<View style={styles.header}>
{store.nav.tab.canGoBack ? (
<>
<View style={styles.header}>
{store.nav.tab.canGoBack ? (
<TouchableOpacity
onPress={onPressBack}
hitSlop={BACK_HITSLOP}
style={styles.backIcon}>
<FontAwesomeIcon
size={18}
icon="angle-left"
style={{marginTop: 6}}
/>
</TouchableOpacity>
) : undefined}
<View style={styles.titleContainer} pointerEvents="none">
<Text style={styles.title}>{title}</Text>
{subtitle ? (
<Text style={styles.subtitle} numberOfLines={1}>
{subtitle}
</Text>
) : undefined}
</View>
<TouchableOpacity
onPress={onPressBack}
hitSlop={BACK_HITSLOP}
style={styles.backIcon}>
<FontAwesomeIcon size={18} icon="angle-left" style={{marginTop: 6}} />
onPress={onPressCompose}
hitSlop={HITSLOP}
style={styles.btn}>
<FontAwesomeIcon size={18} icon="plus" />
</TouchableOpacity>
<TouchableOpacity
onPress={onPressSearch}
hitSlop={HITSLOP}
style={[styles.btn, {marginLeft: 8}]}>
<MagnifyingGlassIcon
size={18}
strokeWidth={3}
style={styles.searchBtnIcon}
/>
</TouchableOpacity>
</View>
{!store.session.online ? (
<TouchableOpacity style={styles.offline} onPress={onPressReconnect}>
{store.session.attemptingConnect ? (
<>
<ActivityIndicator />
<Text style={[s.gray1, s.bold, s.flex1, s.pl5, s.pt5, s.pb5]}>
Connecting...
</Text>
</>
) : (
<>
<FontAwesomeIcon icon="signal" style={[s.gray2]} size={18} />
<FontAwesomeIcon
icon="x"
style={[
s.red4,
{
backgroundColor: colors.gray6,
position: 'relative',
left: -4,
top: 6,
},
]}
border
size={12}
/>
<Text style={[s.gray1, s.bold, s.flex1, s.pl2]}>
Unable to connect
</Text>
<View style={styles.offlineBtn}>
<Text style={styles.offlineBtnText}>Try again</Text>
</View>
</>
)}
</TouchableOpacity>
) : undefined}
<View style={styles.titleContainer} pointerEvents="none">
<Text style={styles.title}>{title}</Text>
{subtitle ? (
<Text style={styles.subtitle} numberOfLines={1}>
{subtitle}
</Text>
) : undefined}
</View>
<TouchableOpacity
onPress={onPressCompose}
hitSlop={HITSLOP}
style={styles.btn}>
<FontAwesomeIcon size={18} icon="plus" />
</TouchableOpacity>
<TouchableOpacity
onPress={onPressSearch}
hitSlop={HITSLOP}
style={[styles.btn, {marginLeft: 8}]}>
<MagnifyingGlassIcon
size={18}
strokeWidth={3}
style={styles.searchBtnIcon}
/>
</TouchableOpacity>
</View>
</>
)
}
})
const styles = StyleSheet.create({
header: {
@ -108,4 +163,26 @@ const styles = StyleSheet.create({
position: 'relative',
top: -1,
},
offline: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: colors.gray6,
paddingLeft: 15,
paddingRight: 10,
paddingVertical: 8,
borderRadius: 8,
marginHorizontal: 4,
marginTop: 4,
},
offlineBtn: {
backgroundColor: colors.gray5,
borderRadius: 5,
paddingVertical: 5,
paddingHorizontal: 10,
},
offlineBtnText: {
color: colors.white,
fontWeight: 'bold',
},
})