});
// Instantiate socket session with crimata-platorm.
- // if (!socket) initSession();
- // socket = true;
+ if (!socket) initSession();
+ socket = true;
// Begin audio stream.
// initRecorder();
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
:viewBox="scrollView"
+ id="test"
>
- <g id="messageView" transform="translate(0, 5)">
+ <g id="messageView" transform="translate(0, 20)">
<g
v-for="(item, index) in renderArr"
:key="index"
- class="messageList"
- transform="translate(0, 25)"
preserverAspectRatio="none"
>
<transition
import useScrollView from "@/modules/scrollView";
import TextBubble from "@/components/textBubble/index.vue";
import { Message } from "@/types/message/index";
-import { defineComponent, reactive, onMounted, onUnmounted } from "vue";
+import { defineComponent, reactive, onMounted, onUnmounted, watch, ref, computed } from "vue";
import useMitt from "@/modules/mitt";
import { useIpc } from "@/modules/ipc";
emitter.on("animateSend", async (message) => {
try {
- renderArr.push(message)
- // await invoke(message);
- // renderArr.push(data.value);
+ // renderArr.push(message)
+ await invoke(message);
+ renderArr.push(data.value);
} catch (e) {
console.log("No response. Do not render.");
}
},
});
</script>
-
-<style lang="scss" scoped>
-svg {
- height: 1%;
- overflow: hidden;
-}
-#messageRenderer {
- margin: 0;
-}
-</style>
/**
* anime js animations used by message renderer
*/
-export default function useMessageViewAnims(): {
- shiftAnimate: MessageAnimeFunc;
- stackAnimate: MessageAnimeFunc;
-} {
+export default function useMessageViewAnims() {
// imports animejs safely
let anime: AnimeFunc;
const animeInject: AnimeFunc | undefined = inject("animejs");
if (animeInject) anime = animeInject;
- // shifts message list by a given value
- function shiftList({ targetList, sv }: { targetList: NodeList | undefined; sv: number | undefined }) {
- if (targetList) {
- for (const element of targetList) {
- const el = element.parentNode as HTMLElement;
- anime({
- targets: el,
- transform: `translate(0 ${sv})`,
- easing: "easeInOutQuad",
- duration: 500,
- });
- }
- }
- }
-
// adds new message at the bottom of the list and shifts existing message list
- const shiftAnimate: MessageAnimeFunc = (el, transform, shiftValue, targetList) => {
+ const shiftAnimate = (el: Element, transform: string, view: SVGGElement, viewTransform: string) => {
anime({
targets: el,
- transform: transform.initialTranslate,
+ transform: transform,
easing: "easeInOutQuad",
- duration: 500,
+ duration: 800,
begin: function() {
- shiftList({
- targetList,
- sv: shiftValue
- });
+ shiftView(view, viewTransform);
},
- complete: function() {
- anime({
- targets: el,
- transform: transform.finalTranslate,
- easing: "easeInOutQuad",
- duration: 500,
- offset: 1000
- });
- }
});
}
// stacks message from top to bottom
- const stackAnimate: MessageAnimeFunc = (el, transform) => {
+ const stackAnimate = (el: Element, transform: string) => {
anime({
targets: el,
- transform: transform.initialTranslate,
+ transform: transform,
easing: "easeInOutQuad",
duration: 1000,
- complete: function() {
- anime({
- targets: el,
- transform: transform.finalTranslate,
- easing: "easeInOutQuad",
- duration: 500,
- offset: 1000
- });
- }
+ });
+ }
+
+ // update message View bottom bound
+ const shiftView = (el: SVGGElement, transform: string) => {
+ anime({
+ targets: el,
+ transform: transform,
+ easing: "easeInOutQuad",
+ duration: 500,
});
}
return {
shiftAnimate,
- stackAnimate
+ stackAnimate,
};
}
let previousMessageHeight = 0;
const messagePadding = 15;
- function calculateX(message: HTMLElement): void {
+ function calculateX(message: HTMLElement| SVGGElement): void {
const computedQuery = window.getComputedStyle(message);
const matrix = new WebKitCSSMatrix(computedQuery.webkitTransform);
xOffset.value = matrix.m41;
import useMessageViewAnims from "./anime";
import useOffsetCalculator from './offsetCalculator';
-export default function useMessageView(): {
- beforeEnter: VueTransitionCallback;
- enter: VueTransitionCallback;
- afterEnter: VueTransitionCallback;
-} {
- // uses offsetCalculator logic and renderer animations
+const wH = 500; // window Height
+const vP = 10; // view padding
+const mP = 15; // message padding
+let mH: number; // message Height
+let vH: number; // view Height
+let vB: number; // view Bottom Bound
+let message: HTMLElement | null;
+let messageOffset = { x: 0, y: 0 };
+let shift = false;
+let beforeEnterVH: number;
+let messageView: SVGGElement;
+
+export default function useMessageView() {
const { calculateMessageOffsets } = useOffsetCalculator();
const { shiftAnimate, stackAnimate } = useMessageViewAnims();
- const messagePadding = 15;
- let messageList: NodeList;
- let message: HTMLElement | null;
- let messageOffset = { x: 0, y: 0 };
- let shift = false;
- let shiftOffset = 0;
-
- // animates message item to 'enter' renderView
const animateMessage = (el: SVGGElement): void => {
- const transform = {
- initialTranslate: `translate(${messageOffset.x} ${messageOffset.y})`,
- finalTranslate: `translate(${messageOffset.x} ${messageOffset.y})`
+ const elTransform = `translate(${messageOffset.x} ${messageOffset.y})`;
+ const viewTransform = `translate(0 ${-vB})`;
+
+ if (shift) {
+ shiftAnimate(el, elTransform, messageView, viewTransform);
+ } else {
+ stackAnimate(el, elTransform)
}
- shift ? shiftAnimate(el, transform, shiftOffset, messageList) : stackAnimate(el, transform);
+
}
const beforeEnter: VueTransitionCallback = () => {
- const queryResult = document.querySelectorAll(".messageList");
- console.log(queryResult)
- if (queryResult.length) messageList = queryResult;
+ // query DOM for messageView element
+ const messageViewQuery = document.querySelectorAll("#messageView");
+ messageView = messageViewQuery[0] as SVGGElement;
+ if (messageViewQuery){
+ beforeEnterVH = messageView.getBBox().height;
+ }
}
const enter: VueTransitionCallback = (el) => {
- // query DOM for latest message as soon as it enters
+ // query DOM for latest message
if (el) {
message = document.getElementById(el.id);
}
}
- const afterEnter: VueTransitionCallback = (el) => {
- // get message positioning & shift state before animating
- if (message) {
- messageOffset = calculateMessageOffsets(message);
- shift = messageOffset.y > 400 ? true : false;
- }
+ const afterEnter: VueTransitionCallback = async (el) => {
+
+ if (message) messageOffset = calculateMessageOffsets(message);
+
if (el) {
- if (shift) {
- shiftOffset -= el.getBBox().height + messagePadding;
- // if (messageOffset.y < 445) {
- // shiftOffset -= 15;
- // } else {
- // shiftOffset -= el.getBBox().height + messagePadding;
- // }
- }
+ // calculate message & view heights, as well as view bottom bound
+ mH = el.getBoundingClientRect().height;
+ vH = mH + beforeEnterVH + mP;
+ vB = Math.abs(vH - wH) + vP;
+
+ shift = vH > wH ? true : false;
animateMessage(el);
}
}
return {
beforeEnter,
enter,
- afterEnter
+ afterEnter,
};
}
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
- @click="emittMessage"
>
<MessageView />
<TextAudioInput />
const counter = ref(0);
const emittMessage = () => {
- console.log('testing')
emitter.emit('animateSend', Messages[counter.value])
counter.value++;
}