import { ref } from 'vue'; import invokeSavedMessages from "@/render/ipc"; import useScroll from "@/render/composables/scroll"; const messages = ref(new Map()); function getTimeStamp(): number { const currentdate = new Date(); return currentdate.getTime(); } const newViewMessage = (message: Message): ViewMessage => { return { text: message.text, context: message.context, audio: message.audio, from: message.from, uid: message.uid, time: getTimeStamp(), isChild: "none", seen: false, newMessage: false }; } const addMessage = (message: Message, newMessage=false) => { const viewMessage = newViewMessage(message); if (newMessage) viewMessage.newMessage = true; messages.value.set(viewMessage.uid, viewMessage); } const updateMessage = (message: Message) => { const viewMessage = messages.value.get(message.uid); viewMessage.context = message.context; viewMessage.text = message.text; } const loadSavedMessages = async () => { const messageData = await invokeSavedMessages(); messages.value = new Map(Object.entries(messageData)); } const saveMessages = () => { const messageData = Object.fromEntries(messages.value); // must save to json. } const pruneMessages = (limit=200) => { if (messages.value.size >= limit) { const oldest = Array.from(messages.value.keys()).shift(); messages.value.delete(oldest); } } const updateGrouping = () => { const isSimmilar = (messageA: ViewMessage, messageB: ViewMessage) => { if ((Math.abs(messageA.time - messageB.time) < 20000) && (messageA.from == messageB.from) && (messageA.context == messageB.context)) { return true } return false } 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() { const { updateScrollRef, adjustScroll } = useScroll("messenger"); /* Given new message object, update the view accordingly */ const updateMessageView = (newMessages: Message[]) => { const bottom = updateScrollRef(); // see if the user is scrolled down // take each message and apply view newMessages.forEach((message: Message) => { // add or update message depending if (messages.value.has(message.uid)) { updateMessage(message); } else addMessage(message); pruneMessages(); // pop off old messages from view updateGrouping(); // group like message together if (bottom) adjustScroll(); // only scroll if user was at bottom saveMessages(); }); } return { messages, updateMessageView, loadSavedMessages } } // // Seed message view with message history. // const prepMessageView = async (newMessages: Message[]) => { // console.log("MSGR:Prepping messenger view.") // // Load and render saved messages and immediately scroll to bottom. // await 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 => { // addMessage(message, true); // }) // setTimeout(setScroll.bind(true), 1000); // } // }