add processing state to button

This commit is contained in:
Hailey
2024-06-06 20:59:31 -07:00
parent 2ea6501e6f
commit 3ebdccfce2
2 changed files with 97 additions and 98 deletions
+2 -62
View File
@@ -2,8 +2,6 @@ import React from 'react'
import {AppBskyActorDefs} from '@atproto/api' import {AppBskyActorDefs} from '@atproto/api'
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
import {useAgent, useSession} from 'state/session'
const steps = ['Details', 'Profiles', 'Feeds'] as const const steps = ['Details', 'Profiles', 'Feeds'] as const
type Step = (typeof steps)[number] type Step = (typeof steps)[number]
@@ -30,12 +28,11 @@ interface State {
processing: boolean processing: boolean
} }
type TStateContext = [State, (action: Action) => void, () => Promise<void>] type TStateContext = [State, (action: Action) => void]
const StateContext = React.createContext<TStateContext>([ const StateContext = React.createContext<TStateContext>([
{} as State, {} as State,
(_: Action) => {}, (_: Action) => {},
async () => {},
]) ])
export const useWizardState = () => React.useContext(StateContext) export const useWizardState = () => React.useContext(StateContext)
@@ -110,9 +107,6 @@ export function Provider({
initialStep?: Step initialStep?: Step
children: React.ReactNode children: React.ReactNode
}) { }) {
const agent = useAgent()
const {currentAccount} = useSession()
const [state, dispatch] = React.useReducer( const [state, dispatch] = React.useReducer(
reducer, reducer,
initialState initialState
@@ -129,62 +123,8 @@ export function Provider({
}, },
) )
const submit = async () => {
dispatch({type: 'SetProcessing', processing: true})
try {
const list = await agent.app.bsky.graph.list.create(
{repo: currentAccount?.did},
{
name: state.name ?? '',
description: state.description ?? '',
descriptionFacets: [],
avatar: undefined,
createdAt: new Date().toISOString(),
purpose: 'app.bsky.graph.defs#referencelist',
},
)
await agent.com.atproto.repo.applyWrites({
repo: currentAccount!.did,
writes: state.profiles.map(p => ({
$type: 'com.atproto.repo.applyWrites#create',
collection: 'app.bsky.graph.listitem',
value: {
$type: 'app.bsky.graph.listitem',
subject: p.did,
list: list.uri,
createdAt: new Date().toISOString(),
},
})),
})
await agent.app.bsky.graph.starterpack.create(
{
repo: currentAccount!.did,
validate: false,
},
{
name: state.name ?? '',
description: state.description ?? '',
descriptionFacets: [],
list: list.uri,
feeds: state.feeds.map(f => ({
uri: f.uri,
})),
createdAt: new Date().toISOString(),
},
)
} catch (e) {
// TODO add error to state
console.error(e)
} finally {
dispatch({type: 'SetProcessing', processing: false})
}
}
return ( return (
<StateContext.Provider value={[state, dispatch, submit]}> <StateContext.Provider value={[state, dispatch]}>
{children} {children}
</StateContext.Provider> </StateContext.Provider>
) )
+75 -16
View File
@@ -1,18 +1,20 @@
import React from 'react' import React from 'react'
import {Keyboard, View} from 'react-native' import {Keyboard, TouchableOpacity, View} from 'react-native'
import {KeyboardAwareScrollView} from 'react-native-keyboard-controller' import {KeyboardAwareScrollView} from 'react-native-keyboard-controller'
import {AppBskyActorDefs} from '@atproto/api' import {AppBskyActorDefs} from '@atproto/api'
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg, Plural, Trans} from '@lingui/macro' import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useFocusEffect, useNavigation} from '@react-navigation/native' import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {HITSLOP_10} from 'lib/constants'
import {CommonNavigatorParams, NavigationProp} from 'lib/routes/types' import {CommonNavigatorParams, NavigationProp} from 'lib/routes/types'
import {enforceLen} from 'lib/strings/helpers' import {enforceLen} from 'lib/strings/helpers'
import {isAndroid, isWeb} from 'platform/detection' import {isAndroid, isWeb} from 'platform/detection'
import {useProfileQuery} from 'state/queries/profile' import {useProfileQuery} from 'state/queries/profile'
import {useSession} from 'state/session' import {useAgent, useSession} from 'state/session'
import {useSetMinimalShellMode} from 'state/shell' import {useSetMinimalShellMode} from 'state/shell'
import {UserAvatar} from 'view/com/util/UserAvatar' import {UserAvatar} from 'view/com/util/UserAvatar'
import {CenteredView} from 'view/com/util/Views' import {CenteredView} from 'view/com/util/Views'
@@ -23,6 +25,7 @@ import {StepProfiles} from '#/screens/StarterPack/Wizard/StepProfiles'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog' import {useDialogControl} from '#/components/Dialog'
import {Loader} from '#/components/Loader'
import {WizardEditListDialog} from '#/components/StarterPack/Wizard/WizardEditListDialog' import {WizardEditListDialog} from '#/components/StarterPack/Wizard/WizardEditListDialog'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {Provider} from './State' import {Provider} from './State'
@@ -75,7 +78,8 @@ function WizardInner() {
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {_} = useLingui() const {_} = useLingui()
const t = useTheme() const t = useTheme()
const [state, dispatch, submit] = useWizardState() const [state, dispatch] = useWizardState()
const agent = useAgent()
const {currentAccount} = useSession() const {currentAccount} = useSession()
const {data: currentProfile} = useProfileQuery({ const {data: currentProfile} = useProfileQuery({
did: currentAccount?.did, did: currentAccount?.did,
@@ -121,6 +125,62 @@ function WizardInner() {
const uiStrings = wizardUiStrings[state.currentStep] const uiStrings = wizardUiStrings[state.currentStep]
const submit = async () => {
dispatch({type: 'SetProcessing', processing: true})
try {
const list = await agent.app.bsky.graph.list.create(
{repo: currentAccount?.did},
{
name: state.name ?? '',
description: state.description ?? '',
descriptionFacets: [],
avatar: undefined,
createdAt: new Date().toISOString(),
purpose: 'app.bsky.graph.defs#referencelist',
},
)
await agent.com.atproto.repo.applyWrites({
repo: currentAccount!.did,
writes: state.profiles.map(p => ({
$type: 'com.atproto.repo.applyWrites#create',
collection: 'app.bsky.graph.listitem',
value: {
$type: 'app.bsky.graph.listitem',
subject: p.did,
list: list.uri,
createdAt: new Date().toISOString(),
},
})),
})
const res = await agent.app.bsky.graph.starterpack.create(
{
repo: currentAccount!.did,
validate: false,
},
{
name: state.name ?? '',
description: state.description ?? '',
descriptionFacets: [],
list: list.uri,
feeds: state.feeds.map(f => ({
uri: f.uri,
})),
createdAt: new Date().toISOString(),
},
)
navigation.navigate('StarterPack', {id: res.uri})
} catch (e) {
// TODO add error to state
console.error(e)
} finally {
// dispatch({type: 'SetProcessing', processing: false})
}
}
const onNext = () => { const onNext = () => {
if (state.currentStep === 'Details' && !state.name) { if (state.currentStep === 'Details' && !state.name) {
dispatch({ dispatch({
@@ -146,7 +206,6 @@ function WizardInner() {
return ( return (
<CenteredView style={[a.flex_1]} sideBorders> <CenteredView style={[a.flex_1]} sideBorders>
<View style={[]}>
<View <View
style={[ style={[
a.flex_row, a.flex_row,
@@ -162,16 +221,15 @@ function WizardInner() {
]}> ]}>
<View style={[{width: 65}]}> <View style={[{width: 65}]}>
{state.currentStep !== 'Details' && ( {state.currentStep !== 'Details' && (
<Button <TouchableOpacity
label={_(msg`Back`)} testID="viewHeaderDrawerBtn"
variant="ghost" onPress={() => dispatch({type: 'Back'})}
color="secondary" hitSlop={HITSLOP_10}
size="xsmall" accessibilityRole="button"
onPress={() => dispatch({type: 'Back'})}> accessibilityLabel={_(msg`Back`)}
<ButtonText> accessibilityHint={_(msg`Go back to the previous step`)}>
<Trans>Back</Trans> <FontAwesomeIcon size={18} icon="angle-left" />
</ButtonText> </TouchableOpacity>
</Button>
)} )}
</View> </View>
<Text style={[a.flex_1, a.font_bold, a.text_lg, a.text_center]}> <Text style={[a.flex_1, a.font_bold, a.text_lg, a.text_center]}>
@@ -179,7 +237,6 @@ function WizardInner() {
</Text> </Text>
<View style={[{width: 65}]} /> <View style={[{width: 65}]} />
</View> </View>
</View>
<Container> <Container>
<StepView /> <StepView />
@@ -348,8 +405,10 @@ function Footer({
variant="solid" variant="solid"
color="primary" color="primary"
size="small" size="small"
onPress={onNext}> onPress={onNext}
disabled={state.canNext || state.processing}>
<ButtonText>{nextBtnText}</ButtonText> <ButtonText>{nextBtnText}</ButtonText>
<Loader size="xs" style={{color: 'white'}} />
</Button> </Button>
</View> </View>