save/load movingUI Presets

This commit is contained in:
RossAscends
2023-07-16 19:47:11 +09:00
parent 7bfaa97ac7
commit 651774fe5e
5 changed files with 187 additions and 41 deletions

View File

@@ -2295,6 +2295,21 @@
</div> </div>
</div> </div>
</div> </div>
<div id="MovingUI-presets-block" class="flex-container flexFlowColumn">
<h4>
<span data-i18n="MovingUI Preset">MovingUI Preset</span>
</h4>
<div class="flex-container flexnowrap alignitemscenter">
<select id="movingUIPresets" class="margin0 margin-r5">
</select>
<div id="movingui-preset-save-button" title="Save changes to a new MovingUI preset file" data-i18n="[title]Save movingUI changes to a new file" class="menu_button padding5 margin0">
<i class="fa-solid fa-save"></i>
</div>
</div>
<div id="movingUIreset" class="menu_button whitespacenowrap" data-i18n="Reset Panels">
Reset MovingUI
</div>
</div>
</div> </div>
</div> </div>
@@ -2335,17 +2350,6 @@
<option value="2" data-i18n="Document">Single Document</option> <option value="2" data-i18n="Document">Single Document</option>
</select> </select>
</div> </div>
<!-- <div id="sheldWidthToggleBlock">
<span data-i18n="Chat Width (PC):">Chat Width (PC):</span><br>
<label>
<input name="sheld_width" type="radio" value="0" />
800px
</label>
<label>
<input name="sheld_width" type="radio" value="1" />
1000px
</label>
</div> -->
<div> <div>
<label for="play_message_sound" class="checkbox_label"> <label for="play_message_sound" class="checkbox_label">
<input id="play_message_sound" type="checkbox" /> <input id="play_message_sound" type="checkbox" />
@@ -2415,8 +2419,7 @@
</select> </select>
</div> </div>
<div id="movingUIreset" class="menu_button whitespacenowrap" data-i18n="Reset Panels">
Reset Panels</div>
</div> </div>
</div> </div>
@@ -3648,16 +3651,14 @@
</label> </label>
<label> <label>
<input type="radio" name="extension_floating_position" value="1" /> <input type="radio" name="extension_floating_position" value="1" />
In-chat @ Depth <input id="extension_floating_depth" class="text_pole widthUnset" type="number" In-chat @ Depth <input id="extension_floating_depth" class="text_pole widthUnset" type="number" min="0" max="99" />
min="0" max="99" />
</label> </label>
</div> </div>
<!--<label for="extension_floating_interval">In-Chat Insertion Depth</label>--> <!--<label for="extension_floating_interval">In-Chat Insertion Depth</label>-->
<label for="extension_floating_interval">Insertion Frequency</label> <label for="extension_floating_interval">Insertion Frequency</label>
<input id="extension_floating_interval" class="text_pole widthUnset" type="number" min="0" <input id="extension_floating_interval" class="text_pole widthUnset" type="number" min="0" max="999" /><small> (0 = Disable, 1 = Always)</small>
max="999" /><small> (0 = Disable, 1 = Always)</small>
<br> <br>
<span>User inputs until next insertion: <span id="extension_floating_counter">(disabled)</span></span> <span>User inputs until next insertion: <span id="extension_floating_counter">(disabled)</span></span>
@@ -3673,8 +3674,7 @@
<small>Will be automatically added as the author's note for this character. Will be used in groups, but <small>Will be automatically added as the author's note for this character. Will be used in groups, but
can't be modified when a group chat is open.</small> can't be modified when a group chat is open.</small>
<textarea id="extension_floating_chara" class="text_pole" rows="8" maxlength="10000" <textarea id="extension_floating_chara" class="text_pole" rows="8" maxlength="10000" placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
<div class="extension_token_counter"> <div class="extension_token_counter">
Tokens: <span id="extension_floating_chara_token_counter">0</span> Tokens: <span id="extension_floating_chara_token_counter">0</span>
</div> </div>
@@ -3708,8 +3708,7 @@
<div class="inline-drawer-content"> <div class="inline-drawer-content">
<small>Will be automatically added as the Author's Note for all new chats.</small> <small>Will be automatically added as the Author's Note for all new chats.</small>
<textarea id="extension_floating_default" class="text_pole" rows="8" maxlength="10000" <textarea id="extension_floating_default" class="text_pole" rows="8" maxlength="10000" placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
<div class="extension_token_counter"> <div class="extension_token_counter">
Tokens: <span id="extension_floating_default_token_counter">0</span> Tokens: <span id="extension_floating_default_token_counter">0</span>
</div> </div>
@@ -3848,4 +3847,4 @@
</script> </script>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,45 @@
{
"name": "Black Magic Time",
"movingUIState": {
"sheld": {
"top": 488,
"left": 1407,
"right": 1,
"bottom": 4,
"margin": "unset",
"width": 471,
"height": 439
},
"floatingPrompt": {
"width": 369,
"height": 441
},
"right-nav-panel": {
"top": 0,
"left": 1400,
"right": 111,
"bottom": 446,
"margin": "unset",
"width": 479,
"height": 487
},
"WorldInfo": {
"top": 41,
"left": 369,
"right": 642,
"bottom": 51,
"margin": "unset",
"width": 1034,
"height": 858
},
"left-nav-panel": {
"top": 442,
"left": 0,
"right": 1546,
"bottom": 25,
"margin": "unset",
"width": 368,
"height": 483
}
}
}

