fit-webview-bridge 0.2.1a3__tar.gz → 0.2.1a5__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fit-webview-bridge
3
- Version: 0.2.1a3
3
+ Version: 0.2.1a5
4
4
  Summary: Qt native WebView bridge with PySide6 bindings
5
5
  Author: FIT Project
6
6
  License: LGPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fit-webview-bridge"
3
- version = "0.2.1a3"
3
+ version = "0.2.1a5"
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"]
@@ -45,13 +45,14 @@ static NSURL* toNSURL(QUrl u);
45
45
  }
46
46
  @end
47
47
 
48
- // =======================
49
- // Navigation + Download delegate
50
- // =======================
48
+ // ===== WKNavDelegate =====
51
49
  @interface WKNavDelegate : NSObject <WKNavigationDelegate, WKDownloadDelegate>
52
50
  @property(nonatomic, assign) WKWebViewWidget* owner;
53
- // stato download (nel delegate, non toccare i privati del widget)
54
- @property(nonatomic, strong) NSMapTable<WKDownload*, NSString*>* downloadPaths;
51
+ // mappe per download
52
+ @property(nonatomic, strong) NSMapTable<WKDownload*, NSString*>* downloadPaths; // weak key -> strong value
53
+ @property(nonatomic, strong) NSMapTable<NSProgress*, WKDownload*>* progressToDownload; // weak->weak
54
+ @property(nonatomic, strong) NSHashTable<NSProgress*>* completedProgresses; // weak set
55
+ @property(nonatomic, strong) NSMapTable<WKDownload*, NSNumber*>* expectedTotals; // weak->strong
55
56
  @end
56
57
 
57
58
  @implementation WKNavDelegate
@@ -59,6 +60,9 @@ static NSURL* toNSURL(QUrl u);
59
60
  - (instancetype)init {
60
61
  if ((self = [super init])) {
61
62
  _downloadPaths = [NSMapTable weakToStrongObjectsMapTable];
63
+ _progressToDownload = [NSMapTable weakToWeakObjectsMapTable];
64
+ _completedProgresses = [NSHashTable weakObjectsHashTable];
65
+ _expectedTotals = [NSMapTable weakToStrongObjectsMapTable];
62
66
  }
63
67
  return self;
64
68
  }
@@ -118,8 +122,7 @@ decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
118
122
  if (navigationResponse.canShowMIMEType) {
119
123
  decisionHandler(WKNavigationResponsePolicyAllow);
120
124
  } else {
121
- // API moderna: "Download" (non BecomeDownload)
122
- decisionHandler(WKNavigationResponsePolicyDownload);
125
+ decisionHandler(WKNavigationResponsePolicyDownload); // API moderna
123
126
  }
124
127
  }
125
128
 
@@ -130,10 +133,9 @@ navigationAction:(WKNavigationAction *)navigationAction
130
133
  didBecomeDownload:(WKDownload *)download
131
134
  {
132
135
  download.delegate = self;
133
- if (self.owner) {
134
- emit self.owner->downloadStarted(QString(), QString());
135
- }
136
-
136
+ if (self.owner) emit self.owner->downloadStarted(QString(), QString());
137
+
138
+ // KVO su NSProgress (3 keyPath, con INITIAL)
137
139
  [download.progress addObserver:self forKeyPath:@"fractionCompleted"
138
140
  options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial)
139
141
  context:NULL];
@@ -143,6 +145,8 @@ didBecomeDownload:(WKDownload *)download
143
145
  [download.progress addObserver:self forKeyPath:@"totalUnitCount"
144
146
  options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial)
145
147
  context:NULL];
148
+
149
+ [self.progressToDownload setObject:download forKey:download.progress];
146
150
  }
147
151
 
148
152
  - (void)webView:(WKWebView *)webView
@@ -153,10 +157,9 @@ didBecomeDownload:(WKDownload *)download
153
157
 
154
158
  NSString* suggested = navigationResponse.response.suggestedFilename ?: @"download";
155
159
  if (self.owner) {
156
- QString destDir = self.owner->downloadDirectory();
157
- QString destPath = destDir + "/" + QString::fromUtf8(suggested.UTF8String);
158
- emit self.owner->downloadStarted(QString::fromUtf8(suggested.UTF8String),
159
- destPath);
160
+ QString dir = self.owner->downloadDirectory();
161
+ QString path = dir + "/" + QString::fromUtf8(suggested.UTF8String);
162
+ emit self.owner->downloadStarted(QString::fromUtf8(suggested.UTF8String), path);
160
163
  }
161
164
 
162
165
  [download.progress addObserver:self forKeyPath:@"fractionCompleted"
@@ -168,6 +171,8 @@ didBecomeDownload:(WKDownload *)download
168
171
  [download.progress addObserver:self forKeyPath:@"totalUnitCount"
169
172
  options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial)
170
173
  context:NULL];
174
+
175
+ [self.progressToDownload setObject:download forKey:download.progress];
171
176
  }
172
177
 
173
178
  #pragma mark - Scegli destinazione
@@ -199,9 +204,7 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
199
204
 
200
205
  QString qdir = self.owner->downloadDirectory();
