]> Repos - mime-chat/commitdiff
add splash screen on load
authorriqo <hernandeze2@xavier.edu>
Sun, 28 Feb 2021 20:27:51 +0000 (14:27 -0600)
committerriqo <hernandeze2@xavier.edu>
Sun, 28 Feb 2021 20:27:51 +0000 (14:27 -0600)
src/App.vue
src/background/audio.ts
src/background/window.ts
src/components/messageItem.vue [new file with mode: 0644]
src/components/splash.vue [moved from src/views/splash.vue with 53% similarity]
src/modules/auth.ts
src/router.ts
src/views/messenger.vue
tests/audio.js

index 583ff1b889aa5c149622c765d9f28a2fa3795eef..17e28a121af9e3470f85f6299079acdb2b257b4f 100644 (file)
@@ -1,5 +1,5 @@
 <template>
-  <div id="app">
+  <div id="app" v-if="!loading">
 
     <button class="titlebar">
 
     <router-view/>
 
   </div>
+  <Splash v-else />
 </template>
 
 <script lang="ts">
 import {defineComponent} from 'vue';
 import { useIpc } from "@/modules/ipc";
+import { useAuth } from "@/modules/auth";
+import Splash from "@/components/splash.vue"
 
 export default defineComponent({
+  components: { Splash },
 
-    setup() {
+  setup() {
 
     const { invoke } = useIpc();
+    const { loading } = useAuth();
 
     const callNavbar = (action: string) => {
-        switch(action) {
-                case 'close':
-                    invoke('nav-bar', 'close');
-                    break;
-                case 'min':
-                    invoke('nav-bar', 'min');
-                    break;
-            }
-        }
-
-        return {
-            callNavbar
-        }
+      invoke('nav-bar', action);
     }
+
+    return {
+        callNavbar,
+        loading
+    }
+  }
 })
 
 </script>
index 3263582539f4d44fb70593bda8a1969a6c0d1cb1..4424d445896d2e1f1d20c2c2506d7d079ff55c1a 100644 (file)
@@ -35,7 +35,9 @@ export const initAudioIO = () => {
     });
     ai.on('data', (chunk: string) => {
       // turn string base64 data into buffer object.
-      audioInput.push(Buffer.from(chunk, encoding));
+      console.log('received string chunk of length', chunk.length)
+      const buf = Buffer.from(chunk, encoding);
+      audioInput.push(buf);
     });
   }
 
@@ -54,7 +56,8 @@ export const updateRecorder = (_event, record: boolean): void => {
     } else {
         // stop mic data flow on space bar key up.
         ai.pause();
-        sendAudio(Buffer.concat(audioInput));
+        const audio = Buffer.concat(audioInput);
+        sendAudio(audio);
         audioInput = [];
     }
 }
