summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaksim Sukharev <antreesy.web@gmail.com>2024-03-02 00:09:51 +0100
committerMaksim Sukharev <antreesy.web@gmail.com>2024-03-02 00:09:51 +0100
commitfdf67210e99652e47cbb97bf1c0111a0ead0de97 (patch)
treee902a75d18b4e6f881b5dbb4de239b781799b7e1
parent0660f4d3c8070940363a29e381615d7cba0f6e51 (diff)
Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue3
-rw-r--r--src/components/MessagesList/MessagesList.vue117
-rw-r--r--src/constants.js2
-rw-r--r--src/store/messagesStore.js24
4 files changed, 129 insertions, 17 deletions
diff --git a/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue b/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue
index 30dc957a8..d51d87902 100644
--- a/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue
+++ b/src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue
@@ -269,7 +269,8 @@ export default {
// Add a new line after file to split content into different paragraphs
return '{file}' + '\n\n' + this.message
} else {
- return this.message
+ // TODO remove
+ return this.id + ' -- ' + this.message
}
},
diff --git a/src/components/MessagesList/MessagesList.vue b/src/components/MessagesList/MessagesList.vue
index 29a3c4998..661f59ca5 100644
--- a/src/components/MessagesList/MessagesList.vue
+++ b/src/components/MessagesList/MessagesList.vue
@@ -68,6 +68,18 @@
<Message :size="64" />
</template>
</NcEmptyContent>
+
+ <div v-if="isConversationInHistoryMode" class="scroller__wrapper">
+ <p>{{ t('spreed', 'This conversation is in history mode') }}</p>
+ <div class="scroller__wrapper-content">
+ <NcButton @click="getNewMessages">
+ {{ t('spreed', 'Load recent messages') }}
+ </NcButton>
+ <NcButton type="primary" @click="clearRouterHash">
+ {{ t('spreed', 'Load current history') }}
+ </NcButton>
+ </div>
+ </div>
</div>
</template>
@@ -82,6 +94,7 @@ import { getCapabilities } from '@nextcloud/capabilities'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import moment from '@nextcloud/moment'
+import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import MessagesGroup from './MessagesGroup/MessagesGroup.vue'
@@ -98,6 +111,7 @@ export default {
components: {
LoadingPlaceholder,
Message,
+ NcButton,
NcEmptyContent,
TransitionWrapper
},
@@ -161,6 +175,8 @@ export default {
loadingOldMessages: false,
+ loadingNewMessages: false,
+
isInitialisingMessages: false,
isFocusingMessage: false,
@@ -235,6 +251,10 @@ export default {
return this.$store.getters.hasMoreMessagesToLoad(this.token)
},
+ isConversationInHistoryMode() {
+ return this.$store.getters.isConversationInHistoryMode(this.token)
+ },
+
/**
* Returns whether the current participant is a participant of the
* current conversation or not.
@@ -712,8 +732,13 @@ export default {
this.isInitialisingMessages = false
- // get new messages
- await this.lookForNewMessages()
+ if (!this.isConversationInHistoryMode) {
+ // get new messages
+ await this.lookForNewMessages()
+ } else {
+ // stop polling
+ this.$store.dispatch('cancelLookForNewMessages', { requestId: this.chatIdentifier })
+ }
if (this.loadChatInLegacyMode || focusMessageId === null) {
// don't scroll if lookForNewMessages was polling as we don't want
@@ -800,6 +825,40 @@ export default {
},
/**
+ * Get message history (with new messages relative to context).
+ *
+ * @param {boolean} [includeLastKnown] Include or exclude the last known message in the response
+ */
+ async getNewMessages(includeLastKnown = false) {
+ // Make the request
+ this.loadingNewMessages = true
+ try {
+ await this.$store.dispatch('fetchMessages', {
+ token: this.token,
+ lastKnownMessageId: this.$store.getters.getLastKnownMessageId(this.token),
+ includeLastKnown,
+ lookIntoFuture: 1,
+ minimumVisible: CHAT.MINIMUM_VISIBLE,
+ })
+ } catch (exception) {
+ if (Axios.isCancel(exception)) {
+ console.debug('The request has been canceled', exception)
+ }
+ // if (exception?.response?.status === 304) {
+ // 304 - Not modified
+ // }
+ console.error(exception)
+ }
+ this.loadingNewMessages = false
+
+ console.log('InHistoryMode', this.isConversationInHistoryMode)
+ if (!this.isConversationInHistoryMode) {
+ // Start polling new messages, if this is the end of the chat
+ this.getNewMessagesPolling()
+ }
+ },
+
+ /**
* Creates a long polling request for a new message.
*
* @param {boolean} scrollToBottom Whether we should try to automatically scroll to the bottom
@@ -922,8 +981,9 @@ export default {
const tolerance = 10
// For chats, scrolled to bottom or / and fitted in one screen
- if (scrollOffset < clientHeight + tolerance && scrollOffset > clientHeight - tolerance && !this.hasMoreMessagesToLoad) {
- this.setChatScrolledToBottom(true)
+ if (scrollOffset < clientHeight + tolerance && scrollOffset > clientHeight - tolerance
+ && (!this.hasMoreMessagesToLoad || this.isConversationInHistoryMode)) {
+ this.setChatScrolledToBottom(!this.hasMoreMessagesToLoad)
this.displayMessagesLoader = false
this.previousScrollTopValue = scrollTop
this.debounceUpdateReadMarkerPosition()
@@ -1243,29 +1303,34 @@ export default {
&& from.token === to.token
&& from.hash !== to.hash) {
+ // the hash is cleared, need to purge messages list and load new messages
+ if (this.isConversationInHistoryMode && !to.hash) {
+ await this.$store.dispatch('purgeMessagesStore', this.token)
+ this.$nextTick(async () => {
+ // TODO just fetch last pack or start with preconditions?
+ await this.handleStartGettingMessagesPreconditions()
+ })
+ }
+
// the hash changed, need to focus/highlight another message
if (to.hash && to.hash.startsWith('#message_')) {
const focusedId = this.getMessageIdFromHash(to.hash)
if (this.messagesList.find(m => m.id === focusedId)) {
// need some delay (next tick is too short) to be able to run
- // after the browser's native "scroll to anchor" from
- // the hash
+ // after the browser's native "scroll to anchor" from the hash
window.setTimeout(() => {
// scroll to message in URL anchor
this.focusMessage(focusedId, true)
}, 2)
} else {
- // Update environment around context to fill the gaps
- this.$store.dispatch('setFirstKnownMessageId', {
- token: this.token,
- id: focusedId,
- })
- this.$store.dispatch('setLastKnownMessageId', {
- token: this.token,
- id: focusedId,
+ // the message is far from current list, need to purge messages list and load old messages
+ // TODO delete only for 'history' mode - need to know conditions (context timestamp)
+ console.log('InHistoryMode', this.isConversationInHistoryMode)
+ this.$store.dispatch('purgeMessagesStore', this.token)
+ this.$nextTick(async () => {
+ await this.handleStartGettingMessagesPreconditions()
+ this.focusMessage(focusedId, true)
})
- await this.getMessageContext(focusedId)
- this.focusMessage(focusedId, true)
}
}
}
@@ -1287,6 +1352,11 @@ export default {
messagesGroupComponent(group) {
return group.isSystemMessagesGroup ? MessagesSystemGroup : MessagesGroup
},
+
+ clearRouterHash() {
+ this.$router.push({ name: 'conversation', params: { token: this.token } })
+ .catch(err => console.debug(`Error while pushing the new conversation's route: ${err}`))
+ },
},
}
</script>
@@ -1311,6 +1381,21 @@ export default {
height: 40px;
transform: translatex(-64px);
}
+
+ &__wrapper {
+ max-width: 800px;
+ padding: 8px 140px 8px 52px;
+ margin: 0 auto;
+
+ &-content {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 8px;
+ margin-top: 4px;
+ color: var(--color-text-maxcontrast);
+ }
+ }
}
.messages-list {
diff --git a/src/constants.js b/src/constants.js
index 9a40b0c2f..5b471dbc2 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -35,6 +35,8 @@ export const SESSION = {
export const CHAT = {
FETCH_LIMIT: 100,
MINIMUM_VISIBLE: 5,
+ HISTORY_LIMIT_TIME: 10 * 60, // 24 hours in seconds
+ HISTORY_LIMIT_AMOUNT: 20, // 300 known unread messages
}
export const CALL = {
diff --git a/src/store/messagesStore.js b/src/store/messagesStore.js
index 932766db2..7da5cf6c9 100644
--- a/src/store/messagesStore.js
+++ b/src/store/messagesStore.js
@@ -157,6 +157,27 @@ const getters = {
return getters.getLastKnownMessageId(token) < conversation.lastMessage.id
},
+ /**
+ * Returns whether the conversation is in 'history' mode, which means that the current
+ * message list contain message context which is older than 24 hours
+ * or amount of unread messages is larger than 300 messages.
+ * If true, the call to "lookForNewMessages" will be blocked.
+ *
+ * @param {object} state the state object.
+ * @param {object} getters the getters object.
+ * @return {boolean} true if context is old enough, false otherwise
+ */
+ isConversationInHistoryMode: (state, getters) => (token) => {
+ const conversation = getters.conversation(token)
+ const lastKnownMessage = getters.message(token, getters.getLastKnownMessageId(token))
+ if (!conversation || !lastKnownMessage) {
+ return false
+ }
+
+ return conversation.lastMessage.timestamp - lastKnownMessage.timestamp > CHAT.HISTORY_LIMIT_TIME
+ || conversation.unreadMessages > CHAT.HISTORY_LIMIT_AMOUNT
+ },
+
isMessageListPopulated: (state) => (token) => {
return !!state.loadedMessages[token]
},
@@ -414,6 +435,9 @@ const mutations = {
if (state.messages[token]) {
Vue.delete(state.messages, token)
}
+ if (state.loadedMessages[token]) {
+ Vue.delete(state.loadedMessages, token)
+ }
},
/**