react-native-windows 0.0.0-canary.476 → 0.0.0-canary.477

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.
Files changed (57) hide show
  1. package/.flowconfig +1 -1
  2. package/Libraries/ActionSheetIOS/ActionSheetIOS.js +7 -0
  3. package/Libraries/ActionSheetIOS/NativeActionSheetManager.js +1 -0
  4. package/Libraries/Blob/URL.js +7 -1
  5. package/Libraries/Components/StatusBar/StatusBar.js +6 -1
  6. package/Libraries/Components/TextInput/TextInputState.js +10 -2
  7. package/Libraries/Components/TextInput/TextInputState.windows.js +10 -3
  8. package/Libraries/Components/TextInput/WindowsTextInputNativeComponent.js +1 -1
  9. package/Libraries/Core/ExceptionsManager.js +1 -1
  10. package/Libraries/Core/ReactNativeVersion.js +1 -1
  11. package/Libraries/LogBox/Data/LogBoxData.js +1 -1
  12. package/Libraries/LogBox/Data/LogBoxLog.js +1 -1
  13. package/Libraries/LogBox/Data/LogBoxSymbolication.js +1 -1
  14. package/Libraries/LogBox/Data/parseLogBoxLog.js +1 -1
  15. package/Libraries/LogBox/LogBox.js +2 -21
  16. package/Libraries/LogBox/UI/LogBoxInspectorFooter.js +1 -0
  17. package/Microsoft.ReactNative/Fabric/ComponentViewRegistry.cpp +13 -0
  18. package/Microsoft.ReactNative/Fabric/ComponentViewRegistry.h +1 -0
  19. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +11 -14
  20. package/Microsoft.ReactNative/Fabric/ScrollViewComponentView.cpp +2 -0
  21. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentDescriptor.h +197 -0
  22. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentView.cpp +308 -0
  23. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputComponentView.h +52 -0
  24. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputEventEmitter.cpp +31 -0
  25. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputEventEmitter.h +33 -0
  26. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputProps.cpp +81 -0
  27. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputProps.h +132 -0
  28. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputShadowNode.cpp +193 -0
  29. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputShadowNode.h +85 -0
  30. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputState.cpp +76 -0
  31. package/Microsoft.ReactNative/Fabric/TextInput/WindowsTextInputState.h +99 -0
  32. package/Microsoft.ReactNative/Fabric/ViewComponentView.cpp +31 -3
  33. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/slider/SliderMeasurementsManager.cpp +26 -15
  34. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +60 -49
  35. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +11 -3
  36. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +5 -0
  37. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +14 -1
  38. package/Microsoft.ReactNative/Views/TextInputViewManager.cpp +1 -1
  39. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +5 -1
  40. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems.filters +2 -3
  41. package/Microsoft.ReactNative.Managed/packages.lock.json +1 -1
  42. package/PropertySheets/Generated/PackageVersion.g.props +1 -1
  43. package/PropertySheets/React.Cpp.props +1 -0
  44. package/ReactCommon/ReactCommon.vcxproj +2 -1
  45. package/ReactCommon/ReactCommon.vcxproj.filters +4 -1
  46. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h +103 -0
  47. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h +61 -0
  48. package/Scripts/OfficeReact.Win32.nuspec +0 -2
  49. package/Scripts/Tfs/Layout-MSRN-Headers.ps1 +2 -1
  50. package/Shared/DevSupportManager.cpp +7 -2
  51. package/Shared/OInstance.cpp +1 -1
  52. package/codegen/NativeActionSheetManagerSpec.g.h +6 -0
  53. package/jest/preprocessor.js +24 -106
  54. package/jest/preprocessor_DO_NOT_USE.js +122 -0
  55. package/package.json +8 -8
  56. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/core/RawPropsParser.cpp +0 -162
  57. package/include/Shared/ViewManager.h +0 -34
package/.flowconfig CHANGED
@@ -118,4 +118,4 @@ untyped-import
118
118
  untyped-type-import
