@@ -18,6 +18,7 @@ import { TranslationContext } from '../boot/TranslationProvider';
18
18
import type { LocalizableText } from '../types' ;
19
19
import { getGlobalSettings } from '../directSelectors' ;
20
20
import { useGlobalSelector } from '../react-redux' ;
21
+ import ZulipText from '../common/ZulipText' ;
21
22
import WebLink from '../common/WebLink' ;
22
23
23
24
type Props = $ReadOnly < { |
@@ -85,6 +86,29 @@ const tryParseInput = (realmInputValue: string): MaybeParsedInput => {
85
86
return { valid : true , value : url } ;
86
87
} ;
87
88
89
+ type Suggestion = ValidationError | null ;
90
+
91
+ function getSuggestion ( realmInputValue , maybeParsedInput ) : Suggestion {
92
+ if ( ! maybeParsedInput . valid ) {
93
+ switch ( maybeParsedInput . error ) {
94
+ case ValidationError . NoUseEmail :
95
+ case ValidationError . UnsupportedSchemeZulip :
96
+ case ValidationError . UnsupportedSchemeOther :
97
+ // Flag high-signal errors
98
+ return maybeParsedInput . error ;
99
+
100
+ case ValidationError . Empty :
101
+ case ValidationError . InvalidUrl :
102
+ // Don't flag more noisy errors, which will often happen when the user
103
+ // just hasn't finished typing a good URL. They'll still show up if
104
+ // they apply at submit time; see the submit handler.
105
+ }
106
+ }
107
+
108
+ // TODO(?): Suggest e.g. CZO or a zulipchat.com URL
109
+ return null ;
110
+ }
111
+
88
112
export default function RealmInputScreen ( props : Props ) : Node {
89
113
const { navigation, route } = props ;
90
114
@@ -143,6 +167,8 @@ export default function RealmInputScreen(props: Props): Node {
143
167
Keyboard . dismiss ( ) ;
144
168
} , [ navigation , maybeParsedInput , globalSettings , _ ] ) ;
145
169
170
+ const suggestion = getSuggestion ( realmInputValue , maybeParsedInput ) ;
171
+
146
172
const styles = React . useMemo (
147
173
( ) =>
148
174
createStyleSheet ( {
@@ -158,12 +184,29 @@ export default function RealmInputScreen(props: Props): Node {
158
184
fontSize : 20 ,
159
185
color : themeContext . color ,
160
186
} ,
161
- hintText : { paddingLeft : 2 , fontSize : 12 } ,
187
+ suggestionText : { fontSize : 12 , fontStyle : 'italic' } ,
162
188
button : { marginTop : 8 } ,
163
189
} ) ,
164
190
[ themeContext ] ,
165
191
) ;
166
192
193
+ const renderedSuggestion = React . useMemo ( ( ) => {
194
+ if ( suggestion === null ) {
195
+ // Vertical spacer so the layout doesn't jump when a suggestion
196
+ // appears or disappears. (The empty string might be neater, but it
197
+ // doesn't give the right height… probably lots of people wanted it to
198
+ // be treated just like false/null/undefined in conditional rendering,
199
+ // and React or RN gave in to that. I've tried the obvious ways to use
200
+ // RN's PixelRatio.getFontScale() and never got the right height
201
+ // either; dunno why.)
202
+ return (
203
+ < ZulipText style = { styles . suggestionText } text = { '\u200b' } /* U+200B ZERO WIDTH SPACE */ />
204
+ ) ;
205
+ } else {
206
+ return < ZulipTextIntl style = { styles . suggestionText } text = { validationErrorMsg ( suggestion ) } /> ;
207
+ }
208
+ } , [ suggestion , styles ] ) ;
209
+
167
210
return (
168
211
< Screen
169
212
title = "Welcome"
@@ -205,7 +248,7 @@ export default function RealmInputScreen(props: Props): Node {
205
248
ref = { textInputRef }
206
249
/>
207
250
</ View >
208
- < ZulipTextIntl text = "e.g. zulip.example.com" style = { styles . hintText } />
251
+ { renderedSuggestion }
209
252
< ZulipButton
210
253
style = { styles . button }
211
254
text = "Enter"
0 commit comments