feat: make Web UI mood dropdowns Evil Mode-aware
- Disable per-server mood controls when Evil Miku is active - Show explanatory notice for disabled server mood dropdowns - Populate global mood dropdown with evil moods when Evil Mode is on - Fix initialization race condition by awaiting evil mode status first - Add CSS styles for disabled mood controls
This commit is contained in:
@@ -915,3 +915,20 @@ body.evil-mode [style*="color: rgb(0, 123, 255)"] {
|
||||
color: #888;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Disabled mood controls (Evil Miku per-server mood lockout) */
|
||||
.server-mood-controls select:disabled,
|
||||
.server-mood-controls button:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
background: #2a2a2a;
|
||||
border-color: #444;
|
||||
}
|
||||
.evil-mode-exempt-notice {
|
||||
color: #888;
|
||||
font-size: 0.85rem;
|
||||
font-style: italic;
|
||||
margin-top: 0.5rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ async function loadProfilePictureMetadata() {
|
||||
// DOMContentLoaded — main initialization
|
||||
// ============================================================================
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
initTabState();
|
||||
initTabWheelScroll();
|
||||
initLogsScrollDetection();
|
||||
@@ -391,12 +391,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
initModalAccessibility();
|
||||
initPromptSourceToggle();
|
||||
|
||||
// Load evil mode status FIRST so mood dropdowns populate with the correct list
|
||||
await checkEvilModeStatus();
|
||||
|
||||
loadStatus();
|
||||
loadServers();
|
||||
populateMoodDropdowns();
|
||||
loadServers(); // internally calls populateMoodDropdowns() with correct evilMode
|
||||
loadLastPrompt();
|
||||
loadLogs();
|
||||
checkEvilModeStatus();
|
||||
checkBipolarModeStatus();
|
||||
checkGPUStatus();
|
||||
refreshLanguageStatus();
|
||||
|
||||
@@ -90,6 +90,9 @@ function updateEvilModeUI() {
|
||||
}
|
||||
|
||||
updateBipolarToggleVisibility();
|
||||
|
||||
// Update per-server mood controls to reflect evil mode state
|
||||
populateMoodDropdowns();
|
||||
}
|
||||
|
||||
// ===== GPU Selection Management =====
|
||||
|
||||
@@ -80,13 +80,16 @@ function displayServers() {
|
||||
<h4 style="margin: 0 0 0.5rem 0; color: #61dafb;">Server Mood</h4>
|
||||
<div><strong>Current Mood:</strong> ${server.current_mood_name || 'neutral'} ${MOOD_EMOJIS[server.current_mood_name] || ''}</div>
|
||||
<div><strong>Sleeping:</strong> ${server.is_sleeping ? 'Yes' : 'No'}</div>
|
||||
<div style="margin-top: 0.5rem;">
|
||||
<div class="server-mood-controls" style="margin-top: 0.5rem;">
|
||||
<select id="mood-select-${String(server.guild_id)}" style="margin-right: 0.5rem; padding: 0.3rem; background: #333; color: white; border: 1px solid #555; border-radius: 3px;">
|
||||
<option value="">Select Mood...</option>
|
||||
</select>
|
||||
<button onclick="setServerMood('${String(server.guild_id)}')" style="margin-right: 0.5rem;">Change Mood</button>
|
||||
<button onclick="resetServerMood('${String(server.guild_id)}')" style="background: #ff9800;">Reset Mood</button>
|
||||
</div>
|
||||
<div class="evil-mode-exempt-notice" id="evil-notice-${String(server.guild_id)}" style="display: none;">
|
||||
⚠️ Per-server moods are unavailable while Evil Miku is active — she applies her global mood everywhere.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
@@ -375,7 +378,7 @@ async function repairConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
// Populate mood dropdowns with available moods
|
||||
// Populate mood dropdowns with available moods (Evil Mode-aware)
|
||||
async function populateMoodDropdowns() {
|
||||
try {
|
||||
console.log('🎭 Loading available moods...');
|
||||
@@ -384,17 +387,28 @@ async function populateMoodDropdowns() {
|
||||
|
||||
if (data.moods) {
|
||||
console.log(`🎭 Found ${data.moods.length} moods:`, data.moods);
|
||||
const emojiMap = evilMode ? EVIL_MOOD_EMOJIS : MOOD_EMOJIS;
|
||||
|
||||
// Determine which mood list to use based on evil mode
|
||||
let moodList = data.moods;
|
||||
let emojiMap = MOOD_EMOJIS;
|
||||
let defaultMood = 'neutral';
|
||||
|
||||
if (evilMode) {
|
||||
// Evil Miku uses evil moods for the global DM dropdown
|
||||
moodList = Object.keys(EVIL_MOOD_EMOJIS);
|
||||
emojiMap = EVIL_MOOD_EMOJIS;
|
||||
defaultMood = 'evil_neutral';
|
||||
}
|
||||
|
||||
// Populate the DM mood dropdown (#mood on tab1)
|
||||
const dmMoodSelect = document.getElementById('mood');
|
||||
if (dmMoodSelect) {
|
||||
dmMoodSelect.innerHTML = '';
|
||||
data.moods.forEach(mood => {
|
||||
moodList.forEach(mood => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = mood;
|
||||
opt.textContent = `${emojiMap[mood] || ''} ${mood}`.trim();
|
||||
if (mood === 'neutral') opt.selected = true;
|
||||
if (mood === defaultMood) opt.selected = true;
|
||||
dmMoodSelect.appendChild(opt);
|
||||
});
|
||||
}
|
||||
@@ -403,32 +417,17 @@ async function populateMoodDropdowns() {
|
||||
const chatMoodSelect = document.getElementById('chat-mood-select');
|
||||
if (chatMoodSelect) {
|
||||
chatMoodSelect.innerHTML = '';
|
||||
data.moods.forEach(mood => {
|
||||
moodList.forEach(mood => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = mood;
|
||||
opt.textContent = `${emojiMap[mood] || ''} ${mood}`.trim();
|
||||
if (mood === 'neutral') opt.selected = true;
|
||||
if (mood === defaultMood) opt.selected = true;
|
||||
chatMoodSelect.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
// Populate per-server mood dropdowns (mood-select-{guildId})
|
||||
document.querySelectorAll('[id^="mood-select-"]').forEach(select => {
|
||||
// Keep only the first option ("Select Mood...")
|
||||
while (select.children.length > 1) {
|
||||
select.removeChild(select.lastChild);
|
||||
}
|
||||
});
|
||||
|
||||
data.moods.forEach(mood => {
|
||||
const moodOption = document.createElement('option');
|
||||
moodOption.value = mood;
|
||||
moodOption.textContent = `${mood} ${emojiMap[mood] || ''}`;
|
||||
|
||||
document.querySelectorAll('[id^="mood-select-"]').forEach(select => {
|
||||
select.appendChild(moodOption.cloneNode(true));
|
||||
});
|
||||
});
|
||||
// Update per-server mood controls based on evil mode state
|
||||
updatePerServerMoodControls(data.moods, MOOD_EMOJIS);
|
||||
|
||||
console.log('🎭 All mood dropdowns populated successfully');
|
||||
} else {
|
||||
@@ -439,6 +438,70 @@ async function populateMoodDropdowns() {
|
||||
}
|
||||
}
|
||||
|
||||
// Update per-server mood controls: enable/disable based on evil mode
|
||||
function updatePerServerMoodControls(regularMoods, regularEmojiMap) {
|
||||
const serverSelects = document.querySelectorAll('[id^="mood-select-"]');
|
||||
|
||||
if (evilMode) {
|
||||
// Evil Miku is active — disable per-server mood controls
|
||||
serverSelects.forEach(select => {
|
||||
const guildId = select.id.replace('mood-select-', '');
|
||||
const controlsDiv = select.closest('.server-mood-controls');
|
||||
const noticeDiv = document.getElementById(`evil-notice-${guildId}`);
|
||||
|
||||
// Disable the select
|
||||
select.disabled = true;
|
||||
|
||||
// Disable buttons in the same controls div
|
||||
if (controlsDiv) {
|
||||
controlsDiv.querySelectorAll('button').forEach(btn => {
|
||||
btn.disabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Show the explanation notice
|
||||
if (noticeDiv) {
|
||||
noticeDiv.style.display = 'block';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Normal mode — enable per-server mood controls and populate with regular moods
|
||||
serverSelects.forEach(select => {
|
||||
const guildId = select.id.replace('mood-select-', '');
|
||||
const controlsDiv = select.closest('.server-mood-controls');
|
||||
const noticeDiv = document.getElementById(`evil-notice-${guildId}`);
|
||||
|
||||
// Enable the select
|
||||
select.disabled = false;
|
||||
|
||||
// Enable buttons in the same controls div
|
||||
if (controlsDiv) {
|
||||
controlsDiv.querySelectorAll('button').forEach(btn => {
|
||||
btn.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Hide the explanation notice
|
||||
if (noticeDiv) {
|
||||
noticeDiv.style.display = 'none';
|
||||
}
|
||||
|
||||
// Populate with regular moods
|
||||
// Keep only the first option ("Select Mood...")
|
||||
while (select.children.length > 1) {
|
||||
select.removeChild(select.lastChild);
|
||||
}
|
||||
|
||||
regularMoods.forEach(mood => {
|
||||
const moodOption = document.createElement('option');
|
||||
moodOption.value = mood;
|
||||
moodOption.textContent = `${mood} ${regularEmojiMap[mood] || ''}`;
|
||||
select.appendChild(moodOption);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Per-Server Mood Management
|
||||
async function setServerMood(guildId) {
|
||||
console.log(`🎭 setServerMood called with guildId: ${guildId} (type: ${typeof guildId})`);
|
||||
|
||||
Reference in New Issue
Block a user