]> Repos - mime-chat/commitdiff
refactor message_renderer
authorEnrique Hernandez <hernandeze2@xavier.edu>
Fri, 6 Nov 2020 15:06:18 +0000 (09:06 -0600)
committerEnrique Hernandez <hernandeze2@xavier.edu>
Fri, 6 Nov 2020 15:06:18 +0000 (09:06 -0600)
src/components/UI/UIDetails/messageRenderer.vue [new file with mode: 0644]
src/components/UI/index.vue
src/composables/messageRenderer/useMessageRenderer.ts [new file with mode: 0644]
src/composables/messageRenderer/useOffsets.ts [new file with mode: 0644]
src/composables/messageRenderer/useRendererAnims.ts [new file with mode: 0644]
src/types/message/index.ts

diff --git a/src/components/UI/UIDetails/messageRenderer.vue b/src/components/UI/UIDetails/messageRenderer.vue
new file mode 100644 (file)
index 0000000..4d205fa
--- /dev/null
@@ -0,0 +1,59 @@
+<template>
+  <g id="cardsDiv">
+    <g
+      v-for="(item, index) in renderArr"
+      :key="index"
+      :id="index"
+      class="test"
+      transform="translate(0, 0)"
+    >
+      <transition
+        appear
+        v-on:before-appear="beforeEnter"
+        v-on:appear="enter"
+        v-on:after-enter="afterEnter"
+      >
+        <MessageItem :item="item" :key="index" />
+      </transition>
+    </g>
+  </g>
+</template>
+
+<script lang="ts">
+import useMessageRenderer from "@/composables/messageRenderer/useMessageRenderer";
+import { defineComponent, reactive, ref, inject } from "vue";
+import MessageItem from "./messageItem.vue";
+import Messages from "./messages";
+import { Message } from "@/types/message/index";
+export default defineComponent({
+  name: "MessageRenderer",
+  components: { MessageItem },
+  setup() {
+    const emitter: any = inject("mitt");
+    const renderArr: Message[] = reactive([]);
+    const messages = Messages;
+    const count = ref(0);
+
+    const { beforeEnter, enter, afterEnter } = useMessageRenderer();
+
+    emitter.on("renderMessage", (payload: any) => {
+      renderArr.push(payload);
+    });
+    function renderMessage() {
+      if (count.value < messages.length) {
+        renderArr.push(messages[count.value]);
+        count.value++;
+        return;
+      }
+    }
+
+    return {
+      renderMessage,
+      renderArr,
+      beforeEnter,
+      enter,
+      afterEnter,
+    };
+  },
+});
+</script>
index 2c71f910d8d66e11828b9ff4fbba0f2b5ad0c5d0..b59a50593809bd914cd3cdbfdb4080f86f2903a5 100644 (file)
@@ -7,52 +7,31 @@
     @click="renderMessage"
   >
     <AI />
-
-    <g id="cardsDiv">
-      <g
-        v-for="(item, index) in renderArr"
-        :key="index"
-        :id="index"
-        class="test"
-        transform="translate(0, 0)"
-      >
-        <transition
-          appear
-          v-on:before-appear="beforeEnter"
-          v-on:appear="enter"
-          v-on:after-enter="afterEnter"
-        >
-          <MessageItem :item="item" :key="index" />
-        </transition>
-      </g>
-    </g>
-
+    <MessageRenderer />
     <InputItem />
     <TitleBar />
   </svg>
 </template>
 
 <script lang="ts">
-import { defineComponent, ref, reactive } from "vue";
+import { defineComponent, ref, reactive, inject } from "vue";
 import MessageItem from "./UIDetails/messageItem.vue";
 import AI from "../AI/index.vue";
 import InputItem from "./UIDetails/inputItem.vue";
 import TitleBar from "./UIDetails/titleBar.vue";
 import Messages from "./UIDetails/messages";
