-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Refactor ViewManagers to detect unimplemented properties #4575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
fdd1867
Publish fix
acoates-ms a53564d
Creating new Microsoft.ReactNative.sln (#4535)
jonthysell 8bc5d3a
applying package updates ***NO_CI***
rnbot ddbfb04
Move playground app to use Microsoft.ReactNative (#4534)
acoates-ms 59094fd
Bump beachball from 1.28.0 to 1.28.1 (#4539)
dependabot-preview[bot] f5db344
applying package updates ***NO_CI***
rnbot 3ef811b
applying package updates ***NO_CI***
rnbot 5201232
Enabling managed unit tests in CI loop (#4532)
jonthysell 4aa64fa
applying package updates ***NO_CI***
rnbot ae4e4c9
Remove 'Delete Android SDK' from E2ETest (#4554)
jonthysell 2f4fffa
Enable WebSocketModule unit tests (#4538)
JunielKatarn aa853d9
applying package updates ***NO_CI***
rnbot e10d541
Improve inner loop and error reporting (local CLI) (#4536)
asklar 5bd5efb
applying package updates ***NO_CI***
rnbot f2a0d00
Don't set readyState on connection error (#4562)
JunielKatarn da695df
applying package updates ***NO_CI***
rnbot 8fdada9
Bump @babel/core from 7.8.4 to 7.9.0 (#4565)
dependabot-preview[bot] e3449a3
Simplified C++ macros and improved their comments (#4568)
vmoroz 380c1ad
applying package updates ***NO_CI***
rnbot cbe66c4
Merge branch 'master' of https://github.com/asklar/react-native-windows
asklar 8e9b031
Refactor View managers to detect unimplemented props
asklar 9a097f8
adding missing files
asklar db92ed1
more files
asklar 0e83eef
Change files
asklar 78144f8
protected
asklar 0022de5
fix typo
asklar d733464
Add display of html metro errors, and enable clicking on the aka.ms link
asklar 4e80a23
move cdebug to reactwindowscore
asklar 60ad428
format
asklar 4b3a01e
use hyperlink instead of tapped()
asklar f718c0c
WebView sizing and styling logic
asklar 3a3d32d
Use DispatcherQueue instead of CoreWindow/CoreDispatcher
asklar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
8 changes: 8 additions & 0 deletions
8
change/react-native-windows-2020-04-11-01-26-56-unimplNotify.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "type": "prerelease", | ||
| "comment": "Refactor View managers to detect unimplemented props", | ||
| "packageName": "react-native-windows", | ||
| "email": "asklar@microsoft.com", | ||
| "dependentChangeType": "patch", | ||
| "date": "2020-04-11T08:26:56.395Z" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,13 +8,18 @@ | |
| #include <winrt/Windows.UI.Core.h> | ||
| #include <winrt/Windows.UI.Xaml.Controls.Primitives.h> | ||
| #include <winrt/Windows.UI.Xaml.Controls.h> | ||
| #include <winrt/Windows.UI.Xaml.Documents.h> | ||
| #include <winrt/Windows.UI.Xaml.Input.h> | ||
| #include <winrt/Windows.UI.Xaml.Markup.h> | ||
| #include <winrt/Windows.Web.Http.h> | ||
|
|
||
| #include <boost/algorithm/string.hpp> | ||
| #include <regex> | ||
| #include "Unicode.h" | ||
|
|
||
| namespace xaml = winrt::Windows::UI::Xaml; | ||
| using namespace winrt::Windows::Foundation; | ||
|
|
||
| namespace Mso::React { | ||
|
|
||
| struct RedBox : public std::enable_shared_from_this<RedBox> { | ||
|
|
@@ -47,7 +52,7 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
|
|
||
| void ShowNewJSError() noexcept { | ||
| m_showing = true; | ||
| m_popup = winrt::Windows::UI::Xaml::Controls::Primitives::Popup{}; | ||
| m_popup = xaml::Controls::Primitives::Popup{}; | ||
|
|
||
| const winrt::hstring xamlString = | ||
| L"<Grid Background='{ThemeResource ContentDialogBackground}'" | ||
|
|
@@ -64,7 +69,7 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| L" </Grid.RowDefinitions>" | ||
| L" <ScrollViewer Grid.Row='0' Grid.ColumnSpan='2' HorizontalAlignment='Stretch'>" | ||
| L" <StackPanel HorizontalAlignment='Stretch'>" | ||
| L" <StackPanel Background='#EECC0000' HorizontalAlignment='Stretch' Padding='15,35,15,15'>" | ||
| L" <StackPanel Background='#EECC0000' HorizontalAlignment='Stretch' Padding='15,35,15,15' x:Name='StackPanelUpper'>" | ||
| L" <TextBlock x:Name='ErrorMessageText' FontSize='14' Foreground='White' IsTextSelectionEnabled='true' TextWrapping='Wrap'/>" | ||
| L" <Border Padding='15,15,15,0'/>" | ||
| L" <TextBlock x:Name='ErrorStackText' FontSize='12' FontFamily='Consolas' Foreground='White' IsTextSelectionEnabled='true' TextWrapping='Wrap'/>" | ||
|
|
@@ -76,30 +81,27 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| L" <Button x:Name='ReloadButton' Grid.Row='1' Grid.Column='2' HorizontalAlignment='Stretch' Margin='15' Style='{StaticResource ButtonRevealStyle}'>Reload (NYI)</Button>" | ||
| L"</Grid>"; | ||
|
|
||
| m_redboxContent = winrt::unbox_value<winrt::Windows::UI::Xaml::Controls::Grid>( | ||
| winrt::Windows::UI::Xaml::Markup::XamlReader::Load(xamlString)); | ||
| m_errorMessageText = | ||
| m_redboxContent.FindName(L"ErrorMessageText").as<winrt::Windows::UI::Xaml::Controls::TextBlock>(); | ||
| m_errorStackText = m_redboxContent.FindName(L"ErrorStackText").as<winrt::Windows::UI::Xaml::Controls::TextBlock>(); | ||
| m_stackPanel = m_redboxContent.FindName(L"StackPanel").as<winrt::Windows::UI::Xaml::Controls::StackPanel>(); | ||
| m_dismissButton = m_redboxContent.FindName(L"DismissButton").as<winrt::Windows::UI::Xaml::Controls::Button>(); | ||
| m_reloadButton = m_redboxContent.FindName(L"ReloadButton").as<winrt::Windows::UI::Xaml::Controls::Button>(); | ||
| m_redboxContent = winrt::unbox_value<xaml::Controls::Grid>(xaml::Markup::XamlReader::Load(xamlString)); | ||
| m_errorMessageText = m_redboxContent.FindName(L"ErrorMessageText").as<xaml::Controls::TextBlock>(); | ||
| m_errorStackText = m_redboxContent.FindName(L"ErrorStackText").as<xaml::Controls::TextBlock>(); | ||
| m_stackPanel = m_redboxContent.FindName(L"StackPanel").as<xaml::Controls::StackPanel>(); | ||
| m_stackPanelUpper = m_redboxContent.FindName(L"StackPanelUpper").as<xaml::Controls::StackPanel>(); | ||
| m_dismissButton = m_redboxContent.FindName(L"DismissButton").as<xaml::Controls::Button>(); | ||
| m_reloadButton = m_redboxContent.FindName(L"ReloadButton").as<xaml::Controls::Button>(); | ||
|
|
||
| m_tokenDismiss = m_dismissButton.Click([&]( | ||
| winrt::Windows::Foundation::IInspectable const & /*sender*/, | ||
| winrt::Windows::UI::Xaml::RoutedEventArgs const & /*args*/) noexcept { Dismiss(); }); | ||
| IInspectable const & /*sender*/, xaml::RoutedEventArgs const & /*args*/) noexcept { Dismiss(); }); | ||
|
|
||
| m_tokenReload = m_reloadButton.Click([&]( | ||
| auto const & /*sender*/, winrt::Windows::UI::Xaml::RoutedEventArgs const & /*args*/) noexcept { | ||
| m_tokenReload = m_reloadButton.Click([&](auto const & /*sender*/, xaml::RoutedEventArgs const & /*args*/) noexcept { | ||
| Dismiss(); | ||
| Reload(); | ||
| }); | ||
|
|
||
| PopulateFrameStackUI(); | ||
| UpdateErorrMessageUI(); | ||
| UpdateErrorMessageUI(); | ||
|
|
||
| // Do some kind of sizing logic... | ||
| auto window = winrt::Windows::UI::Xaml::Window::Current(); | ||
| auto window = xaml::Window::Current(); | ||
| auto windowBounds = window.Bounds(); | ||
| m_redboxContent.MaxHeight(windowBounds.Height); | ||
| m_redboxContent.Height(windowBounds.Height); | ||
|
|
@@ -111,7 +113,7 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| }); | ||
|
|
||
| m_tokenClosed = m_popup.Closed([wkThis = std::weak_ptr(shared_from_this())]( | ||
| auto const & /*sender*/, winrt::Windows::Foundation::IInspectable const & /*args*/) noexcept { | ||
| auto const & /*sender*/, IInspectable const & /*args*/) noexcept { | ||
| if (auto pthis = wkThis.lock()) { | ||
| pthis->OnPopupClosed(); | ||
| } | ||
|
|
@@ -132,7 +134,7 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| m_showing = false; | ||
| m_dismissButton.Click(m_tokenDismiss); | ||
| m_reloadButton.Click(m_tokenReload); | ||
| winrt::Windows::UI::Xaml::Window::Current().SizeChanged(m_tokenSizeChanged); | ||
| xaml::Window::Current().SizeChanged(m_tokenSizeChanged); | ||
| m_popup.Closed(m_tokenClosed); | ||
| m_onClosedCallback(GetId()); | ||
| } | ||
|
|
@@ -142,7 +144,20 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| } | ||
|
|
||
| private: | ||
| void UpdateErorrMessageUI() noexcept { | ||
| static bool IsMetroBundlerError(const std::string &message, const std::string &type) { | ||
| // This string must be kept in sync with the one in formatBundlingError in | ||
| // node_modules\metro\src\lib\formatBundlingError.js | ||
| if (message.find_first_of("Metro Bundler has encountered an error") != message.npos) { | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| #define METRO_TROUBLESHOOTING_URL "http://aka.ms/RNWTroubleshootMetro" | ||
| #define _MAKE_WIDE_STR(x) L##x | ||
| #define MAKE_WIDE_STR(x) _MAKE_WIDE_STR(x) | ||
|
|
||
| void UpdateErrorMessageUI() noexcept { | ||
| try { | ||
| auto json = folly::parseJson(m_errorInfo.Message); | ||
| if (json.count("name") && json["name"] == "Error") { | ||
|
|
@@ -151,8 +166,83 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| m_errorMessageText.Text(Microsoft::Common::Unicode::Utf8ToUtf16(message)); | ||
| m_errorStackText.Text(Microsoft::Common::Unicode::Utf8ToUtf16(stack)); | ||
| return; | ||
| } else if (json.count("type") && json["type"] == "InternalError") { | ||
| auto message = json["message"].asString(); | ||
| m_errorMessageText.Text(Microsoft::Common::Unicode::Utf8ToUtf16(message)); | ||
|
|
||
| if (IsMetroBundlerError(message, json["type"].asString())) { | ||
| xaml::Documents::Hyperlink link; | ||
| link.NavigateUri(Uri(MAKE_WIDE_STR(METRO_TROUBLESHOOTING_URL))); | ||
| xaml::Documents::Run linkRun; | ||
|
|
||
| linkRun.Text(Microsoft::Common::Unicode::Utf8ToUtf16(METRO_TROUBLESHOOTING_URL)); | ||
| link.Foreground( | ||
| xaml::Media::SolidColorBrush(winrt::Windows::UI::ColorHelper::FromArgb(0xff, 0xff, 0xff, 0xff))); | ||
| link.Inlines().Append(linkRun); | ||
| xaml::Documents::Run normalRun; | ||
| normalRun.Text(Microsoft::Common::Unicode::Utf8ToUtf16(json["type"].asString() + (" ─ See "))); | ||
| m_errorStackText.Inlines().Append(normalRun); | ||
| m_errorStackText.Inlines().Append(link); | ||
| } else { | ||
| m_errorStackText.Text(Microsoft::Common::Unicode::Utf8ToUtf16(json["type"].asString())); | ||
| } | ||
| return; | ||
| } | ||
| } catch (...) { | ||
| std::string doctype = "<!DOCTYPE HTML>"; | ||
| if (boost::istarts_with(m_errorInfo.Message, doctype)) { | ||
| auto webView = xaml::Controls::WebView(xaml::Controls::WebViewExecutionMode::SameThread); | ||
|
|
||
| winrt::hstring content( | ||
| Microsoft::Common::Unicode::Utf8ToUtf16(m_errorInfo.Message.substr(doctype.length()).c_str())); | ||
|
|
||
| webView.HorizontalAlignment(xaml::HorizontalAlignment::Stretch); | ||
| webView.VerticalAlignment(xaml::VerticalAlignment::Stretch); | ||
| webView.MinWidth(400); | ||
|
|
||
| m_stackPanel.Children().Clear(); | ||
| m_stackPanel.Children().Append(webView); | ||
|
|
||
| auto dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Thanks for changing this to DispatcherQueue! Strange... I was literally 5 seconds away from suggesting this when I saw your latest revision. #Closed |
||
| // XAML doesn't currently provide a way to measure a WebView control, | ||
| // So we're going to tell the WebView to measure itself by running some javascript, | ||
| // and then we'll post a task back to XAML to set the XAML WebView minimum height. | ||
| // The HTML we get from Metro doesn't have any styling, so we'll take advantage of | ||
| // the fact that we're running javascript in the WebView, to set the | ||
| // foreground/background to match the rest of the RedBox. | ||
| // setProperty returns undefined so we continue the first expression with a comma | ||
| // whereas the height expression gets executed because of the || | ||
| // (since the setProperty calls resulted in undefined). | ||
| // Finally, it's important to note that JS expressions of that are not of string type | ||
| // need to be manually converted to string for them to get marshaled properly back here. | ||
| webView.NavigationCompleted( | ||
| [=](IInspectable const &, xaml::Controls::WebViewNavigationCompletedEventArgs const &) { | ||
| // #eecc0000 ARGB is #be0000 RGB (background doesn't seem to allow alpha channel in WebView) | ||
| std::vector<winrt::hstring> args{ | ||
| L"(document.body.style.setProperty('color', 'white'), " | ||
| L"document.body.style.setProperty('background', '#be0000')) " | ||
| L"|| document.documentElement.scrollHeight.toString()"}; | ||
| auto async = webView.InvokeScriptAsync(L"eval", std::move(args)); | ||
|
|
||
| async.Completed([=](IAsyncOperation<winrt::hstring> const &op, auto &&state) { | ||
| auto result = op.GetResults(); | ||
| int documentHeight = _wtoi(result.c_str()); | ||
| dispatcher.TryEnqueue([=]() { | ||
| // Ensure the webview has a min height of the content it wants to show, | ||
| // and that the horizontal scrollbar that might exist, doesn't occlude the webview. | ||
| constexpr int horizontalScrollbarHeight = 12; | ||
| webView.MinHeight(documentHeight + horizontalScrollbarHeight); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| webView.NavigateToString(content); | ||
|
|
||
| m_stackPanel.Margin(xaml::ThicknessHelper::FromUniformLength(0)); | ||
| m_stackPanelUpper.Visibility(xaml::Visibility::Collapsed); | ||
|
|
||
| return; | ||
| } | ||
| } | ||
| // fall back to displaying the raw message string | ||
| const std::regex colorsRegex( | ||
|
|
@@ -173,16 +263,15 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| L" <TextBlock x:Name='MethodText' FontSize='14' Foreground='White' TextWrapping='Wrap' FontFamily='Consolas'/>" | ||
| L" <TextBlock x:Name='FrameText' FontSize='14' Foreground='Gray' TextWrapping='Wrap' FontFamily='Consolas'/>" | ||
| L"</StackPanel>"; | ||
| auto frameContent = winrt::unbox_value<winrt::Windows::UI::Xaml::Controls::StackPanel>( | ||
| winrt::Windows::UI::Xaml::Markup::XamlReader::Load(xamlFrameString)); | ||
| auto methodText = frameContent.FindName(L"MethodText").as<winrt::Windows::UI::Xaml::Controls::TextBlock>(); | ||
| auto frameText = frameContent.FindName(L"FrameText").as<winrt::Windows::UI::Xaml::Controls::TextBlock>(); | ||
| auto frameContent = | ||
| winrt::unbox_value<xaml::Controls::StackPanel>(xaml::Markup::XamlReader::Load(xamlFrameString)); | ||
| auto methodText = frameContent.FindName(L"MethodText").as<xaml::Controls::TextBlock>(); | ||
| auto frameText = frameContent.FindName(L"FrameText").as<xaml::Controls::TextBlock>(); | ||
| methodText.Text(Microsoft::Common::Unicode::Utf8ToUtf16(frame.Method)); | ||
|
|
||
| // When the user taps on a stack frame, tell the bundler to load that source in the users editor of choice | ||
| frameContent.Tapped([weakReactHost = m_weakReactHost, f = frame]( | ||
| winrt::Windows::Foundation::IInspectable const & /*sender*/, | ||
| winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs const & /*e*/) { | ||
| IInspectable const & /*sender*/, xaml::Input::TappedRoutedEventArgs const & /*e*/) { | ||
| if (auto reactHost = weakReactHost.GetStrongPtr()) { | ||
| auto devSettings = reactHost->Options().DeveloperSettings; | ||
| std::string stackFrameUri = "http://"; | ||
|
|
@@ -191,7 +280,7 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| stackFrameUri.append(devSettings.SourceBundlePath.empty() ? "8081" : devSettings.SourceBundlePort); | ||
| stackFrameUri.append("/open-stack-frame"); | ||
|
|
||
| winrt::Windows::Foundation::Uri uri{Microsoft::Common::Unicode::Utf8ToUtf16(stackFrameUri)}; | ||
| Uri uri{Microsoft::Common::Unicode::Utf8ToUtf16(stackFrameUri)}; | ||
| winrt::Windows::Web::Http::HttpClient httpClient{}; | ||
| winrt::Windows::Data::Json::JsonObject payload{}; | ||
|
|
||
|
|
@@ -226,13 +315,14 @@ struct RedBox : public std::enable_shared_from_this<RedBox> { | |
| } | ||
| } | ||
|
|
||
| winrt::Windows::UI::Xaml::Controls::StackPanel m_stackPanel{nullptr}; | ||
| winrt::Windows::UI::Xaml::Controls::Primitives::Popup m_popup{nullptr}; | ||
| winrt::Windows::UI::Xaml::Controls::Grid m_redboxContent{nullptr}; | ||
| winrt::Windows::UI::Xaml::Controls::Button m_dismissButton{nullptr}; | ||
| winrt::Windows::UI::Xaml::Controls::Button m_reloadButton{nullptr}; | ||
| winrt::Windows::UI::Xaml::Controls::TextBlock m_errorMessageText{nullptr}; | ||
| winrt::Windows::UI::Xaml::Controls::TextBlock m_errorStackText{nullptr}; | ||
| xaml::Controls::StackPanel m_stackPanelUpper{nullptr}; | ||
| xaml::Controls::StackPanel m_stackPanel{nullptr}; | ||
| xaml::Controls::Primitives::Popup m_popup{nullptr}; | ||
| xaml::Controls::Grid m_redboxContent{nullptr}; | ||
| xaml::Controls::Button m_dismissButton{nullptr}; | ||
| xaml::Controls::Button m_reloadButton{nullptr}; | ||
| xaml::Controls::TextBlock m_errorMessageText{nullptr}; | ||
| xaml::Controls::TextBlock m_errorStackText{nullptr}; | ||
|
|
||
| bool m_showing = false; | ||
| Mso::Functor<void(uint32_t)> m_onClosedCallback; | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.