Move shallow toggle to config.yaml
| @@ -1,8 +1,6 @@ | ||
| 1 | 1 | # -- DATA CONFIGURATION -- |
| 2 | 2 | # Root directory for user data storage |
| 3 | 3 | dataRoot: ./data |
| 4 | -# The maximum amount of memory that parsed character cards can use in MB | |
| 5 | -cardsCacheCapacity: 100 | |
| 6 | 4 | # -- SERVER CONFIGURATION -- |
| 7 | 5 | # Listen for incoming connections |
| 8 | 6 | listen: false |
| @@ -135,6 +133,14 @@ thumbnails: | ||
| 135 | 133 | # Maximum thumbnail dimensions per type [width, height] |
| 136 | 134 | dimensions: { 'bg': [160, 90], 'avatar': [96, 144] } |
| 137 | 135 | |
| 136 | +# PERFORMANCE-RELATED CONFIGURATION | |
| 137 | +performance: | |
| 138 | + # Enables lazy loading of character cards. Improves performances with large card libraries. | |
| 139 | + # May have compatibility issues with some extensions. | |
| 140 | + lazyLoadCharacters: false | |
| 141 | + # The maximum amount of memory that parsed character cards can use in MB | |
| 142 | + cardsCacheCapacity: 100 | |
| 143 | + | |
| 138 | 144 | # Allow secret keys exposure via API |
| 139 | 145 | allowKeysExposure: false |
| 140 | 146 | # Skip new default content checks |
| @@ -96,6 +96,11 @@ const keyMigrationMap = [ | ||
| 96 | 96 | newKey: 'logging.minLogLevel', |
| 97 | 97 | migrate: (value) => value, |
| 98 | 98 | }, |
| 99 | + { | |
| 100 | + oldKey: 'cardsCacheCapacity', | |
| 101 | + newKey: 'performance.cardsCacheCapacity', | |
| 102 | + migrate: (value) => value, | |
| 103 | + }, | |
| 99 | 104 | // uncomment one release after 1.12.13 |
| 100 | 105 | /* |
| 101 | 106 | { |
| @@ -4424,13 +4424,6 @@ | ||
| 4424 | 4424 | <option data-i18n="tag_import_existing" value="4">Existing</option> |
| 4425 | 4425 | </select> |
| 4426 | 4426 | </div> |
| 4427 | - <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."> | |
| 4428 | - <input id="shallow_characters" type="checkbox" /> | |
| 4429 | - <small data-i18n="Lazy Load Characters"> | |
| 4430 | - Lazy Load Characters | |
| 4431 | - </small> | |
| 4432 | - <i class="fa-solid fa-flask"></i> | |
| 4433 | - </label> | |
| 4434 | 4427 | <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"> |
| 4435 | 4428 | <input id="fuzzy_search_checkbox" type="checkbox" /> |
| 4436 | 4429 | <small data-i18n="Advanced Character Search">Advanced Character Search</small> |
| @@ -1780,9 +1780,7 @@ export async function getCharacters() { | ||
| 1780 | 1780 | const response = await fetch('/api/characters/all', { |
| 1781 | 1781 | method: 'POST', |
| 1782 | 1782 | headers: getRequestHeaders(), |
| 1783 | 1783 | body: JSON.stringify({}), |
| 1784 | - shallow: power_user.shallow_characters, | |
| 1785 | - }), | |
| 1786 | 1784 | }); |
| 1787 | 1785 | if (response.ok === true) { |
| 1788 | 1786 | characters.splice(0, characters.length); |
| @@ -6718,6 +6716,7 @@ export async function unshallowCharacter(characterId) { | ||
| 6718 | 6716 | return; |
| 6719 | 6717 | } |
| 6720 | 6718 | |
| 6719 | + /** @type {import('./scripts/char-data.js').v1CharData} */ | |
| 6721 | 6720 | const character = characters[characterId]; |
| 6722 | 6721 | if (!character) { |
| 6723 | 6722 | console.warn('Character not found:', characterId); |
| @@ -113,5 +113,6 @@ | ||
| 113 | 113 | * @property {string} chat - name of the current chat file chat |
| 114 | 114 | * @property {string} avatar - file name of the avatar image (acts as a unique identifier) |
| 115 | 115 | * @property {string} json_data - the full raw JSON data of the character |
| 116 | + * @property {boolean?} shallow - if the data is shallow (lazy-loaded) | |
| 116 | 117 | */ |
| 117 | 118 | export default 0;// now this file is a module |
| @@ -314,7 +314,6 @@ let power_user = { | ||
| 314 | 314 | forbid_external_media: true, |
| 315 | 315 | external_media_allowed_overrides: [], |
| 316 | 316 | external_media_forbidden_overrides: [], |
| 317 | - shallow_characters: false, | |
| 318 | 317 | }; |
| 319 | 318 | |
| 320 | 319 | let themes = []; |
| @@ -1596,7 +1595,6 @@ async function loadPowerUserSettings(settings, data) { | ||
| 1596 | 1595 | $('#auto-connect-checkbox').prop('checked', power_user.auto_connect); |
| 1597 | 1596 | $('#auto-load-chat-checkbox').prop('checked', power_user.auto_load_chat); |
| 1598 | 1597 | $('#forbid_external_media').prop('checked', power_user.forbid_external_media); |
| 1599 | - $('#shallow_characters').prop('checked', power_user.shallow_characters); | |
| 1600 | 1598 | |
| 1601 | 1599 | for (const theme of themes) { |
| 1602 | 1600 | const option = document.createElement('option'); |
| @@ -3890,12 +3888,6 @@ $(document).ready(() => { | ||
| 3890 | 3888 | await exportTheme(); |
| 3891 | 3889 | }); |
| 3892 | 3890 | |
| 3893 | - $('#shallow_characters').on('input', function () { | |
| 3894 | - power_user.shallow_characters = !!$(this).prop('checked'); | |
| 3895 | - saveSettingsDebounced(); | |
| 3896 | - toastr.info('Reload the page for this setting to take effect'); | |
| 3897 | - }); | |
| 3898 | - | |
| 3899 | 3891 | $(document).on('click', '#debug_table [data-debug-function]', function () { |
| 3900 | 3892 | const functionId = $(this).data('debug-function'); |
| 3901 | 3893 | const functionRecord = debug_functions.find(f => f.functionId === functionId); |
| @@ -24,11 +24,13 @@ import { importRisuSprites } from './sprites.js'; | ||
| 24 | 24 | const defaultAvatarPath = './public/img/ai4.png'; |
| 25 | 25 | |
| 26 | 26 | // KV-store for parsed character data |
| 27 | 27 | const cacheCapacity = Number(getConfigValue('performance.cardsCacheCapacity', 100, 'number')); // MB |
| 28 | 28 | // With 100 MB limit it would take roughly 3000 characters to reach this limit |
| 29 | 29 | const characterDataCache = new MemoryLimitedMap(1024 * 1024 * cacheCapacity); |
| 30 | 30 | // Some Android devices require tighter memory management |
| 31 | 31 | const isAndroid = process.platform === 'android'; |
| 32 | +// Use shallow character data for the character list | |
| 33 | +const useShallowCharacters = !!getConfigValue('performance.lazyLoadCharacters', false, 'boolean'); | |
| 32 | 34 | |
| 33 | 35 | /** |
| 34 | 36 | * Reads the character card from the specified image file. |
| @@ -207,6 +209,7 @@ const calculateDataSize = (data) => { | ||
| 207 | 209 | */ |
| 208 | 210 | const toShallow = (character) => { |
| 209 | 211 | return { |
| 212 | + shallow: true, | |
| 210 | 213 | name: character.name, |
| 211 | 214 | avatar: character.avatar, |
| 212 | 215 | chat: character.chat, |
| @@ -225,7 +228,6 @@ const toShallow = (character) => { | ||
| 225 | 228 | fav: _.get(character, 'data.extensions.fav', false), |
| 226 | 229 | }, |
| 227 | 230 | }, |
| 228 | - shallow: true, | |
| 229 | 231 | }; |
| 230 | 232 | }; |
| 231 | 233 | |
| @@ -1022,10 +1024,9 @@ router.post('/delete', jsonParser, validateAvatarUrlMiddleware, async function ( | ||
| 1022 | 1024 | */ |
| 1023 | 1025 | router.post('/all', jsonParser, async function (request, response) { |
| 1024 | 1026 | try { |
| 1025 | - const shallow = !!request.body.shallow; | |
| 1026 | 1027 | const files = fs.readdirSync(request.user.directories.characters); |
| 1027 | 1028 | const pngFiles = files.filter(file => file.endsWith('.png')); |
| 1028 | 1029 | const processingPromises = pngFiles.map(file => processCharacter(file, request.user.directories, { shallow: useShallowCharacters })); |
| 1029 | 1030 | const data = (await Promise.all(processingPromises)).filter(c => c.name); |
| 1030 | 1031 | return response.send(data); |
| 1031 | 1032 | } catch (err) { |