-import useUIindexAnims from "@/composables/anims/useUIindexAnims";
+import MessageRenderer from "./UIDetails/messageRenderer.vue";
 export default defineComponent({
   name: "UIindex",
-  components: { AI, MessageItem, InputItem, TitleBar },
+  components: { AI, MessageItem, InputItem, TitleBar, MessageRenderer },
   setup() {
-    const renderArr: Message[] = reactive([]);
     const messages = Messages;
     const count = ref(0);
-
-    const { beforeEnter, enter, afterEnter } = useUIindexAnims();
+    const emitter: any = inject("mitt");
 
     const renderMessage = () => {
       if (count.value < messages.length) {
-        renderArr.push(messages[count.value]);
+        emitter.emit("renderMessage", messages[count.value])
         count.value++;
         return;
       }
@@ -60,10 +39,6 @@ export default defineComponent({
 
     return {
       renderMessage,
-      renderArr,
-      beforeEnter,
-      enter,
-      afterEnter,
     };
   },
 });
diff --git a/src/composables/messageRenderer/useMessageRenderer.ts b/src/composables/messageRenderer/useMessageRenderer.ts
new file mode 100644 (file)
index 0000000..5c57877
--- /dev/null
@@ -0,0 +1,57 @@
+import useMessageOffsets from "./useOffsets";
+import useRendererAnims from "./useRendererAnims";
+export default function useMessageRenderer() {
+
+    const { calculateMessageOffsets } = useMessageOffsets();
+    const { scrollAnimate, stackAnimate } = useRendererAnims();
+
+    let messageOffset = {
+        x: 0,
+        y: 0
+    };
+    let modifier: string;
+    let msg: HTMLElement | null;
+    let renderList: NodeList;
+    let scrollAnim = false;
+    let scroll = 0;
+
+    function setRenderList(): void {
+        const messages = document.querySelectorAll(".test");
+        if (messages.length) renderList = messages;
+    }
+
+    function renderMessage(el: SVGGElement): void {
+        const transform = {
+            initialTranslate: `translate(${messageOffset.x} ${messageOffset.y})`,
+            finalTranslate: `translate(${messageOffset.x} ${messageOffset.y + 5})`
+        }
+        scrollAnim ? scrollAnimate(el, transform, scroll, renderList) : stackAnimate(el, transform);
+    }
+
+    function beforeEnter(el: SVGGElement): void {
+        setRenderList();
+        modifier = el.className.baseVal.substring(0, 2);
+    }
+
+    function enter(el: SVGGElement): void {
+        msg = document.getElementById(el.id);
+    }
+
+    function afterEnter(el: SVGGElement) {
+        const messagePadding = 10;
+        if (msg) {
+            messageOffset = calculateMessageOffsets(msg, modifier);
+            scrollAnim = messageOffset.y > 450 ? true : false;
+        }
+        if (scrollAnim) {
+            scroll -= el.getBBox().height + messagePadding;
+        }
+        renderMessage(el);
+    }
+
+    return {
+        beforeEnter,
+        enter,
+        afterEnter
+    };
+}
diff --git a/src/composables/messageRenderer/useOffsets.ts b/src/composables/messageRenderer/useOffsets.ts
new file mode 100644 (file)
index 0000000..d958b0d
--- /dev/null
@@ -0,0 +1,52 @@
+import { ref, onMounted } from "vue";
+export default function useMessageOffsets() {
+    let xOffset = ref(0);
+    let yOffset = ref(0);
+    let messenger: HTMLElement | null;
+    let winW: number;
+    let previousMessageHeight = 0;
+    const messagePadding = 10;
+
+    onMounted(() => {
+        messenger = document.getElementById("messenger");
+        if (messenger) winW = messenger.clientWidth;
+    })
+
+    function setXoffset(messageWidth: number, modifier: string): void {
+        const paddingLeft = 40;
+        switch (modifier) {
+            case "sf":
+                xOffset.value = winW - messageWidth;
+                break;
+            case "ai":
+                xOffset.value = (winW - messageWidth) / 2;
+                break;
+            default:
+                xOffset.value = paddingLeft;
+        }
+    }
+
+    function setYoffset(messageHeight: number): void {
+        if (previousMessageHeight === 0) {
+            yOffset.value = 40;
+        } else {
+            yOffset.value += previousMessageHeight + messagePadding;
+        }
+        previousMessageHeight = messageHeight;
+    }
+
+    const calculateMessageOffsets = (msg: HTMLElement, modifier: string) => {
+        const msgRect = msg.getBoundingClientRect();
+        setXoffset(msgRect.width, modifier)
+        setYoffset(msgRect.height)
+        const offsets = {
+            x: xOffset.value as number,
+            y: yOffset.value as number
+        };
+        return offsets;
+    }
+
+    return {
+        calculateMessageOffsets,
+    }
+}
diff --git a/src/composables/messageRenderer/useRendererAnims.ts b/src/composables/messageRenderer/useRendererAnims.ts
new file mode 100644 (file)
index 0000000..62e9a63
--- /dev/null
@@ -0,0 +1,65 @@
+import { inject } from "vue";
+import AnimeFunc from "@/types/animejs/index";
+import { MessageAnimeFunc } from '@/types/message/index';
+export default function useRendererAnims() {
+
+    // imports animejs safely
+    let anime: AnimeFunc;
+    const animeInject: AnimeFunc | undefined = inject("animejs");
+    if (animeInject) anime = animeInject;
+
+    function scrollOffset(targetList: NodeList | undefined, height: number | undefined): void {
+        if (targetList) {
+            for (const message of targetList) {
+                const m = message.parentNode as HTMLElement;
+                anime({
+                    targets: m,
+                    transform: `translate(0 ${height})`,
+                    easing: "easeInOutQuad",
+                    duration: 500,
+                });
+            }
+        }
+    }
+
+    const scrollAnimate: MessageAnimeFunc = (el, transform, scrollHeight, targetList) => {
+        anime({
+            targets: el, transform: transform.initialTranslate,
+            easing: "easeInOutQuad",
+            duration: 500,
+            begin: function() {
+                scrollOffset(targetList, scrollHeight);
+            },
+            complete: function() {
+                anime({
+                    targets: el,
+                    transform: transform.finalTranslate,
+                    offset: 1000
+                });
+            }
+        });
+    }
+
+    const stackAnimate: MessageAnimeFunc = (el, transform) => {
+        anime({
+            targets: el,
+            transform: transform.initialTranslate,
+            easing: "easeInOutQuad",
+            duration: 1000,
+            complete: function() {
+                anime({
+                    targets: el,
+                    transform: transform.finalTranslate,
+                    easing: "easeInOutQuad",
+                    duration: 500,
+                    offset: 1000
+                });
+            }
+        });
+    }
+
+    return {
+        scrollAnimate,
+        stackAnimate
+    };
+}
index a736afb27efb306da72c32a77ecdc4667ea956de..a4ced0746eb022b7915bfae78765e7502242c66e 100644 (file)
@@ -13,6 +13,6 @@ interface MessageTransform {
 }
 
 export interface MessageAnimeFunc {
-    (message: SVGElement, transform: MessageTransform): void;
+    (message: SVGElement, transform: MessageTransform, scrollHeight?: number | undefined, targetList?: NodeList | undefined): void;
 }