inputItem v1

This commit is contained in:
Enrique Hernandez 2021-03-07 18:41:22 -06:00
commit f2a240d803
18 changed files with 249 additions and 1072 deletions

View file

@ -0,0 +1,80 @@
/*
* Controls which input to visualize
* Will visualize text input by default as user types or
* if user holds space bar down, input audio stream
* will be visualized & recorded
*/
import { ref, watch, onUnmounted, onMounted } from "vue";
import useKeyDownHandler from "@/modules/keyDownHandler/useKeyDownHandler";
import useMitt from "@/modules/mitt";
import { useIpc } from '@/modules/ipc';
export default function useInputController() {
const isRecording = ref(false);
const isTyping = ref(false);
const { emitter } = useMitt();
const { post } = useIpc();
// send message on ENTER
const enterCallback = (input: string) => {
const message = {
audio: 0,
text: input
};
// trigger send animation
emitter.emit("animate-send");
// send message to backend
if (input) post('message', message);
}
const { keyDownHandler, input } = useKeyDownHandler(enterCallback);
// stops stream recording on space key up
function keyupHandler(e: any) {
if (e.key === " " && isRecording.value) {
isRecording.value = false;
post('update-recorder', isRecording.value);
input.value = ''
}
}
onMounted(async () => {
// add window event keyboard listeners
window.addEventListener("keydown", keyDownHandler);
window.addEventListener('keyup', keyupHandler);
})
onUnmounted(() => {
window.removeEventListener("keydown", keyDownHandler);
window.removeEventListener("keyup", keyupHandler);
});
// determine whether to render text or audio based one the keyboard input
watch(input, (input, prevInput) => {
if (prevInput !== "" || prevInput.length > 0) {
if (!isRecording.value) {
isTyping.value = true;
}
return;
}
if (input === " " && isRecording.value === false) {
// isTyping.value = false;
isRecording.value = true;
post('update-recorder', isRecording.value);
return;
}
isTyping.value = true;
});
return {
input,
isRecording,
isTyping
}
}

View file

@ -0,0 +1,177 @@
<template>
<div
id="inputItem"
class="input-item"
:class="{ playing: isRecording }"
:style="{ top: `${elementY}px`, left: `${elementX}px` }"
>
<span v-if="isRecording" class="play"></span>
<span v-if="isRecording" class="pause"></span>
<div class="text-input" v-show="isTyping && input.length > 0">
<div class="initials">A</div>
<input id="textInput" type="text" />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import draggify from "@/modules/draggify";
import useInputController from "./inputController";
export default defineComponent({
name: "InputItem",
setup() {
const { elementX, elementY } = draggify({ elementId: "inputItem" });
const { input, isRecording, isTyping } = useInputController();
return {
elementX,
elementY,
isRecording,
isTyping,
input,
};
},
});
</script>
<style lang="scss" scoped>
.text-input {
position: absolute;
top: 50%;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
left: 50%;
background-color: #fff;
transform: translate(-12%, -50%);
border-radius: 25px;
input {
border-top-right-radius: 25px;
border-bottom-right-radius: 25px;
padding-top: 10px;
padding-bottom: 10px;
outline: none;
border: none;
pointer-events: none;
}
.initials {
border-radius: 50%;
width: 35px;
height: 35px;
display: flex;
text-align: center;
justify-content: center;
align-items: center;
}
}
.input-item {
position: absolute;
width: 30px;
height: 30px;
border-radius: 19px;
z-index: 20;
top: 200px;
right: 0px;
background-color: white;
border: 4px solid #C3C3C3;
cursor: pointer;
.play,
.pause {
z-index: 5;
&::before,
&::after {
-webkit-border-radius: 1000px;
-moz-border-radius: 1000px;
border-radius: 1000px;
content: "";
position: absolute;
height: 2.35em;
width: 2.35em;
left: 50%;
transform: translate(-50%, -50%);
top: 50%;
z-index: 0;
}
}
.play::before {
box-shadow: 0 0 0 rgba(195, 195, 195, 0);
}
.pause {
opacity: 0;
}
&.playing {
.play {
opacity: 0;
}
.pause {
opacity: 1;
&::before {
-moz-animation: audio1 1.5s infinite ease-in-out;
-o-animation: audio1 1.5s infinite ease-in-out;
-webkit-animation: audio1 1.5s infinite ease-in-out;
animation: audio1 1.5s infinite ease-in-out;
}
&::after {
-moz-animation: audio2 2.2s infinite ease-in-out;
-o-animation: audio2 2.2s infinite ease-in-out;
-webkit-animation: audio2 2.2s infinite ease-in-out;
animation: audio2 2.2s infinite ease-in-out;
}
}
}
}
.animate-audio1 {
-moz-animation: audio1 1.5s infinite ease-in-out;
-o-animation: audio1 1.5s infinite ease-in-out;
-webkit-animation: audio1 1.5s infinite ease-in-out;
animation: audio1 1.5s infinite ease-in-out;
}
@keyframes audio1 {
0%,
100% {
box-shadow: 0 0 0 0.4em rgba(195, 195, 195, 0.4);
}
25% {
box-shadow: 0 0 0 0.15em rgba(195, 195, 195, 0.15);
}
50% {
box-shadow: 0 0 0 0.55em rgba(195, 195, 195, 0.55);
}
75% {
box-shadow: 0 0 0 0.25em rgba(195, 195, 195, 0.25);
}
}
.animate-audio2 {
-moz-animation: audio2 2.2s infinite ease-in-out;
-o-animation: audio2 2.2s infinite ease-in-out;
-webkit-animation: audio2 2.2s infinite ease-in-out;
animation: audio2 2.2s infinite ease-in-out;
}
@keyframes audio2 {
0%,
100% {
box-shadow: 0 0 0 0.25em rgba(195, 195, 195, 0.15);
}
25% {
box-shadow: 0 0 0 0.4em rgba(195, 195, 195, 0.3);
}
50% {
box-shadow: 0 0 0 0.15em rgba(195, 195, 195, 0.05);
}
75% {
box-shadow: 0 0 0 0.55em rgba(195, 195, 195, 0.45);
}
}
</style>