Skip to content

Commit d0d7447

Browse files
committed
chore: loading state during broadcasting
Signed-off-by: iuricmp <[email protected]>
1 parent d50175f commit d0d7447

File tree

16 files changed

+718
-81
lines changed

16 files changed

+718
-81
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react'
2+
import {
3+
BroadcastingFailedView,
4+
BroadcastingSuccessView,
5+
BroadcastingUndefinedView,
6+
BroadcastingView,
7+
Layout
8+
} from '@/components'
9+
import { selectBroadcastResponse, selectBroadcastStatus, useAppSelector } from '@/redux'
10+
import { useRouter } from 'expo-router'
11+
12+
export default function Page() {
13+
const broadcastStatus = useAppSelector(selectBroadcastStatus)
14+
const txResponse = useAppSelector(selectBroadcastResponse)
15+
16+
const router = useRouter()
17+
18+
const goHome = () => router.push('/home')
19+
20+
return (
21+
<Layout.Container>
22+
<Layout.Body>
23+
{!broadcastStatus || broadcastStatus === undefined ? <BroadcastingUndefinedView onCancel={goHome} /> : null}
24+
{broadcastStatus === 'pending' ? <BroadcastingView /> : null}
25+
{broadcastStatus === 'rejected' ? <BroadcastingFailedView txResponse={txResponse} onCancel={goHome} /> : null}
26+
{broadcastStatus === 'fulfilled' ? <BroadcastingSuccessView txResponse={txResponse} onDone={goHome} /> : null}
27+
</Layout.Body>
28+
</Layout.Container>
29+
)
30+
}

mobile/app/(app)/tosign/index.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@ import {
1414
clearLinking,
1515
selectChainId,
1616
selectRemote,
17-
selectBroadcast
17+
selectBroadcast,
18+
broadcastTx
1819
} from '@/redux'
1920
import { useGnoNativeContext } from '@gnolang/gnonative'
2021
import { router } from 'expo-router'
2122
import { useEffect, useState } from 'react'
2223
import * as Linking from 'expo-linking'
23-
import { ScrollView, View, TouchableOpacity, Text as RNText, Alert } from 'react-native'
24-
import { Button, ButtonText, FormItem, FormItemInline, Spacer, Text } from '@/modules/ui-components'
24+
import { ScrollView, View, TouchableOpacity, Alert } from 'react-native'
25+
import { Button, ButtonText, FormItem, FormItemInline, PrettyJSON, Spacer, Text } from '@/modules/ui-components'
2526
import styled from 'styled-components/native'
26-
import PrettyJSON from '../../../modules/ui-components/src/ui/PrettyJSON'
2727

2828
export default function Page() {
2929
const [loading, setLoading] = useState(false)
@@ -103,9 +103,8 @@ export default function Page() {
103103
Alert.alert('No signedTx')
104104
return
105105
}
106-
const res = await gnonative.broadcastTxCommit(signedTx)
107-
console.log('broadcasting the tx', signedTx, res)
108-
router.push('/home')
106+
dispatch(broadcastTx({ signedTx }))
107+
router.push('/tosign/broadcasting')
109108
return
110109
}
111110

