1
1
/* @flow strict-local */
2
- import React , { PureComponent } from 'react' ;
2
+ import React , { useCallback } from 'react' ;
3
3
import type { Node } from 'react' ;
4
4
import { Keyboard } from 'react-native' ;
5
5
@@ -13,18 +13,13 @@ import Screen from '../common/Screen';
13
13
import ZulipButton from '../common/ZulipButton' ;
14
14
import { tryParseUrl } from '../utils/url' ;
15
15
import * as api from '../api' ;
16
+ import { createStyleSheet } from '../styles' ;
16
17
17
18
type Props = $ReadOnly < { |
18
19
navigation : AppNavigationProp < 'realm-input' > ,
19
20
route : RouteProp < 'realm-input' , { | initial : boolean | void | } > ,
20
21
| } > ;
21
22
22
- type State = { |
23
- realmInputValue : string ,
24
- error : string | null ,
25
- progress : boolean ,
26
- | } ;
27
-
28
23
const urlFromInputValue = ( realmInputValue : string ) : URL | void => {
29
24
const withScheme = / ^ h t t p s ? : \/ \/ / . test ( realmInputValue )
30
25
? realmInputValue
@@ -33,88 +28,85 @@ const urlFromInputValue = (realmInputValue: string): URL | void => {
33
28
return tryParseUrl ( withScheme ) ;
34
29
} ;
35
30
36
- export default class RealmInputScreen extends PureComponent < Props , State > {
37
- state : State = {
38
- progress : false ,
39
- realmInputValue : '' ,
40
- error : null ,
41
- } ;
31
+ export default function RealmInputScreen ( props : Props ) : Node {
32
+ const { navigation, route } = props ;
42
33
43
- tryRealm : ( ) = > Promise < void > = async ( ) => {
44
- const { realmInputValue } = this . state ;
34
+ const [ progress , setProgress ] = React . useState ( false ) ;
35
+ const [ realmInputValue , setRealmInputValue ] = React . useState ( '' ) ;
36
+ const [ error , setError ] = React . useState ( null ) ;
45
37
38
+ const tryRealm = React . useCallback ( async ( ) => {
46
39
const parsedRealm = urlFromInputValue ( realmInputValue ) ;
47
40
if ( ! parsedRealm ) {
48
- this . setState ( { error : 'Please enter a valid URL' } ) ;
41
+ setError ( 'Please enter a valid URL' ) ;
49
42
return ;
50
43
}
51
44
if ( parsedRealm . username !== '' ) {
52
- this . setState ( { error : 'Please enter the server URL, not your email' } ) ;
45
+ setError ( 'Please enter the server URL, not your email' ) ;
53
46
return ;
54
47
}
55
48
56
- this . setState ( {
57
- progress : true ,
58
- error : null ,
59
- } ) ;
49
+ setProgress ( true ) ;
50
+ setError ( null ) ;
60
51
try {
61
52
const serverSettings : ApiResponseServerSettings = await api . getServerSettings ( parsedRealm ) ;
62
- this . props . navigation . push ( 'auth' , { serverSettings } ) ;
53
+ navigation . push ( 'auth' , { serverSettings } ) ;
63
54
Keyboard . dismiss ( ) ;
64
55
} catch ( errorIllTyped ) {
65
56
const err : mixed = errorIllTyped ; // https://github.com/facebook/flow/issues/2470
66
- this . setState ( { error : 'Cannot connect to server' } ) ;
57
+ setError ( 'Cannot connect to server' ) ;
67
58
/* eslint-disable no-console */
68
59
console . warn ( 'RealmInputScreen: failed to connect to server:' , err ) ;
69
60
// $FlowFixMe[incompatible-cast]: assuming caught exception was Error
70
61
console . warn ( ( err : Error ) . stack ) ;
71
62
} finally {
72
- this . setState ( { progress : false } ) ;
63
+ setProgress ( false ) ;
73
64
}
74
- } ;
75
-
76
- handleRealmChange : string => void = value => this . setState ( { realmInputValue : value } ) ;
65
+ } , [ navigation , realmInputValue ] ) ;
77
66
78
- render ( ) : Node {
79
- const { navigation } = this . props ;
80
- const { progress , error , realmInputValue } = this . state ;
67
+ const handleRealmChange = useCallback ( value => {
68
+ setRealmInputValue ( value ) ;
69
+ } , [ ] ) ;
81
70
82
- const styles = {
83
- input : { marginTop : 16 , marginBottom : 8 } ,
84
- hintText : { paddingLeft : 2 , fontSize : 12 } ,
85
- button : { marginTop : 8 } ,
86
- } ;
71
+ const styles = React . useMemo (
72
+ ( ) =>
73
+ createStyleSheet ( {
74
+ input : { marginTop : 16 , marginBottom : 8 } ,
75
+ hintText : { paddingLeft : 2 , fontSize : 12 } ,
76
+ button : { marginTop : 8 } ,
77
+ } ) ,
78
+ [ ] ,
79
+ ) ;
87
80
88
- return (
89
- < Screen
90
- title = "Welcome"
91
- canGoBack = { ! this . props . route . params . initial }
92
- padding
93
- centerContent
94
- keyboardShouldPersistTaps = "always"
95
- shouldShowLoadingBanner = { false }
96
- >
97
- < ZulipTextIntl text = "Enter your Zulip server URL:" />
98
- < SmartUrlInput
99
- style = { styles . input }
100
- navigation = { navigation }
101
- onChangeText = { this . handleRealmChange }
102
- onSubmitEditing = { this . tryRealm }
103
- enablesReturnKeyAutomatically
104
- />
105
- { error !== null ? (
106
- < ErrorMsg error = { error } />
107
- ) : (
108
- < ZulipTextIntl text = "e.g. zulip.example.com" style = { styles . hintText } />
109
- ) }
110
- < ZulipButton
111
- style = { styles . button }
112
- text = "Enter"
113
- progress = { progress }
114
- onPress = { this . tryRealm }
115
- disabled = { urlFromInputValue ( realmInputValue ) === undefined }
116
- />
117
- </ Screen >
118
- ) ;
119
- }
81
+ return (
82
+ < Screen
83
+ title = "Welcome"
84
+ canGoBack = { ! route . params . initial }
85
+ padding
86
+ centerContent
87
+ keyboardShouldPersistTaps = "always"
88
+ shouldShowLoadingBanner = { false }
89
+ >
90
+ < ZulipTextIntl text = "Enter your Zulip server URL:" />
91
+ < SmartUrlInput
92
+ style = { styles . input }
93
+ navigation = { navigation }
94
+ onChangeText = { handleRealmChange }
95
+ onSubmitEditing = { tryRealm }
96
+ enablesReturnKeyAutomatically
97
+ />
98
+ { error !== null ? (
99
+ < ErrorMsg error = { error } />
100
+ ) : (
101
+ < ZulipTextIntl text = "e.g. zulip.example.com" style = { styles . hintText } />
102
+ ) }
103
+ < ZulipButton
104
+ style = { styles . button }
105
+ text = "Enter"
106
+ progress = { progress }
107
+ onPress = { tryRealm }
108
+ disabled = { urlFromInputValue ( realmInputValue ) === undefined }
109
+ />
110
+ </ Screen >
111
+ ) ;
120
112
}
0 commit comments