index 334ae679646701beffa5287e076a23ca1419da18..b84a74209103d4c674bbdead6b1922569c33c6f6 100644 (file)
@@ -30,10 +30,11 @@ let win: BrowserWindow | null;
 
 const windowMount = (): void => {
   backgroundMitt.emit('window-active', true);
+  ipcMain.removeAllListeners('update-recorder');
   ipcMain.on('update-recorder', updateRecorder);
-    // handle renderer auth-token event
-    ipcMain.removeHandler('nav-bar'); // avoid setting duplicate handlers
-    ipcMain.handle('nav-bar', navBarHandler);
+  // handle renderer auth-token event
+  ipcMain.removeHandler('nav-bar'); // avoid setting duplicate handlers
+  ipcMain.handle('nav-bar', navBarHandler);
 }
 
 const windowDismount = (): void => {
@@ -58,6 +59,7 @@ export const createWindow = async (options: WindowSettings): Promise<void> => {
       width: options.width,
       height: options.height,
       resizable: options.resizable,
+      backgroundColor: '#EBEBEB',
       frame: false,
       minWidth: 350,
       minHeight: 500,
@@ -82,8 +84,12 @@ export const createWindow = async (options: WindowSettings): Promise<void> => {
     // Handle window close.
     win.on("closed", windowDismount);
 
+    win.once('ready-to-show', () => {
+      if (win) win.show()
+    })
+
     win.webContents.on('did-finish-load', () => {
-      windowMount();
+      windowMount();      
       resolve();
     });
 
diff --git a/src/components/messageItem.vue b/src/components/messageItem.vue
new file mode 100644 (file)
index 0000000..d60795e
--- /dev/null
@@ -0,0 +1,140 @@
+<template>  
+  <div
+    class="message"
+    :id="`${message.modifier}Message`"
+    :key="message.id"
+  >
+
+    <!-- Includes bubble and context. -->
+    <div class="messageBox" :id="`${message.modifier}MessageBox`">
+
+      <!-- message bubble -->
+      <div
+        class="bubble"
+        :id="`${message.modifier}Bubble`"
+      >
+        {{ message.content }}
+      </div>
+
+      <!-- message context -->
+      <span class="context">
+
+        <!-- Render Crimata icon or initials. -->
+        <div v-if="message.avatar == 'crimata'" class="photo">
+          <img src="@/assets/crimata.svg"/>
+        </div>
+
+        <div v-else class="photo">
+          {{ message.avatar }}
+        </div>
+
+        {{ message.context }}
+
+      </span>
+
+    </div>
+
+  </div>
+</template>
+
+<script lang='ts'>
+ import {defineComponent} from 'vue';
+ export default defineComponent({
+  name: "MessageItem",
+  props: {
+      message: {
+        type: Object,
+        required: true
+      } 
+  }
+ })
+</script>
+
+<style lang="scss" scoped>
+
+  .message {
+    width: 100vw;
+
+    display: flex;
+    flex-direction: column;
+
+    padding-top: 9px;
+    padding-bottom: 9px;
+
+  }
+
+  .message:first-child {
+    margin-top: 55px;
+  }
+
+  .message:last-child {
+    margin-bottom: 18px;
+  }
+
+  #aiMessage {
+    align-items: flex-start;
+  }
+
+  #sfMessage {
+    align-items: flex-end;
+  }
+
+  #aiMessageBox {
+    margin-left: 20px;
+  }
+
+  #sfMessageBox {
+    margin-right: 20px;
+  }
+
+  .bubble {
+    max-width: 66vw;
+
+    display: flex;
+    flex-direction: column;
+
+    font-family: "SF Pro Text";
+    font-size: 14px;
+
+    padding: 10px;
+
+    border-radius: 10px;
+  }
+
+  #aiBubble {
+    background-color: white;
+  }
+
+  #sfBubble {
+    background-color: #58c4fd;
+    color: white;
+  }
+
+  .context {
+    display: flex;
+    align-items: center;
+
+    font-family: "SF Compact Display";
+    font-size: 12px;
+    font-weight: bold;
+    margin-left: 7px;
+    margin-top: 5px;
+  }
+
+  .photo {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    margin-right: 5px;
+
+    width: 30px;
+    height: 30px;
+
+    font-size: 14px;
+
+    background-color: white;
+    border-radius: 15px;
+  }
+
+</style>
\ No newline at end of file
similarity index 53%
rename from src/views/splash.vue
rename to src/components/splash.vue
index d30173df6caad324d987233feb7d6424d35cd8a5..247847a7e946f5f57d96c16db6a2f076515653af 100644 (file)
@@ -1,57 +1,55 @@
 <template>
   <div id="splash">
-    <svg 
-      xmlns="http://www.w3.org/2000/svg" 
-      width="57.046" 
-      height="52.759" 
+    <svg
+      xmlns="http://www.w3.org/2000/svg"
+      width="57.046"
+      height="52.759"
       viewBox="0 0 57.046 52.759"
     >
       <g transform="translate(-4127 -507)">
         <g transform="translate(3949 332.206)">
           <g transform="translate(178 174.794)">
             <g transform="translate(0 27.405)">
-              <circle 
-                cx="12.677" 
-                cy="12.677" 
-                r="12.677" 
-                transform="translate(0 0)" 
+              <circle
+                cx="12.677"
+                cy="12.677"
+                r="12.677"
+                transform="translate(0 0)"
                 fill="#383838"
               />
-              <circle 
-                cx="12.677" 
-                cy="12.677" 
-                r="12.677" 
-                transform="translate(31.692 0)" 
+              <circle
+                cx="12.677"
+                cy="12.677"
+                r="12.677"
+                transform="translate(31.692 0)"
                 fill="#383838"
               />
             </g>
-            <circle 
-              cx="12.677" 
-              cy="12.677" 
-              r="12.677" 
-              transform="translate(15.822 0)" 
+            <circle
+              cx="12.677"
+              cy="12.677"
+              r="12.677"
+              transform="translate(15.822 0)"
               fill="#383838"
             />
