migrate chats module to pinia
This commit is contained in:
parent
6dead855d5
commit
5bc802932e
21 changed files with 192 additions and 198 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
import { paramsString, promisedRequest } from './helpers.js'
|
import { paramsString, promisedRequest } from './helpers.js'
|
||||||
|
|
||||||
import { parseChat, parseChatMessage } from 'src/services/entity_normalizer/entity_normalizer.service.js'
|
import {
|
||||||
|
parseChat,
|
||||||
|
parseChatMessage,
|
||||||
|
} from 'src/services/entity_normalizer/entity_normalizer.service.js'
|
||||||
|
|
||||||
const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats'
|
const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats'
|
||||||
const PLEROMA_CHAT_URL = (id) => `/api/v1/pleroma/chats/by-account-id/${id}`
|
const PLEROMA_CHAT_URL = (id) => `/api/v1/pleroma/chats/by-account-id/${id}`
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
import ChatListItem from 'src/components/chat_list_item/chat_list_item.vue'
|
import ChatListItem from 'src/components/chat_list_item/chat_list_item.vue'
|
||||||
import ChatNew from 'src/components/chat_new/chat_new.vue'
|
import ChatNew from 'src/components/chat_new/chat_new.vue'
|
||||||
import List from 'src/components/list/list.vue'
|
import List from 'src/components/list/list.vue'
|
||||||
|
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
|
|
||||||
const ChatList = {
|
const ChatList = {
|
||||||
components: {
|
components: {
|
||||||
ChatListItem,
|
ChatListItem,
|
||||||
|
|
@ -14,7 +17,7 @@ const ChatList = {
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: (state) => state.users.currentUser,
|
currentUser: (state) => state.users.currentUser,
|
||||||
}),
|
}),
|
||||||
...mapGetters(['sortedChatList']),
|
...mapPiniaState(useChatsStore, ['sortedChatList']),
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -22,12 +25,12 @@ const ChatList = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$store.dispatch('fetchChats', { latest: true })
|
useChatsStore().fetchChats()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
cancelNewChat() {
|
cancelNewChat() {
|
||||||
this.isNew = false
|
this.isNew = false
|
||||||
this.$store.dispatch('fetchChats', { latest: true })
|
useChatsStore().fetchChats()
|
||||||
},
|
},
|
||||||
newChat() {
|
newChat() {
|
||||||
this.isNew = true
|
this.isNew = true
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,11 @@ import { useInterfaceStore } from 'src/stores/interface'
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faEllipsisH, faTimes, faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
import {
|
||||||
|
faCircleNotch,
|
||||||
|
faEllipsisH,
|
||||||
|
faTimes,
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
library.add(faTimes, faEllipsisH, faCircleNotch)
|
library.add(faTimes, faEllipsisH, faCircleNotch)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
import { orderBy, throttle, uniqueId } from 'lodash'
|
import { orderBy, uniqueId } from 'lodash'
|
||||||
import { mapState as mapPiniaState } from 'pinia'
|
|
||||||
import { mapGetters, mapState } from 'vuex'
|
|
||||||
|
|
||||||
import ChatMessage from 'src/components/chat_message/chat_message.vue'
|
import ChatMessage from 'src/components/chat_message/chat_message.vue'
|
||||||
|
|
||||||
|
|
@ -34,7 +32,6 @@ const ChatMessageList = {
|
||||||
const date = new Date(message.created_at)
|
const date = new Date(message.created_at)
|
||||||
|
|
||||||
const olderMessage = messages[index - 1]
|
const olderMessage = messages[index - 1]
|
||||||
const newerMessage = messages[index + 1]
|
|
||||||
const newerItem = acc[acc.length - 1]
|
const newerItem = acc[acc.length - 1]
|
||||||
|
|
||||||
const diff = olderMessage
|
const diff = olderMessage
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { throttle } from 'lodash'
|
import { maxBy, minBy, sortBy, throttle } from 'lodash'
|
||||||
import { nextTick } from 'vue'
|
|
||||||
import { mapState as mapPiniaState } from 'pinia'
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { nextTick } from 'vue'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
import ChatMessageList from 'src/components/chat_message_list/chat_message_list.vue'
|
import ChatMessageList from 'src/components/chat_message_list/chat_message_list.vue'
|
||||||
import ChatTitle from 'src/components/chat_title/chat_title.vue'
|
import ChatTitle from 'src/components/chat_title/chat_title.vue'
|
||||||
|
|
@ -15,16 +15,17 @@ import {
|
||||||
isScrollable,
|
isScrollable,
|
||||||
} from './chat_layout_utils.js'
|
} from './chat_layout_utils.js'
|
||||||
|
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
import { useInterfaceStore } from 'src/stores/interface.js'
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
import { useOAuthStore } from 'src/stores/oauth.js'
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
chatMessages,
|
chatMessages,
|
||||||
|
deleteChatMessage,
|
||||||
getOrCreateChat,
|
getOrCreateChat,
|
||||||
readChat,
|
readChat,
|
||||||
sendChatMessage,
|
sendChatMessage,
|
||||||
deleteChatMessage,
|
|
||||||
} from 'src/api/chats.js'
|
} from 'src/api/chats.js'
|
||||||
import { WSConnectionStatus } from 'src/api/websocket.js'
|
import { WSConnectionStatus } from 'src/api/websocket.js'
|
||||||
|
|
||||||
|
|
@ -215,7 +216,7 @@ const Chat = {
|
||||||
credentials: useOAuthStore().token,
|
credentials: useOAuthStore().token,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.$store.commit('readChat', { id: this.chat.id, lastId: lastReadId })
|
useChatsStore().readChat(this.chat.id)
|
||||||
},
|
},
|
||||||
bottomedOut(offset) {
|
bottomedOut(offset) {
|
||||||
return isBottomedOut(offset)
|
return isBottomedOut(offset)
|
||||||
|
|
@ -378,7 +379,10 @@ const Chat = {
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (message.chat_id !== this.chat.id) {
|
if (message.chat_id !== this.chat.id) {
|
||||||
console.warn(`Chat message doesn't belong to current chat (id: ${this.chat.id})!!`, message)
|
console.warn(
|
||||||
|
`Chat message doesn't belong to current chat (id: ${this.chat.id})!!`,
|
||||||
|
message,
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,7 +390,10 @@ const Chat = {
|
||||||
if (message.idempotency_key) {
|
if (message.idempotency_key) {
|
||||||
if (this.pendingMessagesIndex[message.idempotencyKeyIndex]) {
|
if (this.pendingMessagesIndex[message.idempotencyKeyIndex]) {
|
||||||
delete this.pendingMessagesIndex[message.idempotencyKeyIndex]
|
delete this.pendingMessagesIndex[message.idempotencyKeyIndex]
|
||||||
this.pendingMessages = this.pendingMessages.filter(({ idempotency_key }) => idempotency_key !== message.idempotency_key)
|
this.pendingMessages = this.pendingMessages.filter(
|
||||||
|
({ idempotency_key }) =>
|
||||||
|
idempotency_key !== message.idempotency_key,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -445,7 +452,7 @@ const Chat = {
|
||||||
retriesLeft: MAX_RETRIES,
|
retriesLeft: MAX_RETRIES,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async doSendMessage({ params, pendingId, retriesLeft = MAX_RETRIES }) {
|
async doSendMessage({ params, retriesLeft = MAX_RETRIES }) {
|
||||||
if (retriesLeft <= 0) return
|
if (retriesLeft <= 0) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -458,7 +465,11 @@ const Chat = {
|
||||||
messages: [{ ...data }],
|
messages: [{ ...data }],
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name !== 'StatusCodeError' || error.message === 'Failed to fetch') throw error
|
if (
|
||||||
|
error.name !== 'StatusCodeError' ||
|
||||||
|
error.message === 'Failed to fetch'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
console.error('Error sending message', error)
|
console.error('Error sending message', error)
|
||||||
|
|
||||||
this.handleMessageError({
|
this.handleMessageError({
|
||||||
|
|
@ -471,11 +482,10 @@ const Chat = {
|
||||||
(error.statusCode >= 500 && error.statusCode < 600) ||
|
(error.statusCode >= 500 && error.statusCode < 600) ||
|
||||||
error.message === 'Failed to fetch'
|
error.message === 'Failed to fetch'
|
||||||
) {
|
) {
|
||||||
this.messageRetriers[fakeMessage.id] = setTimeout(
|
this.messageRetriers[params.idempotencyKey] = setTimeout(
|
||||||
() => {
|
() => {
|
||||||
this.doSendMessage({
|
this.doSendMessage({
|
||||||
params,
|
params,
|
||||||
fakeMessage,
|
|
||||||
retriesLeft: retriesLeft - 1,
|
retriesLeft: retriesLeft - 1,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
@ -484,7 +494,7 @@ const Chat = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleMessageError(idempotencyKey, isRetry) {
|
handleMessageError(idempotencyKey, isRetry) {
|
||||||
const fakeMessage = this.pendingMessagesIndex[idempotencyKey]
|
const fakeMessage = this.pendingMessagesIndex[idempotencyKey]
|
||||||
|
|
||||||
if (fakeMessage) {
|
if (fakeMessage) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { mapState as mapPiniaState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
import { useInterfaceStore } from 'src/stores/interface.js'
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
import { useSyncConfigStore } from 'src/stores/sync_config.js'
|
import { useSyncConfigStore } from 'src/stores/sync_config.js'
|
||||||
|
|
@ -21,7 +22,7 @@ const ExtraNotifications = {
|
||||||
return (
|
return (
|
||||||
this.mergedConfig.showExtraNotifications &&
|
this.mergedConfig.showExtraNotifications &&
|
||||||
this.mergedConfig.showChatsInExtraNotifications &&
|
this.mergedConfig.showChatsInExtraNotifications &&
|
||||||
this.unreadChatCount
|
this.unreadChatsCount
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
shouldShowAnnouncements() {
|
shouldShowAnnouncements() {
|
||||||
|
|
@ -53,11 +54,12 @@ const ExtraNotifications = {
|
||||||
currentUser() {
|
currentUser() {
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount', 'followRequestCount']),
|
...mapGetters(['followRequestCount']),
|
||||||
...mapPiniaState(useAnnouncementsStore, {
|
...mapState(useAnnouncementsStore, {
|
||||||
unreadAnnouncementCount: 'unreadAnnouncementCount',
|
unreadAnnouncementCount: 'unreadAnnouncementCount',
|
||||||
}),
|
}),
|
||||||
...mapPiniaState(useMergedConfigStore, ['mergedConfig']),
|
...mapState(useMergedConfigStore, ['mergedConfig']),
|
||||||
|
...mapState(useChatsStore, ['unreadChatsCount']),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openNotificationSettings() {
|
openNotificationSettings() {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
class="fa-scale-110 icon"
|
class="fa-scale-110 icon"
|
||||||
icon="comments"
|
icon="comments"
|
||||||
/>
|
/>
|
||||||
{{ $t('notifications.unread_chats', { num: unreadChatCount }, unreadChatCount) }}
|
{{ $t('notifications.unread_chats', { num: unreadChatsCount }, unreadChatsCount) }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
import { defineAsyncComponent } from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
||||||
import GestureService from '../../services/gesture_service/gesture_service'
|
import GestureService from '../../services/gesture_service/gesture_service'
|
||||||
|
|
@ -10,6 +9,7 @@ import {
|
||||||
} from '../../services/notification_utils/notification_utils'
|
} from '../../services/notification_utils/notification_utils'
|
||||||
|
|
||||||
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
import { useInstanceStore } from 'src/stores/instance.js'
|
import { useInstanceStore } from 'src/stores/instance.js'
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
|
||||||
|
|
@ -68,6 +68,7 @@ const MobileNav = {
|
||||||
countExtraNotifications(
|
countExtraNotifications(
|
||||||
this.$store,
|
this.$store,
|
||||||
useMergedConfigStore().mergedConfig,
|
useMergedConfigStore().mergedConfig,
|
||||||
|
useChatsStore().unreadChatsCount,
|
||||||
useAnnouncementsStore().unreadAnnouncementCount,
|
useAnnouncementsStore().unreadAnnouncementCount,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -87,18 +88,18 @@ const MobileNav = {
|
||||||
isChat() {
|
isChat() {
|
||||||
return this.$route.name === 'chat'
|
return this.$route.name === 'chat'
|
||||||
},
|
},
|
||||||
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
|
|
||||||
...mapState(useMergedConfigStore, {
|
|
||||||
pinnedItems: (store) =>
|
|
||||||
new Set(store.prefsStorage.collections.pinnedNavItems).has('chats'),
|
|
||||||
}),
|
|
||||||
shouldConfirmLogout() {
|
shouldConfirmLogout() {
|
||||||
return useMergedConfigStore().mergedConfig.modalOnLogout
|
return useMergedConfigStore().mergedConfig.modalOnLogout
|
||||||
},
|
},
|
||||||
closingDrawerMarksAsSeen() {
|
closingDrawerMarksAsSeen() {
|
||||||
return useMergedConfigStore().mergedConfig.closingDrawerMarksAsSeen
|
return useMergedConfigStore().mergedConfig.closingDrawerMarksAsSeen
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount']),
|
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
|
||||||
|
...mapState(useMergedConfigStore, {
|
||||||
|
pinnedItems: (store) =>
|
||||||
|
new Set(store.prefsStorage.collections.pinnedNavItems).has('chats'),
|
||||||
|
}),
|
||||||
|
...mapState(useChatsStore, ['unreadChatsCount']),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleMobileSidebar() {
|
toggleMobileSidebar() {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
icon="bars"
|
icon="bars"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="(unreadChatCount && !chatsPinned) || unreadAnnouncementCount"
|
v-if="(unreadChatsCount && !chatsPinned) || unreadAnnouncementCount"
|
||||||
class="badge -dot -notification"
|
class="badge -dot -notification"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { mapState as mapPiniaState } from 'pinia'
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
import BookmarkFoldersMenuContent from 'src/components/bookmark_folders_menu/bookmark_folders_menu_content.vue'
|
import BookmarkFoldersMenuContent from 'src/components/bookmark_folders_menu/bookmark_folders_menu_content.vue'
|
||||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
@ -10,6 +10,7 @@ import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
|
||||||
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
||||||
|
|
||||||
import { useAnnouncementsStore } from 'src/stores/announcements'
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
import { useInstanceStore } from 'src/stores/instance.js'
|
import { useInstanceStore } from 'src/stores/instance.js'
|
||||||
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
||||||
import { useSyncConfigStore } from 'src/stores/sync_config.js'
|
import { useSyncConfigStore } from 'src/stores/sync_config.js'
|
||||||
|
|
@ -131,6 +132,7 @@ const NavPanel = {
|
||||||
currentUser: (state) => state.users.currentUser,
|
currentUser: (state) => state.users.currentUser,
|
||||||
followRequestCount: (state) => state.api.followRequests.length,
|
followRequestCount: (state) => state.api.followRequests.length,
|
||||||
}),
|
}),
|
||||||
|
...mapPiniaState(useChatsStore, ['unreadChatsCount']),
|
||||||
timelinesItems() {
|
timelinesItems() {
|
||||||
return filterNavigation(
|
return filterNavigation(
|
||||||
Object.entries({ ...TIMELINES })
|
Object.entries({ ...TIMELINES })
|
||||||
|
|
@ -162,7 +164,6 @@ const NavPanel = {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount']),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ export const ROOT_ITEMS = {
|
||||||
icon: 'comments',
|
icon: 'comments',
|
||||||
label: 'nav.chats',
|
label: 'nav.chats',
|
||||||
badgeStyle: 'notification',
|
badgeStyle: 'notification',
|
||||||
badgeGetter: 'unreadChatCount',
|
badgeGetter: 'unreadChatsCount',
|
||||||
criteria: ['chats'],
|
criteria: ['chats'],
|
||||||
},
|
},
|
||||||
friendRequests: {
|
friendRequests: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
import ExtraNotifications from 'src/components/extra_notifications/extra_notifications.vue'
|
import ExtraNotifications from 'src/components/extra_notifications/extra_notifications.vue'
|
||||||
import Notification from 'src/components/notification/notification.vue'
|
import Notification from 'src/components/notification/notification.vue'
|
||||||
|
|
@ -16,6 +15,7 @@ import notificationsFetcher from '../../services/notifications_fetcher/notificat
|
||||||
import NotificationFilters from './notification_filters.vue'
|
import NotificationFilters from './notification_filters.vue'
|
||||||
|
|
||||||
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
import { useInterfaceStore } from 'src/stores/interface.js'
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
|
||||||
|
|
@ -115,13 +115,14 @@ const Notifications = {
|
||||||
return countExtraNotifications(
|
return countExtraNotifications(
|
||||||
this.$store,
|
this.$store,
|
||||||
useMergedConfigStore().mergedConfig,
|
useMergedConfigStore().mergedConfig,
|
||||||
|
useChatsStore().unreadChatsCount,
|
||||||
useAnnouncementsStore().unreadAnnouncementCount,
|
useAnnouncementsStore().unreadAnnouncementCount,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
unseenCountTitle() {
|
unseenCountTitle() {
|
||||||
return (
|
return (
|
||||||
this.unseenNotifications.length +
|
this.unseenNotifications.length +
|
||||||
this.unreadChatCount +
|
this.unreadChatsCount +
|
||||||
this.unreadAnnouncementCount
|
this.unreadAnnouncementCount
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -160,7 +161,7 @@ const Notifications = {
|
||||||
return !this.noExtra
|
return !this.noExtra
|
||||||
},
|
},
|
||||||
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
|
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
|
||||||
...mapGetters(['unreadChatCount']),
|
...mapState(useChatsStore, ['unreadChatsCount']),
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.scrollerRef = this.$refs.root.closest('.column.-scrollable')
|
this.scrollerRef = this.$refs.root.closest('.column.-scrollable')
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.j
|
||||||
import { useInterfaceStore } from 'src/stores/interface'
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
import { useShoutStore } from 'src/stores/shout'
|
import { useShoutStore } from 'src/stores/shout'
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
|
@ -113,7 +114,8 @@ const SideDrawer = {
|
||||||
sitename: (store) => store.instanceIdentity.name,
|
sitename: (store) => store.instanceIdentity.name,
|
||||||
hideSitename: (store) => store.instanceIdentity.hideSitename,
|
hideSitename: (store) => store.instanceIdentity.hideSitename,
|
||||||
}),
|
}),
|
||||||
...mapGetters(['unreadChatCount', 'draftCount']),
|
...mapState(useChatsStore, ['unreadChatsCount']),
|
||||||
|
...mapGetters(['draftCount']),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleDrawer() {
|
toggleDrawer() {
|
||||||
|
|
|
||||||
|
|
@ -106,10 +106,10 @@
|
||||||
icon="comments"
|
icon="comments"
|
||||||
/> {{ $t("nav.chats") }}
|
/> {{ $t("nav.chats") }}
|
||||||
<span
|
<span
|
||||||
v-if="unreadChatCount"
|
v-if="unreadChatsCount"
|
||||||
class="badge -notification"
|
class="badge -notification"
|
||||||
>
|
>
|
||||||
{{ unreadChatCount }}
|
{{ unreadChatsCount }}
|
||||||
</span>
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { Socket } from 'phoenix'
|
||||||
|
|
||||||
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
|
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
|
||||||
|
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
||||||
import { useInterfaceStore } from 'src/stores/interface.js'
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
import { useOAuthStore } from 'src/stores/oauth.js'
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
|
|
@ -174,7 +175,7 @@ const api = {
|
||||||
) {
|
) {
|
||||||
dispatch('stopFetchingTimeline', { timeline: 'friends' })
|
dispatch('stopFetchingTimeline', { timeline: 'friends' })
|
||||||
dispatch('stopFetchingNotifications')
|
dispatch('stopFetchingNotifications')
|
||||||
dispatch('stopFetchingChats')
|
useChatsStore().stopFetchingChats()
|
||||||
}
|
}
|
||||||
commit('resetRetryMultiplier')
|
commit('resetRetryMultiplier')
|
||||||
commit('setMastoUserSocketStatus', WSConnectionStatus.JOINED)
|
commit('setMastoUserSocketStatus', WSConnectionStatus.JOINED)
|
||||||
|
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
import { find, omitBy, orderBy, sumBy } from 'lodash'
|
|
||||||
import { reactive } from 'vue'
|
|
||||||
|
|
||||||
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
|
|
||||||
import { promiseInterval } from '../services/promise_interval/promise_interval.js'
|
|
||||||
|
|
||||||
import { useOAuthStore } from 'src/stores/oauth.js'
|
|
||||||
|
|
||||||
import { chats, deleteChatMessage } from 'src/api/chats.js'
|
|
||||||
|
|
||||||
const emptyChatList = () => ({
|
|
||||||
data: [],
|
|
||||||
idStore: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
const defaultState = {
|
|
||||||
chatList: emptyChatList(),
|
|
||||||
chatListFetcher: 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 chatsModule = {
|
|
||||||
state: { ...defaultState },
|
|
||||||
getters: {
|
|
||||||
sortedChatList,
|
|
||||||
unreadChatCount,
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
// Chat list
|
|
||||||
startFetchingChats({ dispatch, commit }) {
|
|
||||||
const fetcher = () => dispatch('fetchChats', { latest: true })
|
|
||||||
commit('setChatListFetcher', {
|
|
||||||
fetcher: () => promiseInterval(fetcher, 5000),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
stopFetchingChats({ commit }) {
|
|
||||||
commit('setChatListFetcher', { fetcher: undefined })
|
|
||||||
},
|
|
||||||
fetchChats({ dispatch, rootState }) {
|
|
||||||
return chats({
|
|
||||||
credentials: useOAuthStore().token,
|
|
||||||
}).then(({ data }) => {
|
|
||||||
dispatch('addNewChats', { chats: data })
|
|
||||||
return chats
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addNewChats(store, { chats }) {
|
|
||||||
const { commit, dispatch, rootGetters } = store
|
|
||||||
const newChatMessageSideEffects = (chat) => {
|
|
||||||
maybeShowChatNotification(store, chat)
|
|
||||||
}
|
|
||||||
commit(
|
|
||||||
'addNewUsers',
|
|
||||||
chats.map((k) => k.account).filter((k) => k),
|
|
||||||
)
|
|
||||||
commit('addNewChats', {
|
|
||||||
dispatch,
|
|
||||||
chats,
|
|
||||||
rootGetters,
|
|
||||||
newChatMessageSideEffects,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
setChatListFetcher(state, { fetcher }) {
|
|
||||||
const prevFetcher = state.chatListFetcher
|
|
||||||
if (prevFetcher) {
|
|
||||||
prevFetcher.stop()
|
|
||||||
}
|
|
||||||
state.chatListFetcher = fetcher && fetcher()
|
|
||||||
},
|
|
||||||
addNewChats(state, { chats, newChatMessageSideEffects }) {
|
|
||||||
chats.forEach((updatedChat) => {
|
|
||||||
const chat = getChatById(state, updatedChat.id)
|
|
||||||
|
|
||||||
if (chat) {
|
|
||||||
const isNewMessage =
|
|
||||||
(chat.lastMessage && chat.lastMessage.id) !==
|
|
||||||
(updatedChat.lastMessage && updatedChat.lastMessage.id)
|
|
||||||
chat.lastMessage = updatedChat.lastMessage
|
|
||||||
chat.unread = updatedChat.unread
|
|
||||||
chat.updated_at = updatedChat.updated_at
|
|
||||||
if (isNewMessage && chat.unread) {
|
|
||||||
newChatMessageSideEffects(updatedChat)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.chatList.data.push(updatedChat)
|
|
||||||
state.chatList.idStore[updatedChat.id] = updatedChat
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
updateChat(state, { chat: updatedChat }) {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
state.chatList.idStore[updatedChat.id] = updatedChat
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
resetChats(state, { commit }) {
|
|
||||||
state.chatList = emptyChatList()
|
|
||||||
state.currentChatId = null
|
|
||||||
commit('setChatListFetcher', { fetcher: undefined })
|
|
||||||
},
|
|
||||||
setChatsLoading(state, { value }) {
|
|
||||||
state.chats.loading = value
|
|
||||||
},
|
|
||||||
readChat(state, { id, lastReadId }) {
|
|
||||||
const chat = getChatById(state, id)
|
|
||||||
if (chat) {
|
|
||||||
chat.unread = 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default chatsModule
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import api from './api.js'
|
import api from './api.js'
|
||||||
import chats from './chats.js'
|
|
||||||
import drafts from './drafts.js'
|
import drafts from './drafts.js'
|
||||||
import notifications from './notifications.js'
|
import notifications from './notifications.js'
|
||||||
import profileConfig from './profileConfig.js'
|
import profileConfig from './profileConfig.js'
|
||||||
|
|
@ -13,5 +12,4 @@ export default {
|
||||||
api,
|
api,
|
||||||
profileConfig,
|
profileConfig,
|
||||||
drafts,
|
drafts,
|
||||||
chats,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import {
|
||||||
|
|
||||||
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
import { useAnnouncementsStore } from 'src/stores/announcements.js'
|
||||||
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
|
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
|
||||||
|
import { useChatsStore } from 'src/stores/chats.js'
|
||||||
import { useEmojiStore } from 'src/stores/emoji.js'
|
import { useEmojiStore } from 'src/stores/emoji.js'
|
||||||
import { useInstanceStore } from 'src/stores/instance.js'
|
import { useInstanceStore } from 'src/stores/instance.js'
|
||||||
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
||||||
|
|
@ -725,7 +726,7 @@ const users = {
|
||||||
store.dispatch('stopFetchingFollowRequests')
|
store.dispatch('stopFetchingFollowRequests')
|
||||||
store.commit('clearNotifications')
|
store.commit('clearNotifications')
|
||||||
store.commit('resetStatuses')
|
store.commit('resetStatuses')
|
||||||
store.dispatch('resetChats')
|
useChatsStore().resetChats()
|
||||||
oauth.clearToken()
|
oauth.clearToken()
|
||||||
Cookies.remove('__Host-pleroma_key', { path: '/' })
|
Cookies.remove('__Host-pleroma_key', { path: '/' })
|
||||||
useInterfaceStore().setLastTimeline('public-timeline')
|
useInterfaceStore().setLastTimeline('public-timeline')
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js'
|
import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js'
|
||||||
|
|
||||||
export const maybeShowChatNotification = (store, chat) => {
|
export const maybeShowChatNotification = (chat) => {
|
||||||
if (!chat.lastMessage) return
|
if (!chat.lastMessage) return
|
||||||
if (store.rootState.chats.currentChatId === chat.id && !document.hidden)
|
if (window.vuex.state.users.currentUser.id === chat.lastMessage.account_id)
|
||||||
return
|
|
||||||
if (store.rootState.users.currentUser.id === chat.lastMessage.account_id)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
|
|
@ -21,7 +19,7 @@ export const maybeShowChatNotification = (store, chat) => {
|
||||||
opts.image = chat.lastMessage.attachment.preview_url
|
opts.image = chat.lastMessage.attachment.preview_url
|
||||||
}
|
}
|
||||||
|
|
||||||
showDesktopNotification(store.rootState, opts)
|
showDesktopNotification(window.vuex.state, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const buildFakeMessage = ({
|
export const buildFakeMessage = ({
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,7 @@ export const prepareNotificationObject = (notification, i18n) => {
|
||||||
export const countExtraNotifications = (
|
export const countExtraNotifications = (
|
||||||
store,
|
store,
|
||||||
mergedConfig,
|
mergedConfig,
|
||||||
|
unreadChatsCount,
|
||||||
unreadAnnouncementCount,
|
unreadAnnouncementCount,
|
||||||
) => {
|
) => {
|
||||||
const rootGetters = store.rootGetters || store.getters
|
const rootGetters = store.rootGetters || store.getters
|
||||||
|
|
@ -200,9 +201,7 @@ export const countExtraNotifications = (
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
mergedConfig.showChatsInExtraNotifications
|
mergedConfig.showChatsInExtraNotifications ? unreadChatsCount : 0,
|
||||||
? rootGetters.unreadChatCount
|
|
||||||
: 0,
|
|
||||||
mergedConfig.showAnnouncementsInExtraNotifications
|
mergedConfig.showAnnouncementsInExtraNotifications
|
||||||
? unreadAnnouncementCount
|
? unreadAnnouncementCount
|
||||||
: 0,
|
: 0,
|
||||||
|
|
|
||||||
114
src/stores/chats.js
Normal file
114
src/stores/chats.js
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import { find, omitBy, orderBy, sumBy } from 'lodash'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
|
||||||
|
import { promiseInterval } from '../services/promise_interval/promise_interval.js'
|
||||||
|
|
||||||
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
|
|
||||||
|
import { chats } from 'src/api/chats.js'
|
||||||
|
|
||||||
|
const emptyChatList = () => ({
|
||||||
|
data: [],
|
||||||
|
idStore: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const defaultState = {
|
||||||
|
chatList: emptyChatList(),
|
||||||
|
chatListFetcher: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
const getChatById = (state, id) => {
|
||||||
|
return find(state.chatList.data, { id })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChatsStore = defineStore('chats', {
|
||||||
|
state: () => ({ ...defaultState }),
|
||||||
|
getters: {
|
||||||
|
sortedChatList(state) {
|
||||||
|
return orderBy(state.chatList.data, ['updated_at'], ['desc'])
|
||||||
|
},
|
||||||
|
unreadChatsCount(state) {
|
||||||
|
return sumBy(state.chatList.data, 'unread')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
startFetchingChats() {
|
||||||
|
const fetcher = () => this.fetchChats()
|
||||||
|
this.setChatListFetcher(() => promiseInterval(fetcher, 5000))
|
||||||
|
},
|
||||||
|
stopFetchingChats() {
|
||||||
|
this.setChatListFetcher(null)
|
||||||
|
},
|
||||||
|
async fetchChats() {
|
||||||
|
const { data } = await chats({
|
||||||
|
credentials: useOAuthStore().token,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.addNewChats(data)
|
||||||
|
},
|
||||||
|
setChatListFetcher(fetcher) {
|
||||||
|
const prevFetcher = this.chatListFetcher
|
||||||
|
if (prevFetcher) {
|
||||||
|
prevFetcher.stop()
|
||||||
|
}
|
||||||
|
this.chatListFetcher = fetcher?.()
|
||||||
|
},
|
||||||
|
resetChats() {
|
||||||
|
this.chatList = emptyChatList()
|
||||||
|
this.setChatListFetcher(null)
|
||||||
|
},
|
||||||
|
addNewChats(chats) {
|
||||||
|
window.vuex.commit(
|
||||||
|
'addNewUsers',
|
||||||
|
chats.map((k) => k.account).filter((k) => k),
|
||||||
|
)
|
||||||
|
|
||||||
|
chats.forEach((updatedChat) => {
|
||||||
|
const chat = getChatById(this, updatedChat.id)
|
||||||
|
|
||||||
|
if (chat) {
|
||||||
|
const isNewMessage =
|
||||||
|
(chat.lastMessage && chat.lastMessage.id) !==
|
||||||
|
(updatedChat.lastMessage && updatedChat.lastMessage.id)
|
||||||
|
chat.lastMessage = updatedChat.lastMessage
|
||||||
|
chat.unread = updatedChat.unread
|
||||||
|
chat.updated_at = updatedChat.updated_at
|
||||||
|
if (isNewMessage && chat.unread) {
|
||||||
|
maybeShowChatNotification(chat)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.chatList.data.push(updatedChat)
|
||||||
|
this.chatList.idStore[updatedChat.id] = updatedChat
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
readChat(id) {
|
||||||
|
const chat = getChatById(this, id)
|
||||||
|
if (chat) {
|
||||||
|
chat.unread = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateChat({ chat: updatedChat }) {
|
||||||
|
const chat = getChatById(this, updatedChat.id)
|
||||||
|
if (chat) {
|
||||||
|
chat.lastMessage = updatedChat.lastMessage
|
||||||
|
chat.unread = updatedChat.unread
|
||||||
|
chat.updated_at = updatedChat.updated_at
|
||||||
|
}
|
||||||
|
if (!chat) {
|
||||||
|
this.chatList.data.unshift(updatedChat)
|
||||||
|
}
|
||||||
|
this.chatList.idStore[updatedChat.id] = updatedChat
|
||||||
|
},
|
||||||
|
deleteChat(id) {
|
||||||
|
this.chats.data = this.chats.data.filter(
|
||||||
|
(conversation) => conversation.last_status.id !== id,
|
||||||
|
)
|
||||||
|
this.chats.idStore = omitBy(
|
||||||
|
this.chats.idStore,
|
||||||
|
(conversation) => conversation.last_status.id === id,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue