mirror of
https://github.com/nuttylmao/nutty.gg.git
synced 2026-09-19 04:00:59 -04:00
Added "Font" suggestions
This commit is contained in:
@@ -170,6 +170,24 @@ function LoadJSON(settingsJson) {
|
||||
inputElement.setAttribute('list', 'streamer-bot-actions');
|
||||
inputElement.autocomplete = 'off';
|
||||
break;
|
||||
case 'font':
|
||||
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', 'fonts');
|
||||
inputElement.autocomplete = 'off';
|
||||
|
||||
// Trigger permission prompt and load fonts on first click/focus
|
||||
inputElement.addEventListener('focus', async function loadOnce() {
|
||||
// Remove listener so it only triggers once per session
|
||||
inputElement.removeEventListener('focus', loadOnce);
|
||||
inputElement.placeholder = 'Type to search...';
|
||||
|
||||
await PopulateFontDatalist();
|
||||
}, { once: true });
|
||||
break;
|
||||
case 'button':
|
||||
inputElement = document.createElement('button');
|
||||
inputElement.id = setting.id; //Added setting ID
|
||||
@@ -377,6 +395,38 @@ async function GetSBActions() {
|
||||
document.body.appendChild(datalistElement);
|
||||
}
|
||||
|
||||
async function PopulateFontDatalist() {
|
||||
if (!('queryLocalFonts' in window)) {
|
||||
console.warn("Local Font Access API is not supported in this browser. Font auto-suggestions will be disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Request permission and fetch local fonts
|
||||
const availableFonts = await window.queryLocalFonts();
|
||||
|
||||
// Extract unique font family names and sort them alphabetically
|
||||
const fontFamilies = [...new Set(availableFonts.map(font => font.family))].sort();
|
||||
|
||||
// Create the datalist element
|
||||
const datalistElement = document.createElement('datalist');
|
||||
datalistElement.id = 'fonts';
|
||||
|
||||
// Append each font family as an option
|
||||
fontFamilies.forEach(family => {
|
||||
const option = document.createElement('option');
|
||||
option.value = family;
|
||||
datalistElement.appendChild(option);
|
||||
});
|
||||
|
||||
document.body.appendChild(datalistElement);
|
||||
console.debug(`Loaded ${fontFamilies.length} local fonts into auto-suggest.`);
|
||||
|
||||
} catch (err) {
|
||||
console.error("Permission denied or error fetching local fonts:", err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////
|
||||
@@ -483,56 +533,56 @@ window.addEventListener('message', (event) => {
|
||||
});
|
||||
|
||||
function GetSettingDepth(setting, allSettings) {
|
||||
let depth = 0;
|
||||
let current = setting;
|
||||
let depth = 0;
|
||||
let current = setting;
|
||||
|
||||
while (current.showIf) {
|
||||
depth++;
|
||||
current = allSettings.find(s => s.id === current.showIf) || {};
|
||||
}
|
||||
while (current.showIf) {
|
||||
depth++;
|
||||
current = allSettings.find(s => s.id === current.showIf) || {};
|
||||
}
|
||||
|
||||
return depth;
|
||||
return depth;
|
||||
}
|
||||
|
||||
function InterpolatePlaceholders() {
|
||||
// Regex to match anything inside curly braces, e.g., {smtcBridgeAddress}
|
||||
const tokenRegex = /\{([^}]+)\}/g;
|
||||
// Regex to match anything inside curly braces, e.g., {smtcBridgeAddress}
|
||||
const tokenRegex = /\{([^}]+)\}/g;
|
||||
|
||||
// Iterate over all settings from the original JSON in memory
|
||||
settingsData.settings.forEach(setting => {
|
||||
|
||||
// Only process settings that actually have a placeholder in their description
|
||||
if (setting.description && setting.description.includes('{')) {
|
||||
|
||||
// Start with the original untouched description from the JSON
|
||||
let dynamicHTML = setting.description;
|
||||
let match;
|
||||
// Iterate over all settings from the original JSON in memory
|
||||
settingsData.settings.forEach(setting => {
|
||||
|
||||
// Reset regex state (required when reusing a global regex in a loop)
|
||||
tokenRegex.lastIndex = 0;
|
||||
// Only process settings that actually have a placeholder in their description
|
||||
if (setting.description && setting.description.includes('{')) {
|
||||
|
||||
// Find all {tokens} in the string
|
||||
while ((match = tokenRegex.exec(setting.description)) !== null) {
|
||||
const targetId = match[1]; // The exact text inside the braces
|
||||
const targetInput = document.getElementById(targetId);
|
||||
// Start with the original untouched description from the JSON
|
||||
let dynamicHTML = setting.description;
|
||||
let match;
|
||||
|
||||
if (targetInput) {
|
||||
// Get current value, or fallback to the JSON default if the box is empty
|
||||
const fallback = settingsData.settings.find(s => s.id === targetId)?.defaultValue || '';
|
||||
const currentValue = targetInput.value || fallback;
|
||||
|
||||
// Replace the token with the actual value in our temporary string
|
||||
dynamicHTML = dynamicHTML.replace(match[0], currentValue);
|
||||
}
|
||||
}
|
||||
// Reset regex state (required when reusing a global regex in a loop)
|
||||
tokenRegex.lastIndex = 0;
|
||||
|
||||
// Find the specific <p> tag for this setting in the DOM and overwrite its HTML
|
||||
const descriptionParagraph = document.querySelector(`#item-${setting.id} p`);
|
||||
if (descriptionParagraph) {
|
||||
descriptionParagraph.innerHTML = dynamicHTML;
|
||||
}
|
||||
}
|
||||
});
|
||||
// Find all {tokens} in the string
|
||||
while ((match = tokenRegex.exec(setting.description)) !== null) {
|
||||
const targetId = match[1]; // The exact text inside the braces
|
||||
const targetInput = document.getElementById(targetId);
|
||||
|
||||
if (targetInput) {
|
||||
// Get current value, or fallback to the JSON default if the box is empty
|
||||
const fallback = settingsData.settings.find(s => s.id === targetId)?.defaultValue || '';
|
||||
const currentValue = targetInput.value || fallback;
|
||||
|
||||
// Replace the token with the actual value in our temporary string
|
||||
dynamicHTML = dynamicHTML.replace(match[0], currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the specific <p> tag for this setting in the DOM and overwrite its HTML
|
||||
const descriptionParagraph = document.querySelector(`#item-${setting.id} p`);
|
||||
if (descriptionParagraph) {
|
||||
descriptionParagraph.innerHTML = dynamicHTML;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -542,4 +592,7 @@ function InterpolatePlaceholders() {
|
||||
LoadSettingsFromStorage();
|
||||
|
||||
// Load default settings
|
||||
LoadJSON(settingsJson);
|
||||
LoadJSON(settingsJson);
|
||||
|
||||
// Populate local fonts for auto-suggest
|
||||
PopulateFontDatalist();
|
||||
@@ -20,8 +20,8 @@
|
||||
{
|
||||
"id": "line1Font",
|
||||
"label": "Font",
|
||||
"description": "",
|
||||
"type": "text",
|
||||
"description": "<a href=\"ms-settings:fonts\">Check installed fonts</a>",
|
||||
"type": "font",
|
||||
"defaultValue": "",
|
||||
"showIf": "enableLine1",
|
||||
"group": "Appearance"
|
||||
@@ -112,8 +112,8 @@
|
||||
{
|
||||
"id": "line2Font",
|
||||
"label": "Font",
|
||||
"description": "",
|
||||
"type": "text",
|
||||
"description": "<a href=\"ms-settings:fonts\">Check installed PC fonts</a>",
|
||||
"type": "font",
|
||||
"defaultValue": "",
|
||||
"showIf": "enableLine2",
|
||||
"group": "Appearance"
|
||||
@@ -204,7 +204,7 @@
|
||||
{
|
||||
"id": "line3Font",
|
||||
"label": "Font",
|
||||
"description": "",
|
||||
"description": "<a href=\"ms-settings:fonts\">Check installed PC fonts</a>",
|
||||
"type": "text",
|
||||
"defaultValue": "",
|
||||
"showIf": "enableLine3",
|
||||
|
||||
Reference in New Issue
Block a user