mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Theme Saver
This commit is contained in:
@ -1203,14 +1203,9 @@
|
||||
|
||||
</div>
|
||||
<div class="flex-container flexnowrap alignitemscenter">
|
||||
<select id="main_api" class="margin0 margin-r5">
|
||||
<option value="###">Coming Soon</option>
|
||||
<option value="###">Don't Do</option>
|
||||
<option value="###">Anything Yet</option>
|
||||
<option value="###">Feature Currently</option>
|
||||
<option value="###">Under Construction</option>
|
||||
<select id="themes" class="margin0 margin-r5">
|
||||
</select>
|
||||
<div id="ui-preset-save-button" class="menu_button padding5 margin0">+</div>
|
||||
<div id="ui-preset-save-button" title="Save changes to a new theme file" class="menu_button padding5 margin0">+</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2612,7 +2612,7 @@ async function getSettings(type) {
|
||||
loadPoeSettings(settings);
|
||||
|
||||
// Load power user settings
|
||||
loadPowerUserSettings(settings);
|
||||
loadPowerUserSettings(settings, data);
|
||||
|
||||
|
||||
//Enable GUI deference settings if GUI is selected for Kobold
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { saveSettingsDebounced, characters } from "../script.js";
|
||||
import { delay, debounce } from "./utils.js";
|
||||
import { saveSettingsDebounced, characters, callPopup, token } from "../script.js";
|
||||
import { delay } from "./utils.js";
|
||||
|
||||
|
||||
export {
|
||||
@ -52,19 +52,13 @@ let power_user = {
|
||||
blur_tint_color: `${getComputedStyle(document.documentElement).getPropertyValue('--SmartThemeBlurTintColor').trim()}`,
|
||||
|
||||
waifuMode: false,
|
||||
theme: 'Default (Dark)',
|
||||
};
|
||||
|
||||
let themes = [];
|
||||
|
||||
const storage_keys = {
|
||||
collapse_newlines: "TavernAI_collapse_newlines",
|
||||
force_pygmalion_formatting: "TavernAI_force_pygmalion_formatting",
|
||||
pin_examples: "TavernAI_pin_examples",
|
||||
disable_description_formatting: "TavernAI_disable_description_formatting",
|
||||
disable_scenario_formatting: "TavernAI_disable_scenario_formatting",
|
||||
disable_personality_formatting: "TavernAI_disable_personality_formatting",
|
||||
always_force_name2: "TavernAI_always_force_name2",
|
||||
custom_chat_separator: "TavernAI_custom_chat_separator",
|
||||
fast_ui_mode: "TavernAI_fast_ui_mode",
|
||||
multigen: "TavernAI_multigen",
|
||||
avatar_style: "TavernAI_avatar_style",
|
||||
chat_display: "TavernAI_chat_display",
|
||||
sheld_width: "TavernAI_sheld_width",
|
||||
@ -207,6 +201,39 @@ async function applyFontScale() {
|
||||
chat.style.transition = chatTransition;
|
||||
}
|
||||
|
||||
async function applyTheme(name) {
|
||||
const theme = themes.find(x => x.name == name);
|
||||
|
||||
if (!theme) {
|
||||
return;
|
||||
}
|
||||
|
||||
const themeProperties = [
|
||||
{ key: 'main_text_color', selector: '#main-text-color-picker', type: 'main' },
|
||||
{ key: 'italics_text_color', selector: '#italics-color-picker', type: 'italics' },
|
||||
{ key: 'fastui_bg_color', selector: '#fastui-bg-color-picker', type: 'fastUIBG' },
|
||||
{ key: 'blur_tint_color', selector: '#blur-tint-color-picker', type: 'blurTint' },
|
||||
{
|
||||
key: 'blur_strength',
|
||||
action: async () => {
|
||||
localStorage.setItem(storage_keys.blur_strength, power_user.blur_strength);
|
||||
await applyBlurStrength();
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
for (const { key, selector, type, action } of themeProperties) {
|
||||
if (theme[key] !== undefined) {
|
||||
power_user[key] = theme[key];
|
||||
if (selector) $(selector).attr('color', power_user[key]);
|
||||
if (type) await applyThemeColor(type);
|
||||
if (action) await action();
|
||||
}
|
||||
}
|
||||
|
||||
console.log('theme applied: ' + name);
|
||||
}
|
||||
|
||||
applyAvatarStyle();
|
||||
switchUiMode();
|
||||
applyChatDisplay();
|
||||
@ -216,28 +243,16 @@ applyBlurStrength();
|
||||
applyThemeColor();
|
||||
switchWaifuMode()
|
||||
|
||||
// TODO delete in next release
|
||||
function loadFromLocalStorage() {
|
||||
power_user.collapse_newlines = localStorage.getItem(storage_keys.collapse_newlines) == "true";
|
||||
power_user.force_pygmalion_formatting = localStorage.getItem(storage_keys.force_pygmalion_formatting) == "true";
|
||||
power_user.pin_examples = localStorage.getItem(storage_keys.pin_examples) == "true";
|
||||
power_user.disable_description_formatting = localStorage.getItem(storage_keys.disable_description_formatting) == "true";
|
||||
power_user.disable_scenario_formatting = localStorage.getItem(storage_keys.disable_scenario_formatting) == "true";
|
||||
power_user.disable_personality_formatting = localStorage.getItem(storage_keys.disable_personality_formatting) == "true";
|
||||
power_user.always_force_name2 = localStorage.getItem(storage_keys.always_force_name2) == "true";
|
||||
power_user.custom_chat_separator = localStorage.getItem(storage_keys.custom_chat_separator);
|
||||
power_user.multigen = localStorage.getItem(storage_keys.multigen) == "true";
|
||||
}
|
||||
|
||||
function loadPowerUserSettings(settings) {
|
||||
// Migrate legacy settings
|
||||
loadFromLocalStorage();
|
||||
|
||||
// Now do it properly from settings.json
|
||||
function loadPowerUserSettings(settings, data) {
|
||||
// Load from settings.json
|
||||
if (settings.power_user !== undefined) {
|
||||
Object.assign(power_user, settings.power_user);
|
||||
}
|
||||
|
||||
if (data.themes !== undefined) {
|
||||
themes = data.themes;
|
||||
}
|
||||
|
||||
// These are still local storage
|
||||
const fastUi = localStorage.getItem(storage_keys.fast_ui_mode);
|
||||
const waifuMode = localStorage.getItem(storage_keys.waifuMode);
|
||||
@ -266,16 +281,23 @@ function loadPowerUserSettings(settings) {
|
||||
$(`input[name="chat_display"][value="${power_user.chat_display}"]`).prop("checked", true);
|
||||
$(`input[name="sheld_width"][value="${power_user.sheld_width}"]`).prop("checked", true);
|
||||
$("#font_scale").val(power_user.font_scale);
|
||||
$("#font_scale_counter").html(power_user.font_scale);
|
||||
$("#font_scale_counter").text(power_user.font_scale);
|
||||
|
||||
$("#blur_strength").val(power_user.blur_strength);
|
||||
$("#blur_strength_counter").html(power_user.blur_strength);
|
||||
$("#blur_strength_counter").text(power_user.blur_strength);
|
||||
|
||||
$("#main-text-color-picker").attr('color', power_user.main_text_color);
|
||||
$("#italics-color-picker").attr('color', power_user.italics_text_color);
|
||||
$("#fastui-bg-color-picker").attr('color', power_user.fastui_bg_color);
|
||||
$("#blur-tint-color-picker").attr('color', power_user.blur_tint_color);
|
||||
|
||||
for (const theme of themes) {
|
||||
const option = document.createElement('option');
|
||||
option.value = theme.name;
|
||||
option.innerText = theme.name;
|
||||
option.selected = theme.name == power_user.theme;
|
||||
$("#themes").append(option);
|
||||
}
|
||||
|
||||
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
|
||||
sortCharactersList();
|
||||
@ -415,6 +437,58 @@ $(document).ready(() => {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#themes").on('change', function () {
|
||||
const themeSelected = $(this).find(':selected').val();
|
||||
power_user.theme = themeSelected;
|
||||
applyTheme(themeSelected);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#ui-preset-save-button").on('click', async function () {
|
||||
const name = await callPopup('Name him, name your son:', 'input');
|
||||
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
const theme = {
|
||||
name,
|
||||
blur_strength: power_user.blur_strength,
|
||||
main_text_color: power_user.main_text_color,
|
||||
italics_text_color: power_user.italics_text_color,
|
||||
fastui_bg_color: power_user.fastui_bg_color,
|
||||
blur_tint_color: power_user.blur_tint_color,
|
||||
};
|
||||
|
||||
const response = await fetch('/savetheme', {
|
||||
method: 'POST', headers: {
|
||||
'X-CSRF-Token': token,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(theme)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const themeIndex = themes.findIndex(x => x.name == name);
|
||||
|
||||
if (themeIndex == -1) {
|
||||
themes.push(theme);
|
||||
const option = document.createElement('option');
|
||||
option.selected = true;
|
||||
option.value = name;
|
||||
option.innerText = name;
|
||||
$('#themes').append(option);
|
||||
}
|
||||
else {
|
||||
themes[themeIndex] = theme;
|
||||
$(`#themes option[value="${name}"]`).attr('selected', true);
|
||||
}
|
||||
|
||||
power_user.theme = name;
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
});
|
||||
|
||||
$("#play_message_sound").on('input', function () {
|
||||
power_user.play_message_sound = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
|
8
public/themes/Aqua Blue.json
Normal file
8
public/themes/Aqua Blue.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Aqua Blue",
|
||||
"blur_strength": 2,
|
||||
"main_text_color": "rgba(160, 190, 190, 1)",
|
||||
"italics_text_color": "rgba(170, 200, 200, 1)",
|
||||
"fastui_bg_color": "rgba(7, 54, 66, 0.9)",
|
||||
"blur_tint_color": "rgba(0, 43, 54, 0.8)"
|
||||
}
|
8
public/themes/Default (Dark).json
Normal file
8
public/themes/Default (Dark).json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Default (Dark)",
|
||||
"blur_strength": 10,
|
||||
"main_text_color": "rgb(220, 220, 210)",
|
||||
"italics_text_color": "rgb(175, 175, 175)",
|
||||
"fastui_bg_color": "rgba(0, 0, 0, 0.9)",
|
||||
"blur_tint_color": "rgba(0, 0, 0, 0.5)"
|
||||
}
|
8
public/themes/Megumin Red.json
Normal file
8
public/themes/Megumin Red.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Megumin Red",
|
||||
"blur_strength": 10,
|
||||
"main_text_color": "rgba(230, 230, 230, 1)",
|
||||
"italics_text_color": "rgba(200, 200, 200, 1)",
|
||||
"fastui_bg_color": "rgba(70, 5, 5, 0.9)",
|
||||
"blur_tint_color": "rgba(50, 10, 10, 0.75)"
|
||||
}
|
38
server.js
38
server.js
@ -117,6 +117,7 @@ const directories = {
|
||||
thumbnails: 'thumbnails/',
|
||||
thumbnailsBg: 'thumbnails/bg/',
|
||||
thumbnailsAvatar: 'thumbnails/avatar/',
|
||||
themes: 'public/themes',
|
||||
};
|
||||
|
||||
// CSRF Protection //
|
||||
@ -1037,6 +1038,7 @@ app.post('/getsettings', jsonParser, (request, response) => { //Wintermute's cod
|
||||
const openai_setting_names = [];
|
||||
const textgenerationwebui_presets = [];
|
||||
const textgenerationwebui_preset_names = [];
|
||||
const themes = [];
|
||||
const settings = fs.readFileSync('public/settings.json', 'utf8', (err, data) => {
|
||||
if (err) return response.sendStatus(500);
|
||||
|
||||
@ -1139,6 +1141,30 @@ app.post('/getsettings', jsonParser, (request, response) => { //Wintermute's cod
|
||||
textgenerationwebui_preset_names.push(item.replace(/\.[^/.]+$/, ''));
|
||||
});
|
||||
|
||||
// Theme files
|
||||
const themeFiles = fs
|
||||
.readdirSync(directories.themes)
|
||||
.filter(x => path.parse(x).ext == '.json')
|
||||
.sort();
|
||||
|
||||
themeFiles.forEach(item => {
|
||||
const file = fs.readFileSync(
|
||||
path.join(directories.themes, item),
|
||||
'utf-8',
|
||||
(err, data) => {
|
||||
if (err) return response.sendStatus(500);
|
||||
return data;
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
themes.push(json5.parse(file));
|
||||
}
|
||||
catch {
|
||||
// skip
|
||||
}
|
||||
})
|
||||
|
||||
response.send({
|
||||
settings,
|
||||
koboldai_settings,
|
||||
@ -1150,6 +1176,7 @@ app.post('/getsettings', jsonParser, (request, response) => { //Wintermute's cod
|
||||
openai_setting_names,
|
||||
textgenerationwebui_presets,
|
||||
textgenerationwebui_preset_names,
|
||||
themes,
|
||||
enable_extensions: enableExtensions,
|
||||
});
|
||||
});
|
||||
@ -1182,6 +1209,17 @@ app.post('/deleteworldinfo', jsonParser, (request, response) => {
|
||||
return response.sendStatus(200);
|
||||
});
|
||||
|
||||
app.post('/savetheme', jsonParser, (request, response) => {
|
||||
if (!request.body || !request.body.name) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
|
||||
const filename = path.join(directories.themes, sanitize(request.body.name) + '.json');
|
||||
fs.writeFileSync(filename, JSON.stringify(request.body), 'utf8');
|
||||
|
||||
return response.sendStatus(200);
|
||||
});
|
||||
|
||||
function readWorldInfoFile(worldInfoName) {
|
||||
if (!worldInfoName) {
|
||||
return { entries: {} };
|
||||
|
Reference in New Issue
Block a user