mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-23 04:34:15 -04:00
89 lines
3.1 KiB
Vue
89 lines
3.1 KiB
Vue
<script setup lang="ts">
|
||
import { escapePronunciationString, unescapePronunciationString } from '#shared/helpers.ts';
|
||
import { voices } from '#shared/pronunciation/voices.ts';
|
||
import type { VoiceKey } from '#shared/pronunciation/voices.ts';
|
||
import useConfig from '~/composables/useConfig.ts';
|
||
|
||
const pronounciationModelValue = defineModel<string | null>('pronounciation', { required: true });
|
||
const voiceModelValue = defineModel<VoiceKey | null>('voice', { required: true });
|
||
|
||
const config = useConfig();
|
||
|
||
const rawPronunciation = computed({
|
||
get(): string {
|
||
if (pronounciationModelValue.value) {
|
||
const phonemes = pronounciationModelValue.value.substring(1, pronounciationModelValue.value.length - 1);
|
||
return unescapePronunciationString(phonemes);
|
||
} else {
|
||
return '';
|
||
}
|
||
},
|
||
set(rawPronunciation: string) {
|
||
let pronunciation;
|
||
if (rawPronunciation) {
|
||
pronunciation = `/${escapePronunciationString(rawPronunciation)}/`;
|
||
} else {
|
||
pronunciation = null;
|
||
}
|
||
|
||
pronounciationModelValue.value = pronunciation;
|
||
},
|
||
});
|
||
|
||
watch(pronounciationModelValue, (value, oldValue) => {
|
||
if (oldValue !== null) {
|
||
return;
|
||
}
|
||
// reset voice to default voice
|
||
if (!config.pronunciation?.enabled) {
|
||
voiceModelValue.value = 'gb';
|
||
} else {
|
||
voiceModelValue.value = config.pronunciation.voices[0];
|
||
}
|
||
});
|
||
|
||
const sortedVoices = computed(() => {
|
||
const voicesOfLocale = config.pronunciation?.enabled ? config.pronunciation.voices : [];
|
||
|
||
return entriesWithKeys(voices).toSorted((a, b) => {
|
||
return (voicesOfLocale.includes(b.key as VoiceKey) ? 1 : 0) - (voicesOfLocale.includes(a.key as VoiceKey) ? 1 : 0);
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div class="input-group input-group-sm w-50">
|
||
<span class="input-group-text">/</span>
|
||
<input
|
||
v-model="rawPronunciation"
|
||
class="form-control mw-input"
|
||
:placeholder="$t('profile.pronunciation.ipa')"
|
||
maxlength="255"
|
||
>
|
||
<span class="input-group-text">/</span>
|
||
<template v-if="pronounciationModelValue !== null">
|
||
<select
|
||
v-model="voiceModelValue"
|
||
class="form-control"
|
||
:class="voiceModelValue === null ? 'text-muted' : ''"
|
||
>
|
||
<option :value="null">
|
||
<T>profile.pronunciation.voice.without</T>
|
||
</option>
|
||
<option v-for="voice of sortedVoices" :key="voice.key" :value="voice.key">
|
||
{{ voice.key.toUpperCase() }} – {{ voice.name }}
|
||
</option>
|
||
</select>
|
||
<PronunciationSpeaker
|
||
v-if="voiceModelValue !== null"
|
||
class="btn btn-sm rounded-start-0 btn-outline-secondary"
|
||
:pronunciation="pronounciationModelValue"
|
||
:voice="voiceModelValue"
|
||
/>
|
||
<button v-else class="btn btn-sm rounded-start-0 btn-outline-secondary" type="button" disabled>
|
||
<Icon v="volume-slash" />
|
||
</button>
|
||
</template>
|
||
</div>
|
||
</template>
|