]> Repos - mime-chat/commitdiff
polish
authorAndrew Gundersen <gundersena@xavier.edu>
Tue, 18 Jan 2022 22:58:56 +0000 (16:58 -0600)
committerAndrew Gundersen <gundersena@xavier.edu>
Tue, 18 Jan 2022 22:58:56 +0000 (16:58 -0600)
17 files changed:
src/audio.js
src/io.js
src/main.js
src/render/assets/connectLogo.svg
src/render/components/app.js
src/render/components/bubble.js
src/render/components/context.js
src/render/components/control/scroll.js
src/render/components/control/text.js
src/render/components/drop.js [new file with mode: 0644]
src/render/components/message.js
src/render/components/messenger.js
src/render/components/settings.js
src/render/main.css
src/render/preload.js
src/session.js
src/window.js

index 3736ee9f336f89708db6dd4b112b2201f3846bb4..a42043b9fab78cfe52679e85616db66f8b3477b4 100644 (file)
@@ -67,7 +67,7 @@ function stopRecording()
     setRecordingStatus(false);
 
     sendMessage({
-        category: "audio/L16",
+        category: "audio",
         text: null,
         blob: encode(nodeAudio.utils.mergeChunks(chunks).buffer)
     });
index a269d493e363f06289e5cd3897ce3ae0ee4550eb..435377e57af0a16c6aac88ef2179e84d26beaeb9 100644 (file)
--- a/src/io.js
+++ b/src/io.js
@@ -56,25 +56,3 @@ ipcMain.on("message", (_e, message) => sendMessage(message));
 exports.connectToPlatform = connectToPlatform;
 exports.sendMessage = sendMessage;
 exports.disconnectFromPlatform = disconnectFromPlatform;
-
-
-
-/* ------------- Test Messages------------- */
-
-
-
-setTimeout(() => {
-
-    // sendMessage({
-    //     category: "text/plain", 
-    //     text: "show contacts",
-    //     blob: null
-    // })
-
-    sendMessage({
-        category: "text/plain", 
-        text: "add contact John Smith, john.smith97@gmail.com",
-        blob: null
-    })
-
-}, 2000);
index 841579ecdcb781a841b57c61410a61959b8861a5..f4b803aa1b16fe1e0e418505dc343fb4c5851138 100644 (file)
@@ -8,6 +8,8 @@ const { createWin } = require("./window");
 const { initAccount } = require("./account"); 
 const { terminateAudio } = require("./audio");
 
+app.commandLine.appendSwitch("enable-transparent-visuals");
+
 // Assert a light theme
 nativeTheme.themeSource = "light";
 
@@ -20,7 +22,7 @@ app.on("ready", () =>
     initAccount();
 });
 
-// app.on("will-quit", terminateAudio);
+app.on("will-quit", terminateAudio);
 
 // When user clicks app icon (re-open)
 app.on("activate", createWin);
index 7a390a47aeb833d91158d6d05d30c457bb5e1f70..7adceeab7330560f20d1e5a2c4e1f29d33459e74 100644 (file)
@@ -1,14 +1,12 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24.87" height="23.001" viewBox="0 0 24.87 23.001">
-  <g id="Group_541" data-name="Group 541" transform="translate(-4127 -507)">
-    <g id="Group_33" data-name="Group 33" transform="translate(4127 507)">
-      <g id="Group_32" data-name="Group 32" transform="translate(0 0)">
-        <g id="Group_31" data-name="Group 31" transform="translate(0 11.948)">
-          <circle id="Ellipse_50" data-name="Ellipse 50" cx="5.527" cy="5.527" r="5.527" transform="translate(0 0)" fill="#383838"/>
-          <circle id="Ellipse_51" data-name="Ellipse 51" cx="5.527" cy="5.527" r="5.527" transform="translate(13.817 0)" fill="#383838"/>
-        </g>
-        <circle id="Ellipse_52" data-name="Ellipse 52" cx="5.527" cy="5.527" r="5.527" transform="translate(6.898 0)" fill="#383838"/>
-        <path id="Path_150" data-name="Path 150" d="M36.27,83.67" transform="translate(-30.733 -66.196)" fill="#ff0"/>
+<svg id="logo" xmlns="http://www.w3.org/2000/svg" width="24.87" height="23.001" viewBox="0 0 24.87 23.001">
+  <g id="Group_33" data-name="Group 33">
+    <g id="Group_32" data-name="Group 32" transform="translate(0 0)">
+      <g id="Group_31" data-name="Group 31" transform="translate(0 11.948)">
+        <circle id="Ellipse_50" data-name="Ellipse 50" cx="5.527" cy="5.527" r="5.527" transform="translate(0 0)" fill="#383838"/>
+        <circle id="Ellipse_51" data-name="Ellipse 51" cx="5.527" cy="5.527" r="5.527" transform="translate(13.817 0)" fill="#383838"/>
       </g>
