react-native-windows 0.81.37 → 0.81.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Microsoft.ReactNative/Fabric/AbiComponentDescriptor.cpp +6 -2
- package/Microsoft.ReactNative/Fabric/AbiShadowNode.cpp +0 -47
- package/Microsoft.ReactNative/Fabric/AbiShadowNode.h +40 -8
- package/Microsoft.ReactNative/Fabric/AbiState.h +26 -8
- package/Microsoft.ReactNative/Fabric/AbiTextInputProps.h +51 -0
- package/Microsoft.ReactNative/Fabric/AbiTextInputShadowNode.cpp +88 -0
- package/Microsoft.ReactNative/Fabric/AbiTextInputShadowNode.h +65 -0
- package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.h +52 -18
- package/Microsoft.ReactNative/Fabric/AbiViewShadowNode.cpp +0 -18
- package/Microsoft.ReactNative/Fabric/AbiViewShadowNode.h +16 -4
- package/Microsoft.ReactNative/Fabric/ComponentView.cpp +2 -1
- package/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp +1 -2
- package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +1 -1
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +3 -2
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +6 -4
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +6 -4
- package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +2 -1
- package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +22 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +2 -1
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/AbiTextInputState.h +38 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/ConcreteTextInputShadowNode.h +272 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentDescriptor.h +21 -14
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +345 -90
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +24 -4
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h +1 -1
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +0 -205
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +22 -65
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.h +2 -1
- package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +0 -1
- package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +5 -0
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +0 -1
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +60 -5
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +3 -0
- package/Microsoft.ReactNative/ViewProps.idl +11 -0
- package/Microsoft.ReactNative/Views/ViewViewManager.cpp +2 -2
- package/Microsoft.ReactNative.Cxx/ComponentView.Experimental.interop.h +12 -0
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/PropertySheets/JSEngine.props +1 -1
- package/PropertySheets/React.Cpp.props +0 -1
- package/PropertySheets/WinUI.props +2 -1
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/Instance.cpp +386 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.h +148 -0
- package/Scripts/EnableInternalWinAppSDKFeed.ps1 +12 -5
- package/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 +2 -2
- package/Shared/Networking/WinRTWebSocketResource.h +1 -5
- package/Shared/OInstance.cpp +13 -8
- package/Shared/Shared.vcxitems +3 -3
- package/Shared/Shared.vcxitems.filters +1 -1
- package/external/folly/folly.vcxitems +10 -0
- package/index.windows.js +5 -0
- package/package.json +4 -4
- package/Microsoft.ReactNative/Fabric/AbiState.cpp +0 -29
|
@@ -367,7 +367,8 @@ void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentView
|
|
|
367
367
|
void ComponentView::onLostFocus(
|
|
368
368
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
369
369
|
if (args.OriginalSource() == Tag()) {
|
|
370
|
-
m_eventEmitter
|
|
370
|
+
if (m_eventEmitter)
|
|
371
|
+
m_eventEmitter->onBlur();
|
|
371
372
|
|
|
372
373
|
if (m_componentHostingFocusVisual) {
|
|
373
374
|
auto s = get_strong();
|
|
@@ -415,7 +416,8 @@ winrt::com_ptr<ComponentView> ComponentView::focusVisualRoot(const facebook::rea
|
|
|
415
416
|
void ComponentView::onGotFocus(
|
|
416
417
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
417
418
|
if (args.OriginalSource() == Tag()) {
|
|
418
|
-
m_eventEmitter
|
|
419
|
+
if (m_eventEmitter)
|
|
420
|
+
m_eventEmitter->onFocus();
|
|
419
421
|
if (viewProps()->enableFocusRing &&
|
|
420
422
|
rootComponentView()->focusState() == winrt::Microsoft::ReactNative::FocusState::Keyboard) {
|
|
421
423
|
facebook::react::Rect focusRect = m_layoutMetrics.frame;
|
|
@@ -1376,7 +1378,7 @@ void ViewComponentView::OnKeyDown(
|
|
|
1376
1378
|
((args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::RightWindows) &
|
|
1377
1379
|
winrt::Microsoft::UI::Input::VirtualKeyStates::Down) == winrt::Microsoft::UI::Input::VirtualKeyStates::Down);
|
|
1378
1380
|
|
|
1379
|
-
if (args.OriginalSource() == Tag() && !args.Handled()) {
|
|
1381
|
+
if (m_eventEmitter && args.OriginalSource() == Tag() && !args.Handled()) {
|
|
1380
1382
|
facebook::react::KeyEvent event;
|
|
1381
1383
|
event.shiftKey = fShift;
|
|
1382
1384
|
event.ctrlKey = fCtrl;
|
|
@@ -1423,7 +1425,7 @@ void ViewComponentView::OnKeyUp(
|
|
|
1423
1425
|
((args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::RightWindows) &
|
|
1424
1426
|
winrt::Microsoft::UI::Input::VirtualKeyStates::Down) == winrt::Microsoft::UI::Input::VirtualKeyStates::Down);
|
|
1425
1427
|
|
|
1426
|
-
if (args.OriginalSource() == Tag()) {
|
|
1428
|
+
if (m_eventEmitter && args.OriginalSource() == Tag()) {
|
|
1427
1429
|
facebook::react::KeyEvent event;
|
|
1428
1430
|
event.shiftKey = fShift;
|
|
1429
1431
|
event.ctrlKey = fCtrl;
|
package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp
CHANGED
|
@@ -77,10 +77,12 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
|
|
|
77
77
|
const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portalComponentView) noexcept {
|
|
78
78
|
m_reactContext = portalComponentView.ReactContext();
|
|
79
79
|
|
|
80
|
-
portalComponentView.Mounted(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
portalComponentView.Mounted([](const auto & /*sender*/, const auto &view) {
|
|
81
|
+
view.UserData().template as<ModalHostView>()->OnMounted(view);
|
|
82
|
+
});
|
|
83
|
+
portalComponentView.Unmounted([](const auto & /*sender*/, const auto &view) {
|
|
84
|
+
view.UserData().template as<ModalHostView>()->OnUnmounted(view);
|
|
85
|
+
});
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
void UpdateProps(
|
|
@@ -354,7 +354,8 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
|
|
|
354
354
|
DWRITE_TEXT_METRICS metrics;
|
|
355
355
|
winrt::check_hresult(m_textLayout->GetMetrics(&metrics));
|
|
356
356
|
|
|
357
|
-
if (metrics.width == 0 || metrics.height == 0
|
|
357
|
+
if (metrics.width == 0 || metrics.height == 0 || m_layoutMetrics.frame.size.width == 0 ||
|
|
358
|
+
m_layoutMetrics.frame.size.height == 0) {
|
|
358
359
|
m_drawingSurface = nullptr;
|
|
359
360
|
return;
|
|
360
361
|
}
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
#include "pch.h"
|
|
5
5
|
#include "ReactCompositionViewComponentBuilder.h"
|
|
6
|
+
#include <Fabric/AbiComponentDescriptor.h>
|
|
6
7
|
#include <Fabric/AbiViewComponentDescriptor.h>
|
|
7
8
|
#include <Fabric/Composition/CompositionViewComponentView.h>
|
|
8
9
|
#include <Fabric/Composition/ContentIslandComponentView.h>
|
|
9
10
|
#include <Fabric/Composition/PortalComponentView.h>
|
|
11
|
+
#include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
|
|
10
12
|
#include <strsafe.h>
|
|
11
13
|
#include "CompositionContextHelper.h"
|
|
12
14
|
#include "DynamicWriter.h"
|
|
@@ -133,6 +135,26 @@ void ReactCompositionViewComponentBuilder::SetPortalComponentViewInitializer(
|
|
|
133
135
|
};
|
|
134
136
|
}
|
|
135
137
|
|
|
138
|
+
void ReactCompositionViewComponentBuilder::SetTextInputComponentViewInitializer(
|
|
139
|
+
const TextInputComponentViewInitializer &initializer) noexcept {
|
|
140
|
+
m_fnCreateView = [initializer](
|
|
141
|
+
const IReactContext &reactContext,
|
|
142
|
+
int32_t tag,
|
|
143
|
+
const Experimental::ICompositionContext &context,
|
|
144
|
+
ComponentViewFeatures /*features*/,
|
|
145
|
+
ReactCompositionViewComponentBuilder &builder)
|
|
146
|
+
-> winrt::Microsoft::ReactNative::Composition::WindowsTextInputComponentView {
|
|
147
|
+
auto view = winrt::make<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>(
|
|
148
|
+
context, tag, reactContext, &builder);
|
|
149
|
+
initializer(view);
|
|
150
|
+
return view;
|
|
151
|
+
};
|
|
152
|
+
m_descriptorConstructorFactory = []() {
|
|
153
|
+
return &facebook::react::concreteComponentDescriptorConstructor<
|
|
154
|
+
::Microsoft::ReactNative::AbiWindowsTextInputComponentDescriptor>;
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
136
158
|
// (Object handle, Microsoft.ReactNative.IComponentState state) => void
|
|
137
159
|
// void ReactCompositionViewComponentBuilder::SetStateUpdater(StateUpdater impl) noexcept {
|
|
138
160
|
// m_stateUpdater = impl;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright (c) Microsoft Corporation.
|
|
3
3
|
// Licensed under the MIT License.
|
|
4
4
|
|
|
5
|
-
#include <Fabric/
|
|
5
|
+
#include <Fabric/AbiViewProps.h>
|
|
6
6
|
#include <react/renderer/componentregistry/ComponentDescriptorProvider.h>
|
|
7
7
|
#include <react/renderer/core/ReactPrimitives.h>
|
|
8
8
|
#include "winrt/Microsoft.ReactNative.Composition.Experimental.h"
|
|
@@ -51,6 +51,7 @@ struct ReactCompositionViewComponentBuilder
|
|
|
51
51
|
void SetIVisualToMountChildrenIntoHandler(
|
|
52
52
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate impl) noexcept;
|
|
53
53
|
void SetUpdateLayoutMetricsHandler(UpdateLayoutMetricsDelegate impl) noexcept;
|
|
54
|
+
void SetTextInputComponentViewInitializer(const TextInputComponentViewInitializer &initializer) noexcept;
|
|
54
55
|
|
|
55
56
|
public:
|
|
56
57
|
IComponentProps CreateProps(ViewProps props, const IComponentProps &cloneFrom) noexcept;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "ViewProps.g.h"
|
|
7
|
+
|
|
8
|
+
#include <react/renderer/core/ConcreteState.h>
|
|
9
|
+
#include <react/renderer/core/State.h>
|
|
10
|
+
#include "WindowsTextInputState.h"
|
|
11
|
+
#include "winrt/Microsoft.ReactNative.h"
|
|
12
|
+
|
|
13
|
+
namespace Microsoft::ReactNative {
|
|
14
|
+
|
|
15
|
+
class AbiTextInputStateData : public facebook::react::WindowsTextInputState {
|
|
16
|
+
public:
|
|
17
|
+
AbiTextInputStateData() = default;
|
|
18
|
+
// AbiTextInputStateData(winrt::Windows::Foundation::IInspectable data) : userdata(data) {}
|
|
19
|
+
AbiTextInputStateData(
|
|
20
|
+
facebook::react::AttributedStringBox attributedStringBox,
|
|
21
|
+
facebook::react::AttributedString reactTreeAttributedString,
|
|
22
|
+
facebook::react::ParagraphAttributes paragraphAttributes,
|
|
23
|
+
int64_t mostRecentEventCount,
|
|
24
|
+
winrt::Windows::Foundation::IInspectable userdata)
|
|
25
|
+
: facebook::react::WindowsTextInputState(
|
|
26
|
+
std::move(attributedStringBox),
|
|
27
|
+
std::move(reactTreeAttributedString),
|
|
28
|
+
std::move(paragraphAttributes),
|
|
29
|
+
mostRecentEventCount),
|
|
30
|
+
userdata(userdata) {}
|
|
31
|
+
|
|
32
|
+
AbiTextInputStateData(winrt::Windows::Foundation::IInspectable userdata)
|
|
33
|
+
: facebook::react::WindowsTextInputState({}), userdata(userdata) {}
|
|
34
|
+
|
|
35
|
+
winrt::Windows::Foundation::IInspectable userdata;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
|
|
2
|
+
#include <react/renderer/attributedstring/AttributedString.h>
|
|
3
|
+
#include <react/renderer/attributedstring/AttributedStringBox.h>
|
|
4
|
+
#include <react/renderer/attributedstring/PlaceholderAttributedString.h>
|
|
5
|
+
#include <react/renderer/attributedstring/TextAttributes.h>
|
|
6
|
+
#include <react/renderer/components/text/BaseTextShadowNode.h>
|
|
7
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
8
|
+
#include <react/renderer/core/LayoutConstraints.h>
|
|
9
|
+
#include <react/renderer/core/LayoutContext.h>
|
|
10
|
+
#include <react/renderer/core/conversions.h>
|
|
11
|
+
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
|
12
|
+
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
|
|
13
|
+
#include <react/utils/ContextContainer.h>
|
|
14
|
+
|
|
15
|
+
namespace facebook::react {
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* `ShadowNode` for <WindowsTextInput> component.
|
|
19
|
+
*/
|
|
20
|
+
template <const char *concreteComponentName, typename Props, typename EventEmitter, typename State>
|
|
21
|
+
class ConcreteTextInputShadowNode
|
|
22
|
+
: public facebook::react::ConcreteViewShadowNode<concreteComponentName, Props, EventEmitter, State> {
|
|
23
|
+
public:
|
|
24
|
+
using Super = facebook::react::ConcreteViewShadowNode<concreteComponentName, Props, EventEmitter, State>;
|
|
25
|
+
using Super::Super;
|
|
26
|
+
|
|
27
|
+
static facebook::react::ShadowNodeTraits BaseTraits() {
|
|
28
|
+
auto traits = Super::BaseTraits();
|
|
29
|
+
traits.set(facebook::react::ShadowNodeTraits::Trait::LeafYogaNode);
|
|
30
|
+
traits.set(facebook::react::ShadowNodeTraits::Trait::MeasurableYogaNode);
|
|
31
|
+
traits.set(facebook::react::ShadowNodeTraits::Trait::BaselineYogaNode);
|
|
32
|
+
return traits;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
* Associates a shared TextLayoutManager with the node.
|
|
37
|
+
* `TextInputShadowNode` uses the manager to measure text content
|
|
38
|
+
* and construct `TextInputState` objects.
|
|
39
|
+
*/
|
|
40
|
+
void setTextLayoutManager(std::shared_ptr<const facebook::react::TextLayoutManager> textLayoutManager) {
|
|
41
|
+
Super::ensureUnsealed();
|
|
42
|
+
textLayoutManager_ = std::move(textLayoutManager);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
protected:
|
|
46
|
+
facebook::react::Size measureContent(
|
|
47
|
+
const facebook::react::LayoutContext &layoutContext,
|
|
48
|
+
const facebook::react::LayoutConstraints &layoutConstraints) const override {
|
|
49
|
+
// Layout is called right after measure.
|
|
50
|
+
// Measure is marked as `const`, and `layout` is not; so State can be
|
|
51
|
+
// updated during layout, but not during `measure`. If State is out-of-date
|
|
52
|
+
// in layout, it's too late: measure will have already operated on old
|
|
53
|
+
// State. Thus, we use the same value here that we *will* use in layout to
|
|
54
|
+
// update the state.
|
|
55
|
+
facebook::react::AttributedString attributedString = getMostRecentAttributedString(layoutContext);
|
|
56
|
+
|
|
57
|
+
if (attributedString.isEmpty()) {
|
|
58
|
+
attributedString = getPlaceholderAttributedString(layoutContext);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// BaseTextShadowNode only gets children. We must detect and prepend text
|
|
62
|
+
// value attributes manually.
|
|
63
|
+
if (!Super::getConcreteProps().text.empty()) {
|
|
64
|
+
auto textAttributes = facebook::react::TextAttributes::defaultTextAttributes();
|
|
65
|
+
textAttributes.apply(Super::getConcreteProps().textAttributes);
|
|
66
|
+
auto fragment = facebook::react::AttributedString::Fragment{};
|
|
67
|
+
fragment.string = Super::getConcreteProps().text;
|
|
68
|
+
fragment.textAttributes = textAttributes;
|
|
69
|
+
// If the TextInput opacity is 0 < n < 1, the opacity of the TextInput and
|
|
70
|
+
// text value's background will stack. This is a hack/workaround to prevent
|
|
71
|
+
// that effect.
|
|
72
|
+
fragment.textAttributes.backgroundColor = facebook::react::clearColor();
|
|
73
|
+
fragment.parentShadowView = facebook::react::ShadowView(*this);
|
|
74
|
+
attributedString.prependFragment(std::move(fragment));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
facebook::react::TextLayoutContext textLayoutContext;
|
|
78
|
+
textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor;
|
|
79
|
+
|
|
80
|
+
facebook::react::ParagraphAttributes paragraphAttributes{};
|
|
81
|
+
paragraphAttributes.maximumNumberOfLines = Super::getConcreteProps().multiline ? 0 : 1;
|
|
82
|
+
return textLayoutManager_
|
|
83
|
+
->measure(
|
|
84
|
+
facebook::react::AttributedStringBox{attributedString},
|
|
85
|
+
paragraphAttributes,
|
|
86
|
+
textLayoutContext,
|
|
87
|
+
layoutConstraints)
|
|
88
|
+
.size;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
void layout(facebook::react::LayoutContext layoutContext) override {
|
|
92
|
+
updateStateIfNeeded(layoutContext);
|
|
93
|
+
Super::layout(layoutContext);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
facebook::react::Float baseline(const facebook::react::LayoutContext &layoutContext, facebook::react::Size size)
|
|
97
|
+
const override {
|
|
98
|
+
// Calculate baseline as 80% of the text height
|
|
99
|
+
return size.height * 0.8f;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
std::shared_ptr<const facebook::react::TextLayoutManager> textLayoutManager_;
|
|
103
|
+
|
|
104
|
+
/*
|
|
105
|
+
* Determines the constraints to use while measure the underlying text
|
|
106
|
+
*/
|
|
107
|
+
facebook::react::LayoutConstraints getTextConstraints(
|
|
108
|
+
const facebook::react::LayoutConstraints &layoutConstraints) const {
|
|
109
|
+
if (Super::getConcreteProps().multiline) {
|
|
110
|
+
return layoutConstraints;
|
|
111
|
+
} else {
|
|
112
|
+
// A single line TextInput acts as a horizontal scroller of infinitely
|
|
113
|
+
// expandable text, so we want to measure the text as if it is allowed to
|
|
114
|
+
// infinitely expand horizontally, and later clamp to the constraints of the
|
|
115
|
+
// input.
|
|
116
|
+
return facebook::react::LayoutConstraints{
|
|
117
|
+
.minimumSize = layoutConstraints.minimumSize,
|
|
118
|
+
.maximumSize =
|
|
119
|
+
facebook::react::Size{
|
|
120
|
+
.width = std::numeric_limits<facebook::react::Float>::infinity(),
|
|
121
|
+
.height = layoutConstraints.maximumSize.height,
|
|
122
|
+
},
|
|
123
|
+
.layoutDirection = layoutConstraints.layoutDirection,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
protected:
|
|
129
|
+
// Overridable method so that the Abi version can maintain user's state
|
|
130
|
+
virtual void updateTextInputState(
|
|
131
|
+
facebook::react::AttributedStringBox attributedStringBox,
|
|
132
|
+
facebook::react::AttributedString &reactTreeAttributedString,
|
|
133
|
+
facebook::react::ParagraphAttributes paragraphAttributes,
|
|
134
|
+
int64_t mostRecentEventCount) = 0;
|
|
135
|
+
|
|
136
|
+
/*
|
|
137
|
+
* Creates a `State` object (with `AttributedText` and
|
|
138
|
+
* `TextLayoutManager`) if needed.
|
|
139
|
+
*/
|
|
140
|
+
void updateStateIfNeeded(const facebook::react::LayoutContext &layoutContext) {
|
|
141
|
+
Super::ensureUnsealed();
|
|
142
|
+
const auto &stateData = Super::getStateData();
|
|
143
|
+
auto reactTreeAttributedString = getAttributedString(layoutContext);
|
|
144
|
+
|
|
145
|
+
// Tree is often out of sync with the value of the TextInput.
|
|
146
|
+
// This is by design - don't change the value of the TextInput in the State,
|
|
147
|
+
// and therefore in Java, unless the tree itself changes.
|
|
148
|
+
if (stateData.reactTreeAttributedString == reactTreeAttributedString) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// If props event counter is less than what we already have in state, skip it
|
|
153
|
+
const auto &props = Super::getConcreteProps();
|
|
154
|
+
if (props.mostRecentEventCount < stateData.mostRecentEventCount) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Store default TextAttributes in state.
|
|
159
|
+
// In the case where the TextInput is completely empty (no value, no
|
|
160
|
+
// defaultValue, no placeholder, no children) there are therefore no fragments
|
|
161
|
+
// in the AttributedString, and when State is updated, it needs some way to
|
|
162
|
+
// reconstruct a Fragment with default TextAttributes.
|
|
163
|
+
auto defaultTextAttributes = facebook::react::TextAttributes::defaultTextAttributes();
|
|
164
|
+
defaultTextAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
|
|
165
|
+
defaultTextAttributes.apply(Super::getConcreteProps().textAttributes);
|
|
166
|
+
|
|
167
|
+
auto newEventCount = stateData.reactTreeAttributedString.isContentEqual(reactTreeAttributedString)
|
|
168
|
+
? 0
|
|
169
|
+
: Super::getConcreteProps().mostRecentEventCount;
|
|
170
|
+
auto newAttributedString = getMostRecentAttributedString(layoutContext);
|
|
171
|
+
|
|
172
|
+
// Even if we're here and updating state, it may be only to update the layout
|
|
173
|
+
// manager If that is the case, make sure we don't update text: pass in the
|
|
174
|
+
// current attributedString unchanged, and pass in zero for the "event count"
|
|
175
|
+
// so no changes are applied There's no way to prevent a state update from
|
|
176
|
+
// flowing to Java, so we just ensure it's a noop in those cases.
|
|
177
|
+
|
|
178
|
+
updateTextInputState(
|
|
179
|
+
facebook::react::AttributedStringBox(newAttributedString), reactTreeAttributedString, {}, newEventCount);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
* Returns a `AttributedString` which represents text content of the node.
|
|
184
|
+
*/
|
|
185
|
+
facebook::react::AttributedString getAttributedString(const facebook::react::LayoutContext &layoutContext) const {
|
|
186
|
+
// Use BaseTextShadowNode to get attributed string from children
|
|
187
|
+
|
|
188
|
+
auto childTextAttributes = facebook::react::TextAttributes::defaultTextAttributes();
|
|
189
|
+
childTextAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
|
|
190
|
+
childTextAttributes.apply(Super::getConcreteProps().textAttributes);
|
|
191
|
+
// Don't propagate the background color of the TextInput onto the attributed
|
|
192
|
+
// string. Android tries to render shadow of the background alongside the
|
|
193
|
+
// shadow of the text which results in weird artifacts.
|
|
194
|
+
childTextAttributes.backgroundColor = facebook::react::HostPlatformColor::UndefinedColor;
|
|
195
|
+
|
|
196
|
+
auto attributedString = facebook::react::AttributedString{};
|
|
197
|
+
auto attachments = facebook::react::BaseTextShadowNode::Attachments{};
|
|
198
|
+
facebook::react::BaseTextShadowNode::buildAttributedString(
|
|
199
|
+
childTextAttributes, *this, attributedString, attachments);
|
|
200
|
+
attributedString.setBaseTextAttributes(childTextAttributes);
|
|
201
|
+
|
|
202
|
+
// BaseTextShadowNode only gets children. We must detect and prepend text
|
|
203
|
+
// value attributes manually.
|
|
204
|
+
if (!Super::getConcreteProps().text.empty()) {
|
|
205
|
+
auto textAttributes = facebook::react::TextAttributes::defaultTextAttributes();
|
|
206
|
+
textAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
|
|
207
|
+
textAttributes.apply(Super::getConcreteProps().textAttributes);
|
|
208
|
+
textAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
|
|
209
|
+
auto fragment = facebook::react::AttributedString::Fragment{};
|
|
210
|
+
fragment.string = Super::getConcreteProps().text;
|
|
211
|
+
fragment.textAttributes = textAttributes;
|
|
212
|
+
// If the TextInput opacity is 0 < n < 1, the opacity of the TextInput and
|
|
213
|
+
// text value's background will stack. This is a hack/workaround to prevent
|
|
214
|
+
// that effect.
|
|
215
|
+
fragment.textAttributes.backgroundColor = facebook::react::clearColor();
|
|
216
|
+
fragment.parentShadowView = facebook::react::ShadowView(*this);
|
|
217
|
+
attributedString.prependFragment(std::move(fragment));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return attributedString;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get the most up-to-date attributed string for measurement and State.
|
|
225
|
+
*/
|
|
226
|
+
facebook::react::AttributedString getMostRecentAttributedString(
|
|
227
|
+
const facebook::react::LayoutContext &layoutContext) const {
|
|
228
|
+
const auto &state = Super::getStateData();
|
|
229
|
+
|
|
230
|
+
auto reactTreeAttributedString = getAttributedString(layoutContext);
|
|
231
|
+
|
|
232
|
+
// Sometimes the treeAttributedString will only differ from the state
|
|
233
|
+
// not by inherent properties (string or prop attributes), but by the frame of
|
|
234
|
+
// the parent which has changed Thus, we can't directly compare the entire
|
|
235
|
+
// AttributedString
|
|
236
|
+
bool treeAttributedStringChanged =
|
|
237
|
+
!state.reactTreeAttributedString.compareTextAttributesWithoutFrame(reactTreeAttributedString);
|
|
238
|
+
|
|
239
|
+
return (!treeAttributedStringChanged ? state.attributedStringBox.getValue() : reactTreeAttributedString);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
facebook::react::AttributedString getPlaceholderAttributedString(
|
|
243
|
+
const facebook::react::LayoutContext &layoutContext) const {
|
|
244
|
+
const auto &props = Super::getConcreteProps();
|
|
245
|
+
|
|
246
|
+
facebook::react::AttributedString attributedString;
|
|
247
|
+
attributedString.setBaseTextAttributes(props.textAttributes);
|
|
248
|
+
//[windows
|
|
249
|
+
if (!props.placeholder.empty()) {
|
|
250
|
+
auto textAttributes = facebook::react::TextAttributes::defaultTextAttributes();
|
|
251
|
+
textAttributes.fontSizeMultiplier = layoutContext.fontSizeMultiplier;
|
|
252
|
+
textAttributes.apply(props.textAttributes);
|
|
253
|
+
|
|
254
|
+
/*
|
|
255
|
+
* These props are applied to `View`, therefore they must not be a part of
|
|
256
|
+
* base text attributes.
|
|
257
|
+
*/
|
|
258
|
+
textAttributes.backgroundColor = facebook::react::clearColor();
|
|
259
|
+
textAttributes.opacity = 1;
|
|
260
|
+
|
|
261
|
+
attributedString.appendFragment(
|
|
262
|
+
{.string = props.placeholder,
|
|
263
|
+
.textAttributes = textAttributes,
|
|
264
|
+
.parentShadowView = facebook::react::ShadowView(*this)});
|
|
265
|
+
}
|
|
266
|
+
// windows]
|
|
267
|
+
|
|
268
|
+
return ensurePlaceholderIfEmpty_DO_NOT_USE(attributedString);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
} // namespace facebook::react
|
package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentDescriptor.h
CHANGED
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
#include <yoga/YGEnums.h>
|
|
9
9
|
#include <yoga/YGValue.h>
|
|
10
10
|
|
|
11
|
-
#include <unordered_map>
|
|
12
|
-
|
|
13
11
|
#include <react/renderer/components/text/ParagraphComponentDescriptor.h>
|
|
14
12
|
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
15
13
|
|
|
@@ -18,11 +16,15 @@ namespace facebook::react {
|
|
|
18
16
|
/*
|
|
19
17
|
* Descriptor for <WindowsTextInput> component.
|
|
20
18
|
*/
|
|
21
|
-
|
|
19
|
+
template <typename TShadowNode>
|
|
20
|
+
class ConcreteWindowsTextInputComponentDescriptor : public ConcreteComponentDescriptor<TShadowNode> {
|
|
21
|
+
using Super = ConcreteComponentDescriptor<TShadowNode>;
|
|
22
|
+
using Super::Super;
|
|
23
|
+
|
|
22
24
|
public:
|
|
23
|
-
|
|
24
|
-
:
|
|
25
|
-
textLayoutManager_(getManagerByName<TextLayoutManager>(contextContainer_, TextLayoutManagerKey)) {}
|
|
25
|
+
ConcreteWindowsTextInputComponentDescriptor(const ComponentDescriptorParameters ¶meters)
|
|
26
|
+
: Super(parameters),
|
|
27
|
+
textLayoutManager_(getManagerByName<TextLayoutManager>(this->contextContainer_, TextLayoutManagerKey)) {}
|
|
26
28
|
|
|
27
29
|
/*
|
|
28
30
|
virtual State::Shared createInitialState(
|
|
@@ -67,7 +69,7 @@ virtual State::Shared createInitialState(
|
|
|
67
69
|
|
|
68
70
|
protected:
|
|
69
71
|
void adopt(ShadowNode &shadowNode) const override {
|
|
70
|
-
auto &textInputShadowNode = static_cast<
|
|
72
|
+
auto &textInputShadowNode = static_cast<TShadowNode &>(shadowNode);
|
|
71
73
|
|
|
72
74
|
// `TextInputShadowNode` uses `TextLayoutManager` to measure text content
|
|
73
75
|
// and communicate text rendering metrics to mounting layer.
|
|
@@ -138,12 +140,12 @@ virtual State::Shared createInitialState(
|
|
|
138
140
|
}
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
textInputShadowNode.dirtyLayout();
|
|
142
|
-
|
|
143
143
|
*/
|
|
144
|
+
// Native text and formatting updates change intrinsic size without changing Yoga props.
|
|
145
|
+
textInputShadowNode.dirtyLayout();
|
|
144
146
|
textInputShadowNode.enableMeasurement();
|
|
145
147
|
|
|
146
|
-
|
|
148
|
+
Super::adopt(shadowNode);
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
private:
|
|
@@ -154,11 +156,16 @@ virtual State::Shared createInitialState(
|
|
|
154
156
|
float bottom{};
|
|
155
157
|
};
|
|
156
158
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
const std::shared_ptr<const TextLayoutManager> textLayoutManager_;
|
|
160
|
+
// mutable std::unordered_map<int, ThemePadding> surfaceIdToThemePaddingMap_;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
class WindowsTextInputComponentDescriptor final
|
|
164
|
+
: public ConcreteWindowsTextInputComponentDescriptor<WindowsTextInputShadowNode> {
|
|
165
|
+
using Super = ConcreteWindowsTextInputComponentDescriptor<WindowsTextInputShadowNode>;
|
|
159
166
|
|
|
160
|
-
|
|
161
|
-
|
|
167
|
+
public:
|
|
168
|
+
WindowsTextInputComponentDescriptor(const ComponentDescriptorParameters ¶meters) : Super(parameters) {}
|
|
162
169
|
};
|
|
163
170
|
|
|
164
171
|
} // namespace facebook::react
|