Compare commits

...

2 Commits

Author SHA1 Message Date
Ivan Vershigora
b191c043f7
fix: message type 2026-05-13 14:46:06 +01:00
ncoelho
3168b2232a ref: sign and verify screen 2026-05-12 12:36:58 +02:00
2 changed files with 136 additions and 120 deletions

View File

@ -1,7 +1,7 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import React, { lazy } from 'react';
import navigationStyle from '../components/navigationStyle';
import navigationStyle, { CloseButtonPosition } from '../components/navigationStyle';
import { useTheme } from '../components/themes';
import loc from '../loc';
import { withLazySuspense } from './LazyLoadingIndicator';
@ -19,7 +19,12 @@ const SignVerifyStackRoot = () => {
<Stack.Screen
name="SignVerify"
component={SignVerifyComponent}
options={navigationStyle({ headerBackVisible: false, statusBarStyle: 'light', title: loc.addresses.sign_title })(theme)}
options={navigationStyle({
headerBackVisible: false,
statusBarStyle: 'light',
title: loc.addresses.sign_title,
closeButtonPosition: CloseButtonPosition.Right,
})(theme)}
/>
</Stack.Navigator>
);

View File

@ -1,12 +1,15 @@
import React, { useEffect, useState } from 'react';
import { RouteProp, useRoute } from '@react-navigation/native';
import { ActivityIndicator, Keyboard, LayoutAnimation, Platform, ScrollView, StyleSheet, TextInput, View } from 'react-native';
import Icon from '../../components/Icon';
import Share from 'react-native-share';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import { BlueFormLabel } from '../../BlueComponents';
import presentAlert from '../../components/Alert';
import { FButton, FContainer } from '../../components/FloatButtons';
import Button from '../../components/Button';
import Icon from '../../components/Icon';
import { FButton, FContainer, FloatButtonsBottomFade } from '../../components/FloatButtons';
import { SecondButton } from '../../components/SecondButton';
import { useTheme } from '../../components/themes';
import loc from '../../loc';
import { useStorage } from '../../hooks/context/useStorage';
@ -20,17 +23,17 @@ import useWalletSubscribe from '../../hooks/useWalletSubscribe.tsx';
type SignVerifyRouteParams = {
walletID: string;
address: string;
message: string;
};
const SignVerify = () => {
const { colors } = useTheme();
const insets = useSafeAreaInsets();
const { sleep } = useStorage();
const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
const { address: _address, message: _message, walletID } = useRoute<RouteProp<{ params: SignVerifyRouteParams }, 'params'>>().params;
const { address: _address, walletID } = useRoute<RouteProp<{ params: SignVerifyRouteParams }, 'params'>>().params;
const [address, setAddress] = useState(_address ?? '');
const [message, setMessage] = useState(_message ?? '');
const [address, setAddress] = useState(_address);
const [message, setMessage] = useState('');
const [signature, setSignature] = useState('');
const [loading, setLoading] = useState(false);
const [messageHasFocus, setMessageHasFocus] = useState(false);
@ -53,7 +56,7 @@ const SignVerify = () => {
}, []);
const stylesHooks = StyleSheet.create({
root: {
screen: {
backgroundColor: colors.elevated,
},
text: {
@ -112,82 +115,121 @@ const SignVerify = () => {
if (loading)
return (
<View style={[stylesHooks.root, styles.loading]}>
<View style={[styles.screenRoot, stylesHooks.screen, styles.loading]}>
<ActivityIndicator />
</View>
);
const scrollBottomPad = isShareVisible && !isKeyboardVisible ? insets.bottom + 80 : undefined;
return (
<ScrollView
automaticallyAdjustContentInsets
automaticallyAdjustKeyboardInsets
contentInsetAdjustmentBehavior="automatic"
contentContainerStyle={styles.root}
style={[styles.root, stylesHooks.root]}
>
{!isKeyboardVisible && (
<>
<BlueSpacing20 />
<BlueFormLabel>{loc.addresses.sign_help}</BlueFormLabel>
<BlueSpacing20 />
</>
)}
<View style={[styles.screenRoot, stylesHooks.screen]}>
<ScrollView
automaticallyAdjustContentInsets
automaticallyAdjustKeyboardInsets
contentInsetAdjustmentBehavior="automatic"
contentContainerStyle={[styles.root, scrollBottomPad !== undefined && { paddingBottom: scrollBottomPad }]}
style={styles.scroll}
>
{!isKeyboardVisible && (
<>
<BlueSpacing20 />
<BlueFormLabel>{loc.addresses.sign_help}</BlueFormLabel>
<BlueSpacing20 />
</>
)}
<TextInput
multiline
textAlignVertical="top"
blurOnSubmit
placeholder={loc.addresses.sign_placeholder_address}
placeholderTextColor="#81868e"
value={address}
onChangeText={t => setAddress(t.replace('\n', ''))}
testID="Signature"
style={[styles.text, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
editable={!loading}
/>
<BlueSpacing10 />
<TextInput
multiline
textAlignVertical="top"
blurOnSubmit
placeholder={loc.addresses.sign_placeholder_address}
placeholderTextColor="#81868e"
value={address}
onChangeText={t => setAddress(t.replace('\n', ''))}
testID="SignVerifyAddress"
style={[styles.text, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
/>
<BlueSpacing10 />
<TextInput
multiline
textAlignVertical="top"
blurOnSubmit
placeholder={loc.addresses.sign_placeholder_signature}
placeholderTextColor="#81868e"
value={signature}
onChangeText={t => setSignature(t.replace('\n', ''))}
testID="Signature"
style={[styles.text, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
editable={!loading}
/>
<BlueSpacing10 />
<TextInput
multiline
placeholder={loc.addresses.sign_placeholder_message}
placeholderTextColor="#81868e"
value={message}
onChangeText={setMessage}
testID="Message"
inputAccessoryViewID={DoneAndDismissKeyboardInputAccessoryViewID}
style={[styles.text, styles.messageInput, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
scrollEnabled
textAlignVertical="top"
onFocus={() => handleFocus(true)}
onBlur={() => handleFocus(false)}
/>
<BlueSpacing10 />
<TextInput
multiline
placeholder={loc.addresses.sign_placeholder_message}
placeholderTextColor="#81868e"
value={message}
onChangeText={setMessage}
testID="Message"
inputAccessoryViewID={DoneAndDismissKeyboardInputAccessoryViewID}
style={[styles.flex, styles.text, styles.textMessage, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
editable={!loading}
onFocus={() => handleFocus(true)}
onBlur={() => handleFocus(false)}
/>
<BlueSpacing40 />
<TextInput
multiline
textAlignVertical="top"
blurOnSubmit
placeholder={loc.addresses.sign_placeholder_signature}
placeholderTextColor="#81868e"
value={signature}
onChangeText={t => setSignature(t.replace('\n', ''))}
testID="SignVerifySignature"
style={[styles.text, stylesHooks.text]}
autoCorrect={false}
autoCapitalize="none"
spellCheck={false}
/>
<BlueSpacing40 />
{!isKeyboardVisible && (
<>
<View style={styles.actionButtons}>
<SecondButton onPress={handleVerify} title={loc.addresses.sign_verify} />
<BlueSpacing20 />
<Button onPress={handleSign} title={loc.addresses.sign_sign} />
</View>
<BlueSpacing10 />
</>
)}
{Platform.select({
ios: (
<DoneAndDismissKeyboardInputAccessory
onClearTapped={() => setMessage('')}
onPasteTapped={text => {
setMessage(text);
Keyboard.dismiss();
}}
/>
),
android: isToolbarVisibleForAndroid && (
<DoneAndDismissKeyboardInputAccessory
onClearTapped={() => {
setMessage('');
Keyboard.dismiss();
}}
onPasteTapped={text => {
setMessage(text);
Keyboard.dismiss();
}}
/>
),
})}
</ScrollView>
{isShareVisible && !isKeyboardVisible && (
<>
<FContainer inline>
<FloatButtonsBottomFade />
<FContainer>
<FButton
onPress={handleShare}
text={loc.multisig.share}
@ -198,53 +240,24 @@ const SignVerify = () => {
}
/>
</FContainer>
<BlueSpacing10 />
</>
)}
{!isKeyboardVisible && (
<>
<FContainer inline>
<FButton onPress={handleSign} text={loc.addresses.sign_sign} disabled={loading} icon={null} />
<FButton onPress={handleVerify} text={loc.addresses.sign_verify} disabled={loading} icon={null} />
</FContainer>
<BlueSpacing10 />
</>
)}
{Platform.select({
ios: (
<DoneAndDismissKeyboardInputAccessory
onClearTapped={() => setMessage('')}
onPasteTapped={text => {
setMessage(text);
Keyboard.dismiss();
}}
/>
),
android: isToolbarVisibleForAndroid && (
<DoneAndDismissKeyboardInputAccessory
onClearTapped={() => {
setMessage('');
Keyboard.dismiss();
}}
onPasteTapped={text => {
setMessage(text);
Keyboard.dismiss();
}}
/>
),
})}
</ScrollView>
</View>
);
};
export default SignVerify;
const styles = StyleSheet.create({
root: {
screenRoot: {
flex: 1,
},
scroll: {
flex: 1,
},
root: {
flexGrow: 1,
},
text: {
paddingHorizontal: 8,
paddingVertical: 8,
@ -255,18 +268,16 @@ const styles = StyleSheet.create({
borderRadius: 4,
textAlignVertical: 'top',
},
textMessage: {
minHeight: 50,
messageInput: {
minHeight: 80,
maxHeight: 200,
},
flex: {
flex: 1,
actionButtons: {
alignSelf: 'stretch',
marginHorizontal: 20,
},
loading: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},