@sailfish-ai/recorder 1.7.17 → 1.7.18
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 +178 -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>
|
|
@@ -245,121 +250,96 @@ function setActiveTab(mode) {
|
|
|
245
250
|
}
|
|
246
251
|
}
|
|
247
252
|
function updateModeSpecificUI(mode) {
|
|
248
|
-
const
|
|
249
|
-
const infoMessage = infoText?.querySelector("div");
|
|
253
|
+
const infoMessage = document.querySelector("#sf-issue-mode-info div");
|
|
250
254
|
const submitBtn = document.getElementById("sf-issue-submit-btn");
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
+
const recordContainer = document.getElementById("sf-record-button-container");
|
|
256
|
+
const recordLabel = document.getElementById("sf-recording-timer-label");
|
|
257
|
+
const recordTime = document.getElementById("sf-recording-timer-display");
|
|
258
|
+
const footer = document.getElementById("sf-modal-footer");
|
|
259
|
+
const lookbackContainer = document.getElementById("sf-lookback-container");
|
|
260
|
+
if (!infoMessage ||
|
|
261
|
+
!submitBtn ||
|
|
262
|
+
!recordContainer ||
|
|
263
|
+
!recordLabel ||
|
|
264
|
+
!recordTime ||
|
|
265
|
+
!footer ||
|
|
266
|
+
!lookbackContainer)
|
|
255
267
|
return;
|
|
256
268
|
if (mode === "startnow") {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
269
|
+
// Show record button, hide lookback
|
|
270
|
+
recordContainer.style.display = "block";
|
|
271
|
+
lookbackContainer.style.display = "none";
|
|
272
|
+
footer.style.justifyContent = "space-between";
|
|
261
273
|
infoMessage.textContent = "I want to reproduce the issue right now.";
|
|
262
|
-
// Disable submit if recording not done yet
|
|
263
274
|
const canSubmit = recordingStartTime !== null && recordingEndTime !== null;
|
|
264
275
|
submitBtn.disabled = !canSubmit;
|
|
265
276
|
submitBtn.style.opacity = canSubmit ? "1" : "0.4";
|
|
266
277
|
submitBtn.style.cursor = canSubmit ? "pointer" : "not-allowed";
|
|
267
|
-
|
|
268
|
-
if (recordingStartTime && recordingEndTime && timerText) {
|
|
278
|
+
if (recordingStartTime && recordingEndTime) {
|
|
269
279
|
const duration = Math.floor((recordingEndTime - recordingStartTime) / 1000);
|
|
270
280
|
const mins = String(Math.floor(duration / 60)).padStart(2, "0");
|
|
271
281
|
const secs = String(duration % 60).padStart(2, "0");
|
|
272
|
-
|
|
273
|
-
|
|
282
|
+
recordLabel.style.display = "block";
|
|
283
|
+
recordTime.textContent = `${mins}:${secs}`;
|
|
274
284
|
}
|
|
275
|
-
else
|
|
276
|
-
|
|
277
|
-
timerText.style.color = "#d4d4d8";
|
|
285
|
+
else {
|
|
286
|
+
recordLabel.style.display = "none";
|
|
278
287
|
}
|
|
279
288
|
}
|
|
280
|
-
else
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
289
|
+
else {
|
|
290
|
+
// Show lookback, hide recording
|
|
291
|
+
recordContainer.style.display = "none";
|
|
292
|
+
recordLabel.style.display = "none";
|
|
293
|
+
lookbackContainer.style.display = "block";
|
|
294
|
+
footer.style.justifyContent = "flex-end";
|
|
285
295
|
infoMessage.textContent =
|
|
286
296
|
"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";
|
|
297
|
+
submitBtn.disabled = false;
|
|
298
|
+
submitBtn.style.opacity = "1";
|
|
299
|
+
submitBtn.style.cursor = "pointer";
|
|
296
300
|
}
|
|
297
301
|
}
|
|
298
302
|
function bindListeners() {
|
|
299
|
-
const
|
|
300
|
-
const
|
|
301
|
-
const display = document.getElementById("sf-lookback-time-display");
|
|
303
|
+
const tabButtons = modalEl?.querySelectorAll(".sf-issue-tab");
|
|
304
|
+
const recordBtn = document.getElementById("sf-start-recording-btn");
|
|
302
305
|
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) => {
|
|
306
|
+
const submitBtn = document.getElementById("sf-issue-submit-btn");
|
|
307
|
+
const minutesSelect = document.getElementById("sf-lookback-minutes");
|
|
308
|
+
// Tab switch
|
|
309
|
+
tabButtons?.forEach((tabBtn) => {
|
|
354
310
|
tabBtn.addEventListener("click", (e) => {
|
|
355
311
|
const mode = e.currentTarget.dataset
|
|
356
312
|
.mode;
|
|
357
|
-
currentState.mode = mode;
|
|
358
313
|
setActiveTab(mode);
|
|
359
|
-
// Optionally toggle relevant UI
|
|
360
314
|
updateModeSpecificUI(mode);
|
|
361
315
|
});
|
|
362
316
|
});
|
|
317
|
+
// Close modal
|
|
318
|
+
if (closeBtn) {
|
|
319
|
+
closeBtn.onclick = closeModal;
|
|
320
|
+
}
|
|
321
|
+
// Time select change
|
|
322
|
+
if (minutesSelect) {
|
|
323
|
+
minutesSelect.addEventListener("change", () => {
|
|
324
|
+
if (currentState.mode === "lookback") {
|
|
325
|
+
// Always valid now, so no need to validate input
|
|
326
|
+
submitBtn.disabled = false;
|
|
327
|
+
submitBtn.style.opacity = "1";
|
|
328
|
+
submitBtn.style.cursor = "pointer";
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
// Start recording
|
|
333
|
+
if (recordBtn) {
|
|
334
|
+
recordBtn.onclick = () => {
|
|
335
|
+
const descInput = document.getElementById("sf-issue-description");
|
|
336
|
+
if (descInput) {
|
|
337
|
+
currentState.description = descInput.value;
|
|
338
|
+
}
|
|
339
|
+
startCountdownThenRecord();
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
// Submit
|
|
363
343
|
modalEl?.addEventListener("click", (e) => {
|
|
364
344
|
const target = e.target;
|
|
365
345
|
if (target.closest("#sf-issue-submit-btn")) {
|
|
@@ -374,12 +354,8 @@ function bindListeners() {
|
|
|
374
354
|
endTimestamp = recordingEndTime ?? Date.now();
|
|
375
355
|
}
|
|
376
356
|
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;
|
|
357
|
+
const minutes = Number(minutesSelect?.value || "2");
|
|
358
|
+
const delta = minutes * 60 * 1000;
|
|
383
359
|
endTimestamp = Date.now();
|
|
384
360
|
startTimestamp = endTimestamp - delta;
|
|
385
361
|
}
|
|
@@ -431,28 +407,40 @@ function showFloatingTimer() {
|
|
|
431
407
|
timer.id = "sf-recording-indicator";
|
|
432
408
|
timer.style.cssText = `
|
|
433
409
|
position: fixed;
|
|
434
|
-
bottom:
|
|
435
|
-
right:
|
|
410
|
+
bottom: 20px;
|
|
411
|
+
right: 20px;
|
|
436
412
|
background: white;
|
|
437
|
-
border: 1px solid #cbd5e1;
|
|
438
413
|
border-radius: 8px;
|
|
439
|
-
box-shadow: 0
|
|
440
|
-
padding: 8px
|
|
414
|
+
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
|
415
|
+
padding: 8px 12px;
|
|
441
416
|
font-family: sans-serif;
|
|
442
417
|
font-size: 14px;
|
|
443
418
|
display: flex;
|
|
444
|
-
align-items:
|
|
445
|
-
gap:
|
|
419
|
+
align-items: start;
|
|
420
|
+
gap: 24px;
|
|
446
421
|
z-index: 10000;
|
|
447
|
-
|
|
422
|
+
cursor: pointer;
|
|
448
423
|
`;
|
|
449
424
|
timer.innerHTML = `
|
|
450
|
-
<div
|
|
451
|
-
<div style="width:
|
|
425
|
+
<div style="display:flex; align-items:center; gap:8px;">
|
|
426
|
+
<div style="width:32px; height:32px; background:#FC5555; border-radius:6px; border:1px solid #991b1b; display:flex; align-items:center; justify-content:center;">
|
|
427
|
+
<div style="width:10px; height:10px; background:white; border-radius:2px;"></div>
|
|
428
|
+
</div>
|
|
429
|
+
<div style="display:flex; flex-direction:column; font-size:14px; line-height:20px;">
|
|
430
|
+
<span id="sf-recording-timer" style="font-weight:600; color: #171717;">00:00</span>
|
|
431
|
+
<span style="font-size:12px; line-height:12px; color: #71717A;">Max time 15 mins</span>
|
|
432
|
+
</div>
|
|
433
|
+
</div>
|
|
434
|
+
<div style="display:flex; align-items:center; gap:4px; margin-left:auto; font-size:14px; color:#0F172A;">
|
|
435
|
+
<span style="color: #71717A;">stop</span>
|
|
436
|
+
<span style="display: inline-flex; align-items: center; gap: 4px; color: #94A3B8; font-size: 14px; line-height:18px;">
|
|
437
|
+
<span style="background: #F1F5F9; border-radius: 4px; border:1px solid #cbd5e1; padding: 0 6px; font-weight: 500;">cmd</span>
|
|
438
|
+
+
|
|
439
|
+
<span style="background: #F1F5F9; border-radius: 4px; border:1px solid #cbd5e1; padding: 0 6px; font-weight: 500;">esc</span>
|
|
440
|
+
</span>
|
|
452
441
|
</div>
|
|
453
|
-
<span id="sf-recording-timer">00:00</span>
|
|
454
|
-
<div style="font-size:10px; color:#94a3b8;">[cmd] + [esc]</div>
|
|
455
442
|
`;
|
|
443
|
+
timer.addEventListener("click", () => stopRecording());
|
|
456
444
|
document.body.appendChild(timer);
|
|
457
445
|
const timerEl = timer.querySelector("#sf-recording-timer");
|
|
458
446
|
if (!timerEl)
|
|
@@ -467,8 +455,6 @@ function showFloatingTimer() {
|
|
|
467
455
|
.padStart(2, "0");
|
|
468
456
|
timerEl.textContent = `${mins}:${secs}`;
|
|
469
457
|
}, 1000);
|
|
470
|
-
const stopBtn = timer.querySelector("#sf-stop-icon");
|
|
471
|
-
stopBtn?.addEventListener("click", () => stopRecording());
|
|
472
458
|
}
|
|
473
459
|
function stopRecording() {
|
|
474
460
|
recordingEndTime = Date.now();
|
|
@@ -480,6 +466,23 @@ function stopRecording() {
|
|
|
480
466
|
}
|
|
481
467
|
function reopenModalAfterStop() {
|
|
482
468
|
injectModalHTML("startnow");
|
|
469
|
+
const recordBtn = document.getElementById("sf-start-recording-btn");
|
|
470
|
+
if (recordBtn) {
|
|
471
|
+
const span = recordBtn.querySelector("span");
|
|
472
|
+
if (span)
|
|
473
|
+
span.textContent = "Re-record";
|
|
474
|
+
}
|
|
475
|
+
const timerLabel = document.getElementById("sf-recording-timer-label");
|
|
476
|
+
const timerDisplay = document.getElementById("sf-recording-timer-display");
|
|
477
|
+
if (timerLabel && timerDisplay && recordingStartTime && recordingEndTime) {
|
|
478
|
+
const durationSec = Math.floor((recordingEndTime - recordingStartTime) / 1000);
|
|
479
|
+
const mins = Math.floor(durationSec / 60)
|
|
480
|
+
.toString()
|
|
481
|
+
.padStart(2, "0");
|
|
482
|
+
const secs = (durationSec % 60).toString().padStart(2, "0");
|
|
483
|
+
timerDisplay.textContent = `${mins}:${secs}`;
|
|
484
|
+
timerLabel.style.display = "block";
|
|
485
|
+
}
|
|
483
486
|
const descBox = document.getElementById("sf-issue-description");
|
|
484
487
|
if (descBox)
|
|
485
488
|
descBox.value = currentState.description;
|
|
@@ -536,7 +539,7 @@ function showTriageStatusModal(isLoading, triageId) {
|
|
|
536
539
|
: "";
|
|
537
540
|
const spinner = isLoading
|
|
538
541
|
? `<div style="display:flex; justify-content:center; align-items:center; padding: 40px 0;">
|
|
539
|
-
<div
|
|
542
|
+
<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
543
|
</div>`
|
|
541
544
|
: "";
|
|
542
545
|
const copiedStatus = !isLoading
|