- Selettore personaggio sopra la barra input - Solo PG vivi, nome abbreviato - Click seleziona/deseleziona - Nome preposto all azione: 'Druso: esploro...' - Label azione mostra il nome del PG
This commit is contained in:
1 parent
90ba835868
commit
ea945a37f8
1 file changed
+82
-2
@@ -476,6 +476,44 @@ html, body {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Character selector (above input)
|
||||
============================================================ */
|
||||
.char-selector {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
padding: 6px 20px;
|
||||
background: var(--bg-surface);
|
||||
border-top: 1px solid var(--border);
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.char-selector::-webkit-scrollbar { display: none; }
|
||||
.char-selector.hidden { display: none; }
|
||||
.char-chip {
|
||||
flex-shrink: 0;
|
||||
background: var(--bg-elevated);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 3px 10px;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s, color 0.2s, background 0.2s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.char-chip:hover { border-color: var(--gold-dim); color: var(--text-primary); }
|
||||
.char-chip.active {
|
||||
background: var(--gold-dim);
|
||||
border-color: var(--gold);
|
||||
color: #fff;
|
||||
}
|
||||
.char-chip.dead {
|
||||
opacity: 0.3;
|
||||
text-decoration: line-through;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Input Area
|
||||
============================================================ */
|
||||
@@ -717,6 +755,15 @@ html, body {
|
||||
.msg { max-width: 95%; }
|
||||
.msg-dm-narration { font-size: 15px; }
|
||||
|
||||
.char-selector {
|
||||
padding: 4px 12px;
|
||||
gap: 4px;
|
||||
}
|
||||
.char-chip {
|
||||
font-size: 11px;
|
||||
padding: 3px 8px;
|
||||
}
|
||||
|
||||
#input-area {
|
||||
padding: 10px 12px;
|
||||
padding-bottom: max(12px, env(safe-area-inset-bottom));
|
||||
@@ -825,6 +872,7 @@ html, body {
|
||||
<div id="chat">
|
||||
<div class="msg system"><div class="msg-bubble">Benvenuto, avventuriero. Scrivi la tua azione per iniziare.</div></div>
|
||||
</div>
|
||||
<div id="char-selector" class="char-selector hidden"></div>
|
||||
<div id="input-area">
|
||||
<input type="text" id="input" placeholder="Cosa vuoi fare?" disabled />
|
||||
<button id="btn-send" disabled>➤</button>
|
||||
@@ -843,6 +891,7 @@ let ws = null;
|
||||
let turn = 0;
|
||||
let reconnectTimer = null;
|
||||
let currentAreaId = '';
|
||||
let selectedCharId = null;
|
||||
let state = { characters: [], quests: [], areas: [] };
|
||||
|
||||
const HOST = window.location.host;
|
||||
@@ -1070,6 +1119,29 @@ function renderChar(chars) {
|
||||
if (dead.length > 0) {
|
||||
charDisplay.innerHTML += `<div class="funnel-actions"><button onclick="replaceFunnelDead()" class="btn-funnel">➕ Nuovo PG (rimpiazza caduti)</button></div>`;
|
||||
}
|
||||
renderCharSelector(chars);
|
||||
}
|
||||
|
||||
function renderCharSelector(chars) {
|
||||
const container = document.getElementById('char-selector');
|
||||
const alive = chars.filter(c => c.status !== 'dead');
|
||||
if (alive.length <= 1) {
|
||||
container.classList.add('hidden');
|
||||
selectedCharId = null;
|
||||
return;
|
||||
}
|
||||
container.classList.remove('hidden');
|
||||
container.innerHTML = alive.map(c => `
|
||||
<button class="char-chip ${c.id === selectedCharId ? 'active' : ''}"
|
||||
onclick="selectChar(${c.id})">${escapeHtml(c.name).split(' il ')[0]}</button>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function selectChar(id) {
|
||||
selectedCharId = selectedCharId === id ? null : id;
|
||||
// Re-render selector to update active state
|
||||
renderCharSelector(state.characters);
|
||||
input.focus();
|
||||
}
|
||||
|
||||
async function replaceFunnelDead() {
|
||||
@@ -1238,14 +1310,22 @@ function sendAction() {
|
||||
const text = input.value.trim();
|
||||
if (!text || !ws || ws.readyState !== WebSocket.OPEN) return;
|
||||
|
||||
const chars = state.characters || [];
|
||||
const sel = selectedCharId ? chars.find(c => c.id === selectedCharId) : null;
|
||||
|
||||
// Prepend selected character name if any
|
||||
let actionText = text;
|
||||
if (sel) actionText = `${sel.name}: ${text}`;
|
||||
|
||||
// Optimistic display
|
||||
const div = document.createElement('div');
|
||||
div.className = 'msg player';
|
||||
div.innerHTML = `<div class="msg-label">⚔️ Azione</div><div class="msg-bubble">${escapeHtml(text)}</div>`;
|
||||
const label = sel ? `⚔️ ${sel.name}` : '⚔️ Azione';
|
||||
div.innerHTML = `<div class="msg-label">${label}</div><div class="msg-bubble">${escapeHtml(text)}</div>`;
|
||||
chat.appendChild(div);
|
||||
scrollChat();
|
||||
|
||||
ws.send(JSON.stringify({ type: 'action', payload: text }));
|
||||
ws.send(JSON.stringify({ type: 'action', payload: actionText }));
|
||||
input.value = '';
|
||||
input.focus();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user