frontend ui enhacements
This commit is contained in:
parent
8ff21026a5
commit
af47f884d1
13 changed files with 126 additions and 214 deletions
14
src/App.vue
14
src/App.vue
|
|
@ -25,11 +25,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
|
font-family: "SF Pro Text";
|
||||||
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
|
||||||
color: #2c3e50;
|
|
||||||
|
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
|
||||||
|
|
@ -43,15 +43,15 @@
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
|
|
||||||
|
opacity: 0.75;
|
||||||
|
|
||||||
|
background-color: #EBEBEB;
|
||||||
|
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
|
|
||||||
background-color: red;
|
|
||||||
|
|
||||||
opacity: 0.0;
|
|
||||||
|
|
||||||
border: none;
|
border: none;
|
||||||
outline:none;
|
outline: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,21 +23,21 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
|
|
||||||
// mock messages
|
|
||||||
import Messages from "./mockMessages";
|
|
||||||
|
|
||||||
|
|
||||||
import TextBubble from "@/components/textBubble/index.vue";
|
import TextBubble from "@/components/textBubble/index.vue";
|
||||||
|
|
||||||
import { Message } from "@/types/message/index";
|
import { Message } from "@/types/message/index";
|
||||||
import useTransitions from "./viewDetails/transitions";
|
|
||||||
import useScrollView from "@/modules/scrollView";
|
|
||||||
import useMitt from "@/modules/mitt";
|
|
||||||
import { useIpc } from "@/modules/ipc";
|
import { useIpc } from "@/modules/ipc";
|
||||||
import { Queue } from '@/modules/queue';
|
import { Queue } from '@/modules/queue';
|
||||||
|
|
||||||
|
import useTransitions from "./viewDetails/transitions";
|
||||||
|
import useScrollView from "@/modules/scrollView";
|
||||||
|
|
||||||
|
import useMitt from "@/modules/mitt";
|
||||||
|
|
||||||
import { defineComponent, reactive, onMounted, onUnmounted, watch, ref } from "vue";
|
import { defineComponent, reactive, onMounted, onUnmounted, watch, ref } from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
|
||||||
name: "MessageView",
|
name: "MessageView",
|
||||||
components: { TextBubble },
|
components: { TextBubble },
|
||||||
|
|
||||||
|
|
@ -47,24 +47,13 @@ export default defineComponent({
|
||||||
const renderQ = new Queue();
|
const renderQ = new Queue();
|
||||||
|
|
||||||
const { invoke } = useIpc("message");
|
const { invoke } = useIpc("message");
|
||||||
|
|
||||||
|
// Each method will be called on their respective lifecycle event.
|
||||||
const { beforeEnter, enter, afterEnter, rendering } = useTransitions();
|
const { beforeEnter, enter, afterEnter, rendering } = useTransitions();
|
||||||
const { scrollView } = useScrollView({
|
const { scrollView } = useScrollView({
|
||||||
targetId: "messageView",
|
targetId: "messageView",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const messages = Messages;
|
|
||||||
const count = ref(0);
|
|
||||||
|
|
||||||
function emittMessage() {
|
|
||||||
console.log("emitting mock message")
|
|
||||||
if (count.value < messages.length) {
|
|
||||||
emitter.emit("render-message", messages[count.value]);
|
|
||||||
count.value++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const render = (m: Message) => {
|
const render = (m: Message) => {
|
||||||
if (rendering.value) {
|
if (rendering.value) {
|
||||||
renderQ.enqueue(m);
|
renderQ.enqueue(m);
|
||||||
|
|
@ -81,6 +70,8 @@ export default defineComponent({
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
||||||
|
// Call render function on event "render-message."
|
||||||
window.ipcRenderer.on("render-message", (event, payload) => {
|
window.ipcRenderer.on("render-message", (event, payload) => {
|
||||||
const m = payload.message;
|
const m = payload.message;
|
||||||
if (m.content) render(m);
|
if (m.content) render(m);
|
||||||
|
|
@ -107,8 +98,17 @@ export default defineComponent({
|
||||||
enter,
|
enter,
|
||||||
afterEnter,
|
afterEnter,
|
||||||
scrollView,
|
scrollView,
|
||||||
emittMessage,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
#messageView {
|
||||||
|
width: 1000px;
|
||||||
|
height: 100vh;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
||||||
import { Message } from "@/types/message/index";
|
|
||||||
|
|
||||||
const Messages: Message[] = [
|
|
||||||
{
|
|
||||||
content: "Welcome",
|
|
||||||
context: "ai",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "2",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content:
|
|
||||||
"add friend",
|
|
||||||
context: "launch",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "sf",
|
|
||||||
id: "1",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Did you mean to addcontact?",
|
|
||||||
context: "addcontact",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "5",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "yes",
|
|
||||||
context: "fulfill",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "sf",
|
|
||||||
id: "6",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
content: "Hey Anna, did you get the paper done?",
|
|
||||||
context: "Mesage from Tommy McConville",
|
|
||||||
subContext: "New Conversation",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "3",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Hey do you know Enrique Hernandez?",
|
|
||||||
context: "Message from Crimata",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "7",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
content: "Yes posting it online soon.",
|
|
||||||
context: "You to Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "sf",
|
|
||||||
id: "4",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Hey do you know Enrique Hernandez?",
|
|
||||||
context: "Message from Crimata",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "8",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Hey Anna, did you get the paper done?",
|
|
||||||
context: "Message from Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "9",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Hey Anna, did you get the paper done?",
|
|
||||||
context: "Message from Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "10",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Yes posting it online soon.",
|
|
||||||
context: "Message from Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "sf",
|
|
||||||
id: "11",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content:
|
|
||||||
"I can be there at 5 pm tomorrow to greet you at a Chick file with my almond and chive salad.",
|
|
||||||
context: "You to Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "sf",
|
|
||||||
id: "12",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Hey Anna, did you get the paper done?",
|
|
||||||
context: "Message from Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "13",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Hey Anna, did you get the paper done?",
|
|
||||||
context: "Message from Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "14",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Yes posting it online soon.",
|
|
||||||
context: "You to Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "sf",
|
|
||||||
id: "15",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Sweet, thanks!",
|
|
||||||
context: "Message from Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "16",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Hey do you know Enrique Hernandez?",
|
|
||||||
context: "Message from Crimata AI",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "17",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Yes posting it online soon.",
|
|
||||||
context: "You to Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "sf",
|
|
||||||
id: "18",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
content: "Sweet, thanks!",
|
|
||||||
context: "Message from Tommy McConville",
|
|
||||||
subContext: "",
|
|
||||||
modifier: "ai",
|
|
||||||
id: "19",
|
|
||||||
time: ""
|
|
||||||
},
|
|
||||||
];
|
|
||||||
export default Messages;
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { ref } from "vue";
|
||||||
export default function useOffsetCalculator() {
|
export default function useOffsetCalculator() {
|
||||||
const xOffset = ref(0);
|
const xOffset = ref(0);
|
||||||
const yOffset = ref(0);
|
const yOffset = ref(0);
|
||||||
const firstChildMarginTop = 0;
|
const firstChildMarginTop = 45;
|
||||||
let previousMessageHeight = 0;
|
let previousMessageHeight = 0;
|
||||||
const messagePadding = 15;
|
const messagePadding = 15;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,12 @@ export default function useTransitions() {
|
||||||
|
|
||||||
const animateMessage = async (el: SVGGElement) => {
|
const animateMessage = async (el: SVGGElement) => {
|
||||||
|
|
||||||
|
// Where the message gets translated to.
|
||||||
const elTransform = `translate(${messageOffset.x} ${messageOffset.y})`;
|
const elTransform = `translate(${messageOffset.x} ${messageOffset.y})`;
|
||||||
|
|
||||||
const viewTransform = `translate(0 ${-vB})`;
|
const viewTransform = `translate(0 ${-vB})`;
|
||||||
|
|
||||||
|
// Shift of view height > window height.
|
||||||
if (shift) {
|
if (shift) {
|
||||||
await shiftAnimate(el, elTransform, messageView, viewTransform);
|
await shiftAnimate(el, elTransform, messageView, viewTransform);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -44,6 +47,7 @@ export default function useTransitions() {
|
||||||
rendering.value = false;
|
rendering.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get height of messageView.
|
||||||
const beforeEnter: VueTransitionCallback = () => {
|
const beforeEnter: VueTransitionCallback = () => {
|
||||||
rendering.value = true;
|
rendering.value = true;
|
||||||
// query DOM for messageView element
|
// query DOM for messageView element
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<audio-stream v-if="visualizeStream" :bubbleWidth="audioBubbleWidth" :paths="paths" />
|
|
||||||
<text-input v-else :input="input" :textXoffset="textInputXoffset" />
|
<!-- render audio or text input-->
|
||||||
|
<AudioStream
|
||||||
|
v-if="visualizeStream"
|
||||||
|
:bubbleWidth="audioBubbleWidth"
|
||||||
|
:paths="paths"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
v-else
|
||||||
|
:input="input"
|
||||||
|
:textXoffset="textInputXoffset"
|
||||||
|
:textYoffset="textInputYoffset"
|
||||||
|
/>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// input child components
|
|
||||||
|
// import child components
|
||||||
import TextInput from "./textDetails/text.vue";
|
import TextInput from "./textDetails/text.vue";
|
||||||
import AudioStream from "./audioDetails/audio.vue";
|
import AudioStream from "./audioDetails/audio.vue";
|
||||||
|
|
||||||
import useInputController from "./inputController";
|
import useInputController from "./inputController";
|
||||||
|
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
|
||||||
name: "TextAudioInput",
|
name: "TextAudioInput",
|
||||||
components: { TextInput, AudioStream },
|
components: { TextInput, AudioStream },
|
||||||
setup() {
|
setup() {
|
||||||
|
|
@ -24,14 +40,20 @@ export default defineComponent({
|
||||||
const {
|
const {
|
||||||
input,
|
input,
|
||||||
visualizeStream,
|
visualizeStream,
|
||||||
|
|
||||||
textInputXoffset,
|
textInputXoffset,
|
||||||
|
textInputYoffset,
|
||||||
|
|
||||||
audioBubbleWidth,
|
audioBubbleWidth,
|
||||||
paths,
|
paths,
|
||||||
} = useInputController();
|
} = useInputController();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
input,
|
input,
|
||||||
|
|
||||||
textInputXoffset,
|
textInputXoffset,
|
||||||
|
textInputYoffset,
|
||||||
|
|
||||||
visualizeStream,
|
visualizeStream,
|
||||||
audioBubbleWidth,
|
audioBubbleWidth,
|
||||||
paths,
|
paths,
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,18 @@ export default function useInputController() {
|
||||||
emitter.emit("user-message", message);
|
emitter.emit("user-message", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { visualizeStreamAsPaths, expandBubble } = useAudioVisualizer(visualizeStream);
|
const {
|
||||||
|
visualizeStreamAsPaths,
|
||||||
|
expandBubble
|
||||||
|
} = useAudioVisualizer(visualizeStream);
|
||||||
|
|
||||||
const { keyDownHandler, input } = useKeyDownHandler(enterCallback);
|
const { keyDownHandler, input } = useKeyDownHandler(enterCallback);
|
||||||
const { textInputXoffset, renderTextInput } = useTextVisualizer(input);
|
|
||||||
|
const {
|
||||||
|
textInputXoffset,
|
||||||
|
textInputYoffset,
|
||||||
|
renderTextInput
|
||||||
|
} = useTextVisualizer(input);
|
||||||
|
|
||||||
// stops stream recording on space key up
|
// stops stream recording on space key up
|
||||||
function keyupHandler(e: any) {
|
function keyupHandler(e: any) {
|
||||||
|
|
@ -83,6 +92,7 @@ export default function useInputController() {
|
||||||
input,
|
input,
|
||||||
visualizeStream,
|
visualizeStream,
|
||||||
textInputXoffset,
|
textInputXoffset,
|
||||||
|
textInputYoffset,
|
||||||
audioBubbleWidth,
|
audioBubbleWidth,
|
||||||
paths
|
paths
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,52 @@
|
||||||
<template>
|
<template>
|
||||||
<foreignObject class="inputContainer" :x="textXoffset" y="450" width="55%" height="50%">
|
|
||||||
|
<foreignObject
|
||||||
|
class="inputContainer"
|
||||||
|
:x="textXoffset"
|
||||||
|
:y="textYoffset"
|
||||||
|
width="55%"
|
||||||
|
height="50%"
|
||||||
|
>
|
||||||
<div xmlns="http://www.w3.org/1999/xhtml">
|
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<div class="inputBubble" contenteditable v-show="input.length > 0" font-family="SF Pro">
|
<div class="inputBubble" v-show="input.length > 0">
|
||||||
<p>{{ input }}</p>
|
<p>{{ input }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</foreignObject>
|
</foreignObject>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
|
||||||
name: "TextInput",
|
name: "TextInput",
|
||||||
props: {
|
props: {
|
||||||
input: String,
|
input: String,
|
||||||
textXoffset: String,
|
textXoffset: String,
|
||||||
|
textYoffset: String,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
div[contenteditable] {
|
.inputBubble {
|
||||||
width: auto;
|
|
||||||
max-width: 180px;
|
max-width: 180px;
|
||||||
height: auto;
|
min-height: 32px;
|
||||||
min-height: 36px;
|
|
||||||
display: table;
|
display: table;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
border: 0;
|
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
color: #000;
|
background-color: #B9B9B9;
|
||||||
background-color: #b9b9b9;
|
|
||||||
font-size: 14;
|
font-size: 14px;
|
||||||
text-align: left;
|
|
||||||
p {
|
p {
|
||||||
max-width: 150px;
|
max-width: 150px;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,13 @@ export default function useTextVisualizer(input: Ref<string>) {
|
||||||
return `calc(50% - ${inputWidth.value / 2})`;
|
return `calc(50% - ${inputWidth.value / 2})`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const textInputYoffset = computed(() => {
|
||||||
|
return `calc(97% - ${inputHeight.value})`;
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
textInputXoffset,
|
textInputXoffset,
|
||||||
|
textInputYoffset,
|
||||||
renderTextInput
|
renderTextInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { computed, onMounted, ref } from "vue";
|
||||||
export default function useComputedBubble(m: string, id: string) {
|
export default function useComputedBubble(m: string, id: string) {
|
||||||
const x = ref(0)
|
const x = ref(0)
|
||||||
const paddingLeft = 30;
|
const paddingLeft = 30;
|
||||||
|
|
||||||
const winW = 350;
|
const winW = 350;
|
||||||
const messageWidth = ref(0);
|
const messageWidth = ref(0);
|
||||||
const messageMarginTop = 75;
|
const messageMarginTop = 75;
|
||||||
|
|
@ -39,7 +40,7 @@ export default function useComputedBubble(m: string, id: string) {
|
||||||
const calculateXoffset = async () => {
|
const calculateXoffset = async () => {
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case "sf":
|
case "sf":
|
||||||
x.value = winW - messageWidth.value - selfMessageMarginRight;
|
x.value = 800 - messageWidth.value - selfMessageMarginRight;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
x.value = paddingLeft;
|
x.value = paddingLeft;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<g :id="item.id" :class="item.modifier" :transform="startingOffset">
|
<g :id="item.id" :class="item.modifier" :transform="startingOffset">
|
||||||
<rect ref="messageRect" x="30" y="10" width="196" height="63" rx="10" :fill="bubbleFill" />
|
<rect ref="messageRect" x="30" y="10" width="196" height="63" rx="10" :fill="bubbleFill" />
|
||||||
<text font-size="14" font-family="SF Pro" ref="messageText" :fill="textFill">
|
<text font-size="14" font-family="SF Pro Text" ref="messageText" :fill="textFill">
|
||||||
<tspan dy="16" x="0" v-for="(item, index) in textArr" :key="index">{{ item }}</tspan>
|
<tspan dy="16" x="0" v-for="(item, index) in textArr" :key="index">{{ item }}</tspan>
|
||||||
</text>
|
</text>
|
||||||
<g :transform="signatureTranslate">
|
<g :transform="signatureTranslate">
|
||||||
|
|
|
||||||
|
|
@ -12,30 +12,44 @@ export default function useScrollView({ targetId }: { targetId: string }) {
|
||||||
let topBound: number;
|
let topBound: number;
|
||||||
const scrollStartHeight = 445;
|
const scrollStartHeight = 445;
|
||||||
|
|
||||||
const clampedScroll = computed(() => {
|
|
||||||
if (targetHeight.value === 0) { return 0; }
|
|
||||||
topBound = -targetHeight.value + 450;
|
|
||||||
return Math.max(topBound, Math.min(scroll.value, 0)) as number;
|
|
||||||
})
|
|
||||||
|
|
||||||
const scrollView = computed(() => {
|
const scrollView = computed(() => {
|
||||||
|
|
||||||
if (clampedScroll.value === 0) {
|
if (clampedScroll.value === 0) {
|
||||||
scroll.value = 0;
|
scroll.value = 0;
|
||||||
} else if (clampedScroll.value === topBound) {
|
} else if (clampedScroll.value === topBound) {
|
||||||
scroll.value = topBound;
|
scroll.value = topBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// x, y, width, height
|
||||||
|
// width and height should be dynamic
|
||||||
return `0 ${clampedScroll.value} 350 500`;
|
return `0 ${clampedScroll.value} 350 500`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const clampedScroll = computed(() => {
|
||||||
|
if (targetHeight.value === 0) { return 0; }
|
||||||
|
topBound = -targetHeight.value + 450;
|
||||||
|
return Math.max(topBound, Math.min(scroll.value, 0)) as number;
|
||||||
|
})
|
||||||
|
|
||||||
const getHeight = () => {
|
const getHeight = () => {
|
||||||
if (scrollTarget) {
|
if (scrollTarget) {
|
||||||
return scrollTarget.getBoundingClientRect().height as number;
|
return scrollTarget.getBoundingClientRect().height as number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateView = (verticalScroll: number) => {
|
const getWidth = () => {
|
||||||
if (scrollTarget) {
|
if (scrollTarget) {
|
||||||
|
return scrollTarget.getBoundingClientRect().width as number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateView = (verticalScroll: number) => {
|
||||||
|
|
||||||
|
if (scrollTarget) {
|
||||||
|
|
||||||
const heightResult = getHeight();
|
const heightResult = getHeight();
|
||||||
|
const widthResult = getWidth();
|
||||||
|
|
||||||
if (heightResult) {
|
if (heightResult) {
|
||||||
// only scroll if renderer scrollStart
|
// only scroll if renderer scrollStart
|
||||||
if (heightResult > scrollStartHeight) {
|
if (heightResult > scrollStartHeight) {
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,17 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
|
// Home consists on MessageView and Text/Audio imput component.
|
||||||
import MessageView from "@/components/messageView/index.vue";
|
import MessageView from "@/components/messageView/index.vue";
|
||||||
import TextAudioInput from "@/components/taInput/index.vue";
|
import TextAudioInput from "@/components/taInput/index.vue";
|
||||||
|
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Messenger",
|
name: "Messenger",
|
||||||
components: { MessageView, TextAudioInput },
|
components: { MessageView, TextAudioInput },
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue