wait for list memberships to load before becoming interactive (#1140)
* wait for list memberships to load before becoming interactive * add spinner * remove secondary spinnerzio/stable
parent
b5511e1450
commit
48813a96d6
|
@ -1,6 +1,5 @@
|
||||||
import React, {MutableRefObject} from 'react'
|
import React, {MutableRefObject} from 'react'
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
|
||||||
RefreshControl,
|
RefreshControl,
|
||||||
StyleProp,
|
StyleProp,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
|
@ -166,18 +165,6 @@ export const ListsList = observer(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
const Footer = React.useCallback(
|
|
||||||
() =>
|
|
||||||
listsList.isLoading ? (
|
|
||||||
<View style={styles.feedFooter}>
|
|
||||||
<ActivityIndicator />
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<View />
|
|
||||||
),
|
|
||||||
[listsList],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={style}>
|
<View testID={testID} style={style}>
|
||||||
{data.length > 0 && (
|
{data.length > 0 && (
|
||||||
|
@ -187,7 +174,6 @@ export const ListsList = observer(
|
||||||
data={data}
|
data={data}
|
||||||
keyExtractor={item => item._reactKey}
|
keyExtractor={item => item._reactKey}
|
||||||
renderItem={renderItemInner}
|
renderItem={renderItemInner}
|
||||||
ListFooterComponent={Footer}
|
|
||||||
refreshControl={
|
refreshControl={
|
||||||
<RefreshControl
|
<RefreshControl
|
||||||
refreshing={isRefreshing}
|
refreshing={isRefreshing}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, {useCallback} from 'react'
|
import React, {useCallback} from 'react'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {Pressable, StyleSheet, View} from 'react-native'
|
import {Pressable, StyleSheet, View, ActivityIndicator} from 'react-native'
|
||||||
import {AppBskyGraphDefs as GraphDefs} from '@atproto/api'
|
import {AppBskyGraphDefs as GraphDefs} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
|
@ -42,6 +42,7 @@ export const Component = observer(
|
||||||
string[]
|
string[]
|
||||||
>([])
|
>([])
|
||||||
const [selected, setSelected] = React.useState<string[]>([])
|
const [selected, setSelected] = React.useState<string[]>([])
|
||||||
|
const [membershipsLoaded, setMembershipsLoaded] = React.useState(false)
|
||||||
|
|
||||||
const listsList: ListsListModel = React.useMemo(
|
const listsList: ListsListModel = React.useMemo(
|
||||||
() => new ListsListModel(store, store.me.did),
|
() => new ListsListModel(store, store.me.did),
|
||||||
|
@ -58,12 +59,13 @@ export const Component = observer(
|
||||||
const ids = memberships.memberships.map(m => m.value.list)
|
const ids = memberships.memberships.map(m => m.value.list)
|
||||||
setOriginalSelections(ids)
|
setOriginalSelections(ids)
|
||||||
setSelected(ids)
|
setSelected(ids)
|
||||||
|
setMembershipsLoaded(true)
|
||||||
},
|
},
|
||||||
err => {
|
err => {
|
||||||
store.log.error('Failed to fetch memberships', {err})
|
store.log.error('Failed to fetch memberships', {err})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}, [memberships, listsList, store, setSelected])
|
}, [memberships, listsList, store, setSelected, setMembershipsLoaded])
|
||||||
|
|
||||||
const onPressCancel = useCallback(() => {
|
const onPressCancel = useCallback(() => {
|
||||||
store.shell.closeModal()
|
store.shell.closeModal()
|
||||||
|
@ -107,11 +109,16 @@ export const Component = observer(
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
testID={`toggleBtn-${list.name}`}
|
testID={`toggleBtn-${list.name}`}
|
||||||
style={[styles.listItem, pal.border]}
|
style={[
|
||||||
|
styles.listItem,
|
||||||
|
pal.border,
|
||||||
|
{opacity: membershipsLoaded ? 1 : 0.5},
|
||||||
|
]}
|
||||||
accessibilityLabel={`${isSelected ? 'Remove from' : 'Add to'} ${
|
accessibilityLabel={`${isSelected ? 'Remove from' : 'Add to'} ${
|
||||||
list.name
|
list.name
|
||||||
}`}
|
}`}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
|
disabled={!membershipsLoaded}
|
||||||
onPress={() => onToggleSelected(list.uri)}>
|
onPress={() => onToggleSelected(list.uri)}>
|
||||||
<View style={styles.listItemAvi}>
|
<View style={styles.listItemAvi}>
|
||||||
<UserAvatar size={40} avatar={list.avatar} />
|
<UserAvatar size={40} avatar={list.avatar} />
|
||||||
|
@ -132,23 +139,33 @@ export const Component = observer(
|
||||||
: sanitizeHandle(list.creator.handle, '@')}
|
: sanitizeHandle(list.creator.handle, '@')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
{membershipsLoaded && (
|
||||||
style={
|
<View
|
||||||
isSelected
|
style={
|
||||||
? [styles.checkbox, palPrimary.border, palPrimary.view]
|
isSelected
|
||||||
: [styles.checkbox, pal.borderDark]
|
? [styles.checkbox, palPrimary.border, palPrimary.view]
|
||||||
}>
|
: [styles.checkbox, pal.borderDark]
|
||||||
{isSelected && (
|
}>
|
||||||
<FontAwesomeIcon
|
{isSelected && (
|
||||||
icon="check"
|
<FontAwesomeIcon
|
||||||
style={palInverted.text as FontAwesomeIconStyle}
|
icon="check"
|
||||||
/>
|
style={palInverted.text as FontAwesomeIconStyle}
|
||||||
)}
|
/>
|
||||||
</View>
|
)}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[pal, palPrimary, palInverted, onToggleSelected, selected, store.me.did],
|
[
|
||||||
|
pal,
|
||||||
|
palPrimary,
|
||||||
|
palInverted,
|
||||||
|
onToggleSelected,
|
||||||
|
selected,
|
||||||
|
store.me.did,
|
||||||
|
membershipsLoaded,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
const renderEmptyState = React.useCallback(() => {
|
const renderEmptyState = React.useCallback(() => {
|
||||||
|
@ -200,6 +217,12 @@ export const Component = observer(
|
||||||
label="Save Changes"
|
label="Save Changes"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{(listsList.isLoading || !membershipsLoaded) && (
|
||||||
|
<View style={styles.loadingContainer}>
|
||||||
|
<ActivityIndicator />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -221,6 +244,7 @@ const styles = StyleSheet.create({
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
},
|
},
|
||||||
btns: {
|
btns: {
|
||||||
|
position: 'relative',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
@ -263,4 +287,11 @@ const styles = StyleSheet.create({
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
|
loadingContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 10,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue