pleroma-fe/src/modules/chats.js

264 lines
8.4 KiB
JavaScript
Raw Normal View History

2020-05-07 16:10:53 +03:00
import { find, omitBy, orderBy, sumBy } from 'lodash'
2026-01-06 16:23:17 +02:00
import { reactive } from 'vue'
2020-05-07 16:10:53 +03:00
import chatService from '../services/chat_service/chat_service.js'
2026-01-06 16:23:17 +02:00
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
2026-01-06 16:22:52 +02:00
import {
parseChat,
parseChatMessage,
} from '../services/entity_normalizer/entity_normalizer.service.js'
2020-09-04 11:19:53 +03:00
import { promiseInterval } from '../services/promise_interval/promise_interval.js'
2020-05-07 16:10:53 +03:00
const emptyChatList = () => ({
data: [],
2026-01-06 16:22:52 +02:00
idStore: {},
2020-05-07 16:10:53 +03:00
})
const defaultState = {
chatList: emptyChatList(),
chatListFetcher: null,
2021-04-25 13:24:08 +03:00
openedChats: reactive({}),
openedChatMessageServices: reactive({}),
2020-05-07 16:10:53 +03:00
fetcher: undefined,
2020-10-29 13:33:06 +03:00
currentChatId: null,
2026-01-06 16:22:52 +02:00
lastReadMessageId: null,
2020-05-07 16:10:53 +03:00
}
const getChatById = (state, id) => {
return find(state.chatList.data, { id })
}
const sortedChatList = (state) => {
return orderBy(state.chatList.data, ['updated_at'], ['desc'])
}
const unreadChatCount = (state) => {
return sumBy(state.chatList.data, 'unread')
}
const chats = {
state: { ...defaultState },
getters: {
2026-01-06 16:22:52 +02:00
currentChat: (state) => state.openedChats[state.currentChatId],
currentChatMessageService: (state) =>
state.openedChatMessageServices[state.currentChatId],
findOpenedChatByRecipientId: (state) => (recipientId) =>
find(state.openedChats, (c) => c.account.id === recipientId),
2020-05-07 16:10:53 +03:00
sortedChatList,
2026-01-06 16:22:52 +02:00
unreadChatCount,
2020-05-07 16:10:53 +03:00
},
actions: {
// Chat list
2026-01-06 16:22:52 +02:00
startFetchingChats({ dispatch, commit }) {
2020-09-02 21:01:31 +03:00
const fetcher = () => dispatch('fetchChats', { latest: true })
2020-05-07 16:10:53 +03:00
fetcher()
commit('setChatListFetcher', {
2026-01-06 16:22:52 +02:00
fetcher: () => promiseInterval(fetcher, 5000),
2020-05-07 16:10:53 +03:00
})
},
2026-01-06 16:22:52 +02:00
stopFetchingChats({ commit }) {
2020-05-07 16:10:53 +03:00
commit('setChatListFetcher', { fetcher: undefined })
},
2026-01-06 16:22:52 +02:00
fetchChats({ dispatch, rootState }) {
return rootState.api.backendInteractor.chats().then(({ chats }) => {
dispatch('addNewChats', { chats })
return chats
})
2020-05-07 16:10:53 +03:00
},
2026-01-06 16:22:52 +02:00
addNewChats(store, { chats }) {
2020-07-13 00:06:45 +03:00
const { commit, dispatch, rootGetters } = store
const newChatMessageSideEffects = (chat) => {
maybeShowChatNotification(store, chat)
}
2026-01-06 16:22:52 +02:00
commit(
'addNewUsers',
chats.map((k) => k.account).filter((k) => k),
)
commit('addNewChats', {
dispatch,
chats,
rootGetters,
newChatMessageSideEffects,
})
2020-05-07 16:10:53 +03:00
},
2026-01-06 16:22:52 +02:00
updateChat({ commit }, { chat }) {
2020-05-07 16:10:53 +03:00
commit('updateChat', { chat })
},
// Opened Chats
2026-01-06 16:22:52 +02:00
startFetchingCurrentChat({ dispatch }, { fetcher }) {
2020-05-07 16:10:53 +03:00
dispatch('setCurrentChatFetcher', { fetcher })
},
2026-01-06 16:22:52 +02:00
setCurrentChatFetcher({ commit }, { fetcher }) {
2020-05-07 16:10:53 +03:00
commit('setCurrentChatFetcher', { fetcher })
},
2026-01-06 16:22:52 +02:00
addOpenedChat({ commit, dispatch }, { chat }) {
2020-05-07 16:10:53 +03:00
commit('addOpenedChat', { dispatch, chat: parseChat(chat) })
dispatch('addNewUsers', [chat.account])
},
2026-01-06 16:22:52 +02:00
addChatMessages({ commit }, value) {
2020-05-07 16:10:53 +03:00
commit('addChatMessages', { commit, ...value })
},
2026-01-06 16:22:52 +02:00
resetChatNewMessageCount({ commit }, value) {
2020-05-07 16:10:53 +03:00
commit('resetChatNewMessageCount', value)
},
2026-01-06 16:22:52 +02:00
clearCurrentChat({ commit }) {
2020-05-07 16:10:53 +03:00
commit('setCurrentChatId', { chatId: undefined })
commit('setCurrentChatFetcher', { fetcher: undefined })
},
2026-01-06 16:22:52 +02:00
readChat({ rootState, commit, dispatch }, { id, lastReadId }) {
2020-10-29 13:33:06 +03:00
const isNewMessage = rootState.chats.lastReadMessageId !== lastReadId
2020-05-07 16:10:53 +03:00
dispatch('resetChatNewMessageCount')
2020-10-29 13:33:06 +03:00
commit('readChat', { id, lastReadId })
if (isNewMessage) {
rootState.api.backendInteractor.readChat({ id, lastReadId })
}
2020-05-07 16:10:53 +03:00
},
2026-01-06 16:22:52 +02:00
deleteChatMessage({ rootState, commit }, value) {
2020-05-07 16:10:53 +03:00
rootState.api.backendInteractor.deleteChatMessage(value)
commit('deleteChatMessage', { commit, ...value })
},
2026-01-06 16:22:52 +02:00
resetChats({ commit, dispatch }) {
2020-05-07 16:10:53 +03:00
dispatch('clearCurrentChat')
commit('resetChats', { commit })
},
2026-01-06 16:22:52 +02:00
clearOpenedChats({ commit }) {
2020-05-07 16:10:53 +03:00
commit('clearOpenedChats', { commit })
2020-10-29 13:33:06 +03:00
},
2026-01-06 16:22:52 +02:00
handleMessageError({ commit }, value) {
2020-10-29 13:33:06 +03:00
commit('handleMessageError', { commit, ...value })
},
2026-01-06 16:22:52 +02:00
cullOlderMessages({ commit }, chatId) {
commit('cullOlderMessages', chatId)
2026-01-06 16:22:52 +02:00
},
2020-05-07 16:10:53 +03:00
},
mutations: {
2026-01-06 16:22:52 +02:00
setChatListFetcher(state, { fetcher }) {
2020-05-07 16:10:53 +03:00
const prevFetcher = state.chatListFetcher
if (prevFetcher) {
prevFetcher.stop()
2020-05-07 16:10:53 +03:00
}
state.chatListFetcher = fetcher && fetcher()
},
2026-01-06 16:22:52 +02:00
setCurrentChatFetcher(state, { fetcher }) {
2020-05-07 16:10:53 +03:00
const prevFetcher = state.fetcher
if (prevFetcher) {
prevFetcher.stop()
2020-05-07 16:10:53 +03:00
}
state.fetcher = fetcher && fetcher()
},
2026-01-06 16:22:52 +02:00
addOpenedChat(state, { chat }) {
2020-05-07 16:10:53 +03:00
state.currentChatId = chat.id
2021-04-25 13:24:08 +03:00
state.openedChats[chat.id] = chat
2020-05-07 16:10:53 +03:00
if (!state.openedChatMessageServices[chat.id]) {
2021-04-25 13:24:08 +03:00
state.openedChatMessageServices[chat.id] = chatService.empty(chat.id)
2020-05-07 16:10:53 +03:00
}
},
2026-01-06 16:22:52 +02:00
setCurrentChatId(state, { chatId }) {
2020-05-07 16:10:53 +03:00
state.currentChatId = chatId
},
2026-01-06 16:22:52 +02:00
addNewChats(state, { chats, newChatMessageSideEffects }) {
2020-05-07 16:10:53 +03:00
chats.forEach((updatedChat) => {
const chat = getChatById(state, updatedChat.id)
if (chat) {
2026-01-06 16:22:52 +02:00
const isNewMessage =
(chat.lastMessage && chat.lastMessage.id) !==
(updatedChat.lastMessage && updatedChat.lastMessage.id)
2020-05-07 16:10:53 +03:00
chat.lastMessage = updatedChat.lastMessage
chat.unread = updatedChat.unread
chat.updated_at = updatedChat.updated_at
2020-07-13 00:06:45 +03:00
if (isNewMessage && chat.unread) {
newChatMessageSideEffects(updatedChat)
}
2020-05-07 16:10:53 +03:00
} else {
state.chatList.data.push(updatedChat)
2021-04-25 13:24:08 +03:00
state.chatList.idStore[updatedChat.id] = updatedChat
2020-05-07 16:10:53 +03:00
}
})
},
2026-01-06 16:22:52 +02:00
updateChat(state, { chat: updatedChat }) {
2020-05-07 16:10:53 +03:00
const chat = getChatById(state, updatedChat.id)
if (chat) {
chat.lastMessage = updatedChat.lastMessage
chat.unread = updatedChat.unread
chat.updated_at = updatedChat.updated_at
}
2026-01-06 16:22:52 +02:00
if (!chat) {
state.chatList.data.unshift(updatedChat)
}
2021-04-25 13:24:08 +03:00
state.chatList.idStore[updatedChat.id] = updatedChat
2020-05-07 16:10:53 +03:00
},
2026-01-06 16:22:52 +02:00
deleteChat(state, { id }) {
state.chats.data = state.chats.data.filter(
(conversation) => conversation.last_status.id !== id,
)
state.chats.idStore = omitBy(
state.chats.idStore,
(conversation) => conversation.last_status.id === id,
2020-05-07 16:10:53 +03:00
)
},
2026-01-06 16:22:52 +02:00
resetChats(state, { commit }) {
2020-05-07 16:10:53 +03:00
state.chatList = emptyChatList()
state.currentChatId = null
commit('setChatListFetcher', { fetcher: undefined })
for (const chatId in state.openedChats) {
chatService.clear(state.openedChatMessageServices[chatId])
2021-04-25 13:24:08 +03:00
delete state.openedChats[chatId]
delete state.openedChatMessageServices[chatId]
2020-05-07 16:10:53 +03:00
}
},
2026-01-06 16:22:52 +02:00
setChatsLoading(state, { value }) {
2020-05-07 16:10:53 +03:00
state.chats.loading = value
},
2026-01-06 16:22:52 +02:00
addChatMessages(state, { chatId, messages, updateMaxId }) {
2020-05-07 16:10:53 +03:00
const chatMessageService = state.openedChatMessageServices[chatId]
if (chatMessageService) {
2026-01-06 16:22:52 +02:00
chatService.add(chatMessageService, {
messages: messages.map(parseChatMessage),
updateMaxId,
})
2020-05-07 16:10:53 +03:00
}
},
2026-01-06 16:22:52 +02:00
deleteChatMessage(state, { chatId, messageId }) {
2020-05-07 16:10:53 +03:00
const chatMessageService = state.openedChatMessageServices[chatId]
if (chatMessageService) {
chatService.deleteMessage(chatMessageService, messageId)
}
},
2026-01-06 16:22:52 +02:00
resetChatNewMessageCount(state) {
const chatMessageService =
state.openedChatMessageServices[state.currentChatId]
2020-05-07 16:10:53 +03:00
chatService.resetNewMessageCount(chatMessageService)
},
// Used when a connection loss occurs
2026-01-06 16:22:52 +02:00
clearOpenedChats(state) {
2020-05-07 16:10:53 +03:00
const currentChatId = state.currentChatId
for (const chatId in state.openedChats) {
if (currentChatId !== chatId) {
chatService.clear(state.openedChatMessageServices[chatId])
2021-04-25 13:24:08 +03:00
delete state.openedChats[chatId]
delete state.openedChatMessageServices[chatId]
2020-05-07 16:10:53 +03:00
}
}
},
2026-01-06 16:22:52 +02:00
readChat(state, { id, lastReadId }) {
2020-10-29 13:33:06 +03:00
state.lastReadMessageId = lastReadId
2020-05-07 16:10:53 +03:00
const chat = getChatById(state, id)
if (chat) {
chat.unread = 0
}
2020-10-29 13:33:06 +03:00
},
2026-01-06 16:22:52 +02:00
handleMessageError(state, { chatId, fakeId, isRetry }) {
2020-10-29 13:33:06 +03:00
const chatMessageService = state.openedChatMessageServices[chatId]
chatService.handleMessageError(chatMessageService, fakeId, isRetry)
},
2026-01-06 16:22:52 +02:00
cullOlderMessages(state, chatId) {
chatService.cullOlderMessages(state.openedChatMessageServices[chatId])
2026-01-06 16:22:52 +02:00
},
},
2020-05-07 16:10:53 +03:00
}
export default chats