Settings page now persists on reloads + added a "Load Defaults" button

This commit is contained in:
nuttylmao
2025-05-07 03:32:37 +10:00
parent b9152ed12d
commit 74f8196d7d
3 changed files with 240 additions and 161 deletions
@@ -18,6 +18,7 @@
<span id="urlLabel">Click to copy URL</span> <span id="urlLabel">Click to copy URL</span>
<input id="widgetUrlInput" type="text" readonly onclick="CopyURLToClipboard()"> <input id="widgetUrlInput" type="text" readonly onclick="CopyURLToClipboard()">
</div> </div>
<button id="loadDefaultsButton" onclick="OpenLoadDefaultsPopup()">Load Default Settings</button>
<button id="loadSettingsButton" onclick="OpenLoadSettingsPopup()">Load Settings</button> <button id="loadSettingsButton" onclick="OpenLoadSettingsPopup()">Load Settings</button>
</div> </div>
@@ -48,6 +49,17 @@
</div> </div>
</div> </div>
</div> </div>
<div id="loadDefaultsWrapper">
<div id="loadDefaultsContainer">
<h2>Load Defaults</h2>
<label style="font-size: 0.8em;">Are you sure?</label>
<div style="display: flex; gap: 20px">
<button id="cancelDefaultsButton" onclick="CloseDefaultsPopup()">No</button>
<button style="background-color: var(--accent-color);" onclick="LoadDefaultSettings()">Yes</button>
</div>
</div>
</div>
</body> </body>
</html> </html>
+224 -159
View File
@@ -12,10 +12,14 @@ const urlLabel = document.getElementById('urlLabel');
const settingsPanel = document.getElementById('settingsPanel'); const settingsPanel = document.getElementById('settingsPanel');
const widgetPreview = document.getElementById('widgetPreview'); const widgetPreview = document.getElementById('widgetPreview');
const loadURLBox = document.getElementById('loadUrlBox'); const loadURLBox = document.getElementById('loadUrlBox');
const cancelSettingsButton = document.getElementById('cancelSettingsButton'); const loadDefaultsBox = document.getElementById('loadDefaultsWrapper');
const loadSettingsBox = document.getElementById('loadSettingsWrapper'); const loadSettingsBox = document.getElementById('loadSettingsWrapper');
const unmuteLabel = document.getElementById('unmute-label'); const unmuteLabel = document.getElementById('unmute-label');
// Global variables
let settingsMap = new Map();
// Set visibility of the unmute indicator
if (showUnmuteIndicator) if (showUnmuteIndicator)
unmuteLabel.style.display = 'inline'; unmuteLabel.style.display = 'inline';
@@ -25,184 +29,226 @@ if (showUnmuteIndicator)
// LOAD FROM SETTINGS.JSON // // LOAD FROM SETTINGS.JSON //
///////////////////////////// /////////////////////////////
fetch(settingsJson) function LoadJSON(settingsJson) {
.then(response => response.json()) fetch(settingsJson)
.then(data => { .then(response => response.json())
const groupedSettings = {}; .then(data => {
// Clear the settings panel
settingsPanel.innerHTML = '';
// Group settings by their 'group' property const groupedSettings = {};
data.settings.forEach(setting => {
if (!groupedSettings[setting.group]) {
groupedSettings[setting.group] = [];
}
groupedSettings[setting.group].push(setting);
});
// Render settings for each group // Group settings by their 'group' property
for (const groupName in groupedSettings) { data.settings.forEach(setting => {
const groupDiv = document.createElement('div'); if (!groupedSettings[setting.group]) {
groupDiv.classList.add('setting-group'); groupedSettings[setting.group] = [];
const groupHeader = document.createElement('h2');
groupHeader.textContent = groupName;
groupDiv.appendChild(groupHeader);
groupedSettings[groupName].forEach(setting => {
const settingItem = document.createElement('div');
settingItem.classList.add('setting-item');
settingItem.id = `item-${setting.id}`;
const labelDescriptionDiv = document.createElement('div');
if (setting.label) {
const label = document.createElement('label');
label.textContent = setting.label;
labelDescriptionDiv.appendChild(label);
} }
groupedSettings[setting.group].push(setting);
});
if (setting.description) { // Render settings for each group
const description = document.createElement('p'); for (const groupName in groupedSettings) {
description.innerHTML = setting.description; const groupDiv = document.createElement('div');
labelDescriptionDiv.appendChild(description); groupDiv.classList.add('setting-group');
}
const settingItemContent = document.createElement('div'); const groupHeader = document.createElement('h2');
settingItemContent.classList.add('setting-item-content'); groupHeader.textContent = groupName;
groupDiv.appendChild(groupHeader);
let inputElement; groupedSettings[groupName].forEach(setting => {
switch (setting.type) { const settingItem = document.createElement('div');
case 'text': settingItem.classList.add('setting-item');
inputElement = document.createElement('input'); settingItem.id = `item-${setting.id}`;
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
break;
case 'checkbox':
const labelDiv = document.createElement('label');
labelDiv.classList.add('switch');
checkBoxElement = document.createElement('input');
checkBoxElement.type = 'checkbox';
checkBoxElement.id = setting.id;
checkBoxElement.checked = setting.defaultValue;
labelDiv.appendChild(checkBoxElement);
const slider = document.createElement('span'); const labelDescriptionDiv = document.createElement('div');
slider.classList.add('slider');
slider.classList.add('round');
labelDiv.appendChild(slider);
// Add event listener to the switchDiv if (setting.label) {
labelDiv.addEventListener('click', () => { const label = document.createElement('label');
checkBoxElement.checked = !checkBoxElement.checked; label.textContent = setting.label;
UpdateSettingItemVisibility(); labelDescriptionDiv.appendChild(label);
}); }
inputElement = labelDiv;
break;
case 'select':
inputElement = document.createElement('select');
inputElement.id = setting.id; //Added setting ID
setting.options.forEach(option => {
const optionElement = document.createElement('option');
optionElement.value = option.value;
optionElement.textContent = option.label;
if (option === setting.defaultValue) {
optionElement.selected = true;
}
inputElement.appendChild(optionElement);
});
inputElement.value = setting.defaultValue;
break;
case 'color':
inputElement = document.createElement('input');
inputElement.type = 'color';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
break;
case 'number':
inputElement = document.createElement('input');
inputElement.type = 'number';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
inputElement.min = setting.min;
inputElement.max = setting.max;
inputElement.step = setting.step;
break;
case 'sb-actions':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.placeholder = 'Type to search...';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
inputElement.setAttribute('list', 'streamer-bot-actions');
inputElement.autocomplete = 'off';
break;
case 'button':
inputElement = document.createElement('button');
inputElement.id = setting.id; //Added setting ID
inputElement.textContent = setting.label;
inputElement.addEventListener('click', () => { if (setting.description) {
widgetPreview.contentWindow[setting.callFunction](); const description = document.createElement('p');
description.innerHTML = setting.description;
labelDescriptionDiv.appendChild(description);
}
const defaultBackgroundColor = "#2e2e2e"; const settingItemContent = document.createElement('div');
const defaultTextColor = "white"; settingItemContent.classList.add('setting-item-content');
inputElement.style.transitionDuration = '0s' let inputElement;
inputElement.style.backgroundColor = "#2196f3" switch (setting.type) {
inputElement.style.color = "#ffffff"; case 'text':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
inputElement.autocomplete = 'new-password';
break;
case 'checkbox':
const labelDiv = document.createElement('label');
labelDiv.classList.add('switch');
checkBoxElement = document.createElement('input');
checkBoxElement.type = 'checkbox';
checkBoxElement.id = setting.id;
checkBoxElement.checked = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
labelDiv.appendChild(checkBoxElement);
setTimeout(() => { const slider = document.createElement('span');
inputElement.style.transitionDuration = '0.2s' slider.classList.add('slider');
inputElement.style.backgroundColor = defaultBackgroundColor; slider.classList.add('round');
inputElement.style.color = defaultTextColor; labelDiv.appendChild(slider);
}, 100);
});
break;
default:
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = setting.defaultValue;
}
inputElement.addEventListener('input', function (event) { // Add event listener to the switchDiv
RefreshWidgetPreview(data); labelDiv.addEventListener('click', () => {
checkBoxElement.checked = !checkBoxElement.checked;
UpdateSettingItemVisibility();
});
inputElement = labelDiv;
break;
case 'select':
inputElement = document.createElement('select');
inputElement.id = setting.id; //Added setting ID
setting.options.forEach(option => {
const optionElement = document.createElement('option');
optionElement.value = option.value;
optionElement.textContent = option.label;
if (option === setting.defaultValue) {
optionElement.selected = true;
}
inputElement.appendChild(optionElement);
});
inputElement.value = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
break;
case 'color':
inputElement = document.createElement('input');
inputElement.type = 'color';
inputElement.id = setting.id; //Added setting ID
inputElement.value = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
break;
case 'number':
inputElement = document.createElement('input');
inputElement.type = 'number';
inputElement.id = setting.id; //Added setting ID
inputElement.value = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
inputElement.min = setting.min;
inputElement.max = setting.max;
inputElement.step = setting.step;
break;
case 'sb-actions':
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.placeholder = 'Type to search...';
inputElement.id = setting.id; //Added setting ID
inputElement.value = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
inputElement.setAttribute('list', 'streamer-bot-actions');
inputElement.autocomplete = 'off';
break;
case 'button':
inputElement = document.createElement('button');
inputElement.id = setting.id; //Added setting ID
inputElement.textContent = setting.label;
inputElement.addEventListener('click', () => {
widgetPreview.contentWindow[setting.callFunction]();
const defaultBackgroundColor = "#2e2e2e";
const defaultTextColor = "white";
inputElement.style.transitionDuration = '0s'
inputElement.style.backgroundColor = "#2196f3"
inputElement.style.color = "#ffffff";
setTimeout(() => {
inputElement.style.transitionDuration = '0.2s'
inputElement.style.backgroundColor = defaultBackgroundColor;
inputElement.style.color = defaultTextColor;
}, 100);
});
break;
default:
inputElement = document.createElement('input');
inputElement.type = 'text';
inputElement.id = setting.id; //Added setting ID
inputElement.value = settingsMap.has(setting.id) ? settingsMap.get(setting.id) : setting.defaultValue;
}
// Save settings to settings map
if (!settingsMap.has(setting.id))
settingsMap.set(setting.id, setting.defaultValue);
// Refresh the preview when any setting changes
inputElement.addEventListener('input', function (event) {
const settingElement = document.getElementById(setting.id);
if (setting.type == 'checkbox')
settingsMap.set(setting.id, settingElement.checked);
else
settingsMap.set(setting.id, settingElement.value);
SaveSettingsToStorage();
RefreshWidgetPreview(data);
});
settingItemContent.appendChild(inputElement);
if (setting.type == 'button') {
settingItem.style.display = 'block'
settingItem.appendChild(settingItemContent);
}
else {
settingItem.appendChild(labelDescriptionDiv);
settingItem.appendChild(settingItemContent);
}
groupDiv.appendChild(settingItem);
}); });
settingItemContent.appendChild(inputElement); settingsPanel.appendChild(groupDiv);
}
if (setting.type == 'button') { function UpdateSettingItemVisibility() {
settingItem.style.display = 'block' data.settings.forEach(setting => {
settingItem.appendChild(settingItemContent); if (setting.showIf) {
} if (!document.getElementById(setting.showIf).checked)
else { document.getElementById(`item-${setting.id}`).style.display = 'none'
settingItem.appendChild(labelDescriptionDiv); else
settingItem.appendChild(settingItemContent); document.getElementById(`item-${setting.id}`).style.display = 'flex'
} }
});
}
groupDiv.appendChild(settingItem); UpdateSettingItemVisibility();
}); RefreshWidgetPreview(data);
SaveSettingsToStorage();
})
.catch(error => console.error('Error loading settings:', error));
}
settingsPanel.appendChild(groupDiv); function SaveSettingsToStorage() {
} console.log(settingsMap);
const settingsArray = Array.from(settingsMap.entries());
const settingsArrayString = JSON.stringify(settingsArray);
localStorage.setItem('settingsMap', settingsArrayString);
}
function UpdateSettingItemVisibility() { function LoadSettingsFromStorage() {
data.settings.forEach(setting => { // Retrieve session rankings from local storage
if (setting.showIf) { const settingsMapString = localStorage.getItem('settingsMap');
if (!document.getElementById(setting.showIf).checked) if (settingsMapString) {
document.getElementById(`item-${setting.id}`).style.display = 'none' const settingsMapArray = JSON.parse(settingsMapString);
else settingsMap = new Map(settingsMapArray);
document.getElementById(`item-${setting.id}`).style.display = 'flex' }
} }
});
}
UpdateSettingItemVisibility();
RefreshWidgetPreview(data);
})
.catch(error => console.error('Error loading settings:', error));
function LoadDefaultSettings() {
localStorage.removeItem('settingsMap');
settingsMap = new Map();
LoadJSON(settingsJson);
loadDefaultsBox.style.visibility = 'hidden';
loadDefaultsBox.style.opacity = 0;
}
function RefreshWidgetPreview(data) { function RefreshWidgetPreview(data) {
const settings = {}; const settings = {};
@@ -330,6 +376,11 @@ function CopyURLToClipboard() {
}, 5000); }, 5000);
} }
function CloseDefaultsPopup() {
loadDefaultsBox.style.visibility = 'hidden';
loadDefaultsBox.style.opacity = 0;
};
function CloseSettings() { function CloseSettings() {
loadSettingsBox.style.visibility = 'hidden'; loadSettingsBox.style.visibility = 'hidden';
loadSettingsBox.style.opacity = 0; loadSettingsBox.style.opacity = 0;
@@ -359,6 +410,11 @@ function OpenMembershipPage() {
window.open("https://nutty.gg/collections/member-exclusive-widgets", '_blank').focus(); window.open("https://nutty.gg/collections/member-exclusive-widgets", '_blank').focus();
} }
function OpenLoadDefaultsPopup() {
loadDefaultsBox.style.visibility = 'visible';
loadDefaultsBox.style.opacity = 1;
}
function OpenLoadSettingsPopup() { function OpenLoadSettingsPopup() {
loadSettingsBox.style.visibility = 'visible'; loadSettingsBox.style.visibility = 'visible';
loadSettingsBox.style.opacity = 1; loadSettingsBox.style.opacity = 1;
@@ -416,4 +472,13 @@ window.addEventListener('message', (event) => {
console.log('Iframe has been interacted with!'); console.log('Iframe has been interacted with!');
unmuteLabel.style.display = 'none'; unmuteLabel.style.display = 'none';
} }
}); });
// Load settings from local storage
LoadSettingsFromStorage();
// Load default settings
LoadJSON(settingsJson);
+4 -2
View File
@@ -329,7 +329,8 @@ button:hover {
cursor: pointer; cursor: pointer;
} }
#loadSettingsWrapper { #loadSettingsWrapper,
#loadDefaultsWrapper {
visibility: hidden; visibility: hidden;
position: absolute; position: absolute;
top: 0; top: 0;
@@ -346,7 +347,8 @@ button:hover {
opacity: 0; opacity: 0;
} }
#loadSettingsContainer { #loadSettingsContainer,
#loadDefaultsContainer {
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 50%;