From aa2cf51c05ebdf411d74af5debbbc8fa4d3cf457 Mon Sep 17 00:00:00 2001 From: eugenijm Date: Thu, 7 May 2020 16:10:53 +0300 Subject: Add Chats --- src/modules/chats.js | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 src/modules/chats.js (limited to 'src/modules/chats.js') diff --git a/src/modules/chats.js b/src/modules/chats.js new file mode 100644 index 00000000..f868ca0c --- /dev/null +++ b/src/modules/chats.js @@ -0,0 +1,228 @@ +import Vue from 'vue' +import { find, omitBy, orderBy, sumBy } from 'lodash' +import chatService from '../services/chat_service/chat_service.js' +import { parseChat, parseChatMessage } from '../services/entity_normalizer/entity_normalizer.service.js' + +const emptyChatList = () => ({ + data: [], + idStore: {} +}) + +const defaultState = { + chatList: emptyChatList(), + chatListFetcher: null, + openedChats: {}, + openedChatMessageServices: {}, + fetcher: undefined, + currentChatId: null +} + +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: { + currentChat: state => state.openedChats[state.currentChatId], + currentChatMessageService: state => state.openedChatMessageServices[state.currentChatId], + findOpenedChatByRecipientId: state => recipientId => find(state.openedChats, c => c.account.id === recipientId), + sortedChatList, + unreadChatCount + }, + actions: { + // Chat list + startFetchingChats ({ dispatch, commit }) { + const fetcher = () => { + dispatch('fetchChats', { latest: true }) + } + fetcher() + commit('setChatListFetcher', { + fetcher: () => setInterval(() => { fetcher() }, 5000) + }) + }, + stopFetchingChats ({ commit }) { + commit('setChatListFetcher', { fetcher: undefined }) + }, + fetchChats ({ dispatch, rootState, commit }, params = {}) { + return rootState.api.backendInteractor.chats() + .then(({ chats }) => { + dispatch('addNewChats', { chats }) + return chats + }) + }, + addNewChats ({ rootState, commit, dispatch, rootGetters }, { chats }) { + commit('addNewChats', { dispatch, chats, rootGetters }) + }, + updateChat ({ commit }, { chat }) { + commit('updateChat', { chat }) + }, + + // Opened Chats + startFetchingCurrentChat ({ commit, dispatch }, { fetcher }) { + dispatch('setCurrentChatFetcher', { fetcher }) + }, + setCurrentChatFetcher ({ rootState, commit }, { fetcher }) { + commit('setCurrentChatFetcher', { fetcher }) + }, + addOpenedChat ({ rootState, commit, dispatch }, { chat }) { + commit('addOpenedChat', { dispatch, chat: parseChat(chat) }) + dispatch('addNewUsers', [chat.account]) + }, + addChatMessages ({ commit }, value) { + commit('addChatMessages', { commit, ...value }) + }, + resetChatNewMessageCount ({ commit }, value) { + commit('resetChatNewMessageCount', value) + }, + removeFromCurrentChatStatuses ({ commit }, { id }) { + commit('removeFromCurrentChatStatuses', id) + }, + clearCurrentChat ({ rootState, commit, dispatch }, value) { + commit('setCurrentChatId', { chatId: undefined }) + commit('setCurrentChatFetcher', { fetcher: undefined }) + }, + readChat ({ rootState, commit, dispatch }, { id, lastReadId }) { + dispatch('resetChatNewMessageCount') + commit('readChat', { id }) + rootState.api.backendInteractor.readChat({ id, lastReadId }) + }, + deleteChatMessage ({ rootState, commit }, value) { + rootState.api.backendInteractor.deleteChatMessage(value) + commit('deleteChatMessage', { commit, ...value }) + }, + resetChats ({ commit, dispatch }) { + dispatch('clearCurrentChat') + commit('resetChats', { commit }) + }, + clearOpenedChats ({ rootState, commit, dispatch, rootGetters }) { + commit('clearOpenedChats', { commit }) + } + }, + mutations: { + setChatListFetcher (state, { commit, fetcher }) { + const prevFetcher = state.chatListFetcher + if (prevFetcher) { + clearInterval(prevFetcher) + } + state.chatListFetcher = fetcher && fetcher() + }, + setCurrentChatFetcher (state, { fetcher }) { + const prevFetcher = state.fetcher + if (prevFetcher) { + clearInterval(prevFetcher) + } + state.fetcher = fetcher && fetcher() + }, + addOpenedChat (state, { _dispatch, chat }) { + state.currentChatId = chat.id + Vue.set(state.openedChats, chat.id, chat) + + if (!state.openedChatMessageServices[chat.id]) { + Vue.set(state.openedChatMessageServices, chat.id, chatService.empty(chat.id)) + } + }, + setCurrentChatId (state, { chatId }) { + state.currentChatId = chatId + }, + addNewChats (state, { _dispatch, chats, _rootGetters }) { + chats.forEach((updatedChat) => { + const chat = getChatById(state, updatedChat.id) + + if (chat) { + chat.lastMessage = updatedChat.lastMessage + chat.unread = updatedChat.unread + } else { + state.chatList.data.push(updatedChat) + Vue.set(state.chatList.idStore, updatedChat.id, updatedChat) + } + }) + }, + updateChat (state, { _dispatch, chat: updatedChat, _rootGetters }) { + const chat = getChatById(state, updatedChat.id) + if (chat) { + chat.lastMessage = updatedChat.lastMessage + chat.unread = updatedChat.unread + chat.updated_at = updatedChat.updated_at + } + if (!chat) { state.chatList.data.unshift(updatedChat) } + Vue.set(state.chatList.idStore, updatedChat.id, updatedChat) + }, + deleteChat (state, { _dispatch, id, _rootGetters }) { + 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) + }, + resetChats (state, { commit }) { + state.chatList = emptyChatList() + state.currentChatId = null + commit('setChatListFetcher', { fetcher: undefined }) + for (const chatId in state.openedChats) { + chatService.clear(state.openedChatMessageServices[chatId]) + Vue.delete(state.openedChats, chatId) + Vue.delete(state.openedChatMessageServices, chatId) + } + }, + setChatsLoading (state, { value }) { + state.chats.loading = value + }, + addChatMessages (state, { commit, chatId, messages }) { + const chatMessageService = state.openedChatMessageServices[chatId] + if (chatMessageService) { + chatService.add(chatMessageService, { messages: messages.map(parseChatMessage) }) + commit('refreshLastMessage', { chatId }) + } + }, + refreshLastMessage (state, { chatId }) { + const chatMessageService = state.openedChatMessageServices[chatId] + if (chatMessageService) { + const chat = getChatById(state, chatId) + if (chat) { + chat.lastMessage = chatMessageService.lastMessage + if (chatMessageService.lastMessage) { + chat.updated_at = chatMessageService.lastMessage.created_at + } + } + } + }, + deleteChatMessage (state, { commit, chatId, messageId }) { + const chatMessageService = state.openedChatMessageServices[chatId] + if (chatMessageService) { + chatService.deleteMessage(chatMessageService, messageId) + commit('refreshLastMessage', { chatId }) + } + }, + resetChatNewMessageCount (state, _value) { + const chatMessageService = state.openedChatMessageServices[state.currentChatId] + chatService.resetNewMessageCount(chatMessageService) + }, + // Used when a connection loss occurs + clearOpenedChats (state) { + const currentChatId = state.currentChatId + for (const chatId in state.openedChats) { + if (currentChatId !== chatId) { + chatService.clear(state.openedChatMessageServices[chatId]) + Vue.delete(state.openedChats, chatId) + Vue.delete(state.openedChatMessageServices, chatId) + } + } + }, + readChat (state, { id }) { + const chat = getChatById(state, id) + if (chat) { + chat.unread = 0 + } + } + } +} + +export default chats -- cgit v1.2.3-70-g09d2 From 18a1f5d62a72da45d62672043397a7471ab2c090 Mon Sep 17 00:00:00 2001 From: eugenijm Date: Tue, 7 Jul 2020 18:30:05 +0300 Subject: Add the empty chat list placeholder. Do not use full height when displaying the chat list. Remove an unsued chat action. --- src/components/chat_list/chat_list.vue | 27 ++++++++++++++++++++-- .../post_status_form/post_status_form.js | 2 +- src/i18n/en.json | 3 ++- src/modules/chats.js | 3 --- 4 files changed, 28 insertions(+), 7 deletions(-) (limited to 'src/modules/chats.js') diff --git a/src/components/chat_list/chat_list.vue b/src/components/chat_list/chat_list.vue index e62f58e5..fa138f16 100644 --- a/src/components/chat_list/chat_list.vue +++ b/src/components/chat_list/chat_list.vue @@ -15,7 +15,10 @@
-
+
@@ -39,10 +48,24 @@ @import '../../_variables.scss'; .chat-list { - min-height: calc(100vh - 67px); + min-height: 25em; margin-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; + + &::after { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } +} + +.emtpy-chat-list-alert { + padding: 3em; + font-size: 1.2em; + display: flex; + justify-content: center; + color: $fallback--text; + color: var(--faint, $fallback--text); } diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 9e7cce0f..b0d94555 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -192,7 +192,7 @@ const PostStatusForm = { this.newStatus.poll.error }, showPreview () { - return !!this.preview || this.previewLoading + return !this.disablePreview && (!!this.preview || this.previewLoading) }, emptyStatus () { return this.newStatus.status.trim() === '' && this.newStatus.files.length === 0 diff --git a/src/i18n/en.json b/src/i18n/en.json index c9a34556..5cc75460 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -794,7 +794,8 @@ "more": "More", "delete_confirm": "Do you really want to delete this message?", "error_loading_chat": "Something went wrong when loading the chat.", - "error_sending_message": "Something went wrong when sending the message." + "error_sending_message": "Something went wrong when sending the message.", + "empty_chat_list_placeholder": "You don't have any chats yet. Start a new chat!" }, "file_type": { "audio": "Audio", diff --git a/src/modules/chats.js b/src/modules/chats.js index f868ca0c..228d6256 100644 --- a/src/modules/chats.js +++ b/src/modules/chats.js @@ -83,9 +83,6 @@ const chats = { resetChatNewMessageCount ({ commit }, value) { commit('resetChatNewMessageCount', value) }, - removeFromCurrentChatStatuses ({ commit }, { id }) { - commit('removeFromCurrentChatStatuses', id) - }, clearCurrentChat ({ rootState, commit, dispatch }, value) { commit('setCurrentChatId', { chatId: undefined }) commit('setCurrentChatFetcher', { fetcher: undefined }) -- cgit v1.2.3-70-g09d2