]> Repos - mime-chat/commitdiff
refactor messageItem functionality + update design
authorriqo <hernandeze2@xavier.edu>
Thu, 3 Dec 2020 22:32:08 +0000 (16:32 -0600)
committerriqo <hernandeze2@xavier.edu>
Sat, 5 Dec 2020 17:42:56 +0000 (11:42 -0600)
add dynamic title bar

updat Message object type

src/background.ts
src/components/AI/index.vue
src/components/UI/UIDetails/messageItem.vue
src/components/UI/UIDetails/messages.ts
src/components/UI/index.vue
src/composables/audioRenderer/useAudioRenderer.ts [new file with mode: 0644]
src/composables/messageItem/useMessageItemAnims.ts
src/composables/messageItem/useMessageItemComp.ts
src/types/message/index.ts

index 8bcbbe35364597a31e27fc2ed84a6effc15b8345..c937b1bac67a313f36fe933965ec1bb7ba6cfc36 100644 (file)
@@ -19,7 +19,7 @@ import { SpeechRecorder } from "speech-recorder";
 // });
 //
 
-const recorder = new SpeechRecorder({ sampleRate: 16000, framesPerBuffer: 320 });
+// const recorder = new SpeechRecorder({ sampleRate: 16000, framesPerBuffer: 320 });
 
 // Keep a global reference of the window object, if you don't, the window will
 // be closed automatically when the JavaScript object is garbage collected.
