Skip to content

Commit

Permalink
SmartUrlInput: Remove not-so-helpful "smart"ness
Browse files Browse the repository at this point in the history
And just use an ordinary controlled TextInput, always stretched to
full width, and never just 1px.

The major reason for this is to help with #5228 (can't paste org
URL): native copy-paste is activated by long-pressing in the input
element itself. But long-pressing is really hard when the element is
only 1px wide!

No need to autocomplete with "zulipchat.com", so as not to annoy
self-hosted users, as discussed. It does seem helpful to prepopulate
with "https://" for the sake of users who aren't copy-pasting.

With that "https://" prepopulating in mind, we'll improve this
experience further, along the lines of what Alya says:

> One would have to play with pasting behavior to make sure
> something reasonable happens if you are trying to paste in a whole
> URL, including the https part.

That'll come later in this series.

See discussion at
  https://chat.zulip.org/#narrow/stream/48-mobile/topic/can't.20paste.20org.20URL/near/1327170

Fixes-partly: #5228
  • Loading branch information
chrisbobbe committed Mar 10, 2022
1 parent 77d578f commit f3d37ee
Showing 1 changed file with 10 additions and 48 deletions.
58 changes: 10 additions & 48 deletions src/common/SmartUrlInput.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
/* @flow strict-local */
import React, { useState, useRef, useCallback, useContext } from 'react';
import type { Node } from 'react';
import { Platform, TextInput, TouchableWithoutFeedback, View, Keyboard } from 'react-native';
import { Platform, TextInput, View, Keyboard } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';

import type { AppNavigationProp } from '../nav/AppNavigator';
import { ThemeContext, createStyleSheet } from '../styles';
import { autocompleteRealmPieces, autocompleteRealm, fixRealmUrl } from '../utils/url';
import ZulipText from './ZulipText';

const styles = createStyleSheet({
wrapper: {
flexDirection: 'row',
opacity: 0.8,
},
realmInput: {
flex: 1,
padding: 0,
fontSize: 20,
},
realmPlaceholder: {
opacity: 0.75,
},
realmInputEmpty: {
width: 1,
},
});

type Props = $ReadOnly<{|
// TODO: Currently this type is acceptable because the only
// `navigation` prop we pass to a `SmartUrlInput` instance is the
// one from a component on AppNavigator.
navigation: AppNavigationProp<>,

style?: ViewStyleProp,
onChangeText: (value: string) => void,
onSubmitEditing: () => Promise<void>,
Expand Down Expand Up @@ -93,8 +87,11 @@ export default function SmartUrlInput(props: Props): Node {
/**
* The actual input string, exactly as entered by the user,
* without modifications by autocomplete.
*
* Prepopulates with "https://", because not everyone has memorized that
* sequence of characters.
*/
const [value, setValue] = useState<string>('');
const [value, setValue] = useState<string>('https://');

const themeContext = useContext(ThemeContext);

Expand All @@ -113,26 +110,11 @@ export default function SmartUrlInput(props: Props): Node {
const handleChange = useCallback(
(_value: string) => {
setValue(_value);

onChangeText(
fixRealmUrl(autocompleteRealm(_value, { protocol: 'https://', domain: 'zulipchat.com' })),
);
onChangeText(_value);
},
[onChangeText],
);

// When the "placeholder parts" are pressed, i.e., the parts of the URL
// line that aren't the TextInput itself, we still want to focus the
// TextInput.
// TODO(?): Is it a confusing UX to have a line that looks and acts like
// a text input, but parts of it aren't really?
const urlPress = useCallback(() => {
if (textInputRef.current) {
// `.current` is not type-checked; see definition.
textInputRef.current.focus();
}
}, []);

if (Platform.OS === 'android') {
// (This eslint-disable is fine; the relevant rule is not to call Hooks
// conditionally. But this conditional won't vary in its behavior
Expand All @@ -141,29 +123,11 @@ export default function SmartUrlInput(props: Props): Node {
useRn19366Workaround(textInputRef);
}

const renderPlaceholderPart = (text: string) => (
<TouchableWithoutFeedback onPress={urlPress}>
<ZulipText
style={[styles.realmInput, { color: themeContext.color }, styles.realmPlaceholder]}
text={text}
/>
</TouchableWithoutFeedback>
);

const [prefix, , suffix] = autocompleteRealmPieces(value, {
domain: 'zulipchat.com',
protocol: 'https://',
});

return (
<View style={[styles.wrapper, style]}>
{prefix !== null && renderPlaceholderPart(prefix)}
<TextInput
style={[
styles.realmInput,
{ color: themeContext.color },
value.length === 0 && styles.realmInputEmpty,
]}
value={value}
style={[styles.realmInput, { color: themeContext.color }]}
autoFocus
autoCorrect={false}
autoCapitalize="none"
Expand All @@ -176,8 +140,6 @@ export default function SmartUrlInput(props: Props): Node {
enablesReturnKeyAutomatically={enablesReturnKeyAutomatically}
ref={textInputRef}
/>
{!value && renderPlaceholderPart('your-org')}
{suffix !== null && renderPlaceholderPart(suffix)}
</View>
);
}

0 comments on commit f3d37ee

Please sign in to comment.