]> Repos - mime-chat/commitdiff
improvments
authorAndrew Gundersen <gundersena@xavier.edu>
Wed, 17 Mar 2021 14:32:32 +0000 (09:32 -0500)
committerAndrew Gundersen <gundersena@xavier.edu>
Wed, 17 Mar 2021 14:32:32 +0000 (09:32 -0500)
src/components/inputItem/controllers/audioCtrl.ts [new file with mode: 0644]
src/components/inputItem/controllers/textCtrl.ts [new file with mode: 0644]
src/components/inputItem/inputController.ts [deleted file]
src/components/inputItem/inputItem.vue
src/components/inputItem/menu.vue [deleted file]
src/components/inputItem/menuController.ts [deleted file]
src/components/inputItem/textInput.vue
src/modules/draggify.ts

diff --git a/src/components/inputItem/controllers/audioCtrl.ts b/src/components/inputItem/controllers/audioCtrl.ts
new file mode 100644 (file)
index 0000000..723d31a
--- /dev/null
@@ -0,0 +1,78 @@
+import { onMounted } from "vue";
+import useMitt from "@/modules/mitt";
+import { useIpc } from '@/modules/ipc';
+import keyboardNameMap from "../keyBoardMaps/keyboardNameMap";
+import { renderMessage } from '@/modules/message';
+
+
+
+
+
+
+export default function useAudioInputController () {
+
+    // For sending messages.
+    const { post } = useIpc();
+    const { emitter } = useMitt();
+
+    // Keepp track of when we are recording.
+    let recording = 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);
+        return m.uid;
+    }
+
+    //---Callbacks-----------------------------------------------
+
+    const onKeyDown = (e: KeyboardEvent) => {
+        const cmd = keyboardNameMap[e.keyCode];
+
+        // Start recording on space bar.
+        if (cmd == "SPACE" && !recording) {
+
+            post('update-recorder', {
+                isRecording: true,
+                uid: null
+            });
+
+            recording = true;
+
+        }
+
+    }
+
+    const onKeyUp = (e: KeyboardEvent) => {
+        const cmd = keyboardNameMap[e.keyCode];
+
+        // Stop recording on space up.
+        if (cmd == "SPACE" && recording) {
+
+            // Render audio immediately.
+            const uid = render("", "", "", "sf");
+
+            post('update-recorder', {
+                isRecording: false,
+                uid: uid
+            });
+
+            recording = false;
+
+        }
+
+    }
+
+    //-----------------------------------------------------------
+
+    onMounted(() => {
+        window.addEventListener("keydown", onKeyDown);
+        window.addEventListener("keyup", onKeyUp);
+    })
+
+    return {
+        recording
+    }
+
+}
diff --git a/src/components/inputItem/controllers/textCtrl.ts b/src/components/inputItem/controllers/textCtrl.ts
new file mode 100644 (file)
index 0000000..0955096
--- /dev/null
@@ -0,0 +1,173 @@
+import anime from "animejs";
+import useMitt from "@/modules/mitt";
+import { useIpc } from '@/modules/ipc';
+import { Ref, watch, onMounted } from "vue";
+import keyboardNameMap from "../keyBoardMaps/keyboardNameMap";
+import { clientMessage, renderMessage } from '@/modules/message';
+
+// Post a message to the backend.
+const { post } = useIpc();
+
+
+//---Animations-----------------------------------------------
+
+let side = "right"; // Side of parent we are on.
+let visible = false; // Whether textInput is visible.
+
+function showTextInput () {
+    let t1 = (side === "right") ? 50 : -70;
+    let t2 = (side === "right") ? 110 : -130;
+
+    anime({
+        targets: '#textInput',
+        opacity: [0, 1],
+        translateX: [t1, t2],
+        scale: [0.3, 1],
+        duration: 500,
+        easing: 'easeOutExpo', 
+    })
+
+    visible = true
+}
+
+function hideTextInput() {
+    let t = (side === "right") ? 50 : -80;
+
+    anime({
+        targets: '#textInput',
+        opacity: 0,
+        translateX: t,
+        scale: 0.3,
+        duration: 500,
+        easing: 'easeOutExpo', 
+    })
+
+    visible = false
+}
+
+function switchSide(currentSide: string) {
+    let t = (currentSide === "right") ? -130 : 110;
+
+    anime({
+        targets: '#textInput',
+        translateX: t,
+        duration: 500,
+        easing: 'easeOutExpo', 
+    })
+
+}
+
+//------------------------------------------------------------
+
+
+export default function useTextInputController(elementX: Ref) {
+    let textInput: HTMLInputElement | null;
+
+    let length: number;
+
+    // For sending messages.
+    const { post } = useIpc();
+    const { emitter } = useMitt();
+
+    // Keep track of first key press.
+    let firstKey = true;
+
+    // Clear text input.
+    const clearInput = () => {
+        if (textInput) textInput.value = "";
+        hideTextInput()
+        firstKey = true;
+    }
+
+    // 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);
+        return m.uid;
+    }
+
+    // Send a message and clean up after.
+    const sendMessage = () => {
+        if (textInput) {
+
+            // Render message
+            const uid = render(textInput.value, false, "", "sf");
+
+            // Send it to the backend for processing.
+            const clientM = clientMessage(textInput.value, false, uid);
+            post('client-message', clientM);
+        }
+    }
+
+    //---Callbacks-----------------------------------------------
+
+    const onKeyDown = (e: KeyboardEvent) => {
+        
+        if (textInput) {
+            const key = keyboardNameMap[e.keyCode]
+
+            // Reveal textInput on first key press.
+            if (firstKey) {
+
+                // Handle for space bar
+                if (key == "SPACE") {
+                    return
+                }
+
+                showTextInput()
+                firstKey = false
+            }
+
+            textInput.focus();
+
+            if (textInput.value == "" && !firstKey) {
+                clearInput()
+            }
+
+            if (key == "ENTER") {
+                if (textInput.value) {
+                    sendMessage()
+                    clearInput()
+                }
+            }
+
+            if (key == "ESCAPE") {
+                clearInput()
+
+            }
+        }
+    }
+
+    //-----------------------------------------------------------
+
+    // Watch parent position and update side.
+    watch(elementX, (elementX, previous) => {
+        const winW = window.innerWidth
+
+        // Logic depends on the side we are on.
+        if (side === "right") {
+            if (winW - elementX < 230) {
+                switchSide(side)
+                side = "left"
+            }
+        } 
+
+        else {
+            if (winW - elementX > 230) {
+                switchSide(side)
+                side = "right"
+            }
+        }
+        
+    });
+
+    onMounted(() => {
+        textInput = document.getElementById("textInput") as HTMLInputElement;
+        window.addEventListener("keydown", onKeyDown);
+    })
+
+    return {
+
+    }
+
+}
diff --git a/src/components/inputItem/inputController.ts b/src/components/inputItem/inputController.ts
deleted file mode 100644 (file)
index 0ef68ee..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-* Main logic used by inputItem component.
-* Will visualize text input by default as user types.
-* If user holds space bar down, input audio stream will
-* be recorded and sent to the backend for analysis.
-*/
-
-import { ref, watch, onUnmounted, onMounted } from "vue";
-import useMitt from "@/modules/mitt";
-import { useIpc } from '@/modules/ipc';
-import keyboardNameMap from "./keyBoardMaps/keyboardNameMap";
-import keyboardCharMap from "./keyBoardMaps/keyboardCharMap";
-import anime from "animejs";
-import { clientMessage, renderMessage } from '@/modules/message';
-
-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() {
-
-    const { emitter } = useMitt();
-    const { post } = useIpc();
-    const isRecording = ref(false);
-    const isTyping = ref(false);
-    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.
-    const onEnter = () => {
-
-        if (input.value) {
-
-            // Render the message immediately and get its unique id.
-            const uid = render(input.value, false, "", "sf");
-
-            // Then send it to the backend for processing.
-            const clientM = clientMessage(input.value, false, uid);
-            post('client-message', clientM);
-
-            // Reset the text input.
-            if (textInput) textInput.value = ''; 
-            input.value = " ";
-        }
-
-    }
-
-    // update input on keydown event & listen for special commands.
-    const onKeyDown = (e: KeyboardEvent) => {
-        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.
-        // iCol = 0 is the un-shifted value, while iCol=1 is the shifted value.
-        // See the "keyboardCharMap" module for possible keys.
-        // MODIFY keyboardCharMap to suit your needs if you want
-        //    more/less/different characters to be considered "printable".
-        let iCol = 0;
-        if (e.shiftKey || capsLock.value) {
-          iCol = 1;
-        }
-
-        const ch = keyboardCharMap[e.keyCode][iCol];
-
-        // Optionally do things with non-printables,
-        // like CR, ESC, Backspace, LF, Tab, Arrows, F1-F24, etc.
-        // See the arrary "keyboardNameMap" module for possible keys.
-        const cmd = keyboardNameMap[e.keyCode];
-        
-        switch (cmd) {
-          case "ENTER":
-            onEnter();
-            break;
-          case "BACK_SPACE":
-            input.value = input.value.slice(0, -1);
-            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;
-        }
-
-    }
-
-    // stop stream recording and render audio message on space key up event.
-    const onKeyUp = (e: KeyboardEvent) => {
-        if (e.key === " " && isRecording.value) {
-
-            isRecording.value = false;
-
-            // // Render the message immediately and get its unique id.
-            const uid = render("", "", "", "sf");
-            // Notify main process to stop recording and send send audio to backend for analysis.
-            post('update-recorder', {
-                isRecording: isRecording.value,
-                uid
-            }); 
-
-            // Reset input.
-            input.value = ''
-        }
-        else if (e.code === "CapsLock") {
-            capsLock.value = false;
-        }
-    }
-
-    onMounted(() => {
-        textInput = document.getElementById('textInput') as HTMLInputElement;
-        // add window event keyboard listeners        
-        window.addEventListener("keydown", onKeyDown);
-        window.addEventListener('keyup', onKeyUp);
-    })
-
-    onUnmounted(() => {
-        window.removeEventListener("keydown", onKeyDown);
-        window.removeEventListener("keyup", onKeyUp);
-    });
-
-    // 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) {
-            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
-            });
-            return;
-        }
-
-        isTyping.value = true;
-        expandInput()
-    });
-
-    return {
-        isRecording,
-        isTyping
-    }
-
-}
index ff367dcc573ebe209dcac47e8cf5adf3afde39c5..052e9dde727cb67e7efafbed4664d8ab71768a4c 100644 (file)
@@ -2,22 +2,25 @@
   <div
     id="inputItem"
     class="input-item"
