]> Repos - mime-chat/commitdiff
input item enhancements
authorAndrew Gundersen <gundersena@xavier.edu>
Wed, 17 Mar 2021 20:51:47 +0000 (15:51 -0500)
committerAndrew Gundersen <gundersena@xavier.edu>
Wed, 17 Mar 2021 20:51:47 +0000 (15:51 -0500)
12 files changed:
src/App.vue
src/background/session.ts
src/components/inputItem/controllers/audioCtrl.ts
src/components/inputItem/controllers/textCtrl.ts
src/components/inputItem/inputItem.vue
src/components/inputItem/textInput.vue
src/modules/draggify.ts
src/modules/message.ts
src/modules/messages.ts
src/modules/mitt.ts
src/types/message/index.ts
src/views/messenger.vue

index 165d108c732ca7afd94978993bbf6f97594c0cb7..96593dea5bd0908a8e8bd1d9473c6bf5786afc28 100644 (file)
@@ -67,76 +67,76 @@ export default defineComponent({
 
 <style lang="scss">
 
-  html, body {
-    margin: 0;
-    padding: 0;
-    background-color: #EBEBEB;
-  }
+html, body {
+  margin: 0;
+  padding: 0;
+  background-color: #EBEBEB;
+}
 
-  #app {
-    font-family: "SF Pro Text";
+#app {
+  font-family: "SF Pro Text";
 
-    -webkit-font-smoothing: antialiased;
-    -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
 
-    height: 100vh;
-    width: 100vw;
+  height: 100vh;
+  width: 100vw;
 
-    border-radius: 15px;
  }
+  border-radius: 15px;
+ }
 
-  .titlebar {
-    position: fixed;
+.titlebar {
+  position: fixed;
 
-    width: 100vw;
-    height: 54px;
+  width: 100vw;
+  height: 54px;
 
-    opacity: 0.75;
+  opacity: 0.75;
 
-    background-color: #EBEBEB;
+  background-color: #EBEBEB;
 
-    -webkit-user-select: none;
-    -webkit-app-region: drag;
+  -webkit-user-select: none;
+  -webkit-app-region: drag;
 
-    border: none;
-    outline: none;
+  border: none;
+  outline: none;
 
-    z-index: 1;
+  z-index: 1;
 
-  }
+}
 
-  .menu {
-    position: fixed;
-    margin-left: 20px;
-    margin-top: 20px;
+.menu {
+  position: fixed;
+  margin-left: 20px;
+  margin-top: 20px;
 
-    z-index: 2;
+  z-index: 2;
 
-  }
+}
 
-  .menuButton {
-    border: none;
-    outline:none;
-    min-width: 14px;
-    min-height: 14px;
-    border-radius: 7px;
-  }
+.menuButton {
+  border: none;
+  outline:none;
+  min-width: 14px;
+  min-height: 14px;
+  border-radius: 7px;
+}
 
-  .exitButton {
-    background-color: #FF6157;
-  }
+.exitButton {
+  background-color: #FF6157;
+}
 
-  .exitButton:active {
-    background: #c14645;
-  }
+.exitButton:active {
+  background: #c14645;
+}
 
-  .minimizeButton {
-    background-color: #FFC12F;
-    margin-left: 8px;
-  }
+.minimizeButton {
+  background-color: #FFC12F;
+  margin-left: 8px;
+}
 
-  .minimizeButton:active {
-    background-color: #c08e38;
-  }
+.minimizeButton:active {
+  background-color: #c08e38;
+}
 
 </style>
