add input expand and retract animations as well as minor improvements
This commit is contained in:
parent
930f6fa6b7
commit
65e8a8eb86
4 changed files with 56 additions and 34 deletions
|
|
@ -13,11 +13,34 @@ import keyboardCharMap from "./keyBoardMaps/keyboardCharMap";
|
|||
import { RenderMessage, ClientMessage } from "@/types/message/index";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import {clientMessage, renderMessage} from '@/modules/message';
|
||||
import anime from "animejs";
|
||||
|
||||
let textInput: HTMLInputElement | null;
|
||||
let m: RenderMessage | ClientMessage;
|
||||
let uid: string;
|
||||
|
||||
// Animation functions for text input element.
|
||||
function expandInput() {
|
||||
anime({
|
||||
targets: textInput,
|
||||
width: ['0px', '150px'],
|
||||
duration: 500,
|
||||
easing: 'easeOutExpo',
|
||||
})
|
||||
}
|
||||
|
||||
function retractInput() {
|
||||
anime({
|
||||
targets: textInput,
|
||||
width: ['150px', '0px'],
|
||||
duration: 500,
|
||||
easing: 'easeOutExpo',
|
||||
begin: function() {
|
||||
if (textInput) textInput.blur();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default function useInputController() {
|
||||
|
||||
const { emitter } = useMitt();
|
||||
|
|
@ -25,24 +48,23 @@ export default function useInputController() {
|
|||
const isRecording = ref(false);
|
||||
const isTyping = ref(false);
|
||||
const input = ref("");
|
||||
const capsLock = ref(false);
|
||||
|
||||
// send message on ENTER.
|
||||
const onEnter = () => {
|
||||
|
||||
if (input.value) {
|
||||
// remove first character of input.
|
||||
const text = input.value.substring(1);
|
||||
|
||||
uid = uuidv4();
|
||||
|
||||
m = renderMessage(text, false, "sf", uid);
|
||||
m = renderMessage(input.value, false, "sf", uid);
|
||||
|
||||
// render user message.
|
||||
emitter.emit("self-message", m);
|
||||
|
||||
m = clientMessage(m.content.text, m.content.audio, uid);
|
||||
|
||||
// send message to backend.
|
||||
// send message to main process.
|
||||
post('client-message', m);
|
||||
|
||||
// reset text input.
|
||||
|
|
@ -54,8 +76,10 @@ export default function useInputController() {
|
|||
|
||||
// update input on keydown event & listen for special commands.
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
|
||||
if (textInput) textInput.focus();
|
||||
if (textInput) {
|
||||
textInput.focus();
|
||||
textInput.value = input.value;
|
||||
}
|
||||
|
||||
// keyboardCharMap is an array of arrays, with each inner
|
||||
// array having 2 columns - un-shifted, and shifted values.
|
||||
|
|
@ -64,7 +88,7 @@ export default function useInputController() {
|
|||
// MODIFY keyboardCharMap to suit your needs if you want
|
||||
// more/less/different characters to be considered "printable".
|
||||
let iCol = 0;
|
||||
if (e.shiftKey) {
|
||||
if (e.shiftKey || capsLock.value) {
|
||||
iCol = 1;
|
||||
}
|
||||
|
||||
|
|
@ -81,13 +105,18 @@ export default function useInputController() {
|
|||
break;
|
||||
case "BACK_SPACE":
|
||||
input.value = input.value.slice(0, -1);
|
||||
break;
|
||||
break;
|
||||
case "CAPS_LOCK":
|
||||
capsLock.value = true;
|
||||
break;
|
||||
case "ESCAPE":
|
||||
if (textInput) textInput.value = ''
|
||||
input.value = "";
|
||||
break;
|
||||
default:
|
||||
input.value += ch;
|
||||
input.value.trim();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -112,6 +141,9 @@ export default function useInputController() {
|
|||
|
||||
input.value = ''
|
||||
}
|
||||
else if (e.code === "CapsLock") {
|
||||
capsLock.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
|
@ -126,21 +158,23 @@ export default function useInputController() {
|
|||
window.removeEventListener("keyup", onKeyUp);
|
||||
});
|
||||
|
||||
// watch keyboard input & update current state.
|
||||
watch(input, (input, prevInput) => {
|
||||
|
||||
//
|
||||
// watch keyboard input & update inputItem state.
|
||||
watch(input, (input, prevInput) => {
|
||||
if (isTyping.value && input.length === 0) {
|
||||
retractInput();
|
||||
}
|
||||
|
||||
// Do nothing if user is typing.
|
||||
if (prevInput !== "" || prevInput.length > 0) {
|
||||
if (!isRecording.value) {
|
||||
isTyping.value = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Begin stream recording on space bar.
|
||||
if (input === " " && isRecording.value === false) {
|
||||
isTyping.value = false;
|
||||
isRecording.value = true;
|
||||
// tell main process to begin stream recording.
|
||||
post('update-recorder', {
|
||||
isRecording: isRecording.value,
|
||||
uid: null
|
||||
|
|
@ -149,11 +183,10 @@ export default function useInputController() {
|
|||
}
|
||||
|
||||
isTyping.value = true;
|
||||
|
||||
expandInput()
|
||||
});
|
||||
|
||||
return {
|
||||
input,
|
||||
isRecording,
|
||||
isTyping
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
</span>
|
||||
|
||||
<!-- Show text input on key-down -->
|
||||
<input id="textInput" type="text" v-show="isTyping && input.length > 0"/>
|
||||
<input id="textInput" type="text" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -31,15 +31,14 @@ export default defineComponent({
|
|||
// Calculate position of inputItem on drag.
|
||||
const { elementX, elementY } = draggify({ elementId: "inputItem" });
|
||||
|
||||
//
|
||||
const { input, isRecording, isTyping } = useInputController();
|
||||
// determine whether the user is typing or recording.
|
||||
const { isRecording, isTyping } = useInputController();
|
||||
|
||||
return {
|
||||
elementX,
|
||||
elementY,
|
||||
isRecording,
|
||||
isTyping,
|
||||
input,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
@ -48,7 +47,7 @@ export default defineComponent({
|
|||
<style lang="scss" scoped>
|
||||
|
||||
#textInput {
|
||||
width: 150px;
|
||||
width: 0px;
|
||||
height: 36px;
|
||||
|
||||
border-top-right-radius: 18px;
|
||||
|
|
@ -60,17 +59,6 @@ export default defineComponent({
|
|||
outline: none;
|
||||
border: none;
|
||||
pointer-events: none;
|
||||
animation-name: expand;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
|
||||
@keyframes expand {
|
||||
from {
|
||||
width: 0px;
|
||||
}
|
||||
to {
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.rec-icon {
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@
|
|||
|
||||
z-index: 2;
|
||||
background-color: #EBEBEB;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.settingsButtonDot {
|
||||
|
|
@ -128,6 +130,7 @@
|
|||
margin: 2px;
|
||||
border-radius: 2.5px;
|
||||
background-color: #9B9B9B;
|
||||
|
||||
}
|
||||
|
||||
.settingsOption {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import App from "./App.vue";
|
|||
import router from "./router";
|
||||
|
||||
import mitt from "mitt";
|
||||
import anime from "animejs";
|
||||
import { createApp } from "vue";
|
||||
|
||||
|
||||
|
|
@ -14,6 +13,5 @@ const emitter = mitt();
|
|||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
app.provide("animejs", anime)
|
||||
app.provide("mitt", emitter)
|
||||
app.mount("#app");
|
||||
|
|
|
|||
Loading…
Reference in a new issue