mindboost-rnbo-test-project/pages/fixproblem.vue

380 lines
12 KiB
Vue

<template>
<div>
<div class="container-fluid">
<div class="row">
<div class="col-12 px-0 mx-0">
<video-background
src="/video/bg-video.mp4"
style=" height: 100vh;"
poster="/images/poster.png"
>
<div class="container-fluid pt-3 px-lg-4">
<div class="header d-flex flex-column flex-fill flex-md-row justify-content-between">
<div class="header__logo pt-md-1 pt-lg-1">
<nuxt-link class="navbar-brand" to="/">
<div class="text-center text-md-start">
<img src="/mindboostlogo.svg" height="35" class="img " alt="imae">
</div>
</nuxt-link>
</div>
</div>
<div class="content">
<div class="row text-center">
<div class="col-12">
<h1 v-if="true" class="h3 fw-bold mb-4">
{{ t("The microphone does not provide any level") }}
</h1>
<h1 v-else class="h3 fw-bold mb-4">
{{ t("Nothing to worry, the microphone is working.") }}
</h1>
<p class="text-muted">
{{ t("Please check the input level of the microphone in the audio") }}
</p>
</div>
<div class="row justify-content-center pt-4">
<div class="col-11">
<form>
<div class="row justify-content-center mb-4">
<div class="col-md-5 text-center">
<label for="inputSelect" class="fw-semibold">{{ t('Input device:') }}</label>
<p class="pt-0 mt-0 text-muted pb-2 mb-0" style="font-size: 14px;font-weight: 500">
({{ t('select laptop or mobile device microphone') }})
</p>
<select id="inputSelect" v-model="selectedInput" class="form-select pt-1 mt-0 select-box" @change="handleInputChange">
<option v-for="device in audioInputDevices" :key="device.value" :value="device.value">
{{ device.label }}
</option>
</select>
</div>
</div>
</form>
</div>
<div class=" pt-3 text-center">
<div class="progress-container">
<div class="checkmark col-md-6 pt-2 d-block d-sm-inline-block d-inline-block">
<p class="fw-semibold">{{ t("Microphone Indicator") }}</p>
<div class="col-12 text-center d-flex justify-content-center col-lg-12 pb-5">
<AudioReactiveBar ref="AudioReactiveBar" />
</div>
<div class="col-12 text-center pt-1">
<a href="/" class="btn text-white px-4 fs-5 fw-bolder py-2" type="button" style="background-color: rgb(233, 192, 70);">{{ t('Next') }}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</video-background>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapState } from 'pinia'
import { useCounterStore } from '@/stores/counter'
import { useMicStore } from '@/stores/microphone'
import { useUserStore } from '@/stores/user'
export default {
name: 'FixProblem',
setup () {
const { t } = useI18n()
const localePath = useLocalePath()
const AudioReactiveBar = ref(null)
const micStore = useMicStore()
return {
micStore,
t,
localePath,
AudioReactiveBar
}
},
data () {
return {
bar_val: 100,
audioOutputDevices: [],
selectedInput: null,
selectedOutput: null,
stream: null,
micReady: false,
detectedInput: false
}
},
computed: {
...mapState(useCounterStore, ['count']),
// ...mapState(useMicStore, ['microphones'])
audioInputDevices () {
return this.micStore.availableDevices.map(device => ({
label: device.label || `Microphone ${device.deviceId}`,
value: device.deviceId
}))
}
},
created () {
this.$watch(
() => this.audioInputDevices,
(newDevices) => {
if (newDevices.length > 0 && this.selectedInput === null) {
this.selectedInput = newDevices[0].value
}
},
{ immediate: true }
)
},
fillInputList () {
try {
this.getUserMedia()
.then(() => {
return navigator.mediaDevices.enumerateDevices()
})
.then((devices) => {
// useNuxtApp().$logger.log('DEVICES', { devices })
// Filtere die Geräte nach Typ
this.audioInputDevices = devices.filter(device => device.kind === 'audioinput')
this.audioOutputDevices = devices.filter(device => device.kind === 'audiooutput')
// Setze die Standardwerte, falls keine Geräte verfügbar sind
this.selectedDevice = this.audioInputDevices.length > 0 ? this.audioInputDevices[0].deviceId : null
// Überprüfe, ob `audioInputDevice` und `audioOutputDevice` existieren
if (this.audioInputDevice && this.audioInputDevice.deviceId) {
this.selectedInput = this.audioInputDevices.findIndex(item => item.deviceId === this.audioInputDevice.deviceId)
} else {
this.selectedInput = -1 // Kein passendes Gerät gefunden
}
if (this.audioOutputDevice && this.audioOutputDevice.deviceId) {
this.selectedOutput = this.audioOutputDevices.findIndex(item => item.deviceId === this.audioOutputDevice.deviceId)
} else {
this.selectedOutput = -1 // Kein passendes Gerät gefunden
}
// Standardauswahl, falls nichts gefunden wird
if (this.selectedInput < 0) { this.selectedInput = 0 }
if (this.selectedOutput < 0) { this.selectedOutput = 0 }
// Warnung anzeigen, wenn Geräte gleich sind
if (this.checkIfSameDevice()) {
this.$toast.warning(this.t('bluetoothWarning'), {
duration: 6000,
pauseOnHover: true,
dismissible: true,
queue: true,
position: 'bottom-left'
})
}
})
.catch((error) => {
// Fehler bei der Geräteabfrage behandeln
this.$toast.error(`Error enumerating media devices: ${error.message}`)
useNuxtApp().$logger.error('Error during device enumeration:', error)
})
} catch (error) {
// Allgemeine Fehlerbehandlung
this.$toast.error('Unexpected error occurred.')
useNuxtApp().$logger.error('Unexpected error:', error)
}
},
async mounted () {
this.increment(75)
await this.micStore.updateAvailableDevices()
},
beforeUnmount () {
this.detachMicrophone()
},
methods: {
...mapActions(useCounterStore, ['increment']),
...mapActions(useMicStore, ['getMicrophone', 'getMediaStream', 'switchMicrophone', 'detachMicrophone']),
...mapActions(useUserStore, ['saveInputdevice', 'saveOutputDevice']),
checkMicrophoneReadiness (mic) {
if (mic.microphoneNode instanceof MediaStreamAudioSourceNode &&
mic.microphoneStream instanceof MediaStream) { this.micReady = true }
this.stream = mic.microphoneStream
useNuxtApp().$logger.log(this.micReady)
},
normalizeDeviceName (deviceName) {
return deviceName
.replace('Standard - ', '') // Remove 'Standard - '
.replace(/ \(.*\)$/, '') // Remove any content in parentheses
.trim()
},
async check (event) {
useNuxtApp().$logger.log({ event })
const inputDeviceId = this.audioInputDevices[(event.target).value].deviceId
useNuxtApp().$logger.log('INPUT DEVICE', { inputDeviceId })
await this.switchMicrophone(inputDeviceId)
this.checkIfSameDevice()
},
checkInputLevel () {
const audioreactivebar = AudioReactiveBar.value
useNuxtApp().$logger.log({ audioreactivebar })
this.detectedInput = true
},
getDeviceLabel (outputDevice) {
if (!outputDevice || !outputDevice.label) {
return 'Unknown Device' // Fallback-Label
}
return outputDevice.label
},
checkIfSameDevice () {
const outputDevice = this.audioOutputDevices[this.selectedOutput] || this.audioOutputDevices[this.index]
const inputDevice = this.audioInputDevices[this.selectedInput]
const inputLabel = this.getDeviceLabel(inputDevice)
const outputLabel = this.getDeviceLabel(outputDevice)
if (!inputLabel || !outputLabel) {
throw new Error('Device labels are not selected or not available')
}
const normalizedInput = this.normalizeDeviceName(inputLabel)
const normalizedOutput = this.normalizeDeviceName(outputLabel)
// useNuxtApp().$logger.log(`Normalized Input: ${normalizedInput}, Normalized Output: ${normalizedOutput}`)
return normalizedInput === normalizedOutput
},
saveDevices () {
this.saveInputdevice(this.audioInputDevices[this.selectedInput])
this.saveOutputDevice(this.audioOutputDevices[this.selectedOutput])
this.$router.push(this.localePath('/onboarding'))
},
getUserMedia () {
const constraints = {
audio: { deviceId: this.selectedDevice ? { exact: this.selectedDevice } : undefined }
}
try {
return navigator.mediaDevices.getUserMedia(constraints)
} catch (error) {
this.$toast.error('Error accessing media devices: ', error)
}
},
async handleInputChange () {
await this.switchMicrophone(this.selectedInput)
this.checkIfSameDevice()
if (this.$refs.AudioReactiveBar) {
this.$refs.AudioReactiveBar.updateMicrophone(this.selectedInput)
}
}
}
}
</script>
<style>
.progress-container {
display: flex;
flex-direction: column; /* Elemente werden vertikal angeordnet */
align-items: center; /* Zentriert die Progressbar und den Button horizontal */
}
.checklabel:hover{
border-color: #e9c046;
}
.checklabel {
color: #e9c046 !important;
border: 1px solid #e9c046;
}
.checkmark .checklabel svg path{
/*background-color: white;*/
fill: #e9c046;
}
.checkmark input:checked ~ .checklabel {
background-color: #e9c046;
border: 1px solid #e9c046;
color: #f4f5f7 !important;
}
.checkmark input:checked ~ .checklabel svg path {
fill: white;
}
.checkmark input:hover ~ .checklabel {
background-color: #e9c046;
border: 1px solid #e9c046;
color: #f4f5f7 !important;
}
.checkmark input:hover ~ .checklabel svg path {
fill: white;
}
.tooltip {
position: relative;
display: inline-block;
cursor: pointer;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 200px;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 4px;
padding: 5px;
position: absolute;
z-index: 1;
bottom: 125%; /* Position above the text */
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}
.bar{
background-color: #e9c046 !important;
}
.checklabel{
background-color: white !important;
width: 150px ;
height: 134px ;
}
.px-4{
transition: 1s;
}
.content {
background-color: rgba(255, 255, 255, 0.6);
border-radius: 10px;
padding: 4.5em;
max-width: 1120px;
margin: 10% auto;
min-height: 50vh;
max-height: 75vh;
overflow-y: scroll;
}
@media only screen and (max-width: 768px) {
.content {
padding: 4.5em 3em;
}
}
@media only screen and (max-width: 576px) {
.content {
padding: 2em 1em;
margin: 2.5em auto;
overflow-y: scroll;
max-height: 75vh;
}
}
.nav-buttons {
position: fixed;
bottom: 0px;
left: 0;
right: 0;
background: rgb(255,255,255);
background: linear-gradient(0deg, rgba(255,255,255,1) 20%, rgba(255,255,255,0) 100%);
}
.checkmark {
background-color: transparent;
border: none;
}
</style>