Skip to content

Commit

Permalink
finish transform text and changes from testing
Browse files Browse the repository at this point in the history
  • Loading branch information
buoyad committed Sep 17, 2018
1 parent 4cead52 commit 8c9ad7c
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 10 deletions.
4 changes: 4 additions & 0 deletions shared/common-adapters/hoc-timers.js
Expand Up @@ -78,6 +78,10 @@ function HOCTimers<Props: TimerProps>(
}
}

// TODO forward a ref to `WrappedComponent` when react-redux is patched to
// work with React.forwardRef.
// https://github.com/reduxjs/react-redux/pull/1000

return TimersComponent
}

Expand Down
4 changes: 3 additions & 1 deletion shared/common-adapters/plain-input.js.flow
Expand Up @@ -94,6 +94,8 @@ declare export default class PlainInput extends React.Component<Props> {
static defaultProps: DefaultProps;
blur: () => void;
focus: () => void;
// Supported only on desktop right now
// Note that a selection will only appear when the input is focused. Call
// `focus()` before this if you want to be sure the user will see the
// selection.
transformText: (fn: (TextInfo) => TextInfo, reflectChange?: boolean) => void;
}
36 changes: 27 additions & 9 deletions shared/common-adapters/plain-input.native.js
Expand Up @@ -2,7 +2,6 @@
import React, {Component} from 'react'
import {getStyle as getTextStyle} from './text'
import {NativeTextInput} from './native-wrappers.native'
import HOCTimers, {type PropsWithTimer} from './hoc-timers'
import {collapseStyles, globalColors, styleSheetCreate} from '../styles'
import {isIOS} from '../constants/platform'
import {checkTextInfo} from './input.shared'
Expand All @@ -17,11 +16,9 @@ type State = {
height: ?number,
}

type Props = PropsWithTimer<InternalProps>

// A plain text input component. Handles callbacks, text styling, and auto resizing but
// adds no styling.
class _PlainInput extends Component<Props, State> {
class PlainInput extends Component<InternalProps, State> {
static defaultProps = {
keyboardType: 'default',
textType: 'Body',
Expand All @@ -35,10 +32,23 @@ class _PlainInput extends Component<Props, State> {
_lastNativeText: ?string // sourced from onChangeText
_lastNativeSelection: ?{start: number, end: number}

// TODO remove this when we can use forwardRef with react-redux. That'd let us
// use HOCTimers with this component.
// https://github.com/reduxjs/react-redux/pull/1000
_timeoutIDs = []

_setInputRef = (ref: ?NativeTextInput) => {
this._input = ref
}

_setTimeout = (fn: () => void, timeoutMS: number) => {
this._timeoutIDs.push(setTimeout(fn, timeoutMS))
}

componentWillUnmount() {
this._timeoutIDs.forEach(clearTimeout)
}

// Needed to support wrapping with e.g. a ClickableBox. See
// https://facebook.github.io/react-native/docs/direct-manipulation.html .
setNativeProps = (nativeProps: Object) => {
Expand All @@ -54,11 +64,20 @@ class _PlainInput extends Component<Props, State> {
checkTextInfo(newTextInfo)
this.setNativeProps({text: newTextInfo.text, selection: newTextInfo.selection})
this._lastNativeText = newTextInfo.text
this._lastNativeSelection = newTextInfo.selection
this._setSelection(newTextInfo.selection)
}

setSelection = (selection: {end: number, start: number}) => {
// this.props.setTimeout()
_setSelection = (selection: {start: number, end: number}) => {
this._setTimeout(() => {
// Validate that this selection makes sense with current value
let {start, end} = selection
const text = this._lastNativeText || '' // TODO write a good internal getValue fcn for this
end = Math.max(0, Math.min(end, text.length))
start = Math.min(start, end)
const newSelection = {start, end}
this.setNativeProps({selection: newSelection})
this._lastNativeSelection = selection
}, 0)
}

_onChangeText = (t: string) => {
Expand All @@ -67,7 +86,7 @@ class _PlainInput extends Component<Props, State> {
}

_onSelectionChange = (event: {nativeEvent: {selection: {start: number, end: number}}}) => {
let {start: _start, end: _end} = event.nativeEvent.selection
const {start: _start, end: _end} = event.nativeEvent.selection
// Work around Android bug which sometimes puts end before start:
// https://github.com/facebook/react-native/issues/18579 .
const start = Math.min(_start, _end)
Expand Down Expand Up @@ -196,7 +215,6 @@ class _PlainInput extends Component<Props, State> {
return <NativeTextInput {...props} />
}
}
const PlainInput = HOCTimers(_PlainInput)

const styles = styleSheetCreate({
common: {backgroundColor: globalColors.fastBlank, flexGrow: 1, borderWidth: 0},
Expand Down
1 change: 1 addition & 0 deletions shared/common-adapters/plain-input.stories.js
Expand Up @@ -34,6 +34,7 @@ class ControlledInputPlayground extends React.Component<{}, ControlledInputState
_onTestCrossSelection = () => {
if (this.mutationTarget.current) {
const input = this.mutationTarget.current
input.focus()
input.transformText(ti => ({text: '5char', selection: {start: 0, end: 0}}))
input.transformText(ti => ({text: 'a lot more than 5 characters', selection: {start: 3, end: 5}}))
}
Expand Down

0 comments on commit 8c9ad7c

Please sign in to comment.