@@ -33,9 +33,9 @@ protocol.registerSchemesAsPrivileged([
 function createWindow() {
   // Create the browser window.
   win = new BrowserWindow({
-    width: 350,
-    height: 525,
-    resizable: false,
+    width: 450,
+    height: 1025,
+    resizable: true,
     webPreferences: {
       // Use pluginOptions.nodeIntegration, leave this alone
       // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
@@ -56,24 +56,26 @@ function createWindow() {
     win.loadURL("app://./index.html");
   }
 
-  win.webContents.on('did-finish-load', () => {
-    if (win) {
-      recorder.start({
-        onAudio: (audio: object, speech: boolean) => {
-          if (win) {
-            win.webContents.send('render-audio', {
-              audio: audio,
-              speech: speech
-            })
-          }
-          if (speech) {
-            // TODO: send audio to crimata BE
-            // ws.send(audio);
-          }
-        }
-      });
-    }
-  })
+  // win.webContents.on('did-finish-load', () => {
+  //   if (win) {
+  //     recorder.start({
+  //       onAudio: (audio: object, speech: boolean) => {
+  //         if (win) {
+  //           win.setTitle("Listening...");
+  //           // win.webContents.send('render-audio', {
+  //           //   audio: audio,
+  //           //   speech: speech
+  //           // })
+  //           if (speech) {
+  //             win.setTitle("Recording...");
+  //             // TODO: send audio to crimata BE
+  //             // ws.send(audio);
+  //           }
+  //         }
+  //       }
+  //     });
+  //   }
+  // })
 
   win.on("closed", () => {
     win = null;
index 87a2aa06f6f5bf9c34c036c074b28f2f682cf096..d263eb005118f73b42717265cfc23b6f0139feaa 100644 (file)
@@ -48,7 +48,7 @@ export default defineComponent({
     let gradient;
     const radius = ref(0);
     const think = ref(false);
-    const aiOffset = ref(1.0);
+    const aiOffset = ref(0.7);
 
     const anime = inject("animejs");
     let thinkAnimation;
@@ -100,24 +100,24 @@ export default defineComponent({
       }
     });
 
-    watch(think, async (think, prevThink) => {
-      if (think) {
-        anime({
-          targets: gradient,
-          cy: "0.7",
-        });
-        thinkAnimation.play();
-      } else {
-        thinkAnimation.pause();
-        // thinkAnimation.reset();
-        anime({
-          targets: gradient,
-          cy: "1",
-        });
-
-        // thinkAnimation.reset();
-      }
-    });
+    // watch(think, async (think, prevThink) => {
+    //   if (think) {
+    //     anime({
+    //       targets: gradient,
+    //       cy: "0.7",
+    //     });
+    //     thinkAnimation.play();
+    //   } else {
+    //     thinkAnimation.pause();
+    //     // thinkAnimation.reset();
+    //     anime({
+    //       targets: gradient,
+    //       cy: "1",
+    //     });
+    //
+    //     // thinkAnimation.reset();
+    //   }
+    // });
     return {
       radius,
       aiOffset,
index bbd4343bd977d4196485d3c03fa431bff195a3f7..95049f8f806dd6a40ed24e0cdb49fa95bd5eaad8 100644 (file)
@@ -1,21 +1,26 @@
 <template>
   <g :id="item.id" :class="item.modifier" :transform="startingOffset">
-    <rect ref="messageRect" x="30" y="10" width="196" height="63" rx="20" :fill="bubbleFill" />
+    <rect ref="messageRect" x="30" y="10" width="196" height="63" rx="10" :fill="bubbleFill" />
     <text font-size="14" font-family="SF Pro" ref="messageText" :fill="textFill">
       <tspan dy="16" x="0" v-for="(item, index) in textArr" :key="index">{{ item }}</tspan>
     </text>
     <g :transform="signatureTranslate">
-      <image xlink:href="profile.png" width="29" height="29" fill="#b5b5b5" clip-path="url(#clip)" />
       <text
-        transform="translate(36, 17)"
-        fill="#888"
+        transform="translate(0, 5)"
+        fill="#000"
         font-size="10"
         font-family="SFCompactDisplay-Bold, SF Compact Display"
         font-weight="700"
       >
-        <tspan v-if="item.outgoing">You to</tspan>
-        <tspan v-else>From</tspan>
-        <tspan xml:space="preserve" fill="#000">{{ item.signature }}</tspan>
+        <tspan xml:space="preserve">{{ item.context }}</tspan>
+      </text>
+      <text
+        transform="translate(0, 20)"
+        fill="#6f6f6f"
+        font-size="9"
+        font-family="SFCompactDisplay, SF Compact Display"
+      >
+        <tspan v-if="item.subContext">{{item.subContext}}</tspan>
       </text>
     </g>
   </g>
index 00eb7aeb33bbd0ac9bf0f3ece0e4a8ec08333948..39593c2da082780f1c31017cb0932e1b58cf25ae 100644 (file)
@@ -4,156 +4,156 @@ const Messages: Message[] = [
     {
         content:
             "I can be there at 5 pm tomorrow to greet you at a Chick file with my almond and chive salad.",
-        signature: "Tommy McConville",
-        outgoing: true,
+        context: "You to Josie Wright",
+        subContext: "josie@gmail.com",
         modifier: "sf",
-        imgURL: "../assets/logo.png",
-        id: "1"
+        id: "1",
+        time: ""
     },
     {
         content: "Sounds good, see you Thursday.",
-        signature: "Josie Wright",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "@/assets/logo.png",
-        id: "2"
+        context: "Message from Josie Wright",
+        subContext: "Subject: Chick File",
+        modifier: "ai",
+        id: "2",
+        time: ""
     },
     {
         content: "Hey Anna, did you get the paper done?",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "@/assets/logo.png",
-        id: "3"
+        context: "Mesage from Tommy McConville",
+        subContext: "New Conversation",
+        modifier: "ai",
+        id: "3",
+        time: ""
     },
     {
         content: "Yes posting it online soon.",
-        signature: "Tommy McConville",
-        outgoing: true,
-        modifier: "sf",
-        imgURL: "../../assets/logo.png",
-        id: "4"
+        context: "You to Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "4",
+        time: ""
     },
     {
         content: "Sweet, thanks!",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "../../assets/logo.png",
-        id: "5"
+        context: "Message from Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "5",
+        time: ""
     },
     {
         content: "Hey do you know Enrique Hernandez?",
-        signature: "Crimata AI",
-        outgoing: false,
+        context: "Message from Crimata AI",
+        subContext: "",
         modifier: "ai",
-        imgURL: "../../assets/logo.png",
-        id: "6"
+        id: "6",
+        time: ""
     },
     {
         content: "Hey do you know Enrique Hernandez?",
-        signature: "Crimata AI",
-        outgoing: false,
+        context: "Message from Crimata",
+        subContext: "",
         modifier: "ai",
-        imgURL: "../../assets/logo.png",
-        id: "7"
+        id: "7",
+        time: ""
     },
     {
         content: "Hey do you know Enrique Hernandez?",
-        signature: "Crimata AI",
-        outgoing: false,
+        context: "Message from Crimata",
+        subContext: "",
         modifier: "ai",
-        imgURL: "../../assets/logo.png",
-        id: "8"
+        id: "8",
+        time: ""
     },
     {
         content: "Hey Anna, did you get the paper done?",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "@/assets/logo.png",
-        id: "9"
+        context: "Message from Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "9",
+        time: ""
     },
     {
         content: "Hey Anna, did you get the paper done?",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "@/assets/logo.png",
-        id: "10"
+        context: "Message from Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "10",
+        time: ""
     },
     {
         content: "Yes posting it online soon.",
-        signature: "Tommy McConville",
-        outgoing: true,
+        context: "Message from Tommy McConville",
+        subContext: "",
         modifier: "sf",
-        imgURL: "../../assets/logo.png",
-        id: "11"
+        id: "11",
+        time: ""
     },
     {
         content:
             "I can be there at 5 pm tomorrow to greet you at a Chick file with my almond and chive salad.",
-        signature: "Tommy McConville",
-        outgoing: true,
+        context: "You to Tommy McConville",
+        subContext: "",
         modifier: "sf",
-        imgURL: "../assets/logo.png",
-        id: "12"
+        id: "12",
+        time: ""
     },
     {
         content: "Hey Anna, did you get the paper done?",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "@/assets/logo.png",
-        id: "13"
+        context: "Message from Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "13",
+        time: ""
     },
     {
         content: "Hey Anna, did you get the paper done?",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "@/assets/logo.png",
-        id: "14"
+        context: "Message from Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "14",
+        time: ""
     },
     {
         content: "Yes posting it online soon.",
-        signature: "Tommy McConville",
-        outgoing: true,
+        context: "You to Tommy McConville",
+        subContext: "",
         modifier: "sf",
-        imgURL: "../../assets/logo.png",
-        id: "15"
+        id: "15",
+        time: ""
     },
     {
         content: "Sweet, thanks!",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "../../assets/logo.png",
-        id: "16"
+        context: "Message from Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "16",
+        time: ""
     },
     {
         content: "Hey do you know Enrique Hernandez?",
-        signature: "Crimata AI",
-        outgoing: false,
+        context: "Message from Crimata AI",
+        subContext: "",
         modifier: "ai",
-        imgURL: "../../assets/logo.png",
-        id: "17"
+        id: "17",
+        time: ""
     },
     {
         content: "Yes posting it online soon.",
-        signature: "Tommy McConville",
-        outgoing: true,
+        context: "You to Tommy McConville",
+        subContext: "",
         modifier: "sf",
-        imgURL: "../../assets/logo.png",
-        id: "18"
+        id: "18",
+        time: ""
     },
     {
         content: "Sweet, thanks!",
-        signature: "Tommy McConville",
-        outgoing: false,
-        modifier: "fr",
-        imgURL: "../../assets/logo.png",
-        id: "19"
+        context: "Message from Tommy McConville",
+        subContext: "",
+        modifier: "ai",
+        id: "19",
+        time: ""
     },
 ];
-export default Messages;
+export default Messages;
\ No newline at end of file
index d1e5655de516dfaf5a9ea41532ee409b91372895..5d0ef839847dc00d52b489229536c7b3ca35631e 100644 (file)
@@ -6,7 +6,7 @@
     xmlns:xlink="http://www.w3.org/1999/xlink"
     @click="emittMessage"
   >
-    <AI />
+    <!-- <AI /> -->
     <MessageRenderer />
     <InputItem />
     <!-- <TitleBar /> -->
@@ -23,7 +23,7 @@ import { Mitt } from "@/types/mitt/index";
 import { defineComponent, ref, inject } from "vue";
 export default defineComponent({
   name: "UI",
-  components: { AI, MessageRenderer, InputItem, TitleBar },
+  components: {  MessageRenderer, InputItem },
   setup() {
     const messages = Messages;
     const count = ref(0);
diff --git a/src/composables/audioRenderer/useAudioRenderer.ts b/src/composables/audioRenderer/useAudioRenderer.ts
new file mode 100644 (file)
index 0000000..9047c69
--- /dev/null
@@ -0,0 +1,53 @@
+export default function useAudioRenderer() {
+    const audioCtx = new (window.AudioContext)();
+    const analyzer = audioCtx.createAnalyser();
+    analyzer.fftSize = 2048;
+    const xInitial = 24;
+    const xFinal = 640;
+    // analyzer.minDecibels = -90;
+    analyzer.smoothingTimeConstant = 0.85;
+    const dataArray = new Uint8Array(analyzer.frequencyBinCount);
+    const sampleRate = 16000;
+
+    function convertBlock(buffer: ArrayBuffer): Float32Array {
+        // incoming data is an ArrayBuffer
+        const incomingData = new Uint8Array(buffer); // create a uint8 view on the ArrayBuffer
+        const l = incomingData.length; // length, we need this for the loop
+        const outputData = new Float32Array(incomingData.length); // create the Float32Array for output
+        for (let i = 0; i < l; i++) {
+            outputData[i] = (incomingData[i] - 128) / 128.0; // convert audio to float
+        }
+        return outputData; // return the Float32Array
+    }
+
+    const getAudioFrequencyData = () => {
+
+    }
+
+    const renderAudio = (payload) => {
+
+        // step 1: convert audio from Uint8 to Float32Array
+        const floatArray = convertBlock(payload.audio.buffer);
+
+        // step 2: source audio frequency {ffft} data
+        const buffer = audioCtx.createBuffer(1, floatArray.length, sampleRate);
+        buffer.copyToChannel(floatArray, 0, 0);
+        const source = audioCtx.createBufferSource();
+        source.buffer = buffer;
+        source.connect(analyzer);
+        source.start();
+        analyzer.getByteFrequencyData(dataArray);
+
+        // step 3: process audio frequency data
+        const dataView = dataArray.slice(xInitial, xFinal);
+        const sum = dataView.reduce((a, b) => a + b);
+        const average = sum / dataView.length;
+        const scaled = average / 255;
+        const zeroed = scaled - 0.6;
+        return zeroed;
+    }
+
+    return {
+        renderAudio
+    }
+}
index c381ff7cb2640c6be64b498598ca0380264f06d3..3e2875d0506a3a7da31cf1a15255713d1e3fe417 100644 (file)
@@ -18,7 +18,7 @@ export default function useMessageItemAnims({
 
   function adjustMessageRect(): void {
     // must get dimensions of text box to fit bubble around
-    const padding = 20;
+    const padding = 12.5;
     const textBox = messageText.getBBox();
     messageRect.setAttribute("x", String(textBox.x - padding));
     messageRect.setAttribute("y", String(textBox.y - padding));
@@ -29,8 +29,7 @@ export default function useMessageItemAnims({
   function translateMsgSignature(): void {
     if (messageRect.getAttribute("height") !== null) {
       const height = Number(messageRect.getAttribute("height"));
-      const p = -10;
-      signatureTranslate.value = `translate(-10 ${height + p})`;
+      signatureTranslate.value = `translate(-10 ${height})`;
     }
   }
 
index 341cc3fc5160bad1c33509172a91480a9d4290d3..afb216df76a49c004460d7cdadf061e4bdb91a57 100644 (file)
@@ -1,35 +1,10 @@
 import { computed, onMounted, ref } from "vue";
 export default function useMessageItemComp(m: string, id: string) {
   const x = ref(0)
-  const xOffset = async () => {
-      const paddingLeft = 40;
-      const messageMargin = 20;
-      const winW = 350;
-      let x: number;
-        const msg = await document.getElementById(id);
-        if (msg) {
-          const messageWidth = msg.getBoundingClientRect().width;
-          switch (m) {
-              case "sf":
-                  x = winW - messageWidth;
-                  break;
-              case "ai":
-                  x = messageMargin + (winW -messageWidth) / 2;
-                  break;
-              default:
-                  x = paddingLeft;
-          }
-          return x;
-        }
-  }
-
-  onMounted(async () => {
-    const result = await xOffset();
-    if(result) {
-      x.value =  result;
-    }
-  })
-
+  const paddingLeft = 30;
+  const winW = 350;
+  const messageWidth = ref(0);
+  const messageMarginTop = 75;
 
   const textFill = computed(() => {
     switch (m) {
@@ -44,25 +19,59 @@ export default function useMessageItemComp(m: string, id: string) {
     switch (m) {
       case "sf":
         return "#61b4f4";
-      case "ai":
-        return "#DDDDDD";
-      default:
+      default: 
         return "#fff";
     }
   });
 
+  const setMessageWidthRef = async () => {
+      const msg = await document.getElementById(id);
+      if (msg) {
+        messageWidth.value = msg.getBoundingClientRect().width;
+      }
+  }
+
+  const calculateXoffset = async () => {
+    switch (m) {
+        case "sf":
+            x.value = winW - messageWidth.value;
+            break;
+        default:
+            x.value = paddingLeft;
+            // to center a message
+            // x = messageMargin + (winW -messageWidth) / 2;
+    }
+  }
+
+  // TODO implement func in order to reduce dual renderer height call startingOffset computed prop
+  const getRendererHeight = () => {
+    const messageRenderer = document.getElementById('messageRenderer');
+    if (messageRenderer) {
+      const rect = messageRenderer.getBoundingClientRect();
+      return rect.height;
+    }
+  }
+
   const startingOffset = computed(() => {
-    const messageRenderer = document.getElementById('messageRenderer')
+    const messageRenderer = document.getElementById('messageRenderer');
     if (messageRenderer) {
       const rect = messageRenderer.getBoundingClientRect();
       let Y = 600;
       if (rect.height > 500) {
-        Y = rect.height + 75;
+        Y = rect.height + messageMarginTop;
       }
       return `translate(${x.value} ${Y})`;
     }
   });
 
+  onMounted(async () => {
+    // to calculate X offset:
+    // First: set message width ref
+    await setMessageWidthRef();
+    // Then: calculate message X offset
+    calculateXoffset();
+  })
+
   return {
     textFill,
     bubbleFill,
index a4ced0746eb022b7915bfae78765e7502242c66e..ec210aecb868de50a0823032c8798ce11dc272e6 100644 (file)
@@ -1,10 +1,10 @@
 export interface Message {
     content: string;
-    signature: string;
-    outgoing: boolean;
+    context: string;
+    subContext: string;
     modifier: string;
-    imgURL: string;
     id: string;
+    time: string;
 }
 
 interface MessageTransform {