Bluesky app fork with some witchin' additions 💫

fix collapsed input issue

+157 -148
+157 -148
src/screens/Login/LoginForm.tsx
··· 2 2 import { 3 3 ActivityIndicator, 4 4 Keyboard, 5 + ScrollView, 5 6 TextInput, 6 7 TouchableOpacity, 7 8 View, ··· 21 22 import {useLingui} from '@lingui/react' 22 23 import {useDialogControl} from '#/components/Dialog' 23 24 import {ServerInputDialog} from '../../view/com/auth/server-input' 24 - import {Button} from '#/components/Button' 25 + import {Button, ButtonText} from '#/components/Button' 25 26 import {isAndroid} from '#/platform/detection' 26 27 import {atoms as a, useBreakpoints, useTheme} from '#/alf' 27 28 import {Text} from '#/components/Typography' ··· 43 44 setServiceUrl, 44 45 onPressRetryConnect, 45 46 onPressBack, 47 + onPressForgotPassword, 46 48 }: { 47 49 error: string 48 50 serviceUrl: string ··· 129 131 130 132 const isReady = !!serviceDescription && !!identifier && !!password 131 133 return ( 132 - <View testID="loginForm" style={[a.gap_lg, !gtMobile && a.px_lg]}> 133 - <ServerInputDialog 134 - control={serverInputControl} 135 - onSelect={setServiceUrl} 136 - /> 134 + <ScrollView testID="loginForm" style={a.h_full}> 135 + <View style={[a.gap_lg, !gtMobile && a.px_lg, a.flex_1]}> 136 + <ServerInputDialog 137 + control={serverInputControl} 138 + onSelect={setServiceUrl} 139 + /> 137 140 138 - <View> 139 - <TextField.Label> 140 - <Trans>Hosting provider</Trans> 141 - </TextField.Label> 142 - <TouchableOpacity 143 - accessibilityRole="button" 144 - style={[ 145 - a.w_full, 146 - a.flex_row, 147 - a.align_center, 148 - a.rounded_sm, 149 - a.px_md, 150 - a.gap_xs, 151 - {paddingVertical: isAndroid ? 14 : 9}, 152 - t.atoms.bg_contrast_25, 153 - ]} 154 - onPress={onPressSelectService}> 155 - <TextField.Icon icon={Globe} /> 156 - <Text style={[a.text_md]}>{toNiceDomain(serviceUrl)}</Text> 157 - <View 141 + <View> 142 + <TextField.Label> 143 + <Trans>Hosting provider</Trans> 144 + </TextField.Label> 145 + <TouchableOpacity 146 + accessibilityRole="button" 158 147 style={[ 148 + a.w_full, 149 + a.flex_row, 150 + a.align_center, 159 151 a.rounded_sm, 160 - t.atoms.bg_contrast_100, 161 - {marginLeft: 'auto', left: 6, padding: 6}, 162 - ]}> 163 - <Pencil 164 - style={{color: t.palette.contrast_500}} 165 - height={18} 166 - width={18} 152 + a.px_md, 153 + a.gap_xs, 154 + {paddingVertical: isAndroid ? 14 : 9}, 155 + t.atoms.bg_contrast_25, 156 + ]} 157 + onPress={onPressSelectService}> 158 + <TextField.Icon icon={Globe} /> 159 + <Text style={[a.text_md]}>{toNiceDomain(serviceUrl)}</Text> 160 + <View 161 + style={[ 162 + a.rounded_sm, 163 + t.atoms.bg_contrast_100, 164 + {marginLeft: 'auto', left: 6, padding: 6}, 165 + ]}> 166 + <Pencil 167 + style={{color: t.palette.contrast_500}} 168 + height={18} 169 + width={18} 170 + /> 171 + </View> 172 + </TouchableOpacity> 173 + </View> 174 + <View> 175 + <TextField.Label> 176 + <Trans>Account</Trans> 177 + </TextField.Label> 178 + <TextField.Root> 179 + <TextField.Icon icon={At} /> 180 + <TextField.Input 181 + testID="loginUsernameInput" 182 + label={_(msg`Username or email address`)} 183 + autoCapitalize="none" 184 + autoFocus 185 + autoCorrect={false} 186 + autoComplete="username" 187 + returnKeyType="next" 188 + textContentType="username" 189 + onSubmitEditing={() => { 190 + passwordInputRef.current?.focus() 191 + }} 192 + blurOnSubmit={false} // prevents flickering due to onSubmitEditing going to next field 193 + value={identifier} 194 + onChangeText={str => 195 + setIdentifier((str || '').toLowerCase().trim()) 196 + } 197 + editable={!isProcessing} 198 + accessibilityHint={_( 199 + msg`Input the username or email address you used at signup`, 200 + )} 167 201 /> 202 + </TextField.Root> 203 + </View> 204 + <View> 205 + <TextField.Root> 206 + <TextField.Icon icon={Lock} /> 207 + <TextField.Input 208 + testID="loginPasswordInput" 209 + inputRef={passwordInputRef} 210 + label={_(msg`Password`)} 211 + autoCapitalize="none" 212 + autoCorrect={false} 213 + autoComplete="password" 214 + returnKeyType="done" 215 + enablesReturnKeyAutomatically={true} 216 + secureTextEntry={true} 217 + textContentType="password" 218 + clearButtonMode="while-editing" 219 + value={password} 220 + onChangeText={setPassword} 221 + onSubmitEditing={onPressNext} 222 + blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing 223 + editable={!isProcessing} 224 + accessibilityHint={ 225 + identifier === '' 226 + ? _(msg`Input your password`) 227 + : _(msg`Input the password tied to ${identifier}`) 228 + } 229 + /> 230 + <TouchableOpacity 231 + testID="forgotPasswordButton" 232 + onPress={onPressForgotPassword} 233 + accessibilityRole="button" 234 + accessibilityLabel={_(msg`Forgot password`)} 235 + accessibilityHint={_(msg`Opens password reset form`)} 236 + style={[ 237 + a.rounded_sm, 238 + t.atoms.bg_contrast_100, 239 + {marginLeft: 'auto', left: 6, padding: 6}, 240 + a.z_10, 241 + ]}> 242 + <ButtonText style={t.atoms.text_contrast_medium}> 243 + <Trans>Forgot?</Trans> 244 + </ButtonText> 245 + </TouchableOpacity> 246 + </TextField.Root> 247 + </View> 248 + {error ? ( 249 + <View style={[styles.error, {marginHorizontal: 0}]}> 250 + <Warning style={s.white} size="sm" /> 251 + <View style={(a.flex_1, a.ml_sm)}> 252 + <Text style={[s.white, s.bold]}>{error}</Text> 253 + </View> 168 254 </View> 169 - </TouchableOpacity> 170 - </View> 171 - <View> 172 - <TextField.Label> 173 - <Trans>Account</Trans> 174 - </TextField.Label> 175 - <TextField.Root> 176 - <TextField.Icon icon={At} /> 177 - <TextField.Input 178 - testID="loginUsernameInput" 179 - label={_(msg`Username or email address`)} 180 - autoCapitalize="none" 181 - autoFocus 182 - autoCorrect={false} 183 - autoComplete="username" 184 - returnKeyType="next" 185 - textContentType="username" 186 - onSubmitEditing={() => { 187 - passwordInputRef.current?.focus() 188 - }} 189 - blurOnSubmit={false} // prevents flickering due to onSubmitEditing going to next field 190 - value={identifier} 191 - onChangeText={str => 192 - setIdentifier((str || '').toLowerCase().trim()) 193 - } 194 - editable={!isProcessing} 195 - accessibilityHint={_( 196 - msg`Input the username or email address you used at signup`, 197 - )} 198 - /> 199 - </TextField.Root> 200 - </View> 201 - <View> 202 - <TextField.Root> 203 - <TextField.Icon icon={Lock} /> 204 - <TextField.Input 205 - testID="loginPasswordInput" 206 - inputRef={passwordInputRef} 207 - label={_(msg`Password`)} 208 - autoCapitalize="none" 209 - autoCorrect={false} 210 - autoComplete="password" 211 - returnKeyType="done" 212 - enablesReturnKeyAutomatically={true} 213 - secureTextEntry={true} 214 - textContentType="password" 215 - clearButtonMode="while-editing" 216 - value={password} 217 - onChangeText={setPassword} 218 - onSubmitEditing={onPressNext} 219 - blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing 220 - editable={!isProcessing} 221 - accessibilityHint={ 222 - identifier === '' 223 - ? _(msg`Input your password`) 224 - : _(msg`Input the password tied to ${identifier}`) 225 - } 226 - /> 227 - {/* <TouchableOpacity 228 - testID="forgotPasswordButton" 229 - style={styles.textInputInnerBtn} 230 - onPress={onPressForgotPassword} 231 - accessibilityRole="button" 232 - accessibilityLabel={_(msg`Forgot password`)} 233 - accessibilityHint={_(msg`Opens password reset form`)}> 234 - <Text style={pal.link}> 235 - <Trans>Forgot</Trans> 236 - </Text> 237 - </TouchableOpacity> */} 238 - </TextField.Root> 239 - </View> 240 - {error ? ( 241 - <View style={[styles.error, {marginHorizontal: 0}]}> 242 - <Warning style={s.white} size="sm" /> 243 - <View style={(a.flex_1, a.ml_sm)}> 244 - <Text style={[s.white, s.bold]}>{error}</Text> 245 - </View> 246 - </View> 247 - ) : undefined} 248 - <View style={[a.flex_row, a.align_center]}> 249 - <Button 250 - label={_(msg`Back`)} 251 - variant="solid" 252 - color="secondary" 253 - size="small" 254 - onPress={onPressBack}> 255 - {_(msg`Back`)} 256 - </Button> 257 - <View style={s.flex1} /> 258 - {!serviceDescription && error ? ( 255 + ) : undefined} 256 + <View style={[a.flex_row, a.align_center]}> 259 257 <Button 260 - testID="loginRetryButton" 261 - label={_(msg`Retry`)} 262 - accessibilityHint={_(msg`Retries login`)} 258 + label={_(msg`Back`)} 263 259 variant="solid" 264 260 color="secondary" 265 261 size="small" 266 - onPress={onPressRetryConnect}> 267 - {_(msg`Retry`)} 262 + onPress={onPressBack}> 263 + {_(msg`Back`)} 268 264 </Button> 269 - ) : !serviceDescription ? ( 270 - <> 265 + <View style={s.flex1} /> 266 + {!serviceDescription && error ? ( 267 + <Button 268 + testID="loginRetryButton" 269 + label={_(msg`Retry`)} 270 + accessibilityHint={_(msg`Retries login`)} 271 + variant="solid" 272 + color="secondary" 273 + size="small" 274 + onPress={onPressRetryConnect}> 275 + {_(msg`Retry`)} 276 + </Button> 277 + ) : !serviceDescription ? ( 278 + <> 279 + <ActivityIndicator /> 280 + <Text style={[t.atoms.text_contrast_high, a.pl_md]}> 281 + <Trans>Connecting...</Trans> 282 + </Text> 283 + </> 284 + ) : isProcessing ? ( 271 285 <ActivityIndicator /> 272 - <Text style={[t.atoms.text_contrast_high, a.pl_md]}> 273 - <Trans>Connecting...</Trans> 274 - </Text> 275 - </> 276 - ) : isProcessing ? ( 277 - <ActivityIndicator /> 278 - ) : isReady ? ( 279 - <Button 280 - label={_(msg`Next`)} 281 - accessibilityHint={_(msg`Navigates to the next screen`)} 282 - variant="solid" 283 - color="primary" 284 - size="small" 285 - onPress={onPressNext}> 286 - {_(msg`Next`)} 287 - </Button> 288 - ) : undefined} 286 + ) : isReady ? ( 287 + <Button 288 + label={_(msg`Next`)} 289 + accessibilityHint={_(msg`Navigates to the next screen`)} 290 + variant="solid" 291 + color="primary" 292 + size="small" 293 + onPress={onPressNext}> 294 + {_(msg`Next`)} 295 + </Button> 296 + ) : undefined} 297 + </View> 289 298 </View> 290 - </View> 299 + </ScrollView> 291 300 ) 292 301 }