+      <circle id="Ellipse_52" data-name="Ellipse 52" cx="5.527" cy="5.527" r="5.527" transform="translate(6.898)" fill="#383838"/>
+      <path id="Path_150" data-name="Path 150" d="M36.27,83.67" transform="translate(-30.733 -66.196)" fill="#ff0"/>
     </g>
   </g>
 </svg>
index 08909a6b585cb315027a33de2474edf567cf4a64..ffc34f74f4e77374c010a639c28ab9de857c934e 100644 (file)
@@ -1,6 +1,7 @@
+import Login from "./login.js";
 import Splash from "./splash.js";
+import Header from "./header.js";
 import Messenger from "./messenger.js";
-import Login from "./login.js";
 
 const account = Vue.ref(null);
 
@@ -8,6 +9,7 @@ const App =
 {
     components: {
         Splash,
+        Header,
         Messenger,
         Login
     },
@@ -20,7 +22,7 @@ const App =
     template: `
         <main id="app" v-if="account !== null">
 
-            <button id="header-titlebar" />
+            <Header />
 
             <Messenger v-if="account"/>
             <Login v-else />
@@ -31,7 +33,6 @@ const App =
 }
 
 window.mainApi.on("set-account", (account_) => {
-    console.log("setting-account");
     account.value = account_;
 });
 
index 16f79835440f9bfafb5ac9853fb11437fd3c73b4..59e04170fbb24777f6765ff9a25eda7d778ab297 100644 (file)
@@ -1,6 +1,6 @@
 const Bubble =
 {
-    props: ["category", "text", "blob", "modifier", "child"],
+    props: ["category", "text", "html", "blob", "modifier", "child"],
 
     setup(props)
     {
@@ -9,7 +9,7 @@ const Bubble =
         }
 
         Vue.onMounted(() => {
-            document.getElementById("messenger").dispatchEvent(new CustomEvent('adjust-scroll'));
+            document.dispatchEvent(new CustomEvent("scroll"));
         });
 
         return { getUrl };
@@ -18,13 +18,13 @@ const Bubble =
     template: `
         <div :class="'bubble ' + modifier + '-bubble ' + modifier +'-'+ child">
 
-            <p v-if="category=='text/plain'">{{ text }}</p>
+            <p v-if="category=='text'">{{ text }}</p>
 
-            <p v-else-if="category=='audio/L16'">{{ text }}</p>
+            <p v-else-if="category=='audio'">{{ text }}</p>
 
-            <div v-else-if="category=='text/html'" v-html="text"></div>
+            <div v-else-if="category=='html'" v-html="html"></div>
 
-            <img v-else-if="category.startsWith('image/')" :src="getUrl()" />
+            <img v-else-if="category == 'image'" :src="getUrl()" />
 
             <a v-else :href="getUrl()">{{ text }}</a>
 
index b6879ae0ba7735da654097c4b915a8baebbab3c0..0c9e89c21c53384307dd9ecdd5b620479a7252ae 100644 (file)
@@ -20,15 +20,10 @@ const Context =
     template: `
         <span :class="'context ' + modifier + '-context'">
 
-            <div 
-                v-show="avatar"
-                class="context-avatar"
+            <img v-show="avatar" class="context-avatar" 
                 :class="{ audio: playback }"
-            >    
-
-                <img :src="'data:image/png;base64,' + avatar" />
-
-            </div>
+                :src="'data:image/png;base64,' + avatar" 
+            />
 
             {{ context }}
 
index 4666ea151a9572f9623189b6fcef3c3320caa4ee..db0dd3b98d9c6665c0073bd25e0fe8937525dc75 100644 (file)
@@ -7,13 +7,11 @@ const initScroll = (elementId) => {
 }
 
 const isBottom = () => {
-  if (el) {
-    return el.scrollHeight - el.clientHeight <= el.scrollTop + 1;
-  }
+  return el.scrollHeight - el.clientHeight <= el.scrollTop + 1;
 }
 
 const adjustScroll = () => {
-  if (el) {
+  if (isBottom()) {
     el.scrollTo({
       top: el.scrollHeight - el.clientHeight,
       behavior: 'smooth'
index 626746f2dca7b245dd4a3c5811afa2e1c4afdc76..cc8fafd38e49621a252d5f672c5682ee1beb19ec 100644 (file)
@@ -35,7 +35,7 @@ function useText(elementId, left, typing)
 
         window.addEventListener("keydown", (e) => {
 
-            if (!show.value && !metaKeys.includes(e.key))
+            if (!show.value && !metaKeys.includes(e.key) && !e.ctrlKey)
             {
                 show.value = true;
             }
@@ -47,7 +47,7 @@ function useText(elementId, left, typing)
             if (e.key === "Enter" && el.value)
             {
                 window.mainApi.send("message", { 
-                    category: "text/plain", 
+                    category: "text", 
                     text: el.value,
                     blob: null
                 });
diff --git a/src/render/components/drop.js b/src/render/components/drop.js
new file mode 100644 (file)
index 0000000..e677555
--- /dev/null
@@ -0,0 +1,19 @@
+const onDrop = async (e) => {
+    const file = e.dataTransfer.items[0].getAsFile();
+
+    const buffer = await file.arrayBuffer();
+    const b64String = await window.mainApi.invoke("encode", buffer);
+
+    let category = "file";
+    if (file.type.startsWith("image/")) {
+        category = "image"
+    }
+
+    window.mainApi.send("message", {
+        category: category,
+        text: file.name,
+        blob: b64String
+    });
+}
+
+export default onDrop;
\ No newline at end of file
index fd1b41c87a27fc9ae1942f26c4a367df1cc961ff..23e28df0fd964e5369ed12fa15f70064bcfd8e65 100644 (file)
@@ -22,6 +22,7 @@ const Message =
                 v-for="(c, index) in content"
                 :category="c.category"
                 :text="c.text"
+                :html="c.html"
                 :blob="c.blob"
                 :modifier="modifier"
                 :child="calcChild(index, content.length)"
index 668b50585a7e665497e4e4631f26899ec80e6f1a..3384d6d85bbed5dccf3241864a8fe11c3dbe6f52 100644 (file)
@@ -1,4 +1,5 @@
-import initScroll from "./control/scroll.js";
+import onDrop from "./control/drop.js";
+import adjustScroll from "./control/scroll.js";
 
 import WS from "./ws.js";
 import Input from "./input.js";
@@ -17,62 +18,32 @@ const Messenger = {
     setup()
     {
         const person = Vue.ref("");
-        const messages = Vue.ref([{
-            modifier: "ai",
-            content: [{
-                category: "text/html",
-                text: `<div class="mail">
-                           <h4>About HTML Parser</h4>
-                           <p>Return the text of the most recently opened start tag. This should not normally be needed for structured processing, but may be useful in dealing with HTML “as deployed” or for re-generating input with minimal changes (whitespace between attributes can be preserved, etc.).</p>
-                       </div>`,
-                blob: null
-            }],
-            context: "Email from David Spade",
-            avatar: null,
-            id: 0
-        }]);
-
-        const onDrop = async (e) => {
-            const file = e.dataTransfer.items[0].getAsFile();
-
-            const buffer = await file.arrayBuffer();
-            const b64String = await window.mainApi.invoke("encode", buffer);
-
-            window.mainApi.send("message", {
-                category: file.type,
-                text: file.name,
-                blob: b64String
-            });
-        }
+        const messages = Vue.ref([]);
 
         Vue.onMounted(() => {
 
-            window.mainApi.on("message", (message) => {
-                if (message.person)
+            window.mainApi.on("update", (update) => {
+
+                if (update.name)
                 {
-                    person.value = message.person;
-                    messages.value = message.messages;
+                    person.value = update;
                 }
-                else if (message.name) 
+                else if (typeof update == Array)
                 {
-                    person.value = message;
+                    messages.value.push(...update);
                 }
                 else if (message.content)
                 {
-                    messages.value.push(message);
+                    messages.value.push(update);
                 }
-                else
+                else if (update.new)
                 {
-                    messages.value[messages.value.length - 1].content.push(message);
+                    messages.value.at(-1)[update.new] = update.val;
                 }
-            });
 
-            initScroll("messenger");
-            window.mainApi.send("messenger");
-        });
+            });
 
-        Vue.onUnmounted(() => {
-            messages.value = [];
+            window.mainApi.send("message", "win");
         });
 
         return { person, messages, onDrop };
index 68d69f2579e33d1a51d857e7afb97affbc42369a..8e4a0fc066b52f35e98fefda9ce1115342979bcb 100644 (file)
@@ -4,15 +4,23 @@ const Settings =
     setup() {
         const active = Vue.ref(false);
 
-        window.addEventListener("keydown", (e) => {
-            console.log("toggle settings");
-        })
+        function hideSettings(e) {
+            if (e.key == "Escape") {
+                active.value = false;
+                window.removeEventListener("keydown", hideSettings);
+            }
+        }
+
+        function showSettings() {
+            active.value = true;
+            window.addEventListener("keydown", hideSettings);
+        }
 
         const logout = async () => {
             await window.mainApi.send("logout");
         }
 
-      return { active, logout };
+      return { showSettings, active, logout };
     },
 
     template: `
@@ -22,7 +30,11 @@ const Settings =
                 Logout
             </button>
 
-        </div>`
+        </div>
+
+        <button v-else class="settings-icon" @click="showSettings">
+            <img src="./assets/settingsIcon.svg">
+        </button>`
 }
 
 export default Settings;
