125 lines
No EOL
3.3 KiB
TypeScript
125 lines
No EOL
3.3 KiB
TypeScript
import { ref } from 'vue';
|
|
import useScroll from "@/modules/scroll";
|
|
import { RenderMessage, Annotation } from "@/types";
|
|
|
|
const messages = ref(new Map());
|
|
|
|
const addMessage = (message: RenderMessage) => {
|
|
messages.value.set(message.uid, message)
|
|
}
|
|
|
|
const updateMessage = (annotation: Annotation) => {
|
|
const message = messages.value.get(annotation.uid)
|
|
message.context = annotation.context
|
|
message.content.text = annotation.text
|
|
}
|
|
|
|
const loadSavedMessages = () => {
|
|
const rawData = window.localStorage.getItem("crimata_messages");
|
|
if (rawData) {
|
|
const messageData = JSON.parse(rawData)
|
|
messages.value = new Map(Object.entries(messageData));
|
|
}
|
|
}
|
|
|
|
const saveMessages = () => {
|
|
const messageData = Object.fromEntries(messages.value);
|
|
window.localStorage.setItem("crimata_messages", JSON.stringify(messageData));
|
|
}
|
|
|
|
const isSimmilar = (messageA: RenderMessage, messageB: RenderMessage) => {
|
|
if ((Math.abs(messageA.time - messageB.time) < 20000) && (messageA.modifier == messageB.modifier) && (messageA.context == messageB.context)) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
const updateGrouping = () => {
|
|
console.log("updating grouping")
|
|
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() {
|
|
|
|
// Scroll controller.
|
|
const { setScroll, updateScrollRef, adjustScroll } = useScroll("messenger");
|
|
|
|
// Main function for updating the message view.
|
|
const updateMessageView = (message: RenderMessage | Annotation) => {
|
|
|
|
// Step 1: See if user is scrolled down.
|
|
updateScrollRef()
|
|
|
|
// Step 2: Add the new content to the view.
|
|
if ("content" in message) {
|
|
addMessage(message)
|
|
} else {
|
|
updateMessage(message)
|
|
}
|
|
|
|
// Step 3: Pop off oldest message (if > 200).
|
|
if (messages.value.size >= 200) {
|
|
const oldest = Array.from(messages.value.keys()).shift();
|
|
messages.value.delete(oldest);
|
|
}
|
|
|
|
// Step 4: Update grouping.
|
|
updateGrouping()
|
|
|
|
// Setp 5: Scroll the view (if scrolled down).
|
|
setTimeout(adjustScroll, 20);
|
|
|
|
// Step 6: Save the view data.
|
|
saveMessages()
|
|
|
|
}
|
|
|
|
// Seed message view with message history.
|
|
const prepMessageView = (newMessages: RenderMessage[]) => {
|
|
console.log("MSGR:Prepping messenger view.")
|
|
|
|
// Load and render saved messages and immediately scroll to bottom.
|
|
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 => {
|
|
message.newMessage = true;
|
|
addMessage(message)
|
|
})
|
|
|
|
setTimeout(setScroll.bind(true), 1000);
|
|
|
|
}
|
|
}
|
|
|
|
return {
|
|
messages,
|
|
prepMessageView,
|
|
updateMessageView
|
|
}
|
|
} |