@sailfish-ai/recorder 1.7.17 → 1.7.19
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/modal.js +179 -175
- package/dist/sailfish-recorder.cjs.js +1 -1
- package/dist/sailfish-recorder.cjs.js.br +0 -0
- package/dist/sailfish-recorder.cjs.js.gz +0 -0
- package/dist/sailfish-recorder.es.js +1 -1
- package/dist/sailfish-recorder.es.js.br +0 -0
- package/dist/sailfish-recorder.es.js.gz +0 -0
- package/dist/sailfish-recorder.umd.js +1 -1
- package/dist/sailfish-recorder.umd.js.br +0 -0
- package/dist/sailfish-recorder.umd.js.gz +0 -0
- package/package.json +1 -1
package/dist/modal.js
CHANGED
|
@@ -25,12 +25,12 @@ export function setupIssueReporting(options) {
|
|
|
25
25
|
const isCmdOrCtrl = e.metaKey || e.ctrlKey;
|
|
26
26
|
// Shortcuts for modal open
|
|
27
27
|
if (!typingInInput && options.enableShortcuts && !isCmdOrCtrl) {
|
|
28
|
-
if (key === "
|
|
28
|
+
if (key === "e") {
|
|
29
29
|
e.preventDefault();
|
|
30
30
|
injectModalHTML("lookback");
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
if (key === "
|
|
33
|
+
if (key === "n") {
|
|
34
34
|
e.preventDefault();
|
|
35
35
|
injectModalHTML("startnow");
|
|
36
36
|
return;
|
|
@@ -59,10 +59,10 @@ export function setupIssueReporting(options) {
|
|
|
59
59
|
key === "r" &&
|
|
60
60
|
modalOpen &&
|
|
61
61
|
currentState.mode === "startnow") {
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
62
|
+
const recordBtn = document.getElementById("sf-start-recording-btn");
|
|
63
|
+
if (recordBtn) {
|
|
64
64
|
e.preventDefault();
|
|
65
|
-
|
|
65
|
+
recordBtn.click();
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
});
|
|
@@ -107,7 +107,7 @@ function injectModalHTML(initialMode = "lookback") {
|
|
|
107
107
|
<div style="position:fixed; inset:0; background:rgba(0,0,0,0.4); z-index:9998;"></div>
|
|
108
108
|
<div style="position:fixed; top:50%; left:50%; transform:translate(-50%, -50%);
|
|
109
109
|
background:#fff; padding:24px; border-radius:12px;
|
|
110
|
-
width:
|
|
110
|
+
width:476px; max-width:90%; z-index:9999;
|
|
111
111
|
box-shadow:0 4px 20px rgba(0,0,0,0.15); font-family:sans-serif;">
|
|
112
112
|
|
|
113
113
|
<button id="sf-modal-close-btn"
|
|
@@ -121,13 +121,13 @@ function injectModalHTML(initialMode = "lookback") {
|
|
|
121
121
|
<h2 style="font-size:18px; font-weight:600; margin-bottom:16px;">Report Issue</h2>
|
|
122
122
|
|
|
123
123
|
<div id="sf-issue-tabs" style="display:flex; gap:4px; margin-bottom:16px; background:#f1f5f9; padding:6px; border-radius:6px; width: fit-content;">
|
|
124
|
-
<button id="sf-tab-lookback" data-mode="lookback" class="issue-tab ${!isStartNow ? "active" : ""}"
|
|
125
|
-
style="padding:6px 12px; border:none; background:${!isStartNow ? "white" : "transparent"}; color: ${!isStartNow ? "#0F172A" : "#64748B"}; border-radius:4px; font-size:14px; cursor:pointer; font-weight:500; height:32px;">
|
|
126
|
-
|
|
124
|
+
<button id="sf-tab-lookback" data-mode="lookback" class="sf-issue-tab ${!isStartNow ? "active" : ""}"
|
|
125
|
+
style="padding:6px 12px; border:none; background:${!isStartNow ? "white" : "transparent"}; color: ${!isStartNow ? "#0F172A" : "#64748B"}; border-radius:4px; font-size:14px; cursor:pointer; font-weight:500; height:32px; display: flex; align-items: center; gap: 8px;">
|
|
126
|
+
Existing <span style="background: #F1F5F9; border:1px solid #cbd5e1; border-radius: 4px; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; color: #94A3B8; font-weight: 500;">e</span>
|
|
127
127
|
</button>
|
|
128
|
-
<button id="sf-tab-startnow" data-mode="startnow" class="issue-tab ${isStartNow ? "active" : ""}"
|
|
129
|
-
style="padding:6px 12px; border:none; background:${isStartNow ? "white" : "transparent"}; color: ${isStartNow ? "#0F172A" : "#64748B"}; border-radius:4px; font-size:14px; cursor:pointer; font-weight:500; height:32px;">
|
|
130
|
-
Capture new <span style="color
|
|
128
|
+
<button id="sf-tab-startnow" data-mode="startnow" class="sf-issue-tab ${isStartNow ? "active" : ""}"
|
|
129
|
+
style="padding:6px 12px; border:none; background:${isStartNow ? "white" : "transparent"}; color: ${isStartNow ? "#0F172A" : "#64748B"}; border-radius:4px; font-size:14px; cursor:pointer; font-weight:500; height:32px; display: flex; align-items: center; gap: 8px;">
|
|
130
|
+
Capture new <span style="background: #F1F5F9; border:1px solid #cbd5e1; border-radius: 4px; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; color: #94A3B8; font-weight: 500;">n</span>
|
|
131
131
|
</button>
|
|
132
132
|
</div>
|
|
133
133
|
|
|
@@ -138,11 +138,7 @@ function injectModalHTML(initialMode = "lookback") {
|
|
|
138
138
|
<path d="M7 9.33333V7" stroke="#A1A1AA" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
|
139
139
|
<path d="M7 4.66663H7.00583" stroke="#A1A1AA" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
|
140
140
|
</g>
|
|
141
|
-
<defs>
|
|
142
|
-
<clipPath id="clip0_2477_11797">
|
|
143
|
-
<rect width="14" height="14" fill="white"/>
|
|
144
|
-
</clipPath>
|
|
145
|
-
</defs>
|
|
141
|
+
<defs><clipPath id="clip0_2477_11797"><rect width="14" height="14" fill="white"/></clipPath></defs>
|
|
146
142
|
</svg>
|
|
147
143
|
<div style="font-size:14px;">
|
|
148
144
|
${isStartNow
|
|
@@ -159,67 +155,76 @@ function injectModalHTML(initialMode = "lookback") {
|
|
|
159
155
|
border:1px solid #cbd5e1; border-radius:6px; margin-bottom:20px;
|
|
160
156
|
resize:none; outline:none;"></textarea>
|
|
161
157
|
|
|
162
|
-
<div id="sf-lookback-
|
|
163
|
-
<label for="sf-lookback-
|
|
164
|
-
|
|
158
|
+
<div id="sf-lookback-container" style="display:${isStartNow ? "none" : "block"}; margin-bottom:20px;">
|
|
159
|
+
<label for="sf-lookback-minutes" style="display:block; font-size:14px; font-weight:500; margin-bottom:6px;">
|
|
160
|
+
When does this happened?
|
|
165
161
|
</label>
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
162
|
+
<div style="display:flex; align-items:center; gap:6px;">
|
|
163
|
+
<div style="position:relative;">
|
|
164
|
+
<select id="sf-lookback-minutes"
|
|
165
|
+
style="
|
|
166
|
+
background: white;
|
|
167
|
+
padding: 4px 8px;
|
|
168
|
+
font-size: 14px;
|
|
169
|
+
border: 1px solid #cbd5e1;
|
|
170
|
+
border-radius: 6px;
|
|
171
|
+
color: #64748B;
|
|
172
|
+
font-family: sans-serif;
|
|
173
|
+
outline: none;
|
|
174
|
+
box-shadow: none;
|
|
175
|
+
appearance: none;
|
|
176
|
+
-webkit-appearance: none;
|
|
177
|
+
-moz-appearance: none;
|
|
178
|
+
padding-right: 28px;
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
font-size: 14px;
|
|
181
|
+
line-height: 20px;
|
|
182
|
+
">
|
|
183
|
+
${Array.from({ length: 15 }, (_, i) => {
|
|
184
|
+
const value = i + 1;
|
|
185
|
+
const selected = value === 2 ? "selected" : "";
|
|
186
|
+
return `<option value="${value}" ${selected}>${value}</option>`;
|
|
187
|
+
}).join("")}
|
|
188
|
+
</select>
|
|
189
|
+
<div style="position:absolute; left:32px; top:50%; transform:translateY(-50%); pointer-events:none;">
|
|
190
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"
|
|
191
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
192
|
+
<path d="M4 6L8 10L12 6" stroke="#52525B" stroke-width="1.33333"
|
|
193
|
+
stroke-linecap="round" stroke-linejoin="round"/>
|
|
194
|
+
</svg>
|
|
194
195
|
</div>
|
|
195
196
|
</div>
|
|
197
|
+
<span style="font-size:14px; color: #64748B;">mins ago</span>
|
|
196
198
|
</div>
|
|
197
|
-
|
|
198
|
-
<div style="font-size:12px; color:#a1a1aa; margin-top:4px;">Enter time stamp here. Max 1 hour.</div>
|
|
199
199
|
</div>
|
|
200
200
|
|
|
201
|
-
<div id="sf-
|
|
202
|
-
<label for="sf-inline-record-chip" style="display:block; font-size:14px; font-weight:500; margin-bottom:6px;">
|
|
203
|
-
Start recording <span style="color:#94a3b8;">[r]</span>
|
|
204
|
-
</label>
|
|
201
|
+
<div id="sf-modal-footer" style="display:flex; justify-content:${isStartNow ? "space-between" : "flex-end"}; align-items:flex-end;">
|
|
205
202
|
|
|
206
|
-
<div id="sf-
|
|
207
|
-
<div id="sf-
|
|
208
|
-
<
|
|
209
|
-
</div>
|
|
210
|
-
<div>
|
|
211
|
-
<div id="sf-inline-record-timer" style="font-family: monospace; font-weight: 500; color: #d4d4d8;">00:00</div>
|
|
212
|
-
<div style="font-size: 12px; color: #a1a1aa; margin-top: 2px;">Max time stamp 1 hour.</div>
|
|
203
|
+
<div id="sf-record-button-container" style="display:${isStartNow ? "block" : "none"};">
|
|
204
|
+
<div id="sf-recording-timer-label" style="display:none; font-size:14px; margin-bottom:20px;">
|
|
205
|
+
Recording: <span id="sf-recording-timer-display">00:00</span>
|
|
213
206
|
</div>
|
|
207
|
+
<button id="sf-start-recording-btn"
|
|
208
|
+
style="display:flex; align-items:center; gap:8px; border:1px solid #fc5555;
|
|
209
|
+
background:transparent; padding:6px 12px; font-size:14px;
|
|
210
|
+
color: #fc5555; border-radius:6px; cursor:pointer; font-weight:500;">
|
|
211
|
+
<div id="sf-record-icon" style="padding: 6px; border-radius: 6px; border: 1px solid #fc5555; cursor: pointer;">
|
|
212
|
+
<div style="width: 14px; height: 14px; background: #fc5555; border-radius: 50%; border: 1px solid #991b1b;"></div>
|
|
213
|
+
</div>
|
|
214
|
+
<span>Start Recording</span>
|
|
215
|
+
<span style="background: #F1F5F9; border:1px solid #cbd5e1; border-radius: 4px; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; color: #94A3B8; font-weight: 500;">r</span>
|
|
216
|
+
</button>
|
|
214
217
|
</div>
|
|
215
|
-
</div>
|
|
216
218
|
|
|
217
|
-
<div style="display:flex; justify-content:flex-end; margin-top:16px;">
|
|
218
219
|
<button id="sf-issue-submit-btn"
|
|
219
220
|
style="background: #295DBF; color:white; border:none; padding:8px 16px;
|
|
220
|
-
border-radius:6px; font-size:14px; line-height: 24px; font-weight:500;
|
|
221
|
-
disabled>
|
|
222
|
-
Create Triage <span style="
|
|
221
|
+
border-radius:6px; font-size:14px; line-height: 24px; font-weight:500;
|
|
222
|
+
cursor:${isStartNow ? "not-allowed" : "pointer"}; opacity:${isStartNow ? "0.4" : "1"}; margin-bottom:1px" ${isStartNow ? "disabled" : ""}>
|
|
223
|
+
Create Triage <span style="margin-left: 8px; display: inline-flex; align-items: center; gap: 4px; color: #94A3B8; font-size: 14px; line-height:18px;">
|
|
224
|
+
<span style="background: #F1F5F9; border-radius: 4px; padding: 0 6px; font-weight: 500;">cmd</span>
|
|
225
|
+
+
|
|
226
|
+
<span style="background: #F1F5F9; border-radius: 4px; padding: 0 6px; font-weight: 500;">enter</span>
|
|
227
|
+
</span>
|
|
223
228
|
</button>
|
|
224
229
|
</div>
|
|
225
230
|
</div>
|
|
@@ -229,6 +234,7 @@ function injectModalHTML(initialMode = "lookback") {
|
|
|
229
234
|
bindListeners();
|
|
230
235
|
}
|
|
231
236
|
function setActiveTab(mode) {
|
|
237
|
+
currentState.mode = mode;
|
|
232
238
|
const tabLookback = modalEl?.querySelector("#sf-tab-lookback");
|
|
233
239
|
const tabStartnow = modalEl?.querySelector("#sf-tab-startnow");
|
|
234
240
|
if (mode === "lookback") {
|
|
@@ -245,121 +251,96 @@ function setActiveTab(mode) {
|
|
|
245
251
|
}
|
|
246
252
|
}
|
|
247
253
|
function updateModeSpecificUI(mode) {
|
|
248
|
-
const
|
|
249
|
-
const infoMessage = infoText?.querySelector("div");
|
|
254
|
+
const infoMessage = document.querySelector("#sf-issue-mode-info div");
|
|
250
255
|
const submitBtn = document.getElementById("sf-issue-submit-btn");
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
|
|
256
|
+
const recordContainer = document.getElementById("sf-record-button-container");
|
|
257
|
+
const recordLabel = document.getElementById("sf-recording-timer-label");
|
|
258
|
+
const recordTime = document.getElementById("sf-recording-timer-display");
|
|
259
|
+
const footer = document.getElementById("sf-modal-footer");
|
|
260
|
+
const lookbackContainer = document.getElementById("sf-lookback-container");
|
|
261
|
+
if (!infoMessage ||
|
|
262
|
+
!submitBtn ||
|
|
263
|
+
!recordContainer ||
|
|
264
|
+
!recordLabel ||
|
|
265
|
+
!recordTime ||
|
|
266
|
+
!footer ||
|
|
267
|
+
!lookbackContainer)
|
|
255
268
|
return;
|
|
256
269
|
if (mode === "startnow") {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
270
|
+
// Show record button, hide lookback
|
|
271
|
+
recordContainer.style.display = "block";
|
|
272
|
+
lookbackContainer.style.display = "none";
|
|
273
|
+
footer.style.justifyContent = "space-between";
|
|
261
274
|
infoMessage.textContent = "I want to reproduce the issue right now.";
|
|
262
|
-
// Disable submit if recording not done yet
|
|
263
275
|
const canSubmit = recordingStartTime !== null && recordingEndTime !== null;
|
|
264
276
|
submitBtn.disabled = !canSubmit;
|
|
265
277
|
submitBtn.style.opacity = canSubmit ? "1" : "0.4";
|
|
266
278
|
submitBtn.style.cursor = canSubmit ? "pointer" : "not-allowed";
|
|
267
|
-
|
|
268
|
-
if (recordingStartTime && recordingEndTime && timerText) {
|
|
279
|
+
if (recordingStartTime && recordingEndTime) {
|
|
269
280
|
const duration = Math.floor((recordingEndTime - recordingStartTime) / 1000);
|
|
270
281
|
const mins = String(Math.floor(duration / 60)).padStart(2, "0");
|
|
271
282
|
const secs = String(duration % 60).padStart(2, "0");
|
|
272
|
-
|
|
273
|
-
|
|
283
|
+
recordLabel.style.display = "block";
|
|
284
|
+
recordTime.textContent = `${mins}:${secs}`;
|
|
274
285
|
}
|
|
275
|
-
else
|
|
276
|
-
|
|
277
|
-
timerText.style.color = "#d4d4d8";
|
|
286
|
+
else {
|
|
287
|
+
recordLabel.style.display = "none";
|
|
278
288
|
}
|
|
279
289
|
}
|
|
280
|
-
else
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
290
|
+
else {
|
|
291
|
+
// Show lookback, hide recording
|
|
292
|
+
recordContainer.style.display = "none";
|
|
293
|
+
recordLabel.style.display = "none";
|
|
294
|
+
lookbackContainer.style.display = "block";
|
|
295
|
+
footer.style.justifyContent = "flex-end";
|
|
285
296
|
infoMessage.textContent =
|
|
286
297
|
"Something already happened. Capture the past few minutes.";
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const secs = Number(document.getElementById("sf-lookback-seconds")
|
|
291
|
-
?.value || "0");
|
|
292
|
-
const canSubmit = mins > 0 || secs > 0;
|
|
293
|
-
submitBtn.disabled = !canSubmit;
|
|
294
|
-
submitBtn.style.opacity = canSubmit ? "1" : "0.4";
|
|
295
|
-
submitBtn.style.cursor = canSubmit ? "pointer" : "not-allowed";
|
|
298
|
+
submitBtn.disabled = false;
|
|
299
|
+
submitBtn.style.opacity = "1";
|
|
300
|
+
submitBtn.style.cursor = "pointer";
|
|
296
301
|
}
|
|
297
302
|
}
|
|
298
303
|
function bindListeners() {
|
|
299
|
-
const
|
|
300
|
-
const
|
|
301
|
-
const display = document.getElementById("sf-lookback-time-display");
|
|
304
|
+
const tabButtons = modalEl?.querySelectorAll(".sf-issue-tab");
|
|
305
|
+
const recordBtn = document.getElementById("sf-start-recording-btn");
|
|
302
306
|
const closeBtn = document.getElementById("sf-modal-close-btn");
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
if (recordIcon) {
|
|
310
|
-
recordIcon.onclick = () => {
|
|
311
|
-
const descInput = document.getElementById("sf-issue-description");
|
|
312
|
-
currentState.description = descInput?.value ?? "";
|
|
313
|
-
startCountdownThenRecord();
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
timeInput?.addEventListener("click", () => {
|
|
317
|
-
if (!dropdown)
|
|
318
|
-
return;
|
|
319
|
-
if (dropdown.style.display === "none") {
|
|
320
|
-
dropdown.style.display = "block";
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
dropdown.style.display = "none";
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
window.addEventListener("click", (e) => {
|
|
327
|
-
if (!dropdown)
|
|
328
|
-
return;
|
|
329
|
-
if (!dropdown.contains(e.target) &&
|
|
330
|
-
!timeInput?.contains(e.target)) {
|
|
331
|
-
dropdown.style.display = "none";
|
|
332
|
-
}
|
|
333
|
-
});
|
|
334
|
-
const updateTimeDisplay = () => {
|
|
335
|
-
const mins = Number(document.getElementById("sf-lookback-minutes")
|
|
336
|
-
?.value || "0");
|
|
337
|
-
const secs = Number(document.getElementById("sf-lookback-seconds")
|
|
338
|
-
?.value || "0");
|
|
339
|
-
if (display) {
|
|
340
|
-
display.textContent = `${mins.toString().padStart(2, "0")}:${secs
|
|
341
|
-
.toString()
|
|
342
|
-
.padStart(2, "0")}`;
|
|
343
|
-
}
|
|
344
|
-
updateModeSpecificUI("lookback"); // re-check submit button status
|
|
345
|
-
};
|
|
346
|
-
// Handle dropdown value changes
|
|
347
|
-
document
|
|
348
|
-
.getElementById("sf-lookback-minutes")
|
|
349
|
-
?.addEventListener("change", updateTimeDisplay);
|
|
350
|
-
document
|
|
351
|
-
.getElementById("sf-lookback-seconds")
|
|
352
|
-
?.addEventListener("change", updateTimeDisplay);
|
|
353
|
-
modalEl?.querySelectorAll(".issue-tab").forEach((tabBtn) => {
|
|
307
|
+
const submitBtn = document.getElementById("sf-issue-submit-btn");
|
|
308
|
+
const minutesSelect = document.getElementById("sf-lookback-minutes");
|
|
309
|
+
// Tab switch
|
|
310
|
+
tabButtons?.forEach((tabBtn) => {
|
|
354
311
|
tabBtn.addEventListener("click", (e) => {
|
|
355
312
|
const mode = e.currentTarget.dataset
|
|
356
313
|
.mode;
|
|
357
|
-
currentState.mode = mode;
|
|
358
314
|
setActiveTab(mode);
|
|
359
|
-
// Optionally toggle relevant UI
|
|
360
315
|
updateModeSpecificUI(mode);
|
|
361
316
|
});
|
|
362
317
|
});
|
|
318
|
+
// Close modal
|
|
319
|
+
if (closeBtn) {
|
|
320
|
+
closeBtn.onclick = closeModal;
|
|
321
|
+
}
|
|
322
|
+
// Time select change
|
|
323
|
+
if (minutesSelect) {
|
|
324
|
+
minutesSelect.addEventListener("change", () => {
|
|
325
|
+
if (currentState.mode === "lookback") {
|
|
326
|
+
// Always valid now, so no need to validate input
|
|
327
|
+
submitBtn.disabled = false;
|
|
328
|
+
submitBtn.style.opacity = "1";
|
|
329
|
+
submitBtn.style.cursor = "pointer";
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
// Start recording
|
|
334
|
+
if (recordBtn) {
|
|
335
|
+
recordBtn.onclick = () => {
|
|
336
|
+
const descInput = document.getElementById("sf-issue-description");
|
|
337
|
+
if (descInput) {
|
|
338
|
+
currentState.description = descInput.value;
|
|
339
|
+
}
|
|
340
|
+
startCountdownThenRecord();
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
// Submit
|
|
363
344
|
modalEl?.addEventListener("click", (e) => {
|
|
364
345
|
const target = e.target;
|
|
365
346
|
if (target.closest("#sf-issue-submit-btn")) {
|
|
@@ -374,12 +355,8 @@ function bindListeners() {
|
|
|
374
355
|
endTimestamp = recordingEndTime ?? Date.now();
|
|
375
356
|
}
|
|
376
357
|
else {
|
|
377
|
-
|
|
378
|
-
const
|
|
379
|
-
?.value || "0");
|
|
380
|
-
const seconds = Number(document.getElementById("sf-lookback-seconds")
|
|
381
|
-
?.value || "0");
|
|
382
|
-
const delta = (minutes * 60 + seconds) * 1000;
|
|
358
|
+
const minutes = Number(minutesSelect?.value || "2");
|
|
359
|
+
const delta = minutes * 60 * 1000;
|
|
383
360
|
endTimestamp = Date.now();
|
|
384
361
|
startTimestamp = endTimestamp - delta;
|
|
385
362
|
}
|
|
@@ -431,28 +408,40 @@ function showFloatingTimer() {
|
|
|
431
408
|
timer.id = "sf-recording-indicator";
|
|
432
409
|
timer.style.cssText = `
|
|
433
410
|
position: fixed;
|
|
434
|
-
bottom:
|
|
435
|
-
right:
|
|
411
|
+
bottom: 20px;
|
|
412
|
+
right: 20px;
|
|
436
413
|
background: white;
|
|
437
|
-
border: 1px solid #cbd5e1;
|
|
438
414
|
border-radius: 8px;
|
|
439
|
-
box-shadow: 0
|
|
440
|
-
padding: 8px
|
|
415
|
+
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
|
416
|
+
padding: 8px 12px;
|
|
441
417
|
font-family: sans-serif;
|
|
442
418
|
font-size: 14px;
|
|
443
419
|
display: flex;
|
|
444
|
-
align-items:
|
|
445
|
-
gap:
|
|
420
|
+
align-items: start;
|
|
421
|
+
gap: 24px;
|
|
446
422
|
z-index: 10000;
|
|
447
|
-
|
|
423
|
+
cursor: pointer;
|
|
448
424
|
`;
|
|
449
425
|
timer.innerHTML = `
|
|
450
|
-
<div
|
|
451
|
-
<div style="width:
|
|
426
|
+
<div style="display:flex; align-items:center; gap:8px;">
|
|
427
|
+
<div style="width:32px; height:32px; background:#FC5555; border-radius:6px; border:1px solid #991b1b; display:flex; align-items:center; justify-content:center;">
|
|
428
|
+
<div style="width:10px; height:10px; background:white; border-radius:2px;"></div>
|
|
429
|
+
</div>
|
|
430
|
+
<div style="display:flex; flex-direction:column; font-size:14px; line-height:20px;">
|
|
431
|
+
<span id="sf-recording-timer" style="font-weight:600; color: #171717;">00:00</span>
|
|
432
|
+
<span style="font-size:12px; line-height:12px; color: #71717A;">Max time 15 mins</span>
|
|
433
|
+
</div>
|
|
434
|
+
</div>
|
|
435
|
+
<div style="display:flex; align-items:center; gap:4px; margin-left:auto; font-size:14px; color:#0F172A;">
|
|
436
|
+
<span style="color: #71717A;">stop</span>
|
|
437
|
+
<span style="display: inline-flex; align-items: center; gap: 4px; color: #94A3B8; font-size: 14px; line-height:18px;">
|
|
438
|
+
<span style="background: #F1F5F9; border-radius: 4px; border:1px solid #cbd5e1; padding: 0 6px; font-weight: 500;">cmd</span>
|
|
439
|
+
+
|
|
440
|
+
<span style="background: #F1F5F9; border-radius: 4px; border:1px solid #cbd5e1; padding: 0 6px; font-weight: 500;">esc</span>
|
|
441
|
+
</span>
|
|
452
442
|
</div>
|
|
453
|
-
<span id="sf-recording-timer">00:00</span>
|
|
454
|
-
<div style="font-size:10px; color:#94a3b8;">[cmd] + [esc]</div>
|
|
455
443
|
`;
|
|
444
|
+
timer.addEventListener("click", () => stopRecording());
|
|
456
445
|
document.body.appendChild(timer);
|
|
457
446
|
const timerEl = timer.querySelector("#sf-recording-timer");
|
|
458
447
|
if (!timerEl)
|
|
@@ -467,8 +456,6 @@ function showFloatingTimer() {
|
|
|
467
456
|
.padStart(2, "0");
|
|
468
457
|
timerEl.textContent = `${mins}:${secs}`;
|
|
469
458
|
}, 1000);
|
|
470
|
-
const stopBtn = timer.querySelector("#sf-stop-icon");
|
|
471
|
-
stopBtn?.addEventListener("click", () => stopRecording());
|
|
472
459
|
}
|
|
473
460
|
function stopRecording() {
|
|
474
461
|
recordingEndTime = Date.now();
|
|
@@ -480,6 +467,23 @@ function stopRecording() {
|
|
|
480
467
|
}
|
|
481
468
|
function reopenModalAfterStop() {
|
|
482
469
|
injectModalHTML("startnow");
|
|
470
|
+
const recordBtn = document.getElementById("sf-start-recording-btn");
|
|
471
|
+
if (recordBtn) {
|
|
472
|
+
const span = recordBtn.querySelector("span");
|
|
473
|
+
if (span)
|
|
474
|
+
span.textContent = "Re-record";
|
|
475
|
+
}
|
|
476
|
+
const timerLabel = document.getElementById("sf-recording-timer-label");
|
|
477
|
+
const timerDisplay = document.getElementById("sf-recording-timer-display");
|
|
478
|
+
if (timerLabel && timerDisplay && recordingStartTime && recordingEndTime) {
|
|
479
|
+
const durationSec = Math.floor((recordingEndTime - recordingStartTime) / 1000);
|
|
480
|
+
const mins = Math.floor(durationSec / 60)
|
|
481
|
+
.toString()
|
|
482
|
+
.padStart(2, "0");
|
|
483
|
+
const secs = (durationSec % 60).toString().padStart(2, "0");
|
|
484
|
+
timerDisplay.textContent = `${mins}:${secs}`;
|
|
485
|
+
timerLabel.style.display = "block";
|
|
486
|
+
}
|
|
483
487
|
const descBox = document.getElementById("sf-issue-description");
|
|
484
488
|
if (descBox)
|
|
485
489
|
descBox.value = currentState.description;
|
|
@@ -536,7 +540,7 @@ function showTriageStatusModal(isLoading, triageId) {
|
|
|
536
540
|
: "";
|
|
537
541
|
const spinner = isLoading
|
|
538
542
|
? `<div style="display:flex; justify-content:center; align-items:center; padding: 40px 0;">
|
|
539
|
-
<div
|
|
543
|
+
<div style="width:24px; height:24px; border:2px solid #295dbf; border-top:2px solid white; border-radius:50%; animation:spin 1s linear infinite;"></div>
|
|
540
544
|
</div>`
|
|
541
545
|
: "";
|
|
542
546
|
const copiedStatus = !isLoading
|