@leeguoo/pwtk-network-debugger 1.3.6 → 1.3.8

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.
@@ -10,17 +10,37 @@ class Container {
10
10
  static pendingForceRefresh = false;
11
11
  static settingsKey = "pwtk_glass_settings_v1";
12
12
  static defaultSettings = {
13
- enableWebGL: true,
13
+ enableWebGL: false,
14
14
  autoRefresh: true,
15
15
  enableButtonAnimation: true
16
16
  };
17
17
  static settings = { ...Container.defaultSettings };
18
+ static maxSnapshotPixels = 3e6;
19
+ static minSnapshotScale = 0.5;
20
+ static pageSnapshotScale = 1;
21
+ static documentWriteWarnDepth = 0;
22
+ static originalConsoleWarn = null;
18
23
  static handleWindowRefresh = () => Container.scheduleSnapshotRefresh();
19
24
  static handleVisibilityRefresh = () => {
20
25
  if (typeof document !== "undefined" && !document.hidden) {
21
26
  Container.scheduleSnapshotRefresh();
22
27
  }
23
28
  };
29
+ static getDevicePixelRatio() {
30
+ if (typeof window === "undefined") return 1;
31
+ const dpr = window.devicePixelRatio || 1;
32
+ return Math.max(1, Math.min(dpr, 2));
33
+ }
34
+ static computeSnapshotScale(pageWidth, pageHeight) {
35
+ const baseScale = Container.getDevicePixelRatio();
36
+ const area = pageWidth * pageHeight;
37
+ if (!Number.isFinite(area) || area <= 0) {
38
+ return baseScale;
39
+ }
40
+ const maxScale = Math.sqrt(Container.maxSnapshotPixels / area);
41
+ const scale = Math.min(baseScale, maxScale);
42
+ return Math.max(Container.minSnapshotScale, Math.min(scale, baseScale));
43
+ }
24
44
  static loadSettings() {
25
45
  if (typeof window === "undefined" || typeof window.localStorage === "undefined") {
26
46
  return { ...Container.defaultSettings };
@@ -116,6 +136,32 @@ class Container {
116
136
  });
117
137
  }
118
138
  }
139
+ static suppressDocumentWriteWarnings() {
140
+ if (typeof console === "undefined" || typeof console.warn !== "function") {
141
+ return;
142
+ }
143
+ if (Container.documentWriteWarnDepth === 0) {
144
+ Container.originalConsoleWarn = console.warn;
145
+ console.warn = (...args) => {
146
+ if (args.length > 0 && typeof args[0] === "string" && args[0].includes("Avoid using document.write")) {
147
+ return;
148
+ }
149
+ if (Container.originalConsoleWarn) {
150
+ Container.originalConsoleWarn.apply(console, args);
151
+ }
152
+ };
153
+ }
154
+ Container.documentWriteWarnDepth++;
155
+ }
156
+ static restoreDocumentWriteWarnings() {
157
+ if (Container.documentWriteWarnDepth > 0) {
158
+ Container.documentWriteWarnDepth--;
159
+ if (Container.documentWriteWarnDepth === 0 && Container.originalConsoleWarn) {
160
+ console.warn = Container.originalConsoleWarn;
161
+ Container.originalConsoleWarn = null;
162
+ }
163
+ }
164
+ }
119
165
  static shouldUseWebGL() {
120
166
  return Container.settings.enableWebGL !== false;
121
167
  }