201
206
  NSString* dir = [NSString stringWithUTF8String:qdir.toUtf8().constData()];
202
- if (!dir.length) {
203
- dir = [NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"];
204
- }
207
+ if (!dir.length) dir = [NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"];
205
208
 
206
209
  [[NSFileManager defaultManager] createDirectoryAtPath:dir
207
210
  withIntermediateDirectories:YES
@@ -215,6 +218,16 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
215
218
  QString::fromUtf8(finalPath.UTF8String)
216
219
  );
217
220
 
221
+ // Leggi il Content-Length se disponibile e salvalo
222
+ long long expected = response.expectedContentLength; // -1 se sconosciuto
223
+ if (expected >= 0) {
224
+ [self.expectedTotals setObject:@(expected) forKey:download];
225
+ if (self.owner) {
226
+ // progress iniziale (0 di total)
227
+ emit self.owner->downloadProgress(0, expected);
228
+ }
229
+ }
230
+
218
231
  completionHandler([NSURL fileURLWithPath:finalPath]);
219
232
  }
220
233
 
@@ -227,18 +240,32 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
227
240
  [super observeValueForKeyPath:keyPath ofObject:obj change:change context:ctx];
228
241
  return;
229
242
  }
230
-
231
243
  NSProgress* prog = (NSProgress*)obj;
232
- int64_t total = prog.totalUnitCount; // può essere -1 (sconosciuto)
244
+
245
+ // Calcolo grezzo fuori dal main
246
+ int64_t total = prog.totalUnitCount; // -1 se sconosciuto
233
247
  int64_t done = prog.completedUnitCount;
234
248
 
235
- // Emetti SEMPRE su main (thread-safety Qt/UI)
249
+ // Dispatch su main, ma **ricontrolla** lo stato "completed" dentro al blocco
250
+ // DOPO (compatibile MRC)
251
+ __unsafe_unretained WKNavDelegate* weakSelf = self;
236
252
  dispatch_async(dispatch_get_main_queue(), ^{
237
- emit self.owner->downloadProgress(done, (total >= 0 ? total : -1));
253
+ WKNavDelegate* strongSelf = weakSelf;
254
+ if (!strongSelf || !strongSelf.owner) return;
255
+
256
+ // blocca update tardivi dopo finished/failed
257
+ if ([strongSelf.completedProgresses containsObject:prog]) return;
258
+
259
+ WKDownload* dl = [strongSelf.progressToDownload objectForKey:prog];
260
+ NSNumber* exp = dl ? [strongSelf.expectedTotals objectForKey:dl] : nil;
261
+
262
+ int64_t totalEff = (total >= 0 ? total : (exp ? exp.longLongValue : -1));
263
+ emit strongSelf.owner->downloadProgress(done, totalEff);
238
264
  });
239
- }
240
265
 
241
266
 
267
+ }
268
+
242
269
  - (void)downloadDidFinish:(WKDownload *)download {
243
270
  if (!self.owner) return;
244
271
 
@@ -248,13 +275,14 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
248
275
  [download.progress removeObserver:self forKeyPath:@"totalUnitCount"];
249
276
  } @catch (...) {}
250
277
 
278
+ [self.completedProgresses addObject:download.progress];
279
+
280
+
251
281
  NSString* finalPath = [self.downloadPaths objectForKey:download];
252
- if (finalPath) {
253
- emit self.owner->downloadFinished(QString::fromUtf8(finalPath.UTF8String));
254
- [self.downloadPaths removeObjectForKey:download];
255
- } else {
256
- emit self.owner->downloadFinished(QString());
257
- }
282
+ emit self.owner->downloadFinished(finalPath ? QString::fromUtf8(finalPath.UTF8String) : QString());
283
+ if (finalPath) [self.downloadPaths removeObjectForKey:download];
284
+ [self.progressToDownload removeObjectForKey:download.progress];
285
+ [self.expectedTotals removeObjectForKey:download];
258
286
  }
259
287
 
260
288
  - (void)download:(WKDownload *)download didFailWithError:(NSError *)error resumeData:(NSData *)resumeData {
@@ -266,10 +294,16 @@ completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler
266
294
  [download.progress removeObserver:self forKeyPath:@"totalUnitCount"];
267
295
  } @catch (...) {}
268
296
 
269
- NSString* finalPath = [self.downloadPaths objectForKey:download];
270
- QString qpath = finalPath ? QString::fromUtf8(finalPath.UTF8String) : QString();
271
- emit self.owner->downloadFailed(qpath, QString::fromUtf8(error.localizedDescription.UTF8String));
297
+ [self.completedProgresses addObject:download.progress];
298
+
299
+ NSString* finalPath = [self.downloadPaths objectForKey:download];
300
+ emit self.owner->downloadFailed(
301
+ finalPath ? QString::fromUtf8(finalPath.UTF8String) : QString(),
302
+ QString::fromUtf8(error.localizedDescription.UTF8String)
303
+ );
272
304
  if (finalPath) [self.downloadPaths removeObjectForKey:download];
305
+ [self.progressToDownload removeObjectForKey:download.progress];
306
+ [self.expectedTotals removeObjectForKey:download];
273
307
  }
274
308
 
275
309
  @end