This commit is contained in:
Andrew Gundersen 2021-03-14 13:25:19 -05:00
commit ed71b603fd
6 changed files with 93 additions and 78 deletions

View file

@ -5,8 +5,7 @@ import { backgroundMitt } from './emitter';
import { ipcMain } from "electron"; import { ipcMain } from "electron";
import { play } from './audio'; import { play } from './audio';
import { UserCreds, ClientMessage, RenderMessage, Annotation } from "@/types/message/index"; import { UserCreds, ClientMessage, RenderMessage, Annotation } from "@/types/message/index";
import { clientMessage, initRenderMessageFromString } from '@/modules/message'; import { clientMessage, renderMessage } from '@/modules/message';
import { v4 as uuidv4 } from 'uuid';
const ip = 'ws://127.0.0.1'; const ip = 'ws://127.0.0.1';
const port = 8760; const port = 8760;
@ -43,20 +42,25 @@ const onAuthSession = async (e: any, payload: string | UserCreds | null): Promis
}); });
}; };
const onMessage = (message_str: string): void => { const onMessage = (messageStr: string): void => {
while (!auth) { while (!auth) {
backgroundMitt.emit('auth-res', message_str); backgroundMitt.emit('auth-res', messageStr);
return; return;
} }
// Decode the message. // Decode the message.
const m = JSON.parse(message_str) const m = JSON.parse(messageStr)
let message: RenderMessage | Annotation; let message: RenderMessage | Annotation;
// Check to see if this is a Render Message. // Check to see if this is a Render Message.
if (m.content) { if (m.content) {
message = initRenderMessageFromString(message_str) message = renderMessage({
text: m.content.text,
audio: m.content.audio,
context: m.context,
modifier: m.modifier,
});
// Play audio if any. // Play audio if any.
if (message.content.audio) { if (message.content.audio) {

View file

@ -10,10 +10,33 @@ import useMitt from "@/modules/mitt";
import { useIpc } from '@/modules/ipc'; import { useIpc } from '@/modules/ipc';
import keyboardNameMap from "./keyBoardMaps/keyboardNameMap"; import keyboardNameMap from "./keyBoardMaps/keyboardNameMap";
import keyboardCharMap from "./keyBoardMaps/keyboardCharMap"; import keyboardCharMap from "./keyBoardMaps/keyboardCharMap";
import {clientMessage, initRenderMessage} from '@/modules/message'; import anime from "animejs";
import { clientMessage, renderMessage } from '@/modules/message';
let textInput: HTMLInputElement | null; let textInput: HTMLInputElement | null;
// 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() { export default function useInputController() {
const { emitter } = useMitt(); const { emitter } = useMitt();
@ -21,20 +44,26 @@ export default function useInputController() {
const isRecording = ref(false); const isRecording = ref(false);
const isTyping = ref(false); const isTyping = ref(false);
const input = ref(""); const input = ref("");
const capsLock = ref(false);
// Utility function to render message.
const render = (text: string, audio: boolean | string, context: string, modifier: string): string => {
const m = renderMessage({ text, audio, context, modifier });
emitter.emit("self-message", m);
console.log(m.time)
return m.uid;
}
// send message on ENTER. // send message on ENTER.
const onEnter = () => { const onEnter = () => {
if (input.value) { if (input.value) {
// remove first character of input.
const text = input.value.substring(1);
// Render the message immediately. // Render the message immediately and get its unique id.
const message = initRenderMessage(text, "", "", "sf"); const uid = render(input.value, false, "", "sf");
emitter.emit("self-message", message);
// Then send it to the backend for processing. // Then send it to the backend for processing.
const clientM = clientMessage(text, false, message.uid); const clientM = clientMessage(input.value, false, uid);
post('client-message', clientM); post('client-message', clientM);
// Reset the text input. // Reset the text input.
@ -46,8 +75,10 @@ export default function useInputController() {
// update input on keydown event & listen for special commands. // update input on keydown event & listen for special commands.
const onKeyDown = (e: KeyboardEvent) => { const onKeyDown = (e: KeyboardEvent) => {
if (textInput) {
if (textInput) textInput.focus(); textInput.focus();
textInput.value = input.value;
}
// keyboardCharMap is an array of arrays, with each inner // keyboardCharMap is an array of arrays, with each inner
// array having 2 columns - un-shifted, and shifted values. // array having 2 columns - un-shifted, and shifted values.
@ -56,7 +87,7 @@ export default function useInputController() {
// MODIFY keyboardCharMap to suit your needs if you want // MODIFY keyboardCharMap to suit your needs if you want
// more/less/different characters to be considered "printable". // more/less/different characters to be considered "printable".
let iCol = 0; let iCol = 0;
if (e.shiftKey) { if (e.shiftKey || capsLock.value) {
iCol = 1; iCol = 1;
} }
@ -73,13 +104,18 @@ export default function useInputController() {
break; break;
case "BACK_SPACE": case "BACK_SPACE":
input.value = input.value.slice(0, -1); input.value = input.value.slice(0, -1);
break; break;
case "CAPS_LOCK":
capsLock.value = true;
break;
case "ESCAPE": case "ESCAPE":
if (textInput) textInput.value = '' if (textInput) textInput.value = ''
input.value = ""; input.value = "";
break; break;
default: default:
input.value += ch; input.value += ch;
input.value.trim();
break;
} }
} }
@ -90,19 +126,20 @@ export default function useInputController() {
isRecording.value = false; isRecording.value = false;
// Render the message immediately. // // Render the message immediately and get its unique id.
const audioMessage = initRenderMessage("", "", "", "sf") const uid = render("", "", "", "sf");
emitter.emit("self-message", audioMessage); // Notify main process to stop recording and send send audio to backend for analysis.
// Notify backend to stop recording and send audio to python backend for audio processing.
post('update-recorder', { post('update-recorder', {
isRecording: isRecording.value, isRecording: isRecording.value,
uid: audioMessage.uid uid
}); });
// Reset input. // Reset input.
input.value = '' input.value = ''
} }
else if (e.code === "CapsLock") {
capsLock.value = false;
}
} }
onMounted(() => { onMounted(() => {
@ -117,19 +154,22 @@ export default function useInputController() {
window.removeEventListener("keyup", onKeyUp); window.removeEventListener("keyup", onKeyUp);
}); });
// watch keyboard input & update current state. // watch keyboard input & update inputItem state.
watch(input, (input, prevInput) => { watch(input, (input, prevInput) => {
if (isTyping.value && input.length === 0) {
retractInput();
}
// Do nothing if user is typing.
if (prevInput !== "" || prevInput.length > 0) { if (prevInput !== "" || prevInput.length > 0) {
if (!isRecording.value) {
isTyping.value = true;
}
return; return;
} }
// Begin stream recording on space bar.
if (input === " " && isRecording.value === false) { if (input === " " && isRecording.value === false) {
isTyping.value = false; isTyping.value = false;
isRecording.value = true; isRecording.value = true;
// tell main process to begin stream recording.
post('update-recorder', { post('update-recorder', {
isRecording: isRecording.value, isRecording: isRecording.value,
uid: null uid: null
@ -138,11 +178,10 @@ export default function useInputController() {
} }
isTyping.value = true; isTyping.value = true;
expandInput()
}); });
return { return {
input,
isRecording, isRecording,
isTyping isTyping
} }

View file

@ -13,7 +13,7 @@
</span> </span>
<!-- Show text input on key-down --> <!-- Show text input on key-down -->
<input id="textInput" type="text" v-show="isTyping && input.length > 0"/> <input id="textInput" type="text" />
</div> </div>
</template> </template>
@ -31,15 +31,14 @@ export default defineComponent({
// Calculate position of inputItem on drag. // Calculate position of inputItem on drag.
const { elementX, elementY } = draggify({ elementId: "inputItem" }); const { elementX, elementY } = draggify({ elementId: "inputItem" });
// // determine whether the user is typing or recording.
const { input, isRecording, isTyping } = useInputController(); const { isRecording, isTyping } = useInputController();
return { return {
elementX, elementX,
elementY, elementY,
isRecording, isRecording,
isTyping, isTyping,
input,
}; };
}, },
}); });
@ -48,7 +47,7 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
#textInput { #textInput {
width: 150px; width: 0px;
height: 36px; height: 36px;
border-top-right-radius: 18px; border-top-right-radius: 18px;
@ -60,17 +59,6 @@ export default defineComponent({
outline: none; outline: none;
border: none; border: none;
pointer-events: none; pointer-events: none;
animation-name: expand;
animation-duration: 0.5s;
}
@keyframes expand {
from {
width: 0px;
}
to {
width: 150px;
}
} }
.rec-icon { .rec-icon {

View file

@ -133,6 +133,7 @@
margin: 2px; margin: 2px;
border-radius: 2.5px; border-radius: 2.5px;
background-color: #9B9B9B; background-color: #9B9B9B;
} }
.settingsOption { .settingsOption {

View file

@ -4,7 +4,6 @@ import App from "./App.vue";
import router from "./router"; import router from "./router";
import mitt from "mitt"; import mitt from "mitt";
import anime from "animejs";
import { createApp } from "vue"; import { createApp } from "vue";
@ -14,6 +13,5 @@ const emitter = mitt();
const app = createApp(App) const app = createApp(App)
app.use(router) app.use(router)
app.provide("animejs", anime)
app.provide("mitt", emitter) app.provide("mitt", emitter)
app.mount("#app"); app.mount("#app");

View file

@ -1,47 +1,32 @@
import { RenderMessage, ClientMessage } from "@/types/message/index"; import { RenderMessage, ClientMessage } from "@/types/message/index";
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
// Create a RenderMessage object directly from json string. interface RenderParams {
export function initRenderMessageFromString(messageStr: string) { text: string;
audio: boolean | string;
context: string;
modifier: string;
}
// Parse the string. function getTimeStamp(): number {
const m = JSON.parse(messageStr);
// Auto set uid and time.
const currentdate = new Date(); const currentdate = new Date();
return currentdate.getTime();
const message: RenderMessage = {
content: m.content,
context: m.context,
modifier: m.modifier,
time: currentdate.getTime(),
uid: uuidv4(),
isChild: "none"
}
return message
} }
// Create a RenderMessage object. // Create a RenderMessage object.
export function initRenderMessage(text: string, audio: string, context: string, modifier: string) { export const renderMessage = (params: RenderParams): RenderMessage => (
{
// Auto set uid and time.
const currentdate = new Date();
const message: RenderMessage = {
content: { content: {
text: text, text: params.text,
audio: audio audio: params.audio
}, },
context: context, context: params.context,
modifier: modifier, modifier: params.modifier,
time: currentdate.getTime(), time: getTimeStamp(),
uid: uuidv4(), uid: uuidv4(),
isChild: "none" isChild: "none"
} }
)
return message
}
export const clientMessage = (text: string, audio: string | boolean, uid: string): ClientMessage => ( export const clientMessage = (text: string, audio: string | boolean, uid: string): ClientMessage => (
{ {