| 1010 | 1011 | |
| 1011 | 1012 | /** |
| 1012 | 1013 | * Init voiceMapEntries for character select list. |
| 1014 | + * If an initialization is already in progress, it returns the existing Promise instead of starting a new one. |
| 1013 | 1015 | * @param {boolean} unrestricted - If true, will include all characters in voiceMapEntries, even if they are not in the current chat. |
| 1016 | + * @returns {Promise} A promise that resolves when the initialization is complete. |
| 1014 | 1017 | */ |
| 1015 | 1018 | export async function initVoiceMap(unrestricted = false) { |
| 1019 | + // Preventing parallel execution |
| 1020 | + if (currentInitVoiceMapPromise) { |
| 1021 | + return currentInitVoiceMapPromise; |
| 1022 | + } |
| 1023 | + |
| 1024 | + currentInitVoiceMapPromise = (async () => { |
| 1025 | + try { |
| 1026 | + await initVoiceMapInternal(unrestricted); |
| 1027 | + } finally { |
| 1028 | + currentInitVoiceMapPromise = null; |
| 1029 | + } |
| 1030 | + })(); |
| 1031 | + |
| 1032 | + return currentInitVoiceMapPromise; |
| 1033 | +} |
| 1034 | + |
| 1035 | +/** |
| 1036 | + * Init voiceMapEntries for character select list. |
| 1037 | + * @param {boolean} unrestricted - If true, will include all characters in voiceMapEntries, even if they are not in the current chat. |
| 1038 | + */ |
| 1039 | +async function initVoiceMapInternal(unrestricted) { |
| 1040 | + |
| 1016 | 1041 | // Gate initialization if not enabled or TTS Provider not ready. Prevents error popups. |
| 1017 | 1042 | const enabled = $('#tts_enabled').is(':checked'); |
| 1018 | 1043 | if (!enabled) { |