@pocketping/widget 2.4.0 → 2.5.1
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/dist/index.cjs +143 -1
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +143 -1
- package/dist/pocketping.min.global.js +16 -16
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2991,7 +2991,7 @@ function AttachmentDisplay({ attachment }) {
|
|
|
2991
2991
|
}
|
|
2992
2992
|
|
|
2993
2993
|
// src/version.ts
|
|
2994
|
-
var VERSION = "
|
|
2994
|
+
var VERSION = "2.6.0";
|
|
2995
2995
|
|
|
2996
2996
|
// src/client.ts
|
|
2997
2997
|
function detectBotSignals() {
|
|
@@ -4024,6 +4024,14 @@ var PocketPingClient = class {
|
|
|
4024
4024
|
console.error("[PocketPing] Failed to parse SSE message:", err);
|
|
4025
4025
|
}
|
|
4026
4026
|
});
|
|
4027
|
+
this.sse.addEventListener("screenshot_request", (event) => {
|
|
4028
|
+
try {
|
|
4029
|
+
const data = JSON.parse(event.data);
|
|
4030
|
+
this.handleRealtimeEvent(data);
|
|
4031
|
+
} catch (err) {
|
|
4032
|
+
console.error("[PocketPing] Failed to parse SSE screenshot_request:", err);
|
|
4033
|
+
}
|
|
4034
|
+
});
|
|
4027
4035
|
this.sse.addEventListener("connected", () => {
|
|
4028
4036
|
});
|
|
4029
4037
|
this.sse.onerror = () => {
|
|
@@ -4206,6 +4214,10 @@ var PocketPingClient = class {
|
|
|
4206
4214
|
this.emit("configUpdate", configData);
|
|
4207
4215
|
}
|
|
4208
4216
|
break;
|
|
4217
|
+
case "screenshot_request":
|
|
4218
|
+
const screenshotData = event.data;
|
|
4219
|
+
this.handleScreenshotRequest(screenshotData);
|
|
4220
|
+
break;
|
|
4209
4221
|
}
|
|
4210
4222
|
}
|
|
4211
4223
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -4252,6 +4264,7 @@ var PocketPingClient = class {
|
|
|
4252
4264
|
try {
|
|
4253
4265
|
const lastEventTimestamp = this.getLastEventTimestamp();
|
|
4254
4266
|
const newMessages = await this.fetchMessages(lastEventTimestamp ?? void 0);
|
|
4267
|
+
await this.pollScreenshotRequests();
|
|
4255
4268
|
this.pollingFailures = 0;
|
|
4256
4269
|
for (const message of newMessages) {
|
|
4257
4270
|
const existingIndex = this.session.messages.findIndex((m) => m.id === message.id);
|
|
@@ -4502,6 +4515,135 @@ var PocketPingClient = class {
|
|
|
4502
4515
|
generateId() {
|
|
4503
4516
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
4504
4517
|
}
|
|
4518
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4519
|
+
// Screenshot Request Polling (for polling fallback mode)
|
|
4520
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4521
|
+
async pollScreenshotRequests() {
|
|
4522
|
+
if (!this.session) return;
|
|
4523
|
+
try {
|
|
4524
|
+
const response = await this.fetch(`/screenshot/requests?sessionId=${this.session.sessionId}`, { method: "GET" });
|
|
4525
|
+
for (const request of response.requests || []) {
|
|
4526
|
+
this.handleScreenshotRequest(request);
|
|
4527
|
+
}
|
|
4528
|
+
} catch (err) {
|
|
4529
|
+
}
|
|
4530
|
+
}
|
|
4531
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4532
|
+
// Screenshot Capture
|
|
4533
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4534
|
+
/**
|
|
4535
|
+
* Handle screenshot request from operator
|
|
4536
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
4537
|
+
*/
|
|
4538
|
+
async handleScreenshotRequest(data) {
|
|
4539
|
+
console.log("[PocketPing] Screenshot requested by", data.requestedBy, "via", data.requestedFrom, data.silent ? "(silent)" : "");
|
|
4540
|
+
try {
|
|
4541
|
+
const blob = await this.captureScreenshot();
|
|
4542
|
+
const initResponse = await this.fetch("/screenshot/upload", {
|
|
4543
|
+
method: "POST",
|
|
4544
|
+
body: JSON.stringify({
|
|
4545
|
+
sessionId: this.session?.sessionId,
|
|
4546
|
+
requestId: data.requestId
|
|
4547
|
+
})
|
|
4548
|
+
});
|
|
4549
|
+
const uploadResponse = await fetch(initResponse.uploadUrl, {
|
|
4550
|
+
method: "PUT",
|
|
4551
|
+
body: blob,
|
|
4552
|
+
headers: {
|
|
4553
|
+
"Content-Type": "image/png"
|
|
4554
|
+
}
|
|
4555
|
+
});
|
|
4556
|
+
if (!uploadResponse.ok) {
|
|
4557
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
4558
|
+
}
|
|
4559
|
+
await this.fetch("/screenshot/upload/complete", {
|
|
4560
|
+
method: "POST",
|
|
4561
|
+
body: JSON.stringify({
|
|
4562
|
+
sessionId: this.session?.sessionId,
|
|
4563
|
+
requestId: data.requestId,
|
|
4564
|
+
attachmentId: initResponse.attachmentId,
|
|
4565
|
+
size: blob.size
|
|
4566
|
+
})
|
|
4567
|
+
});
|
|
4568
|
+
console.log("[PocketPing] Screenshot captured and uploaded successfully");
|
|
4569
|
+
} catch (error) {
|
|
4570
|
+
console.error("[PocketPing] Screenshot capture failed:", error);
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
/**
|
|
4574
|
+
* Capture screenshot of the viewport using html2canvas
|
|
4575
|
+
*/
|
|
4576
|
+
async captureScreenshot() {
|
|
4577
|
+
const html2canvas = await this.loadHtml2Canvas();
|
|
4578
|
+
const widgetContainer = document.getElementById("pocketping-widget");
|
|
4579
|
+
const widgetToggle = document.getElementById("pocketping-toggle");
|
|
4580
|
+
let widgetWasVisible = false;
|
|
4581
|
+
let toggleWasVisible = false;
|
|
4582
|
+
if (widgetContainer) {
|
|
4583
|
+
widgetWasVisible = widgetContainer.style.display !== "none";
|
|
4584
|
+
widgetContainer.style.display = "none";
|
|
4585
|
+
}
|
|
4586
|
+
if (widgetToggle) {
|
|
4587
|
+
toggleWasVisible = widgetToggle.style.display !== "none";
|
|
4588
|
+
widgetToggle.style.display = "none";
|
|
4589
|
+
}
|
|
4590
|
+
try {
|
|
4591
|
+
const canvas = await html2canvas(document.documentElement, {
|
|
4592
|
+
width: window.innerWidth,
|
|
4593
|
+
height: window.innerHeight,
|
|
4594
|
+
x: window.scrollX,
|
|
4595
|
+
y: window.scrollY,
|
|
4596
|
+
windowWidth: window.innerWidth,
|
|
4597
|
+
windowHeight: window.innerHeight,
|
|
4598
|
+
logging: false,
|
|
4599
|
+
useCORS: true,
|
|
4600
|
+
allowTaint: true
|
|
4601
|
+
});
|
|
4602
|
+
return new Promise((resolve, reject) => {
|
|
4603
|
+
canvas.toBlob(
|
|
4604
|
+
(blob) => {
|
|
4605
|
+
if (blob) {
|
|
4606
|
+
resolve(blob);
|
|
4607
|
+
} else {
|
|
4608
|
+
reject(new Error("Failed to create blob from canvas"));
|
|
4609
|
+
}
|
|
4610
|
+
},
|
|
4611
|
+
"image/png",
|
|
4612
|
+
0.9
|
|
4613
|
+
);
|
|
4614
|
+
});
|
|
4615
|
+
} finally {
|
|
4616
|
+
if (widgetContainer && widgetWasVisible) {
|
|
4617
|
+
widgetContainer.style.display = "";
|
|
4618
|
+
}
|
|
4619
|
+
if (widgetToggle && toggleWasVisible) {
|
|
4620
|
+
widgetToggle.style.display = "";
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
/**
|
|
4625
|
+
* Dynamically load html2canvas from CDN
|
|
4626
|
+
*/
|
|
4627
|
+
async loadHtml2Canvas() {
|
|
4628
|
+
const win = window;
|
|
4629
|
+
if (typeof win.html2canvas !== "undefined") {
|
|
4630
|
+
return win.html2canvas;
|
|
4631
|
+
}
|
|
4632
|
+
return new Promise((resolve, reject) => {
|
|
4633
|
+
const script = document.createElement("script");
|
|
4634
|
+
script.src = "https://cdn.jsdelivr.net/npm/html2canvas-pro@1.6.6/dist/html2canvas-pro.min.js";
|
|
4635
|
+
script.onload = () => {
|
|
4636
|
+
const w = window;
|
|
4637
|
+
if (typeof w.html2canvas !== "undefined") {
|
|
4638
|
+
resolve(w.html2canvas);
|
|
4639
|
+
} else {
|
|
4640
|
+
reject(new Error("html2canvas-pro failed to load"));
|
|
4641
|
+
}
|
|
4642
|
+
};
|
|
4643
|
+
script.onerror = () => reject(new Error("Failed to load html2canvas-pro from CDN"));
|
|
4644
|
+
document.head.appendChild(script);
|
|
4645
|
+
});
|
|
4646
|
+
}
|
|
4505
4647
|
};
|
|
4506
4648
|
|
|
4507
4649
|
// src/index.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -475,6 +475,20 @@ declare class PocketPingClient {
|
|
|
475
475
|
private storeIdentity;
|
|
476
476
|
private clearIdentity;
|
|
477
477
|
private generateId;
|
|
478
|
+
private pollScreenshotRequests;
|
|
479
|
+
/**
|
|
480
|
+
* Handle screenshot request from operator
|
|
481
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
482
|
+
*/
|
|
483
|
+
private handleScreenshotRequest;
|
|
484
|
+
/**
|
|
485
|
+
* Capture screenshot of the viewport using html2canvas
|
|
486
|
+
*/
|
|
487
|
+
private captureScreenshot;
|
|
488
|
+
/**
|
|
489
|
+
* Dynamically load html2canvas from CDN
|
|
490
|
+
*/
|
|
491
|
+
private loadHtml2Canvas;
|
|
478
492
|
}
|
|
479
493
|
|
|
480
494
|
declare function init(config: PocketPingConfig): PocketPingClient;
|
package/dist/index.d.ts
CHANGED
|
@@ -475,6 +475,20 @@ declare class PocketPingClient {
|
|
|
475
475
|
private storeIdentity;
|
|
476
476
|
private clearIdentity;
|
|
477
477
|
private generateId;
|
|
478
|
+
private pollScreenshotRequests;
|
|
479
|
+
/**
|
|
480
|
+
* Handle screenshot request from operator
|
|
481
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
482
|
+
*/
|
|
483
|
+
private handleScreenshotRequest;
|
|
484
|
+
/**
|
|
485
|
+
* Capture screenshot of the viewport using html2canvas
|
|
486
|
+
*/
|
|
487
|
+
private captureScreenshot;
|
|
488
|
+
/**
|
|
489
|
+
* Dynamically load html2canvas from CDN
|
|
490
|
+
*/
|
|
491
|
+
private loadHtml2Canvas;
|
|
478
492
|
}
|
|
479
493
|
|
|
480
494
|
declare function init(config: PocketPingConfig): PocketPingClient;
|
package/dist/index.js
CHANGED
|
@@ -2950,7 +2950,7 @@ function AttachmentDisplay({ attachment }) {
|
|
|
2950
2950
|
}
|
|
2951
2951
|
|
|
2952
2952
|
// src/version.ts
|
|
2953
|
-
var VERSION = "
|
|
2953
|
+
var VERSION = "2.6.0";
|
|
2954
2954
|
|
|
2955
2955
|
// src/client.ts
|
|
2956
2956
|
function detectBotSignals() {
|
|
@@ -3983,6 +3983,14 @@ var PocketPingClient = class {
|
|
|
3983
3983
|
console.error("[PocketPing] Failed to parse SSE message:", err);
|
|
3984
3984
|
}
|
|
3985
3985
|
});
|
|
3986
|
+
this.sse.addEventListener("screenshot_request", (event) => {
|
|
3987
|
+
try {
|
|
3988
|
+
const data = JSON.parse(event.data);
|
|
3989
|
+
this.handleRealtimeEvent(data);
|
|
3990
|
+
} catch (err) {
|
|
3991
|
+
console.error("[PocketPing] Failed to parse SSE screenshot_request:", err);
|
|
3992
|
+
}
|
|
3993
|
+
});
|
|
3986
3994
|
this.sse.addEventListener("connected", () => {
|
|
3987
3995
|
});
|
|
3988
3996
|
this.sse.onerror = () => {
|
|
@@ -4165,6 +4173,10 @@ var PocketPingClient = class {
|
|
|
4165
4173
|
this.emit("configUpdate", configData);
|
|
4166
4174
|
}
|
|
4167
4175
|
break;
|
|
4176
|
+
case "screenshot_request":
|
|
4177
|
+
const screenshotData = event.data;
|
|
4178
|
+
this.handleScreenshotRequest(screenshotData);
|
|
4179
|
+
break;
|
|
4168
4180
|
}
|
|
4169
4181
|
}
|
|
4170
4182
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -4211,6 +4223,7 @@ var PocketPingClient = class {
|
|
|
4211
4223
|
try {
|
|
4212
4224
|
const lastEventTimestamp = this.getLastEventTimestamp();
|
|
4213
4225
|
const newMessages = await this.fetchMessages(lastEventTimestamp ?? void 0);
|
|
4226
|
+
await this.pollScreenshotRequests();
|
|
4214
4227
|
this.pollingFailures = 0;
|
|
4215
4228
|
for (const message of newMessages) {
|
|
4216
4229
|
const existingIndex = this.session.messages.findIndex((m) => m.id === message.id);
|
|
@@ -4461,6 +4474,135 @@ var PocketPingClient = class {
|
|
|
4461
4474
|
generateId() {
|
|
4462
4475
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
4463
4476
|
}
|
|
4477
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4478
|
+
// Screenshot Request Polling (for polling fallback mode)
|
|
4479
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4480
|
+
async pollScreenshotRequests() {
|
|
4481
|
+
if (!this.session) return;
|
|
4482
|
+
try {
|
|
4483
|
+
const response = await this.fetch(`/screenshot/requests?sessionId=${this.session.sessionId}`, { method: "GET" });
|
|
4484
|
+
for (const request of response.requests || []) {
|
|
4485
|
+
this.handleScreenshotRequest(request);
|
|
4486
|
+
}
|
|
4487
|
+
} catch (err) {
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4491
|
+
// Screenshot Capture
|
|
4492
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4493
|
+
/**
|
|
4494
|
+
* Handle screenshot request from operator
|
|
4495
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
4496
|
+
*/
|
|
4497
|
+
async handleScreenshotRequest(data) {
|
|
4498
|
+
console.log("[PocketPing] Screenshot requested by", data.requestedBy, "via", data.requestedFrom, data.silent ? "(silent)" : "");
|
|
4499
|
+
try {
|
|
4500
|
+
const blob = await this.captureScreenshot();
|
|
4501
|
+
const initResponse = await this.fetch("/screenshot/upload", {
|
|
4502
|
+
method: "POST",
|
|
4503
|
+
body: JSON.stringify({
|
|
4504
|
+
sessionId: this.session?.sessionId,
|
|
4505
|
+
requestId: data.requestId
|
|
4506
|
+
})
|
|
4507
|
+
});
|
|
4508
|
+
const uploadResponse = await fetch(initResponse.uploadUrl, {
|
|
4509
|
+
method: "PUT",
|
|
4510
|
+
body: blob,
|
|
4511
|
+
headers: {
|
|
4512
|
+
"Content-Type": "image/png"
|
|
4513
|
+
}
|
|
4514
|
+
});
|
|
4515
|
+
if (!uploadResponse.ok) {
|
|
4516
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
4517
|
+
}
|
|
4518
|
+
await this.fetch("/screenshot/upload/complete", {
|
|
4519
|
+
method: "POST",
|
|
4520
|
+
body: JSON.stringify({
|
|
4521
|
+
sessionId: this.session?.sessionId,
|
|
4522
|
+
requestId: data.requestId,
|
|
4523
|
+
attachmentId: initResponse.attachmentId,
|
|
4524
|
+
size: blob.size
|
|
4525
|
+
})
|
|
4526
|
+
});
|
|
4527
|
+
console.log("[PocketPing] Screenshot captured and uploaded successfully");
|
|
4528
|
+
} catch (error) {
|
|
4529
|
+
console.error("[PocketPing] Screenshot capture failed:", error);
|
|
4530
|
+
}
|
|
4531
|
+
}
|
|
4532
|
+
/**
|
|
4533
|
+
* Capture screenshot of the viewport using html2canvas
|
|
4534
|
+
*/
|
|
4535
|
+
async captureScreenshot() {
|
|
4536
|
+
const html2canvas = await this.loadHtml2Canvas();
|
|
4537
|
+
const widgetContainer = document.getElementById("pocketping-widget");
|
|
4538
|
+
const widgetToggle = document.getElementById("pocketping-toggle");
|
|
4539
|
+
let widgetWasVisible = false;
|
|
4540
|
+
let toggleWasVisible = false;
|
|
4541
|
+
if (widgetContainer) {
|
|
4542
|
+
widgetWasVisible = widgetContainer.style.display !== "none";
|
|
4543
|
+
widgetContainer.style.display = "none";
|
|
4544
|
+
}
|
|
4545
|
+
if (widgetToggle) {
|
|
4546
|
+
toggleWasVisible = widgetToggle.style.display !== "none";
|
|
4547
|
+
widgetToggle.style.display = "none";
|
|
4548
|
+
}
|
|
4549
|
+
try {
|
|
4550
|
+
const canvas = await html2canvas(document.documentElement, {
|
|
4551
|
+
width: window.innerWidth,
|
|
4552
|
+
height: window.innerHeight,
|
|
4553
|
+
x: window.scrollX,
|
|
4554
|
+
y: window.scrollY,
|
|
4555
|
+
windowWidth: window.innerWidth,
|
|
4556
|
+
windowHeight: window.innerHeight,
|
|
4557
|
+
logging: false,
|
|
4558
|
+
useCORS: true,
|
|
4559
|
+
allowTaint: true
|
|
4560
|
+
});
|
|
4561
|
+
return new Promise((resolve, reject) => {
|
|
4562
|
+
canvas.toBlob(
|
|
4563
|
+
(blob) => {
|
|
4564
|
+
if (blob) {
|
|
4565
|
+
resolve(blob);
|
|
4566
|
+
} else {
|
|
4567
|
+
reject(new Error("Failed to create blob from canvas"));
|
|
4568
|
+
}
|
|
4569
|
+
},
|
|
4570
|
+
"image/png",
|
|
4571
|
+
0.9
|
|
4572
|
+
);
|
|
4573
|
+
});
|
|
4574
|
+
} finally {
|
|
4575
|
+
if (widgetContainer && widgetWasVisible) {
|
|
4576
|
+
widgetContainer.style.display = "";
|
|
4577
|
+
}
|
|
4578
|
+
if (widgetToggle && toggleWasVisible) {
|
|
4579
|
+
widgetToggle.style.display = "";
|
|
4580
|
+
}
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
/**
|
|
4584
|
+
* Dynamically load html2canvas from CDN
|
|
4585
|
+
*/
|
|
4586
|
+
async loadHtml2Canvas() {
|
|
4587
|
+
const win = window;
|
|
4588
|
+
if (typeof win.html2canvas !== "undefined") {
|
|
4589
|
+
return win.html2canvas;
|
|
4590
|
+
}
|
|
4591
|
+
return new Promise((resolve, reject) => {
|
|
4592
|
+
const script = document.createElement("script");
|
|
4593
|
+
script.src = "https://cdn.jsdelivr.net/npm/html2canvas-pro@1.6.6/dist/html2canvas-pro.min.js";
|
|
4594
|
+
script.onload = () => {
|
|
4595
|
+
const w = window;
|
|
4596
|
+
if (typeof w.html2canvas !== "undefined") {
|
|
4597
|
+
resolve(w.html2canvas);
|
|
4598
|
+
} else {
|
|
4599
|
+
reject(new Error("html2canvas-pro failed to load"));
|
|
4600
|
+
}
|
|
4601
|
+
};
|
|
4602
|
+
script.onerror = () => reject(new Error("Failed to load html2canvas-pro from CDN"));
|
|
4603
|
+
document.head.appendChild(script);
|
|
4604
|
+
});
|
|
4605
|
+
}
|
|
4464
4606
|
};
|
|
4465
4607
|
|
|
4466
4608
|
// src/index.ts
|