@@ -125,9 +171,11 @@ class Container {
125
171
  constructor(options = {}) {
126
172
  this.width = 0;
127
173
  this.height = 0;
174
+ this.dpr = Container.getDevicePixelRatio();
128
175
  this.borderRadius = options.borderRadius || 48;
129
176
  this.type = options.type || "rounded";
130
- this.tintOpacity = options.tintOpacity !== void 0 ? options.tintOpacity : 0.2;
177
+ this.tintOpacity = options.tintOpacity !== void 0 ? options.tintOpacity : 0.06;
178
+ this.glassOpacity = options.glassOpacity !== void 0 ? options.glassOpacity : 0.08;
131
179
  this.canvas = null;
132
180
  this.element = null;
133
181
  this.gl = null;
@@ -135,6 +183,7 @@ class Container {
135
183
  this.webglInitialized = false;
136
184
  this.children = [];
137
185
  this.animationFrameId = null;
186
+ this.destroyed = false;
138
187
  Container.instances.push(this);
139
188
  Container.ensureGlobalObservers();
140
189
  this.init();
@@ -164,6 +213,7 @@ class Container {
164
213
  }
165
214
  updateSizeFromDOM() {
166
215
  requestAnimationFrame(() => {
216
+ if (!this.element || !this.canvas) return;
167
217
  const rect = this.element.getBoundingClientRect();
168
218
  let newWidth = Math.ceil(rect.width);
169
219
  let newHeight = Math.ceil(rect.height);
@@ -179,16 +229,20 @@ class Container {
179
229
  this.borderRadius = newHeight / 2;
180
230
  this.element.style.borderRadius = this.borderRadius + "px";
181
231
  }
182
- if (newWidth !== this.width || newHeight !== this.height) {
232
+ const nextDpr = Container.getDevicePixelRatio();
233
+ const pixelWidth = Math.max(1, Math.round(newWidth * nextDpr));
234
+ const pixelHeight = Math.max(1, Math.round(newHeight * nextDpr));
235
+ if (newWidth !== this.width || newHeight !== this.height || nextDpr !== this.dpr) {
183
236
  this.width = newWidth;
184
237
  this.height = newHeight;
185
- this.canvas.width = newWidth;
186
- this.canvas.height = newHeight;
238
+ this.dpr = nextDpr;
239
+ this.canvas.width = pixelWidth;
240
+ this.canvas.height = pixelHeight;
187
241
  this.canvas.style.width = newWidth + "px";
188
242
  this.canvas.style.height = newHeight + "px";
189
243
  this.canvas.style.borderRadius = this.borderRadius + "px";
190
244
  if (this.gl_refs.gl) {
191
- this.gl_refs.gl.viewport(0, 0, newWidth, newHeight);
245
+ this.gl_refs.gl.viewport(0, 0, pixelWidth, pixelHeight);
192
246
  this.gl_refs.gl.uniform2f(this.gl_refs.resolutionLoc, newWidth, newHeight);
193
247
  this.gl_refs.gl.uniform1f(this.gl_refs.borderRadiusLoc, this.borderRadius);
194
248
  }
@@ -196,8 +250,8 @@ class Container {
196
250
  if (child instanceof Button && child.isNestedGlass && child.gl_refs.gl) {
197
251
  const gl = child.gl_refs.gl;
198
252
  gl.bindTexture(gl.TEXTURE_2D, child.gl_refs.texture);
199
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, newWidth, newHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
200
- gl.uniform2f(child.gl_refs.textureSizeLoc, newWidth, newHeight);
253
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.canvas.width, this.canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
254
+ gl.uniform2f(child.gl_refs.textureSizeLoc, this.canvas.width, this.canvas.height);
201
255
  if (child.gl_refs.containerSizeLoc) {
202
256
  gl.uniform2f(child.gl_refs.containerSizeLoc, newWidth, newHeight);
203
257
  }
@@ -248,6 +302,7 @@ class Container {
248
302
  this.gl = this.canvas.getContext("webgl", { preserveDrawingBuffer: true });
249
303
  if (!this.gl) {
250
304
  console.error("WebGL not supported");
305
+ this.applyFallbackStyles();
251
306
  return;
252
307
  }
253
308
  }
@@ -303,15 +358,30 @@ class Container {
303
358
  if (!html2canvas) {
304
359
  console.error("[PWTK] html2canvas not available, containers will not initialize");
305
360
  Container.isCapturing = false;
361
+ const pending = Container.waitingForSnapshot.slice();
306
362
  Container.waitingForSnapshot = [];
363
+ pending.forEach((container) => {
364
+ if (container && typeof container.applyFallbackStyles === "function") {
365
+ container.applyFallbackStyles();
366
+ }
367
+ });
307
368
  return;
308
369
  }
309
370
  const targets = Container.drainWaitingQueue();
371
+ const doc = document.documentElement;
372
+ const body = document.body;
373
+ const pageWidth = Math.max(doc?.scrollWidth || 0, body?.scrollWidth || 0, window.innerWidth || 0);
374
+ const pageHeight = Math.max(doc?.scrollHeight || 0, body?.scrollHeight || 0, window.innerHeight || 0);
375
+ const scale = Container.computeSnapshotScale(pageWidth, pageHeight);
376
+ Container.pageSnapshotScale = scale;
377
+ Container.suppressDocumentWriteWarnings();
310
378
  html2canvas(document.body, {
311
- scale: 1,
379
+ scale,
312
380
  useCORS: true,
313
- allowTaint: true,
381
+ allowTaint: false,
314
382
  backgroundColor: null,
383
+ windowWidth: pageWidth,
384
+ windowHeight: pageHeight,
315
385
  logging: false,
316
386
  ignoreElements: function(element) {
317
387
  return element.classList.contains("glass-container") || element.classList.contains("glass-button") || element.classList.contains("glass-button-text");
@@ -326,7 +396,13 @@ class Container {
326
396
  }).catch((error) => {
327
397
  console.error("[PWTK] html2canvas error:", error);
328
398
  Container.isCapturing = false;
399
+ const pending = Container.toUniqueList([...targets, ...Container.waitingForSnapshot]);
329
400
  Container.waitingForSnapshot = [];
401
+ pending.forEach((container) => {
402
+ if (container && typeof container.applyFallbackStyles === "function") {
403
+ container.applyFallbackStyles();
404
+ }
405
+ });
330
406
  }).finally(() => {
331
407
  Container.isCapturing = false;
332
408
  if (Container.pendingForceRefresh || Container.waitingForSnapshot.length > 0) {
@@ -334,6 +410,7 @@ class Container {
334
410
  Container.pendingForceRefresh = false;
335
411
  Container.refreshAll(shouldForce);
336
412
  }
413
+ Container.restoreDocumentWriteWarnings();
337
414
  });
338
415
  }
339
416
  initWebGL() {
@@ -345,6 +422,11 @@ class Container {
345
422
  if (!this.webglInitialized) {
346
423
  this.setupShader(snapshotCanvas);
347
424
  this.webglInitialized = true;
425
+ this.children.forEach((child) => {
426
+ if (child instanceof Button && child.isNestedGlass && !child.webglInitialized) {
427
+ child.initNestedGlass();
428
+ }
429
+ });
348
430
  return;
349
431
  }
350
432
  const gl = this.gl_refs.gl;
@@ -534,6 +616,7 @@ class Container {
534
616
  uniform vec2 u_resolution;
535
617
  uniform vec2 u_textureSize;
536
618
  uniform float u_scrollY;
619
+ uniform float u_pageWidth;
537
620
  uniform float u_pageHeight;
538
621
  uniform float u_viewportHeight;
539
622
  uniform float u_blurRadius;
@@ -549,6 +632,7 @@ class Container {
549
632
  uniform float u_cornerBoost;
550
633
  uniform float u_rippleEffect;
551
634
  uniform float u_tintOpacity;
635
+ uniform float u_glassOpacity;
552
636
  varying vec2 v_texcoord;
553
637
 
554
638
  // Function to calculate distance from rounded rectangle edge
@@ -626,8 +710,13 @@ class Container {
626
710
  vec2 containerOffset = (coord - 0.5) * containerSize;
627
711
  vec2 pagePixel = containerCenter + containerOffset;
628
712
 
713
+ float scaleX = u_textureSize.x / max(u_pageWidth, 1.0);
714
+ float scaleY = u_textureSize.y / max(u_pageHeight, 1.0);
715
+ vec2 scaledPagePixel = vec2(pagePixel.x * scaleX, pagePixel.y * scaleY);
716
+
629
717
  // Convert to texture coordinate (0 to 1)
630
- vec2 textureCoord = pagePixel / textureSize;
718
+ vec2 textureCoord = scaledPagePixel / textureSize;
719
+ textureCoord = clamp(textureCoord, vec2(0.0), vec2(1.0));
631
720
 
632
721
  // Glass refraction effects
633
722
  float distFromEdgeShape;
@@ -786,7 +875,8 @@ class Container {
786
875
  }
787
876
  float mask = 1.0 - smoothstep(-1.0, 1.0, maskDistance);
788
877
 
789
- gl_FragColor = vec4(color.rgb, mask);
878
+ float opacity = clamp(u_glassOpacity, 0.02, 0.95);
879
+ gl_FragColor = vec4(color.rgb, mask * opacity);
790
880
  }
791
881
  `;
792
882
  const program = this.createProgram(gl, vsSource, fsSource);
@@ -803,6 +893,7 @@ class Container {
803
893
  const resolutionLoc = gl.getUniformLocation(program, "u_resolution");
804
894
  const textureSizeLoc = gl.getUniformLocation(program, "u_textureSize");
805
895
  const scrollYLoc = gl.getUniformLocation(program, "u_scrollY");
896
+ const pageWidthLoc = gl.getUniformLocation(program, "u_pageWidth");
806
897
  const pageHeightLoc = gl.getUniformLocation(program, "u_pageHeight");
807
898
  const viewportHeightLoc = gl.getUniformLocation(program, "u_viewportHeight");
808
899
  const blurRadiusLoc = gl.getUniformLocation(program, "u_blurRadius");
@@ -818,6 +909,7 @@ class Container {
818
909
  const cornerBoostLoc = gl.getUniformLocation(program, "u_cornerBoost");
819
910
  const rippleEffectLoc = gl.getUniformLocation(program, "u_rippleEffect");
820
911
  const tintOpacityLoc = gl.getUniformLocation(program, "u_tintOpacity");
912
+ const glassOpacityLoc = gl.getUniformLocation(program, "u_glassOpacity");
821
913
  const imageLoc = gl.getUniformLocation(program, "u_image");
822
914
  const texture = gl.createTexture();
823
915
  gl.bindTexture(gl.TEXTURE_2D, texture);
@@ -828,9 +920,11 @@ class Container {
828
920
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
829
921
  this.gl_refs = {
830
922
  gl,
923
+ program,
831
924
  texture,
832
925
  textureSizeLoc,
833
926
  scrollYLoc,
927
+ pageWidthLoc,
834
928
  positionLoc,
835
929
  texcoordLoc,
836
930
  resolutionLoc,
@@ -849,6 +943,7 @@ class Container {
849
943
  cornerBoostLoc,
850
944
  rippleEffectLoc,
851
945
  tintOpacityLoc,
946
+ glassOpacityLoc,
852
947
  imageLoc,
853
948
  positionBuffer,
854
949
  texcoordBuffer
@@ -861,7 +956,9 @@ class Container {
861
956
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
862
957
  gl.enableVertexAttribArray(texcoordLoc);
863
958
  gl.vertexAttribPointer(texcoordLoc, 2, gl.FLOAT, false, 0, 0);
864
- gl.uniform2f(resolutionLoc, this.canvas.width, this.canvas.height);
959
+ const cssWidth = this.width || Math.max(1, Math.round(this.canvas.width / this.dpr));
960
+ const cssHeight = this.height || Math.max(1, Math.round(this.canvas.height / this.dpr));
961
+ gl.uniform2f(resolutionLoc, cssWidth, cssHeight);
865
962
  gl.uniform2f(textureSizeLoc, image.width, image.height);
866
963
  gl.uniform1f(blurRadiusLoc, window.glassControls?.blurRadius || 5);
867
964
  gl.uniform1f(borderRadiusLoc, this.borderRadius);
@@ -875,10 +972,13 @@ class Container {
875
972
  gl.uniform1f(cornerBoostLoc, window.glassControls?.cornerBoost || 0.02);
876
973
  gl.uniform1f(rippleEffectLoc, window.glassControls?.rippleEffect || 0.1);
877
974
  gl.uniform1f(tintOpacityLoc, this.tintOpacity);
975
+ gl.uniform1f(glassOpacityLoc, window.glassControls?.glassOpacity ?? this.glassOpacity);
878
976
  const position = this.getPosition();
879
977
  gl.uniform2f(containerPositionLoc, position.x, position.y);
978
+ const pageWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
880
979
  const pageHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
881
980
  const viewportHeight = window.innerHeight;
981
+ gl.uniform1f(pageWidthLoc, pageWidth);
882
982
  gl.uniform1f(pageHeightLoc, pageHeight);
883
983
  gl.uniform1f(viewportHeightLoc, viewportHeight);
884
984
  gl.activeTexture(gl.TEXTURE0);
@@ -892,16 +992,25 @@ class Container {
892
992
  this.animationFrameId = null;
893
993
  }
894
994
  const render = () => {
895
- if (!this.gl_refs.gl) {
995
+ if (this.destroyed || !this.gl_refs.gl) {
896
996
  this.animationFrameId = null;
897
997
  return;
898
998
  }
999
+ if (!this.element || !this.element.isConnected) {
1000
+ this.destroy();
1001
+ return;
1002
+ }
899
1003
  const gl = this.gl_refs.gl;
900
1004
  gl.clear(gl.COLOR_BUFFER_BIT);
901
1005
  const scrollY = window.pageYOffset || document.documentElement.scrollTop;
902
1006
  gl.uniform1f(this.gl_refs.scrollYLoc, scrollY);
903
1007
  const position = this.getPosition();
904
1008
  gl.uniform2f(this.gl_refs.containerPositionLoc, position.x, position.y);
1009
+ const pageWidth = Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);
1010
+ const pageHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
1011
+ gl.uniform1f(this.gl_refs.pageWidthLoc, pageWidth);
1012
+ gl.uniform1f(this.gl_refs.pageHeightLoc, pageHeight);
1013
+ gl.uniform1f(this.gl_refs.viewportHeightLoc, window.innerHeight);
905
1014
  gl.drawArrays(gl.TRIANGLES, 0, 6);
906
1015
  this.animationFrameId = window.requestAnimationFrame(render);
907
1016
  };
@@ -932,6 +1041,58 @@ class Container {
932
1041
  }
933
1042
  return shader;
934
1043
  }
1044
+ destroy() {
1045
+ if (this.destroyed) return;
1046
+ this.destroyed = true;
1047
+ if (this.animationFrameId !== null) {
1048
+ window.cancelAnimationFrame(this.animationFrameId);
1049
+ this.animationFrameId = null;
1050
+ }
1051
+ this.children.forEach((child) => {
1052
+ if (typeof child.stopNestedAnimation === "function") {
1053
+ child.stopNestedAnimation();
1054
+ }
1055
+ });
1056
+ if (this.gl_refs.gl) {
1057
+ const gl = this.gl_refs.gl;
1058
+ if (this.gl_refs.texture) gl.deleteTexture(this.gl_refs.texture);
1059
+ if (this.gl_refs.positionBuffer) gl.deleteBuffer(this.gl_refs.positionBuffer);
1060
+ if (this.gl_refs.texcoordBuffer) gl.deleteBuffer(this.gl_refs.texcoordBuffer);
1061
+ if (this.gl_refs.program) gl.deleteProgram(this.gl_refs.program);
1062
+ }
1063
+ this.gl_refs = {};
1064
+ this.webglInitialized = false;
1065
+ Container.waitingForSnapshot = Container.waitingForSnapshot.filter((item) => item !== this);
1066
+ Container.instances = Container.instances.filter((item) => item !== this);
1067
+ if (!Container.instances.length) {
1068
+ Container.teardownGlobalObservers();
1069
+ Container.pageSnapshot = null;
1070
+ Container.pageSnapshotScale = 1;
1071
+ Container.isCapturing = false;
1072
+ Container.pendingForceRefresh = false;
1073
+ }
1074
+ }
1075
+ static teardownGlobalObservers() {
1076
+ if (!Container.globalListenersSetup) return;
1077
+ if (typeof window === "undefined" || typeof document === "undefined") {
1078
+ Container.globalListenersSetup = false;
1079
+ return;
1080
+ }
1081
+ if (Container.refreshTimer) {
1082
+ window.clearTimeout(Container.refreshTimer);
1083
+ Container.refreshTimer = null;
1084
+ }
1085
+ if (Container.mutationObserver) {
1086
+ Container.mutationObserver.disconnect();
1087
+ Container.mutationObserver = null;
1088
+ }
1089
+ window.removeEventListener("resize", Container.handleWindowRefresh);
1090
+ window.removeEventListener("orientationchange", Container.handleWindowRefresh);
1091
+ window.removeEventListener("focus", Container.handleWindowRefresh);
1092
+ window.removeEventListener("pageshow", Container.handleWindowRefresh);
1093
+ document.removeEventListener("visibilitychange", Container.handleVisibilityRefresh);
1094
+ Container.globalListenersSetup = false;
1095
+ }
935
1096
  }
936
1097
  if (typeof window !== "undefined") {
937
1098
  Container.settings = Container.loadSettings();