2
2
import React , { useState , useCallback } from 'react' ;
3
3
import type { Node } from 'react' ;
4
4
import { Keyboard } from 'react-native' ;
5
+ import Clipboard from '@react-native-clipboard/clipboard' ;
5
6
6
7
import type { RouteProp } from '../react-navigation' ;
7
8
import type { AppNavigationProp } from '../nav/AppNavigator' ;
@@ -15,6 +16,7 @@ import ZulipButton from '../common/ZulipButton';
15
16
import { tryParseUrl } from '../utils/url' ;
16
17
import * as api from '../api' ;
17
18
import { navigateToAuth } from '../actions' ;
19
+ import { useClipboardHasURL } from '../@react-native-clipboard/clipboard' ;
18
20
19
21
type Props = $ReadOnly < { |
20
22
navigation : AppNavigationProp < 'realm-input' > ,
@@ -69,6 +71,24 @@ export default function RealmInputScreen(props: Props): Node {
69
71
button : { marginTop : 8 } ,
70
72
} ;
71
73
74
+ const tryCopiedUrl = useCallback ( async ( ) => {
75
+ // The copied string might not be a valid realm URL:
76
+ // - It might not be a URL because useClipboardHasURL is subject to
77
+ // races (and Clipboard.getString is itself async).
78
+ // - It might not be a valid Zulip realm that the client can connect to.
79
+ //
80
+ // So…
81
+ const url = await Clipboard . getString ( ) ;
82
+
83
+ // …let the user see what string is being tried and edit it if it fails…
84
+ setRealmInputValue ( url ) ;
85
+
86
+ // …and run it through our usual validation.
87
+ await tryRealm ( url ) ;
88
+ } , [ tryRealm ] ) ;
89
+
90
+ const clipboardHasURL = useClipboardHasURL ( ) ;
91
+
72
92
return (
73
93
< Screen
74
94
title = "Welcome"
@@ -99,6 +119,32 @@ export default function RealmInputScreen(props: Props): Node {
99
119
onPress = { handleInputSubmit }
100
120
disabled = { tryParseUrl ( realmInputValue ) === undefined }
101
121
/>
122
+ { clipboardHasURL === true && (
123
+ // We prepopulate the input with https:// to help when you're not
124
+ // copy-pasting. (Not everyone has memorized that sequence of
125
+ // characters.)
126
+ //
127
+ // When you *do* want to copy-paste, though, prepopulating with
128
+ // https:// can be annoying -- you don't want to end up with
129
+ // https://https://chat.zulip.org.
130
+ //
131
+ // To solve that, it's risky to fuss around with the input value
132
+ // while the user is focused on it, or overcomplicate the input
133
+ // field (like by breaking it into two parts). I think these kinds
134
+ // of solutions risk leaving some users confused or dissatisfied.
135
+ //
136
+ // Instead, we try to recognize when the user has copied a URL, and
137
+ // let them use it without making them enter it into the input.
138
+ //
139
+ // TODO(?): Instead, use a FAB that persists while
140
+ // clipboardHasURL !== true && !progress
141
+ < ZulipButton
142
+ style = { styles . button }
143
+ text = "Use copied URL"
144
+ progress = { progress }
145
+ onPress = { tryCopiedUrl }
146
+ />
147
+ ) }
102
148
</ Screen >
103
149
) ;
104
150
}
0 commit comments