add processing state to button
This commit is contained in:
@@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user