@loupekit/sdk 0.10.0 → 0.10.1-next.42
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.global.js +71 -6
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +71 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.global.js
CHANGED
|
@@ -2455,6 +2455,7 @@ var Loupe = (() => {
|
|
|
2455
2455
|
};
|
|
2456
2456
|
|
|
2457
2457
|
// src/app.ts
|
|
2458
|
+
var SDK_VERSION = true ? "0.10.1" : "dev";
|
|
2458
2459
|
var DOCK_MODES = ["left", "right", "bottom", "float"];
|
|
2459
2460
|
var RECORD_MAX_MS = 2e4;
|
|
2460
2461
|
var MAX_FILES = 10;
|
|
@@ -2468,11 +2469,23 @@ var Loupe = (() => {
|
|
|
2468
2469
|
}
|
|
2469
2470
|
function isTouchDevice() {
|
|
2470
2471
|
try {
|
|
2471
|
-
|
|
2472
|
+
if (window.matchMedia("(pointer: coarse)").matches) return true;
|
|
2473
|
+
if (window.matchMedia("(hover: none)").matches) return true;
|
|
2474
|
+
} catch {
|
|
2475
|
+
}
|
|
2476
|
+
if (typeof navigator !== "undefined" && (navigator.maxTouchPoints ?? 0) > 0) return true;
|
|
2477
|
+
return typeof window !== "undefined" && "ontouchstart" in window;
|
|
2478
|
+
}
|
|
2479
|
+
function coarsePointer() {
|
|
2480
|
+
try {
|
|
2481
|
+
return window.matchMedia("(pointer: coarse)").matches;
|
|
2472
2482
|
} catch {
|
|
2473
2483
|
return false;
|
|
2474
2484
|
}
|
|
2475
2485
|
}
|
|
2486
|
+
function canShareScreen() {
|
|
2487
|
+
return typeof navigator.mediaDevices?.getDisplayMedia === "function";
|
|
2488
|
+
}
|
|
2476
2489
|
function dataUrlToFile(dataUrl, name) {
|
|
2477
2490
|
const m = /^data:([^;,]+)(;base64)?,([\s\S]*)$/.exec(dataUrl);
|
|
2478
2491
|
if (!m) return null;
|
|
@@ -2852,10 +2865,18 @@ var Loupe = (() => {
|
|
|
2852
2865
|
regionBtn.title = "Drag a free-size box, screenshot it, and comment";
|
|
2853
2866
|
regionBtn.onclick = () => this.setMode(this.mode === "region" ? "off" : "region");
|
|
2854
2867
|
const recordBtn = this.toolBtn(RECORD_ICON, "Record", "record");
|
|
2855
|
-
recordBtn.title = "Drag a box, record a screen video of it, and comment";
|
|
2868
|
+
recordBtn.title = isTouchDevice() ? "Record your screen, then describe the issue" : "Drag a box, record a screen video of it, and comment";
|
|
2856
2869
|
recordBtn.onclick = () => this.setMode(this.mode === "record" ? "off" : "record");
|
|
2857
|
-
|
|
2858
|
-
|
|
2870
|
+
if (canShareScreen()) {
|
|
2871
|
+
tools.append(inspectBtn, freeBtn, regionBtn, recordBtn);
|
|
2872
|
+
} else if (isTouchDevice()) {
|
|
2873
|
+
const cameraBtn = this.toolBtn(CAMERA_ICON, "Camera", "camera");
|
|
2874
|
+
cameraBtn.title = "Record a video with the camera and comment";
|
|
2875
|
+
cameraBtn.onclick = () => this.pickCameraVideo();
|
|
2876
|
+
tools.append(inspectBtn, freeBtn, regionBtn, cameraBtn);
|
|
2877
|
+
} else {
|
|
2878
|
+
tools.append(inspectBtn, freeBtn, regionBtn);
|
|
2879
|
+
}
|
|
2859
2880
|
const listHead = el("div", "listhead");
|
|
2860
2881
|
listHead.append(document.createTextNode("Comments"));
|
|
2861
2882
|
this.countEl = el("span", "count", "0");
|
|
@@ -3030,6 +3051,37 @@ var Loupe = (() => {
|
|
|
3030
3051
|
file ? [file] : []
|
|
3031
3052
|
);
|
|
3032
3053
|
}
|
|
3054
|
+
/**
|
|
3055
|
+
* Touch devices with no screen recorder (every iOS browser) can still report a video:
|
|
3056
|
+
* record one with the camera. Opens the native recorder and hands the clip to the
|
|
3057
|
+
* composer exactly like the screen capture does.
|
|
3058
|
+
*/
|
|
3059
|
+
pickCameraVideo() {
|
|
3060
|
+
this.setMode("off");
|
|
3061
|
+
const input = document.createElement("input");
|
|
3062
|
+
input.type = "file";
|
|
3063
|
+
input.accept = "video/*";
|
|
3064
|
+
input.setAttribute("capture", "environment");
|
|
3065
|
+
input.style.display = "none";
|
|
3066
|
+
input.onchange = () => {
|
|
3067
|
+
const file = input.files?.[0];
|
|
3068
|
+
input.remove();
|
|
3069
|
+
if (!file) return;
|
|
3070
|
+
const docX = window.scrollX + window.innerWidth / 2;
|
|
3071
|
+
const docY = window.scrollY + window.innerHeight / 2;
|
|
3072
|
+
const docW = Math.max(1, document.documentElement.scrollWidth);
|
|
3073
|
+
const docH = Math.max(1, document.documentElement.scrollHeight);
|
|
3074
|
+
const offset = { x: clamp(docX / docW), y: clamp(docY / docH) };
|
|
3075
|
+
this.openComposer(
|
|
3076
|
+
{ kind: "free", offset, point: { x: docX, y: docY }, label: "Camera video \xB7 attached" },
|
|
3077
|
+
8,
|
|
3078
|
+
window.innerHeight / 2,
|
|
3079
|
+
[file]
|
|
3080
|
+
);
|
|
3081
|
+
};
|
|
3082
|
+
this.shadow.appendChild(input);
|
|
3083
|
+
input.click();
|
|
3084
|
+
}
|
|
3033
3085
|
/** Capture the selected viewport rect, then open the composer for a region comment. */
|
|
3034
3086
|
async finishRegion(vp) {
|
|
3035
3087
|
this.selbox.style.display = "none";
|
|
@@ -3124,6 +3176,10 @@ var Loupe = (() => {
|
|
|
3124
3176
|
document.addEventListener("click", this.onFreeClick, true);
|
|
3125
3177
|
} else if (mode === "region" && isTouchDevice()) {
|
|
3126
3178
|
void this.captureViewportForComposer();
|
|
3179
|
+
} else if (mode === "record" && isTouchDevice()) {
|
|
3180
|
+
const vp = { x: 0, y: 0, w: window.innerWidth, h: window.innerHeight };
|
|
3181
|
+
this.setMode("off");
|
|
3182
|
+
void this.finishRecording(vp);
|
|
3127
3183
|
} else if (mode === "region" || mode === "record") {
|
|
3128
3184
|
document.addEventListener("pointerdown", this.onRegionDown, true);
|
|
3129
3185
|
}
|
|
@@ -3279,8 +3335,16 @@ var Loupe = (() => {
|
|
|
3279
3335
|
screenshot,
|
|
3280
3336
|
recording,
|
|
3281
3337
|
attachments: await this.uploadAttachments(files),
|
|
3282
|
-
//
|
|
3283
|
-
|
|
3338
|
+
// The screen this was captured on, plus enough to tell a stale bundle from a real
|
|
3339
|
+
// bug when someone reports "it still doesn't work" (see Comment.viewport).
|
|
3340
|
+
viewport: {
|
|
3341
|
+
w: window.innerWidth,
|
|
3342
|
+
h: window.innerHeight,
|
|
3343
|
+
v: SDK_VERSION,
|
|
3344
|
+
touch: isTouchDevice(),
|
|
3345
|
+
coarse: coarsePointer(),
|
|
3346
|
+
gdm: canShareScreen()
|
|
3347
|
+
},
|
|
3284
3348
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3285
3349
|
};
|
|
3286
3350
|
await this.store.save(comment);
|
|
@@ -3665,6 +3729,7 @@ var Loupe = (() => {
|
|
|
3665
3729
|
var REGION_ICON = `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true"><rect x="1.5" y="2.5" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4" stroke-dasharray="2.4 1.8"/></svg>`;
|
|
3666
3730
|
var NOTE_ICON = `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true"><path d="M2 2.5h11v7.5H6l-3 2.5v-2.5H2z" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg>`;
|
|
3667
3731
|
var RECORD_ICON = `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true"><rect x="1.5" y="2.5" width="12" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4" stroke-dasharray="2.4 1.8"/><circle cx="7.5" cy="7.5" r="2.4" fill="currentColor"/></svg>`;
|
|
3732
|
+
var CAMERA_ICON = `<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true"><rect x="1.2" y="3.8" width="9.2" height="7.4" rx="1.6" stroke="currentColor" stroke-width="1.3"/><path d="M10.4 7.3l3.4-2v4.4l-3.4-2z" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg>`;
|
|
3668
3733
|
var I_GITHUB = `<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 .2a8 8 0 0 0-2.5 15.6c.4.07.55-.17.55-.38v-1.3c-2.2.48-2.67-1.07-2.67-1.07-.36-.92-.88-1.16-.88-1.16-.72-.5.05-.48.05-.48.8.056 1.22.82 1.22.82.71 1.22 1.87.87 2.33.66.07-.52.28-.87.5-1.07-1.76-.2-3.6-.88-3.6-3.9 0-.86.3-1.57.82-2.12-.08-.2-.36-1 .08-2.1 0 0 .67-.21 2.2.8a7.6 7.6 0 0 1 4 0c1.53-1.02 2.2-.8 2.2-.8.44 1.1.16 1.9.08 2.1.5.55.82 1.26.82 2.12 0 3.03-1.85 3.7-3.61 3.9.28.24.54.72.54 1.46v2.16c0 .21.14.46.55.38A8 8 0 0 0 8 .2z"/></svg>`;
|
|
3669
3734
|
var I_SLACK = `<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M3.4 10.1a1.6 1.6 0 1 1-1.6-1.6h1.6v1.6zm.8 0a1.6 1.6 0 0 1 3.2 0v4a1.6 1.6 0 1 1-3.2 0v-4zM5.8 3.4a1.6 1.6 0 1 1 1.6-1.6v1.6H5.8zm0 .8a1.6 1.6 0 0 1 0 3.2h-4a1.6 1.6 0 1 1 0-3.2h4zm6.7 1.6a1.6 1.6 0 1 1 1.6 1.6h-1.6V5.8zm-.8 0a1.6 1.6 0 0 1-3.2 0v-4a1.6 1.6 0 1 1 3.2 0v4zm-1.6 6.7a1.6 1.6 0 1 1-1.6 1.6v-1.6h1.6zm0-.8a1.6 1.6 0 0 1 0-3.2h4a1.6 1.6 0 1 1 0 3.2h-4z"/></svg>`;
|
|
3670
3735
|
var I_TELEGRAM = `<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0zm3.7 5.4-1.24 5.85c-.09.41-.34.51-.69.32l-1.9-1.4-.92.88c-.1.1-.19.19-.38.19l.14-1.93 3.5-3.17c.15-.13-.03-.2-.24-.07l-4.32 2.72-1.86-.58c-.4-.13-.41-.4.09-.6l7.26-2.8c.34-.12.63.08.52.6z"/></svg>`;
|