Show character avatar images in casting pickers (v1.14.12)
The Characters Found sidebar, the "Assign to" popup's character list, and the "merge with an already-found character" list now show each character's saved portrait when one exists (same source as the profile detail panel), falling back to the existing colour-keyed initial-letter dot otherwise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
2133fe25c7
commit
3db3616830
@ -9,6 +9,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
||||
|
||||
---
|
||||
|
||||
## [1.14.12] — 2026-07-09
|
||||
|
||||
### Added
|
||||
- **Character avatar images in the casting pickers** — the Characters Found sidebar, the "Assign to" popup's character list, and the "merge with an already-found character" list now show the character's saved portrait (same source as the profile detail panel) when one exists, falling back to the colour-keyed initial-letter dot otherwise.
|
||||
|
||||
---
|
||||
|
||||
## [1.14.11] — 2026-07-09
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="theme-color" content="#2563EB">
|
||||
<meta name="app-version" content="1.14.11">
|
||||
<meta name="app-version" content="1.14.12">
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/static/icon.svg">
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
||||
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.14.11">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.14.12">
|
||||
|
||||
|
||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||
@ -365,7 +365,7 @@ window.toggleNavTree = function(treeId, chevronId) {
|
||||
</script>
|
||||
|
||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||
<script src="/static/loader.js?v=1.14.11"></script>
|
||||
<script src="/static/loader.js?v=1.14.12"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1566,6 +1566,16 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
else roster.get(name).color = color;
|
||||
return roster.get(name).color;
|
||||
};
|
||||
// Small round avatar for character pickers/lists — the character's saved
|
||||
// portrait (same source as the profile detail panel) when one exists,
|
||||
// otherwise the colour-keyed initial-letter dot used everywhere else.
|
||||
const _abAvatarHtml = (name, color) => {
|
||||
const img = recordForName(name)?.image;
|
||||
const c = color || colorFor(name);
|
||||
return img
|
||||
? `<span class="ab-char-dot ab-char-dot-img"><img src="${escHtml(img)}" alt=""></span>`
|
||||
: `<span class="ab-char-dot" style="background:${c}">${escHtml((name || '?')[0].toUpperCase())}</span>`;
|
||||
};
|
||||
const setCharacterColor = (name, color) => {
|
||||
const safe = _abNormalizeColor(color, name);
|
||||
const info = roster.get(name);
|
||||
@ -1982,7 +1992,7 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
chars.innerHTML = items.map(([n, info]) => {
|
||||
const color = info.color || colorFor(n);
|
||||
return `<div class="ab-char-item${prev===n?' is-active':''}" data-name="${escHtml(n)}">
|
||||
<span class="ab-char-dot" style="background:${color}">${escHtml((n||'?')[0].toUpperCase())}</span>
|
||||
${_abAvatarHtml(n, color)}
|
||||
<span class="ab-char-name">${escHtml(n)}</span>
|
||||
<b class="ab-char-count">${roster.get(n)?.count||0}</b>
|
||||
<button class="ab-char-alias-btn" data-name="${escHtml(n)}" title="Add alias / also known as"><span class="mdi mdi-tag-plus-outline"></span></button>
|
||||
@ -2039,7 +2049,7 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
</datalist>
|
||||
${otherNames.length ? `<div class="ab-alias-popup-hint">Or merge with an already-found character:</div>
|
||||
<div class="ab-alias-popup-list">
|
||||
${otherNames.slice(0, 8).map(([n, info]) => `<button type="button" class="ab-alias-merge-opt" data-name="${escHtml(n)}">${escHtml(n)} <span class="ab-alias-merge-count">${info.count}</span></button>`).join('')}
|
||||
${otherNames.slice(0, 8).map(([n, info]) => `<button type="button" class="ab-alias-merge-opt" data-name="${escHtml(n)}"><span class="ab-alias-merge-name">${_abAvatarHtml(n, info.color)}${escHtml(n)}</span><span class="ab-alias-merge-count">${info.count}</span></button>`).join('')}
|
||||
</div>` : ''}
|
||||
<div class="ab-alias-popup-actions">
|
||||
<button type="button" class="btn-secondary btn-sm ab-alias-cancel">Cancel</button>
|
||||
@ -2700,7 +2710,10 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
const btn = document.createElement('div');
|
||||
btn.dataset.name = n;
|
||||
btn.style.cssText = 'padding:6px 8px; font-size:12px; cursor:pointer; border-radius:4px; display:flex; align-items:center; gap:6px; transition:background 0.1s; font-weight:600; color:var(--text);';
|
||||
btn.innerHTML = `<span style="width:8px;height:8px;border-radius:50%;background:${info.color};"></span> ${escHtml(n)}`;
|
||||
const img = recordForName(n)?.image;
|
||||
btn.innerHTML = (img
|
||||
? `<span style="width:18px;height:18px;border-radius:50%;flex-shrink:0;overflow:hidden;"><img src="${escHtml(img)}" alt="" style="width:100%;height:100%;object-fit:cover;"></span>`
|
||||
: `<span style="width:8px;height:8px;border-radius:50%;background:${info.color};flex-shrink:0;"></span>`) + ` ${escHtml(n)}`;
|
||||
btn.onmouseover = () => btn.style.background = 'var(--panel)';
|
||||
btn.onmouseout = () => btn.style.background = 'transparent';
|
||||
btn.onclick = () => assignName(n);
|
||||
|
||||
@ -5530,6 +5530,8 @@ code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-fami
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
font-size:11px; font-weight:700; color:#fff;
|
||||
}
|
||||
.ab-char-dot-img { overflow: hidden; background: var(--panel); }
|
||||
.ab-char-dot-img img { width: 100%; height: 100%; object-fit: cover; }
|
||||
.ab-char-name { flex:1; font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width: 0; }
|
||||
.ab-char-count { font-size:11px; color:var(--subtext); font-weight:700; flex-shrink:0; }
|
||||
.ab-char-alias-btn {
|
||||
@ -5563,7 +5565,9 @@ code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-fami
|
||||
background: none; color: var(--text); cursor: pointer; text-align: left;
|
||||
}
|
||||
.ab-alias-merge-opt:hover { background: var(--panel); border-color: var(--border); }
|
||||
.ab-alias-merge-count { font-size: 10.5px; color: var(--subtext); font-weight: 700; }
|
||||
.ab-alias-merge-name { display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.ab-alias-merge-name .ab-char-dot { width: 18px; height: 18px; font-size: 9px; }
|
||||
.ab-alias-merge-count { font-size: 10.5px; color: var(--subtext); font-weight: 700; flex-shrink: 0; }
|
||||
.ab-alias-popup-actions { display: flex; justify-content: flex-end; gap: 6px; }
|
||||
/* Character detail panel inside the casting feed area */
|
||||
.ab-char-detail-panel {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user