@@ -173,6 +172,13 @@ export default function Page() {
173172
<Spacer space={32} />
174173

175174
<ScrollView contentContainerStyle={{}}>
175+
<Ruller />
176+
<FormItemInline label="Signature Verification">
177+
<View style={{ backgroundColor: 'white', width: 100, borderRadius: 20, alignContent: 'center', padding: 2 }}>
178+
<Text.Body style={{ color: 'red', textAlign: 'center' }}>Unverified</Text.Body>
179+
</View>
180+
</FormItemInline>
181+
176182
<Ruller />
177183

178184
<FormItem label="Client name">

mobile/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const Layout = { Container, Header, Body, BodyAlignedBotton, Footer }
88
export * from './controls/toggle/Toggle'
99
export * from './items'
1010
export * from './shared-components/UnifiedText'
11+
export * from './view'
1112

1213
export { default as TextCopy } from './text/text-copy'
1314
export { default as ModalHeader } from './modal/ModalHeader'

mobile/components/view/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { BroadcastingView } from './tx/broadcastingView'
2+
export { BroadcastingFailedView } from './tx/broadcastingFailedView'
3+
export { BroadcastingSuccessView } from './tx/broadcastingSuccessView'
4+
export { BroadcastingUndefinedView } from './tx/broadcastingUndefinedView'
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { Button, PrettyJSON, Spacer, Text } from '@/modules/ui-components'
2+
import React, { useEffect, useRef, useState } from 'react'
3+
import { View, Animated, Easing, StyleSheet, Vibration } from 'react-native'
4+
5+
interface Prop {
6+
onCancel: () => void
7+
txResponse?: string
8+
}
9+
10+
export function BroadcastingFailedView({ onCancel = () => {}, txResponse = '' }: Prop) {
11+
const shakeAnim = useRef(new Animated.Value(0)).current
12+
const fadeAnim = useRef(new Animated.Value(1)).current
13+
const scaleAnim = useRef(new Animated.Value(1)).current
14+
15+
const [details, showDetails] = useState(false)
16+
17+
useEffect(() => {
18+
Vibration.vibrate(500)
19+
20+
Animated.sequence([
21+
Animated.parallel([
22+
Animated.sequence([
23+
Animated.timing(shakeAnim, {
24+
toValue: 10,
25+
duration: 100,
26+
useNativeDriver: true
27+
}),
28+
Animated.timing(shakeAnim, {
29+
toValue: -10,
30+
duration: 100,
31+
useNativeDriver: true
32+
}),
33+
Animated.timing(shakeAnim, {
34+
toValue: 6,
35+
duration: 100,
36+
useNativeDriver: true
37+
}),
38+
Animated.timing(shakeAnim, {
39+
toValue: -6,
40+
duration: 100,
41+
useNativeDriver: true
42+
}),
43+
Animated.timing(shakeAnim, {
44+
toValue: 0,
45+
duration: 100,
46+
useNativeDriver: true
47+
})
48+
]),
49+
Animated.sequence([
50+
Animated.timing(scaleAnim, {
51+
toValue: 1.2,
52+
duration: 300,
53+
useNativeDriver: true
54+
}),
55+
Animated.timing(scaleAnim, {
56+
toValue: 1,
57+
duration: 300,
58+
useNativeDriver: true
59+
})
60+
])
61+
]),
62+
Animated.timing(fadeAnim, {
63+
toValue: 1,
64+
duration: 500,
65+
easing: Easing.out(Easing.ease),
66+
useNativeDriver: true
67+
})
68+
]).start()
69+
// eslint-disable-next-line react-hooks/exhaustive-deps
70+
}, [])
71+
72+
return (
73+
<View style={styles.container}>
74+
<View style={styles.center}>
75+
<Animated.View
76+
style={[
77+
styles.xCircle,
78+
{
79+
transform: [{ translateX: shakeAnim }, { scale: scaleAnim }],
80+
opacity: fadeAnim
81+
}
82+
]}
83+
>
84+
<Text.Body style={styles.statusText}></Text.Body>
85+
</Animated.View>
86+
</View>
87+
<Text.Body style={styles.statusText}>Transaction Failed</Text.Body>
88+
<Spacer space={56} />
89+
<Button color="tertirary" onPress={() => showDetails(!details)}>
90+
Show details...
91+
</Button>
92+
93+
{details && <PrettyJSON data={JSON.parse(txResponse)} />}
94+
95+
<View style={styles.middleScreen}>
96+
<View style={styles.botton}>
97+
<Button color="primary" onPress={onCancel}>
98+
Try Again
99+
</Button>
100+
</View>
101+
</View>
102+
</View>
103+
)
104+
}
105+
const styles = StyleSheet.create({
106+
container: {
107+
flex: 1,
108+
paddingTop: 120
109+
},
110+
middleScreen: {
111+
flex: 1,
112+
alignContent: 'flex-end',
113+
marginTop: 42
114+
},
115+
center: {
116+
alignItems: 'center',
117+
textAlign: 'center'
118+
},
119+
failedText: {
120+
fontSize: 18,
121+
fontWeight: '600',
122+
marginTop: 10
123+
},
124+
xCircle: {
125+
width: 80,
126+
height: 80,
127+
backgroundColor: '#e74c3c',
128+
borderRadius: 40,
129+
justifyContent: 'center',
130+
alignItems: 'center',
131+
shadowColor: '#e74c3c',
132+
shadowOpacity: 0.4,
133+
shadowRadius: 10,
134+
shadowOffset: { width: 0, height: 4 },
135+
marginBottom: 20
136+
},
137+
statusText: {
138+
color: '#fff',
139+
fontWeight: 'bold',
140+
textAlign: 'center'
141+
},
142+
botton: {
143+
flex: 1,
144+
alignContent: 'center',
145+
justifyContent: 'flex-end'
146+
}
147+
})
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Text } from '@/modules/ui-components'
2+
import React from 'react'
3+
import { StyleSheet, View } from 'react-native'
4+
5+
type Props = {
6+
title: string
7+
iconView: React.ReactNode
8+
actions?: React.ReactNode
9+
details?: React.ReactNode
10+
}
11+
12+
export const BroadcastingLayout = ({ title = 'Title', iconView = null, actions = null, details = null }: Props) => {
13+
return (
14+
<View style={styles.container}>
15+
<View style={styles.centerView}>
16+
<View style={styles.title}>
17+
<Text.H3>{title}</Text.H3>
18+
</View>
19+
<View style={styles.iconView}>{iconView}</View>
20+
</View>
21+
22+
<View style={styles.details}>{details}</View>
23+
24+
<View style={styles.actions}>{actions}</View>
25+
</View>
26+
)
27+
}
28+
29+
const styles = StyleSheet.create({
30+
container: {
31+
flex: 1,
32+
alignContent: 'center',
33+
paddingTop: 80
34+
},
35+
centerView: {
36+
alignItems: 'center'
37+
},
38+
title: {},
39+
iconView: {
40+
marginTop: 40
41+
},
42+
details: {
43+
flex: 1
44+
},
45+
actions: {}
46+
})

0 commit comments

Comments
 (0)