mirror of
https://github.com/nuttylmao/nutty.gg.git
synced 2026-09-19 04:00:59 -04:00
Settings page now persists on reloads + added a "Load Defaults" button
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -417,3 +473,12 @@ window.addEventListener('message', (event) => {
|
|||||||
unmuteLabel.style.display = 'none';
|
unmuteLabel.style.display = 'none';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Load settings from local storage
|
||||||
|
LoadSettingsFromStorage();
|
||||||
|
|
||||||
|
// Load default settings
|
||||||
|
LoadJSON(settingsJson);
|
||||||
@@ -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%;
|
||||||
|
|||||||
Reference in New Issue
Block a user