]> Repos - mime-chat/commitdiff
more changes
authorAndrew Gundersen <gundersena@xavier.edu>
Sat, 12 Jun 2021 14:49:41 +0000 (09:49 -0500)
committerAndrew Gundersen <gundersena@xavier.edu>
Sat, 12 Jun 2021 14:49:41 +0000 (09:49 -0500)
src/api/account.ts
src/composables/canvas.ts [new file with mode: 0644]
src/composables/store.ts [deleted file]
src/composables/websockets.ts
src/main.ts
src/render/App.vue
src/render/components/controllers/messenger.control.ts
src/render/components/messenger.vue
src/session.ts
src/state.ts [deleted file]
src/types.ts

index de1335b8c21d1bb621a2246a678864fa0e3f1bb7..98d3c69da3533bde6368a0c303c8f470843a0175 100644 (file)
@@ -4,20 +4,33 @@ import axios from "axios";
 
 const { post } = useHttp();
 
-export const submit = async (email: string, password: string) => (
-    await post('/account/login', { email, password })
-)
+export const usrPwdAuth = async (email: string, password: string) => {
 
-export const fetchAccount = async (email: string, token: string) => (
-    await axios({
+  try {
+    return await post('/account/login', { email, password })
+
+  } catch (e) {
+    return null;
+  }
+
+}
+
+export const tokenAuth = async (cid: string, token: string) => {
+
+  try {
+    return await axios({
       url: "http://127.0.0.1:3000/api/account/profile",
       headers: {
           Cookie: `jwt=${token}`
       },
       method: 'GET',
       data: {
-        email,
+        cid,
       }
     })
-)
 
+  } catch (e) {
+    return null;
+  }
+
+}
\ No newline at end of file
diff --git a/src/composables/canvas.ts b/src/composables/canvas.ts
new file mode 100644 (file)
index 0000000..c85f7ed
--- /dev/null
@@ -0,0 +1,36 @@
+
+
+
+export default class Canvas {
+
+    messages: Message[];
+
+    /* seed canvas with messages on init */
+    constructor(messages: Message[]) {
+        this.messages = messages;
+        ipcEmit("seed-view", this.messages);
+    }
+
+    /* add a new message to the canvas */
+    add(message: Message) {
+        this.messages.push(message);
+        ipcEmit("update-view", message);
+    }
+
+    /* update an existing message */
+    update(message: Message) {
+
+        /* get the target message */
+        let target_message = this.messages.filter((m: Message) => {
+            return m.uid = message.uid;
+        })[0];
+
+        /* replace the target message */
+        if (target_message) {
+            target_message = message;
+            ipcEmit("update-view", message);
+        }
+
+    }
+
+}
diff --git a/src/composables/store.ts b/src/composables/store.ts
deleted file mode 100644 (file)
index 16f8409..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-
-const Store = require('electron-store');
-
-const schema = {
-       key: {
-               type: 'string',
-       },
-    crimataId: {
-        type: 'string'
-    }
-};
-
-export const store = new Store({
-    schema,
-    encryptionKey: "super user test"
-});
index 779f00bf946867ce497df29dc2ed78ce7114b19a..d034027a1092ab34b3c0a8a561433cabde94b7e4 100644 (file)
@@ -3,7 +3,7 @@
 
 import WebSocket from 'ws';
 
-export default function useWebSockets(receiveCallback: (s: string) => void, openCallback?: () => void) {
+export default function useWebSockets(onMessageCallback: (s: string) => void) {
 
     let socket: WebSocket | null = null;
 
@@ -19,36 +19,25 @@ export default function useWebSockets(receiveCallback: (s: string) => void, open
         });
     }
 
-    const onOpen = (_event: WebSocket.OpenEvent) => {
-        console.log("WS:Connected to WS Server!");
-        if (openCallback) openCallback();
-    }
-
-    const onServerMessage = (event: WebSocket.MessageEvent) => {
-        console.log("WS:Message received: ", event.data);
-        receiveCallback(event.data.toString())
-    }
+    const connect = (socketUrl: string, secret: string) => {
 
-    const onClose = (event: WebSocket.CloseEvent) => {
-        console.log("WS:Socket closed normally.")  
-    }
+        /* create a new socket */
+        socket = new WebSocket(socketUrl)
 
-    // Reconnect automatically on error.
-    const onError = (event: WebSocket.ErrorEvent) => {
-        console.log("WS:WebSocket error: ", event.message);
-        console.log("Attempting reconnect in 1s.")
-        setTimeout(createSocket, 1000);
-    }
+        /* add event listeners */
 
-    const createSocket = (socketUrl: string) => {
+        socket.on("open", () => {
+            if (socket)
+            socket.send(secret);
+        });
 
-        socket = new WebSocket(socketUrl)
+        socket.on("message", (event: WebSocket.MessageEvent) => {
+            onMessageCallback(event.data.toString())
+        });
 
-        // Add listeners.
-        socket.addEventListener("open", onOpen);
-        socket.addEventListener("message", onServerMessage);
-        socket.addEventListener("close", onClose);
-        socket.addEventListener("error", onError);
+        socket.on("close", () => {
+            return
+        });
 
     }
 
@@ -59,15 +48,10 @@ export default function useWebSockets(receiveCallback: (s: string) => void, open
         }
     }
 
-    const checkConnection = () => {
-        return true;
-    }
-
     return {
-        createSocket,
+        connect,
         send,
-        close,
-        checkConnection
+        close
     };
 
 }
index 744643db11d4cfc46d856a81038b8a305b5f19b0..9d6414c0073cd152e247013fd85b85e315773e55 100644 (file)
@@ -9,37 +9,29 @@
  * 
  */
 
-import { fetchAccount, submit } from "@/api/account";
+import { tokenAuth, usrPwdAuth } from "@/api/account";
 import { launchSession, endSession } from "@/session";
 import useIpc from "@/ipc/index";
 import store from "@/composables/store";
 
-/* user profile, signals whether user is logged in */
-let auth: Profile | null = null;
-
 /* authenticate the user */
 export async function authenticate(email: string, password: string) {
 
     /* attempt normal login */
-    try {
-        auth = await submit(email, password);
-    } catch (e) {
-        console.log(e);
-    }
+    const platformKey, token, crimataId = await usrPwdAuth(email, password);
+
+    /* launch if successful */
+    if (platformKey)
+    launchSession(platformKey, crimataId);
 
-    /* launch if profile */
-    if (auth) {
-        launchSession(auth);
-    }
+    /* save the token */
+    store.set("token", token);
 
 }
 
 /* logout the user, end the session */
 export function deauthenticate() {
 
-    /* set profile back to null */
-    auth = null;
-
     /* terminate the session */
     endSession();
 
@@ -47,26 +39,24 @@ export function deauthenticate() {
 
 export default async function main() {
 
+    /* initiate controls for frontend to use when needed */
+    useIpc();
+
     /* launch browser window */
-    // await createWindow();
+    await createWindow();
 
-    /* attempt key-based authentication with business api */
-    const token = store.get('key', null);
-    const crimataId = store.get('crimataId', null);
+    /* attempt to get a login token from the store */
+    const token = store.get("token");
 
-    try {
-        const res = await fetchAccount(crimataId, token);
-        auth = parseAuthRes(res);
-    } catch (e) {
-        console.log('[MAIN]', e);
-    }
+    /* try to login with it, returns platform secret and new token on success */
+    if (token)
+    const newToken, profile = await tokenAuth(token);
 
-    /* connect to Crimata, or listen for manual login req */
-    if (auth) {
-        launchSession(auth);
-    }
+    /* if secret, we launch a session */
+    if (newToken)
+    launchSession(newToken, profile);
 
-    /* initiate controls for frontend to use when needed */
-    useIpc();
+    /* finally, save the most recent token */
+    store.set("token", newToken);
 
 }
\ No newline at end of file
index e5c477da03bf77ffcb26805c997bfd1c44e2cb67..d90bcc07c497352dd4b22332e5c0ac997bcd8800 100644 (file)
@@ -6,8 +6,9 @@
 
     <!-- Main Components -->
     <Messenger
-      v-if="profile"
-      :profile="profile"
+      v-if="state.profile"
+      :profile="state.profile"
+      :messages="state.messages"
     />
     <Login v-else />
 
@@ -39,13 +40,13 @@ export default defineComponent({
 
   setup() {
 
-    const state: Ref;
+    const crimataId = ref(false);
 
     onMounted(async () => {
       console.log("[APP]:mounted.");
 
       /* listen for auth related messages */
-      window.addEventListener("update-state", (event: any) => {
+      window.addEventListener("update-auth", (event: any) => {
         state.value = event.data;
       });
 
@@ -56,7 +57,7 @@ export default defineComponent({
     });
 
     return {
-        profile
+        crimataId
     }
   }
 })
@@ -68,7 +69,6 @@ export default defineComponent({
 html, body {
   margin: 0;
   padding: 0;
-  // Background color set in window.ts
 }
 
 #app {
index 63f15ee35ad70407afd2e5889e8b8662e2141ea6..9ae7d47f18cfa9033cf0e5249b146de9bd3cb22a 100644 (file)
 import { ref } from 'vue';
-import invokeSavedMessages from "@/render/ipc";
 import useScroll from "@/render/composables/scroll";
 
-const messages = ref(new Map());
+const canvas = ref();
 
-function getTimeStamp(): number {  
-  const currentdate = new Date();
-  return currentdate.getTime();
+/* seed the canvas with messages */
+const seedCanvas = (messages: Message[]) => {
+  canvas.value = messages;
 }
 
-const newViewMessage = (message: Message): ViewMessage => {
-  return {
-    text: message.text,
-    context: message.context,
-    audio: message.audio,
-    from: message.from,
-    uid: message.uid,
-    time: getTimeStamp(),
-    isChild: "none",
-    seen: false,
-    newMessage: false
-  };
-}
-
-const addMessage = (message: Message, newMessage=false) => {
-  const viewMessage = newViewMessage(message);
-  if (newMessage) viewMessage.newMessage = true;
-  messages.value.set(viewMessage.uid, viewMessage);
+const addMessage = (message: Message) => {
+  canvas.value.push(message);
 }
 
 const updateMessage = (message: Message) => {
-  const viewMessage = messages.value.get(message.uid);
-  viewMessage.context = message.context;
-  viewMessage.text = message.text;
-}
-
-const loadSavedMessages = async () => {
-  const messageData = await invokeSavedMessages();
-  messages.value = new Map(Object.entries(messageData));
-}
-
-const saveMessages = () => {
-  const messageData = Object.fromEntries(messages.value);
-  // must save to json.
-}
 
-const pruneMessages = (limit=200) => {
-  if (messages.value.size >= limit) {
-    const oldest = Array.from(messages.value.keys()).shift();
-    messages.value.delete(oldest);
-  }
-}
-
-const updateGrouping = () => {
+  let target_message = canvas.value.filter((m: Message) => {
+      return m.uid = message.uid;
+  })[0];
 
-  const isSimmilar = (messageA: ViewMessage, messageB: ViewMessage) => {
-    if ((Math.abs(messageA.time - messageB.time) < 20000) && (messageA.from == messageB.from) && (messageA.context == messageB.context)) {
-      return true
-    }
-    return false
+  if (target_message) {
+    target_message = message;
   }
 
-  const refs = Array.from(messages.value.keys())
-
-  // Get the last three messages.
-  const first = messages.value.get(refs[refs.length - 1])
-  const second = messages.value.get(refs[refs.length - 2])
-  const third = messages.value.get(refs[refs.length - 3])
-
-  // If messages are simmilar, update the classes.
-  if ((first) && (second)) {
-    if (isSimmilar(first, second)) {
-      first.isChild = "last" // i.e. last in group.
-      second.isChild = "first"
-
-      if (third) {
-        if ((third.isChild == "first") || (third.isChild == "middle")) {
-          second.isChild = "middle"
-        }
-      }
-    }
-  }
 }
 
 export default function useMessages() {
 
   const { updateScrollRef, adjustScroll } = useScroll("messenger");
 
-  /* Given new message object, update the view accordingly */
-  const updateMessageView = (newMessages: Message[]) => {
-
-    const bottom = updateScrollRef(); // see if the user is scrolled down
-
-    // take each message and apply view
-    newMessages.forEach((message: Message) => {
-
-      // add or update message depending
-      if (messages.value.has(message.uid)) {
-        updateMessage(message);
-      } else addMessage(message);
-
-      pruneMessages(); // pop off old messages from view
-      updateGrouping(); // group like message together
-
-      if (bottom) adjustScroll(); // only scroll if user was at bottom
-      
-      saveMessages();
-
-    });
-
-  }
-
   return {
-    messages,
-    updateMessageView,
-    loadSavedMessages
-  }
-
-}
-
-
-  // // Seed message view with message history.
-  // const prepMessageView = async (newMessages: Message[]) => {
-  //   console.log("MSGR:Prepping messenger view.")
-
-  //   // Load and render saved messages and immediately scroll to bottom.
-  //   await loadSavedMessages();
-  //   setTimeout(setScroll.bind(false), 10);
-
-  //   // Render new messages, then wait 1s to scroll.
-  //   if (newMessages.length) {
-
-  //     console.log("MSGR:Adding new messages")
-
-  //     newMessages.forEach(message => {
-  //       addMessage(message, true);
-  //     })
-
-  //     setTimeout(setScroll.bind(true), 1000);
+    canvas,
+    seedCanvas,
+    addMessage,
+    updateMessage
+  };
 
-  //   }
-  // }
\ No newline at end of file
+}
\ No newline at end of file
index 77d54f30431c613668bce6284314baf8f322a2a1..4ea2d5b73c90c808023f6bdc7a30b1016bc6f593 100644 (file)
@@ -11,6 +11,7 @@
       v-for="message in messages"
       :text="message.text"
       :context="message.context"
+      :child
       :key="message[0]"
     />
   </div>
@@ -28,7 +29,7 @@ import useMessages from "@/render/composables/messages";
 export default defineComponent({
   name: "Messenger",
 
-  props: ["state"],
+  props: ["profile", "messages"],
 
   components: {
     Message,
@@ -43,12 +44,19 @@ export default defineComponent({
 
     onMounted(() => {
 
-      /* populate the message view with existing messages */
-      updateMessageView(state.savedMessages, state.newMessages);
+      /* seed messages */
+      window.ipcRenderer.on("init-messages", (e_: any, payload: any) => {
+        seedMessages(payload.messages);
+      });
+
+      /* add a new message */
+      window.ipcRenderer.on("add-message", (_e: any, payload: any) => {
+        addMessage(payload.message);
+      });
 
-      /* wait and listen for new messages to come in */
-      window.ipcRenderer.on("new-message", (_e: any, payload: any) => {
-        updateMessageView(payload.message);
+      /* update an existing message */
+      window.ipcRenderer.on("update-message", (_e: any, payload: any) => {
+        updateMessage(payload.message);
       });
 
     });
index 0a893d85aa09997d5459795ccc9e5178cee9b84b..afebe5b2af6d5cb6aabf559144dbe3cdc29787fa 100644 (file)
@@ -3,7 +3,11 @@
 
 
 import useAudio from "@/audio";
-import { loadState, saveState, emitState } from "@/state";
+import Canvas from "@/composables/convas";
+import ipcEmit from "@/composables/emitter";
+
+/* data structure of messages that's tied to the UI */
+let msgrState: UIState | null = null;
 
 /* start and stop audio functionality */
 const { initAudio, closeAudio } = useAudio();
@@ -12,53 +16,57 @@ const { initAudio, closeAudio } = useAudio();
  * Controls for interfacing with the platform.
  * Takes an onMessage callback which we define below.
  */
-const { connect, send, close } = usePlatform((message: Message) => {
-
-    /* add the message to the state */
-    addMessage(message);
-
-    /* push the message to the browser */
-    if (win) emit("new-message", message);
+const { connect, send, close } = useWebsockets((content: any) => {
+
+    /* if the platform fails to authenticate, we must back down */
+    if (content === "auth_error") {
+        deauthenticate();
+        return;
+    }
+
+    /* on init, platform sends state, used to init canvas */
+    if (isInitMessage(content)) {
+        uiState.set(content);
+    }
+    
+    
+    else if (isAddMessage(content)) {
+        uiState.add(content);
+    }
+
+    else {
+        uiState.update(content);
+    }
 
 });
 
 /* send a message to the platform */ 
 export function sendMessage(message: Message) {
 
-    /* add the message to the state */
-    addMessage(message);
-
-    /* push the message to the browser */
-    if (win) emit("new-message", message);
-
     /* socket send */
     send(message);
 
 }
 
 /* launch a new session (the main process for authenticated users) */
-export function launchSession(profile: Profile) {
-
-    /* load any previously saved state for that user */
-    loadState(profile);
+export function launchSession(platformKey: string, crimata_id: string) {
 
     /* connect to the platform */
-    connect(profile);
+    connect(PLATFORM_URL, platformKey);
 
     /* initialize the audio streams */
-    // initAudio();
+    initAudio();
 
-    /* finally we can push state to browser */
-    if (win) emitState();
+    /* push profile to window */
+    if (win)
+    ipcEmit("update-auth", crimata_id);
 
 }
 
 export function endSession() {
 
-    closeAudioStreams();
+    closeAudio();
 
-    closeSocket();
+    close();
 
-    state.clear();
-
-}
\ No newline at end of file
+}
diff --git a/src/state.ts b/src/state.ts
deleted file mode 100644 (file)
index 1d6ce02..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-const Store = require('electron-store');
-
-/* simple data persistance */
-const store = new Store;
-
-/* state of the session (e.g. profile and messages for now) */
-let state: State | null = null;
-
-/* load saved state in electron store for given user */
-export function loadState(profile: Profile) {
-    state = store.get("state", null);
-}
-
-/* add a message to state.messages */
-export function addMessage(message: Message) {
-    if (state) {
-        state.messages.push(message);
-        saveState();
-    }
-}
-
-export function saveState() {
-    store.set("state", state);
-}
-
-export function emitState() {
-    emit("update-state", state);
-}
-
index b437ffad4d126e20446149a6d3ec13c2f93462e0..e8682b89f3a8fa207199a2b0d8755947f0258cfb 100644 (file)
@@ -9,8 +9,6 @@ interface Message {
 
 interface ViewMessage extends Message {
     child: string;
-    seen: boolean;
-    newMessage: boolean;
 }
 
 interface WindowState {
@@ -26,11 +24,6 @@ interface Profile {
     initials: string;
 }
 
-interface State {
-    profile: Profile | null;
-    messages
-}
-
 interface LoginPayload {
     email: string;
     password: string;