119
119
 
120
120
  [version]
121
- ^0.172.0
121
+ ^0.173.0
@@ -143,6 +143,13 @@ const ActionSheetIOS = {
143
143
  successCallback,
144
144
  );
145
145
  },
146
+
147
+ dismissActionSheet: () => {
148
+ invariant(RCTActionSheetManager, "ActionSheetManager doesn't exist");
149
+ if (typeof RCTActionSheetManager.dismissActionSheet === 'function') {
150
+ RCTActionSheetManager.dismissActionSheet();
151
+ }
152
+ },
146
153
  };
147
154
 
148
155
  module.exports = ActionSheetIOS;
@@ -47,6 +47,7 @@ export interface Spec extends TurboModule {
47
47
  |}) => void,
48
48
  successCallback: (completed: boolean, activityType: ?string) => void,
49
49
  ) => void;
50
+ +dismissActionSheet?: () => void;
50
51
  }
51
52
 
52
53
  export default (TurboModuleRegistry.get<Spec>('ActionSheetManager'): ?Spec);
@@ -101,7 +101,13 @@ export class URLSearchParams {
101
101
  }
102
102
  const last = this._searchParams.length - 1;
103
103
  return this._searchParams.reduce((acc, curr, index) => {
104
- return acc + curr.join('=') + (index === last ? '' : '&');
104
+ return (
105
+ acc +
106
+ encodeURIComponent(curr[0]) +
107
+ '=' +
108
+ encodeURIComponent(curr[1]) +
109
+ (index === last ? '' : '&')
110
+ );
105
111
  }, '');
106
112
  }
107
113
  }
