Spaces:
Running
Running
Commit ·
63fd7b5
1
Parent(s): 77edcd1
Audiobook: row remove button, voice chip with arrow + name label, subtler lines, wider page
Browse files- index.html +50 -12
index.html
CHANGED
|
@@ -284,6 +284,7 @@ body {
|
|
| 284 |
}
|
| 285 |
|
| 286 |
.content-inner { width: 100%; max-width: 720px; }
|
|
|
|
| 287 |
|
| 288 |
.page { display: none; }
|
| 289 |
.page.active { display: block; }
|
|
@@ -369,22 +370,38 @@ body {
|
|
| 369 |
padding: 8px 14px; border: 1px solid var(--border); border-top: none;
|
| 370 |
border-radius: 0 0 12px 12px; background: var(--surface2); margin-bottom: 16px;
|
| 371 |
}
|
| 372 |
-
.ab-row { display: flex; align-items: flex-start; gap:
|
| 373 |
.ab-chip {
|
| 374 |
-
flex: none; width:
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
}
|
| 379 |
-
.ab-chip.
|
| 380 |
.ab-para {
|
| 381 |
-
flex: 1; font-size: 15px; line-height: 1.55; color: var(--text); padding:
|
| 382 |
-
border-radius: 6px; background:
|
| 383 |
white-space: pre-wrap; word-break: break-word;
|
| 384 |
}
|
| 385 |
-
.ab-para:
|
|
|
|
| 386 |
.ab-para:empty::before { content: "Type or paste a paragraph… (Enter starts a new line, each line is its own voice)"; color: var(--text-muted); pointer-events: none; }
|
| 387 |
.ab-row-side { flex: none; display: flex; align-items: center; gap: 6px; margin-top: 2px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 388 |
.ab-play-one {
|
| 389 |
width: 26px; height: 26px; border-radius: 6px; border: 1px solid var(--border);
|
| 390 |
background: var(--surface3); color: var(--text-secondary); cursor: pointer; padding: 0;
|
|
@@ -3793,8 +3810,14 @@ function renderAbRows() {
|
|
| 3793 |
chip.type = "button";
|
| 3794 |
chip.className = "ab-chip" + (s.voiceId ? " overridden" : "");
|
| 3795 |
const eff = abEffectiveVoice(s.voiceId);
|
| 3796 |
-
|
| 3797 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3798 |
chip.title = `Voice: ${eff.label}${s.voiceId ? " (override)" : " (default)"} — click to change`;
|
| 3799 |
chip.onmousedown = (e) => e.preventDefault();
|
| 3800 |
chip.onclick = (e) => abOpenVoiceMenu(e, i);
|
|
@@ -3818,7 +3841,10 @@ function renderAbRows() {
|
|
| 3818 |
const st = document.createElement("span");
|
| 3819 |
st.className = "ab-row-status " + (s.status === "idle" ? "" : s.status);
|
| 3820 |
st.textContent = s.status === "done" ? "✓" : s.status === "error" ? "✕" : s.status === "active" ? "…" : "";
|
| 3821 |
-
|
|
|
|
|
|
|
|
|
|
| 3822 |
|
| 3823 |
row.appendChild(chip); row.appendChild(para); row.appendChild(side);
|
| 3824 |
doc.appendChild(row);
|
|
@@ -3886,6 +3912,18 @@ function abParaPaste(e, i) {
|
|
| 3886 |
}
|
| 3887 |
}
|
| 3888 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3889 |
window.abClearDoc = function() {
|
| 3890 |
abSegments = [{ text: "", voiceId: "", status: "idle", url: null }];
|
| 3891 |
renderAbRows();
|
|
|
|
| 284 |
}
|
| 285 |
|
| 286 |
.content-inner { width: 100%; max-width: 720px; }
|
| 287 |
+
.content-inner:has(#page-audiobook.active) { max-width: 960px; }
|
| 288 |
|
| 289 |
.page { display: none; }
|
| 290 |
.page.active { display: block; }
|
|
|
|
| 370 |
padding: 8px 14px; border: 1px solid var(--border); border-top: none;
|
| 371 |
border-radius: 0 0 12px 12px; background: var(--surface2); margin-bottom: 16px;
|
| 372 |
}
|
| 373 |
+
.ab-row { display: flex; align-items: flex-start; gap: 10px; padding: 4px 0; position: relative; }
|
| 374 |
.ab-chip {
|
| 375 |
+
flex: none; width: 56px; background: none; border: none; cursor: pointer; padding: 0;
|
| 376 |
+
display: flex; flex-direction: column; align-items: center; gap: 2px; margin-top: 1px;
|
| 377 |
+
}
|
| 378 |
+
.ab-chip-av {
|
| 379 |
+
width: 30px; height: 30px; border-radius: 50%; border: 2px solid var(--border);
|
| 380 |
+
color: #fff; font-size: 12px; font-weight: 700;
|
| 381 |
+
display: flex; align-items: center; justify-content: center; gap: 1px; position: relative;
|
| 382 |
+
}
|
| 383 |
+
.ab-chip-av svg { width: 9px; height: 9px; opacity: 0.85; }
|
| 384 |
+
.ab-chip.overridden .ab-chip-av { box-shadow: 0 0 0 2px var(--accent); }
|
| 385 |
+
.ab-chip-name {
|
| 386 |
+
font-size: 10px; font-weight: 600; color: var(--text-muted); max-width: 56px;
|
| 387 |
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1.2;
|
| 388 |
}
|
| 389 |
+
.ab-chip:hover .ab-chip-name { color: var(--text-secondary); }
|
| 390 |
.ab-para {
|
| 391 |
+
flex: 1; font-size: 15px; line-height: 1.55; color: var(--text); padding: 4px 8px;
|
| 392 |
+
border-radius: 6px; background: transparent; outline: none; min-height: 1.55em;
|
| 393 |
white-space: pre-wrap; word-break: break-word;
|
| 394 |
}
|
| 395 |
+
.ab-para:hover { background: var(--surface2); }
|
| 396 |
+
.ab-para:focus { background: var(--surface2); }
|
| 397 |
.ab-para:empty::before { content: "Type or paste a paragraph… (Enter starts a new line, each line is its own voice)"; color: var(--text-muted); pointer-events: none; }
|
| 398 |
.ab-row-side { flex: none; display: flex; align-items: center; gap: 6px; margin-top: 2px; }
|
| 399 |
+
.ab-row-del {
|
| 400 |
+
width: 24px; height: 24px; border-radius: 6px; border: 1px solid transparent;
|
| 401 |
+
background: none; color: var(--text-muted); cursor: pointer; padding: 0;
|
| 402 |
+
display: flex; align-items: center; justify-content: center; font-size: 15px; line-height: 1;
|
| 403 |
+
}
|
| 404 |
+
.ab-row-del:hover { color: #dc2626; border-color: var(--border); background: var(--surface3); }
|
| 405 |
.ab-play-one {
|
| 406 |
width: 26px; height: 26px; border-radius: 6px; border: 1px solid var(--border);
|
| 407 |
background: var(--surface3); color: var(--text-secondary); cursor: pointer; padding: 0;
|
|
|
|
| 3810 |
chip.type = "button";
|
| 3811 |
chip.className = "ab-chip" + (s.voiceId ? " overridden" : "");
|
| 3812 |
const eff = abEffectiveVoice(s.voiceId);
|
| 3813 |
+
const av = document.createElement("span");
|
| 3814 |
+
av.className = "ab-chip-av";
|
| 3815 |
+
av.style.background = eff.color;
|
| 3816 |
+
av.innerHTML = `<span>${eff.initial}</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><polyline points="6 9 12 15 18 9"/></svg>`;
|
| 3817 |
+
const nm = document.createElement("span");
|
| 3818 |
+
nm.className = "ab-chip-name";
|
| 3819 |
+
nm.textContent = eff.label;
|
| 3820 |
+
chip.appendChild(av); chip.appendChild(nm);
|
| 3821 |
chip.title = `Voice: ${eff.label}${s.voiceId ? " (override)" : " (default)"} — click to change`;
|
| 3822 |
chip.onmousedown = (e) => e.preventDefault();
|
| 3823 |
chip.onclick = (e) => abOpenVoiceMenu(e, i);
|
|
|
|
| 3841 |
const st = document.createElement("span");
|
| 3842 |
st.className = "ab-row-status " + (s.status === "idle" ? "" : s.status);
|
| 3843 |
st.textContent = s.status === "done" ? "✓" : s.status === "error" ? "✕" : s.status === "active" ? "…" : "";
|
| 3844 |
+
const del = document.createElement("button");
|
| 3845 |
+
del.type = "button"; del.className = "ab-row-del"; del.title = "Remove line"; del.textContent = "✕";
|
| 3846 |
+
del.onclick = () => abRemoveRow(i);
|
| 3847 |
+
side.appendChild(play); side.appendChild(st); side.appendChild(del);
|
| 3848 |
|
| 3849 |
row.appendChild(chip); row.appendChild(para); row.appendChild(side);
|
| 3850 |
doc.appendChild(row);
|
|
|
|
| 3912 |
}
|
| 3913 |
}
|
| 3914 |
|
| 3915 |
+
window.abRemoveRow = function(i) {
|
| 3916 |
+
if (abSegments.length <= 1) {
|
| 3917 |
+
abSegments = [{ text: "", voiceId: "", status: "idle", url: null }];
|
| 3918 |
+
renderAbRows();
|
| 3919 |
+
abFocusRow(0, 0);
|
| 3920 |
+
return;
|
| 3921 |
+
}
|
| 3922 |
+
abSegments.splice(i, 1);
|
| 3923 |
+
renderAbRows();
|
| 3924 |
+
abFocusRow(Math.max(0, i - 1), abSegments[Math.max(0, i - 1)].text.length);
|
| 3925 |
+
};
|
| 3926 |
+
|
| 3927 |
window.abClearDoc = function() {
|
| 3928 |
abSegments = [{ text: "", voiceId: "", status: "idle", url: null }];
|
| 3929 |
renderAbRows();
|