react-native-windows 0.82.0-preview.1 → 0.82.0-preview.10

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 (56) hide show
  1. package/Libraries/Animated/nodes/AnimatedValue.js +0 -8
  2. package/Libraries/BatchedBridge/BatchedBridge.js +1 -0
  3. package/Libraries/BatchedBridge/MessageQueue.js +1 -0
  4. package/Libraries/Components/Switch/Switch.js +1 -1
  5. package/Libraries/Components/Switch/Switch.windows.js +1 -1
  6. package/Libraries/Core/ReactNativeVersion.js +2 -2
  7. package/Libraries/Core/Timers/JSTimers.js +1 -0
  8. package/Libraries/Core/Timers/NativeTiming.js +1 -0
  9. package/Libraries/Core/Timers/immediateShim.js +1 -0
  10. package/Libraries/Core/setUpPerformance.js +3 -5
  11. package/Libraries/Interaction/PanResponder.js +6 -51
  12. package/Microsoft.ReactNative/ComponentView.idl +2 -0
  13. package/Microsoft.ReactNative/Composition.Input.idl +7 -0
  14. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +18 -0
  15. package/Microsoft.ReactNative/Fabric/ComponentView.h +9 -0
  16. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +12 -0
  17. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +15 -0
  18. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +75 -0
  19. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +1 -0
  20. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +6 -67
  21. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +0 -4
  22. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +82 -14
  23. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.h +11 -4
  24. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +59 -31
  25. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +3 -0
  26. package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +42 -15
  27. package/Microsoft.ReactNative.Cxx/ReactCommon/react/timing/primitives.h +12 -0
  28. package/PropertySheets/Generated/PackageVersion.g.props +2 -2
  29. package/PropertySheets/Warnings.props +1 -2
  30. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.cpp +174 -0
  31. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.h +69 -0
  32. package/Scripts/rnw-dependencies.ps1 +15 -1
  33. package/Shared/Shared.vcxitems +1 -0
  34. package/Shared/Shared.vcxitems.filters +1 -3
  35. package/codegen/NativePerformanceSpec.g.h +41 -35
  36. package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +55 -49
  37. package/codegen/rnwcoreJSI-generated.cpp +434 -422
  38. package/codegen/rnwcoreJSI.h +18 -0
  39. package/index.js +6 -0
  40. package/index.windows.js +6 -0
  41. package/package.json +15 -14
  42. package/src/private/featureflags/ReactNativeFeatureFlags.js +6 -1
  43. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +2 -1
  44. package/src/private/setup/{setUpPerformanceObserver.js → setUpPerformanceModern.js} +43 -18
  45. package/src/private/specs_DEPRECATED/components/SwitchNativeComponent.js +1 -0
  46. package/src/private/specs_DEPRECATED/modules/NativeTiming.js +1 -0
  47. package/src/private/webapis/performance/EventTiming.js +34 -15
  48. package/src/private/webapis/performance/LongTasks.js +35 -2
  49. package/src/private/webapis/performance/Performance.js +49 -13
  50. package/src/private/webapis/performance/PerformanceEntry.js +21 -8
  51. package/src/private/webapis/performance/PerformanceObserver.js +30 -1
  52. package/src/private/webapis/performance/ReactNativeStartupTiming.js +3 -24
  53. package/src/private/webapis/performance/ResourceTiming.js +29 -18
  54. package/src/private/webapis/performance/UserTiming.js +33 -28
  55. package/src/private/webapis/performance/internals/RawPerformanceEntry.js +3 -4
  56. package/src/private/webapis/performance/specs/NativePerformance.js +2 -0
@@ -107,6 +107,10 @@ void ParagraphComponentView::updateProps(
107
107
  m_requireRedraw = true;
108
108
  }
109
109
 
110
+ if (oldViewProps.selectionColor != newViewProps.selectionColor) {
111
+ m_requireRedraw = true;
112
+ }
113
+
110
114
  Super::updateProps(props, oldProps);
111
115
  }
112
116
 
@@ -167,6 +171,26 @@ void ParagraphComponentView::updateTextAlignment(
167
171
  m_textLayout = nullptr;
168
172
  }
169
173
 