@@ -471,7 +471,12 @@ class StatusBar extends React.Component<Props> {
471
471
  if (!oldProps || oldProps.hidden.value !== mergedProps.hidden.value) {
472
472
  NativeStatusBarManagerAndroid.setHidden(mergedProps.hidden.value);
473
473
  }
474
- if (!oldProps || oldProps.translucent !== mergedProps.translucent) {
474
+ // Activities are not translucent by default, so always set if true.
475
+ if (
476
+ !oldProps ||
477
+ oldProps.translucent !== mergedProps.translucent ||
478
+ mergedProps.translucent
479
+ ) {
475
480
  NativeStatusBarManagerAndroid.setTranslucent(mergedProps.translucent);
476
481
  }
477
482
  }
@@ -73,7 +73,7 @@ function blurField(textFieldID: ?number) {
73
73
  /**
74
74
  * @param {number} TextInputID id of the text field to focus
75
75
  * Focuses the specified text field
76
- * noop if the text field was already focused
76
+ * noop if the text field was already focused or if the field is not editable
77
77
  */
78
78
  function focusTextInput(textField: ?ComponentRef) {
79
79
  if (typeof textField === 'number') {
@@ -86,7 +86,15 @@ function focusTextInput(textField: ?ComponentRef) {
86
86
  return;
87
87
  }
88
88
 
89
- if (currentlyFocusedInputRef !== textField && textField != null) {
89
+ if (textField != null) {
90
+ const fieldCanBeFocused =
91
+ currentlyFocusedInputRef !== textField &&
92
+ // $FlowFixMe - `currentProps` is missing in `NativeMethods`
93
+ textField.currentProps?.editable !== false;
94
+
95
+ if (!fieldCanBeFocused) {
96
+ return;
97
+ }
90
98
  focusInput(textField);
91
99
  if (Platform.OS === 'ios') {
92
100
  // This isn't necessarily a single line text input
@@ -20,7 +20,6 @@ import {Commands as iOSTextInputCommands} from '../../Components/TextInput/RCTSi
20
20
  import {Commands as WindowsTextInputCommands} from '../../Components/TextInput/WindowsTextInputNativeComponent';
21
21
 
22
22
  import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
23
- import {UIManager} from 'react-native';
24
23
  type ComponentRef = React.ElementRef<HostComponent<mixed>>;
25
24
 
26
25
  let currentlyFocusedInputRef: ?ComponentRef = null;
@@ -75,7 +74,7 @@ function blurField(textFieldID: ?number) {
75
74
  /**
76
75
  * @param {number} TextInputID id of the text field to focus
77
76
  * Focuses the specified text field
78
- * noop if the text field was already focused
77
+ * noop if the text field was already focused or if the field is not editable
79
78
  */
80
79
  function focusTextInput(textField: ?ComponentRef) {
81
80
  if (typeof textField === 'number') {
@@ -97,7 +96,15 @@ function focusTextInput(textField: ?ComponentRef) {
97
96
  focusInput(textField);
98
97
  WindowsTextInputCommands.focus(textField);
99
98
  // Windows]
100
- } else if (currentlyFocusedInputRef !== textField && textField != null) {
99
+ } else if (textField != null) {
100
+ const fieldCanBeFocused =
101
+ currentlyFocusedInputRef !== textField &&
102
+ // $FlowFixMe - `currentProps` is missing in `NativeMethods`
103
+ textField.currentProps?.editable !== false;
104
+
105
+ if (!fieldCanBeFocused) {
106
+ return;
107
+ }
101
108
  focusInput(textField);
102
109
  if (Platform.OS === 'ios') {
103
110
  // This isn't necessarily a single line text input
@@ -17,7 +17,7 @@ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
17
17
  });
18
18
 
19
19
  const WindowsTextInputComponent: NativeType =
20
- requireNativeComponent<mixed>('RCTTextInput');
20
+ requireNativeComponent<mixed>('WindowsTextInput');
21
21
 
22
22
  export default WindowsTextInputComponent;
23
23
  // [Windows]
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  * @format
8
- * @flow strict-local
8
+ * @flow strict
9
9
  */
10
10
 
11
11
  'use strict';
@@ -13,5 +13,5 @@ exports.version = {
13
13
  major: 0,
14
14
  minor: 0,
15
15
  patch: 0,
16
- prerelease: '20220311-2027-b676ca560',
16
+ prerelease: '20220322-2008-8a5460ce8',
17
17
  };
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @flow strict-local
7
+ * @flow strict
8
8
  * @format
9
9
  */
10
10
 
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @flow strict-local
7
+ * @flow strict
8
8
  * @format
9
9
  */
10
10
 
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @flow strict-local
7
+ * @flow strict
8
8
  * @format
9
9
  */
10
10
 
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @flow strict-local
7
+ * @flow strict
8
8
  * @format
9
9
  */
10
10
 
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @flow
7
+ * @flow strict
8
8
  * @format
9
9
  */
10
10
 
@@ -75,24 +75,6 @@ if (__DEV__) {
75
75
  consoleErrorImpl = registerError;
76
76
  consoleWarnImpl = registerWarning;
77
77
 
78
- if ((console: any).disableYellowBox === true) {
79
- LogBoxData.setDisabled(true);
80
- console.warn(
81
- 'console.disableYellowBox has been deprecated and will be removed in a future release. Please use LogBox.ignoreAllLogs(value) instead.',
82
- );
83
- }
84
-
85
- (Object.defineProperty: any)(console, 'disableYellowBox', {
86
- configurable: true,
87
- get: () => LogBoxData.isDisabled(),
88
- set: value => {
89
- LogBoxData.setDisabled(value);
90
- console.warn(
91
- 'console.disableYellowBox has been deprecated and will be removed in a future release. Please use LogBox.ignoreAllLogs(value) instead.',
92
- );
93
- },
94
- });
95
-
96
78
  if (Platform.isTesting) {
97
79
  LogBoxData.setDisabled(true);
98
80
  }
@@ -115,7 +97,6 @@ if (__DEV__) {
115
97
  // After uninstalling: original > LogBox (noop) > OtherErrorHandler
116
98
  consoleErrorImpl = originalConsoleError;
117
99
  consoleWarnImpl = originalConsoleWarn;
118
- delete (console: any).disableLogBox;
119
100
  },
120
101
 
121
102
  isInstalled(): boolean {
@@ -153,7 +134,7 @@ if (__DEV__) {
153
134
  return typeof args[0] === 'string' && args[0].startsWith('(ADVICE)');
154
135
  };
155
136
 
156
- const isWarningModuleWarning = (...args: any) => {
137
+ const isWarningModuleWarning = (...args: Array<mixed>) => {
157
138
  return typeof args[0] === 'string' && args[0].startsWith('Warning: ');
158
139
  };
159
140
 
@@ -69,6 +69,7 @@ function FooterButton(props: ButtonProps): React.Node {
69
69
  const buttonStyles = StyleSheet.create({
70
70
  safeArea: {
71
71
  flex: 1,
72
+ // $FlowFixMe[sketchy-null-bool]
72
73
  paddingBottom: DeviceInfo.getConstants().isIPhoneX_deprecated ? 30 : 0,
73
74
  },
74
75
  content: {
@@ -19,6 +19,7 @@
19
19
  #include <react/renderer/components/text/TextShadowNode.h>
20
20
  #include <react/renderer/components/textinput/iostextinput/TextInputShadowNode.h>
21
21
  #include <react/renderer/components/view/ViewShadowNode.h>
22
+ #include "TextInput/WindowsTextInputShadowNode.h"
22
23
 
23
24
  #include "ActivityIndicatorComponentView.h"
24
25
  #include "ImageComponentView.h"
@@ -27,6 +28,7 @@
27
28
  #include "SliderComponentView.h"
28
29
  #include "SwitchComponentView.h"
29
30
  #include "TextComponentView.h"
31
+ #include "TextInput/WindowsTextInputComponentView.h"
30
32
  #include "ViewComponentView.h"
31
33
  #include "XamlView.h"
32
34
 
@@ -55,6 +57,8 @@ ComponentViewDescriptor const &ComponentViewRegistry::dequeueComponentViewWithCo
55
57
  view = std::make_shared<SliderComponentView>(m_context);
56
58
  } else if (componentHandle == facebook::react::SwitchShadowNode::Handle()) {
57
59
  view = std::make_shared<SwitchComponentView>(m_context);
60
+ } else if (componentHandle == facebook::react::WindowsTextInputShadowNode::Handle()) {
61
+ view = std::make_shared<WindowsTextInputComponentView>();
58
62
  } else if (componentHandle == facebook::react::ActivityIndicatorViewShadowNode::Handle()) {
59
63
  view = std::make_shared<ActivityIndicatorComponentView>();
60
64
  } else {
@@ -80,6 +84,15 @@ ComponentViewDescriptor const &ComponentViewRegistry::componentViewDescriptorWit
80
84
  return iterator->second;
81
85
  }
82
86
 
87
+ std::shared_ptr<IComponentView> ComponentViewRegistry::findComponentViewWithTag(
88
+ facebook::react::Tag tag) const noexcept {
89
+ auto iterator = m_registry.find(tag);
90
+ if (iterator == m_registry.end()) {
91
+ return nullptr;
92
+ }
93
+ return iterator->second.view;
94
+ }
95
+
83
96
  void ComponentViewRegistry::enqueueComponentViewWithComponentHandle(
84
97
  facebook::react::ComponentHandle componentHandle,
85
98
  facebook::react::Tag tag,
@@ -23,6 +23,7 @@ class ComponentViewRegistry final {
23
23
  facebook::react::ComponentHandle componentHandle,
24
24
  facebook::react::Tag tag) noexcept;
25
25
  ComponentViewDescriptor const &componentViewDescriptorWithTag(facebook::react::Tag tag) const noexcept;
26
+ std::shared_ptr<IComponentView> findComponentViewWithTag(facebook::react::Tag tag) const noexcept;
26
27
  void enqueueComponentViewWithComponentHandle(
27
28
  facebook::react::ComponentHandle componentHandle,
28
29
  facebook::react::Tag tag,
@@ -29,6 +29,7 @@
29
29
  #include <react/utils/ContextContainer.h>
30
30
  #include <runtimeexecutor/ReactCommon/RuntimeExecutor.h>
31
31
  #include <winrt/Windows.Graphics.Display.h>
32
+ #include "TextInput/WindowsTextInputComponentDescriptor.h"
32
33
  #include "Unicode.h"
33
34
 
34
35
  #pragma warning(push)
@@ -153,6 +154,8 @@ std::shared_ptr<facebook::react::ComponentDescriptorProviderRegistry const> shar
153
154
  facebook::react::concreteComponentDescriptorProvider<facebook::react::TextInputComponentDescriptor>());
154
155
  providerRegistry->add(
155
156
  facebook::react::concreteComponentDescriptorProvider<facebook::react::ViewComponentDescriptor>());
157
+ providerRegistry->add(
158
+ facebook::react::concreteComponentDescriptorProvider<facebook::react::WindowsTextInputComponentDescriptor>());
156
159
  return providerRegistry;
157
160
  }();
158
161
 
@@ -166,6 +169,10 @@ void FabricUIManager::installFabricUIManager() noexcept {
166
169
  std::lock_guard<std::mutex> schedulerLock(m_schedulerMutex);
167
170
 
168
171
  facebook::react::ContextContainer::Shared contextContainer = std::make_shared<facebook::react::ContextContainer>();
172
+
173
+ // This allows access to our ReactContext from the contextContainer thats passed around the fabric codebase
174
+ contextContainer->insert("MSRN.ReactContext", m_context);
175
+
169
176
  auto runtimeExecutor = SchedulerSettings::GetRuntimeExecutor(m_context.Properties());
170
177
 
171
178
  // TODO: T31905686 Create synchronous Event Beat
@@ -205,9 +212,6 @@ void FabricUIManager::installFabricUIManager() noexcept {
205
212
  toolbox.runtimeExecutor = runtimeExecutor;
206
213
  toolbox.synchronousEventBeatFactory = synchronousBeatFactory;
207
214
  toolbox.asynchronousEventBeatFactory = asynchronousBeatFactory;
208
- // We currently rely on using XAML elements to perform measure/layout,
209
- // which requires that the background thread also be the UI thread
210
- /*
211
215
  toolbox.backgroundExecutor = [context = m_context,
212
216
  dispatcher = Mso::DispatchQueue::MakeLooperQueue()](std::function<void()> &&callback) {
213
217
  if (context.UIDispatcher().HasThreadAccess()) {
@@ -217,15 +221,6 @@ void FabricUIManager::installFabricUIManager() noexcept {
217
221
 
218
222
  dispatcher.Post(std::move(callback));
219
223
  };
220
- */
221
- toolbox.backgroundExecutor = [context = m_context](std::function<void()> &&callback) {
222
- if (context.UIDispatcher().HasThreadAccess()) {
223
- callback();
224
- return;
225
- }
226
-
227
- context.UIDispatcher().Post(std::move(callback));
228
- };
229
224
 
230
225
  m_scheduler = std::make_shared<facebook::react::Scheduler>(
231
226
  toolbox, (/*animationDriver_ ? animationDriver_.get() :*/ nullptr), this);
@@ -501,8 +496,10 @@ void FabricUIManager::schedulerDidDispatchCommand(
501
496
  m_context.UIDispatcher().Post(
502
497
  [wkThis = weak_from_this(), commandName, tag = shadowView.tag, args = folly::dynamic(arg)]() {
503
498
  if (auto pThis = wkThis.lock()) {
504
- auto descriptor = pThis->m_registry.componentViewDescriptorWithTag(tag);
505
- descriptor.view->handleCommand(commandName, args);
499
+ auto view = pThis->m_registry.findComponentViewWithTag(tag);
500
+ if (view) {
501
+ view->handleCommand(commandName, args);
502
+ }
506
503
  }
507
504
  });
508
505
  }
@@ -23,6 +23,8 @@ ScrollViewComponentView::ScrollViewComponentView() {
23
23
  // m_props = defaultProps;
24
24
 
25
25
  m_element.Content(m_contentPanel);
26
+ m_contentPanel.VerticalAlignment(xaml::VerticalAlignment::Top);
27
+ m_contentPanel.HorizontalAlignment(xaml::HorizontalAlignment::Left);
26
28
 
27
29
  m_scrollViewerViewChangingRevoker =
28
30
  m_element.ViewChanging(winrt::auto_revoke, [this](const auto &sender, const auto &args) {
@@ -0,0 +1,197 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #pragma once
5
+
6
+ #include "WindowsTextInputShadowNode.h"
7
+
8
+ #include <yoga/CompactValue.h>
9
+ #include <yoga/YGEnums.h>
10
+ #include <yoga/YGValue.h>
11
+
12
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
13
+
14
+ namespace facebook {
15
+ namespace react {
16
+
17
+ // [Windows
18
+ void InitTextInputThemeInfo(const Mso::React::IReactContext &reactContext) {
19
+ xaml::Thickness textBoxPadding;
20
+ xaml::Application::Current().Resources().TryLookup(winrt::box_value(L"TextControlThemePadding")).as(textBoxPadding);
21
+ winrt::Microsoft::ReactNative::ReactPropertyBag(reactContext.Properties())
22
+ .Set(winrt::Microsoft::ReactNative::ReactPropertyId<xaml::Thickness>(L"TextBoxDefaultPadding"), textBoxPadding);
23
+ }
24
+
25
+ YGStyle::Edges PaddingFromContext(const facebook::react::ContextContainer &contextContainer) {
26
+ auto context = contextContainer.at<winrt::Microsoft::ReactNative::ReactContext>("MSRN.ReactContext");
27
+ auto defaultPadding = *context.Properties().Get(
28
+ winrt::Microsoft::ReactNative::ReactPropertyId<xaml::Thickness>(L"TextBoxDefaultPadding"));
29
+ YGStyle::Edges theme;
30
+ theme[YGEdgeStart] = YGValue{static_cast<float>(defaultPadding.Left), YGUnitPoint};
31
+ theme[YGEdgeEnd] = YGValue{static_cast<float>(defaultPadding.Right), YGUnitPoint};
32
+ theme[YGEdgeTop] = YGValue{static_cast<float>(defaultPadding.Top), YGUnitPoint};
33
+ theme[YGEdgeBottom] = YGValue{static_cast<float>(defaultPadding.Bottom), YGUnitPoint};
34
+ return theme;
35
+ }
36
+ // Windows]
37
+
38
+ /*
39
+ * Descriptor for <WindowsTextInput> component.
40
+ */
41
+ class WindowsTextInputComponentDescriptor final : public ConcreteComponentDescriptor<WindowsTextInputShadowNode> {
42
+ public:
43
+ WindowsTextInputComponentDescriptor(ComponentDescriptorParameters const &parameters)
44
+ : ConcreteComponentDescriptor<WindowsTextInputShadowNode>(parameters) {
45
+ // Every single `WindowsTextInputShadowNode` will have a reference to
46
+ // a shared `TextLayoutManager`.
47
+ textLayoutManager_ = std::make_shared<TextLayoutManager>(contextContainer_);
48
+ }
49
+
50
+ virtual State::Shared createInitialState(ShadowNodeFragment const &fragment, ShadowNodeFamily::Shared const &family)
51
+ const override {
52
+ /*
53
+ int surfaceId = family->getSurfaceId();
54
+
55
+ YGStyle::Edges theme;
56
+ // TODO: figure out RTL/start/end/left/right stuff here
57
+ if (surfaceIdToThemePaddingMap_.find(surfaceId) !=
58
+ surfaceIdToThemePaddingMap_.end()) {
59
+ theme = surfaceIdToThemePaddingMap_[surfaceId];
60
+ } else {
61
+ const jni::global_ref<jobject> &fabricUIManager =
62
+ contextContainer_->at<jni::global_ref<jobject>>("FabricUIManager");
63
+
64
+ auto env = jni::Environment::current();
65
+ auto defaultTextInputPaddingArray = env->NewFloatArray(4);
66
+ static auto getThemeData =
67
+ jni::findClassStatic(UIManagerJavaDescriptor)
68
+ ->getMethod<jboolean(jint, jfloatArray)>("getThemeData");
69
+
70
+ if (getThemeData(
71
+ fabricUIManager, surfaceId, defaultTextInputPaddingArray)) {
72
+ jfloat *defaultTextInputPadding =
73
+ env->GetFloatArrayElements(defaultTextInputPaddingArray, 0);
74
+ theme[YGEdgeStart] = (YGValue){defaultTextInputPadding[0], YGUnitPoint};
75
+ theme[YGEdgeEnd] = (YGValue){defaultTextInputPadding[1], YGUnitPoint};
76
+ theme[YGEdgeTop] = (YGValue){defaultTextInputPadding[2], YGUnitPoint};
77
+ theme[YGEdgeBottom] =
78
+ (YGValue){defaultTextInputPadding[3], YGUnitPoint};
79
+ surfaceIdToThemePaddingMap_.emplace(std::make_pair(surfaceId, theme));
80
+ env->ReleaseFloatArrayElements(
81
+ defaultTextInputPaddingArray, defaultTextInputPadding, JNI_ABORT);
82
+ }
83
+ env->DeleteLocalRef(defaultTextInputPaddingArray);
84
+ }
85
+ */
86
+
87
+ auto theme = PaddingFromContext(*contextContainer_); // [Windows]
88
+
89
+ return std::make_shared<WindowsTextInputShadowNode::ConcreteState>(
90
+ std::make_shared<WindowsTextInputState const>(WindowsTextInputState(
91
+ 0,
92
+ {},
93
+ {},
94
+ {},
95
+ {},
96
+ {},
97
+ ((YGValue)theme[YGEdgeStart]).value,
98
+ ((YGValue)theme[YGEdgeEnd]).value,
99
+ ((YGValue)theme[YGEdgeTop]).value,
100
+ ((YGValue)theme[YGEdgeBottom]).value)),
101
+ family);
102
+ }
103
+
104
+ protected:
105
+ void adopt(ShadowNode::Unshared const &shadowNode) const override {
106
+ auto textInputShadowNode = std::static_pointer_cast<WindowsTextInputShadowNode>(shadowNode);
107
+
108
+ // `ParagraphShadowNode` uses `TextLayoutManager` to measure text content
109
+ // and communicate text rendering metrics to mounting layer.
110
+ textInputShadowNode->setTextLayoutManager(textLayoutManager_);
111
+
112
+ textInputShadowNode->setContextContainer(const_cast<ContextContainer *>(getContextContainer().get()));
113
+
114
+ /*
115
+ int surfaceId = textInputShadowNode->getSurfaceId();
116
+ if (surfaceIdToThemePaddingMap_.find(surfaceId) !=
117
+ surfaceIdToThemePaddingMap_.end()) */
118
+ {
119
+ // YGStyle::Edges theme = surfaceIdToThemePaddingMap_[surfaceId];
120
+
121
+ auto theme = PaddingFromContext(*contextContainer_); // [Windows]
122
+
123
+ // Override padding
124
+ // Node is still unsealed during adoption, before layout is complete
125
+ // TODO: T62959168 account for RTL and paddingLeft when setting default
126
+ // paddingStart, and vice-versa with paddingRight/paddingEnd.
127
+ // For now this assumes no RTL.
128
+ YGStyle::Edges result = textInputShadowNode->getConcreteProps().yogaStyle.padding();
129
+ bool changedPadding = false;
130
+ if (!textInputShadowNode->getConcreteProps().hasPadding &&
131
+ !textInputShadowNode->getConcreteProps().hasPaddingStart &&
132
+ !textInputShadowNode->getConcreteProps().hasPaddingLeft &&
133
+ !textInputShadowNode->getConcreteProps().hasPaddingHorizontal) {
134
+ changedPadding = true;
135
+ result[YGEdgeStart] = theme[YGEdgeStart];
136
+ }
137
+ if (!textInputShadowNode->getConcreteProps().hasPadding &&
138
+ !textInputShadowNode->getConcreteProps().hasPaddingEnd &&
139
+ !textInputShadowNode->getConcreteProps().hasPaddingRight &&
140
+ !textInputShadowNode->getConcreteProps().hasPaddingHorizontal) {
141
+ changedPadding = true;
142
+ result[YGEdgeEnd] = theme[YGEdgeEnd];
143
+ }
144
+ if (!textInputShadowNode->getConcreteProps().hasPadding &&
145
+ !textInputShadowNode->getConcreteProps().hasPaddingTop &&
146
+ !textInputShadowNode->getConcreteProps().hasPaddingVertical) {
147
+ changedPadding = true;
148
+ result[YGEdgeTop] = theme[YGEdgeTop];
149
+ }
150
+ if (!textInputShadowNode->getConcreteProps().hasPadding &&
151
+ !textInputShadowNode->getConcreteProps().hasPaddingBottom &&
152
+ !textInputShadowNode->getConcreteProps().hasPaddingVertical) {
153
+ changedPadding = true;
154
+ result[YGEdgeBottom] = theme[YGEdgeBottom];
155
+ }
156
+
157
+ // If the TextInput initially does not have paddingLeft or paddingStart, a
158
+ // paddingStart may be set from the theme. If that happens, when there's a
159
+ // paddingLeft update, we must explicitly unset paddingStart... (same with
160
+ // paddingEnd)
161
+ // TODO: support RTL
162
+ if ((textInputShadowNode->getConcreteProps().hasPadding ||
163
+ textInputShadowNode->getConcreteProps().hasPaddingLeft ||
164
+ textInputShadowNode->getConcreteProps().hasPaddingHorizontal) &&
165
+ !textInputShadowNode->getConcreteProps().hasPaddingStart) {
166
+ result[YGEdgeStart] = YGValueUndefined;
167
+ }
168
+ if ((textInputShadowNode->getConcreteProps().hasPadding ||
169
+ textInputShadowNode->getConcreteProps().hasPaddingRight ||
170
+ textInputShadowNode->getConcreteProps().hasPaddingHorizontal) &&
171
+ !textInputShadowNode->getConcreteProps().hasPaddingEnd) {
172
+ result[YGEdgeEnd] = YGValueUndefined;
173
+ }
174
+
175
+ // Note that this is expensive: on every adopt, we need to set the Yoga
176
+ // props again, which normally only happens during prop parsing. Every
177
+ // commit, state update, etc, will incur this cost.
178
+ if (changedPadding) {
179
+ // Set new props on node
180
+ const_cast<WindowsTextInputProps &>(textInputShadowNode->getConcreteProps()).yogaStyle.padding() = result;
181
+ // Communicate new props to Yoga part of the node
182
+ textInputShadowNode->updateYogaProps();
183
+ }
184
+ }
185
+
186
+ textInputShadowNode->dirtyLayout();
187
+ textInputShadowNode->enableMeasurement();
188
+
189
+ ConcreteComponentDescriptor::adopt(shadowNode);
190
+ }
191
+
192
+ private:
193
+ SharedTextLayoutManager textLayoutManager_;
194
+ };
195
+
196
+ } // namespace react
197
+ } // namespace facebook