plusui-native-core 0.1.4 → 0.1.7
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/Core/CMakeLists.txt +190 -7
- package/Core/Features/App/app.cpp +129 -0
- package/Core/Features/App/app.ts +126 -0
- package/Core/Features/Browser/browser.cpp +181 -0
- package/Core/Features/Browser/browser.ts +182 -0
- package/Core/Features/Clipboard/clipboard.cpp +234 -0
- package/Core/Features/Clipboard/clipboard.ts +113 -0
- package/Core/Features/Display/display.cpp +209 -0
- package/Core/Features/Display/display.ts +104 -0
- package/Core/Features/Event/Events.ts +166 -0
- package/Core/Features/Event/events.cpp +200 -0
- package/Core/Features/Keyboard/keyboard.cpp +186 -0
- package/Core/Features/Keyboard/keyboard.ts +175 -0
- package/Core/Features/Menu/context-menu.css +293 -0
- package/Core/Features/Menu/menu.cpp +481 -0
- package/Core/Features/Menu/menu.ts +439 -0
- package/Core/Features/Tray/tray.cpp +310 -0
- package/Core/Features/Tray/tray.ts +68 -0
- package/Core/Features/WebGPU/webgpu.cpp +939 -0
- package/Core/Features/WebGPU/webgpu.ts +1013 -0
- package/Core/Features/WebView/webview.cpp +1052 -0
- package/Core/Features/WebView/webview.ts +510 -0
- package/Core/Features/Window/window.cpp +664 -0
- package/Core/Features/Window/window.ts +142 -0
- package/Core/Features/WindowManager/window_manager.cpp +341 -0
- package/Core/include/plusui/app.hpp +73 -0
- package/Core/include/plusui/browser.hpp +66 -0
- package/Core/include/plusui/clipboard.hpp +41 -0
- package/Core/include/plusui/events.hpp +58 -0
- package/Core/include/{keyboard.hpp → plusui/keyboard.hpp} +21 -44
- package/Core/include/plusui/menu.hpp +153 -0
- package/Core/include/plusui/tray.hpp +93 -0
- package/Core/include/plusui/webgpu.hpp +434 -0
- package/Core/include/plusui/webview.hpp +142 -0
- package/Core/include/plusui/window.hpp +111 -0
- package/Core/include/plusui/window_manager.hpp +57 -0
- package/Core/vendor/WebView2EnvironmentOptions.h +406 -0
- package/Core/vendor/stb_image.h +7988 -0
- package/Core/vendor/webview.h +618 -510
- package/Core/vendor/webview2.h +52079 -0
- package/README.md +19 -0
- package/package.json +12 -15
- package/Core/include/app.hpp +0 -121
- package/Core/include/menu.hpp +0 -79
- package/Core/include/tray.hpp +0 -81
- package/Core/include/window.hpp +0 -106
- package/Core/src/app.cpp +0 -311
- package/Core/src/display.cpp +0 -424
- package/Core/src/tray.cpp +0 -275
- package/Core/src/window.cpp +0 -528
- package/dist/index.d.ts +0 -205
- package/dist/index.js +0 -198
- package/src/index.ts +0 -574
- /package/Core/include/{display.hpp → plusui/display.hpp} +0 -0
package/Core/CMakeLists.txt
CHANGED
|
@@ -5,11 +5,33 @@ set(CMAKE_CXX_STANDARD 20)
|
|
|
5
5
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
6
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
7
7
|
|
|
8
|
+
# ============================================================
|
|
9
|
+
# WebGPU (Optional - disabled by default)
|
|
10
|
+
# ============================================================
|
|
11
|
+
option(PLUSUI_ENABLE_WEBGPU "Enable WebGPU support via Dawn" OFF)
|
|
12
|
+
|
|
13
|
+
# Platform detection
|
|
14
|
+
if(WIN32)
|
|
15
|
+
add_definitions(-DPLUSUI_EDGE)
|
|
16
|
+
elseif(APPLE)
|
|
17
|
+
add_definitions(-DPLUSUI_COCOA)
|
|
18
|
+
else()
|
|
19
|
+
add_definitions(-DPLUSUI_GTK)
|
|
20
|
+
endif()
|
|
21
|
+
|
|
8
22
|
add_library(plusui STATIC
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
Features/App/app.cpp
|
|
24
|
+
Features/Window/window.cpp
|
|
25
|
+
Features/WindowManager/window_manager.cpp
|
|
26
|
+
Features/WebView/webview.cpp
|
|
27
|
+
Features/Browser/browser.cpp
|
|
28
|
+
Features/Display/display.cpp
|
|
29
|
+
Features/Tray/tray.cpp
|
|
30
|
+
Features/Clipboard/clipboard.cpp
|
|
31
|
+
Features/Menu/menu.cpp
|
|
32
|
+
Features/Keyboard/keyboard.cpp
|
|
33
|
+
Features/Event/events.cpp
|
|
34
|
+
Features/WebGPU/webgpu.cpp
|
|
13
35
|
)
|
|
14
36
|
|
|
15
37
|
target_include_directories(plusui PUBLIC
|
|
@@ -18,16 +40,177 @@ target_include_directories(plusui PUBLIC
|
|
|
18
40
|
$<INSTALL_INTERFACE:include>
|
|
19
41
|
)
|
|
20
42
|
|
|
21
|
-
|
|
43
|
+
# Define WEBVIEW_EDGE on Windows to enable WebView2 backend
|
|
44
|
+
if(WIN32)
|
|
45
|
+
target_compile_definitions(plusui PUBLIC WEBVIEW_EDGE)
|
|
46
|
+
endif()
|
|
22
47
|
target_compile_options(plusui PRIVATE
|
|
23
|
-
$<$<CXX_COMPILER_ID:MSVC>:/W4 /utf-8>
|
|
48
|
+
$<$<CXX_COMPILER_ID:MSVC>:/W4 /utf-8 /FS>
|
|
24
49
|
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra>
|
|
25
50
|
)
|
|
26
51
|
|
|
27
52
|
find_package(Threads REQUIRED)
|
|
53
|
+
target_link_libraries(plusui PRIVATE Threads::Threads)
|
|
54
|
+
|
|
55
|
+
# ============================================================
|
|
56
|
+
# WebGPU: Dawn Library (Optional)
|
|
57
|
+
# ============================================================
|
|
58
|
+
if(PLUSUI_ENABLE_WEBGPU)
|
|
59
|
+
include(FetchContent)
|
|
60
|
+
|
|
61
|
+
set(DAWN_FETCH_DEPENDENCIES ON)
|
|
62
|
+
set(DAWN_BUILD_SAMPLES OFF)
|
|
63
|
+
set(DAWN_BUILD_TESTS OFF)
|
|
64
|
+
if(WIN32)
|
|
65
|
+
set(DAWN_ENABLE_D3D12 ON)
|
|
66
|
+
set(DAWN_ENABLE_METAL OFF)
|
|
67
|
+
set(DAWN_ENABLE_VULKAN OFF)
|
|
68
|
+
set(DAWN_USE_X11 OFF)
|
|
69
|
+
elseif(APPLE)
|
|
70
|
+
set(DAWN_ENABLE_D3D12 OFF)
|
|
71
|
+
set(DAWN_ENABLE_METAL ON)
|
|
72
|
+
set(DAWN_ENABLE_VULKAN OFF)
|
|
73
|
+
set(DAWN_USE_X11 OFF)
|
|
74
|
+
else()
|
|
75
|
+
set(DAWN_ENABLE_D3D12 OFF)
|
|
76
|
+
set(DAWN_ENABLE_METAL OFF)
|
|
77
|
+
set(DAWN_ENABLE_VULKAN ON)
|
|
78
|
+
set(DAWN_USE_X11 ON)
|
|
79
|
+
endif()
|
|
80
|
+
|
|
81
|
+
FetchContent_Declare(
|
|
82
|
+
dawn
|
|
83
|
+
GIT_REPOSITORY https://dawn.googlesource.com/dawn
|
|
84
|
+
GIT_TAG d41e7df926f0d84ca64262cffa7f3a0ddc56c53c
|
|
85
|
+
GIT_SHALLOW TRUE
|
|
86
|
+
TIMEOUT 600
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
message(STATUS "Fetching Dawn WebGPU library...")
|
|
90
|
+
FetchContent_MakeAvailable(dawn)
|
|
91
|
+
|
|
92
|
+
target_link_libraries(plusui PUBLIC
|
|
93
|
+
dawncpp
|
|
94
|
+
dawn_native
|
|
95
|
+
dawn_proc
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
target_include_directories(plusui PUBLIC
|
|
99
|
+
${dawn_SOURCE_DIR}/include
|
|
100
|
+
${dawn_BINARY_DIR}/gen/include
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
target_compile_definitions(plusui PUBLIC PLUSUI_WEBGPU_ENABLED)
|
|
104
|
+
message(STATUS "WebGPU support enabled via Dawn")
|
|
105
|
+
else()
|
|
106
|
+
message(STATUS "WebGPU support disabled (set PLUSUI_ENABLE_WEBGPU=ON to enable)")
|
|
107
|
+
endif()
|
|
28
108
|
|
|
109
|
+
# ============================================================
|
|
110
|
+
# Windows: WebView2 SDK
|
|
111
|
+
# ============================================================
|
|
29
112
|
if(WIN32)
|
|
30
|
-
|
|
113
|
+
include(FetchContent)
|
|
114
|
+
|
|
115
|
+
# Download Microsoft WebView2 SDK
|
|
116
|
+
FetchContent_Declare(
|
|
117
|
+
webview2
|
|
118
|
+
URL https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/1.0.2210.55
|
|
119
|
+
URL_HASH SHA256=482d0b55f78a9a90fe4a03e66b5ba5d0dc4b9b55dfe9e9e4e3f3e6e6e3e3e3e3e
|
|
120
|
+
DOWNLOAD_NO_EXTRACT FALSE
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Check if already downloaded, if not use alternative method
|
|
124
|
+
set(WEBVIEW2_DIR "${CMAKE_BINARY_DIR}/_deps/webview2")
|
|
125
|
+
|
|
126
|
+
if(NOT EXISTS "${WEBVIEW2_DIR}/build/native/include/WebView2.h")
|
|
127
|
+
message(STATUS "Downloading WebView2 SDK...")
|
|
128
|
+
|
|
129
|
+
# Create directory
|
|
130
|
+
file(MAKE_DIRECTORY "${WEBVIEW2_DIR}")
|
|
131
|
+
|
|
132
|
+
# Download the NuGet package
|
|
133
|
+
set(WEBVIEW2_NUGET_URL "https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/1.0.2210.55")
|
|
134
|
+
set(WEBVIEW2_ZIP "${WEBVIEW2_DIR}/webview2.zip")
|
|
135
|
+
|
|
136
|
+
if(NOT EXISTS "${WEBVIEW2_ZIP}")
|
|
137
|
+
file(DOWNLOAD
|
|
138
|
+
"${WEBVIEW2_NUGET_URL}"
|
|
139
|
+
"${WEBVIEW2_ZIP}"
|
|
140
|
+
SHOW_PROGRESS
|
|
141
|
+
STATUS DOWNLOAD_STATUS
|
|
142
|
+
)
|
|
143
|
+
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
|
|
144
|
+
if(NOT STATUS_CODE EQUAL 0)
|
|
145
|
+
message(WARNING "Failed to download WebView2 SDK. Trying alternative...")
|
|
146
|
+
# Try alternative URL
|
|
147
|
+
file(DOWNLOAD
|
|
148
|
+
"https://globalcdn.nuget.org/packages/microsoft.web.webview2.1.0.2210.55.nupkg"
|
|
149
|
+
"${WEBVIEW2_ZIP}"
|
|
150
|
+
SHOW_PROGRESS
|
|
151
|
+
)
|
|
152
|
+
endif()
|
|
153
|
+
endif()
|
|
154
|
+
|
|
155
|
+
# Extract the package
|
|
156
|
+
if(EXISTS "${WEBVIEW2_ZIP}" AND NOT EXISTS "${WEBVIEW2_DIR}/build")
|
|
157
|
+
message(STATUS "Extracting WebView2 SDK...")
|
|
158
|
+
execute_process(
|
|
159
|
+
COMMAND ${CMAKE_COMMAND} -E tar xzf "${WEBVIEW2_ZIP}"
|
|
160
|
+
WORKING_DIRECTORY "${WEBVIEW2_DIR}"
|
|
161
|
+
)
|
|
162
|
+
endif()
|
|
163
|
+
endif()
|
|
164
|
+
|
|
165
|
+
# Add WebView2 include directory
|
|
166
|
+
if(EXISTS "${WEBVIEW2_DIR}/build/native/include")
|
|
167
|
+
target_include_directories(plusui PUBLIC "${WEBVIEW2_DIR}/build/native/include")
|
|
168
|
+
message(STATUS "WebView2 SDK found at: ${WEBVIEW2_DIR}/build/native/include")
|
|
169
|
+
else()
|
|
170
|
+
message(WARNING "WebView2 SDK headers not found. Please install WebView2 SDK manually.")
|
|
171
|
+
endif()
|
|
172
|
+
|
|
173
|
+
# Link required Windows libraries
|
|
174
|
+
target_link_libraries(plusui PRIVATE
|
|
175
|
+
ole32
|
|
176
|
+
shell32
|
|
177
|
+
shlwapi
|
|
178
|
+
user32
|
|
179
|
+
version
|
|
180
|
+
advapi32
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# Link WebView2 loader library
|
|
184
|
+
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
185
|
+
set(WEBVIEW2_ARCH "x64")
|
|
186
|
+
else()
|
|
187
|
+
set(WEBVIEW2_ARCH "x86")
|
|
188
|
+
endif()
|
|
189
|
+
|
|
190
|
+
set(WEBVIEW2_LIB "${WEBVIEW2_DIR}/build/native/${WEBVIEW2_ARCH}/WebView2LoaderStatic.lib")
|
|
191
|
+
if(EXISTS "${WEBVIEW2_LIB}")
|
|
192
|
+
target_link_libraries(plusui PUBLIC "${WEBVIEW2_LIB}")
|
|
193
|
+
else()
|
|
194
|
+
# Try the loader DLL approach
|
|
195
|
+
set(WEBVIEW2_LOADER_LIB "${WEBVIEW2_DIR}/build/native/${WEBVIEW2_ARCH}/WebView2Loader.dll.lib")
|
|
196
|
+
if(EXISTS "${WEBVIEW2_LOADER_LIB}")
|
|
197
|
+
target_link_libraries(plusui PUBLIC "${WEBVIEW2_LOADER_LIB}")
|
|
198
|
+
endif()
|
|
199
|
+
endif()
|
|
200
|
+
|
|
201
|
+
elseif(APPLE)
|
|
202
|
+
# macOS: WebKit frameworks
|
|
203
|
+
find_library(WEBKIT_LIBRARY WebKit REQUIRED)
|
|
204
|
+
find_library(COCOA_LIBRARY Cocoa REQUIRED)
|
|
205
|
+
target_link_libraries(plusui PRIVATE ${WEBKIT_LIBRARY} ${COCOA_LIBRARY})
|
|
206
|
+
|
|
207
|
+
else()
|
|
208
|
+
# Linux: GTK + WebKitGTK
|
|
209
|
+
find_package(PkgConfig REQUIRED)
|
|
210
|
+
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
|
211
|
+
pkg_check_modules(WEBKIT2 REQUIRED webkit2gtk-4.0)
|
|
212
|
+
target_include_directories(plusui PRIVATE ${GTK3_INCLUDE_DIRS} ${WEBKIT2_INCLUDE_DIRS})
|
|
213
|
+
target_link_libraries(plusui PRIVATE ${GTK3_LIBRARIES} ${WEBKIT2_LIBRARIES})
|
|
31
214
|
endif()
|
|
32
215
|
|
|
33
216
|
install(TARGETS plusui ARCHIVE DESTINATION lib)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#ifdef _WIN32
|
|
2
|
+
#define WIN32_LEAN_AND_MEAN
|
|
3
|
+
#include <windows.h>
|
|
4
|
+
#endif
|
|
5
|
+
|
|
6
|
+
#include <plusui/app.hpp>
|
|
7
|
+
#include <plusui/tray.hpp>
|
|
8
|
+
#include <plusui/webview.hpp>
|
|
9
|
+
#include <plusui/window.hpp>
|
|
10
|
+
#include <plusui/window_manager.hpp>
|
|
11
|
+
|
|
12
|
+
namespace plusui {
|
|
13
|
+
|
|
14
|
+
struct App::Impl {
|
|
15
|
+
bool running = false;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
App::App() : pImpl(std::make_unique<Impl>()) {}
|
|
19
|
+
App::~App() = default;
|
|
20
|
+
|
|
21
|
+
void App::run() {
|
|
22
|
+
pImpl->running = true;
|
|
23
|
+
#ifdef _WIN32
|
|
24
|
+
MSG msg;
|
|
25
|
+
while (GetMessage(&msg, nullptr, 0, 0)) {
|
|
26
|
+
TranslateMessage(&msg);
|
|
27
|
+
DispatchMessage(&msg);
|
|
28
|
+
}
|
|
29
|
+
#endif
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
void App::quit() {
|
|
33
|
+
pImpl->running = false;
|
|
34
|
+
#ifdef _WIN32
|
|
35
|
+
PostQuitMessage(0);
|
|
36
|
+
#endif
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
App::Builder::Builder() = default;
|
|
40
|
+
|
|
41
|
+
App::Builder &App::Builder::title(const std::string &t) {
|
|
42
|
+
config.title = t;
|
|
43
|
+
return *this;
|
|
44
|
+
}
|
|
45
|
+
App::Builder &App::Builder::width(int w) {
|
|
46
|
+
config.width = w;
|
|
47
|
+
return *this;
|
|
48
|
+
}
|
|
49
|
+
App::Builder &App::Builder::height(int h) {
|
|
50
|
+
config.height = h;
|
|
51
|
+
return *this;
|
|
52
|
+
}
|
|
53
|
+
App::Builder &App::Builder::resizable(bool r) {
|
|
54
|
+
config.resizable = r;
|
|
55
|
+
return *this;
|
|
56
|
+
}
|
|
57
|
+
App::Builder &App::Builder::devtools(bool d) {
|
|
58
|
+
config.devtools = d;
|
|
59
|
+
return *this;
|
|
60
|
+
}
|
|
61
|
+
App::Builder &App::Builder::trayIcon(const std::string &icon) {
|
|
62
|
+
config.trayIconPath = icon;
|
|
63
|
+
return *this;
|
|
64
|
+
}
|
|
65
|
+
App::Builder &App::Builder::trayTooltip(const std::string &tooltip) {
|
|
66
|
+
config.trayTooltip = tooltip;
|
|
67
|
+
return *this;
|
|
68
|
+
}
|
|
69
|
+
App::Builder &App::Builder::alwaysOnTop(bool top) {
|
|
70
|
+
config.alwaysOnTop = top;
|
|
71
|
+
return *this;
|
|
72
|
+
}
|
|
73
|
+
App::Builder &App::Builder::centered(bool center) {
|
|
74
|
+
config.centered = center;
|
|
75
|
+
return *this;
|
|
76
|
+
}
|
|
77
|
+
App::Builder &App::Builder::transparent(bool transparent) {
|
|
78
|
+
config.transparent = transparent;
|
|
79
|
+
return *this;
|
|
80
|
+
}
|
|
81
|
+
App::Builder &App::Builder::decorations(bool decorations) {
|
|
82
|
+
config.decorations = decorations;
|
|
83
|
+
return *this;
|
|
84
|
+
}
|
|
85
|
+
App::Builder &App::Builder::skipTaskbar(bool skip) {
|
|
86
|
+
config.skipTaskbar = skip;
|
|
87
|
+
return *this;
|
|
88
|
+
}
|
|
89
|
+
App::Builder &App::Builder::scrollbars(bool show) {
|
|
90
|
+
config.scrollbars = show;
|
|
91
|
+
return *this;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
WebView App::Builder::build() {
|
|
95
|
+
WindowConfig winConfig;
|
|
96
|
+
winConfig.title = config.title;
|
|
97
|
+
winConfig.width = config.width;
|
|
98
|
+
winConfig.height = config.height;
|
|
99
|
+
winConfig.resizable = config.resizable;
|
|
100
|
+
winConfig.alwaysOnTop = config.alwaysOnTop;
|
|
101
|
+
winConfig.center = config.centered;
|
|
102
|
+
winConfig.transparent = config.transparent;
|
|
103
|
+
winConfig.decorations = config.decorations;
|
|
104
|
+
winConfig.skipTaskbar = config.skipTaskbar;
|
|
105
|
+
|
|
106
|
+
auto win = std::make_shared<Window>(Window::create(winConfig));
|
|
107
|
+
win->show();
|
|
108
|
+
|
|
109
|
+
WebViewConfig webConfig;
|
|
110
|
+
webConfig.devtools = config.devtools;
|
|
111
|
+
webConfig.scrollbars = config.scrollbars;
|
|
112
|
+
|
|
113
|
+
WebView wv = WebView::create(win->nativeHandle(), webConfig);
|
|
114
|
+
wv.setWindow(win);
|
|
115
|
+
|
|
116
|
+
if (!config.trayIconPath.empty()) {
|
|
117
|
+
wv.tray().setIcon(config.trayIconPath);
|
|
118
|
+
wv.tray().setVisible(true);
|
|
119
|
+
if (!config.trayTooltip.empty()) {
|
|
120
|
+
wv.tray().setTooltip(config.trayTooltip);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return wv;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
App::Builder createApp() { return App::Builder(); }
|
|
128
|
+
|
|
129
|
+
} // namespace plusui
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export interface AppConfig {
|
|
2
|
+
title?: string;
|
|
3
|
+
width?: number;
|
|
4
|
+
height?: number;
|
|
5
|
+
resizable?: boolean;
|
|
6
|
+
devtools?: boolean;
|
|
7
|
+
trayIcon?: string;
|
|
8
|
+
trayTooltip?: string;
|
|
9
|
+
alwaysOnTop?: boolean;
|
|
10
|
+
centered?: boolean;
|
|
11
|
+
transparent?: boolean;
|
|
12
|
+
decorations?: boolean;
|
|
13
|
+
skipTaskbar?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface InvokeOptions {
|
|
17
|
+
timeout?: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class App {
|
|
21
|
+
private initialized = false;
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
private config: AppConfig = {},
|
|
25
|
+
private invokeFn?: (name: string, args?: unknown[]) => Promise<unknown>
|
|
26
|
+
) {
|
|
27
|
+
if (typeof window !== 'undefined') {
|
|
28
|
+
this.init();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private init(): void {
|
|
33
|
+
if (this.initialized) return;
|
|
34
|
+
this.initialized = true;
|
|
35
|
+
|
|
36
|
+
if (typeof window !== 'undefined') {
|
|
37
|
+
const win = window as Window & {
|
|
38
|
+
__plusui_listeners__?: Map<string, Set<(...args: unknown[]) => void>>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
win.__plusui_listeners__ = new Map();
|
|
42
|
+
|
|
43
|
+
window.addEventListener('message', (event: MessageEvent) => {
|
|
44
|
+
if (event.data?.type === '__plusui_event__') {
|
|
45
|
+
const { event: eventName, payload } = event.data;
|
|
46
|
+
const listeners = win.__plusui_listeners__?.get(eventName);
|
|
47
|
+
if (listeners) {
|
|
48
|
+
listeners.forEach(cb => cb(payload));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async invoke<T = unknown>(name: string, args?: unknown[], options: InvokeOptions = {}): Promise<T> {
|
|
56
|
+
const { timeout = 30000 } = options;
|
|
57
|
+
|
|
58
|
+
if (this.invokeFn) {
|
|
59
|
+
return this.invokeFn(name, args) as Promise<T>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (typeof window !== 'undefined') {
|
|
63
|
+
const win = window as Window & {
|
|
64
|
+
__plusui_invoke__?: (name: string, args?: unknown[]) => Promise<unknown>;
|
|
65
|
+
__invoke__?: (name: string, args?: unknown[]) => Promise<unknown>;
|
|
66
|
+
__native_invoke__?: (request: string) => void;
|
|
67
|
+
};
|
|
68
|
+
// Check for SDK bridge first (__invoke__ from plusui-native-core)
|
|
69
|
+
if (win.__invoke__) {
|
|
70
|
+
return win.__invoke__(name, args) as Promise<T>;
|
|
71
|
+
}
|
|
72
|
+
// Check for legacy __plusui_invoke__
|
|
73
|
+
if (win.__plusui_invoke__) {
|
|
74
|
+
return win.__plusui_invoke__(name, args) as Promise<T>;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return new Promise((_, reject) => {
|
|
79
|
+
setTimeout(() => reject(new Error(`Invocation ${name} timed out`)), timeout);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
on(event: string, callback: (...args: unknown[]) => void): () => void {
|
|
84
|
+
if (typeof window === 'undefined') {
|
|
85
|
+
return () => { };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const win = window as Window & {
|
|
89
|
+
__plusui_listeners__?: Map<string, Set<(...args: unknown[]) => void>>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
if (!win.__plusui_listeners__) {
|
|
93
|
+
win.__plusui_listeners__ = new Map();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!win.__plusui_listeners__.has(event)) {
|
|
97
|
+
win.__plusui_listeners__.set(event, new Set());
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
win.__plusui_listeners__.get(event)!.add(callback);
|
|
101
|
+
|
|
102
|
+
return () => {
|
|
103
|
+
win.__plusui_listeners__.get(event)?.delete(callback);
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
once(event: string, callback: (...args: unknown[]) => void): void {
|
|
108
|
+
const unsubscribe = this.on(event, (...args) => {
|
|
109
|
+
unsubscribe();
|
|
110
|
+
callback(...args);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
emit(event: string, payload?: unknown): void {
|
|
115
|
+
if (typeof window !== 'undefined') {
|
|
116
|
+
const customEvent = new CustomEvent(event, { detail: payload });
|
|
117
|
+
window.dispatchEvent(customEvent);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function createApp(config?: AppConfig): App {
|
|
123
|
+
return new App(config);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export default App;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#include <iostream>
|
|
2
|
+
#include <plusui/browser.hpp>
|
|
3
|
+
#include <plusui/webview.hpp>
|
|
4
|
+
|
|
5
|
+
namespace plusui {
|
|
6
|
+
|
|
7
|
+
struct Browser::Impl {
|
|
8
|
+
WebView* webview = nullptr;
|
|
9
|
+
std::map<std::string, std::string> routes;
|
|
10
|
+
std::string currentRoute;
|
|
11
|
+
BrowserState state;
|
|
12
|
+
|
|
13
|
+
std::vector<NavigateCallback> navigateCallbacks;
|
|
14
|
+
std::vector<StateCallback> stateCallbacks;
|
|
15
|
+
std::vector<LoadCallback> loadStartCallbacks;
|
|
16
|
+
std::vector<LoadCallback> loadEndCallbacks;
|
|
17
|
+
std::vector<std::function<void(const std::string&)>> loadErrorCallbacks;
|
|
18
|
+
|
|
19
|
+
void updateState() {
|
|
20
|
+
if (webview) {
|
|
21
|
+
state.url = webview->getURL();
|
|
22
|
+
state.title = webview->getTitle();
|
|
23
|
+
state.canGoBack = webview->canGoBack();
|
|
24
|
+
state.canGoForward = webview->canGoForward();
|
|
25
|
+
state.isLoading = webview->isLoading();
|
|
26
|
+
|
|
27
|
+
for (auto& cb : stateCallbacks) {
|
|
28
|
+
cb(state);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void notifyNavigate(const std::string& url) {
|
|
34
|
+
state.url = url;
|
|
35
|
+
for (auto& cb : navigateCallbacks) {
|
|
36
|
+
cb(url);
|
|
37
|
+
}
|
|
38
|
+
updateState();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
Browser::Browser() : pImpl(std::make_shared<Impl>()) {}
|
|
43
|
+
|
|
44
|
+
Browser::~Browser() = default;
|
|
45
|
+
|
|
46
|
+
Browser Browser::create(WebView* webview) {
|
|
47
|
+
Browser browser;
|
|
48
|
+
browser.pImpl->webview = webview;
|
|
49
|
+
|
|
50
|
+
if (webview) {
|
|
51
|
+
webview->onNavigationStart([impl = browser.pImpl](const std::string& url) {
|
|
52
|
+
impl->notifyNavigate(url);
|
|
53
|
+
return true;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
webview->onLoadStart([impl = browser.pImpl]() {
|
|
57
|
+
impl->state.isLoading = true;
|
|
58
|
+
for (auto& cb : impl->loadStartCallbacks) {
|
|
59
|
+
cb();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
webview->onLoadEnd([impl = browser.pImpl]() {
|
|
64
|
+
impl->state.isLoading = false;
|
|
65
|
+
impl->updateState();
|
|
66
|
+
for (auto& cb : impl->loadEndCallbacks) {
|
|
67
|
+
cb();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
webview->onLoadError([impl = browser.pImpl](const std::string& error, int code) {
|
|
72
|
+
impl->state.isLoading = false;
|
|
73
|
+
for (auto& cb : impl->loadErrorCallbacks) {
|
|
74
|
+
cb(error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return browser;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
void Browser::navigate(const std::string& url) {
|
|
83
|
+
if (pImpl->webview) {
|
|
84
|
+
pImpl->webview->navigate(url);
|
|
85
|
+
pImpl->notifyNavigate(url);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
void Browser::goBack() {
|
|
90
|
+
if (pImpl->webview && pImpl->webview->canGoBack()) {
|
|
91
|
+
pImpl->webview->goBack();
|
|
92
|
+
pImpl->updateState();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
void Browser::goForward() {
|
|
97
|
+
if (pImpl->webview && pImpl->webview->canGoForward()) {
|
|
98
|
+
pImpl->webview->goForward();
|
|
99
|
+
pImpl->updateState();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void Browser::reload() {
|
|
104
|
+
if (pImpl->webview) {
|
|
105
|
+
pImpl->webview->reload();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
void Browser::stop() {
|
|
110
|
+
if (pImpl->webview) {
|
|
111
|
+
pImpl->webview->stop();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
std::string Browser::getURL() const {
|
|
116
|
+
return pImpl->webview ? pImpl->webview->getURL() : "";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
std::string Browser::getTitle() const {
|
|
120
|
+
return pImpl->webview ? pImpl->webview->getTitle() : "";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
BrowserState Browser::getState() const {
|
|
124
|
+
return pImpl->state;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
bool Browser::canGoBack() const {
|
|
128
|
+
return pImpl->webview ? pImpl->webview->canGoBack() : false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
bool Browser::canGoForward() const {
|
|
132
|
+
return pImpl->webview ? pImpl->webview->canGoForward() : false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
bool Browser::isLoading() const {
|
|
136
|
+
return pImpl->state.isLoading;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
void Browser::onNavigate(NavigateCallback callback) {
|
|
140
|
+
pImpl->navigateCallbacks.push_back(callback);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
void Browser::onStateChange(StateCallback callback) {
|
|
144
|
+
pImpl->stateCallbacks.push_back(callback);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
void Browser::onLoadStart(LoadCallback callback) {
|
|
148
|
+
pImpl->loadStartCallbacks.push_back(callback);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
void Browser::onLoadEnd(LoadCallback callback) {
|
|
152
|
+
pImpl->loadEndCallbacks.push_back(callback);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
void Browser::onLoadError(std::function<void(const std::string& error)> callback) {
|
|
156
|
+
pImpl->loadErrorCallbacks.push_back(callback);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
void Browser::setRoutes(const std::map<std::string, std::string>& routes) {
|
|
160
|
+
pImpl->routes = routes;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void Browser::push(const std::string& route) {
|
|
164
|
+
pImpl->currentRoute = route;
|
|
165
|
+
auto it = pImpl->routes.find(route);
|
|
166
|
+
if (it != pImpl->routes.end()) {
|
|
167
|
+
navigate(it->second);
|
|
168
|
+
} else {
|
|
169
|
+
navigate(route);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
void Browser::replace(const std::string& route) {
|
|
174
|
+
push(route);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
std::string Browser::getCurrentRoute() const {
|
|
178
|
+
return pImpl->currentRoute;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
} // namespace plusui
|