Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Caret position on WEB #17331

Merged
merged 17 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
98ad44a
calculates the position of the caret and updates the component state …
perunt Apr 12, 2023
b452aa8
eslint
perunt Apr 12, 2023
d35ea9b
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt Apr 17, 2023
c33ef11
Merge branch 'main' of https://github.com/margelo/expensify-app-fork …
perunt Apr 21, 2023
23472c3
change func name to addCursorPositionToSelectionChange
perunt Apr 21, 2023
70903e7
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt Apr 24, 2023
b855615
add optional statement
perunt Apr 24, 2023
5ae86d5
fix positionY
perunt May 3, 2023
7ff9e1e
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt May 4, 2023
3381a58
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt May 5, 2023
92ec9ce
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt May 10, 2023
aec217b
prettier
perunt May 10, 2023
05ddf81
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt May 10, 2023
499a755
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt May 10, 2023
5240081
Merge branch 'perunt/web-caret-position' of https://github.com/margel…
perunt May 12, 2023
49d961d
addressed comment after review
perunt May 12, 2023
d3d530a
Merge branch 'main' of https://github.com/Expensify/App into perunt/w…
perunt May 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 84 additions & 20 deletions src/components/Composer/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable rulesdir/onyx-props-must-have-default */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this? It looks like you did set a default for the new prop you added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially set a default value, but ran into linter issues. After rechecking, the specific issue is resolved. However, we're facing additional errors with the linter, unrelated to this PR. It seems to conflict with our new Prettier configuration.

import React from 'react';
import {StyleSheet} from 'react-native';
import {StyleSheet, View} from 'react-native';
import PropTypes from 'prop-types';
import _ from 'underscore';
import ExpensiMark from 'expensify-common/lib/ExpensiMark';
Expand All @@ -15,6 +16,7 @@ import Clipboard from '../../libs/Clipboard';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
import compose from '../../libs/compose';
import styles from '../../styles/styles';
import Text from '../Text';

const propTypes = {
/** Maximum number of lines in the text input */
Expand Down Expand Up @@ -73,6 +75,9 @@ const propTypes = {
/** Whether the composer is full size */
isComposerFullSize: PropTypes.bool,

/** Whether the composer is full size */
shouldCalculateCaretPosition: PropTypes.bool,

...withLocalizePropTypes,

...windowDimensionsPropTypes,
Expand All @@ -99,6 +104,7 @@ const defaultProps = {
isFullComposerAvailable: false,
setIsFullComposerAvailable: () => {},
isComposerFullSize: false,
shouldCalculateCaretPosition: false,
};

const IMAGE_EXTENSIONS = {
Expand Down Expand Up @@ -129,6 +135,7 @@ class Composer extends React.Component {
start: initialValue.length,
end: initialValue.length,
},
valueBeforeCaret: '',
};

this.paste = this.paste.bind(this);
Expand All @@ -137,6 +144,8 @@ class Composer extends React.Component {
this.handleWheel = this.handleWheel.bind(this);
this.putSelectionInClipboard = this.putSelectionInClipboard.bind(this);
this.shouldCallUpdateNumberOfLines = this.shouldCallUpdateNumberOfLines.bind(this);
this.addCursorPositionToSelectionChange = this.addCursorPositionToSelectionChange.bind(this);
this.textRef = React.createRef(null);
}

componentDidMount() {
Expand Down Expand Up @@ -190,6 +199,36 @@ class Composer extends React.Component {
this.textInput.removeEventListener('wheel', this.handleWheel);
}

addCursorPositionToSelectionChange(event) {
if (this.props.shouldCalculateCaretPosition) {
this.setState(
{
valueBeforeCaret: event.target.value.slice(
0,
event.nativeEvent.selection.start,
),
},

() => {
const customEvent = {
nativeEvent: {
selection: {
start: event.nativeEvent.selection.start,
end: event.nativeEvent.selection.end,
positionX: this.textRef.current.offsetLeft,
positionY: this.textRef.current.offsetTop,
},
},
};
this.props.onSelectionChange(customEvent);
},
);
return;
}

this.props.onSelectionChange(event);
}

/**
* Set pasted text to clipboard
* @param {String} text
Expand Down Expand Up @@ -348,6 +387,7 @@ class Composer extends React.Component {
updateIsFullComposerAvailable(this.props, numberOfLines);
this.setState({
numberOfLines,
width: computedStyle.width,
});
this.props.onNumberOfLinesChange(numberOfLines);
});
Expand All @@ -358,28 +398,52 @@ class Composer extends React.Component {
propStyles.outline = 'none';
const propsWithoutStyles = _.omit(this.props, 'style');

// This code creates a hidden text component that helps track the caret position in the visible input.

const calculationCaretPositionElement = (
<View
style={{
position: 'absolute',
bottom: -2000,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this changes made a regression - #26535

zIndex: -1,
opacity: 0,
}}
>
<Text
multiline
style={[styles.textInputCompose, {width: this.state.width}]}
>
{this.state.valueBeforeCaret}
<Text ref={this.textRef} />
</Text>
</View>
);

// We're disabling autoCorrect for iOS Safari until Safari fixes this issue. See https://github.com/Expensify/App/issues/8592
return (
<RNTextInput
autoComplete="off"
autoCorrect={!Browser.isMobileSafari()}
placeholderTextColor={themeColors.placeholderText}
ref={el => this.textInput = el}
selection={this.state.selection}
onChange={this.shouldCallUpdateNumberOfLines}
onSelectionChange={this.onSelectionChange}
style={[
propStyles,

// We are hiding the scrollbar to prevent it from reducing the text input width,
// so we can get the correct scroll height while calculating the number of lines.
this.state.numberOfLines < this.props.maxLines ? styles.overflowHidden : {},
]}
<>
<RNTextInput
autoComplete="off"
autoCorrect={!Browser.isMobileSafari()}
placeholderTextColor={themeColors.placeholderText}
ref={el => this.textInput = el}
selection={this.state.selection}
onChange={this.shouldCallUpdateNumberOfLines}
style={[
propStyles,

// We are hiding the scrollbar to prevent it from reducing the text input width,
// so we can get the correct scroll height while calculating the number of lines.
this.state.numberOfLines < this.props.maxLines ? styles.overflowHidden : {},
]}
/* eslint-disable-next-line react/jsx-props-no-spreading */
{...propsWithoutStyles}
numberOfLines={this.state.numberOfLines}
disabled={this.props.isDisabled}
/>
{...propsWithoutStyles}
onSelectionChange={this.addCursorPositionToSelectionChange}
numberOfLines={this.state.numberOfLines}
disabled={this.props.isDisabled}
/>
{this.props.shouldCalculateCaretPosition && calculationCaretPositionElement}
</>
);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/pages/home/report/ReportActionCompose.js
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,7 @@ class ReportActionCompose extends React.Component {
value={this.state.value}
numberOfLines={this.props.numberOfLines}
onNumberOfLinesChange={this.updateNumberOfLines}
shouldCalculateCaretPosition
onLayout={(e) => {
const composerHeight = e.nativeEvent.layout.height;
if (this.state.composerHeight === composerHeight) {
Expand Down