Chat message deletion

This commit is contained in:
eugenijm 2020-05-12 23:27:16 +03:00
parent 855f36eeda
commit d2456d5fea
12 changed files with 136 additions and 43 deletions

View file

@ -74,12 +74,16 @@ const Chat = {
return this.$t('chats.write_message')
}
},
customRef () {
return this.$store.state.chats.ref
},
...mapGetters(['currentChat', 'currentChatMessageService', 'findUser']),
...mapState({
backendInteractor: state => state.api.backendInteractor,
currentUser: state => state.users.currentUser,
isMobileLayout: state => state.interface.mobileLayout,
openedChats: state => state.chats.openedChats
openedChats: state => state.chats.openedChats,
openedChatMessageServices: state => state.chats.openedChatMessageServices
})
},
watch: {
@ -92,6 +96,11 @@ const Chat = {
}
})
},
'currentChatMessageService.messages.length': {
handler: function () {
this.chatViewItems = chatService.getView(this.currentChatMessageService)
}
},
'$route': function (prev, next) {
this.recipientId = this.$route.params.recipient_id
this.startFetching()
@ -108,11 +117,6 @@ const Chat = {
this.scrollDown({ forceRead: true })
})
},
onScopeNoticeDismissed () {
this.$nextTick(() => {
this.updateSize()
})
},
onFilesDropped () {
this.$nextTick(() => {
this.updateSize()
@ -327,7 +331,6 @@ const Chat = {
let bottomedOut = this.bottomedOut()
this.loadingOlderMessages = false
this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => {
this.chatViewItems = chatService.getView(this.currentChatMessageService)
if (positionBeforeLoading) {
this.$nextTick(() => {
let positionAfterLoading = this.getPosition()

View file

@ -14,7 +14,10 @@
class="go-back-button"
@click="goBack"
> -->
<i class="button-icon icon-left-open" @click="goBack" />
<i
class="button-icon icon-left-open"
@click="goBack"
/>
<!-- </a> -->
<div class="title text-center">
<ChatTitle
@ -35,7 +38,7 @@
style="margin-right: 0.3em;"
@click="goBack"
> -->
<i class="button-icon icon-info-circled" />
<i class="button-icon icon-info-circled" />
<!-- </a> -->
</div>
</div>

View file

@ -1,4 +1,5 @@
import { mapState, mapGetters } from 'vuex'
import Popover from '../popover/popover.vue'
import Attachment from '../attachment/attachment.vue'
import UserAvatar from '../user_avatar/user_avatar.vue'
import Gallery from '../gallery/gallery.vue'
@ -16,6 +17,7 @@ const ChatMessage = {
'sequenceHovered'
],
components: {
Popover,
Attachment,
StatusContent,
UserAvatar,
@ -46,30 +48,45 @@ const ChatMessage = {
return this.chatViewItem.type === 'message'
},
messageForStatusContent () {
let result = {
return {
summary: '',
statusnet_html: this.message.content,
text: this.message.content
text: this.message.content,
attachments: this.message.attachments
}
if (this.message.attachment) {
result.attachments = [this.message.attachment]
} else {
result.attachments = []
}
return result
},
...mapState({
betterShadow: state => state.interface.browserSupport.cssFilter,
currentUser: state => state.users.currentUser,
restrictedNicknames: state => state.instance.restrictedNicknames
}),
wrapperStyle () {
return {
'opacity': this.hovered || this.menuOpened ? '1' : '0'
}
},
...mapGetters(['mergedConfig', 'findUser'])
},
data () {
return {
hovered: false,
menuOpened: false
}
},
methods: {
onHover (bool) {
this.$emit('hover', { state: bool, sequenceId: this.chatViewItem.sequenceId })
},
async deleteMessage () {
const confirmed = window.confirm(this.$t('chats.delete_confirm'))
if (confirmed) {
await this.$store.dispatch('deleteChatMessage', {
messageId: this.chatViewItem.data.id,
chatId: this.chatViewItem.data.chat_id
})
}
this.hovered = false
this.menuOpened = false
}
}
}

View file

@ -24,16 +24,8 @@
.status {
padding: 0.75em;
&:hover {
.chat-message-menu {
// visibility: visible;
opacity: 1;
}
}
.chat-message-menu {
transition: opacity 0.1s;
// visibility: hidden;
opacity: 0;
button {
@ -41,6 +33,16 @@
padding-bottom: 3px;
}
}
.icon-ellipsis {
cursor: pointer;
&:hover,
.extra-button-popover.open & {
color: $fallback--text;
color: var(--text, $fallback--text);
}
}
}
.direct-conversation {

View file

@ -26,24 +26,54 @@
</router-link>
</div>
<div class="direct-conversation-inner">
<div class="status-body" :style="{ 'min-width': message.attachment ? '80%' : '' }">
<div
class="status-body"
:style="{ 'min-width': message.attachment ? '80%' : '' }"
>
<div
class="media status"
style="position: relative"
>
@mouseenter="hovered = true"
@mouseleave="hovered = false"
>
<div
v-if="isCurrentUser"
class="chat-message-menu"
style="position: absolute; right: 5px; top: -10px"
:style="wrapperStyle"
>
<Popover
trigger="click"
placement="top"
:bound-to="{ x: 'container' }"
@show="menuOpened = true"
@close="menuOpened = false"
>
<button
title="more"
>
<i class="icon-dot-3" />
</button>
<div
slot="content"
slot-scope=""
>
<div class="dropdown-menu">
<button
class="dropdown-item dropdown-item-icon"
@click="deleteMessage"
>
<i class="icon-cancel" /> {{ $t("chats.delete") }}
</button>
</div>
</div>
<button
slot="trigger"
:title="$t('chats.more')"
>
<i class="icon-dot-3" />
</button>
</Popover>
</div>
<StatusContent
:status="messageForStatusContent"
:full-content="true">
:full-content="true"
>
<span
slot="footer"
class="created-at"

View file

@ -11,7 +11,10 @@
width="23px"
height="23px"
/>
<span v-if="withAvatar" style="margin-right: 0.5em" />
<span
v-if="withAvatar"
style="margin-right: 0.5em"
/>
<span
v-for="(user, index) in otherUsersTruncated"
:key="user.id"

View file

@ -46,7 +46,10 @@
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
<i class="button-icon icon-mail-alt" /> {{ $t("nav.dms") }}
</router-link>
<router-link :to="{ name: 'chats', params: { username: currentUser.screen_name } }" style="position: relative">
<router-link
:to="{ name: 'chats', params: { username: currentUser.screen_name } }"
style="position: relative"
>
<i class="button-icon icon-chat" /> {{ $t("nav.chats") }}
<span
v-if="unreadChatCount(currentChat)"

View file

@ -759,7 +759,9 @@
"delete": "Delete",
"chats": "Chats",
"new": "New Chat",
"empty_message_error": "Cannot post empty message"
"empty_message_error": "Cannot post empty message",
"more": "More",
"delete_confirm": "Do you really want to delete this message?"
},
"display_date": {
"today": "Today"

View file

@ -1,3 +1,4 @@
import { set } from 'vue'
import { find, omitBy, debounce, last } from 'lodash'
import chatService from '../services/chat_service/chat_service.js'
import { parseChat, parseChatMessage } from '../services/entity_normalizer/entity_normalizer.service.js'
@ -57,7 +58,7 @@ const chats = {
setCurrentChatFetcher ({ rootState, commit }, { fetcher }) {
commit('setCurrentChatFetcher', { fetcher })
},
addOpenedChat ({ commit, dispatch }, { chat }) {
addOpenedChat ({ rootState, commit, dispatch }, { chat }) {
commit('addOpenedChat', { dispatch, chat: parseChat(chat) })
dispatch('addNewUsers', [chat.account])
},
@ -85,6 +86,10 @@ const chats = {
rootState.api.backendInteractor.readChat({ id }).then(() => {
// dispatch('refreshCurrentUser')
})
},
deleteChatMessage ({ rootState, commit, dispatch }, value) {
rootState.api.backendInteractor.deleteChatMessage(value)
commit('deleteChatMessage', value)
}
},
mutations: {
@ -97,10 +102,10 @@ const chats = {
},
addOpenedChat (state, { _dispatch, chat }) {
state.currentChatId = chat.id
state.openedChats[chat.id] = chat
set(state.openedChats, chat.id, chat)
if (!state.openedChatMessageServices[chat.id]) {
state.openedChatMessageServices[chat.id] = chatService.empty(chat.id)
set(state.openedChatMessageServices, chat.id, chatService.empty(chat.id))
}
},
setCurrentChatId (state, { chatId }) {
@ -152,6 +157,12 @@ const chats = {
chatService.add(chatMessageService, { messages: messages.map(parseChatMessage) })
}
},
deleteChatMessage (state, { chatId, messageId }) {
const chatMessageService = state.openedChatMessageServices[chatId]
if (chatMessageService) {
chatService.deleteMessage(chatMessageService, messageId)
}
},
resetChatNewMessageCount (state, _value) {
const chatMessageService = state.openedChatMessageServices[state.currentChatId]
chatService.resetNewMessageCount(chatMessageService)

View file

@ -82,6 +82,7 @@ const PLEROMA_CHATS_URL = `/api/v1/pleroma/chats`
const PLEROMA_CHAT_URL = id => `/api/v1/pleroma/chats/by-account-id/${id}`
const PLEROMA_CHAT_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read`
const PLEROMA_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => `/api/v1/pleroma/chats/${chatId}/messages/${messageId}`
const oldfetch = window.fetch
@ -1192,6 +1193,14 @@ const readChat = ({ id, credentials }) => {
})
}
const deleteChatMessage = ({ chatId, messageId, credentials }) => {
return promisedRequest({
url: PLEROMA_DELETE_CHAT_MESSAGE_URL(chatId, messageId),
method: 'DELETE',
credentials
})
}
const apiService = {
verifyCredentials,
fetchTimeline,
@ -1273,7 +1282,8 @@ const apiService = {
getOrCreateChat,
chatMessages,
postChatMessage,
readChat
readChat,
deleteChatMessage
}
export default apiService

View file

@ -11,6 +11,12 @@ const empty = (chatId) => {
}
}
const deleteMessage = (storage, messageId) => {
if (!storage) { return }
storage.messages = storage.messages.filter(m => m.id !== messageId)
delete storage.idIndex[messageId]
}
const add = (storage, { messages: newMessages }) => {
if (!storage) { return }
for (let i = 0; i < newMessages.length; i++) {
@ -99,6 +105,7 @@ const ChatService = {
add,
empty,
getView,
deleteMessage,
resetNewMessageCount
}

View file

@ -389,7 +389,9 @@ export const parseChatMessage = (message) => {
output.chat_id = parseInt(message.chat_id, 10)
output.content = addEmojis(message.content, message.emojis)
if (message.attachment) {
output.attachment = parseAttachment(message.attachment)
output.attachments = [parseAttachment(message.attachment)]
} else {
output.attachments = []
}
return output
}