Skip to content

Commit

Permalink
in speech-to-text settings, implement language pinning (#32)
Browse files Browse the repository at this point in the history
* in speech-to-text settings, implement language pinning

* create type for list items (title, value)

* lint check

---------

Co-authored-by: nae <[email protected]>
  • Loading branch information
fuwako and naeruru authored Feb 21, 2024
1 parent 6cfff6f commit 0db5499
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 6 deletions.
63 changes: 60 additions & 3 deletions src/components/settings/STT.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,41 @@
</v-row>

<v-col :cols="12">
<v-radio-group v-if="Object.keys(speechStore.pinned_languages).length > 0" v-model="speechStore.stt.language" :label="$t('settings.stt.pinned_languages')">
<v-card v-for="language in speechStore.pinned_languages" class="language-card pa-2 mb-2" :color="language.value === speechStore.stt.language ? 'primary' : 'default'" @click="speechStore.stt.language = language.value">
<v-radio :label="language.title" :value="language.value">
<template #label>
<div class="d-flex flex-grow-1 justify-space-between me-2">
<div>{{ language.title }}</div>
<div class="pin-icon">
<v-icon v-if="!is_pinned_language(language)" class="pin-icon-not-pinned" @click.prevent="pin_language(language)">
mdi-star-outline
</v-icon>
<v-icon v-else class="pin-icon-pinned" @click.prevent="unpin_language(language)">
mdi-star
</v-icon>
</div>
</div>
</template>
</v-radio>
</v-card>
</v-radio-group>
<v-radio-group v-model="speechStore.stt.language" :label="$t('settings.stt.language')">
<v-text-field v-model="search_lang" class="mb-2" label="Search" variant="outlined" single-line hide-details />
<v-card v-for="(language, i) in filtered_lang" class="pa-2 mb-2" :color="language.value === speechStore.stt.language ? 'primary' : 'default'" @click="speechStore.stt.language = language.value">
<v-card v-for="(language, i) in filtered_lang" class="language-card pa-2 mb-2" :color="language.value === speechStore.stt.language ? 'primary' : 'default'" @click="speechStore.stt.language = language.value">
<v-radio :label="language.title" :value="language.value">
<template #label>
<div>{{ language.title }}</div>
<div class="d-flex flex-grow-1 justify-space-between me-2">
<div>{{ language.title }}</div>
<div class="pin-icon">
<v-icon v-if="!is_pinned_language(language)" class="pin-icon-not-pinned" @click.prevent="pin_language(language)">
mdi-star-outline
</v-icon>
<v-icon v-else class="pin-icon-pinned" @click.prevent="unpin_language(language)">
mdi-star
</v-icon>
</div>
</div>
</template>
</v-radio>
</v-card>
Expand Down Expand Up @@ -204,10 +233,38 @@ export default {
})
})
},
pin_language(selected_language: list_item) {
this.speechStore.pin_language(selected_language)
},
unpin_language(selected_language: list_item) {
this.speechStore.unpin_language(selected_language)
},
is_pinned_language(selected_language: list_item) {
return this.speechStore.is_pinned_language(selected_language)
},
},
}
</script>

<style scoped>
<style>
.language-card .v-selection-control .v-label {
width: 100%;
}
.language-card .pin-icon-not-pinned {
display: none !important;
}
.language-card:hover .pin-icon-not-pinned {
display: inline-block !important;
}
/* v-hover is unreliable and doesn't respond to layout changes. */
.pin-icon-pinned:hover:before {
content: "\F1564" !important; /* mdi-star-minus */
}
.pin-icon-not-pinned:hover:before {
content: "\F1567" !important; /* mdi-star-plus-outline */
}
</style>
2 changes: 1 addition & 1 deletion src/components/settings/TTS.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<v-row>
<v-col :cols="12">
<v-card>
<v-list-item :title="$t('settings.tts.enabled') ">
<v-list-item :title="$t('settings.tts.enabled') ">
<template #append>
<v-switch
v-model="speechStore.tts.enabled"
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,8 @@ export default {
window.open(link, '_blank')
},
handleKeyDown(event: KeyboardEvent) {
if (event.key === 'Escape') {
if (event.key === 'Escape')
this.$router.push({ path: '/' })
}
},
},
}
Expand Down
1 change: 1 addition & 0 deletions src/plugins/localization/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default {
sensitivity_start: 'Check',
sensitivity_stop: 'Stop',
device: 'Listening: ',
pinned_languages: 'Pinned languages',
language: 'Select a speech detection language',
unsupported: {
text: 'Web Speech API Speech-to-Text is only available on the {0}. (^・ω・^)',
Expand Down
1 change: 1 addition & 0 deletions src/plugins/localization/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export default {
sensitivity_start: 'Probar',
sensitivity_stop: 'Parar',
device: 'Escuchando: ',
pinned_languages: 'Lenguajes fijados',
language: 'Selecciones un lenguaje de escucha',
unsupported: {
text: 'Web Speech API (Voz a Texto) solo está disponible en {0}. (^・ω・^)',
Expand Down
1 change: 1 addition & 0 deletions src/plugins/localization/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default {
sensitivity_start: 'マイクテスト',
sensitivity_stop: 'テストを中...',
device: 'デバイス: ',
pinned_languages: 'ピン留めされた言語',
language: 'Speech-to-textの言語を選択',
unsupported: {
text: 'Web Speech APIのSpeech-to-Textは{0}で利用できます。(^・ω・^)',
Expand Down
5 changes: 5 additions & 0 deletions src/shims.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,10 @@ declare module '*.vue' {
export default component
}

interface list_item {
title: string
value: string
}

declare const __APP_NAME__: string
declare const __APP_VERSION__: string
32 changes: 32 additions & 0 deletions src/stores/speech.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import is_electron from '@/helpers/is_electron'
import { i18n } from '@/plugins/i18n'
import { WebSpeech } from '@/modules/speech'

interface pinned_languages {
[key: string]: list_item
}

declare const window: any

export const useSpeechStore = defineStore('speech', {
Expand All @@ -34,6 +38,7 @@ export const useSpeechStore = defineStore('speech', {
rate: 1,
pitch: 1,
},
pinned_languages: {} as pinned_languages,
}),
getters: {

Expand Down Expand Up @@ -215,5 +220,32 @@ export const useSpeechStore = defineStore('speech', {
defaultStore.ws.send(`{"type": "text", "data": ${JSON.stringify(log)}}`)
}
},
pin_language(selected_language: list_item) {
const pins = this.pinned_languages

// Pin.
pins[selected_language.title] = selected_language

// Alphabetically sort.
const sortedKeys = Object.keys(pins).sort()
const sortedPins = {} as pinned_languages

sortedKeys.forEach((key) => {
sortedPins[key] = pins[key]
})

this.pinned_languages = sortedPins
},
unpin_language(selected_language: list_item) {
const pins = this.pinned_languages

// Unpin.
delete pins[selected_language.title]
},
is_pinned_language(selected_language: list_item) {
const pins = this.pinned_languages

return pins.hasOwnProperty(selected_language.title)
},
},
})

0 comments on commit 0db5499

Please sign in to comment.