Bluesky app fork with some witchin' additions 💫

Fix keyboard double pad issue in email change & verify modals (#1664)

authored by

Paul Frazee and committed by
GitHub
e878da04 fc28fc63

+250 -275
+115 -129
src/view/com/modals/ChangeEmail.tsx
··· 1 1 import React, {useState} from 'react' 2 - import { 3 - ActivityIndicator, 4 - KeyboardAvoidingView, 5 - SafeAreaView, 6 - StyleSheet, 7 - View, 8 - } from 'react-native' 2 + import {ActivityIndicator, SafeAreaView, StyleSheet, View} from 'react-native' 9 3 import {ScrollView, TextInput} from './util' 10 4 import {observer} from 'mobx-react-lite' 11 5 import {Text} from '../util/text/Text' ··· 101 95 } 102 96 103 97 return ( 104 - <KeyboardAvoidingView 105 - behavior="padding" 106 - style={[pal.view, styles.container]}> 107 - <SafeAreaView style={s.flex1}> 108 - <ScrollView 109 - testID="changeEmailModal" 110 - style={[s.flex1, isMobile && {paddingHorizontal: 18}]}> 111 - <View style={styles.titleSection}> 112 - <Text type="title-lg" style={[pal.text, styles.title]}> 113 - {stage === Stages.InputEmail ? 'Change Your Email' : ''} 114 - {stage === Stages.ConfirmCode ? 'Security Step Required' : ''} 115 - {stage === Stages.Done ? 'Email Updated' : ''} 116 - </Text> 117 - </View> 118 - 119 - <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}> 120 - {stage === Stages.InputEmail ? ( 121 - <>Enter your new email address below.</> 122 - ) : stage === Stages.ConfirmCode ? ( 123 - <> 124 - An email has been sent to your previous address,{' '} 125 - {store.session.currentSession?.email || ''}. It includes a 126 - confirmation code which you can enter below. 127 - </> 128 - ) : ( 129 - <> 130 - Your email has been updated but not verified. As a next step, 131 - please verify your new email. 132 - </> 133 - )} 98 + <SafeAreaView style={[pal.view, s.flex1]}> 99 + <ScrollView 100 + testID="changeEmailModal" 101 + style={[s.flex1, isMobile && {paddingHorizontal: 18}]}> 102 + <View style={styles.titleSection}> 103 + <Text type="title-lg" style={[pal.text, styles.title]}> 104 + {stage === Stages.InputEmail ? 'Change Your Email' : ''} 105 + {stage === Stages.ConfirmCode ? 'Security Step Required' : ''} 106 + {stage === Stages.Done ? 'Email Updated' : ''} 134 107 </Text> 108 + </View> 135 109 136 - {stage === Stages.InputEmail && ( 137 - <TextInput 138 - testID="emailInput" 139 - style={[styles.textInput, pal.border, pal.text]} 140 - placeholder="alice@mail.com" 141 - placeholderTextColor={pal.colors.textLight} 142 - value={email} 143 - onChangeText={setEmail} 144 - accessible={true} 145 - accessibilityLabel="Email" 146 - accessibilityHint="" 147 - autoCapitalize="none" 148 - autoComplete="email" 149 - autoCorrect={false} 150 - /> 151 - )} 152 - {stage === Stages.ConfirmCode && ( 153 - <TextInput 154 - testID="confirmCodeInput" 155 - style={[styles.textInput, pal.border, pal.text]} 156 - placeholder="XXXXX-XXXXX" 157 - placeholderTextColor={pal.colors.textLight} 158 - value={confirmationCode} 159 - onChangeText={setConfirmationCode} 160 - accessible={true} 161 - accessibilityLabel="Confirmation code" 162 - accessibilityHint="" 163 - autoCapitalize="none" 164 - autoComplete="off" 165 - autoCorrect={false} 166 - /> 110 + <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}> 111 + {stage === Stages.InputEmail ? ( 112 + <>Enter your new email address below.</> 113 + ) : stage === Stages.ConfirmCode ? ( 114 + <> 115 + An email has been sent to your previous address,{' '} 116 + {store.session.currentSession?.email || ''}. It includes a 117 + confirmation code which you can enter below. 118 + </> 119 + ) : ( 120 + <> 121 + Your email has been updated but not verified. As a next step, 122 + please verify your new email. 123 + </> 167 124 )} 125 + </Text> 168 126 169 - {error ? ( 170 - <ErrorMessage message={error} style={styles.error} /> 171 - ) : undefined} 127 + {stage === Stages.InputEmail && ( 128 + <TextInput 129 + testID="emailInput" 130 + style={[styles.textInput, pal.border, pal.text]} 131 + placeholder="alice@mail.com" 132 + placeholderTextColor={pal.colors.textLight} 133 + value={email} 134 + onChangeText={setEmail} 135 + accessible={true} 136 + accessibilityLabel="Email" 137 + accessibilityHint="" 138 + autoCapitalize="none" 139 + autoComplete="email" 140 + autoCorrect={false} 141 + /> 142 + )} 143 + {stage === Stages.ConfirmCode && ( 144 + <TextInput 145 + testID="confirmCodeInput" 146 + style={[styles.textInput, pal.border, pal.text]} 147 + placeholder="XXXXX-XXXXX" 148 + placeholderTextColor={pal.colors.textLight} 149 + value={confirmationCode} 150 + onChangeText={setConfirmationCode} 151 + accessible={true} 152 + accessibilityLabel="Confirmation code" 153 + accessibilityHint="" 154 + autoCapitalize="none" 155 + autoComplete="off" 156 + autoCorrect={false} 157 + /> 158 + )} 172 159 173 - <View style={[styles.btnContainer]}> 174 - {isProcessing ? ( 175 - <View style={styles.btn}> 176 - <ActivityIndicator color="#fff" /> 177 - </View> 178 - ) : ( 179 - <View style={{gap: 6}}> 180 - {stage === Stages.InputEmail && ( 181 - <Button 182 - testID="requestChangeBtn" 183 - type="primary" 184 - onPress={onRequestChange} 185 - accessibilityLabel="Request Change" 186 - accessibilityHint="" 187 - label="Request Change" 188 - labelContainerStyle={{justifyContent: 'center', padding: 4}} 189 - labelStyle={[s.f18]} 190 - /> 191 - )} 192 - {stage === Stages.ConfirmCode && ( 193 - <Button 194 - testID="confirmBtn" 195 - type="primary" 196 - onPress={onConfirm} 197 - accessibilityLabel="Confirm Change" 198 - accessibilityHint="" 199 - label="Confirm Change" 200 - labelContainerStyle={{justifyContent: 'center', padding: 4}} 201 - labelStyle={[s.f18]} 202 - /> 203 - )} 204 - {stage === Stages.Done && ( 205 - <Button 206 - testID="verifyBtn" 207 - type="primary" 208 - onPress={onVerify} 209 - accessibilityLabel="Verify New Email" 210 - accessibilityHint="" 211 - label="Verify New Email" 212 - labelContainerStyle={{justifyContent: 'center', padding: 4}} 213 - labelStyle={[s.f18]} 214 - /> 215 - )} 160 + {error ? ( 161 + <ErrorMessage message={error} style={styles.error} /> 162 + ) : undefined} 163 + 164 + <View style={[styles.btnContainer]}> 165 + {isProcessing ? ( 166 + <View style={styles.btn}> 167 + <ActivityIndicator color="#fff" /> 168 + </View> 169 + ) : ( 170 + <View style={{gap: 6}}> 171 + {stage === Stages.InputEmail && ( 216 172 <Button 217 - testID="cancelBtn" 218 - type="default" 219 - onPress={() => store.shell.closeModal()} 220 - accessibilityLabel="Cancel" 173 + testID="requestChangeBtn" 174 + type="primary" 175 + onPress={onRequestChange} 176 + accessibilityLabel="Request Change" 177 + accessibilityHint="" 178 + label="Request Change" 179 + labelContainerStyle={{justifyContent: 'center', padding: 4}} 180 + labelStyle={[s.f18]} 181 + /> 182 + )} 183 + {stage === Stages.ConfirmCode && ( 184 + <Button 185 + testID="confirmBtn" 186 + type="primary" 187 + onPress={onConfirm} 188 + accessibilityLabel="Confirm Change" 189 + accessibilityHint="" 190 + label="Confirm Change" 191 + labelContainerStyle={{justifyContent: 'center', padding: 4}} 192 + labelStyle={[s.f18]} 193 + /> 194 + )} 195 + {stage === Stages.Done && ( 196 + <Button 197 + testID="verifyBtn" 198 + type="primary" 199 + onPress={onVerify} 200 + accessibilityLabel="Verify New Email" 221 201 accessibilityHint="" 222 - label="Cancel" 202 + label="Verify New Email" 223 203 labelContainerStyle={{justifyContent: 'center', padding: 4}} 224 204 labelStyle={[s.f18]} 225 205 /> 226 - </View> 227 - )} 228 - </View> 229 - </ScrollView> 230 - </SafeAreaView> 231 - </KeyboardAvoidingView> 206 + )} 207 + <Button 208 + testID="cancelBtn" 209 + type="default" 210 + onPress={() => store.shell.closeModal()} 211 + accessibilityLabel="Cancel" 212 + accessibilityHint="" 213 + label="Cancel" 214 + labelContainerStyle={{justifyContent: 'center', padding: 4}} 215 + labelStyle={[s.f18]} 216 + /> 217 + </View> 218 + )} 219 + </View> 220 + </ScrollView> 221 + </SafeAreaView> 232 222 ) 233 223 }) 234 224 235 225 const styles = StyleSheet.create({ 236 - container: { 237 - flex: 1, 238 - paddingBottom: isWeb ? 0 : 40, 239 - }, 240 226 titleSection: { 241 227 paddingTop: isWeb ? 0 : 4, 242 228 paddingBottom: isWeb ? 14 : 10,
+135 -146
src/view/com/modals/VerifyEmail.tsx
··· 1 1 import React, {useState} from 'react' 2 2 import { 3 3 ActivityIndicator, 4 - KeyboardAvoidingView, 5 4 Pressable, 6 5 SafeAreaView, 7 6 StyleSheet, ··· 82 81 } 83 82 84 83 return ( 85 - <KeyboardAvoidingView 86 - behavior="padding" 87 - style={[pal.view, styles.container]}> 88 - <SafeAreaView style={s.flex1}> 89 - <ScrollView 90 - testID="verifyEmailModal" 91 - style={[s.flex1, isMobile && {paddingHorizontal: 18}]}> 92 - {stage === Stages.Reminder && <ReminderIllustration />} 93 - <View style={styles.titleSection}> 94 - <Text type="title-lg" style={[pal.text, styles.title]}> 95 - {stage === Stages.Reminder ? 'Please Verify Your Email' : ''} 96 - {stage === Stages.ConfirmCode ? 'Enter Confirmation Code' : ''} 97 - {stage === Stages.Email ? 'Verify Your Email' : ''} 98 - </Text> 99 - </View> 100 - 101 - <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}> 102 - {stage === Stages.Reminder ? ( 103 - <> 104 - Your email has not yet been verified. This is an important 105 - security step which we recommend. 106 - </> 107 - ) : stage === Stages.Email ? ( 108 - <> 109 - This is important in case you ever need to change your email or 110 - reset your password. 111 - </> 112 - ) : stage === Stages.ConfirmCode ? ( 113 - <> 114 - An email has been sent to{' '} 115 - {store.session.currentSession?.email || ''}. It includes a 116 - confirmation code which you can enter below. 117 - </> 118 - ) : ( 119 - '' 120 - )} 84 + <SafeAreaView style={[pal.view, s.flex1]}> 85 + <ScrollView 86 + testID="verifyEmailModal" 87 + style={[s.flex1, isMobile && {paddingHorizontal: 18}]}> 88 + {stage === Stages.Reminder && <ReminderIllustration />} 89 + <View style={styles.titleSection}> 90 + <Text type="title-lg" style={[pal.text, styles.title]}> 91 + {stage === Stages.Reminder ? 'Please Verify Your Email' : ''} 92 + {stage === Stages.ConfirmCode ? 'Enter Confirmation Code' : ''} 93 + {stage === Stages.Email ? 'Verify Your Email' : ''} 121 94 </Text> 95 + </View> 122 96 123 - {stage === Stages.Email ? ( 97 + <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}> 98 + {stage === Stages.Reminder ? ( 124 99 <> 125 - <View style={styles.emailContainer}> 126 - <FontAwesomeIcon 127 - icon="envelope" 128 - color={pal.colors.text} 129 - size={16} 130 - /> 131 - <Text 132 - type="xl-medium" 133 - style={[pal.text, s.flex1, {minWidth: 0}]}> 134 - {store.session.currentSession?.email || ''} 135 - </Text> 136 - </View> 137 - <Pressable 138 - accessibilityRole="link" 139 - accessibilityLabel="Change my email" 140 - accessibilityHint="" 141 - onPress={onEmailIncorrect} 142 - style={styles.changeEmailLink}> 143 - <Text type="lg" style={pal.link}> 144 - Change 145 - </Text> 146 - </Pressable> 100 + Your email has not yet been verified. This is an important 101 + security step which we recommend. 102 + </> 103 + ) : stage === Stages.Email ? ( 104 + <> 105 + This is important in case you ever need to change your email or 106 + reset your password. 147 107 </> 148 108 ) : stage === Stages.ConfirmCode ? ( 149 - <TextInput 150 - testID="confirmCodeInput" 151 - style={[styles.textInput, pal.border, pal.text]} 152 - placeholder="XXXXX-XXXXX" 153 - placeholderTextColor={pal.colors.textLight} 154 - value={confirmationCode} 155 - onChangeText={setConfirmationCode} 156 - accessible={true} 157 - accessibilityLabel="Confirmation code" 109 + <> 110 + An email has been sent to{' '} 111 + {store.session.currentSession?.email || ''}. It includes a 112 + confirmation code which you can enter below. 113 + </> 114 + ) : ( 115 + '' 116 + )} 117 + </Text> 118 + 119 + {stage === Stages.Email ? ( 120 + <> 121 + <View style={styles.emailContainer}> 122 + <FontAwesomeIcon 123 + icon="envelope" 124 + color={pal.colors.text} 125 + size={16} 126 + /> 127 + <Text type="xl-medium" style={[pal.text, s.flex1, {minWidth: 0}]}> 128 + {store.session.currentSession?.email || ''} 129 + </Text> 130 + </View> 131 + <Pressable 132 + accessibilityRole="link" 133 + accessibilityLabel="Change my email" 158 134 accessibilityHint="" 159 - autoCapitalize="none" 160 - autoComplete="off" 161 - autoCorrect={false} 162 - /> 163 - ) : undefined} 135 + onPress={onEmailIncorrect} 136 + style={styles.changeEmailLink}> 137 + <Text type="lg" style={pal.link}> 138 + Change 139 + </Text> 140 + </Pressable> 141 + </> 142 + ) : stage === Stages.ConfirmCode ? ( 143 + <TextInput 144 + testID="confirmCodeInput" 145 + style={[styles.textInput, pal.border, pal.text]} 146 + placeholder="XXXXX-XXXXX" 147 + placeholderTextColor={pal.colors.textLight} 148 + value={confirmationCode} 149 + onChangeText={setConfirmationCode} 150 + accessible={true} 151 + accessibilityLabel="Confirmation code" 152 + accessibilityHint="" 153 + autoCapitalize="none" 154 + autoComplete="off" 155 + autoCorrect={false} 156 + /> 157 + ) : undefined} 164 158 165 - {error ? ( 166 - <ErrorMessage message={error} style={styles.error} /> 167 - ) : undefined} 159 + {error ? ( 160 + <ErrorMessage message={error} style={styles.error} /> 161 + ) : undefined} 168 162 169 - <View style={[styles.btnContainer]}> 170 - {isProcessing ? ( 171 - <View style={styles.btn}> 172 - <ActivityIndicator color="#fff" /> 173 - </View> 174 - ) : ( 175 - <View style={{gap: 6}}> 176 - {stage === Stages.Reminder && ( 163 + <View style={[styles.btnContainer]}> 164 + {isProcessing ? ( 165 + <View style={styles.btn}> 166 + <ActivityIndicator color="#fff" /> 167 + </View> 168 + ) : ( 169 + <View style={{gap: 6}}> 170 + {stage === Stages.Reminder && ( 171 + <Button 172 + testID="getStartedBtn" 173 + type="primary" 174 + onPress={() => setStage(Stages.Email)} 175 + accessibilityLabel="Get Started" 176 + accessibilityHint="" 177 + label="Get Started" 178 + labelContainerStyle={{justifyContent: 'center', padding: 4}} 179 + labelStyle={[s.f18]} 180 + /> 181 + )} 182 + {stage === Stages.Email && ( 183 + <> 177 184 <Button 178 - testID="getStartedBtn" 185 + testID="sendEmailBtn" 179 186 type="primary" 180 - onPress={() => setStage(Stages.Email)} 181 - accessibilityLabel="Get Started" 187 + onPress={onSendEmail} 188 + accessibilityLabel="Send Confirmation Email" 182 189 accessibilityHint="" 183 - label="Get Started" 184 - labelContainerStyle={{justifyContent: 'center', padding: 4}} 190 + label="Send Confirmation Email" 191 + labelContainerStyle={{ 192 + justifyContent: 'center', 193 + padding: 4, 194 + }} 185 195 labelStyle={[s.f18]} 186 196 /> 187 - )} 188 - {stage === Stages.Email && ( 189 - <> 190 - <Button 191 - testID="sendEmailBtn" 192 - type="primary" 193 - onPress={onSendEmail} 194 - accessibilityLabel="Send Confirmation Email" 195 - accessibilityHint="" 196 - label="Send Confirmation Email" 197 - labelContainerStyle={{ 198 - justifyContent: 'center', 199 - padding: 4, 200 - }} 201 - labelStyle={[s.f18]} 202 - /> 203 - <Button 204 - testID="haveCodeBtn" 205 - type="default" 206 - accessibilityLabel="I have a code" 207 - accessibilityHint="" 208 - label="I have a confirmation code" 209 - labelContainerStyle={{ 210 - justifyContent: 'center', 211 - padding: 4, 212 - }} 213 - labelStyle={[s.f18]} 214 - onPress={() => setStage(Stages.ConfirmCode)} 215 - /> 216 - </> 217 - )} 218 - {stage === Stages.ConfirmCode && ( 219 197 <Button 220 - testID="confirmBtn" 221 - type="primary" 222 - onPress={onConfirm} 223 - accessibilityLabel="Confirm" 198 + testID="haveCodeBtn" 199 + type="default" 200 + accessibilityLabel="I have a code" 224 201 accessibilityHint="" 225 - label="Confirm" 226 - labelContainerStyle={{justifyContent: 'center', padding: 4}} 202 + label="I have a confirmation code" 203 + labelContainerStyle={{ 204 + justifyContent: 'center', 205 + padding: 4, 206 + }} 227 207 labelStyle={[s.f18]} 208 + onPress={() => setStage(Stages.ConfirmCode)} 228 209 /> 229 - )} 210 + </> 211 + )} 212 + {stage === Stages.ConfirmCode && ( 230 213 <Button 231 - testID="cancelBtn" 232 - type="default" 233 - onPress={() => store.shell.closeModal()} 234 - accessibilityLabel={ 235 - stage === Stages.Reminder ? 'Not right now' : 'Cancel' 236 - } 214 + testID="confirmBtn" 215 + type="primary" 216 + onPress={onConfirm} 217 + accessibilityLabel="Confirm" 237 218 accessibilityHint="" 238 - label={stage === Stages.Reminder ? 'Not right now' : 'Cancel'} 219 + label="Confirm" 239 220 labelContainerStyle={{justifyContent: 'center', padding: 4}} 240 221 labelStyle={[s.f18]} 241 222 /> 242 - </View> 243 - )} 244 - </View> 245 - </ScrollView> 246 - </SafeAreaView> 247 - </KeyboardAvoidingView> 223 + )} 224 + <Button 225 + testID="cancelBtn" 226 + type="default" 227 + onPress={() => store.shell.closeModal()} 228 + accessibilityLabel={ 229 + stage === Stages.Reminder ? 'Not right now' : 'Cancel' 230 + } 231 + accessibilityHint="" 232 + label={stage === Stages.Reminder ? 'Not right now' : 'Cancel'} 233 + labelContainerStyle={{justifyContent: 'center', padding: 4}} 234 + labelStyle={[s.f18]} 235 + /> 236 + </View> 237 + )} 238 + </View> 239 + </ScrollView> 240 + </SafeAreaView> 248 241 ) 249 242 }) 250 243 ··· 274 267 } 275 268 276 269 const styles = StyleSheet.create({ 277 - container: { 278 - flex: 1, 279 - paddingBottom: isWeb ? 0 : 40, 280 - }, 281 270 titleSection: { 282 271 paddingTop: isWeb ? 0 : 4, 283 272 paddingBottom: isWeb ? 14 : 10,