delete works

This commit is contained in:
Henry Jameson 2026-07-08 19:34:09 +03:00
commit 5e306026d8
8 changed files with 42 additions and 98 deletions

View file

@ -43,6 +43,10 @@ const ChatMessage = {
hour12: false,
})
},
isStatus() {
// ChatMessage only has account_id while Status has full user data
return !!this.message.user
},
author() {
const accountId = this.message.account_id || this.message.user.id
@ -101,7 +105,7 @@ const ChatMessage = {
async deleteMessage() {
const confirmed = window.confirm(this.$t('chats.delete_confirm'))
if (confirmed) {
await this.$store.dispatch('deleteChatMessage', {
await this.$emit('delete', {
messageId: this.chatItem.data.id,
chatId: this.chatItem.data.chat_id,
})

View file

@ -22,6 +22,7 @@ const ChatMessageList = {
hoveredMessageChainId: undefined,
}
},
emits: ['messageDelete'],
computed: {
chatItems() {
const messages = [
@ -104,6 +105,9 @@ const ChatMessageList = {
onMessageHover({ isHovered, messageChainId }) {
this.hoveredMessageChainId = isHovered ? messageChainId : undefined
},
onMessageDelete({ messageId, chatId }) {
this.$emit('messageDelete', { messageId, chatId })
},
},
}

View file

@ -6,6 +6,7 @@
:chat-item="chatItem"
:hovered-message-chain="chatItem.messageChainId === hoveredMessageChainId"
@hover="onMessageHover"
@delete="onMessageDelete"
/>
</div>
</template>

View file

@ -6,7 +6,6 @@ import { mapGetters, mapState } from 'vuex'
import ChatMessageList from 'src/components/chat_message_list/chat_message_list.vue'
import ChatTitle from 'src/components/chat_title/chat_title.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import chatService from '../../services/chat_service/chat_service.js'
import { buildFakeMessage } from '../../services/chat_utils/chat_utils.js'
import { promiseInterval } from '../../services/promise_interval/promise_interval.js'
import {
@ -25,6 +24,7 @@ import {
getOrCreateChat,
readChat,
sendChatMessage,
deleteChatMessage,
} from 'src/api/chats.js'
import { WSConnectionStatus } from 'src/api/websocket.js'
@ -352,6 +352,26 @@ const Chat = {
)
this.fetchChat({ isFirstFetch: true })
},
async deleteChatMessage({ chatId, messageId }) {
await deleteChatMessage({
chatId,
messageId,
credentials: useOAuthStore().token,
})
this.messages = this.messages.filter((m) => m.id !== messageId)
delete this.messagesIndex[messageId]
if (this.maxId === messageId) {
const lastMessage = maxBy(this.messages, 'id')
this.maxId = lastMessage.id
}
if (this.minId === messageId) {
const firstMessage = minBy(this.messages, 'id')
this.minId = firstMessage.id
}
},
addMessages({ messages: newMessages }) {
for (let i = 0; i < newMessages.length; i++) {
const message = newMessages[i]
@ -438,11 +458,12 @@ const Chat = {
messages: [{ ...data }],
})
} catch (error) {
if (error.name !== 'StatusCodeError') throw error
if (error.name !== 'StatusCodeError' || error.message === 'Failed to fetch') throw error
console.error('Error sending message', error)
this.handleMessageError({
chatId: this.chat.id,
idempotencyKey: params.idempotencyKey,
isRetry: retriesLeft !== MAX_RETRIES,
})
@ -463,6 +484,14 @@ const Chat = {
}
}
},
handleMessageError(idempotencyKey, isRetry) {
const fakeMessage = this.pendingMessagesIndex[idempotencyKey]
if (fakeMessage) {
fakeMessage.error = true
fakeMessage.pending = false
}
},
goBack() {
this.$router.push({
name: 'chats',

View file

@ -29,6 +29,7 @@
header-date
:messages="messages"
:pending-messages="pendingMessages"
@message-delete="deleteChatMessage"
/>
<div
ref="footer"

View file

@ -1,7 +1,6 @@
import { find, omitBy, orderBy, sumBy } from 'lodash'
import { reactive } from 'vue'
import chatService from '../services/chat_service/chat_service.js'
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
import { promiseInterval } from '../services/promise_interval/promise_interval.js'
@ -17,9 +16,6 @@ const emptyChatList = () => ({
const defaultState = {
chatList: emptyChatList(),
chatListFetcher: null,
fetcher: undefined,
currentChatId: null,
lastReadMessageId: null,
}
const getChatById = (state, id) => {
@ -75,31 +71,6 @@ const chatsModule = {
newChatMessageSideEffects,
})
},
// Opened Chats
addOpenedChat({ commit, dispatch }, { chat }) {
commit('addOpenedChat', { dispatch, chat })
dispatch('addNewUsers', [chat.account])
},
addChatMessages({ commit }, value) {
commit('addChatMessages', { commit, ...value })
},
deleteChatMessage({ rootState, commit }, value) {
deleteChatMessage({
...value,
credentials: useOAuthStore().token,
})
commit('deleteChatMessage', { commit, ...value })
},
resetChats({ commit, dispatch }) {
commit('resetChats', { commit })
},
clearOpenedChats({ commit }) {
commit('clearOpenedChats', { commit })
},
handleMessageError({ commit }, value) {
commit('handleMessageError', { commit, ...value })
},
},
mutations: {
setChatListFetcher(state, { fetcher }) {
@ -109,9 +80,6 @@ const chatsModule = {
}
state.chatListFetcher = fetcher && fetcher()
},
setCurrentChatId(state, { chatId }) {
state.currentChatId = chatId
},
addNewChats(state, { chats, newChatMessageSideEffects }) {
chats.forEach((updatedChat) => {
const chat = getChatById(state, updatedChat.id)

View file

@ -1,61 +0,0 @@
import { maxBy, minBy, orderBy, sortBy, uniqueId } from 'lodash'
const deleteMessage = (storage, messageId) => {
if (!storage) {
return
}
storage.messages = storage.messages.filter((m) => m.id !== messageId)
delete storage.idIndex[messageId]
if (storage.maxId === messageId) {
const lastMessage = maxBy(storage.messages, 'id')
storage.maxId = lastMessage.id
}
if (storage.minId === messageId) {
const firstMessage = minBy(storage.messages, 'id')
storage.minId = firstMessage.id
}
}
const handleMessageError = (storage, fakeId, isRetry) => {
if (!storage) {
return
}
const fakeMessage = storage.idIndex[fakeId]
if (fakeMessage) {
fakeMessage.error = true
fakeMessage.pending = false
if (!isRetry) {
// Ensure the failed message doesn't stay at the bottom of the list.
const lastPersistedMessage = orderBy(
storage.messages,
['pending', 'id'],
['asc', 'desc'],
)[0]
if (lastPersistedMessage) {
const oldId = fakeMessage.id
fakeMessage.id = `${lastPersistedMessage.id}-${new Date().getTime()}`
storage.idIndex[fakeMessage.id] = fakeMessage
delete storage.idIndex[oldId]
}
}
}
}
const resetNewMessageCount = (storage) => {
if (!storage) {
return
}
storage.newMessageCount = 0
storage.lastSeenMessageId = storage.maxId
}
const ChatService = {
deleteMessage,
resetNewMessageCount,
handleMessageError,
}
export default ChatService

View file

@ -1,5 +1,3 @@
import chatService from '../../../../../src/services/chat_service/chat_service.js'
const message1 = {
id: '9wLkdcmQXD21Oy8lEX',
idempotency_key: '1',