pinokiod 3.92.0 → 3.93.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/package.json +1 -1
- package/server/public/common.js +104 -1
package/package.json
CHANGED
package/server/public/common.js
CHANGED
|
@@ -105,6 +105,11 @@ body.dark .capture-modal-button.secondary{background:rgba(148,163,184,0.2);color
|
|
|
105
105
|
this.overlayHidden = false;
|
|
106
106
|
this.floatingControls = null;
|
|
107
107
|
this.floatingStatus = null;
|
|
108
|
+
this.floatingDrag = null;
|
|
109
|
+
this.onFloatingPointerDown = this.startFloatingDrag.bind(this);
|
|
110
|
+
this.onFloatingPointerMove = this.handleFloatingPointerMove.bind(this);
|
|
111
|
+
this.onFloatingPointerUp = (event) => this.stopFloatingDrag(event);
|
|
112
|
+
this.onFloatingWindowResize = this.handleFloatingResize.bind(this);
|
|
108
113
|
this.resolveFn = null;
|
|
109
114
|
this.rejectFn = null;
|
|
110
115
|
this.colorDefault = '#ddd';
|
|
@@ -991,7 +996,7 @@ body.dark .capture-modal-button.secondary{background:rgba(148,163,184,0.2);color
|
|
|
991
996
|
color:#fff; padding:10px 14px; border-radius:12px;
|
|
992
997
|
box-shadow:0 8px 24px rgba(0,0,0,0.35);
|
|
993
998
|
font-size:14px; font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
|
|
994
|
-
pointer-events:auto;
|
|
999
|
+
pointer-events:auto; cursor:grab; touch-action:none;
|
|
995
1000
|
`;
|
|
996
1001
|
|
|
997
1002
|
const status = document.createElement('div');
|
|
@@ -1012,11 +1017,25 @@ body.dark .capture-modal-button.secondary{background:rgba(148,163,184,0.2);color
|
|
|
1012
1017
|
|
|
1013
1018
|
controls.append(status, stopBtn);
|
|
1014
1019
|
document.body.appendChild(controls);
|
|
1020
|
+
const rect = controls.getBoundingClientRect();
|
|
1021
|
+
const initial = this.clampFloatingPosition(rect);
|
|
1022
|
+
controls.style.left = `${initial.left}px`;
|
|
1023
|
+
controls.style.top = `${initial.top}px`;
|
|
1024
|
+
controls.style.right = 'auto';
|
|
1025
|
+
controls.style.bottom = 'auto';
|
|
1015
1026
|
this.floatingControls = controls;
|
|
1016
1027
|
this.floatingStatus = status;
|
|
1028
|
+
|
|
1029
|
+
controls.addEventListener('pointerdown', this.onFloatingPointerDown);
|
|
1030
|
+
window.addEventListener('resize', this.onFloatingWindowResize, { passive: true });
|
|
1017
1031
|
}
|
|
1018
1032
|
|
|
1019
1033
|
removeFloatingControls() {
|
|
1034
|
+
this.stopFloatingDrag();
|
|
1035
|
+
if (this.floatingControls) {
|
|
1036
|
+
this.floatingControls.removeEventListener('pointerdown', this.onFloatingPointerDown);
|
|
1037
|
+
}
|
|
1038
|
+
window.removeEventListener('resize', this.onFloatingWindowResize);
|
|
1020
1039
|
if (this.floatingControls && this.floatingControls.parentNode) {
|
|
1021
1040
|
this.floatingControls.parentNode.removeChild(this.floatingControls);
|
|
1022
1041
|
}
|
|
@@ -1024,6 +1043,90 @@ body.dark .capture-modal-button.secondary{background:rgba(148,163,184,0.2);color
|
|
|
1024
1043
|
this.floatingStatus = null;
|
|
1025
1044
|
}
|
|
1026
1045
|
|
|
1046
|
+
clampFloatingPosition(rect) {
|
|
1047
|
+
const margin = 8;
|
|
1048
|
+
const maxLeft = Math.max(margin, window.innerWidth - rect.width - margin);
|
|
1049
|
+
const maxTop = Math.max(margin, window.innerHeight - rect.height - margin);
|
|
1050
|
+
const left = Math.min(Math.max(rect.left, margin), maxLeft);
|
|
1051
|
+
const top = Math.min(Math.max(rect.top, margin), maxTop);
|
|
1052
|
+
return { left, top };
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
startFloatingDrag(event) {
|
|
1056
|
+
if (!this.floatingControls || event.button !== 0) return;
|
|
1057
|
+
if (event.target && event.target.closest('button')) return;
|
|
1058
|
+
const rect = this.floatingControls.getBoundingClientRect();
|
|
1059
|
+
const { left, top } = this.clampFloatingPosition(rect);
|
|
1060
|
+
this.floatingControls.style.left = `${left}px`;
|
|
1061
|
+
this.floatingControls.style.top = `${top}px`;
|
|
1062
|
+
this.floatingControls.style.right = 'auto';
|
|
1063
|
+
this.floatingControls.style.bottom = 'auto';
|
|
1064
|
+
|
|
1065
|
+
this.floatingDrag = {
|
|
1066
|
+
pointerId: event.pointerId,
|
|
1067
|
+
startX: event.clientX,
|
|
1068
|
+
startY: event.clientY,
|
|
1069
|
+
baseLeft: left,
|
|
1070
|
+
baseTop: top
|
|
1071
|
+
};
|
|
1072
|
+
|
|
1073
|
+
if (this.floatingControls.setPointerCapture) {
|
|
1074
|
+
try {
|
|
1075
|
+
this.floatingControls.setPointerCapture(event.pointerId);
|
|
1076
|
+
} catch (_) {
|
|
1077
|
+
// Ignore inability to capture pointer (e.g., already captured).
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
this.floatingControls.style.cursor = 'grabbing';
|
|
1081
|
+
window.addEventListener('pointermove', this.onFloatingPointerMove);
|
|
1082
|
+
window.addEventListener('pointerup', this.onFloatingPointerUp);
|
|
1083
|
+
window.addEventListener('pointercancel', this.onFloatingPointerUp);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
handleFloatingPointerMove(event) {
|
|
1087
|
+
if (!this.floatingDrag || event.pointerId !== this.floatingDrag.pointerId || !this.floatingControls) return;
|
|
1088
|
+
const dx = event.clientX - this.floatingDrag.startX;
|
|
1089
|
+
const dy = event.clientY - this.floatingDrag.startY;
|
|
1090
|
+
const proposed = {
|
|
1091
|
+
left: this.floatingDrag.baseLeft + dx,
|
|
1092
|
+
top: this.floatingDrag.baseTop + dy,
|
|
1093
|
+
width: this.floatingControls.offsetWidth,
|
|
1094
|
+
height: this.floatingControls.offsetHeight
|
|
1095
|
+
};
|
|
1096
|
+
const clamped = this.clampFloatingPosition(proposed);
|
|
1097
|
+
this.floatingControls.style.left = `${clamped.left}px`;
|
|
1098
|
+
this.floatingControls.style.top = `${clamped.top}px`;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
stopFloatingDrag(event) {
|
|
1102
|
+
if (!this.floatingDrag) return;
|
|
1103
|
+
if (event && this.floatingDrag.pointerId !== event.pointerId) return;
|
|
1104
|
+
window.removeEventListener('pointermove', this.onFloatingPointerMove);
|
|
1105
|
+
window.removeEventListener('pointerup', this.onFloatingPointerUp);
|
|
1106
|
+
window.removeEventListener('pointercancel', this.onFloatingPointerUp);
|
|
1107
|
+
if (this.floatingControls && this.floatingControls.releasePointerCapture && this.floatingDrag.pointerId != null) {
|
|
1108
|
+
try {
|
|
1109
|
+
this.floatingControls.releasePointerCapture(this.floatingDrag.pointerId);
|
|
1110
|
+
} catch (_) {
|
|
1111
|
+
// Ignore release errors (e.g., pointer already released).
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
if (this.floatingControls) {
|
|
1115
|
+
this.floatingControls.style.cursor = 'grab';
|
|
1116
|
+
}
|
|
1117
|
+
this.floatingDrag = null;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
handleFloatingResize() {
|
|
1121
|
+
if (!this.floatingControls) return;
|
|
1122
|
+
const rect = this.floatingControls.getBoundingClientRect();
|
|
1123
|
+
const clamped = this.clampFloatingPosition(rect);
|
|
1124
|
+
this.floatingControls.style.left = `${clamped.left}px`;
|
|
1125
|
+
this.floatingControls.style.top = `${clamped.top}px`;
|
|
1126
|
+
this.floatingControls.style.right = 'auto';
|
|
1127
|
+
this.floatingControls.style.bottom = 'auto';
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1027
1130
|
formatDuration(ms) {
|
|
1028
1131
|
const totalSeconds = Math.floor(ms / 1000);
|
|
1029
1132
|
const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0');
|