diff --git a/plugins/plugins/core/components/ChatPage.js b/plugins/plugins/core/components/ChatPage.js
index 0f1be491..dee271f1 100644
--- a/plugins/plugins/core/components/ChatPage.js
+++ b/plugins/plugins/core/components/ChatPage.js
@@ -55,8 +55,8 @@ const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
export const queue = new RequestQueue();
-export const chatLimit = 10
-export const totalMsgCount = 20
+export const chatLimit = 40
+export const totalMsgCount = 120
class ChatPage extends LitElement {
static get properties() {
return {
@@ -1367,6 +1367,8 @@ class ChatPage extends LitElement {
this.addToUpdateMessageHashmap = this.addToUpdateMessageHashmap.bind(this)
this.getAfterMessages = this.getAfterMessages.bind(this)
this.oldMessages = []
+ this.lastReadMessageTimestamp = 0
+ this.initUpdate = this.initUpdate.bind(this)
}
setOpenGifModal(value) {
@@ -2006,42 +2008,42 @@ class ChatPage extends LitElement {
document.addEventListener('keydown', this.initialChat)
document.addEventListener('paste', this.pasteImage)
- if (this.chatId) {
- window.parent.reduxStore.dispatch(window.parent.reduxAction.addChatLastSeen({
- key: this.chatId,
- timestamp: Date.now()
- }))
- }
+ // if (this.chatId) {
+ // window.parent.reduxStore.dispatch(window.parent.reduxAction.addChatLastSeen({
+ // key: this.chatId,
+ // timestamp: Date.now()
+ // }))
+ // }
- let callback = (entries, observer) => {
- entries.forEach(entry => {
- if (entry.isIntersecting) {
+ // let callback = (entries, observer) => {
+ // entries.forEach(entry => {
+ // if (entry.isIntersecting) {
- this.isPageVisible = true
- if (this.chatId) {
- window.parent.reduxStore.dispatch(window.parent.reduxAction.addChatLastSeen({
- key: this.chatId,
- timestamp: Date.now()
- }))
+ // this.isPageVisible = true
+ // if (this.chatId) {
+ // window.parent.reduxStore.dispatch(window.parent.reduxAction.addChatLastSeen({
+ // key: this.chatId,
+ // timestamp: Date.now()
+ // }))
- }
- } else {
- this.isPageVisible = false
- }
- })
- }
+ // }
+ // } else {
+ // this.isPageVisible = false
+ // }
+ // })
+ // }
- let options = {
- root: null,
- rootMargin: '0px',
- threshold: 0.5
- }
+ // let options = {
+ // root: null,
+ // rootMargin: '0px',
+ // threshold: 0.5
+ // }
- // Create the observer with the callback function and options
- this.observer = new IntersectionObserver(callback, options)
- const mainContainer = this.shadowRoot.querySelector('.main-container')
+ // // Create the observer with the callback function and options
+ // this.observer = new IntersectionObserver(callback, options)
+ // const mainContainer = this.shadowRoot.querySelector('.main-container')
- this.observer.observe(mainContainer)
+ // this.observer.observe(mainContainer)
}
disconnectedCallback() {
@@ -2416,6 +2418,17 @@ class ChatPage extends LitElement {
// this.selectedAddress = selectedAddress
// })
+ // })
+ this.lastReadMessageTimestamp = await chatLastSeen.getItem(this.chatId) || 0
+ // parentEpml.subscribe('chat_last_seen', async chatList => {
+ // const parsedChatList = JSON.parse(chatList)
+ // console.log({parsedChatList}, this.chatId)
+ // const findChatSeen = parsedChatList.find(chat=> chat.key === this.chatId)
+ // console.log({findChatSeen})
+ // if(findChatSeen && this.lastReadMessageTimestamp !== findChatSeen.timestamp){
+ // this.lastReadMessageTimestamp = findChatSeen.timestamp
+
+ // }
// })
parentEpml.imReady()
@@ -2994,9 +3007,28 @@ class ChatPage extends LitElement {
this.requestUpdate()
}
+ findContent(identifier, data) {
+ const [type, id] = identifier.split('/');
+
+ if (type === 'group') {
+ for (let group of data.groups) {
+ if (group.groupId === parseInt(id, 10)) {
+ return group;
+ }
+ }
+ } else if (type === 'direct') {
+ for (let direct of data.direct) {
+ if (direct.address === id) {
+ return direct;
+ }
+ }
+ }
+ return null;
+ }
+
- async processMessages(messages, isInitial) {
+ async processMessages(messages, isInitial, isUnread) {
const isReceipient = this.chatId.includes('direct')
let decodedMessages = []
if(!this.webWorkerDecodeMessages){
@@ -3058,10 +3090,27 @@ class ChatPage extends LitElement {
// TODO: Determine number of initial messages by screen height...
// this.messagesRendered = this._messages
- this.messagesRendered = {
- messages: this._messages,
- type: 'initial'
+ const lastReadMessageTimestamp = this.lastReadMessageTimestamp
+
+
+ if(isUnread){
+ this.messagesRendered = {
+ messages: this._messages,
+ type: 'initialLastSeen',
+ lastReadMessageTimestamp
+ }
+
+ window.parent.reduxStore.dispatch(window.parent.reduxAction.addChatLastSeen({
+ key: this.chatId,
+ timestamp: Date.now()
+ }))
+ } else {
+ this.messagesRendered = {
+ messages: this._messages,
+ type: 'initial'
+ }
}
+
this.isLoadingMessages = false
setTimeout(() => this.downElementObserver(), 500)
@@ -3272,25 +3321,47 @@ class ChatPage extends LitElement {
directSocketTimeout = setTimeout(pingDirectSocket, 45000)
return
}
+
if (initial === 0) {
+ this.lastReadMessageTimestamp = await chatLastSeen.getItem(this.chatId) || 0
if (noInitial) return
- const cachedData = null
let getInitialMessages = []
- if (cachedData && cachedData.length !== 0) {
- const lastMessage = cachedData[cachedData.length - 1]
- const newMessages = await parentEpml.request('apiCall', {
+ let isUnread = false
+
+ const chatId = this.chatId
+ console.log('this.chatHeads', this.chatHeads)
+ const findContent = this.chatHeads.find((item)=> item.url === chatId)
+ const chatInfoTimestamp = findContent.timestamp || 0
+ const lastReadMessageTimestamp = this.lastReadMessageTimestamp
+
+ console.log({lastReadMessageTimestamp, chatInfoTimestamp})
+
+ if(lastReadMessageTimestamp && chatInfoTimestamp){
+ if(lastReadMessageTimestamp < chatInfoTimestamp){
+ isUnread = true
+ }
+ }
+ console.log({isUnread})
+ if(isUnread){
+ const getInitialMessagesBefore = await parentEpml.request('apiCall', {
type: 'api',
- url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${cid}&limit=${chatLimit}&reverse=true&after=${lastMessage.timestamp}&haschatreference=false&encoding=BASE64`
+ url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${cid}&limit=${20}&reverse=true&before=${lastReadMessageTimestamp}&haschatreference=false&encoding=BASE64`
})
- getInitialMessages = [...newMessages]
+ const getInitialMessagesAfter = await parentEpml.request('apiCall', {
+ type: 'api',
+ url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${cid}&limit=${20}&reverse=false&after=${lastReadMessageTimestamp - 1000}&haschatreference=false&encoding=BASE64`
+ })
+ getInitialMessages = [...getInitialMessagesBefore, ...getInitialMessagesAfter]
} else {
getInitialMessages = await parentEpml.request('apiCall', {
type: 'api',
url: `/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${cid}&limit=${chatLimit}&reverse=true&haschatreference=false&encoding=BASE64`
})
}
+
+
- this.processMessages(getInitialMessages, true)
+ this.processMessages(getInitialMessages, true, isUnread)
initial = initial + 1
@@ -3371,27 +3442,48 @@ class ChatPage extends LitElement {
return
}
if (initial === 0) {
+ this.lastReadMessageTimestamp = await chatLastSeen.getItem(this.chatId) || 0
if (noInitial) return
- const cachedData = null
let getInitialMessages = []
- if (cachedData && cachedData.length !== 0) {
+ const lastReadMessageTimestamp = this.lastReadMessageTimestamp
- const lastMessage = cachedData[cachedData.length - 1]
+ let isUnread = false
+
+ const chatId = this.chatId
+ console.log('this.chatHeads', this.chatHeads)
+ const findContent = this.chatHeads.find((item)=> item.url === chatId)
+ const chatInfoTimestamp = findContent.timestamp || 0
+ console.log({lastReadMessageTimestamp, chatInfoTimestamp})
- const newMessages = await parentEpml.request('apiCall', {
- type: 'api',
- url: `/chat/messages?txGroupId=${groupId}&limit=${chatLimit}&reverse=true&after=${lastMessage.timestamp}&haschatreference=false&encoding=BASE64`
- })
- getInitialMessages = [...newMessages]
- }else {
- getInitialMessages = await parentEpml.request('apiCall', {
- type: 'api',
- url: `/chat/messages?txGroupId=${groupId}&limit=${chatLimit}&reverse=true&haschatreference=false&encoding=BASE64`
- })
+ if(lastReadMessageTimestamp && chatInfoTimestamp){
+ if(lastReadMessageTimestamp < chatInfoTimestamp){
+ isUnread = true
+ }
+ }
+ console.log({isUnread}, '2')
+ if(isUnread){
+
+
+ const getInitialMessagesBefore = await parentEpml.request('apiCall', {
+ type: 'api',
+ url: `/chat/messages?txGroupId=${groupId}&limit=${20}&reverse=true&before=${lastReadMessageTimestamp}&haschatreference=false&encoding=BASE64`
+ })
+ const getInitialMessagesAfter = await parentEpml.request('apiCall', {
+ type: 'api',
+ url: `/chat/messages?txGroupId=${groupId}&limit=${20}&reverse=false&after=${lastReadMessageTimestamp - 1000}&haschatreference=false&encoding=BASE64`
+ })
+ getInitialMessages = [...getInitialMessagesBefore, ...getInitialMessagesAfter]
+ } else {
+ getInitialMessages = await parentEpml.request('apiCall', {
+ type: 'api',
+ url: `/chat/messages?txGroupId=${groupId}&limit=${chatLimit}&reverse=true&haschatreference=false&encoding=BASE64`
+ })
+ }
+
+
- }
- this.processMessages(getInitialMessages, true)
+ this.processMessages(getInitialMessages, true, isUnread)
initial = initial + 1
} else {
diff --git a/plugins/plugins/core/components/ChatScroller-css.js b/plugins/plugins/core/components/ChatScroller-css.js
index 028b0a79..d2ac074a 100644
--- a/plugins/plugins/core/components/ChatScroller-css.js
+++ b/plugins/plugins/core/components/ChatScroller-css.js
@@ -753,6 +753,17 @@ export const chatStyles = css`
visibility: visible;
}
+ .unread-divider {
+ width: 100%;
+ background: #9B111E;
+ padding: 5px;
+ color: #FAEBD7;
+ display: flex;
+ justify-content: center;
+ border-radius: 2px;
+ margin-top: 5px;
+ }
+
.blink-bg{
border-radius: 8px;
animation: blinkingBackground 3s;
diff --git a/plugins/plugins/core/components/ChatScroller.js b/plugins/plugins/core/components/ChatScroller.js
index 9b7cce0d..33b4ffc6 100644
--- a/plugins/plugins/core/components/ChatScroller.js
+++ b/plugins/plugins/core/components/ChatScroller.js
@@ -10,6 +10,7 @@ import { roundToNearestDecimal } from '../../utils/roundToNearestDecimal.js'
import { EmojiPicker } from 'emoji-picker-js'
import { generateHTML } from '@tiptap/core'
import isElectron from 'is-electron'
+import localForage from 'localforage'
import axios from 'axios'
import Highlight from '@tiptap/extension-highlight'
@@ -32,7 +33,9 @@ import '@vaadin/tooltip'
import { chatLimit, totalMsgCount } from './ChatPage.js'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
-
+const chatLastSeen = localForage.createInstance({
+ name: "chat-last-seen",
+})
let toggledMessage = {}
const uid = new ShortUniqueId()
@@ -259,7 +262,9 @@ class ChatScroller extends LitElement {
this.oldMessages = []
this._upObserverhandler = this._upObserverhandler.bind(this)
this.newListMessages = this.newListMessages.bind(this)
+ this.newListMessagesUnreadMessages = this.newListMessagesUnreadMessages.bind(this)
this._downObserverHandler = this._downObserverHandler.bind(this)
+ this.isLastMessageBeforeUnread = this.isLastMessageBeforeUnread.bind(this)
this.replaceMessagesWithUpdate = this.replaceMessagesWithUpdate.bind(this)
this.__bottomObserverForFetchingMessagesHandler = this.__bottomObserverForFetchingMessagesHandler.bind(this)
this.myAddress = window.parent.reduxStore.getState().app.selectedAddress.address
@@ -273,6 +278,7 @@ class ChatScroller extends LitElement {
this.isLoadingBefore = false
this.isLoadingAfter = false
this.disableAddingNewMessages = false
+ this.lastReadMessageTimestamp = null
}
addSeenMessage(val) {
@@ -346,6 +352,57 @@ class ChatScroller extends LitElement {
}
+ async newListMessagesUnreadMessages(newMessages, message, lastReadMessageTimestamp) {
+ const viewElement = this.shadowRoot.querySelector("#viewElement");
+
+ console.log('sup', lastReadMessageTimestamp);
+ let data = [];
+ const copy = [...newMessages];
+
+ let dividerPlaced = false; // To ensure the divider is added only once
+
+ // Start from the end of the list (newest messages)
+ for (let i = copy.length - 1; i >= 0; i--) {
+ let newMessage = copy[i];
+
+ // Initialize a property for the divider
+ newMessage.isDivider = false;
+
+ // Check if this is the message before which the divider should be placed
+ if (!dividerPlaced && newMessage.timestamp <= lastReadMessageTimestamp) {
+ console.log('true true')
+ newMessage.isDivider = true;
+ dividerPlaced = true; // Ensure the divider is only added once
+ break; // Exit once the divider is placed
+ }
+ }
+
+ copy.forEach((newMessage, groupIndex) => {
+ const lastGroupedMessage = data[data.length - 1];
+
+ if (this.shouldGroupWithLastMessage(newMessage, lastGroupedMessage)) {
+ lastGroupedMessage.messages.push(newMessage);
+ } else {
+ data.push({
+ messages: [newMessage],
+ ...newMessage
+ });
+ }
+ });
+
+ console.log({ data });
+ this.messagesToRender = data;
+ this.clearLoaders();
+ this.requestUpdate();
+ await this.updateComplete;
+ const findElement = this.shadowRoot.getElementById('unread-divider-id')
+ if (findElement) {
+ findElement.scrollIntoView({ behavior: 'auto', block: 'center' })
+ }
+ }
+
+
+
async addNewMessages(newMessages, type) {
@@ -402,7 +459,7 @@ class ChatScroller extends LitElement {
if (type === 'initial') {
- this.viewElement.scrollTop = this.viewElement.scrollHeight
+ viewElement.scrollTop = viewElement.scrollHeight
@@ -547,13 +604,17 @@ class ChatScroller extends LitElement {
async updated(changedProperties) {
if (changedProperties && changedProperties.has('messages')) {
-
+ console.log({changedProperties}, this.messages)
if (this.messages.type === 'initial') {
this.addNewMessages(this.messages.messages, 'initial')
- } else if (this.messages.type === 'new') this.addNewMessages(this.messages.messages)
+ } else if (this.messages.type === 'initialLastSeen') {
+ this.newListMessagesUnreadMessages(this.messages.messages, 'initialLastSeen', this.messages.lastReadMessageTimestamp)
+
+ }
+ else if (this.messages.type === 'new') this.addNewMessages(this.messages.messages)
else if(this.messages.type === 'newComingInAuto') this.addNewMessages(this.messages.messages, 'newComingInAuto')
else if (this.messages.type === 'old') this.prependOldMessages(this.messages.messages)
else if (this.messages.type === 'inBetween') this.newListMessages(this.messages.messages, this.messages.signature)
@@ -567,6 +628,15 @@ class ChatScroller extends LitElement {
}
+ isLastMessageBeforeUnread(message, formattedMessages) {
+ // if the message is the last one in the older messages list and its timestamp is before the user's last seen timestamp
+ if (message.timestamp < this.lastReadMessageTimestamp && formattedMessages.indexOf(message) === (formattedMessages.length - 21)) {
+ return true;
+ }
+ return false;
+ }
+
+
render() {
// let formattedMessages = this.messages.reduce((messageArray, message) => {
// const currentMessage = this.updateMessageHash[message.signature] || message;
@@ -617,10 +687,12 @@ class ChatScroller extends LitElement {
formattedMessages,
(formattedMessage) => formattedMessage.id, // Use .id as the unique key for formattedMessage.
(formattedMessage) => html`
+
${repeat(
formattedMessage.messages,
(message) => message.signature,
(message, indexMessage) => html`
+