@@ -18,6 +18,7 @@ import { TranslationContext } from '../boot/TranslationProvider';
1818import type { LocalizableText } from '../types' ;
1919import { getGlobalSettings } from '../directSelectors' ;
2020import { useGlobalSelector } from '../react-redux' ;
21+ import ZulipText from '../common/ZulipText' ;
2122import WebLink from '../common/WebLink' ;
2223
2324type Props = $ReadOnly < { |
@@ -85,6 +86,29 @@ const tryParseInput = (realmInputValue: string): MaybeParsedInput => {
8586 return { valid : true , value : url } ;
8687} ;
8788
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+
88112export default function RealmInputScreen ( props : Props ) : Node {
89113 const { navigation, route } = props ;
90114
@@ -143,6 +167,8 @@ export default function RealmInputScreen(props: Props): Node {
143167 Keyboard . dismiss ( ) ;
144168 } , [ navigation , maybeParsedInput , globalSettings , _ ] ) ;
145169
170+ const suggestion = getSuggestion ( realmInputValue , maybeParsedInput ) ;
171+
146172 const styles = React . useMemo (
147173 ( ) =>
148174 createStyleSheet ( {
@@ -158,12 +184,29 @@ export default function RealmInputScreen(props: Props): Node {
158184 fontSize : 20 ,
159185 color : themeContext . color ,
160186 } ,
161- hintText : { paddingLeft : 2 , fontSize : 12 } ,
187+ suggestionText : { fontSize : 12 , fontStyle : 'italic' } ,
162188 button : { marginTop : 8 } ,
163189 } ) ,
164190 [ themeContext ] ,
165191 ) ;
166192
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+
167210 return (
168211 < Screen
169212 title = "Welcome"
@@ -205,7 +248,7 @@ export default function RealmInputScreen(props: Props): Node {
205248 ref = { textInputRef }
206249 />
207250 </ View >
208- < ZulipTextIntl text = "e.g. zulip.example.com" style = { styles . hintText } />
251+ { renderedSuggestion }
209252 < ZulipButton
210253 style = { styles . button }
211254 text = "Enter"
0 commit comments