Skip to content

Commit

Permalink
Just keep characters mode for now
Browse files Browse the repository at this point in the history
  • Loading branch information
danielayala94 committed Jul 19, 2024
1 parent d9b18ef commit 60ca1ce
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 139 deletions.
14 changes: 6 additions & 8 deletions packages/e2e-test-app-fabric/test/TextInputComponentTest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ describe('TextInput Tests', () => {
);
expect(await component.getText()).toBe('hello world');
});
test('TextInputs can autocapitalize: Autocapitalize Sentences', async () => {
// Comment out once the sentences mode has been implemented.
/*test('TextInputs can autocapitalize: Autocapitalize Sentences', async () => {
const component = await app.findElementByTestID('capitalize-sentences');
await component.waitForDisplayed({timeout: 5000});
const dump = await dumpVisualTree('capitalize-sentences');
Expand All @@ -132,8 +133,9 @@ describe('TextInput Tests', () => {
timeout: 5000,
timeoutMsg: `Unable to enter correct text.`,
});
});
test('TextInputs can autocapitalize: Autocapitalize Words', async () => {
});*/
// Comment out once the words mode has been implemented.
/*test('TextInputs can autocapitalize: Autocapitalize Words', async () => {
const component = await app.findElementByTestID('capitalize-words');
await component.waitForDisplayed({timeout: 5000});
const dump = await dumpVisualTree('capitalize-words');
Expand All @@ -152,16 +154,12 @@ describe('TextInput Tests', () => {
timeout: 5000,
timeoutMsg: `Unable to enter correct text.`,
});
});
});*/
test('TextInputs can autocapitalize: Autocapitalize Characters', async () => {
const component = await app.findElementByTestID('capitalize-characters');
await component.waitForDisplayed({timeout: 5000});
const dump = await dumpVisualTree('capitalize-characters');
expect(dump).toMatchSnapshot();

// Test behavior when text is set from JS
// Comment for now, the returned text is in lowercase, even though the UI shows it is all capitalized.
// expect(await component.getText()).toBe('INITIAL TEXT IS CAPITALIZED');

await app.waitUntil(
async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -895,14 +895,7 @@ void WindowsTextInputComponentView::OnCharacterReceived(
}
emitter->onKeyPress(onKeyPressArgs);

WPARAM wParam;

// Auto-capitalize when character is alphabetic AND current string index qualifies for capitalization.
if (std::isalpha(args.KeyCode()) && shouldAutoCapitalize()) {
wParam = static_cast<WPARAM>(std::towupper(static_cast<wchar_t>(args.KeyCode())));
} else {
wParam = static_cast<WPARAM>(args.KeyCode());
}
WPARAM wParam = static_cast<WPARAM>(args.KeyCode());

LPARAM lParam = 0;
lParam = args.KeyStatus().RepeatCount; // bits 0-15
Expand Down Expand Up @@ -1058,7 +1051,6 @@ void WindowsTextInputComponentView::updateProps(
m_submitKeyEvents.clear();
}

// Modify this structure, let autoCapitalizeOnUpdateProps take all the stuff
if (oldTextInputProps.autoCapitalize != newTextInputProps.autoCapitalize) {
autoCapitalizeOnUpdateProps(oldTextInputProps.autoCapitalize, newTextInputProps.autoCapitalize);
}
Expand Down Expand Up @@ -1534,7 +1526,7 @@ winrt::Microsoft::ReactNative::ComponentView WindowsTextInputComponentView::Crea
return winrt::make<WindowsTextInputComponentView>(compContext, tag, reactContext);
}

// This functions assumes that previous and new capitalization types are different.
// This function assumes that previous and new capitalization types are different.
void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
const std::string &previousCapitalizationType,
const std::string &newCapitalizationType) noexcept {
Expand All @@ -1544,6 +1536,8 @@ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
Words - First letter of each word.
Sentences - First letter of each sentence.
None - Do not autocapitalize anything.
For now, only characters and none are supported.
*/

if (previousCapitalizationType == "characters") {
Expand All @@ -1554,85 +1548,7 @@ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
if (newCapitalizationType == "characters") {
winrt::check_hresult(m_textServices->TxSendMessage(
EM_SETEDITSTYLE, SES_UPPERCASE /* enable */, SES_UPPERCASE /* flag affected */, nullptr /* LRESULT */));
} else if (newCapitalizationType == "words" || newCapitalizationType == "sentences") {
// Cast text services to text document to get an ITextRange object
winrt::com_ptr<ITextDocument> textDocument;
winrt::check_hresult(m_textServices->QueryInterface(textDocument.put()));

// tomForward is a constant that indicates the end of the text range.
winrt::com_ptr<ITextRange> textRange;
winrt::check_hresult(textDocument->Range(0 /* start of string */, tomForward, textRange.put()));

if (newCapitalizationType == "words") {
winrt::check_hresult(textRange->ChangeCase(tomTitleCase));
} else if (newCapitalizationType == "sentences") {
winrt::check_hresult(textRange->ChangeCase(tomSentenceCase));
}
}
}

bool WindowsTextInputComponentView::shouldAutoCapitalize() {
std::string_view autoCapitalizeType = windowsTextInputProps().autoCapitalize;

// Characters scenario is already handled by RichEdit, return false to avoid taking any further action.
if (autoCapitalizeType == "characters") {
return false;
} else if (autoCapitalizeType == "words") {
auto textServicesString = GetTextFromRichEdit();

if (textServicesString.empty()) {
return true;
}

winrt::com_ptr<ITextDocument> textDocument;
winrt::check_hresult(m_textServices->QueryInterface(textDocument.put()));

winrt::com_ptr<ITextSelection> textSelection;
winrt::check_hresult(textDocument->GetSelection(textSelection.put()));

long pos = 0; // Retrieve the current string index where cursor is sitting.
winrt::check_hresult(textSelection->GetStart(&pos));

if (pos == 0) { // Cursor is pointing at the start of the string.
return true;
} else if (std::isspace(textServicesString[pos - 1])) { // Previous character is a whitespace.
return true;
}
} else if (autoCapitalizeType == "sentences") {
auto textServicesString = GetTextFromRichEdit();

if (textServicesString.empty()) {
return true;
} else {
winrt::com_ptr<ITextDocument> textDocument;
winrt::check_hresult(m_textServices->QueryInterface(textDocument.put()));

winrt::com_ptr<ITextSelection> textSelection;
winrt::check_hresult(textDocument->GetSelection(textSelection.put()));

long pos = 0; // Retrieve the current string index where cursor is sitting.
winrt::check_hresult(textSelection->GetStart(&pos));

if (pos == 0) { // Cursor is pointing at the start of the string.
return true;
} else if (std::all_of(textServicesString.begin(), textServicesString.begin() + pos, [](char c) { return std::isspace(c); })) {
// Check if characters to the left of pos are all whitespace.
return true;
} else if (pos >= 2) {
// Check for some punctuation mark patterns.
auto secondToLastChar = textServicesString[pos - 2];
bool isPunctuationMarkChar = secondToLastChar == '.' || secondToLastChar == '!' || secondToLastChar == '?';

// If the last character is a space AND the second-to-last character is a
// punctuation mark, then we want to capitalize.
if (isPunctuationMarkChar && std::isspace(textServicesString[pos - 1])) {
return true;
}
}
}
}

return false;
}

} // namespace winrt::Microsoft::ReactNative::Composition::implementation
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ struct WindowsTextInputComponentView
void autoCapitalizeOnUpdateProps(
const std::string &previousCapitalizationType,
const std::string &newcapitalizationType) noexcept;
bool shouldAutoCapitalize();

winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
Expand Down
112 changes: 70 additions & 42 deletions vnext/Microsoft.ReactNative/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"Microsoft.UI.Xaml": {
"type": "Direct",
"requested": "[2.8.0, )",
"resolved": "2.8.0",
"contentHash": "vxdHxTr63s5KVtNddMFpgvjBjUH50z7seq/5jLWmmSuf8poxg+sXrywkofUdE8ZstbpO9y3FL/IXXUcPYbeesA==",
"dependencies": {
"Microsoft.Web.WebView2": "1.0.1264.42"
}
},
"Microsoft.Windows.CppWinRT": {
"type": "Direct",
"requested": "[2.0.230706.1, )",
"resolved": "2.0.230706.1",
"contentHash": "l0D7oCw/5X+xIKHqZTi62TtV+1qeSz7KVluNFdrJ9hXsst4ghvqQ/Yhura7JqRdZWBXAuDS0G0KwALptdoxweQ=="
},
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "1.1.1",
Expand All @@ -49,10 +49,10 @@
"resolved": "1.1.1",
"contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg=="
},
"Microsoft.Web.WebView2": {
"Microsoft.Windows.SDK.BuildTools": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"resolved": "10.0.22621.756",
"contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA=="
},
"common": {
"type": "Project",
Expand All @@ -66,8 +66,8 @@
"folly": {
"type": "Project",
"dependencies": {
"Fmt": "[1.0.0, )",
"boost": "[1.76.0, )"
"boost": "[1.76.0, )",
"fmt": "[1.0.0, )"
}
},
"reactcommon": {
Expand All @@ -79,52 +79,80 @@
}
},
"native,Version=v0.0/win10-arm": {
"Microsoft.Web.WebView2": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-arm-aot": {
"Microsoft.Web.WebView2": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-arm64-aot": {
"Microsoft.Web.WebView2": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x64": {
"Microsoft.Web.WebView2": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x64-aot": {
"Microsoft.Web.WebView2": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x86": {
"Microsoft.Web.WebView2": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
},
"native,Version=v0.0/win10-x86-aot": {
"Microsoft.Web.WebView2": {
"type": "Transitive",
"resolved": "1.0.1264.42",
"contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
"Microsoft.WindowsAppSDK": {
"type": "Direct",
"requested": "[1.5.240227000, )",
"resolved": "1.5.240227000",
"contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==",
"dependencies": {
"Microsoft.Windows.SDK.BuildTools": "10.0.22621.756"
}
}
}
}
Expand Down

0 comments on commit 60ca1ce

Please sign in to comment.