fit-webview-bridge 0.2.0a2__tar.gz → 0.2.0a4__tar.gz
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.
Potentially problematic release.
This version of fit-webview-bridge might be problematic. Click here for more details.
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/PKG-INFO +1 -1
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/pyproject.toml +1 -1
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/src/macos/WKWebViewWidget.mm +87 -10
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/.github/workflows/wheels-macos.yml +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/.gitignore +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/.vscode/settings.json +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/README.md +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/bindings/pyside6/macos/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/bindings/pyside6/macos/typesystem_wkwebview.xml +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/examples/macos/wkwebview_demo.py +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/fit_webview_bridge/__init__.py +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/src/macos/CMakeLists.txt +0 -0
- {fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/src/macos/WKWebViewWidget.h +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fit-webview-bridge"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.0a4"
|
|
4
4
|
description = "Qt native WebView bridge with PySide6 bindings"
|
|
5
5
|
requires-python = ">=3.11,<3.14"
|
|
6
6
|
dependencies = ["PySide6==6.9.0", "shiboken6==6.9.0", "shiboken6-generator==6.9.0"]
|
|
@@ -8,10 +8,13 @@
|
|
|
8
8
|
#include <QUrl>
|
|
9
9
|
|
|
10
10
|
@class WKNavDelegate;
|
|
11
|
+
@class FitUrlMsgHandler;
|
|
11
12
|
|
|
12
13
|
struct WKWebViewWidget::Impl {
|
|
13
|
-
WKWebView*
|
|
14
|
-
WKNavDelegate*
|
|
14
|
+
WKWebView* wk = nil;
|
|
15
|
+
WKNavDelegate* delegate = nil;
|
|
16
|
+
WKUserContentController* ucc = nil;
|
|
17
|
+
FitUrlMsgHandler* msg = nil;
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
@interface WKNavDelegate : NSObject <WKNavigationDelegate>
|
|
@@ -19,11 +22,34 @@ struct WKWebViewWidget::Impl {
|
|
|
19
22
|
@end
|
|
20
23
|
|
|
21
24
|
@implementation WKNavDelegate
|
|
25
|
+
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
|
|
26
|
+
if (!self.owner) return;
|
|
27
|
+
if (webView.URL)
|
|
28
|
+
emit self.owner->urlChanged(QUrl::fromEncoded(QByteArray(webView.URL.absoluteString.UTF8String)));
|
|
29
|
+
emit self.owner->loadProgress(5);
|
|
30
|
+
emit self.owner->canGoBackChanged(webView.canGoBack);
|
|
31
|
+
emit self.owner->canGoForwardChanged(webView.canGoForward);
|
|
32
|
+
}
|
|
33
|
+
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
|
|
34
|
+
if (!self.owner) return;
|
|
35
|
+
if (webView.URL)
|
|
36
|
+
emit self.owner->urlChanged(QUrl::fromEncoded(QByteArray(webView.URL.absoluteString.UTF8String)));
|
|
37
|
+
emit self.owner->loadProgress(50);
|
|
38
|
+
emit self.owner->canGoBackChanged(webView.canGoBack);
|
|
39
|
+
emit self.owner->canGoForwardChanged(webView.canGoForward);
|
|
40
|
+
}
|
|
41
|
+
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
|
|
42
|
+
if (!self.owner) return;
|
|
43
|
+
if (webView.URL)
|
|
44
|
+
emit self.owner->urlChanged(QUrl::fromEncoded(QByteArray(webView.URL.absoluteString.UTF8String)));
|
|
45
|
+
}
|
|
22
46
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
|
23
47
|
if (!self.owner) return;
|
|
24
48
|
emit self.owner->loadFinished(true);
|
|
25
|
-
if (webView.URL)
|
|
26
|
-
|
|
49
|
+
if (webView.URL)
|
|
50
|
+
emit self.owner->urlChanged(QUrl::fromEncoded(QByteArray(webView.URL.absoluteString.UTF8String)));
|
|
51
|
+
if (webView.title)
|
|
52
|
+
emit self.owner->titleChanged(QString::fromUtf8(webView.title.UTF8String));
|
|
27
53
|
emit self.owner->loadProgress(100);
|
|
28
54
|
emit self.owner->canGoBackChanged(webView.canGoBack);
|
|
29
55
|
emit self.owner->canGoForwardChanged(webView.canGoForward);
|
|
@@ -35,20 +61,32 @@ struct WKWebViewWidget::Impl {
|
|
|
35
61
|
emit self.owner->canGoBackChanged(webView.canGoBack);
|
|
36
62
|
emit self.owner->canGoForwardChanged(webView.canGoForward);
|
|
37
63
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
64
|
+
@end
|
|
65
|
+
|
|
66
|
+
// Handler per messaggi JS (SPA: pushState/replaceState/popstate/click)
|
|
67
|
+
@interface FitUrlMsgHandler : NSObject <WKScriptMessageHandler>
|
|
68
|
+
@property(nonatomic, assign) WKWebViewWidget* owner;
|
|
69
|
+
@end
|
|
70
|
+
|
|
71
|
+
@implementation FitUrlMsgHandler
|
|
72
|
+
- (void)userContentController:(WKUserContentController *)userContentController
|
|
73
|
+
didReceiveScriptMessage:(WKScriptMessage *)message {
|
|
74
|
+
if (!self.owner) return;
|
|
75
|
+
if (![message.name isEqualToString:@"fitUrlChanged"]) return;
|
|
76
|
+
if (![message.body isKindOfClass:[NSString class]]) return;
|
|
77
|
+
QString s = QString::fromUtf8([(NSString*)message.body UTF8String]);
|
|
78
|
+
emit self.owner->urlChanged(QUrl::fromEncoded(s.toUtf8()));
|
|
43
79
|
}
|
|
44
80
|
@end
|
|
45
81
|
|
|
82
|
+
// Conversione QUrl -> NSURL con forzatura http->https e normalizzazione user-input
|
|
46
83
|
static NSURL* toNSURL(QUrl u) {
|
|
47
84
|
if (!u.isValid()) return nil;
|
|
48
85
|
|
|
49
86
|
if (u.scheme().isEmpty())
|
|
50
87
|
u = QUrl::fromUserInput(u.toString());
|
|
51
88
|
|
|
89
|
+
// Forza sempre http -> https (nessuna eccezione)
|
|
52
90
|
if (u.scheme() == "http")
|
|
53
91
|
u.setScheme("https");
|
|
54
92
|
|
|
@@ -59,7 +97,6 @@ static NSURL* toNSURL(QUrl u) {
|
|
|
59
97
|
return [NSURL URLWithString:[NSString stringWithUTF8String:enc.constData()]];
|
|
60
98
|
}
|
|
61
99
|
|
|
62
|
-
|
|
63
100
|
WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
64
101
|
: QWidget(parent), d(new Impl) {
|
|
65
102
|
setAttribute(Qt::WA_NativeWindow, true);
|
|
@@ -70,6 +107,39 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
|
70
107
|
if ([cfg respondsToSelector:@selector(defaultWebpagePreferences)]) {
|
|
71
108
|
cfg.defaultWebpagePreferences.allowsContentJavaScript = YES;
|
|
72
109
|
}
|
|
110
|
+
|
|
111
|
+
// UserContentController + script per intercettare navigazioni SPA
|
|
112
|
+
d->ucc = [WKUserContentController new];
|
|
113
|
+
d->msg = [FitUrlMsgHandler new];
|
|
114
|
+
d->msg.owner = this;
|
|
115
|
+
[d->ucc addScriptMessageHandler:d->msg name:@"fitUrlChanged"];
|
|
116
|
+
|
|
117
|
+
NSString* js =
|
|
118
|
+
@"(function(){"
|
|
119
|
+
@" function emit(){"
|
|
120
|
+
@" try{ window.webkit.messageHandlers.fitUrlChanged.postMessage(location.href); }catch(e){}"
|
|
121
|
+
@" }"
|
|
122
|
+
@" var _ps = history.pushState;"
|
|
123
|
+
@" history.pushState = function(){ _ps.apply(this, arguments); emit(); };"
|
|
124
|
+
@" var _rs = history.replaceState;"
|
|
125
|
+
@" history.replaceState = function(){ _rs.apply(this, arguments); emit(); };"
|
|
126
|
+
@" window.addEventListener('popstate', emit, true);"
|
|
127
|
+
@" document.addEventListener('click', function(ev){"
|
|
128
|
+
@" var a = ev.target && ev.target.closest ? ev.target.closest('a[href]') : null;"
|
|
129
|
+
@" if (!a) return;"
|
|
130
|
+
@" if (a.target === '_blank' || a.hasAttribute('download')) return;"
|
|
131
|
+
@" setTimeout(emit, 0);" // lascia tempo alla SPA di aggiornare l’URL
|
|
132
|
+
@" }, true);"
|
|
133
|
+
@"})();";
|
|
134
|
+
|
|
135
|
+
WKUserScript* us = [[WKUserScript alloc]
|
|
136
|
+
initWithSource:js
|
|
137
|
+
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
|
|
138
|
+
forMainFrameOnly:YES];
|
|
139
|
+
|
|
140
|
+
[d->ucc addUserScript:us];
|
|
141
|
+
cfg.userContentController = d->ucc;
|
|
142
|
+
|
|
73
143
|
d->wk = [[WKWebView alloc] initWithFrame:nsParent.bounds configuration:cfg];
|
|
74
144
|
d->wk.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
|
75
145
|
[nsParent addSubview:d->wk];
|
|
@@ -81,8 +151,15 @@ WKWebViewWidget::WKWebViewWidget(QWidget* parent)
|
|
|
81
151
|
|
|
82
152
|
WKWebViewWidget::~WKWebViewWidget() {
|
|
83
153
|
if (!d) return;
|
|
154
|
+
if (d->ucc && d->msg) {
|
|
155
|
+
@try { [d->ucc removeScriptMessageHandlerForName:@"fitUrlChanged"]; } @catch (...) {}
|
|
156
|
+
}
|
|
157
|
+
d->msg = nil;
|
|
158
|
+
|
|
84
159
|
if (d->wk) { [d->wk removeFromSuperview]; d->wk = nil; }
|
|
85
160
|
d->delegate = nil;
|
|
161
|
+
d->ucc = nil;
|
|
162
|
+
|
|
86
163
|
delete d; d = nullptr;
|
|
87
164
|
}
|
|
88
165
|
|
{fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/.github/workflows/wheels-macos.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fit_webview_bridge-0.2.0a2 → fit_webview_bridge-0.2.0a4}/bindings/pyside6/macos/CMakeLists.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|