@autono/pinbox-toolbar 0.12.0 → 0.13.0
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.js +1 -1
- package/dist/react.js +1 -1
- package/dist/{src-C-gslo8y.js → src-C3zvwQrr.js} +36 -9
- package/dist/svelte.js +1 -1
- package/dist/toolbar.iife.js +36 -9
- package/dist/vue.js +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-
|
|
1
|
+
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-C3zvwQrr.js";
|
|
2
2
|
export { HubError, HubTransport, Pinbox, PinboxToolbarElement, appendThreadMessage, applyHubEvent, createStore, defineToolbarElement, deriveUiStatus, upsertPin };
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as defineToolbarElement, r as PinboxToolbarElement } from "./src-
|
|
1
|
+
import { n as defineToolbarElement, r as PinboxToolbarElement } from "./src-C3zvwQrr.js";
|
|
2
2
|
import { createElement, useEffect, useRef } from "react";
|
|
3
3
|
//#region src/react.ts
|
|
4
4
|
/**
|
|
@@ -837,6 +837,39 @@ async function firstFrame(win, stream) {
|
|
|
837
837
|
});
|
|
838
838
|
return video;
|
|
839
839
|
}
|
|
840
|
+
/**
|
|
841
|
+
* The one live capture stream, reused across pins. getDisplayMedia MUST
|
|
842
|
+
* prompt on every call (spec — no persistent grant exists), so the only way
|
|
843
|
+
* to stop asking per pin is to never re-call it: prompt once, keep the track,
|
|
844
|
+
* and read a fresh frame from the still-playing video for every capture.
|
|
845
|
+
* The browser's "sharing this tab" indicator stays on while the track lives —
|
|
846
|
+
* honest, and the user ending it from there simply re-prompts on the next pin.
|
|
847
|
+
*/
|
|
848
|
+
let liveCapture = null;
|
|
849
|
+
async function captureVideo(win, media) {
|
|
850
|
+
const track = liveCapture?.stream.getVideoTracks()[0];
|
|
851
|
+
if (liveCapture && track?.readyState === "live") return liveCapture.video;
|
|
852
|
+
releaseCapture();
|
|
853
|
+
const stream = await media.getDisplayMedia({
|
|
854
|
+
video: true,
|
|
855
|
+
audio: false,
|
|
856
|
+
preferCurrentTab: true
|
|
857
|
+
});
|
|
858
|
+
const video = await firstFrame(win, stream);
|
|
859
|
+
stream.getVideoTracks()[0]?.addEventListener("ended", releaseCapture, { once: true });
|
|
860
|
+
liveCapture = {
|
|
861
|
+
stream,
|
|
862
|
+
video
|
|
863
|
+
};
|
|
864
|
+
return video;
|
|
865
|
+
}
|
|
866
|
+
/** Stop the cached stream (toolbar disconnect; also the track-ended handler). */
|
|
867
|
+
function releaseCapture() {
|
|
868
|
+
if (liveCapture === null) return;
|
|
869
|
+
for (const t of liveCapture.stream.getTracks()) t.stop();
|
|
870
|
+
liveCapture.video.srcObject = null;
|
|
871
|
+
liveCapture = null;
|
|
872
|
+
}
|
|
840
873
|
/** webp-encode a bitmap; also emit the ≤32px placeholder data URL. */
|
|
841
874
|
async function encode(bmp) {
|
|
842
875
|
const canvas = new OffscreenCanvas(bmp.width, bmp.height);
|
|
@@ -876,21 +909,14 @@ async function captureElement(el) {
|
|
|
876
909
|
const crop = visibleCropRect(el);
|
|
877
910
|
if (source === null || crop === null) return null;
|
|
878
911
|
const { win, media } = source;
|
|
879
|
-
let stream = null;
|
|
880
912
|
try {
|
|
881
|
-
|
|
882
|
-
video: true,
|
|
883
|
-
audio: false,
|
|
884
|
-
preferCurrentTab: true
|
|
885
|
-
});
|
|
886
|
-
const video = await firstFrame(win, stream);
|
|
913
|
+
const video = await captureVideo(win, media);
|
|
887
914
|
const sx = video.videoWidth / win.innerWidth;
|
|
888
915
|
const sy = video.videoHeight / win.innerHeight;
|
|
889
916
|
return await encode(await createImageBitmap(video, Math.round(crop.x * sx), Math.round(crop.y * sy), Math.max(1, Math.round(crop.width * sx)), Math.max(1, Math.round(crop.height * sy))));
|
|
890
917
|
} catch {
|
|
918
|
+
releaseCapture();
|
|
891
919
|
return null;
|
|
892
|
-
} finally {
|
|
893
|
-
if (stream) for (const track of stream.getTracks()) track.stop();
|
|
894
920
|
}
|
|
895
921
|
}
|
|
896
922
|
/**
|
|
@@ -2645,6 +2671,7 @@ var PinboxToolbarElement = class extends BaseElement {
|
|
|
2645
2671
|
this.#aim = null;
|
|
2646
2672
|
this.#min?.destroy();
|
|
2647
2673
|
this.#min = null;
|
|
2674
|
+
releaseCapture();
|
|
2648
2675
|
this.#unsubscribe?.();
|
|
2649
2676
|
this.#unsubscribe = null;
|
|
2650
2677
|
this.#pageStyle?.remove();
|
package/dist/svelte.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-
|
|
1
|
+
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-C3zvwQrr.js";
|
|
2
2
|
//#region src/svelte.ts
|
|
3
3
|
/**
|
|
4
4
|
* `<div use:pinbox={{ endpoint }} />` — creates + configures the element BEFORE insertion
|
package/dist/toolbar.iife.js
CHANGED
|
@@ -839,6 +839,39 @@ var Pinbox = (function(exports) {
|
|
|
839
839
|
});
|
|
840
840
|
return video;
|
|
841
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
* The one live capture stream, reused across pins. getDisplayMedia MUST
|
|
844
|
+
* prompt on every call (spec — no persistent grant exists), so the only way
|
|
845
|
+
* to stop asking per pin is to never re-call it: prompt once, keep the track,
|
|
846
|
+
* and read a fresh frame from the still-playing video for every capture.
|
|
847
|
+
* The browser's "sharing this tab" indicator stays on while the track lives —
|
|
848
|
+
* honest, and the user ending it from there simply re-prompts on the next pin.
|
|
849
|
+
*/
|
|
850
|
+
let liveCapture = null;
|
|
851
|
+
async function captureVideo(win, media) {
|
|
852
|
+
const track = liveCapture?.stream.getVideoTracks()[0];
|
|
853
|
+
if (liveCapture && track?.readyState === "live") return liveCapture.video;
|
|
854
|
+
releaseCapture();
|
|
855
|
+
const stream = await media.getDisplayMedia({
|
|
856
|
+
video: true,
|
|
857
|
+
audio: false,
|
|
858
|
+
preferCurrentTab: true
|
|
859
|
+
});
|
|
860
|
+
const video = await firstFrame(win, stream);
|
|
861
|
+
stream.getVideoTracks()[0]?.addEventListener("ended", releaseCapture, { once: true });
|
|
862
|
+
liveCapture = {
|
|
863
|
+
stream,
|
|
864
|
+
video
|
|
865
|
+
};
|
|
866
|
+
return video;
|
|
867
|
+
}
|
|
868
|
+
/** Stop the cached stream (toolbar disconnect; also the track-ended handler). */
|
|
869
|
+
function releaseCapture() {
|
|
870
|
+
if (liveCapture === null) return;
|
|
871
|
+
for (const t of liveCapture.stream.getTracks()) t.stop();
|
|
872
|
+
liveCapture.video.srcObject = null;
|
|
873
|
+
liveCapture = null;
|
|
874
|
+
}
|
|
842
875
|
/** webp-encode a bitmap; also emit the ≤32px placeholder data URL. */
|
|
843
876
|
async function encode(bmp) {
|
|
844
877
|
const canvas = new OffscreenCanvas(bmp.width, bmp.height);
|
|
@@ -878,21 +911,14 @@ var Pinbox = (function(exports) {
|
|
|
878
911
|
const crop = visibleCropRect(el);
|
|
879
912
|
if (source === null || crop === null) return null;
|
|
880
913
|
const { win, media } = source;
|
|
881
|
-
let stream = null;
|
|
882
914
|
try {
|
|
883
|
-
|
|
884
|
-
video: true,
|
|
885
|
-
audio: false,
|
|
886
|
-
preferCurrentTab: true
|
|
887
|
-
});
|
|
888
|
-
const video = await firstFrame(win, stream);
|
|
915
|
+
const video = await captureVideo(win, media);
|
|
889
916
|
const sx = video.videoWidth / win.innerWidth;
|
|
890
917
|
const sy = video.videoHeight / win.innerHeight;
|
|
891
918
|
return await encode(await createImageBitmap(video, Math.round(crop.x * sx), Math.round(crop.y * sy), Math.max(1, Math.round(crop.width * sx)), Math.max(1, Math.round(crop.height * sy))));
|
|
892
919
|
} catch {
|
|
920
|
+
releaseCapture();
|
|
893
921
|
return null;
|
|
894
|
-
} finally {
|
|
895
|
-
if (stream) for (const track of stream.getTracks()) track.stop();
|
|
896
922
|
}
|
|
897
923
|
}
|
|
898
924
|
/**
|
|
@@ -2647,6 +2673,7 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2647
2673
|
this.#aim = null;
|
|
2648
2674
|
this.#min?.destroy();
|
|
2649
2675
|
this.#min = null;
|
|
2676
|
+
releaseCapture();
|
|
2650
2677
|
this.#unsubscribe?.();
|
|
2651
2678
|
this.#unsubscribe = null;
|
|
2652
2679
|
this.#pageStyle?.remove();
|
package/dist/vue.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autono/pinbox-toolbar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@autono/pinbox-core": "0.
|
|
74
|
+
"@autono/pinbox-core": "0.13.0",
|
|
75
75
|
"@types/react": "^19.2.0",
|
|
76
76
|
"typescript": "^7.0.0",
|
|
77
77
|
"tsdown": "^0.22.0",
|