174
+ facebook::react::Tag ParagraphComponentView::hitTest(
175
+ facebook::react::Point pt,
176
+ facebook::react::Point &localPt,
177
+ bool ignorePointerEvents) const noexcept {
178
+ facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
179
+ const auto &props = paragraphProps();
180
+ const auto &vProps = *viewProps();
181
+
182
+ if (props.isSelectable && ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
183
+ ptLocal.y <= m_layoutMetrics.frame.size.height) {
184
+ // claims if pointer events are enabled for this component
185
+ if (ignorePointerEvents || vProps.pointerEvents == facebook::react::PointerEventsMode::Auto ||
186
+ vProps.pointerEvents == facebook::react::PointerEventsMode::BoxOnly) {
187
+ localPt = ptLocal;
188
+ return Tag();
189
+ }
190
+ }
191
+ return Super::hitTest(pt, localPt, ignorePointerEvents);
192
+ }
193
+
170
194
  bool ParagraphComponentView::IsTextSelectableAtPoint(facebook::react::Point pt) noexcept {
171
195
  // paragraph-level selectable prop is enabled
172
196
  const auto &props = paragraphProps();
@@ -454,9 +478,14 @@ void ParagraphComponentView::DrawSelectionHighlight(
454
478
  return;
455
479
  }
456
480
 
457
- // TODO: use prop selectionColor if provided
458
481
  winrt::com_ptr<ID2D1SolidColorBrush> selectionBrush;
459
- const D2D1_COLOR_F selectionColor = theme()->D2DPlatformColor("Highlight@40");
482
+ D2D1_COLOR_F selectionColor;
483
+ const auto &props = paragraphProps();
484
+ if (props.selectionColor) {
485
+ selectionColor = theme()->D2DColor(**props.selectionColor);
486
+ } else {
487
+ selectionColor = theme()->D2DPlatformColor("Highlight@40");
488
+ }
460
489
  hr = renderTarget.CreateSolidColorBrush(selectionColor, selectionBrush.put());
461
490
 
462
491
  if (FAILED(hr)) {
@@ -519,6 +548,7 @@ void ParagraphComponentView::ClearSelection() noexcept {
519
548
  m_selectionStart = std::nullopt;
520
549
  m_selectionEnd = std::nullopt;
521
550
  m_isSelecting = false;
551
+ m_isWordSelecting = false;
522
552
  if (hadSelection) {
523
553
  // Clears selection highlight
524
554
  DrawText();
@@ -534,7 +564,8 @@ void ParagraphComponentView::OnPointerPressed(
534
564
  return;
535
565
  }
536
566
 
537
- auto pp = args.GetCurrentPoint(-1);
567
+ // Use Tag() to get coordinates in component's local space
568
+ auto pp = args.GetCurrentPoint(static_cast<int32_t>(Tag()));
538
569
 
539
570
  // Ignores right-click
540
571
  if (pp.Properties().PointerUpdateKind() ==
@@ -545,8 +576,8 @@ void ParagraphComponentView::OnPointerPressed(
545
576
 
546
577
  auto position = pp.Position();
547
578
 
548
- facebook::react::Point localPt{
549
- position.X - m_layoutMetrics.frame.origin.x, position.Y - m_layoutMetrics.frame.origin.y};
579
+ // GetCurrentPoint(Tag()) returns position relative to component origin
580
+ facebook::react::Point localPt{position.X, position.Y};
550
581
 
551
582
  std::optional<int32_t> charPosition = GetTextPositionAtPoint(localPt);
552
583
 
@@ -568,7 +599,13 @@ void ParagraphComponentView::OnPointerPressed(
568
599
 
569
600
  if (isDoubleClick) {
570
601
  SelectWordAtPosition(*charPosition);
571
- m_isSelecting = false;
602
+ if (m_selectionStart && m_selectionEnd) {
603
+ m_isWordSelecting = true;
604
+ m_wordAnchorStart = *m_selectionStart;
605
+ m_wordAnchorEnd = *m_selectionEnd;
606
+ m_isSelecting = true;
607
+ CapturePointer(args.Pointer());
608
+ }
572
609
  } else {
573
610
  // Single-click: start drag selection
574
611
  m_selectionStart = charPosition;
@@ -610,17 +647,35 @@ void ParagraphComponentView::OnPointerMoved(
610
647
  facebook::react::Point localPt{position.X, position.Y};
611
648
  std::optional<int32_t> charPosition = GetClampedTextPosition(localPt);
612
649
 
613
- if (charPosition && charPosition != m_selectionEnd) {
614
- m_selectionEnd = charPosition;
615
- DrawText();
616
- args.Handled(true);
650
+ if (charPosition) {
651
+ if (m_isWordSelecting) {
652
+ // Extend selection by whole words
653
+ auto [wordStart, wordEnd] = GetWordBoundariesAtPosition(*charPosition);
654
+
655
+ if (*charPosition < m_wordAnchorStart) {
656
+ m_selectionStart = wordStart;
657
+ m_selectionEnd = m_wordAnchorEnd;
658
+ } else if (*charPosition >= m_wordAnchorEnd) {
659
+ m_selectionStart = m_wordAnchorStart;
660
+ m_selectionEnd = wordEnd;
661
+ } else {
662
+ m_selectionStart = m_wordAnchorStart;
663
+ m_selectionEnd = m_wordAnchorEnd;
664
+ }
665
+ DrawText();
666
+ args.Handled(true);
667
+ } else if (charPosition != m_selectionEnd) {
668
+ m_selectionEnd = charPosition;
669
+ DrawText();
670
+ args.Handled(true);
671
+ }
617
672
  }
618
673
  }
619
674
 
620
675
  void ParagraphComponentView::OnPointerReleased(
621
676
  const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
622
677
  // Check for right-click to show context menu
623
- auto pp = args.GetCurrentPoint(-1);
678
+ auto pp = args.GetCurrentPoint(static_cast<int32_t>(Tag()));
624
679
  if (pp.Properties().PointerUpdateKind() ==
625
680
  winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::RightButtonReleased) {
626
681
  const auto &props = paragraphProps();
@@ -637,6 +692,7 @@ void ParagraphComponentView::OnPointerReleased(
637
692
  }
638
693
 
639
694
  m_isSelecting = false;
695
+ m_isWordSelecting = false;
640
696
 
641
697
  ReleasePointerCapture(args.Pointer());
642
698
 
@@ -661,6 +717,7 @@ void ParagraphComponentView::OnPointerCaptureLost() noexcept {
661
717
  // Pointer capture was lost stop any active selection drag
662
718
  if (m_isSelecting) {
663
719
  m_isSelecting = false;
720
+ m_isWordSelecting = false;
664
721
 
665
722
  if (!m_selectionStart || !m_selectionEnd || *m_selectionStart == *m_selectionEnd) {
666
723
  m_selectionStart = std::nullopt;
@@ -711,12 +768,17 @@ void ParagraphComponentView::CopySelectionToClipboard() noexcept {
711
768
  winrt::Windows::ApplicationModel::DataTransfer::Clipboard::SetContent(dataPackage);
712
769
  }
713
770
 
714
- void ParagraphComponentView::SelectWordAtPosition(int32_t charPosition) noexcept {
771
+ std::pair<int32_t, int32_t> ParagraphComponentView::GetWordBoundariesAtPosition(int32_t charPosition) noexcept {
715
772
  const std::wstring utf16Text{facebook::react::WindowsTextLayoutManager::GetTransformedText(m_attributedStringBox)};
716
773
  const int32_t textLength = static_cast<int32_t>(utf16Text.length());
717
774
 
718
- if (utf16Text.empty() || charPosition < 0 || charPosition >= textLength) {
719
- return;
775
+ if (utf16Text.empty() || charPosition < 0) {
776
+ return {0, 0};
777
+ }
778
+
779
+ charPosition = std::min(charPosition, textLength - 1);
780
+ if (charPosition < 0) {
781
+ return {0, 0};
720
782
  }
721
783
 
722
784
  int32_t wordStart = charPosition;
@@ -749,6 +811,12 @@ void ParagraphComponentView::SelectWordAtPosition(int32_t charPosition) noexcept
749
811
  }
750
812
  }
751
813
 
814
+ return {wordStart, wordEnd};
815
+ }
816
+
817
+ void ParagraphComponentView::SelectWordAtPosition(int32_t charPosition) noexcept {
818
+ auto [wordStart, wordEnd] = GetWordBoundariesAtPosition(charPosition);
819
+
752
820
  if (wordEnd > wordStart) {
753
821
  SetSelection(wordStart, wordEnd);
754
822
  DrawText();
@@ -49,6 +49,11 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
49
49
  static facebook::react::SharedViewProps defaultProps() noexcept;
50
50
  const facebook::react::ParagraphProps &paragraphProps() const noexcept;
51
51
 
52
+ facebook::react::Tag hitTest(
53
+ facebook::react::Point pt,
54
+ facebook::react::Point &localPt,
55
+ bool ignorePointerEvents = false) const noexcept override;
56
+
52
57
  // Returns true when text is selectable
53
58
  bool focusable() const noexcept override;
54
59
 
@@ -90,16 +95,13 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
90
95
  std::optional<int32_t> GetClampedTextPosition(facebook::react::Point pt) noexcept;
91
96
  std::string GetSelectedText() const noexcept;
92
97
 
93
- // Copies currently selected text to the system clipboard
94
98
  void CopySelectionToClipboard() noexcept;
95
99
 
96
- // Selects the word at the given character position
97
100
  void SelectWordAtPosition(int32_t charPosition) noexcept;
101
+ std::pair<int32_t, int32_t> GetWordBoundariesAtPosition(int32_t charPosition) noexcept;
98
102
 
99
- // Shows a context menu with Copy/Select All options on right-click
100
103
  void ShowContextMenu() noexcept;
101
104
 
102
- // m_selectionStart <= m_selectionEnd
103
105
  void SetSelection(int32_t start, int32_t end) noexcept;
104
106
 
105
107
  winrt::com_ptr<::IDWriteTextLayout> m_textLayout;
@@ -113,6 +115,11 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
113
115
  std::optional<int32_t> m_selectionEnd;
114
116
  bool m_isSelecting{false};
115
117
 
118
+ // Double click + drag selection
119
+ bool m_isWordSelecting{false};
120
+ int32_t m_wordAnchorStart{0};
121
+ int32_t m_wordAnchorEnd{0};
122
+
116
123
  // Double-click detection
117
124
  std::chrono::steady_clock::time_point m_lastClickTime{};
118
125
  std::optional<int32_t> m_lastClickPosition;
@@ -186,6 +186,7 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
186
186
 
187
187
  auto pt = m_outer->getClientOffset();
188
188
  m_outer->m_caretVisual.Position({x - pt.x, y - pt.y});
189
+ m_outer->m_caretPosition = {x, y};
189
190
  return true;
190
191
  }
191
192
 
@@ -696,17 +697,10 @@ void WindowsTextInputComponentView::OnPointerPressed(
696
697
  }
697
698
 
698
699
  if (m_textServices && msg) {
699
- if (msg == WM_RBUTTONUP && !windowsTextInputProps().contextMenuHidden) {
700
- ShowContextMenu(position);
701
- args.Handled(true);
702
- } else if (msg == WM_RBUTTONUP && windowsTextInputProps().contextMenuHidden) {
703
- args.Handled(true);
704
- } else {
705
- LRESULT lresult;
706
- DrawBlock db(*this);
707
- auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
708
- args.Handled(hr != S_FALSE);
709
- }
700
+ LRESULT lresult;
701
+ DrawBlock db(*this);
702
+ auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
703
+ args.Handled(hr != S_FALSE);
710
704
  }
711
705
 
712
706
  // Emits the OnPressIn event
@@ -768,10 +762,18 @@ void WindowsTextInputComponentView::OnPointerReleased(
768
762
  }
769
763
 
770
764
  if (m_textServices && msg) {
771
- LRESULT lresult;
772
- DrawBlock db(*this);
773
- auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
774
- args.Handled(hr != S_FALSE);
765
+ // Show context menu on right button release (standard Windows behavior)
766
+ if (msg == WM_RBUTTONUP && !windowsTextInputProps().contextMenuHidden) {
767
+ ShowContextMenu(LocalToScreen(position));
768
+ args.Handled(true);
769
+ } else if (msg == WM_RBUTTONUP) {
770
+ // Context menu is hidden - don't mark as handled, let app add custom behavior
771
+ } else {
772
+ LRESULT lresult;
773
+ DrawBlock db(*this);
774
+ auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
775
+ args.Handled(hr != S_FALSE);
776
+ }
775
777
  }
776
778
 
777
779
  // Emits the OnPressOut event
@@ -1508,18 +1510,26 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1508
1510
  cfNew.wWeight =
1509
1511
  props.textAttributes.fontWeight ? static_cast<WORD>(*props.textAttributes.fontWeight) : DWRITE_FONT_WEIGHT_NORMAL;
1510
1512
 
1511
- // set font style
1512
- // cfNew.dwMask |= (CFM_ITALIC | CFM_STRIKEOUT | CFM_UNDERLINE);
1513
- // int dFontStyle = fontDetails.FontStyle;
1514
- // if (dFontStyle & FS_Italic) {
1515
- // cfNew.dwEffects |= CFE_ITALIC;
1516
- // }
1517
- // if (dFontStyle & FS_StrikeOut) {
1518
- // cfNew.dwEffects |= CFE_STRIKEOUT;
1519
- //}
1520
- // if (dFontStyle & FS_Underline) {
1521
- // cfNew.dwEffects |= CFE_UNDERLINE;
1522
- // }
1513
+ // set font style (italic)
1514
+ cfNew.dwMask |= CFM_ITALIC;
1515
+ if (props.textAttributes.fontStyle == facebook::react::FontStyle::Italic ||
1516
+ props.textAttributes.fontStyle == facebook::react::FontStyle::Oblique) {
1517
+ cfNew.dwEffects |= CFE_ITALIC;
1518
+ }
1519
+
1520
+ // set text decoration (underline and strikethrough)
1521
+ cfNew.dwMask |= (CFM_UNDERLINE | CFM_STRIKEOUT);
1522
+ if (props.textAttributes.textDecorationLineType.has_value()) {
1523
+ auto decorationType = *props.textAttributes.textDecorationLineType;
1524
+ if (decorationType == facebook::react::TextDecorationLineType::Underline ||
1525
+ decorationType == facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
1526
+ cfNew.dwEffects |= CFE_UNDERLINE;
1527
+ }
1528
+ if (decorationType == facebook::react::TextDecorationLineType::Strikethrough ||
1529
+ decorationType == facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
1530
+ cfNew.dwEffects |= CFE_STRIKEOUT;
1531
+ }
1532
+ }
1523
1533
 
1524
1534
  // set font family
1525
1535
  if (!props.textAttributes.fontFamily.empty()) {
@@ -1871,6 +1881,21 @@ void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
1871
1881
  m_textServices->TxSendMessage(EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0, &lresult));
1872
1882
  }
1873
1883
 
1884
+ void WindowsTextInputComponentView::OnContextMenuKey(
1885
+ const winrt::Microsoft::ReactNative::Composition::Input::ContextMenuKeyEventArgs &args) noexcept {
1886
+ // Handle context menu key event (SHIFT+F10 or Context Menu key)
1887
+ if (!windowsTextInputProps().contextMenuHidden) {
1888
+ // m_caretPosition is stored from TxSetCaretPos in RichEdit client rect space (physical pixels).
1889
+ // LocalToScreen expects logical (DIP) coordinates, so divide by pointScaleFactor.
1890
+ auto screenPt = LocalToScreen(winrt::Windows::Foundation::Point{
1891
+ static_cast<float>(m_caretPosition.x) / m_layoutMetrics.pointScaleFactor,
1892
+ static_cast<float>(m_caretPosition.y) / m_layoutMetrics.pointScaleFactor});
1893
+ ShowContextMenu(screenPt);
1894
+ args.Handled(true);
1895
+ }
1896
+ // If contextMenuHidden, don't mark as handled - let app handle it
1897
+ }
1898
+
1874
1899
  void WindowsTextInputComponentView::ShowContextMenu(const winrt::Windows::Foundation::Point &position) noexcept {
1875
1900
  HMENU menu = CreatePopupMenu();
1876
1901
  if (!menu)
@@ -1890,13 +1915,16 @@ void WindowsTextInputComponentView::ShowContextMenu(const winrt::Windows::Founda
1890
1915
  AppendMenuW(menu, MF_STRING | (canPaste ? 0 : MF_GRAYED), 3, L"Paste");
1891
1916
  AppendMenuW(menu, MF_STRING | (!isEmpty && !isReadOnly ? 0 : MF_GRAYED), 4, L"Select All");
1892
1917
 
1893
- POINT cursorPos;
1894
- GetCursorPos(&cursorPos);
1895
-
1896
1918
  HWND hwnd = GetActiveWindow();
1897
1919
 
1898
1920
  int cmd = TrackPopupMenu(
1899
- menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY, cursorPos.x, cursorPos.y, 0, hwnd, NULL);
1921
+ menu,
1922
+ TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
1923
+ static_cast<int>(position.X),
1924
+ static_cast<int>(position.Y),
1925
+ 0,
1926
+ hwnd,
1927
+ NULL);
1900
1928
 
1901
1929
  if (cmd == 1) { // Cut
1902
1930
  m_textServices->TxSendMessage(WM_CUT, 0, 0, &res);
@@ -67,6 +67,8 @@ struct WindowsTextInputComponentView
67
67
  void OnKeyUp(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
68
68
  void OnCharacterReceived(const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs
69
69
  &args) noexcept override;
70
+ void OnContextMenuKey(
71
+ const winrt::Microsoft::ReactNative::Composition::Input::ContextMenuKeyEventArgs &args) noexcept override;
70
72
  void onMounted() noexcept override;
71
73
 
72
74
  std::optional<std::string> getAccessiblityValue() noexcept override;
@@ -146,6 +148,7 @@ struct WindowsTextInputComponentView
146
148
  DWORD m_propBitsMask{0};
147
149
  DWORD m_propBits{0};
148
150
  HCURSOR m_hcursor{nullptr};
151
+ POINT m_caretPosition{0, 0};
149
152
  std::chrono::steady_clock::time_point m_lastClickTime{};
150
153
  std::vector<facebook::react::CompWindowsTextInputSubmitKeyEventsStruct> m_submitKeyEvents;
151
154
  };
@@ -24,15 +24,28 @@ using namespace Windows::Storage::Streams;
24
24
 
25
25
  namespace Microsoft::ReactNative {
26
26
 
27
+ static const char *ERROR_INVALID_URI = "E_INVALID_URI";
28
+ static const char *ERROR_GET_SIZE_FAILURE = "E_GET_SIZE_FAILURE";
29
+
27
30
  winrt::fire_and_forget GetImageSizeAsync(
28
31
  const winrt::Microsoft::ReactNative::IReactPropertyBag &properties,
29
32
  std::string uriString,
30
33
  winrt::Microsoft::ReactNative::JSValue &&headers,
31
34
  Mso::Functor<void(int32_t width, int32_t height)> successCallback,
32
- Mso::Functor<void()> errorCallback) {
35
+ Mso::Functor<void(const char *errorCode, std::string errorMessage)> errorCallback) {
33
36
  bool succeeded{false};
37
+ const char *errorCode = ERROR_GET_SIZE_FAILURE;
38
+ std::string errorMessage;
34
39
 
35
40
  try {
41
+ // Validate URI is not empty
42
+ if (uriString.empty()) {
43
+ errorCode = ERROR_INVALID_URI;
44
+ errorMessage = "Cannot get the size of an image for an empty URI";
45
+ errorCallback(errorCode, errorMessage);
46
+ co_return;
47
+ }
48
+
36
49
  ReactImageSource source;
37
50
  source.uri = uriString;
38
51
  if (!headers.IsNull()) {
@@ -45,28 +58,38 @@ winrt::fire_and_forget GetImageSizeAsync(
45
58
  winrt::hstring scheme{uri.SchemeName()};
46
59
  bool needsDownload = (scheme == L"http") || (scheme == L"https");
47
60
  bool inlineData = scheme == L"data";
61
+ bool isLocalFile = (scheme == L"file") || (scheme == L"ms-appx") || (scheme == L"ms-appdata");
48
62
 
49
63
  winrt::IRandomAccessStream memoryStream;
50
- if (needsDownload) {
64
+ if (needsDownload || isLocalFile) {
51
65
  memoryStream = co_await GetImageStreamAsync(properties, source);
52
66
  } else if (inlineData) {
53
67
  memoryStream = co_await GetImageInlineDataAsync(source);
54
68
  }
55
- auto result = wicBitmapSourceFromStream(memoryStream);
56
- if (!std::get<std::shared_ptr<facebook::react::ImageErrorInfo>>(result)) {
57
- auto imagingFactory = std::get<winrt::com_ptr<IWICImagingFactory>>(result);
58
- auto wicBmpSource = std::get<winrt::com_ptr<IWICBitmapSource>>(result);
59
- UINT width, height;
60
- if (SUCCEEDED(wicBmpSource->GetSize(&width, &height))) {
61
- successCallback(width, height);
62
- succeeded = true;
69
+
70
+ if (memoryStream) {
71
+ auto result = wicBitmapSourceFromStream(memoryStream);
72
+ if (!std::get<std::shared_ptr<facebook::react::ImageErrorInfo>>(result)) {
73
+ auto imagingFactory = std::get<winrt::com_ptr<IWICImagingFactory>>(result);
74
+ auto wicBmpSource = std::get<winrt::com_ptr<IWICBitmapSource>>(result);
75
+ UINT width, height;
76
+ if (SUCCEEDED(wicBmpSource->GetSize(&width, &height))) {
77
+ successCallback(width, height);
78
+ succeeded = true;
79
+ }
63
80
  }
64
81
  }
65
- } catch (winrt::hresult_error const &) {
82
+ } catch (winrt::hresult_error const &e) {
83
+ errorMessage = "Failed to get image size: " + Microsoft::Common::Unicode::Utf16ToUtf8(std::wstring(e.message())) +
84
+ " for URI: " + uriString;
66
85
  }
67
86
 
68
- if (!succeeded)
69
- errorCallback();
87
+ if (!succeeded) {
88
+ if (errorMessage.empty()) {
89
+ errorMessage = "Failed to get image size for URI: " + uriString;
90
+ }
91
+ errorCallback(errorCode, errorMessage);
92
+ }
70
93
 
71
94
  co_return;
72
95
  }
@@ -85,7 +108,9 @@ void ImageLoader::getSize(std::string uri, React::ReactPromise<std::vector<doubl
85
108
  [result](double width, double height) noexcept {
86
109
  result.Resolve(std::vector<double>{width, height});
87
110
  },
88
- [result]() noexcept { result.Reject("Failed"); });
111
+ [result](const char *errorCode, std::string errorMessage) noexcept {
112
+ result.Reject(React::ReactError{errorCode, errorMessage});
113
+ });
89
114
  });
90
115
  }
91
116
 
@@ -105,7 +130,9 @@ void ImageLoader::getSizeWithHeaders(
105
130
  [result](double width, double height) noexcept {
106
131
  result.Resolve(Microsoft::ReactNativeSpecs::ImageLoaderIOSSpec_getSizeWithHeaders_returnType{width, height});
107
132
  },
108
- [result]() noexcept { result.Reject("Failed"); });
133
+ [result](const char *errorCode, std::string errorMessage) noexcept {
134
+ result.Reject(React::ReactError{errorCode, errorMessage});
135
+ });
109
136
  });
110
137
  }
111
138
 
@@ -201,6 +201,11 @@ class HighResTimeStamp {
201
201
  return HighResTimeStamp(chronoNow());
202
202
  }
203
203
 
204
+ static HighResDuration unsafeOriginFromUnixTimeStamp() noexcept {
205
+ static auto origin = computeUnsafeOriginFromUnixTimeStamp();
206
+ return origin;
207
+ }
208
+
204
209
  static constexpr HighResTimeStamp min() noexcept {
205
210
  return HighResTimeStamp(std::chrono::steady_clock::time_point::min());
206
211
  }
@@ -285,6 +290,13 @@ class HighResTimeStamp {
285
290
 
286
291
  std::chrono::steady_clock::time_point chronoTimePoint_;
287
292
 
293
+ static HighResDuration computeUnsafeOriginFromUnixTimeStamp() noexcept {
294
+ auto systemNow = std::chrono::system_clock::now();
295
+ auto steadyNow = std::chrono::steady_clock::now();
296
+ return HighResDuration(
297
+ systemNow.time_since_epoch() - steadyNow.time_since_epoch());
298
+ }
299
+
288
300
  #ifdef REACT_NATIVE_DEBUG
289
301
  static std::function<std::chrono::steady_clock::time_point()>&
290
302
  getTimeStampProvider() {
@@ -10,11 +10,11 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.82.0-preview.1</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.82.0-preview.10</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>82</ReactNativeWindowsMinor>
16
16
  <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
17
17
  <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
- <ReactNativeWindowsCommitId>ff00401de651ccddf5a25d411c3ace8e49f12189</ReactNativeWindowsCommitId>
18
+ <ReactNativeWindowsCommitId>8dab2200781d9264a8a3ad08005d3a04b44e7c18</ReactNativeWindowsCommitId>
19
19
  </PropertyGroup>
20
20
  </Project>
@@ -24,8 +24,7 @@
24
24
  4701; <!-- potentially uninitialized local variable used -->
25
25
  4703; <!-- potentially uninitialized local pointer variable used -->
26
26
  4789; <!-- destination of memory copy too small -->
27
- 4995; <!-- function marked as pragma deprecated -->
28
- 4996 <!-- deprecated function (including std::) -->
27
+ 4995 <!-- function marked as pragma deprecated -->
29
28
  </SDLMandatoryWarnings>
30
29
 
31
30
  <!-- SDL RECOMMENDED WARNINGS (Strongly recommended to fix) -->