View File

@@ -0,0 +1,4 @@
{
"name": "Default",
"movingUIState": {}
}

View File

@@ -138,9 +138,11 @@ let power_user = {
waifuMode: false, waifuMode: false,
movingUI: false, movingUI: false,
movingUIState: {}, movingUIState: {},
movingUIPreset: '',
noShadows: false, noShadows: false,
theme: 'Default (Dark) 1.7.1', theme: 'Default (Dark) 1.7.1',
auto_swipe: false, auto_swipe: false,
auto_swipe_minimum_length: 0, auto_swipe_minimum_length: 0,
auto_swipe_blacklist: [], auto_swipe_blacklist: [],
@@ -188,6 +190,7 @@ let power_user = {
}; };
let themes = []; let themes = [];
let movingUIPresets = [];
let instruct_presets = []; let instruct_presets = [];
const storage_keys = { const storage_keys = {
@@ -582,6 +585,20 @@ async function applyTheme(name) {
console.log('theme applied: ' + name); console.log('theme applied: ' + name);
} }
async function applyMovingUIPreset(name) {
resetMovablePanels('quiet')
const movingUIPreset = movingUIPresets.find(x => x.name == name);
if (!movingUIPreset) {
return;
}
power_user.movingUIState = movingUIPreset.movingUIState;
console.log('MovingUI Preset applied: ' + name);
loadMovingUIState()
}
switchUiMode(); switchUiMode();
applyFontScale(); applyFontScale();
applyThemeColor(); applyThemeColor();
@@ -606,6 +623,10 @@ function loadPowerUserSettings(settings, data) {
themes = data.themes; themes = data.themes;
} }
if (data.movingUIPresets !== undefined) {
movingUIPresets = data.movingUIPresets;
}
if (data.instruct !== undefined) { if (data.instruct !== undefined) {
instruct_presets = data.instruct; instruct_presets = data.instruct;
} }
@@ -723,6 +744,15 @@ function loadPowerUserSettings(settings, data) {
$("#themes").append(option); $("#themes").append(option);
} }
for (const movingUIPreset of movingUIPresets) {
const option = document.createElement('option');
option.value = movingUIPreset.name;
option.innerText = movingUIPreset.name;
option.selected = movingUIPreset.name == power_user.MovingUIPreset;
$("#movingUIPresets").append(option);
}
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true); $(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
sortCharactersList(); sortCharactersList();
reloadMarkdownProcessor(power_user.render_formulas); reloadMarkdownProcessor(power_user.render_formulas);
@@ -1027,6 +1057,48 @@ async function saveTheme() {
} }
} }
async function saveMovingUI() {
const name = await callPopup('Enter a name for the MovingUI Preset:', 'input');
if (!name) {
return;
}
const movingUIPreset = {
name,
movingUIState: power_user.movingUIState
}
console.log(movingUIPreset)
const response = await fetch('/savemovingui', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify(movingUIPreset)
});
if (response.ok) {
const movingUIPresetIndex = movingUIPresets.findIndex(x => x.name == name);
if (movingUIPresetIndex == -1) {
movingUIPresets.push(movingUIPreset);
const option = document.createElement('option');
option.selected = true;
option.value = name;
option.innerText = name;
$('#movingUIPresets').append(option);
}
else {
movingUIPresets[movingUIPresetIndex] = movingUIPreset;
$(`#movingUIPresets option[value="${name}"]`).attr('selected', true);
}
power_user.movingUIPreset = name;
saveSettingsDebounced();
} else {
toastr.warning('failed to save MovingUI state.')
}
}
async function resetMovablePanels(type) { async function resetMovablePanels(type) {
const panelIds = [ const panelIds = [
'sheld', 'sheld',
@@ -1072,6 +1144,8 @@ async function resetMovablePanels(type) {
$(".resizing").removeClass('resizing'); $(".resizing").removeClass('resizing');
if (type === 'resize') { if (type === 'resize') {
toastr.warning('Panel positions reset due to zoom/resize'); toastr.warning('Panel positions reset due to zoom/resize');
} else if (type === 'quiet') {
return
} else { } else {
toastr.success('Panel positions reset'); toastr.success('Panel positions reset');
} }
@@ -1647,7 +1721,17 @@ $(document).ready(() => {
saveSettingsDebounced(); saveSettingsDebounced();
}); });
$("#movingUIPresets").on('change', async function () {
console.log('saw MUI preset change')
const movingUIPresetSelected = $(this).find(':selected').val();
power_user.movingUIPreset = movingUIPresetSelected;
applyMovingUIPreset(movingUIPresetSelected);
saveSettingsDebounced();
});
$("#ui-preset-save-button").on('click', saveTheme); $("#ui-preset-save-button").on('click', saveTheme);
$("#movingui-preset-save-button").on('click', saveMovingUI);
$("#never_resize_avatars").on('input', function () { $("#never_resize_avatars").on('input', function () {
power_user.never_resize_avatars = !!$(this).prop('checked'); power_user.never_resize_avatars = !!$(this).prop('checked');

View File

@@ -258,6 +258,7 @@ const directories = {
thumbnailsBg: 'thumbnails/bg/', thumbnailsBg: 'thumbnails/bg/',
thumbnailsAvatar: 'thumbnails/avatar/', thumbnailsAvatar: 'thumbnails/avatar/',
themes: 'public/themes', themes: 'public/themes',
movingUI: 'public/movingUI',
extensions: 'public/scripts/extensions', extensions: 'public/scripts/extensions',
instruct: 'public/instruct', instruct: 'public/instruct',
context: 'public/context', context: 'public/context',
@@ -1072,7 +1073,7 @@ app.post("/editcharacterattribute", jsonParser, async function (request, respons
charaWrite(avatarPath, char, (request.body.avatar_url).replace('.png', ''), response, 'Character saved'); charaWrite(avatarPath, char, (request.body.avatar_url).replace('.png', ''), response, 'Character saved');
}).catch((err) => { }).catch((err) => {
console.error('An error occured, character edit invalidated.', err); console.error('An error occured, character edit invalidated.', err);
} ); });
} }
catch { catch {
console.error('An error occured, character edit invalidated.'); console.error('An error occured, character edit invalidated.');
@@ -1496,6 +1497,7 @@ app.post('/getsettings', jsonParser, (request, response) => {
const world_names = worldFiles.map(item => path.parse(item).name); const world_names = worldFiles.map(item => path.parse(item).name);
const themes = readAndParseFromDirectory(directories.themes); const themes = readAndParseFromDirectory(directories.themes);
const movingUIPresets = readAndParseFromDirectory(directories.movingUI);
const instruct = readAndParseFromDirectory(directories.instruct); const instruct = readAndParseFromDirectory(directories.instruct);
const context = readAndParseFromDirectory(directories.context); const context = readAndParseFromDirectory(directories.context);
@@ -1511,6 +1513,7 @@ app.post('/getsettings', jsonParser, (request, response) => {
textgenerationwebui_presets, textgenerationwebui_presets,
textgenerationwebui_preset_names, textgenerationwebui_preset_names,
themes, themes,
movingUIPresets,
instruct, instruct,
context, context,
enable_extensions: enableExtensions, enable_extensions: enableExtensions,
@@ -1556,6 +1559,17 @@ app.post('/savetheme', jsonParser, (request, response) => {
return response.sendStatus(200); return response.sendStatus(200);
}); });
app.post('/savemovingui', jsonParser, (request, response) => {
if (!request.body || !request.body.name) {
return response.sendStatus(400);
}
const filename = path.join(directories.movingUI, sanitize(request.body.name) + '.json');
fs.writeFileSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
return response.sendStatus(200);
});
function convertWorldInfoToCharacterBook(name, entries) { function convertWorldInfoToCharacterBook(name, entries) {
const result = { entries: [], name }; const result = { entries: [], name };
@@ -3481,7 +3495,7 @@ function createTokenizationHandler(getTokenizerFn) {
app.post("/tokenize_llama", jsonParser, createTokenizationHandler(() => spp_llama)); app.post("/tokenize_llama", jsonParser, createTokenizationHandler(() => spp_llama));
app.post("/tokenize_nerdstash", jsonParser, createTokenizationHandler(() => spp_nerd)); app.post("/tokenize_nerdstash", jsonParser, createTokenizationHandler(() => spp_nerd));
app.post("/tokenize_nerdstash_v2", jsonParser, createTokenizationHandler(() => spp_nerd_v2)); app.post("/tokenize_nerdstash_v2", jsonParser, createTokenizationHandler(() => spp_nerd_v2));
app.post("/tokenize_via_api", jsonParser, async function(request, response) { app.post("/tokenize_via_api", jsonParser, async function (request, response) {
if (!request.body) { if (!request.body) {
return response.sendStatus(400); return response.sendStatus(400);
} }
@@ -3489,7 +3503,7 @@ app.post("/tokenize_via_api", jsonParser, async function(request, response) {
try { try {
const args = { const args = {
body: JSON.stringify({"prompt": text}), body: JSON.stringify({ "prompt": text }),
headers: { "Content-Type": "application/json" } headers: { "Content-Type": "application/json" }
}; };
@@ -4467,22 +4481,22 @@ async function getManifest(extensionPath) {
} }
async function checkIfRepoIsUpToDate(extensionPath) { async function checkIfRepoIsUpToDate(extensionPath) {
const git = simpleGit(); const git = simpleGit();
await git.cwd(extensionPath).fetch('origin'); await git.cwd(extensionPath).fetch('origin');
const currentBranch = await git.cwd(extensionPath).branch(); const currentBranch = await git.cwd(extensionPath).branch();
const currentCommitHash = await git.cwd(extensionPath).revparse(['HEAD']); const currentCommitHash = await git.cwd(extensionPath).revparse(['HEAD']);
const log = await git.cwd(extensionPath).log({ const log = await git.cwd(extensionPath).log({
from: currentCommitHash, from: currentCommitHash,
to: `origin/${currentBranch.current}`, to: `origin/${currentBranch.current}`,
}); });
// Fetch remote repository information // Fetch remote repository information
const remotes = await git.cwd(extensionPath).getRemotes(true); const remotes = await git.cwd(extensionPath).getRemotes(true);
return { return {
isUpToDate: log.total === 0, isUpToDate: log.total === 0,
remoteUrl: remotes[0].refs.fetch, // URL of the remote repository remoteUrl: remotes[0].refs.fetch, // URL of the remote repository
}; };
} }
@@ -4597,7 +4611,7 @@ app.post('/get_extension_version', jsonParser, async (request, response) => {
const extensionPath = path.join(directories.extensions, 'third-party', extensionName); const extensionPath = path.join(directories.extensions, 'third-party', extensionName);
if (!fs.existsSync(extensionPath)) { if (!fs.existsSync(extensionPath)) {
return response.status(404).send(`Directory does not exist at ${extensionPath}`); return response.status(404).send(`Directory does not exist at ${extensionPath}`);
} }
const currentBranch = await git.cwd(extensionPath).branch(); const currentBranch = await git.cwd(extensionPath).branch();
@@ -4614,7 +4628,7 @@ app.post('/get_extension_version', jsonParser, async (request, response) => {
console.log('Getting extension version failed', error); console.log('Getting extension version failed', error);
return response.status(500).send(`Server Error: ${error.message}`); return response.status(500).send(`Server Error: ${error.message}`);
} }
} }
); );
/** /**