fix(sonar): remove unused variables and commented-out code
Removes 43 small Sonar findings (unused locals, dead helpers, a misread comment); behaviour unchanged. CHANGELOG entry was already swept into 9f78a15.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a60b7e555d
commit
1d65a4df7c
@ -2600,7 +2600,7 @@ def extract_pages(pdf_path: Path, out_dir: Path, render_dpi: int = 110,
|
||||
blocks: list[Block] = []
|
||||
data = {} if extra_turn else page.get_text("dict")
|
||||
for bi, blk in enumerate(data.get("blocks", [])):
|
||||
if blk.get("type") != 0: # 0 = text, 1 = image
|
||||
if blk.get("type") != 0: # block type: text or image
|
||||
continue
|
||||
texts, sizes, fonts, bolds = [], [], [], []
|
||||
for line in blk.get("lines", []):
|
||||
|
||||
@ -348,7 +348,7 @@ def _nvidia_clone_request_audio(
|
||||
if audio_path is None:
|
||||
raise RuntimeError(f"reference voice not found in library: {voice}")
|
||||
prompt_wav = _to_wav_24k(audio_path)
|
||||
has_ref, saved_transcript = _read_reference_text(audio_path)
|
||||
_, saved_transcript = _read_reference_text(audio_path)
|
||||
prompt_transcript = str(reference_transcript or saved_transcript or "").strip()
|
||||
if mode == "flow" and not prompt_transcript:
|
||||
raise RuntimeError("NVIDIA Magpie Flow requires the selected voice to have an exact saved reference transcript")
|
||||
|
||||
@ -2939,11 +2939,6 @@ def _build_compact_character_render_prompts(name: str, book: str, sheet: dict,
|
||||
f"The scalp, crown, hairline, {ear_shape}, and complete natural hairstyle are visibly exposed and unobstructed."
|
||||
)
|
||||
bareheaded = not has_headwear
|
||||
head_lock = (
|
||||
f"HEAD CONTINUITY: In all three figures, clearly show the exposed scalp, crown, hairline, {ear_shape}, and complete natural hairstyle in front, profile, and rear views. "
|
||||
if bareheaded else
|
||||
"HEADWEAR LOCK: reproduce only the explicitly established period headwear, identically in all three views. "
|
||||
)
|
||||
leather_only = _character_is_leather_only_armor(sheet)
|
||||
period_materials = (
|
||||
"wool, linen, leather, hand-worked fastenings, and flat stitched-leather footwear"
|
||||
@ -3095,12 +3090,6 @@ def _build_compact_character_render_prompts(name: str, book: str, sheet: dict,
|
||||
f"{female_presentation_lock}"
|
||||
f"{no_headwear}"
|
||||
)
|
||||
if visual_style == "concept":
|
||||
portrait_style = "One fixed semi-realistic hand-painted fantasy production artist with grounded anatomy and weathered materials."
|
||||
sheet_style = portrait_style
|
||||
else:
|
||||
portrait_style = "Strict live-action photorealistic historical-fantasy production photography; real actor, honest skin, natural hair, restrained warm-neutral film color."
|
||||
sheet_style = "Strict live-action photorealistic costume-continuity studio photography by that same production photographer, with a real actor and physically believable period materials."
|
||||
# Nothing previously told the model what a correctly-proportioned body
|
||||
# looks like, and the turnaround triptych in particular squeezes each
|
||||
# full-body figure into a narrow 512-wide third of the frame — confirmed
|
||||
@ -3112,7 +3101,7 @@ def _build_compact_character_render_prompts(name: str, book: str, sheet: dict,
|
||||
# same reasoning as the armor lock above: this encoder still visualizes a
|
||||
# noun mentioned after "no"/"not", so "adult proportions, not dwarfed"
|
||||
# would still cue dwarfism rather than prevent it.
|
||||
subject_clause, identical_noun, proportion_lock = _age_body_lock(sheet)
|
||||
_, identical_noun, proportion_lock = _age_body_lock(sheet)
|
||||
# Short and framing-first. The long version (~3 000 characters, framing rules buried in the middle)
|
||||
# was measured against this one on the same character, 5 seeds each, scored by the image check:
|
||||
# full bodies 0/5 vs 5/5 on a 1536x1024 canvas (also 5/5 at 1536x1280), plain backdrop 2/5 vs 5/5.
|
||||
@ -4104,7 +4093,6 @@ def _comfyui_upload_data_uri(comfyui_url: str, data_uri: str) -> str:
|
||||
except Exception as exc:
|
||||
raise HTTPException(400, f"Identity image is not valid base64: {exc}")
|
||||
mime = header.split(";", 1)[0].split(":", 1)[-1].lower()
|
||||
ext = ".jpg" if mime in {"image/jpeg", "image/jpg"} else ".webp" if mime == "image/webp" else ".png"
|
||||
filename = f"voice_creator_identity_{uuid.uuid4().hex}.png"
|
||||
try:
|
||||
resp = requests.post(
|
||||
|
||||
@ -3006,7 +3006,7 @@ def _spelling_agent_job(doc_id: str, job_id: str, article_id: str | None, page:
|
||||
@router.post("/api/magazine/{doc_id}/spelling/agent")
|
||||
async def magazine_spelling_agent(doc_id: str, request: Request):
|
||||
"""Background job: the LLM fixes provable OCR misspellings; the rest stays marked."""
|
||||
d, _ = _require_magazine(doc_id)
|
||||
_, _ = _require_magazine(doc_id)
|
||||
body = await request.json()
|
||||
body = body if isinstance(body, dict) else {}
|
||||
article = _article_id(str(body["article"])) if body.get("article") else None
|
||||
@ -3213,7 +3213,7 @@ def _audio_generate_one_sync(doc_id: str, job_id: str, article_id: str, voice: s
|
||||
async def magazine_generate_article_audio(doc_id: str, article_id: str, request: Request):
|
||||
"""Render one approved article to a single tagged MP3 (title/author/album,
|
||||
its own text as embedded lyrics, cover art) -- for taking it out of the app."""
|
||||
d, meta = _require_magazine(doc_id)
|
||||
_, meta = _require_magazine(doc_id)
|
||||
article_id = _article_id(article_id)
|
||||
body = await request.json() if await request.body() else {}
|
||||
voice = str(body.get("voice") or meta.get("default_voice") or "").strip()
|
||||
@ -3484,7 +3484,6 @@ async def magazine_audio_zip(doc_id: str, provenance: str = "", voice: str = "")
|
||||
import tempfile
|
||||
with tempfile.TemporaryDirectory(prefix="mag-prov-") as tagdir, zipfile.ZipFile(buf, "w", zipfile.ZIP_STORED) as zf:
|
||||
for i, a in enumerate(ordered, start=1):
|
||||
page = (a.get("pages") or [0])[0]
|
||||
name = _article_download_filename(meta, a)
|
||||
# Zero-padded sequence prefix so extracting the zip and sorting
|
||||
# by filename gives the reading order even where two articles
|
||||
|
||||
@ -227,7 +227,6 @@ def _cast_to_md(data: dict) -> str:
|
||||
doesn't need to round-trip back through _md_to_cast (that function only
|
||||
still matters for pre-migration legacy .md files)."""
|
||||
segments = data.get("segments") or []
|
||||
roster = data.get("roster") or []
|
||||
saved_at = data.get("savedAt")
|
||||
saved_str = ""
|
||||
if saved_at:
|
||||
|
||||
@ -25,16 +25,6 @@ async def get_settings(request: Request, response: Response):
|
||||
# install shows a real usable key in Settings immediately without a
|
||||
# migration step, whether or not the gate is actually turned on yet.
|
||||
s["external_api_key"] = _ensure_external_api_key()
|
||||
host = request.headers.get("host", "")
|
||||
origin = request.headers.get("origin", "") or request.headers.get("referer", "")
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
same_origin = (
|
||||
request.headers.get("sec-fetch-site", "").lower() == "same-origin"
|
||||
or bool(origin and host and urlparse(origin).netloc == host)
|
||||
)
|
||||
except Exception:
|
||||
same_origin = False
|
||||
# Never return provider credentials to browser JavaScript. The mask lets
|
||||
# the Settings UI indicate that a value exists without making it usable in
|
||||
# client-side requests or browser storage.
|
||||
|
||||
12
static/dist/main.min.js
vendored
12
static/dist/main.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1789,7 +1789,6 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
const _abRedoStack = [];
|
||||
const _abHistoryLimit = 40;
|
||||
const _abSyncTopbar = () => {
|
||||
const hasSelection = !_abBar.hidden;
|
||||
const hasHistory = _abUndoStack.length > 0 || _abRedoStack.length > 0;
|
||||
_abEditToolbar.hidden = !hasHistory;
|
||||
// Always visible — it hosts the font-size controls now, not just the
|
||||
@ -1803,16 +1802,6 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
return { key: 'segments', arr: [] };
|
||||
};
|
||||
const _abCloneSegments = (segs) => (segs || []).map(s => ({ ...s }));
|
||||
const _abSyncRosterList = (segs) => {
|
||||
const names = [];
|
||||
for (const s of segs || []) {
|
||||
|
||||
const sp = s?.type === 'dialogue' && s.speaker ? s.speaker : '';
|
||||
if (!sp || /^Narrator$/i.test(sp) || /^Unknown|Unbekannt/i.test(sp)) continue;
|
||||
if (!names.some(n => n.toLowerCase() === sp.toLowerCase())) names.push(sp);
|
||||
}
|
||||
_audiobook.roster = names;
|
||||
};
|
||||
const _abPersistManualEdit = () => {
|
||||
const active = _abActiveSegments();
|
||||
if (_audiobook.lastText) {
|
||||
|
||||
@ -391,7 +391,6 @@ async function audiobookAutoRepairCast(threshold = 10, maxRounds = 4) {
|
||||
// uses the same bounded suspect-scored pass as the rounds above.
|
||||
toast(`2.4 Still ${prev} unknown — running full verification pass…`, 'info');
|
||||
await audiobookRecastUnknown(null, null, { repairNarration: true });
|
||||
const afterVerify = countUnknown();
|
||||
// 2.5 — consistency is a different kind of check (it re-judges lines already
|
||||
// attributed), so it runs last, once attributions have settled, and only if
|
||||
// the passes above didn't leave the cast in a worse state than they found it.
|
||||
|
||||
@ -1629,24 +1629,6 @@ function csSourceBadgeHtml(s, field) {
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function csField(label, value, sheet, field) {
|
||||
if (!value) return '';
|
||||
const badge = sheet && field ? csSourceBadgeHtml(sheet, field) : '';
|
||||
const key = field ? ` data-sheet-key="${escHtml(field)}"` : '';
|
||||
// Value text lives in its own span, separate from the source-citation
|
||||
// badge buttons — the whole <dd> used to be the only option, which would
|
||||
// have made the badges themselves editable/deletable text once this
|
||||
// became contenteditable.
|
||||
return `<div class="cs-row"><dt>${label}</dt><dd><span class="cs-field-editable"${key}>${escHtml(String(value))}</span>${badge ? ` ${badge}` : ''}</dd></div>`;
|
||||
}
|
||||
|
||||
function csIdentityCell(label, value, sheet, field) {
|
||||
if (!value) return '';
|
||||
const badge = sheet && field ? csSourceBadgeHtml(sheet, field) : '';
|
||||
const key = field ? ` data-sheet-key="${escHtml(field)}"` : '';
|
||||
return `<div class="cs-id-cell"><dt>${label}</dt><dd><span class="cs-field-editable"${key}>${escHtml(String(value))}</span>${badge ? ` ${badge}` : ''}</dd></div>`;
|
||||
}
|
||||
|
||||
function csPromptBox(label, value, sheetKey, emptyNote, extraImage) {
|
||||
const text = _csStr(value);
|
||||
const has = !!text.trim();
|
||||
@ -1692,20 +1674,6 @@ function csAvatarHtml(s) {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function csIdentityTagList(s) {
|
||||
const tags = [];
|
||||
const add = (label, value) => {
|
||||
const text = String(value || '').trim();
|
||||
if (!text) return;
|
||||
const key = text.toLowerCase();
|
||||
if (tags.some(t => t.key === key)) return;
|
||||
tags.push({ label, text, key });
|
||||
};
|
||||
const firstLast = [s.first_name, s.last_name].filter(Boolean).join(' ').trim();
|
||||
if (firstLast && firstLast !== String(s.name || '').trim()) add('first / last', firstLast);
|
||||
return tags;
|
||||
}
|
||||
|
||||
function csNameHue(name) {
|
||||
return Math.abs((name || '?').split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) % 360, 0));
|
||||
}
|
||||
@ -2203,7 +2171,7 @@ function csWireResultInteractions(root, sheets, sourceText, book, inline = false
|
||||
// editing two fields within 900ms can't cancel each other's still-pending
|
||||
// save the way a single shared timer did elsewhere in this app earlier
|
||||
// this session). Fields that are currently empty aren't rendered at all
|
||||
// (csField/csIdentityCell skip blank values), so adding a brand-new value
|
||||
// (blank values are not rendered), so adding a brand-new value
|
||||
// to a field that has nothing yet still needs the full Library profile
|
||||
// page — this only covers correcting a value that's already shown.
|
||||
root.querySelectorAll('.cs-edit-toggle').forEach(btn => {
|
||||
@ -2592,27 +2560,10 @@ async function csForReaderSelective(selectedNames) {
|
||||
// that race regardless of which async step caused it.
|
||||
if (typeof showReaderView === 'function') setTimeout(() => showReaderView('chars'), 120);
|
||||
const pageHost = csReaderPageHost();
|
||||
const knownRoster = csKnownReaderRoster();
|
||||
let records = [];
|
||||
try { records = (typeof clGetAllByTagOrBook === 'function') ? await clGetAllByTagOrBook(book) : []; } catch (_) { records = []; }
|
||||
const picked = [];
|
||||
const seen = new Set();
|
||||
const matchesWanted = (rec) => {
|
||||
const tokens = csNameTokens({
|
||||
name: rec?.name || '',
|
||||
aliases: rec?.sheet?.aliases || '',
|
||||
first_name: rec?.sheet?.first_name || '',
|
||||
last_name: rec?.sheet?.last_name || '',
|
||||
full_name: rec?.sheet?.full_name || '',
|
||||
});
|
||||
for (const t of tokens) {
|
||||
const lower = String(t || '').toLowerCase();
|
||||
for (const w of wanted) {
|
||||
if (lower === w || lower.includes(w) || w.includes(lower)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// Exact canonical names always win. Alias matching is only a fallback for
|
||||
// old records that have no exact record; otherwise selecting Lysandra could
|
||||
// pick an Alrik profile whose generated aliases happened to contain the
|
||||
|
||||
@ -1241,7 +1241,7 @@ $('s-import-voices-file')?.addEventListener('change', async function () {
|
||||
const turnN = turnCount;
|
||||
const t0 = Date.now();
|
||||
|
||||
const userBubble = addBubble('user', text);
|
||||
addBubble('user', text);
|
||||
const assistantBubble = addTypingBubble();
|
||||
convCurrentSentenceBubble = assistantBubble;
|
||||
let assistantText = '';
|
||||
|
||||
@ -207,7 +207,7 @@ function initElevenLabsBrowser() {
|
||||
const e = await r.json().catch(() => ({}));
|
||||
throw new Error(e.detail || r.statusText);
|
||||
}
|
||||
const d = await r.json();
|
||||
await r.json();
|
||||
btn.innerHTML = '<span class="mdi mdi-check"></span> In library';
|
||||
btn.classList.add('el-imported');
|
||||
if (typeof toast === 'function') toast(`Imported "${name}" — transcript and benchmark are preparing in the background`, 'success');
|
||||
|
||||
@ -808,29 +808,6 @@ function _charGenderLabel(sh) {
|
||||
return gender.charAt(0).toUpperCase() + gender.slice(1);
|
||||
}
|
||||
|
||||
function _charRelsHtml(rec, allChars) {
|
||||
if (!allChars || allChars.length < 2) return '';
|
||||
const relText = _libStr(rec.sheet?.relationships).toLowerCase();
|
||||
if (!relText) return '';
|
||||
const hits = allChars
|
||||
.filter(function (c) { return c.id !== rec.id && (c.name || '').length > 1; })
|
||||
.map(function (c) {
|
||||
const re = new RegExp(c.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi');
|
||||
return { c: c, n: (relText.match(re) || []).length };
|
||||
})
|
||||
.filter(function (x) { return x.n > 0; })
|
||||
.sort(function (a, b) { return b.n - a.n; })
|
||||
.slice(0, 5);
|
||||
if (!hits.length) return '';
|
||||
return '<div class="lib-char-rels">'
|
||||
+ hits.map(function (x) {
|
||||
const h = _charHue(x.c.name);
|
||||
return '<span class="lib-char-rel-dot" style="background:hsl(' + h + ',55%,38%)" title="' + escHtml(x.c.name) + ' (' + x.n + '×)">'
|
||||
+ escHtml((x.c.name || '?')[0].toUpperCase()) + '</span>';
|
||||
}).join('')
|
||||
+ '</div>';
|
||||
}
|
||||
|
||||
// Single shared floating preview element, positioned near whichever avatar
|
||||
// is currently hovered — created lazily on first use rather than once per
|
||||
// row (there can be dozens of rows in a production).
|
||||
@ -1037,24 +1014,11 @@ function _charCardHtml(rec, allChars) {
|
||||
: tier === 'supporting' ? '<span class="lib-char-tier support">Neben</span>' : '';
|
||||
const gender = String(sh.gender || '').toLowerCase();
|
||||
const genderIcon = gender.startsWith('f') ? 'mdi-gender-female' : gender.startsWith('m') ? 'mdi-gender-male' : 'mdi-gender-non-binary';
|
||||
const snippet = _libStr(sh.mannerisms || sh.voice_pattern || sh.motivation || sh.backstory || '').slice(0, 190);
|
||||
const roleLine = _libStr(sh.profession || sh.archetype).trim();
|
||||
const ageLabel = _charAgeLabel(sh);
|
||||
const langLabel = _charLangLabel(rec);
|
||||
const genderLabel = _charGenderLabel(sh);
|
||||
const bookLabel = _libStr(rec.book || '');
|
||||
const lineLabel = sh.line_count != null ? String(sh.line_count) + ' Zeilen' : '';
|
||||
// Every character is auto-tagged with the book it was found in (see
|
||||
// clUpsert/clMergeTags) — surfacing the chips here is how you tell a
|
||||
// character recurring across several books apart from a same-named one
|
||||
// that's book-local, since tags (not the single `book` field) are what
|
||||
// carries multi-book membership.
|
||||
const tagList = String(rec.tags || '').split(',').map(function (t) { return t.trim(); }).filter(Boolean);
|
||||
const tagsHtml = tagList.length
|
||||
? '<div class="lib-char-tags">' + tagList.map(function (t) {
|
||||
return '<span class="cl-tag-chip"><span class="mdi mdi-tag-outline"></span>' + escHtml(t) + '</span>';
|
||||
}).join('') + '</div>'
|
||||
: '';
|
||||
|
||||
// A saved portrait used to be squeezed into a small 96px circle floating
|
||||
// over the same colour-gradient banner everyone without a photo gets —
|
||||
@ -1158,8 +1122,6 @@ function _charsTableHtml(chars, sortMode, sortDir) {
|
||||
const tier = String(sh.tier || '').toLowerCase();
|
||||
const tierBadge = tier === 'main' ? '<span class="lib-char-tier main">Haupt</span>'
|
||||
: tier === 'supporting' ? '<span class="lib-char-tier support">Neben</span>' : '';
|
||||
const gender = String(sh.gender || '').toLowerCase();
|
||||
const genderIcon = gender.startsWith('f') ? 'mdi-gender-female' : gender.startsWith('m') ? 'mdi-gender-male' : gender ? 'mdi-gender-non-binary' : '';
|
||||
const genderLabel = _charGenderLabel(sh);
|
||||
const score = sh.moral_alignment_score;
|
||||
const pct = score != null ? Math.max(0, Math.min(100, score)) : null;
|
||||
@ -2222,7 +2184,6 @@ window._charDetailPage = _charDetailPage;
|
||||
|
||||
function _charDetailModal(rec, allChars) {
|
||||
const sh = rec.sheet || {};
|
||||
const cov = libBookCover(rec.name);
|
||||
const hue = _charHue(rec.name);
|
||||
const tier = String(sh.tier || '').toLowerCase();
|
||||
const tierLabel = tier === 'main' ? 'Hauptcharakter' : tier === 'supporting' ? 'Nebencharakter' : tier === 'minor' ? 'Nebenfigur' : '';
|
||||
|
||||
@ -851,24 +851,6 @@ function confidenceLabel(c) {
|
||||
// says the same thing in context, so it was just a second, redundant
|
||||
// warning -- removed.
|
||||
|
||||
// The next page after `afterPage` that still needs a human decision -- no
|
||||
// article covers it at all, or one does but is still sitting at its
|
||||
// detected/unreviewed status. A page touched by several articles only
|
||||
// counts as resolved once none of them are still pending.
|
||||
function magNextUnresolvedPage(afterPage) {
|
||||
const pageCount = state.doc?.pageCount || 0;
|
||||
const byPage = new Map();
|
||||
state.articles.forEach((a) => (a.pages || []).forEach((p) => {
|
||||
if (!byPage.has(p)) byPage.set(p, []);
|
||||
byPage.get(p).push(a);
|
||||
}));
|
||||
for (let p = afterPage + 1; p <= pageCount; p++) {
|
||||
const arts = byPage.get(p) || [];
|
||||
if (!arts.length || arts.some((a) => a.status === 'detected')) return p;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Opens Review at a specific page even when no article covers it, by
|
||||
// anchoring on whichever approved-or-not article is nearest that page (the
|
||||
// review UI needs *an* article as context, but its own page navigation is
|
||||
@ -4131,8 +4113,6 @@ async function magSetStatus(status) {
|
||||
// exactly what is read as one paragraph: below (same column), column (top of another column) or
|
||||
// page (another page).
|
||||
|
||||
const MAG_FLOW_LABEL = { below: 'continues below', column: 'continues in the next column', page: 'continues on page' };
|
||||
|
||||
async function magFlowLoad() {
|
||||
const a = state.article;
|
||||
if (!a || !state.doc) return;
|
||||
|
||||
@ -488,7 +488,6 @@ function _lineAudioCachePut(book, key, blob) {
|
||||
// of the current script's lines already have a matching file, and lights
|
||||
// up their dots — without downloading any actual audio (that still only
|
||||
// happens lazily, right when a line is about to play).
|
||||
let _lineAudioSyncedFor = null; // unused now, kept for compat
|
||||
async function _lineAudioSyncDots() {
|
||||
const book = _lineAudioBookName();
|
||||
_ensureNarrator();
|
||||
|
||||
@ -1350,7 +1350,6 @@ function rehMarkCastDesigning(sp, state, msg, info) {
|
||||
} else if (state === 'done' && panel) {
|
||||
// Collapse to a summary line
|
||||
const descEl = panel.querySelector('.reh-cdp-desc');
|
||||
const metaEl = panel.querySelector('.reh-cdp-meta');
|
||||
const stepEl = panel.querySelector('.reh-cdp-step');
|
||||
if (stepEl) stepEl.remove();
|
||||
if (descEl) {
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
// single-language audiobook.
|
||||
const SEED_FINDER_TEXT_DE = 'Die dreitausendfünfhundertsiebenundsechzig neuen Geräte für das Update benötigten eine außergewöhnlich starke Kühlung und regelmäßige Wartung, um die Leistung bei großer Last zu gewährleisten. Notiere dir den einundzwanzigsten Juni um vierzehn Uhr. Es ist reine Zeitverschwendung, etwas Mittelmäßiges zu tun! Träume beginnen mit einem positiven Mindset.';
|
||||
const SEED_FINDER_TEXT_EN = 'The new devices for the update required exceptionally strong cooling and regular maintenance to guarantee performance under heavy load. Make a note for the twenty-first of June at two in the afternoon. It is a genuine waste of time to do something mediocre! Dreams begin with a positive mindset.';
|
||||
const SEED_FINDER_TEXT_TORTURE = 'Die 3.567 neuen High-End Geräte für das Server-Update benötigen eine außergewöhnlich starke Kühlung und regelmäßige Maßnahmen, um die Performance bei großer Last zu gewährleisten. - The system administrator successfully configured the customized Docker stacks and benchmarked the inference engines at exactly 8:45 AM. - Notiere dir an Midsummer 21.06. um 14 Uhr - Es ist reine Zeitverschwendung, etwas Mittelmäßiges zu tun! Schöne Grüße! — Madonna - Träume beginnt mit einem positiven Mindset.';
|
||||
|
||||
const _sfT = s => (typeof window.t === 'function' ? window.t(s) : s);
|
||||
|
||||
|
||||
@ -808,7 +808,7 @@ document.addEventListener('click', async e => { if (!e.target.closest('.s-save-b
|
||||
['vibevoice', 's-tts-extra-vibevoice', 'VibeVoice'],
|
||||
];
|
||||
try {
|
||||
for (const [key, id, label] of paramFields) {
|
||||
for (const [key, id] of paramFields) {
|
||||
ttsExtraParamsByBackend[key] = JSON.parse($(id).value || '{}');
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@ -247,7 +247,7 @@ function _statusApplyToSelects(ids, value) {
|
||||
}
|
||||
|
||||
async function _statusOpenLlmFlyup(anchor) {
|
||||
const { url, model, apiKey } = statusLlmTarget();
|
||||
const { url, model } = statusLlmTarget();
|
||||
if (!url) { _statusFlyupList(anchor, [], null, 'No LLM endpoint configured', 'llm'); return; }
|
||||
_statusFlyupList(anchor, [], null, 'Loading models…', 'llm');
|
||||
let models = [];
|
||||
@ -315,7 +315,7 @@ document.addEventListener('click', e => {
|
||||
|
||||
async function refreshStatusBarEngines({ force = false } = {}) {
|
||||
updateStatusBar();
|
||||
const { url, model, apiKey } = statusLlmTarget();
|
||||
const { url, model } = statusLlmTarget();
|
||||
if (!url || STATUS_LLM_CACHE.pending) return;
|
||||
const fresh = STATUS_LLM_CACHE.url === url && STATUS_LLM_CACHE.model === model && (Date.now() - STATUS_LLM_CACHE.checked) < 30000;
|
||||
if (fresh && !force) return;
|
||||
|
||||
@ -910,7 +910,6 @@ document.querySelectorAll('.qwen-sample').forEach(card => {
|
||||
|
||||
async function runVoiceDesign() {
|
||||
const baseInstruct=$('design-instruct').value.trim(), sample=$('design-sample-text').value.trim();
|
||||
const dialogue = isDialogueDesign(baseInstruct, sample, currentDesignSource);
|
||||
const instruct = baseInstruct;
|
||||
if (!instruct) { toast('Enter a voice description first','error'); return; }
|
||||
$('design-generate-btn').disabled=true; $('design-status').textContent='Generating…';
|
||||
|
||||
@ -54,7 +54,6 @@ function selectVoice(wrap) {
|
||||
const dispName = (v.name && String(v.name).trim())
|
||||
? String(v.name).trim()
|
||||
: (nameParts.length > 1 ? nameParts[nameParts.length - 1] : voiceId);
|
||||
const initial = (dispName[0] || voiceId[0] || '?').toUpperCase();
|
||||
const picSrcInsp = hasPicture ? `/api/voice/picture/${encodeURIComponent(voiceId)}` : null;
|
||||
const inspFlagCc = flagCc || langCode;
|
||||
const inspFlagIcon = inspFlagCc
|
||||
|
||||
@ -279,7 +279,6 @@ const FLAG_LANGUAGE_CANDIDATES = {
|
||||
CN:['ZH'], TW:['ZH'], HK:['ZH'], MO:['ZH'], JP:['JA'], KR:['KO'], VN:['VI'], TH:['TH'], ID:['ID'], MY:['MS'], PK:['UR'], BD:['BN'], LK:['SI'], NP:['NE'],
|
||||
SA:['AR'], EG:['AR'], AE:['AR'], MA:['AR'], QA:['AR'], KW:['AR'], OM:['AR'], JO:['AR'], LB:['AR'], IQ:['AR'], IR:['FA'], IL:['HE'],
|
||||
};
|
||||
const FLAG_LANGUAGE = Object.fromEntries(Object.entries(FLAG_LANGUAGE_CANDIDATES).map(([cc, langs]) => [cc, langs[0]]));
|
||||
|
||||
const LANGUAGE_LABELS = {
|
||||
EN:'English', DE:'German', FR:'French', ES:'Spanish', PT:'Portuguese', IT:'Italian', NL:'Dutch', PL:'Polish', SV:'Swedish',
|
||||
@ -935,12 +934,6 @@ function setBenchmarkProgress(done, total, label = '', stats = {}) {
|
||||
if (last && stats.last) last.textContent = stats.last;
|
||||
}
|
||||
|
||||
function hideBenchmarkProgress() {
|
||||
$('benchmark-progress').hidden = true;
|
||||
$('benchmark-progress-bar').style.width = '0%';
|
||||
if ($('benchmark-live-last')) $('benchmark-live-last').textContent = '';
|
||||
}
|
||||
|
||||
async function clearTtsRestartFlags() {
|
||||
const r = await fetch('/api/tts/restart-flags/clear', { method:'POST' });
|
||||
if (!r.ok) { const e = await r.json().catch(()=>({})); throw new Error(e.detail || r.statusText); }
|
||||
@ -1878,7 +1871,6 @@ function renderVoiceList() {
|
||||
if (window._voiceTagFilter) {
|
||||
filtered = filtered.filter(v => String(v.tag || '').split(',').map(t => t.trim()).includes(window._voiceTagFilter));
|
||||
}
|
||||
const visibleCount = filtered.length;
|
||||
filtered = filtered.filter(libraryFilterMatch);
|
||||
const filterCount = filtered.length;
|
||||
if (_libraryIssueFilter) filtered = filtered.filter(v => libraryIssueMatch(v));
|
||||
@ -2257,10 +2249,6 @@ function makeVoiceRow(v) {
|
||||
// confusing 404 for a voice that clearly has reference audio in its own
|
||||
// panel (confirmed live).
|
||||
const isClone = !!v.has_ref;
|
||||
const initial = v.id[0] ? v.id[0].toUpperCase() : '?';
|
||||
const flagIconHtml = currentFlag
|
||||
? `<span class="fi fi-${currentFlag.toLowerCase()}" role="img" aria-label="${langCode}"></span>`
|
||||
: null;
|
||||
|
||||
// Avatar: photo > gender/type icon > silhouette (with color)
|
||||
const defaultSilClass = gender === 'M' ? 'mdi-face-man' : (gender === 'F' ? 'mdi-face-woman' : 'mdi-account');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user