Initial commit
This commit is contained in:
379
pages/fixproblem.vue
Normal file
379
pages/fixproblem.vue
Normal file
@@ -0,0 +1,379 @@
|
||||
<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>
|
Reference in New Issue
Block a user