Move shallow toggle to config.yaml

This commit is contained in:
Cohee 2025-03-04 23:32:42 +02:00
parent 383806325a
commit 3d813e4ef6
7 changed files with 21 additions and 24 deletions

View File

@ -1,8 +1,6 @@
# -- DATA CONFIGURATION --
# Root directory for user data storage
dataRoot: ./data
# The maximum amount of memory that parsed character cards can use in MB
cardsCacheCapacity: 100
# -- SERVER CONFIGURATION --
# Listen for incoming connections
listen: false
@ -135,6 +133,14 @@ thumbnails:
# Maximum thumbnail dimensions per type [width, height]
dimensions: { 'bg': [160, 90], 'avatar': [96, 144] }
# PERFORMANCE-RELATED CONFIGURATION
performance:
# Enables lazy loading of character cards. Improves performances with large card libraries.
# May have compatibility issues with some extensions.
lazyLoadCharacters: false
# The maximum amount of memory that parsed character cards can use in MB
cardsCacheCapacity: 100
# Allow secret keys exposure via API
allowKeysExposure: false
# Skip new default content checks

View File

@ -96,6 +96,11 @@ const keyMigrationMap = [
newKey: 'logging.minLogLevel',
migrate: (value) => value,
},
{
oldKey: 'cardsCacheCapacity',
newKey: 'performance.cardsCacheCapacity',
migrate: (value) => value,
},
// uncomment one release after 1.12.13
/*
{

View File

@ -4424,13 +4424,6 @@
<option data-i18n="tag_import_existing" value="4">Existing</option>
</select>
</div>
<label class="checkbox_label" for="shallow_characters" data-i18n="[title]Experimental feature. May behave unstable and have compatibility issues." title="Experimental feature. May behave unstable and have compatibility issues.">
<input id="shallow_characters" type="checkbox" />
<small data-i18n="Lazy Load Characters">
Lazy Load Characters
</small>
<i class="fa-solid fa-flask"></i>
</label>
<label class="checkbox_label" for="fuzzy_search_checkbox" title="Use fuzzy matching, and search characters in the list by all data fields, not just by a name substring." data-i18n="[title]Use fuzzy matching, and search characters in the list by all data fields, not just by a name substring">
<input id="fuzzy_search_checkbox" type="checkbox" />
<small data-i18n="Advanced Character Search">Advanced Character Search</small>

View File

@ -1780,9 +1780,7 @@ export async function getCharacters() {
const response = await fetch('/api/characters/all', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
shallow: power_user.shallow_characters,
}),
body: JSON.stringify({}),
});
if (response.ok === true) {
characters.splice(0, characters.length);
@ -6718,6 +6716,7 @@ export async function unshallowCharacter(characterId) {
return;
}
/** @type {import('./scripts/char-data.js').v1CharData} */
const character = characters[characterId];
if (!character) {
console.warn('Character not found:', characterId);

View File

@ -113,5 +113,6 @@
* @property {string} chat - name of the current chat file chat
* @property {string} avatar - file name of the avatar image (acts as a unique identifier)
* @property {string} json_data - the full raw JSON data of the character
* @property {boolean?} shallow - if the data is shallow (lazy-loaded)
*/
export default 0;// now this file is a module

View File

@ -314,7 +314,6 @@ let power_user = {
forbid_external_media: true,
external_media_allowed_overrides: [],
external_media_forbidden_overrides: [],
shallow_characters: false,
};
let themes = [];
@ -1596,7 +1595,6 @@ async function loadPowerUserSettings(settings, data) {
$('#auto-connect-checkbox').prop('checked', power_user.auto_connect);
$('#auto-load-chat-checkbox').prop('checked', power_user.auto_load_chat);
$('#forbid_external_media').prop('checked', power_user.forbid_external_media);
$('#shallow_characters').prop('checked', power_user.shallow_characters);
for (const theme of themes) {
const option = document.createElement('option');
@ -3890,12 +3888,6 @@ $(document).ready(() => {
await exportTheme();
});
$('#shallow_characters').on('input', function () {
power_user.shallow_characters = !!$(this).prop('checked');
saveSettingsDebounced();
toastr.info('Reload the page for this setting to take effect');
});
$(document).on('click', '#debug_table [data-debug-function]', function () {
const functionId = $(this).data('debug-function');
const functionRecord = debug_functions.find(f => f.functionId === functionId);

View File

@ -24,11 +24,13 @@ import { importRisuSprites } from './sprites.js';
const defaultAvatarPath = './public/img/ai4.png';
// KV-store for parsed character data
const cacheCapacity = Number(getConfigValue('cardsCacheCapacity', 100, 'number')); // MB
const cacheCapacity = Number(getConfigValue('performance.cardsCacheCapacity', 100, 'number')); // MB
// With 100 MB limit it would take roughly 3000 characters to reach this limit
const characterDataCache = new MemoryLimitedMap(1024 * 1024 * cacheCapacity);
// Some Android devices require tighter memory management
const isAndroid = process.platform === 'android';
// Use shallow character data for the character list
const useShallowCharacters = !!getConfigValue('performance.lazyLoadCharacters', false, 'boolean');
/**
* Reads the character card from the specified image file.
@ -207,6 +209,7 @@ const calculateDataSize = (data) => {
*/
const toShallow = (character) => {
return {
shallow: true,
name: character.name,
avatar: character.avatar,
chat: character.chat,
@ -225,7 +228,6 @@ const toShallow = (character) => {
fav: _.get(character, 'data.extensions.fav', false),
},
},
shallow: true,
};
};
@ -1022,10 +1024,9 @@ router.post('/delete', jsonParser, validateAvatarUrlMiddleware, async function (
*/
router.post('/all', jsonParser, async function (request, response) {
try {
const shallow = !!request.body.shallow;
const files = fs.readdirSync(request.user.directories.characters);
const pngFiles = files.filter(file => file.endsWith('.png'));
const processingPromises = pngFiles.map(file => processCharacter(file, request.user.directories, { shallow }));
const processingPromises = pngFiles.map(file => processCharacter(file, request.user.directories, { shallow: useShallowCharacters }));
const data = (await Promise.all(processingPromises)).filter(c => c.name);
return response.send(data);
} catch (err) {