index 0f71cf949ccbcbef7ebfd01fb111cf7cc07a9662..92609db4bcf368a898641888fb94a3350ff6492e 100644 (file)
@@ -55,12 +55,7 @@ const onMessage = (messageStr: string): void => {
 
     // Check to see if this is a Render Message.
     if (m.content) {
-         message = renderMessage({
-            text: m.content.text,
-            audio: m.content.audio,
-            context: m.context,
-            modifier: m.modifier,
-        });
+         message = renderMessage(m.content.text, m.content.audio, m.context, m.modifier);
 
         // Play audio if any.
         if (message.content.audio) {
index 723d31a247d6d6c2cce740f20e834a5fa3f05c34..9b2df9fab39103f52d56ed50a8d07e085dfae007 100644 (file)
@@ -1,44 +1,62 @@
-import { onMounted } from "vue";
+import anime from "animejs";
+import { onMounted, onUnmounted, ref, Ref } from "vue";
 import useMitt from "@/modules/mitt";
 import { useIpc } from '@/modules/ipc';
 import keyboardNameMap from "../keyBoardMaps/keyboardNameMap";
 import { renderMessage } from '@/modules/message';
 
 
+function showRecIcon () {
 
+    anime({
+        targets: '#recIcon',
+        opacity: [0, 0.75],
+        scale: [0.0, 1],
+        duration: 250,
+        easing: 'linear', 
+    })
+
+}
 
+function hideRecIcon () {
 
+    anime({
+        targets: '#recIcon',
+        opacity: [0.75, 0],
+        scale: [1, 0],
+        duration: 250,
+        easing: 'linear', 
+    })
+
+}
 
-export default function useAudioInputController () {
+
+export default function useAudioInputController (typing: Ref) {
 
     // 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;
-    }
+    const recording = ref(false);
 
     //---Callbacks-----------------------------------------------
 
     const onKeyDown = (e: KeyboardEvent) => {
         const cmd = keyboardNameMap[e.keyCode];
+        // console.log(cmd)
 
         // Start recording on space bar.
-        if (cmd == "SPACE" && !recording) {
+        if (cmd == "SPACE" && !recording.value && !typing.value) {
 
             post('update-recorder', {
                 isRecording: true,
                 uid: null
             });
 
-            recording = true;
+            showRecIcon()
+            recording.value = true;
+            console.log("Recording...")
 
         }
 
@@ -48,17 +66,20 @@ export default function useAudioInputController () {
         const cmd = keyboardNameMap[e.keyCode];
 
         // Stop recording on space up.
-        if (cmd == "SPACE" && recording) {
+        if (cmd == "SPACE" && recording.value) {
 
             // Render audio immediately.
-            const uid = render("", "", "", "sf");
+            const message = renderMessage("", "", "", "sf")
+            emitter.emit("self-message", message);
 
             post('update-recorder', {
                 isRecording: false,
-                uid: uid
+                uid: message.uid
             });
 
-            recording = false;
+            hideRecIcon()
+            recording.value = false;
+            console.log("Stopping record...")
 
         }
 
@@ -71,6 +92,12 @@ export default function useAudioInputController () {
         window.addEventListener("keyup", onKeyUp);
     })
 
+    onUnmounted(() => {
+        window.removeEventListener("keydown", onKeyDown);
+        window.removeEventListener("keyup", onKeyUp);
+    });
+
+
     return {
         recording
     }
index 115e9c582287a8f1f01eea3e891acd9c57057dda..1958badbdf64eef07454d598bc14f5ccbf5021e2 100644 (file)
@@ -1,18 +1,13 @@
 import anime from "animejs";
 import useMitt from "@/modules/mitt";
 import { useIpc } from '@/modules/ipc';
-import { Ref, watch, onMounted } from "vue";
+import { Ref, ref, watch, onMounted, onUnmounted } 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 () {
     const t1 = (side === "right") ? 50 : -70;
@@ -27,7 +22,6 @@ function showTextInput () {
         easing: 'easeOutExpo', 
     })
 
-    visible = true
 }
 
 function hideTextInput() {
@@ -35,14 +29,13 @@ function hideTextInput() {
 
     anime({
         targets: '#textInput',
-        opacity: 0,
+        opacity: [1, 0],
         translateX: t,
         scale: 0.3,
         duration: 500,
         easing: 'easeOutExpo', 
     })
 
-    visible = false
 }
 
 function switchSide(currentSide: string) {
@@ -63,27 +56,29 @@ function switchSide(currentSide: string) {
 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;
+    const typing = ref(false);
 
-    // Clear text input.
+    // Prep inputItem for typing.
+    const prepInput = () => {
+        showTextInput()
+        typing.value = true
+    }
+
+    // Clear and hide inputItem after done typing.
     const clearInput = () => {
-        if (textInput) textInput.value = "";
+
+        if (textInput) {
+            textInput.value = "";
+            textInput.blur();
+        }
+        
         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;
+        typing.value = false;
     }
 
     // Send a message and clean up after.
@@ -91,50 +86,53 @@ export default function useTextInputController(elementX: Ref) {
         if (textInput) {
 
             // Render message
-            const uid = render(textInput.value, false, "", "sf");
+            const message = renderMessage(textInput.value, false, "", "sf")
+            emitter.emit("self-message", message);
 
             // Send it to the backend for processing.
-            const clientM = clientMessage(textInput.value, false, uid);
+            const clientM = clientMessage(textInput.value, false, message.uid);
             post('client-message', clientM);
+
+            clearInput()
         }
     }
 
     //---Callbacks-----------------------------------------------
 
     const onKeyDown = (e: KeyboardEvent) => {
+        const key = keyboardNameMap[e.keyCode]
+        console.log(key)
         
         if (textInput) {
-            const key = keyboardNameMap[e.keyCode]
-
-            // Reveal textInput on first key press.
+           
+            // First-key handler.
             if (firstKey) {
-
-                // Handle for space bar
-                if (key == "SPACE") {
-                    return
-                }
-
-                showTextInput()
-                firstKey = false
+                if (key == "SPACE") return
+                prepInput()
             }
 
             textInput.focus();
 
+            // Close input when no text or on ESC.
             if (textInput.value == "" && !firstKey) {
                 clearInput()
+                return
             }
 
-            if (key == "ENTER") {
+            if (key === "ESCAPE") {
+                clearInput()
+                return
+            }
+
+            // Close and send on enter.
+            if (key === "ENTER") {
                 if (textInput.value) {
                     sendMessage()
-                    clearInput()
+                    return
                 }
             }
 
-            if (key == "ESCAPE") {
-                clearInput()
-
-            }
+            if (firstKey) firstKey = false
         }
     }
 
@@ -166,8 +164,12 @@ export default function useTextInputController(elementX: Ref) {
         window.addEventListener("keydown", onKeyDown);
     })
 
-    return {
+    onUnmounted(() => {
+        window.removeEventListener("keydown", onKeyDown);
+    });
 
+    return {
+        typing
     }
 
 }
index 052e9dde727cb67e7efafbed4664d8ab71768a4c..05b859ce09cead27477222a362a3f0c3c9e842c6 100644 (file)
@@ -7,14 +7,9 @@
   >
     AG
 
-    <!-- Show audio input on spacebar -->
-    <AudioInput />
-
-
+    <!-- Recording animation on space bar -->
     <span v-if="recording" class="play"></span>
-    <span v-if="recording" class="pause">
-      <div class="rec-icon"></div>
-    </span>
+    <span v-if="recording" class="pause"></span>
 
     <!-- Show text input on key-down -->
     <TextInput />
@@ -43,12 +38,19 @@ export default defineComponent({
   },
   setup() {
 
+    // Initial position.
+    const xStart = 15;
+    const yStart = window.innerHeight - 200;
+
     // Calculate position of inputItem on drag.
-    const { elementX, elementY } = draggify({ elementId: "inputItem" });
+    const { elementX, elementY } = draggify(
+      { elementId: "inputItem" }, 
+      { x: xStart, y: yStart }
+    );
 
     // Controllers for text and audio.
-    useTextInputController(elementX)
-    const { recording } = useAudioInputController()
+    const { typing } = useTextInputController(elementX)
+    const { recording } = useAudioInputController(typing)
 
     return {
       elementX,
@@ -64,8 +66,6 @@ export default defineComponent({
 .input-item {
   position: absolute;
 
-  opacity: 1.0;
-
   display: flex;
   align-items: center;
   justify-content: center;
@@ -80,7 +80,8 @@ export default defineComponent({
   // border: 4px solid #C6C6C6;
   border-radius: 20px;
 
-  background-color: #EBEBEB;
+  // Set opacity here to not affect child.
+  background-color: rgba(235, 235, 235, 0.75);
 
   cursor: pointer;
 
index d9c2dad439d997193f7bc104c3dd5837b0e750d6..45e1af7d88b36d8285dc6f207db2ceb4f8e9c2bc 100644 (file)
@@ -8,7 +8,7 @@
 </template>
 
 <script lang="ts">
-import { defineComponent, ref, watch } from "vue";
+import { defineComponent } from "vue";
 
 export default defineComponent({
   name: "TextInput",
@@ -46,15 +46,4 @@ export default defineComponent({
 
 }
 
-@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 be9c0de2739196556a43179581d35473334f2320..d634c9bbd7caa6ee4d02057e185d219b9ba7e5c9 100644 (file)
@@ -30,7 +30,7 @@ function calcPosition (elementPosition: number, percent: number,
     return elementPosition
 }
 
-export default function draggify(input: { elementId: string }) {
+export default function draggify(input: { elementId: string }, initPosition: { x: number; y: number}) {
 
     let element: HTMLElement | null;
 
@@ -113,8 +113,8 @@ export default function draggify(input: { elementId: string }) {
     });
 
     // Initialize the coordinants.
-    elementX.value = 15;
-    elementY.value = 300;
+    elementX.value = initPosition.x;
+    elementY.value = initPosition.y;
 
     // remove event listeners on component dismount.
     onUnmounted(() => {
index 04435098ea3a852e55c1953a449099740c494625..e0f0c50eeb085c018058fd52b713b704f73bc7ff 100644 (file)
@@ -1,27 +1,20 @@
 import { RenderMessage, ClientMessage } from "@/types/message/index";
 import { v4 as uuidv4 } from 'uuid';
 
-interface RenderParams {
-  text: string;
-  audio: boolean | string;
-  context: string;
-  modifier: string;
-}
-
 function getTimeStamp(): number {  
   const currentdate = new Date();
   return currentdate.getTime();
 }
 
 // Create a RenderMessage object.
-export const renderMessage = (params: RenderParams): RenderMessage => (
+export const renderMessage = (text: boolean | string, audio: boolean | string, context: string, modifier: string): RenderMessage => (
   {
     content: {
-        text: params.text,
-        audio: params.audio
+        text: text,
+        audio: audio
     },
-    context: params.context,
-    modifier: params.modifier,
+    context: context,
+    modifier: modifier,
     time: getTimeStamp(),
     uid: uuidv4(),
     isChild: "none"
index cdfb6f239cf2c14f6a9db5795917dc8a4a328b1f..cde26a26b52a1989378ea01c49a92d3af560f8ea 100644 (file)
@@ -66,13 +66,16 @@ export default function useMessages() {
         updateScrollRef()
 
         // update message if in the map.
-        const m = messages.value.get(a.uid)
-        m.context = a.context
-        m.text = a.text
+        const message = messages.value.get(a.uid)
+        message.context = a.context
+        message.content.text = a.text
 
         setTimeout(adjustScroll, 10);
 
-        return m
+        console.log(`Annotation: ${a.text}`)
+        console.log(`Annotation: ${a.context}`)
+
+        return message
     }
 
     const saveMessages = () => {
index 3ec8a9228eb05ead2b0a53aab296448de3490674..9804d0b1b640e56cae21517eb6d15d90d4629a3f 100644 (file)
@@ -12,6 +12,4 @@ export default function useMitt() {
     return {
         emitter
     }
-}
-
-
+}
\ No newline at end of file
index 40023969fc7b9c867e5c910197a2ca6bd7abb59b..1c1d4750ff10f1f9e36a1853167065269a14473b 100644 (file)
@@ -5,7 +5,7 @@ export interface UserCreds {
 
 export interface RenderMessage {
     content: {
-        text: string;
+        text: boolean | string;
         audio: boolean | string;
     };
     context: string;
index 1e5b56bdd1a5d80adc8e619ad5eb8cb1485e4d9d..761457852651a10f95aabd56af400f7e617e61e2 100644 (file)
@@ -2,6 +2,8 @@
   <InputItem />
   <Settings />
 
+  <div id="recIcon" />
+
   <!-- List of message bubbles. -->
   <div id="messenger">
     <MessageItem v-for="message in messages" :message="message[1]" :key="message[0]" />
@@ -109,4 +111,26 @@ export default defineComponent({
 #messenger::-webkit-scrollbar {
   display: none;
 }
+
+#recIcon {
+  position: fixed;
+  right: 0;
+
+  opacity: 0;
+  transform: scale(0.0);
+
+  margin-top: 24px;
+  margin-right: 66px;
+
+
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  background-color: #FF3B3B;
+
+  z-index: 2;
+
+}
+
+
 </style>