--- /dev/null
+import {computed} from "vue";
+
+// Size of "side-gutters" of message window.
+const margin = 20;
+const messagePadding = 15;
+const firstChildMargin = 45;
+
+
+function calcXPosition(messageWidth: number, windowWidth: number, modifier: string) {
+ let offset = margin;
+
+ if (modifier == "sf") {
+ offset = windowWidth - messageWidth - margin;
+ }
+
+ return offset
+}
+
+function calcMessagePosition(modifier: string, messageWidth: number,
+ windowWidth: number, anchorPosition: any) {
+
+ const X = calcXPosition(messageWidth, windowWidth, modifier);
+
+ // Depends on if first child.
+ let Y = firstChildMargin;
+ if (anchorPosition != "none") {
+ Y = anchorPosition + messagePadding;
+ }
+
+ return `translate(${X} ${Y})`;
+}
+
+export default calcMessagePosition;
\ No newline at end of file
--- /dev/null
+<template>
+
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="100"
+ height="46"
+ :transform="position"
+ >
+
+ <rect
+ :id="message.id"
+ :class="message.modifier"
+
+ width="100" height="46" rx="10" fill="#58c4fd"
+ />
+
+ </svg>
+
+</template>
+
+<script lang="ts">
+
+import { defineComponent, computed, onMounted, ref, reactive } from "vue";
+
+import calcMessagePosition from "./calcPosition";
+
+
+export default defineComponent({
+ name: "MessageBubble",
+
+ props: {
+
+ // DOM ID of the previous message.
+ // Null if message is first child.
+ anchor: {
+ type: String,
+ required: true
+ },
+
+ // Passing in the message contents.
+ message: {
+ type: Object,
+ required: true
+ },
+
+ },
+
+ setup(props) {
+
+ // e.g. "translate(20 200)"
+ const position = ref("");
+ let anchorPosition: any;
+
+ // Call to update the position variable.
+ const updatePosition = () => {
+
+ // First get anchor's position.
+ if (props.anchor == "none") {
+ anchorPosition = "none";
+ }
+
+ const m = document.getElementById(props.anchor)
+ if (m) {
+ anchorPosition = m.getBoundingClientRect().bottom
+ }
+
+ position.value = calcMessagePosition(
+ props.message.modifier,
+ 100,
+ window.innerWidth,
+ anchorPosition
+ );
+
+ console.log(
+ `Message: ${props.message.id}: \n
+ Anchor: ${props.anchor}: ${anchorPosition} \n
+ Position: ${position.value}`
+ )
+
+ }
+
+ // Assign initial position.
+ updatePosition();
+
+ onMounted(() => {
+
+ // We gotta know when the message above us changes position.
+
+ // Add listener for window resize.
+ window.addEventListener("resize", updatePosition);
+
+ })
+
+ return {
+ position
+ }
+
+ },
+
+});
+</script>
+++ /dev/null
-<template>
-
- <svg
- xmlns="http://www.w3.org/2000/svg"
- width="width"
- height="height"
- viewBox="0 0 100 46"
- >
-
- <rect
- :id="item.id"
- :class="item.modifier"
- :transform="position"
-
- width="width" height="height" rx="10" fill="#58c4fd"
- />
-
- </svg>
-
-</template>
-
-<script lang="ts">
-
-import { defineComponent, computed, onMounted, ref, reactive } from "vue";
-
-export default defineComponent({
- name: "TextBubble",
-
- props: {
-
- // Passing in the message contents.
- message: {
- type: Object,
- required: true,
- },
-
- },
-
- setup(props) {
-
- // The position of the bubble.
- const position = ref()
-
- // Calculate the position.
- computed(() => {
-
- const calculateX = () => {
- let x = 20 // side-padding
-
- if (props.message.modifier == 'sf') {
- x = window.innerWidth - 100 - 20
- }
-
- return x
- }
-
- const calculateY = () => {
- let y = 45 // top-padding
-
- if (previousMessage) {
- prev = document.getElementById(previousMessage)
- prevPosition = prev.getBoundingClientRect().height
-
- y = prevPosition + 15 // message-message padding
- }
-
- return y
- }
-
- let X = calculateX();
- let Y = calculateY();
-
- position.value = `translate(${X} ${Y})`;
-
- })
-
- return {
- position
- }
- },
-
-});
-</script>
if (parentView) {
const dimensions = parentView.getBoundingClientRect();
- let X = calculateXoffset(dimensions.width);
- let Y = calculateYoffset(dimensions.height);
+ const X = calculateXoffset(dimensions.width);
+ const Y = calculateYoffset(dimensions.height);
return `translate(${X} ${Y})`;
}
audio: 0,
text: input
};
-<<<<<<< Updated upstream
// trigger send animation
emitter.emit("animate-send");
const {
visualizeStreamAsPaths,
-=======
- emitter.emit("animate-send", message);
- }
-
- const {
- visualizeStreamAsPaths,
->>>>>>> Stashed changes
expandBubble
} = useAudioVisualizer(visualizeStream);
<TextAudioInput />
- <!-- List of text bubbles. -->
- <div id="messenger" v-for="message in messages">
- <!-- <TextBubble :message="message"/> -->
- <div>Hello</div>
+ <!-- List of message bubbles. -->
+ <div id="messenger">
+
+ <MessageBubble id="message" v-for="(message, index) in messages"
+ :message="message"
+ :anchor="getAnchor(index)"
+ />
+
</div>
</template>
<script lang="ts">
-import { defineComponent, reactive, onMounted } from "vue";
+import { defineComponent, computed, reactive, onMounted, ref } from "vue";
import TextAudioInput from "@/components/taInput/index.vue";
-// import TextBubble from "@/components/messageView/textBubble.vue";
+import MessageBubble from "@/components/messageView/message/message.vue";
import { Message } from "@/types/message/index";
export default defineComponent({
name: "Messenger",
- components: {
- // TextBubble
+ components: {
+ MessageBubble,
TextAudioInput
},
- setup() {
+ setup(props) {
// List of messages in the view.
+ // Oldest message first.
const messages: Message[] = reactive([])
// Render a message.
const render = (message: Message) => {
messages.push(message)
+ console.log(`Pushing: ${message.modifier}: ${message.content}`)
+ }
+
+ // Get the "anchor" message for a given message.
+ const getAnchor = (index: number) => {
+ let anchor = "none";
+
+ // If not the first message.
+ if (index > 0) {
+ anchor = messages[index - 1].id
+ }
+
+ return anchor
}
onMounted(() => {
})
return {
- messages
+ messages,
+ getAnchor
}
}
#messenger {
width: 100vw;
- height: 100vh;
+ min-height: 100vh;
+
+ overflow: scroll;
background-color: #EBEBEB;
}
+ #message {
+ position: absolute;
+ }
+
</style>