\ No newline at end of file
index f25adda87d93e296a1f6d6b228ea141031281963..57429e3d0ade085d6137a6dde4280a908c669db8 100644 (file)
@@ -1,6 +1,7 @@
 html, body {
   margin: 0;
   padding: 0;
+  background-color: rgba(235, 235, 235, 0.75);
 }
 
 /* The first word of the class is the component that it modifys. */
@@ -46,6 +47,7 @@ html, body {
 }
 
 .contacts img {
+  height: 30px;
   border-radius: 50%;
 }
 
@@ -60,26 +62,10 @@ html, body {
 
 .contacts .email {
   font-family: SF Compact Display;
-  font-weight: bold;
   font-size: 12px;
   color: #898989;
 }
 
-.mail {
-  padding: 12px;
-  margin: 0px;
-  background-color: #D6F2FF;
-  border-radius: inherit;
-}
-
-.mail h4 {
-  margin-top: 0px;
-}
-
-.mail p {
-  margin-bottom: 0px;
-}
-
 #header-menu {
   position: fixed;
   margin-left: 20px;
@@ -251,6 +237,7 @@ html, body {
   content: '';
   display: inline-block;
   position: absolute;
+  box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.15);
 }
 
 .ws-dot::before {
@@ -493,13 +480,13 @@ html, body {
 }
 
 .bubble a {
+  display:inline-block;
+  text-decoration: none;
   border-radius: inherit;
-  font-family: "SF Compact Rounded";
   background-color: #D9D9D9;
   font-weight: bold;
-  padding: 12px;
+  padding: 10px;
   color: #727272;
-  margin: 0px;
 }
 
 .context {
@@ -522,18 +509,9 @@ html, body {
 }
 
 .context-avatar {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 30px;
-  height: 30px;
-  background-color: white;
-  border-radius: 15px;
   margin-right: 5px;
-}
-
-.context-avatar img {
   border-radius: 50%;
+  height: 30px;
 }
 
 /* ---------- shared between components ---------- */
index 9b50adf51a4c028fade4458613e22a3a2925c752..e3c66f97341c453de5ffa26186e8bd4a3701ee14 100644 (file)
@@ -4,7 +4,7 @@ const { contextBridge, ipcRenderer } = require("electron");
 
 const validFromMainChannels = [
     "set-account", 
-    "message", 
+    "update", 
     "ws-status",
     "record",
     "playback"
@@ -16,7 +16,8 @@ const validToMain = [
     "login",
     "logout",
     "encode",
-    "decode"
+    "decode",
+    "nav-bar"
 ]
 
 ipcRenderer.setMaxListeners(250);
index 08ece17a3c032dc5736d15fcdea69de484b83a33..b4433a4cbdfdc0b2b951ba26eaa3ab92cac54c55 100644 (file)
@@ -5,21 +5,13 @@ const { backgroundMitt, ipcEmit } = require("./utils/emitter");
 const { connectToPlatform, disconnectFromPlatform } = require("./io");
 const { initAudio, terminateAudio, playback, streamState } = require("./audio");
 
-let ui; /* wait to receive ui from the platform */
-
 const messageQueue = [];
 
 let processContentId;
 
-/* Possible messages:
- *    - New UI (set ui)
- *    - New message (add message to ui.messages)
- *    - New content (add content to existing message)
- *    - Update person
- */
 backgroundMitt.on("message", (message) => messageQueue.push(message));
 
-function handleMessageQueue()
+function handleUpdateQueue()
 {
     if (!streamState.pb && !streamState.rec)
     {
@@ -27,71 +19,32 @@ function handleMessageQueue()
 
         if (update)
         {
-            console.log("Handling UI Update:", update);
-
-            if (update.person)
-            {
-                ui = update;
-            }
-            else if (update.name)
-            {
-                ui.person = update;
-            }
-            else if (update.content)
+            if (update.title)
             {
-                ui.messages.push(update); 
+                new Notification(update).show();
             }
-            else
+            else if (update.audio)
             {
-                ui.messages[ui.messages.length - 1].content.push(update); 
+                playback(update);
             }
-
-            ipcEmit("message", update);
-
-            // notify();
+            else { ipcEmit("update", update); }
         }
     }
 }
 
-
-function notify()
-{
-    const message = ui.messages[ui.messages.length - 1];
-
-    const content = message.content[message.content.length -1];
-
-    new Notification(
-    {
-        title: message.context, 
-        body: content.text
-    }
-    ).show();
-
-    if (content.category == "audio/L16") playback(content.blob, message.id);
-}
-
 function launchSession(account)
 {
     connectToPlatform(account);
-    // initAudio();
+    initAudio();
     processContentId = setInterval(handleMessageQueue, 100);
 }
 
 function endSession()
 {
     clearInterval(processContentId);
-    // terminateAudio();
+    terminateAudio();
     disconnectFromPlatform();
-    ui = null;
 }
 
-ipcMain.on("messenger", () => {
-    if (ui) {
-        ipcEmit("message", ui);
-    }
-});
-
 exports.launchSession = launchSession;
 exports.endSession = endSession;
-
-// ui.messages[ui.messages.findIndex(m => m.id === message.id)].content.push(message);
index 77db4ea38b9b1dd10926f12b2bf235f8804a672c..45a45da2c50e52cf85850dc620ee1da5f529a908 100644 (file)
@@ -21,28 +21,11 @@ function updateWindowPosition()
 }
 
 
-function createPreviewWin(_e, content)
+function onNavBar(_e, cmd) 
 {
-    console.log("Creating preview window");
-
-    const preview = new BrowserWindow({
-        width:           500,
-        height:          300,
-        x:               null,
-        y:               null,
-        resizable:       true,
-        frame:           false,
-        webPreferences:  { preload: path.join(__dirname, "/render/preload.js") }
-    });
-    
-    preview.loadFile(path.join(__dirname, "preview.html"));
-
-    preview.webContents.on("did-finish-load", () => {
-        preview.webContents.send("preview-init", content);
-    });
+    cmd === "close" ? win.close() : win.minimize();
 }
 
-
 function createWin()
 {
     if (win) return;
@@ -56,7 +39,6 @@ function createWin()
         x:               pos.x,
         y:               pos.y,
         resizable:       true,
-        backgroundColor: "#EBEBEB",
         frame:           false,
         minWidth:        350,
         minHeight:       500,
@@ -92,6 +74,6 @@ function createWin()
     });
 }
 
-ipcMain.on("preview", createPreviewWin);
+ipcMain.on("nav-bar", onNavBar);
 
 exports.createWin = createWin;