11/* @flow strict-local */
2- import React , { PureComponent } from 'react' ;
2+ import React , { useCallback } from 'react' ;
33import type { Node } from 'react' ;
44import { Keyboard } from 'react-native' ;
55
@@ -13,18 +13,13 @@ import Screen from '../common/Screen';
1313import ZulipButton from '../common/ZulipButton' ;
1414import { tryParseUrl } from '../utils/url' ;
1515import * as api from '../api' ;
16+ import { createStyleSheet } from '../styles' ;
1617
1718type Props = $ReadOnly < { |
1819 navigation : AppNavigationProp < 'realm-input' > ,
1920 route : RouteProp < 'realm-input' , { | initial : boolean | void | } > ,
2021| } > ;
2122
22- type State = { |
23- realmInputValue : string ,
24- error : string | null ,
25- progress : boolean ,
26- | } ;
27-
2823const urlFromInputValue = ( realmInputValue : string ) : URL | void => {
2924 const withScheme = / ^ h t t p s ? : \/ \/ / . test ( realmInputValue )
3025 ? realmInputValue
@@ -33,88 +28,85 @@ const urlFromInputValue = (realmInputValue: string): URL | void => {
3328 return tryParseUrl ( withScheme ) ;
3429} ;
3530
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 ;
4233
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 ) ;
4537
38+ const tryRealm = React . useCallback ( async ( ) => {
4639 const parsedRealm = urlFromInputValue ( realmInputValue ) ;
4740 if ( ! parsedRealm ) {
48- this . setState ( { error : 'Please enter a valid URL' } ) ;
41+ setError ( 'Please enter a valid URL' ) ;
4942 return ;
5043 }
5144 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' ) ;
5346 return ;
5447 }
5548
56- this . setState ( {
57- progress : true ,
58- error : null ,
59- } ) ;
49+ setProgress ( true ) ;
50+ setError ( null ) ;
6051 try {
6152 const serverSettings : ApiResponseServerSettings = await api . getServerSettings ( parsedRealm ) ;
62- this . props . navigation . push ( 'auth' , { serverSettings } ) ;
53+ navigation . push ( 'auth' , { serverSettings } ) ;
6354 Keyboard . dismiss ( ) ;
6455 } catch ( errorIllTyped ) {
6556 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' ) ;
6758 /* eslint-disable no-console */
6859 console . warn ( 'RealmInputScreen: failed to connect to server:' , err ) ;
6960 // $FlowFixMe[incompatible-cast]: assuming caught exception was Error
7061 console . warn ( ( err : Error ) . stack ) ;
7162 } finally {
72- this . setState ( { progress : false } ) ;
63+ setProgress ( false ) ;
7364 }
74- } ;
75-
76- handleRealmChange : string => void = value => this . setState ( { realmInputValue : value } ) ;
65+ } , [ navigation , realmInputValue ] ) ;
7766
78- render ( ) : Node {
79- const { navigation } = this . props ;
80- const { progress , error , realmInputValue } = this . state ;
67+ const handleRealmChange = useCallback ( value => {
68+ setRealmInputValue ( value ) ;
69+ } , [ ] ) ;
8170
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+ ) ;
8780
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+ ) ;
120112}
0 commit comments