-            <path 
-              d="M36.27,83.67" 
-              transform="translate(-23.569 -43.588)" 
+            <path
+              d="M36.27,83.67"
+              transform="translate(-23.569 -43.588)"
               fill="#ff0"
             />
           </g>
         </g>
       </g>
-    </svg>    
+    </svg>
   </div>
 </template>
 
 <script lang="ts">
-    
+
 import { defineComponent } from "vue";
 
 export default defineComponent({
-
   name: "Splash",
-
 });
 
 </script>
@@ -68,4 +66,4 @@ export default defineComponent({
 
   }
 
-</style>
\ No newline at end of file
+</style>
index 6a1120e1daaf8071a34828d50f58f2957feaf84b..c541c3f44b015c9e76253ddf2a9a8f05b4605cd2 100644 (file)
@@ -1,4 +1,4 @@
-import { reactive, toRefs } from 'vue';
+import { reactive, toRefs, ref } from 'vue';
 import { useIpc } from './ipc';
 
 interface AuthState {
@@ -11,6 +11,8 @@ const state = reactive<AuthState>({
     error: undefined,
 });
 
+const loading = ref(true);
+
 const AUTH_KEY = 'crimata_token';
 
 const token = window.localStorage.getItem(AUTH_KEY);
@@ -20,6 +22,7 @@ if (token) {
 }
 
 const authToken = async () => {
+   loading.value = true;
    const { invoke  } = useIpc();
     try {
         const res = await invoke('auth-session', token);
@@ -32,6 +35,7 @@ const authToken = async () => {
         window.localStorage.removeItem(AUTH_KEY);
         state.accessToken = null;
     }
+    loading.value = false;
 }
 
 // authenticate on auth event
@@ -56,5 +60,6 @@ export const useAuth = () => {
         setToken,
         logout,
         ...toRefs(state), // accessToken, error
+        loading
     }
 }
index d3459dc8813a36d2113a84019344cbb0fc85bd17..ee94a6137aa14f719970623442705afa1e146141 100644 (file)
@@ -5,7 +5,6 @@ import {
   RouteRecordRaw
 } from "vue-router";
 import Home from "@/views/messenger.vue";
-import Splash from "@/views/splash.vue";
 import { useAuth } from '@/modules/auth';
 
 // Define the routes (/*) for the app here.
@@ -16,14 +15,6 @@ const routes: Array<RouteRecordRaw> = [
     component: Home,
     meta: { requiresAuth: true },
   },
-  {
-    path: "/splash",
-    name: "splash",
-    component: Splash,
-    meta: {
-        requiresAuth: false
-    },
-  },
   {
     path: "/login",
     name: "login",
index 58f0094d17531d2e67927b1ff3078188c8d8d789..25ebd75ccf986feda2f8511d75843afc2b940ca5 100644 (file)
@@ -3,74 +3,37 @@
     <TextAudioInput />
 
     <!-- List of message bubbles. -->
-    <div id="messenger">
-      
-      <!-- message box (view width) -->
-      <div 
-        class="message" 
-        :id="`${message.modifier}Message`"
-        v-for="message in messages"
-      >
-
-        <!-- Includes bubble and context. -->
-        <div class="messageBox" :id="`${message.modifier}MessageBox`">
-
-          <!-- message bubble -->
-          <div 
-            class="bubble"
-            :id="`${message.modifier}Bubble`"
-          >
-            {{ message.content }}
-          </div>
-
-          <!-- message context -->
-          <span class="context">
-
-            <!-- Render Crimata icon or initials. -->
-            <div v-if="message.avatar == 'crimata'" class="photo">
-              <img src="@/assets/crimata.svg"/>
-            </div>
-
-            <div v-else class="photo">
-              {{ message.avatar }}
-            </div>
-
-            {{ message.context }}
-
-          </span>
-
-        </div>
-
-      </div>
-
+    <div id="messenger" >
+      <MessageItem v-for="message in messages" :message="message" :key="message.id"/>
     </div>
-
 </template>
 
 <script lang="ts">
 
-import { defineComponent, computed, reactive, onMounted, ref } from "vue";
-
+import { defineComponent, reactive, onMounted, ref, onUnmounted } from "vue";
 import TextAudioInput from "@/components/taInput/index.vue";
 import { Message } from "@/types/message/index";
+import MessageItem from '@/components/messageItem.vue'
 
 export default defineComponent({
   name: "Messenger",
 
   components: {
-    TextAudioInput 
+    TextAudioInput,
+    MessageItem,
   },
 
-  setup(props) {
+  setup() {
 
     // List of messages in the view.
     // Oldest message first.
-    const messages: Message[] = reactive([])
+    const messages: Message[] = reactive([]);
 
     // Render a message.
     const render = (message: Message) => {
-      messages.push(message)
-      console.log(`Pushing: ${message.modifier}: ${message.avatar}, ${message.content}`)
+      messages.push(message);
+      console.log(`Pushing: ${message.modifier}: ${message.avatar}, ${message.content}`);
     }
 
     onMounted(() => {
@@ -82,6 +45,10 @@ export default defineComponent({
 
     })
 
+    onUnmounted(() => {
+        window.ipcRenderer.removeAllListeners('render-message');
+    })
+
     return {
       messages,
     }
@@ -112,91 +79,4 @@ export default defineComponent({
     display: none;
   }
 
-  .message {
-    width: 100vw;
-
-    display: flex;
-    flex-direction: column;
-
-    padding-top: 9px;
-    padding-bottom: 9px;
-
-  }
-
-  .message:first-child {
-    margin-top: 55px;
-  }
-
-  .message:last-child {
-    margin-bottom: 18px;
-  }
-
-  #aiMessage {
-    align-items: flex-start;
-  }
-
-  #sfMessage {
-    align-items: flex-end;
-  }
-
-  #aiMessageBox {
-    margin-left: 20px;
-  }
-
-  #sfMessageBox {
-    margin-right: 20px;
-  }
-
-  .bubble {
-    max-width: 66vw;
-
-    display: flex;
-    flex-direction: column;    
-
-    font-family: "SF Pro Text";
-    font-size: 14px;
-
-    padding: 10px;
-
-    border-radius: 10px;
-  }
-
-  #aiBubble {
-    background-color: white;
-  }
-
-  #sfBubble {
-    background-color: #58c4fd;
-    color: white;
-  }
-
-  .context {
-    display: flex;
-    align-items: center;
-
-    font-family: "SF Compact Display";
-    font-size: 12px;
-    font-weight: bold;
-    margin-left: 7px;
-    margin-top: 5px;
-  }
-
-  .photo {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-
-    margin-right: 5px;
-
-    width: 30px;
-    height: 30px;
-
-    font-size: 14px;
-
-    background-color: white;
-    border-radius: 15px;
-  }
-
-
-
 </style>
index 8fde8eb42eb8b991ed5eaa3ff25e79685723219c..ea08facfa2804cd6ce31237ade615e1f5d0aef7c 100644 (file)
@@ -52,68 +52,21 @@ const ia = new portAudio.AudioIO({
     closeOnError: false,
   },
 });
-// ia.setEncoding('base64');
+ia.setEncoding('base64');
 ia.start();
 ia.on('error', (e) => {
     console.log('error recording audio', + e);
 });
 ia.on('data', (chunk) => {
-    audioInput.push(chunk);
-});
 
-const ao = new portAudio.AudioIO({
-  outOptions: {
-    channelCount: 1,
-    sampleFormat: portAudio.SampleFormat16Bit,
-    sampleRate: 16000,
-    deviceId: -1, // Use -1 or omit the deviceId to select the default device
-    closeOnError: true // Close the stream if an audio error is detected, if set false then just log the error
-  }
+    const buf = Buffer.from(chunk, 'base64');
+    audioInput.push(buf);
 });
 
-ao.start();
-
-const callback = () => {
-    console.log('yayayay')
-}
-
-const play = (audio) => {
-
-    console.log('audio length', audio.length);
-    let i = 0;
-    write();
-
-    function write() {
-        let ok = true;
-         do {
-              const chunk = audio[i]
-                console.log(chunk, i)
-
-              i++;
-              if (i === audio.length - 1) {
-                // Last time!
-                ao.write(chunk, null, callback);
-              } else {
-                // See if we should continue, or wait.
-                // Don't pass the callback, because we're not done yet.
-                ok = ao.write(chunk, null);
-              }
-        } while (i < audio.length - 1 && ok);
-        if (i < audio.length - 1) {
-          // Had to stop early!
-          // Write some more once it drains.
-          ao.on('drain', write);
-        }
-    }
-
-}
-
 async function processAudio() {
 
     const buf = Buffer.concat(audioInput);
 
-    play(audioInput);
-
     audioInput = [];
 
    transcribeSpeech({