@sentry/wizard 3.39.0 → 3.40.0
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/CHANGELOG.md +4 -0
- package/README.md +3 -3
- package/dist/e2e-tests/tests/flutter.test.d.ts +1 -0
- package/dist/e2e-tests/tests/flutter.test.js +190 -0
- package/dist/e2e-tests/tests/flutter.test.js.map +1 -0
- package/dist/e2e-tests/utils/index.d.ts +11 -0
- package/dist/e2e-tests/utils/index.js +36 -1
- package/dist/e2e-tests/utils/index.js.map +1 -1
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/apple/apple-wizard.js +1 -1
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/xcode-manager.d.ts +4 -4
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/flutter/code-tools.d.ts +17 -0
- package/dist/src/flutter/code-tools.js +263 -0
- package/dist/src/flutter/code-tools.js.map +1 -0
- package/dist/src/flutter/flutter-wizard.d.ts +2 -0
- package/dist/src/flutter/flutter-wizard.js +171 -0
- package/dist/src/flutter/flutter-wizard.js.map +1 -0
- package/dist/src/flutter/templates.d.ts +9 -0
- package/dist/src/flutter/templates.js +40 -0
- package/dist/src/flutter/templates.js.map +1 -0
- package/dist/src/run.d.ts +1 -1
- package/dist/src/run.js +39 -32
- package/dist/src/run.js.map +1 -1
- package/dist/src/utils/clack-utils.d.ts +1 -1
- package/dist/src/utils/clack-utils.js.map +1 -1
- package/dist/test/flutter/code-tools.test.d.ts +1 -0
- package/dist/test/flutter/code-tools.test.js +84 -0
- package/dist/test/flutter/code-tools.test.js.map +1 -0
- package/dist/test/flutter/templates.test.d.ts +1 -0
- package/dist/test/flutter/templates.test.js +41 -0
- package/dist/test/flutter/templates.test.js.map +1 -0
- package/e2e-tests/README.md +5 -1
- package/e2e-tests/test-applications/flutter-test-app/.metadata +45 -0
- package/e2e-tests/test-applications/flutter-test-app/README.md +16 -0
- package/e2e-tests/test-applications/flutter-test-app/analysis_options.yaml +28 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/build.gradle +44 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/debug/AndroidManifest.xml +7 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/AndroidManifest.xml +45 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/kotlin/com/example/flutter_magic/MainActivity.kt +5 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/drawable/launch_background.xml +12 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/values/styles.xml +18 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/main/res/values-night/styles.xml +18 -0
- package/e2e-tests/test-applications/flutter-test-app/android/app/src/profile/AndroidManifest.xml +7 -0
- package/e2e-tests/test-applications/flutter-test-app/android/build.gradle +18 -0
- package/e2e-tests/test-applications/flutter-test-app/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/e2e-tests/test-applications/flutter-test-app/android/gradle.properties +3 -0
- package/e2e-tests/test-applications/flutter-test-app/android/settings.gradle +25 -0
- package/e2e-tests/test-applications/flutter-test-app/lib/main.dart +125 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/CMakeLists.txt +145 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/CMakeLists.txt +88 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/generated_plugin_registrant.cc +11 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/generated_plugin_registrant.h +15 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/flutter/generated_plugins.cmake +23 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/main.cc +6 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/my_application.cc +124 -0
- package/e2e-tests/test-applications/flutter-test-app/linux/my_application.h +18 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Flutter/Flutter-Debug.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Flutter/Flutter-Release.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Flutter/GeneratedPluginRegistrant.swift +10 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Podfile +43 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/AppDelegate.swift +9 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Base.lproj/MainMenu.xib +343 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/AppInfo.xcconfig +14 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/Debug.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/Release.xcconfig +2 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Configs/Warnings.xcconfig +13 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/DebugProfile.entitlements +12 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Info.plist +32 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/MainFlutterWindow.swift +15 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner/Release.entitlements +8 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcodeproj/project.pbxproj +705 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +98 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcworkspace/contents.xcworkspacedata +7 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/e2e-tests/test-applications/flutter-test-app/macos/RunnerTests/RunnerTests.swift +12 -0
- package/e2e-tests/test-applications/flutter-test-app/pubspec.lock +213 -0
- package/e2e-tests/test-applications/flutter-test-app/pubspec.yaml +89 -0
- package/e2e-tests/test-applications/flutter-test-app/test/widget_test.dart +30 -0
- package/e2e-tests/test-applications/flutter-test-app/web/favicon.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-192.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-512.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-maskable-192.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/icons/Icon-maskable-512.png +0 -0
- package/e2e-tests/test-applications/flutter-test-app/web/index.html +38 -0
- package/e2e-tests/test-applications/flutter-test-app/web/manifest.json +35 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/CMakeLists.txt +108 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/CMakeLists.txt +109 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/generated_plugin_registrant.cc +11 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/generated_plugin_registrant.h +15 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/flutter/generated_plugins.cmake +23 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/CMakeLists.txt +40 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/Runner.rc +121 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/flutter_window.cpp +71 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/flutter_window.h +33 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/main.cpp +43 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/resource.h +16 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/resources/app_icon.ico +0 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/runner.exe.manifest +14 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/utils.cpp +65 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/utils.h +19 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/win32_window.cpp +288 -0
- package/e2e-tests/test-applications/flutter-test-app/windows/runner/win32_window.h +102 -0
- package/e2e-tests/tests/flutter.test.ts +127 -0
- package/e2e-tests/utils/index.ts +33 -0
- package/lib/Constants.ts +5 -0
- package/package.json +1 -1
- package/src/apple/apple-wizard.ts +1 -1
- package/src/apple/xcode-manager.ts +5 -5
- package/src/flutter/code-tools.ts +284 -0
- package/src/flutter/flutter-wizard.ts +164 -0
- package/src/flutter/templates.ts +90 -0
- package/src/run.ts +7 -0
- package/src/utils/clack-utils.ts +4 -2
- package/test/flutter/code-tools.test.ts +212 -0
- package/test/flutter/templates.test.ts +100 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
#include "win32_window.h"
|
|
2
|
+
|
|
3
|
+
#include <dwmapi.h>
|
|
4
|
+
#include <flutter_windows.h>
|
|
5
|
+
|
|
6
|
+
#include "resource.h"
|
|
7
|
+
|
|
8
|
+
namespace {
|
|
9
|
+
|
|
10
|
+
/// Window attribute that enables dark mode window decorations.
|
|
11
|
+
///
|
|
12
|
+
/// Redefined in case the developer's machine has a Windows SDK older than
|
|
13
|
+
/// version 10.0.22000.0.
|
|
14
|
+
/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
|
|
15
|
+
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
|
16
|
+
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
|
20
|
+
|
|
21
|
+
/// Registry key for app theme preference.
|
|
22
|
+
///
|
|
23
|
+
/// A value of 0 indicates apps should use dark mode. A non-zero or missing
|
|
24
|
+
/// value indicates apps should use light mode.
|
|
25
|
+
constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
|
|
26
|
+
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
|
|
27
|
+
constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
|
|
28
|
+
|
|
29
|
+
// The number of Win32Window objects that currently exist.
|
|
30
|
+
static int g_active_window_count = 0;
|
|
31
|
+
|
|
32
|
+
using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
|
|
33
|
+
|
|
34
|
+
// Scale helper to convert logical scaler values to physical using passed in
|
|
35
|
+
// scale factor
|
|
36
|
+
int Scale(int source, double scale_factor) {
|
|
37
|
+
return static_cast<int>(source * scale_factor);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
|
|
41
|
+
// This API is only needed for PerMonitor V1 awareness mode.
|
|
42
|
+
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
|
|
43
|
+
HMODULE user32_module = LoadLibraryA("User32.dll");
|
|
44
|
+
if (!user32_module) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
auto enable_non_client_dpi_scaling =
|
|
48
|
+
reinterpret_cast<EnableNonClientDpiScaling*>(
|
|
49
|
+
GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
|
|
50
|
+
if (enable_non_client_dpi_scaling != nullptr) {
|
|
51
|
+
enable_non_client_dpi_scaling(hwnd);
|
|
52
|
+
}
|
|
53
|
+
FreeLibrary(user32_module);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
} // namespace
|
|
57
|
+
|
|
58
|
+
// Manages the Win32Window's window class registration.
|
|
59
|
+
class WindowClassRegistrar {
|
|
60
|
+
public:
|
|
61
|
+
~WindowClassRegistrar() = default;
|
|
62
|
+
|
|
63
|
+
// Returns the singleton registrar instance.
|
|
64
|
+
static WindowClassRegistrar* GetInstance() {
|
|
65
|
+
if (!instance_) {
|
|
66
|
+
instance_ = new WindowClassRegistrar();
|
|
67
|
+
}
|
|
68
|
+
return instance_;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Returns the name of the window class, registering the class if it hasn't
|
|
72
|
+
// previously been registered.
|
|
73
|
+
const wchar_t* GetWindowClass();
|
|
74
|
+
|
|
75
|
+
// Unregisters the window class. Should only be called if there are no
|
|
76
|
+
// instances of the window.
|
|
77
|
+
void UnregisterWindowClass();
|
|
78
|
+
|
|
79
|
+
private:
|
|
80
|
+
WindowClassRegistrar() = default;
|
|
81
|
+
|
|
82
|
+
static WindowClassRegistrar* instance_;
|
|
83
|
+
|
|
84
|
+
bool class_registered_ = false;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
|
|
88
|
+
|
|
89
|
+
const wchar_t* WindowClassRegistrar::GetWindowClass() {
|
|
90
|
+
if (!class_registered_) {
|
|
91
|
+
WNDCLASS window_class{};
|
|
92
|
+
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
|
93
|
+
window_class.lpszClassName = kWindowClassName;
|
|
94
|
+
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
|
95
|
+
window_class.cbClsExtra = 0;
|
|
96
|
+
window_class.cbWndExtra = 0;
|
|
97
|
+
window_class.hInstance = GetModuleHandle(nullptr);
|
|
98
|
+
window_class.hIcon =
|
|
99
|
+
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
|
|
100
|
+
window_class.hbrBackground = 0;
|
|
101
|
+
window_class.lpszMenuName = nullptr;
|
|
102
|
+
window_class.lpfnWndProc = Win32Window::WndProc;
|
|
103
|
+
RegisterClass(&window_class);
|
|
104
|
+
class_registered_ = true;
|
|
105
|
+
}
|
|
106
|
+
return kWindowClassName;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
void WindowClassRegistrar::UnregisterWindowClass() {
|
|
110
|
+
UnregisterClass(kWindowClassName, nullptr);
|
|
111
|
+
class_registered_ = false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Win32Window::Win32Window() {
|
|
115
|
+
++g_active_window_count;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Win32Window::~Win32Window() {
|
|
119
|
+
--g_active_window_count;
|
|
120
|
+
Destroy();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
bool Win32Window::Create(const std::wstring& title,
|
|
124
|
+
const Point& origin,
|
|
125
|
+
const Size& size) {
|
|
126
|
+
Destroy();
|
|
127
|
+
|
|
128
|
+
const wchar_t* window_class =
|
|
129
|
+
WindowClassRegistrar::GetInstance()->GetWindowClass();
|
|
130
|
+
|
|
131
|
+
const POINT target_point = {static_cast<LONG>(origin.x),
|
|
132
|
+
static_cast<LONG>(origin.y)};
|
|
133
|
+
HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
|
|
134
|
+
UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
|
|
135
|
+
double scale_factor = dpi / 96.0;
|
|
136
|
+
|
|
137
|
+
HWND window = CreateWindow(
|
|
138
|
+
window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
|
|
139
|
+
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
|
|
140
|
+
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
|
|
141
|
+
nullptr, nullptr, GetModuleHandle(nullptr), this);
|
|
142
|
+
|
|
143
|
+
if (!window) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
UpdateTheme(window);
|
|
148
|
+
|
|
149
|
+
return OnCreate();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
bool Win32Window::Show() {
|
|
153
|
+
return ShowWindow(window_handle_, SW_SHOWNORMAL);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// static
|
|
157
|
+
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
|
158
|
+
UINT const message,
|
|
159
|
+
WPARAM const wparam,
|
|
160
|
+
LPARAM const lparam) noexcept {
|
|
161
|
+
if (message == WM_NCCREATE) {
|
|
162
|
+
auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
|
|
163
|
+
SetWindowLongPtr(window, GWLP_USERDATA,
|
|
164
|
+
reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
|
|
165
|
+
|
|
166
|
+
auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
|
|
167
|
+
EnableFullDpiSupportIfAvailable(window);
|
|
168
|
+
that->window_handle_ = window;
|
|
169
|
+
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
|
170
|
+
return that->MessageHandler(window, message, wparam, lparam);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return DefWindowProc(window, message, wparam, lparam);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
LRESULT
|
|
177
|
+
Win32Window::MessageHandler(HWND hwnd,
|
|
178
|
+
UINT const message,
|
|
179
|
+
WPARAM const wparam,
|
|
180
|
+
LPARAM const lparam) noexcept {
|
|
181
|
+
switch (message) {
|
|
182
|
+
case WM_DESTROY:
|
|
183
|
+
window_handle_ = nullptr;
|
|
184
|
+
Destroy();
|
|
185
|
+
if (quit_on_close_) {
|
|
186
|
+
PostQuitMessage(0);
|
|
187
|
+
}
|
|
188
|
+
return 0;
|
|
189
|
+
|
|
190
|
+
case WM_DPICHANGED: {
|
|
191
|
+
auto newRectSize = reinterpret_cast<RECT*>(lparam);
|
|
192
|
+
LONG newWidth = newRectSize->right - newRectSize->left;
|
|
193
|
+
LONG newHeight = newRectSize->bottom - newRectSize->top;
|
|
194
|
+
|
|
195
|
+
SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
|
|
196
|
+
newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
|
|
197
|
+
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
case WM_SIZE: {
|
|
201
|
+
RECT rect = GetClientArea();
|
|
202
|
+
if (child_content_ != nullptr) {
|
|
203
|
+
// Size and position the child window.
|
|
204
|
+
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
|
|
205
|
+
rect.bottom - rect.top, TRUE);
|
|
206
|
+
}
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
case WM_ACTIVATE:
|
|
211
|
+
if (child_content_ != nullptr) {
|
|
212
|
+
SetFocus(child_content_);
|
|
213
|
+
}
|
|
214
|
+
return 0;
|
|
215
|
+
|
|
216
|
+
case WM_DWMCOLORIZATIONCOLORCHANGED:
|
|
217
|
+
UpdateTheme(hwnd);
|
|
218
|
+
return 0;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return DefWindowProc(window_handle_, message, wparam, lparam);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
void Win32Window::Destroy() {
|
|
225
|
+
OnDestroy();
|
|
226
|
+
|
|
227
|
+
if (window_handle_) {
|
|
228
|
+
DestroyWindow(window_handle_);
|
|
229
|
+
window_handle_ = nullptr;
|
|
230
|
+
}
|
|
231
|
+
if (g_active_window_count == 0) {
|
|
232
|
+
WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
|
|
237
|
+
return reinterpret_cast<Win32Window*>(
|
|
238
|
+
GetWindowLongPtr(window, GWLP_USERDATA));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
void Win32Window::SetChildContent(HWND content) {
|
|
242
|
+
child_content_ = content;
|
|
243
|
+
SetParent(content, window_handle_);
|
|
244
|
+
RECT frame = GetClientArea();
|
|
245
|
+
|
|
246
|
+
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
|
|
247
|
+
frame.bottom - frame.top, true);
|
|
248
|
+
|
|
249
|
+
SetFocus(child_content_);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
RECT Win32Window::GetClientArea() {
|
|
253
|
+
RECT frame;
|
|
254
|
+
GetClientRect(window_handle_, &frame);
|
|
255
|
+
return frame;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
HWND Win32Window::GetHandle() {
|
|
259
|
+
return window_handle_;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
void Win32Window::SetQuitOnClose(bool quit_on_close) {
|
|
263
|
+
quit_on_close_ = quit_on_close;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
bool Win32Window::OnCreate() {
|
|
267
|
+
// No-op; provided for subclasses.
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
void Win32Window::OnDestroy() {
|
|
272
|
+
// No-op; provided for subclasses.
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
void Win32Window::UpdateTheme(HWND const window) {
|
|
276
|
+
DWORD light_mode;
|
|
277
|
+
DWORD light_mode_size = sizeof(light_mode);
|
|
278
|
+
LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
|
|
279
|
+
kGetPreferredBrightnessRegValue,
|
|
280
|
+
RRF_RT_REG_DWORD, nullptr, &light_mode,
|
|
281
|
+
&light_mode_size);
|
|
282
|
+
|
|
283
|
+
if (result == ERROR_SUCCESS) {
|
|
284
|
+
BOOL enable_dark_mode = light_mode == 0;
|
|
285
|
+
DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
|
286
|
+
&enable_dark_mode, sizeof(enable_dark_mode));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#ifndef RUNNER_WIN32_WINDOW_H_
|
|
2
|
+
#define RUNNER_WIN32_WINDOW_H_
|
|
3
|
+
|
|
4
|
+
#include <windows.h>
|
|
5
|
+
|
|
6
|
+
#include <functional>
|
|
7
|
+
#include <memory>
|
|
8
|
+
#include <string>
|
|
9
|
+
|
|
10
|
+
// A class abstraction for a high DPI-aware Win32 Window. Intended to be
|
|
11
|
+
// inherited from by classes that wish to specialize with custom
|
|
12
|
+
// rendering and input handling
|
|
13
|
+
class Win32Window {
|
|
14
|
+
public:
|
|
15
|
+
struct Point {
|
|
16
|
+
unsigned int x;
|
|
17
|
+
unsigned int y;
|
|
18
|
+
Point(unsigned int x, unsigned int y) : x(x), y(y) {}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
struct Size {
|
|
22
|
+
unsigned int width;
|
|
23
|
+
unsigned int height;
|
|
24
|
+
Size(unsigned int width, unsigned int height)
|
|
25
|
+
: width(width), height(height) {}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
Win32Window();
|
|
29
|
+
virtual ~Win32Window();
|
|
30
|
+
|
|
31
|
+
// Creates a win32 window with |title| that is positioned and sized using
|
|
32
|
+
// |origin| and |size|. New windows are created on the default monitor. Window
|
|
33
|
+
// sizes are specified to the OS in physical pixels, hence to ensure a
|
|
34
|
+
// consistent size this function will scale the inputted width and height as
|
|
35
|
+
// as appropriate for the default monitor. The window is invisible until
|
|
36
|
+
// |Show| is called. Returns true if the window was created successfully.
|
|
37
|
+
bool Create(const std::wstring& title, const Point& origin, const Size& size);
|
|
38
|
+
|
|
39
|
+
// Show the current window. Returns true if the window was successfully shown.
|
|
40
|
+
bool Show();
|
|
41
|
+
|
|
42
|
+
// Release OS resources associated with window.
|
|
43
|
+
void Destroy();
|
|
44
|
+
|
|
45
|
+
// Inserts |content| into the window tree.
|
|
46
|
+
void SetChildContent(HWND content);
|
|
47
|
+
|
|
48
|
+
// Returns the backing Window handle to enable clients to set icon and other
|
|
49
|
+
// window properties. Returns nullptr if the window has been destroyed.
|
|
50
|
+
HWND GetHandle();
|
|
51
|
+
|
|
52
|
+
// If true, closing this window will quit the application.
|
|
53
|
+
void SetQuitOnClose(bool quit_on_close);
|
|
54
|
+
|
|
55
|
+
// Return a RECT representing the bounds of the current client area.
|
|
56
|
+
RECT GetClientArea();
|
|
57
|
+
|
|
58
|
+
protected:
|
|
59
|
+
// Processes and route salient window messages for mouse handling,
|
|
60
|
+
// size change and DPI. Delegates handling of these to member overloads that
|
|
61
|
+
// inheriting classes can handle.
|
|
62
|
+
virtual LRESULT MessageHandler(HWND window,
|
|
63
|
+
UINT const message,
|
|
64
|
+
WPARAM const wparam,
|
|
65
|
+
LPARAM const lparam) noexcept;
|
|
66
|
+
|
|
67
|
+
// Called when CreateAndShow is called, allowing subclass window-related
|
|
68
|
+
// setup. Subclasses should return false if setup fails.
|
|
69
|
+
virtual bool OnCreate();
|
|
70
|
+
|
|
71
|
+
// Called when Destroy is called.
|
|
72
|
+
virtual void OnDestroy();
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
friend class WindowClassRegistrar;
|
|
76
|
+
|
|
77
|
+
// OS callback called by message pump. Handles the WM_NCCREATE message which
|
|
78
|
+
// is passed when the non-client area is being created and enables automatic
|
|
79
|
+
// non-client DPI scaling so that the non-client area automatically
|
|
80
|
+
// responds to changes in DPI. All other messages are handled by
|
|
81
|
+
// MessageHandler.
|
|
82
|
+
static LRESULT CALLBACK WndProc(HWND const window,
|
|
83
|
+
UINT const message,
|
|
84
|
+
WPARAM const wparam,
|
|
85
|
+
LPARAM const lparam) noexcept;
|
|
86
|
+
|
|
87
|
+
// Retrieves a class instance pointer for |window|
|
|
88
|
+
static Win32Window* GetThisFromHandle(HWND const window) noexcept;
|
|
89
|
+
|
|
90
|
+
// Update the window frame's theme to match the system theme.
|
|
91
|
+
static void UpdateTheme(HWND const window);
|
|
92
|
+
|
|
93
|
+
bool quit_on_close_ = false;
|
|
94
|
+
|
|
95
|
+
// window handle for top level window.
|
|
96
|
+
HWND window_handle_ = nullptr;
|
|
97
|
+
|
|
98
|
+
// window handle for hosted content.
|
|
99
|
+
HWND child_content_ = nullptr;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
#endif // RUNNER_WIN32_WINDOW_H_
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* eslint-disable jest/expect-expect */
|
|
2
|
+
import { Integration } from '../../lib/Constants';
|
|
3
|
+
import {
|
|
4
|
+
// checkEnvBuildPlugin,
|
|
5
|
+
cleanupGit,
|
|
6
|
+
KEYS,
|
|
7
|
+
revertLocalChanges,
|
|
8
|
+
} from '../utils';
|
|
9
|
+
import { startWizardInstance } from '../utils';
|
|
10
|
+
import {
|
|
11
|
+
checkFileContents,
|
|
12
|
+
// checkFileExists,
|
|
13
|
+
checkSentryProperties,
|
|
14
|
+
checkIfFlutterBuilds,
|
|
15
|
+
} from '../utils';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
|
|
19
|
+
describe('Flutter', () => {
|
|
20
|
+
const integration = Integration.flutter;
|
|
21
|
+
const projectDir = path.resolve(
|
|
22
|
+
__dirname,
|
|
23
|
+
'../test-applications/flutter-test-app',
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
describe('with apple platforms', () => {
|
|
27
|
+
beforeAll(async () => {
|
|
28
|
+
const wizardInstance = startWizardInstance(integration, projectDir);
|
|
29
|
+
|
|
30
|
+
const tracingOptionPrompted = await wizardInstance.waitForOutput(
|
|
31
|
+
// "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
|
|
32
|
+
'to track the performance of your application?',
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const profilingOptionPrompted = tracingOptionPrompted &&
|
|
36
|
+
(await wizardInstance.sendStdinAndWaitForOutput(
|
|
37
|
+
[KEYS.ENTER],
|
|
38
|
+
// "Do you want to enable Profiling", sometimes doesn't work as `Profiling` can be printed in bold.
|
|
39
|
+
'to analyze CPU usage and optimize performance-critical code on iOS & macOS?',
|
|
40
|
+
));
|
|
41
|
+
|
|
42
|
+
profilingOptionPrompted &&
|
|
43
|
+
(await wizardInstance.sendStdinAndWaitForOutput(
|
|
44
|
+
[KEYS.ENTER],
|
|
45
|
+
'Successfully installed the Sentry Flutter SDK!',
|
|
46
|
+
));
|
|
47
|
+
|
|
48
|
+
wizardInstance.kill();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
afterAll(() => {
|
|
52
|
+
revertLocalChanges(projectDir);
|
|
53
|
+
cleanupGit(projectDir);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('pubspec.yaml is updated.', () => {
|
|
57
|
+
checkFileContents(`${projectDir}/pubspec.yaml`, `sentry_flutter:`); // dependencies
|
|
58
|
+
checkFileContents(`${projectDir}/pubspec.yaml`, `sentry_dart_plugin:`); // dev_dependencies
|
|
59
|
+
checkFileContents(`${projectDir}/pubspec.yaml`, `sentry:`); // gradle plugin options
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('sentry.properties exists and has auth token', () => {
|
|
63
|
+
checkSentryProperties(projectDir);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('.gitignore has sentry.properties', () => {
|
|
67
|
+
checkFileContents(`${projectDir}/.gitignore`, `sentry.properties`);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('lib/main.dart calls sentry init', () => {
|
|
71
|
+
checkFileContents(`${projectDir}/lib/main.dart`, `import 'package:sentry_flutter/sentry_flutter.dart';`);
|
|
72
|
+
checkFileContents(`${projectDir}/lib/main.dart`, `await SentryFlutter.init(`);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('lib/main.dart enables tracing and profiling', () => {
|
|
76
|
+
checkFileContents(`${projectDir}/lib/main.dart`, `options.tracesSampleRate = 1.0;`);
|
|
77
|
+
checkFileContents(`${projectDir}/lib/main.dart`, `options.profilesSampleRate = 1.0;`);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('builds correctly', async () => {
|
|
81
|
+
await checkIfFlutterBuilds(projectDir, '✓ Built build/web');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('without apple platforms', () => {
|
|
86
|
+
beforeAll(async () => {
|
|
87
|
+
|
|
88
|
+
const wizardInstance = startWizardInstance(integration, projectDir);
|
|
89
|
+
|
|
90
|
+
if (fs.existsSync(`${projectDir}/ios`)) {
|
|
91
|
+
fs.renameSync(`${projectDir}/ios`, `${projectDir}/_ios`);
|
|
92
|
+
}
|
|
93
|
+
if (fs.existsSync(`${projectDir}/macos`)) {
|
|
94
|
+
fs.renameSync(`${projectDir}/macos`, `${projectDir}/_macos`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const continueOnUncommitedFilesPromted = await wizardInstance.waitForOutput(
|
|
98
|
+
'Do you want to continue anyway?'
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
const tracingOptionPrompted = continueOnUncommitedFilesPromted &&
|
|
102
|
+
(await wizardInstance.sendStdinAndWaitForOutput(
|
|
103
|
+
[KEYS.ENTER],
|
|
104
|
+
// "Do you want to enable Tracing", sometimes doesn't work as `Tracing` can be printed in bold.
|
|
105
|
+
'to track the performance of your application?',
|
|
106
|
+
));
|
|
107
|
+
|
|
108
|
+
tracingOptionPrompted &&
|
|
109
|
+
(await wizardInstance.sendStdinAndWaitForOutput(
|
|
110
|
+
[KEYS.ENTER],
|
|
111
|
+
'Successfully installed the Sentry Flutter SDK!',
|
|
112
|
+
));
|
|
113
|
+
|
|
114
|
+
wizardInstance.kill();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
afterAll(() => {
|
|
118
|
+
revertLocalChanges(projectDir);
|
|
119
|
+
cleanupGit(projectDir);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('lib/main.dart does not add profiling with missing ios and macos folder', () => {
|
|
123
|
+
const fileContent = fs.readFileSync(`${projectDir}/lib/main.dart`, 'utf-8');
|
|
124
|
+
expect(fileContent).not.toContain(`options.profilesSampleRate = 1.0;`);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
package/e2e-tests/utils/index.ts
CHANGED
|
@@ -348,6 +348,18 @@ export function checkEnvBuildPlugin(projectDir: string) {
|
|
|
348
348
|
}
|
|
349
349
|
|
|
350
350
|
/**
|
|
351
|
+
* Check if the sentry.properties contains the auth token
|
|
352
|
+
* @param projectDir
|
|
353
|
+
*/
|
|
354
|
+
export function checkSentryProperties(projectDir: string) {
|
|
355
|
+
checkFileContents(
|
|
356
|
+
`${projectDir}/sentry.properties`,
|
|
357
|
+
`auth_token=${TEST_ARGS.AUTH_TOKEN}`,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Check if the project builds
|
|
351
363
|
* Check if the project builds and ends with status code 0.
|
|
352
364
|
* @param projectDir
|
|
353
365
|
*/
|
|
@@ -363,6 +375,27 @@ export async function checkIfBuilds(projectDir: string) {
|
|
|
363
375
|
).resolves.toBe(true);
|
|
364
376
|
}
|
|
365
377
|
|
|
378
|
+
/**
|
|
379
|
+
* Check if the flutter project builds
|
|
380
|
+
* @param projectDir
|
|
381
|
+
*/
|
|
382
|
+
export async function checkIfFlutterBuilds(
|
|
383
|
+
projectDir: string,
|
|
384
|
+
expectedOutput: string,
|
|
385
|
+
debug = false,
|
|
386
|
+
) {
|
|
387
|
+
const testEnv = new WizardTestEnv('flutter', ['build', 'web'], {
|
|
388
|
+
cwd: projectDir,
|
|
389
|
+
debug: debug,
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
await expect(
|
|
393
|
+
testEnv.waitForOutput(expectedOutput, {
|
|
394
|
+
timeout: 120_000,
|
|
395
|
+
}),
|
|
396
|
+
).resolves.toBe(true);
|
|
397
|
+
}
|
|
398
|
+
|
|
366
399
|
/**
|
|
367
400
|
* Check if the project runs on dev mode
|
|
368
401
|
* @param projectDir
|
package/lib/Constants.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Key value should be the same here */
|
|
2
2
|
export enum Integration {
|
|
3
3
|
reactNative = 'reactNative',
|
|
4
|
+
flutter = 'flutter',
|
|
4
5
|
ios = 'ios',
|
|
5
6
|
android = 'android',
|
|
6
7
|
cordova = 'cordova',
|
|
@@ -41,6 +42,8 @@ export function getIntegrationDescription(type: string): string {
|
|
|
41
42
|
return 'Android';
|
|
42
43
|
case Integration.reactNative:
|
|
43
44
|
return 'React Native';
|
|
45
|
+
case Integration.flutter:
|
|
46
|
+
return 'Flutter';
|
|
44
47
|
case Integration.cordova:
|
|
45
48
|
return 'Cordova';
|
|
46
49
|
case Integration.electron:
|
|
@@ -66,6 +69,8 @@ export function mapIntegrationToPlatform(type: string): string | undefined {
|
|
|
66
69
|
return 'android';
|
|
67
70
|
case Integration.reactNative:
|
|
68
71
|
return 'react-native';
|
|
72
|
+
case Integration.flutter:
|
|
73
|
+
return 'flutter';
|
|
69
74
|
case Integration.cordova:
|
|
70
75
|
return 'cordova';
|
|
71
76
|
case Integration.electron:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/wizard",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.40.0",
|
|
4
4
|
"homepage": "https://github.com/getsentry/sentry-wizard",
|
|
5
5
|
"repository": "https://github.com/getsentry/sentry-wizard",
|
|
6
6
|
"description": "Sentry wizard helping you to configure your project",
|
|
@@ -109,7 +109,7 @@ async function runAppleWizardWithTelementry(
|
|
|
109
109
|
const availableTargets = xcProject.getAllTargets();
|
|
110
110
|
|
|
111
111
|
if (availableTargets.length == 0) {
|
|
112
|
-
clack.log.error(`No
|
|
112
|
+
clack.log.error(`No suitable target found in ${xcodeProjFile}`);
|
|
113
113
|
Sentry.setTag('No-Target', true);
|
|
114
114
|
await abort();
|
|
115
115
|
return;
|
|
@@ -10,7 +10,7 @@ import * as templates from './templates';
|
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
const xcode = require('xcode');
|
|
12
12
|
|
|
13
|
-
interface
|
|
13
|
+
interface ProjectFile {
|
|
14
14
|
key: string;
|
|
15
15
|
path: string;
|
|
16
16
|
}
|
|
@@ -190,7 +190,7 @@ export class XcodeProject {
|
|
|
190
190
|
projectPath: string;
|
|
191
191
|
project: any;
|
|
192
192
|
objects: any;
|
|
193
|
-
files:
|
|
193
|
+
files: ProjectFile[] | undefined;
|
|
194
194
|
|
|
195
195
|
public constructor(projectPath: string) {
|
|
196
196
|
this.projectPath = projectPath;
|
|
@@ -282,7 +282,7 @@ export class XcodeProject {
|
|
|
282
282
|
.filter((f: string) => f.length > 0) as string[];
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
projectFiles():
|
|
285
|
+
projectFiles(): ProjectFile[] {
|
|
286
286
|
if (this.files === undefined) {
|
|
287
287
|
const proj = this.project.getFirstProject();
|
|
288
288
|
const mainGroupKey = proj.firstProject.mainGroup;
|
|
@@ -292,8 +292,8 @@ export class XcodeProject {
|
|
|
292
292
|
return this.files;
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
buildGroup(group: any, path = ''):
|
|
296
|
-
const result:
|
|
295
|
+
buildGroup(group: any, path = ''): ProjectFile[] {
|
|
296
|
+
const result: ProjectFile[] = [];
|
|
297
297
|
for (const child of group.children) {
|
|
298
298
|
if (this.objects.PBXFileReference[child.value]) {
|
|
299
299
|
const fileReference = this.objects.PBXFileReference[child.value];
|