Files
zeroone/src/renderer/src/components/device/DevicePreview.vue
2024-03-13 03:14:08 +01:00

202 lines
6.2 KiB
Vue

<template>
<div class="aspect-[800/1100]">
<div
class="relative size-full bg-contain bg-top bg-no-repeat"
:style="{
backgroundImage: `linear-gradient(to bottom, black, rgba(0,0,0,0.25) 12%, rgba(0,0,0,0.35) 95%, black), url(${previewDeviceImage})`,
backgroundBlendMode: 'multiply'
}"
>
<Transition name="fade">
<div v-if="deviceStore.connected" class="flex h-12 items-center justify-between px-10">
<h2>
<ScrambleText
:delay="100"
scramble-on-mount
:fill-interval="50"
:replace-interval="50"
text="Nano_D++"
/>
</h2>
<div class="font-mono text-sm">
<span class="text-muted-foreground">Firmware: </span>
<ScrambleText
:delay="100"
scramble-on-mount
:fill-interval="50"
:replace-interval="50"
text="v1.3.2a"
/>
</div>
</div>
</Transition>
<Transition name="fade-delayed">
<DeviceLEDRing
v-if="deviceStore.connected"
:value="barValue"
class="absolute inset-x-0 top-[12.5%] mx-auto h-[66%]"
/>
</Transition>
<div
class="absolute inset-x-0 top-[30.5%] mx-auto flex aspect-square h-[30%] flex-col items-center justify-center overflow-hidden rounded-full"
style="background: linear-gradient(45deg, black 30%, #252525 50%, #232323 60%, black)"
>
<TransitionGroup name="fade-display">
<div
v-if="deviceStore.connected"
class="absolute flex flex-col items-center pb-2 text-center mix-blend-screen"
>
<img :src="LogoMidi" alt="midi-logo" class="h-4 opacity-50" />
<h2 class="font-pixellg text-5xl">
{{ parseInt(barValue - deviceStore.turns * 100) }}
</h2>
<div class="font-pixelsm text-md">HIGH PASS</div>
<DeviceBar :value="barValue" :count="30" :width="120" />
<span class="font-pixelsm w-36 text-[7pt] uppercase text-muted-foreground">
KORG MINILOGUE HIGH PASS FILTER 0-127
</span>
</div>
<div v-else class="flex flex-col items-center text-center mix-blend-screen">
<ScrambleText
:text="offlineText"
character-set="_()*=0011"
scramble-on-mount
:delay="1000"
:fill-interval="50"
:replace-interval="50"
class="font-pixelsm text-[7pt] uppercase text-muted-foreground"
@finish="nextOfflineText"
/>
</div>
</TransitionGroup>
</div>
<Transition name="fade-delayed">
<button
v-if="deviceStore.connected"
class="absolute inset-x-0 top-[24.5%] mx-auto aspect-square h-[41.5%] rounded-full outline-2 transition-all"
:class="{
'outline outline-white': appStore.selectedFeature === 'knob',
'outline-zinc-400 hover:outline': appStore.selectedFeature !== 'knob'
}"
@click="appStore.selectConfigFeature('knob')"
/>
</Transition>
<Transition name="fade-delayed">
<DeviceKeys
v-if="deviceStore.connected"
:keys="keyColors"
class="absolute inset-x-0 top-[77.5%] mx-auto w-[72.7%] gap-[2.2%]"
:selected="appStore.selectedFeature === 'key' ? appStore.selectedKey : ''"
@select="appStore.selectKey"
/>
</Transition>
</div>
</div>
</template>
<script setup>
import RenderNanoOne from '@renderer/assets/images/renderNanoOneTransparent.png'
import RenderNanoZero from '@renderer/assets/images/renderNanoZeroTransparent.png'
import LogoMidi from '@renderer/assets/logos/logoMidi.svg'
import DeviceBar from '@renderer/components/device/DeviceBar.vue'
import { useAppStore } from '@renderer/appStore'
import { useDeviceStore } from '@renderer/deviceStore'
import ScrambleText from '@renderer/components/common/ScrambleText.vue'
import { computed, ref } from 'vue'
import DeviceLEDRing from '@renderer/components/device/DeviceLEDRing.vue'
import DeviceKeys from '@renderer/components/device/DeviceKeys.vue'
import { storeToRefs } from 'pinia'
import Color from 'color'
const appStore = useAppStore()
const deviceStore = useDeviceStore()
const barValue = computed(() => 100 - (deviceStore.angle / Math.PI / 2) * 100)
const previewDeviceImages = {
nanoOne: RenderNanoOne,
nanoZero: RenderNanoZero
}
const previewDeviceImage = computed(
() => previewDeviceImages[appStore.previewDeviceModel || 'nanoOne']
)
const { keyColor } = storeToRefs(deviceStore)
const keyColors = computed(() => {
return {
a: Color(keyColor.value('a', deviceStore.keyStates.a)),
b: Color(keyColor.value('b', deviceStore.keyStates.b)),
c: Color(keyColor.value('c', deviceStore.keyStates.c)),
d: Color(keyColor.value('d', deviceStore.keyStates.d))
}
})
const offlineText = ref('NO DEVICE CONNECTED')
const offlineTexts = [
'AWAITING CONNECTION',
'ARE YOU STILL THERE?',
'DEVICE OFFLINE',
'AWAITING CONNECTION',
'I MISS YOU',
'AWAITING CONNECTION',
'NO DEVICE CONNECTED',
'IS ANYONE THERE?',
'AWAITING CONNECTION',
'DEVICE OFFLINE',
'NAP TIME',
'NO DEVICE CONNECTED'
]
let offlineTextIndex = 0
const nextOfflineText = () => {
if (offlineText.value === '') {
offlineText.value = offlineTexts[offlineTextIndex]
offlineTextIndex = (offlineTextIndex + 1) % offlineTexts.length
} else {
setTimeout(() => {
offlineText.value = ''
}, 3500)
}
}
</script>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 500ms ease;
}
.fade-slow-enter-active,
.fade-slow-leave-active,
.fade-delayed-enter-active,
.fade-delayed-leave-active {
transition: opacity 1000ms ease;
}
.fade-delayed-enter-active,
.fade-slow-enter-active {
transition-delay: 150ms;
}
.fade-display-enter-active,
.fade-display-leave-active {
transition: opacity 500ms ease;
}
.fade-display-enter-active {
transition-delay: 1000ms;
}
.fade-enter-from,
.fade-leave-to,
.fade-slow-enter-from,
.fade-slow-leave-to,
.fade-delayed-enter-from,
.fade-delayed-leave-to,
.fade-display-enter-from,
.fade-display-leave-to {
opacity: 0;
}
</style>