-    :class="{ playing: isRecording }"
+    :class="{ playing: recording }"
     :style="{ top: `${elementY}px`, left: `${elementX}px` }"
   >
     AG
 
-    <!-- animations for recording and on-standby -->
-    <span v-if="isRecording" class="play"></span>
-    <span v-if="isRecording" class="pause">
+    <!-- Show audio input on spacebar -->
+    <AudioInput />
+
+
+    <span v-if="recording" class="play"></span>
+    <span v-if="recording" class="pause">
       <div class="rec-icon"></div>
     </span>
 
     <!-- Show text input on key-down -->
-    <TextInput :position="elementX"/>
+    <TextInput />
 
     <!-- Show suggestions menu on click -->
-    <!-- <SuggestionsMenu /> -->
+    <!-- <Menu /> -->
 
   </div>
 </template>
 
 import { defineComponent } from "vue";
 import draggify from "@/modules/draggify";
-import useInputController from "./inputController";
+
 import TextInput from "@/components/inputItem/textInput.vue"
+import useTextInputController from 
+  "@/components/inputItem/controllers/textCtrl"
+import useAudioInputController from 
+  "@/components/inputItem/controllers/audioCtrl"
 
 export default defineComponent({
   name: "InputItem",
@@ -39,14 +46,14 @@ export default defineComponent({
     // Calculate position of inputItem on drag.
     const { elementX, elementY } = draggify({ elementId: "inputItem" });
 
-    // determine whether the user is typing or recording.
-    const { isRecording, isTyping } = useInputController();
+    // Controllers for text and audio.
+    useTextInputController(elementX)
+    const { recording } = useAudioInputController()
 
     return {
       elementX,
       elementY,
-      isRecording,
-      isTyping,
+      recording
     };
   },
 });
@@ -57,6 +64,8 @@ export default defineComponent({
 .input-item {
   position: absolute;
 
+  opacity: 1.0;
+
   display: flex;
   align-items: center;
   justify-content: center;
@@ -66,12 +75,12 @@ export default defineComponent({
   width: 40px;
   height: 40px;
 
-  border: 4px solid #C6C6C6;
-  border-radius: 24px;
-
   z-index: 3;
 
-  background-color: white;
+  // border: 4px solid #C6C6C6;
+  border-radius: 20px;
+
+  background-color: #EBEBEB;
 
   cursor: pointer;
 
diff --git a/src/components/inputItem/menu.vue b/src/components/inputItem/menu.vue
deleted file mode 100644 (file)
index 3ecda9b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-<template>
-    <div id="menu">
-      <ul id="menu-list">
-        <li 
-            v-for="suggestion in menuItems.values()"
-            @click="submitSuggestion(suggestion)"
-        >
-                {{ suggestion }}
-            </li>
-      </ul>
-    </div>
-</template>
-
-<script lang="ts">
-import { defineComponent, ref } from "vue";
-import useMenu from "./menuController";
-
-export default defineComponent({
-    name: "SuggestionsMenu",
-
-    setup() {
-        const menuItems = ref(new Map())
-        // menuItems.value.set(0, 'add contact')
-        // menuItems.value.set(1, 'delete contact')
-        // menuItems.value.set(2, 'show contacts')
-        // menuItems.value.set(3, 'send a message')
-
-        const { submitSuggestion } = useMenu();
-
-        return {
-            menuItems,
-            submitSuggestion
-        }
-    }
-})
-</script>
-
-<style lang="scss" scoped>
-    #menu {
-        margin-top: 20px;
-        min-width: 200px;
-        height: 200px;
-        background-color: white;
-        border-radius: 18px;
-
-        margin: 0;
-        padding: 0;
-
-        animation-name: menu-appear;
-        animation-duration: 1s;
-        box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.15);
-    }
-
-    #menu-list {
-        margin: 0;
-        padding: 0;
-    }
-
-    @keyframes menu-appear {
-        from {
-            height: 0px;
-        }
-        to {
-            height: 200px;
-        }
-    }
-
-
-
-</style>
diff --git a/src/components/inputItem/menuController.ts b/src/components/inputItem/menuController.ts
deleted file mode 100644 (file)
index 8868281..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-export default function useMenu() {
-
-    const submitSuggestion = (suggestion: string) => {
-        console.log(`Submit...${suggestion}`)
-
-        // // Render the message immediately and get its unique id.
-        // const uid = render(suggestion, false, "", "sf");
-
-        // // Then send it to the backend for processing.
-        // const clientM = clientMessage(suggestion, false, uid);
-        // post('client-message', clientM);
-    }
-
-    return {
-        submitSuggestion
-    }
-    
-}
\ No newline at end of file
index ba9dd3f6cd9bf44858167c4c4c5baae7023f8e58..d9c2dad439d997193f7bc104c3dd5837b0e750d6 100644 (file)
@@ -1,11 +1,9 @@
 <template>
 
-  <div
-    class="text-input"
-    :class="`text-input-${updateSide}`"
-  >
-    <input id="textInput" type="text" />
-  </div>
+  <input 
+    id="textInput" 
+    type="text" 
+  />
 
 </template>
 
@@ -15,54 +13,48 @@ import { defineComponent, ref, watch } from "vue";
 export default defineComponent({
   name: "TextInput",
 
-  data: {
-
-    // Where is avatar?
-    position: Number
-
-  },
-
-  setup(data) {
-
-    const side = ref("")
-    side.value = "left"
-    
-    // Watch the position of parent.
-    // watch(data.position, (position, prevPosition) => {
-    //   console.log("position moved")
-    // })
-
-    return {
-      side
-    }
-  }
 })
 </script>
 
 <style lang="scss" scoped>
 
-.text-input {
+#textInput {
   position: absolute;
 
+  opacity: 0;
+
   min-width: 150px;
-  height: 36px;
+  height: 16px;
 
   border-radius: 18px;
 
+  padding: 10px;
+  margin-right: 10px;
+  margin-left: 10px;
+
   outline: none;
   border: none;
   pointer-events: none;
 
   background-color: white;
 
+  z-index: -1;
+
   box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.15);
-}
 
-// Activate if we need 
-.text-input-left {
+  transform: translateX(50px) scale(0.3);
 
-  left: -200px;
-  background-color: red;
+}
 
+@keyframes appear {
+  from {
+    opacity: 0;
+    transform: translateX(50px) scale(0.3);
+  }
+  to {
+    opacity: 1;
+    transform: translateX(110px) scale(1.0);
+  }
 }
+
 </style>
\ No newline at end of file
index b357ddf5e76e82bcd7149b560fac26d578e199b4..be9c0de2739196556a43179581d35473334f2320 100644 (file)
@@ -113,8 +113,8 @@ export default function draggify(input: { elementId: string }) {
     });
 
     // Initialize the coordinants.
-    elementX.value = 20;
-    elementY.value = 200 - 38 - 20;
+    elementX.value = 15;
+    elementY.value = 300;
 
     // remove event listeners on component dismount.
     onUnmounted(() => {