Skip to content

Commit

Permalink
Pass callbacks for when grammarCheck, spellCheck and autoCorrect are …
Browse files Browse the repository at this point in the history
…changed on Mac [RFC]

When users change spellCheck, grammarCheck or autoCorrect in the context menu, one of 3 callbacks for MULTILINE inputs are called:
- toggleGrammarChecking
- toggleContinuousSpellChecking
- toggleAutomaticSpellingCorrection

If JS is going to be the source of truth for text proofing settings, we should have a way to notify JS when these settings are changed from the native side.
  • Loading branch information
Alex Chiu authored and christophpurrer committed Aug 4, 2022
1 parent e6482e0 commit a1911e5
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 2 deletions.
42 changes: 41 additions & 1 deletion Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ export type EditingEvent = SyntheticEvent<
|}>,
>;

// macOS-only // [TODO(macOS GH#774)
export type StateChangeEvent = SyntheticEvent<
$ReadOnly<{|
enabled: boolean,
|}>,
>; // ]TODO(macOS GH#774)


type DataDetectorTypesType =
// iOS+macOS
| 'phoneNumber'
Expand Down Expand Up @@ -306,7 +314,7 @@ type IOSProps = $ReadOnly<{|
// [TODO(macOS GH#774)
/**
* If `false`, disables grammar-check.
* @platform macOS
* @platform macos
*/
grammarCheck?: ?boolean,
// ]TODO(macOS GH#774)
Expand Down Expand Up @@ -637,6 +645,38 @@ export type Props = $ReadOnly<{|
*/
onChangeText?: ?(text: string) => mixed,

// [TODO(macOS GH#774)
/**
* Callback that is called when the text input's autoCorrect setting changes.
* This will be called with
* `{ nativeEvent: { enabled } }`.
* Does only work with 'multiline={true}'.
*
* @platform macos
*/
onAutoCorrectChange?: ?(e: StateChangeEvent) => mixed,

/**
* Callback that is called when the text input's spellCheck setting changes.
* This will be called with
* `{ nativeEvent: { enabled } }`.
* Does only work with 'multiline={true}'.
*
* @platform macos
*/
onSpellCheckChange?: ?(e: StateChangeEvent) => mixed,

/**
* Callback that is called when the text input's grammarCheck setting changes.
* This will be called with
* `{ nativeEvent: { enabled } }`.
* Does only work with 'multiline={true}'.
*
* @platform macos
*/
onGrammarCheckChange?: ?(e: StateChangeEvent) => mixed,
// ]TODO(macOS GH#774)

/**
* DANGER: this API is not stable and will change in the future.
*
Expand Down
18 changes: 18 additions & 0 deletions Libraries/Text/TextInput/Multiline/RCTUITextView.m
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@ - (void)setPlaceholderColor:(RCTUIColor *)placeholderColor // TODO(OSS Candidate
}

#if TARGET_OS_OSX // [TODO(macOS GH#774)
- (void)toggleAutomaticSpellingCorrection:(id)sender
{
self.automaticSpellingCorrectionEnabled = !self.isAutomaticSpellingCorrectionEnabled;
[_textInputDelegate automaticSpellingCorrectionDidChange:self.isAutomaticSpellingCorrectionEnabled];
}

- (void)toggleContinuousSpellChecking:(id)sender
{
self.continuousSpellCheckingEnabled = !self.isContinuousSpellCheckingEnabled;
[_textInputDelegate continuousSpellCheckingDidChange:self.isContinuousSpellCheckingEnabled];
}

- (void)toggleGrammarChecking:(id)sender
{
self.grammarCheckingEnabled = !self.isGrammarCheckingEnabled;
[_textInputDelegate grammarCheckingDidChange:self.isGrammarCheckingEnabled];
}

- (void)setSelectionColor:(RCTUIColor *)selectionColor
{
NSMutableDictionary *selectTextAttributes = self.selectedTextAttributes.mutableCopy;
Expand Down
4 changes: 4 additions & 0 deletions Libraries/Text/TextInput/RCTBackedTextInputDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)textInputShouldReturn; // May be called right before `textInputShouldEndEditing` if "Return" button was pressed.
- (void)textInputDidReturn;

- (void)automaticSpellingCorrectionDidChange:(BOOL)enabled;
- (void)continuousSpellCheckingDidChange:(BOOL)enabled;
- (void)grammarCheckingDidChange:(BOOL)enabled;

/*
* Called before any change in the TextInput. The delegate has the opportunity to change the replacement string or reject the change completely.
* To change the replacement, return the changed version of the `text`.
Expand Down
5 changes: 5 additions & 0 deletions Libraries/Text/TextInput/RCTBaseTextInputView.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy, nullable) RCTDirectEventBlock onChangeSync;
@property (nonatomic, copy, nullable) RCTDirectEventBlock onTextInput;
@property (nonatomic, copy, nullable) RCTDirectEventBlock onScroll;
#if TARGET_OS_OSX // TODO(macOS GH#774)
@property (nonatomic, copy, nullable) RCTDirectEventBlock onAutoCorrectChange;
@property (nonatomic, copy, nullable) RCTDirectEventBlock onSpellCheckChange;
@property (nonatomic, copy, nullable) RCTDirectEventBlock onGrammarCheckChange;
#endif // TODO(macOS GH#774)

@property (nonatomic, assign) NSInteger mostRecentEventCount;
@property (nonatomic, assign, readonly) NSInteger nativeEventCount;
Expand Down
20 changes: 20 additions & 0 deletions Libraries/Text/TextInput/RCTBaseTextInputView.m
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,26 @@ - (void)textInputDidEndEditing
key:nil
eventCount:_nativeEventCount];
}
- (void)automaticSpellingCorrectionDidChange:(BOOL)enabled
{
if (_onAutoCorrectChange) {
_onAutoCorrectChange(@{@"enabled": [NSNumber numberWithBool:enabled]});
}
}

- (void)continuousSpellCheckingDidChange:(BOOL)enabled
{
if (_onSpellCheckChange) {
_onSpellCheckChange(@{@"enabled": [NSNumber numberWithBool:enabled]});
}
}

- (void)grammarCheckingDidChange:(BOOL)enabled
{
if (_onGrammarCheckChange) {
_onGrammarCheckChange(@{@"enabled": [NSNumber numberWithBool:enabled]});
}
}

- (BOOL)textInputShouldReturn
{
Expand Down
6 changes: 6 additions & 0 deletions Libraries/Text/TextInput/RCTBaseTextInputViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ @implementation RCTBaseTextInputViewManager
RCT_EXPORT_VIEW_PROPERTY(textContentType, NSString)
RCT_EXPORT_VIEW_PROPERTY(passwordRules, NSString)

#if TARGET_OS_OSX // TODO(macOS GH#774)
RCT_EXPORT_VIEW_PROPERTY(onAutoCorrectChange, RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onSpellCheckChange, RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onGrammarCheckChange, RCTBubblingEventBlock);
#endif // TODO(macOS GH#774)

RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onKeyPressSync, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onChangeSync, RCTDirectEventBlock)
Expand Down
24 changes: 23 additions & 1 deletion packages/rn-tester/js/examples/TextInput/TextInputExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const {
Switch,
Alert,
} = require('react-native');
import type {KeyboardType} from 'react-native/Libraries/Components/TextInput/TextInput';
import type {KeyboardType, StateChangeEvent} from 'react-native/Libraries/Components/TextInput/TextInput';

const TextInputSharedExamples = require('./TextInputSharedExamples.js');

Expand Down Expand Up @@ -820,4 +820,26 @@ exports.examples = ([
);
},
},
{
title: 'AutoCorrect, spellCheck and grammarCheck callbacks - Multiline Textfield',
render: function(): React.Node {
const [enableAutoCorrect, setEnableAutoCorrect] = React.useState(false);
const [enableSpellSpeck, setEnableSpellSpeck] = React.useState(false);
const [enableGrammarCheck, setEnableGrammarCheck] = React.useState(false);
return (
<>
<Text>enableAutoCorrect: {enableAutoCorrect ? "enabled" : "disabled"}</Text>
<Text>enableSpellSpeck: {enableSpellSpeck ? "enabled" : "disabled"}</Text>
<Text>enableGrammarCheck: {enableGrammarCheck ? "enabled" : "disabled"}</Text>
<TextInput
autoCorrect={enableAutoCorrect}
style={{padding: 10, marginTop: 10}}
multiline={true}
onAutoCorrectChange={(event: StateChangeEvent) => setEnableAutoCorrect(event.nativeEvent.enabled)}
onSpellCheckChange={(event: StateChangeEvent) => setEnableSpellSpeck(event.nativeEvent.enabled)}
onGrammarCheckChange={(event: StateChangeEvent) => setEnableGrammarCheck(event.nativeEvent.enabled)}
/>
</>);
},
},
]: Array<RNTesterModuleExample>);

0 comments on commit a1911e5

Please sign in to comment.