forked from AkkomaGang/akkoma-fe
Chat message deletion
This commit is contained in:
parent
855f36eeda
commit
d2456d5fea
12 changed files with 136 additions and 43 deletions
|
@ -74,12 +74,16 @@ const Chat = {
|
||||||
return this.$t('chats.write_message')
|
return this.$t('chats.write_message')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
customRef () {
|
||||||
|
return this.$store.state.chats.ref
|
||||||
|
},
|
||||||
...mapGetters(['currentChat', 'currentChatMessageService', 'findUser']),
|
...mapGetters(['currentChat', 'currentChatMessageService', 'findUser']),
|
||||||
...mapState({
|
...mapState({
|
||||||
backendInteractor: state => state.api.backendInteractor,
|
backendInteractor: state => state.api.backendInteractor,
|
||||||
currentUser: state => state.users.currentUser,
|
currentUser: state => state.users.currentUser,
|
||||||
isMobileLayout: state => state.interface.mobileLayout,
|
isMobileLayout: state => state.interface.mobileLayout,
|
||||||
openedChats: state => state.chats.openedChats
|
openedChats: state => state.chats.openedChats,
|
||||||
|
openedChatMessageServices: state => state.chats.openedChatMessageServices
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -92,6 +96,11 @@ const Chat = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
'currentChatMessageService.messages.length': {
|
||||||
|
handler: function () {
|
||||||
|
this.chatViewItems = chatService.getView(this.currentChatMessageService)
|
||||||
|
}
|
||||||
|
},
|
||||||
'$route': function (prev, next) {
|
'$route': function (prev, next) {
|
||||||
this.recipientId = this.$route.params.recipient_id
|
this.recipientId = this.$route.params.recipient_id
|
||||||
this.startFetching()
|
this.startFetching()
|
||||||
|
@ -108,11 +117,6 @@ const Chat = {
|
||||||
this.scrollDown({ forceRead: true })
|
this.scrollDown({ forceRead: true })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onScopeNoticeDismissed () {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.updateSize()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onFilesDropped () {
|
onFilesDropped () {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.updateSize()
|
this.updateSize()
|
||||||
|
@ -327,7 +331,6 @@ const Chat = {
|
||||||
let bottomedOut = this.bottomedOut()
|
let bottomedOut = this.bottomedOut()
|
||||||
this.loadingOlderMessages = false
|
this.loadingOlderMessages = false
|
||||||
this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => {
|
this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => {
|
||||||
this.chatViewItems = chatService.getView(this.currentChatMessageService)
|
|
||||||
if (positionBeforeLoading) {
|
if (positionBeforeLoading) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
let positionAfterLoading = this.getPosition()
|
let positionAfterLoading = this.getPosition()
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
class="go-back-button"
|
class="go-back-button"
|
||||||
@click="goBack"
|
@click="goBack"
|
||||||
> -->
|
> -->
|
||||||
<i class="button-icon icon-left-open" @click="goBack" />
|
<i
|
||||||
|
class="button-icon icon-left-open"
|
||||||
|
@click="goBack"
|
||||||
|
/>
|
||||||
<!-- </a> -->
|
<!-- </a> -->
|
||||||
<div class="title text-center">
|
<div class="title text-center">
|
||||||
<ChatTitle
|
<ChatTitle
|
||||||
|
@ -35,7 +38,7 @@
|
||||||
style="margin-right: 0.3em;"
|
style="margin-right: 0.3em;"
|
||||||
@click="goBack"
|
@click="goBack"
|
||||||
> -->
|
> -->
|
||||||
<i class="button-icon icon-info-circled" />
|
<i class="button-icon icon-info-circled" />
|
||||||
<!-- </a> -->
|
<!-- </a> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
|
import Popover from '../popover/popover.vue'
|
||||||
import Attachment from '../attachment/attachment.vue'
|
import Attachment from '../attachment/attachment.vue'
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
import Gallery from '../gallery/gallery.vue'
|
import Gallery from '../gallery/gallery.vue'
|
||||||
|
@ -16,6 +17,7 @@ const ChatMessage = {
|
||||||
'sequenceHovered'
|
'sequenceHovered'
|
||||||
],
|
],
|
||||||
components: {
|
components: {
|
||||||
|
Popover,
|
||||||
Attachment,
|
Attachment,
|
||||||
StatusContent,
|
StatusContent,
|
||||||
UserAvatar,
|
UserAvatar,
|
||||||
|
@ -46,30 +48,45 @@ const ChatMessage = {
|
||||||
return this.chatViewItem.type === 'message'
|
return this.chatViewItem.type === 'message'
|
||||||
},
|
},
|
||||||
messageForStatusContent () {
|
messageForStatusContent () {
|
||||||
let result = {
|
return {
|
||||||
summary: '',
|
summary: '',
|
||||||
statusnet_html: this.message.content,
|
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({
|
...mapState({
|
||||||
betterShadow: state => state.interface.browserSupport.cssFilter,
|
betterShadow: state => state.interface.browserSupport.cssFilter,
|
||||||
currentUser: state => state.users.currentUser,
|
currentUser: state => state.users.currentUser,
|
||||||
restrictedNicknames: state => state.instance.restrictedNicknames
|
restrictedNicknames: state => state.instance.restrictedNicknames
|
||||||
}),
|
}),
|
||||||
|
wrapperStyle () {
|
||||||
|
return {
|
||||||
|
'opacity': this.hovered || this.menuOpened ? '1' : '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
...mapGetters(['mergedConfig', 'findUser'])
|
...mapGetters(['mergedConfig', 'findUser'])
|
||||||
},
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
hovered: false,
|
||||||
|
menuOpened: false
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onHover (bool) {
|
onHover (bool) {
|
||||||
this.$emit('hover', { state: bool, sequenceId: this.chatViewItem.sequenceId })
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,16 +24,8 @@
|
||||||
.status {
|
.status {
|
||||||
padding: 0.75em;
|
padding: 0.75em;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.chat-message-menu {
|
|
||||||
// visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-message-menu {
|
.chat-message-menu {
|
||||||
transition: opacity 0.1s;
|
transition: opacity 0.1s;
|
||||||
// visibility: hidden;
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
@ -41,6 +33,16 @@
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-ellipsis {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
.extra-button-popover.open & {
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.direct-conversation {
|
.direct-conversation {
|
||||||
|
|
|
@ -26,24 +26,54 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="direct-conversation-inner">
|
<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
|
<div
|
||||||
class="media status"
|
class="media status"
|
||||||
style="position: relative"
|
style="position: relative"
|
||||||
>
|
@mouseenter="hovered = true"
|
||||||
|
@mouseleave="hovered = false"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
|
v-if="isCurrentUser"
|
||||||
class="chat-message-menu"
|
class="chat-message-menu"
|
||||||
style="position: absolute; right: 5px; top: -10px"
|
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
|
<div
|
||||||
title="more"
|
slot="content"
|
||||||
>
|
slot-scope=""
|
||||||
<i class="icon-dot-3" />
|
>
|
||||||
</button>
|
<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>
|
</div>
|
||||||
<StatusContent
|
<StatusContent
|
||||||
:status="messageForStatusContent"
|
:status="messageForStatusContent"
|
||||||
:full-content="true">
|
:full-content="true"
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
slot="footer"
|
slot="footer"
|
||||||
class="created-at"
|
class="created-at"
|
||||||
|
|
|
@ -11,7 +11,10 @@
|
||||||
width="23px"
|
width="23px"
|
||||||
height="23px"
|
height="23px"
|
||||||
/>
|
/>
|
||||||
<span v-if="withAvatar" style="margin-right: 0.5em" />
|
<span
|
||||||
|
v-if="withAvatar"
|
||||||
|
style="margin-right: 0.5em"
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
v-for="(user, index) in otherUsersTruncated"
|
v-for="(user, index) in otherUsersTruncated"
|
||||||
:key="user.id"
|
:key="user.id"
|
||||||
|
|
|
@ -46,7 +46,10 @@
|
||||||
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
|
<router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }">
|
||||||
<i class="button-icon icon-mail-alt" /> {{ $t("nav.dms") }}
|
<i class="button-icon icon-mail-alt" /> {{ $t("nav.dms") }}
|
||||||
</router-link>
|
</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") }}
|
<i class="button-icon icon-chat" /> {{ $t("nav.chats") }}
|
||||||
<span
|
<span
|
||||||
v-if="unreadChatCount(currentChat)"
|
v-if="unreadChatCount(currentChat)"
|
||||||
|
|
|
@ -759,7 +759,9 @@
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"chats": "Chats",
|
"chats": "Chats",
|
||||||
"new": "New Chat",
|
"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": {
|
"display_date": {
|
||||||
"today": "Today"
|
"today": "Today"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { set } from 'vue'
|
||||||
import { find, omitBy, debounce, last } from 'lodash'
|
import { find, omitBy, debounce, last } from 'lodash'
|
||||||
import chatService from '../services/chat_service/chat_service.js'
|
import chatService from '../services/chat_service/chat_service.js'
|
||||||
import { parseChat, parseChatMessage } from '../services/entity_normalizer/entity_normalizer.service.js'
|
import { parseChat, parseChatMessage } from '../services/entity_normalizer/entity_normalizer.service.js'
|
||||||
|
@ -57,7 +58,7 @@ const chats = {
|
||||||
setCurrentChatFetcher ({ rootState, commit }, { fetcher }) {
|
setCurrentChatFetcher ({ rootState, commit }, { fetcher }) {
|
||||||
commit('setCurrentChatFetcher', { fetcher })
|
commit('setCurrentChatFetcher', { fetcher })
|
||||||
},
|
},
|
||||||
addOpenedChat ({ commit, dispatch }, { chat }) {
|
addOpenedChat ({ rootState, commit, dispatch }, { chat }) {
|
||||||
commit('addOpenedChat', { dispatch, chat: parseChat(chat) })
|
commit('addOpenedChat', { dispatch, chat: parseChat(chat) })
|
||||||
dispatch('addNewUsers', [chat.account])
|
dispatch('addNewUsers', [chat.account])
|
||||||
},
|
},
|
||||||
|
@ -85,6 +86,10 @@ const chats = {
|
||||||
rootState.api.backendInteractor.readChat({ id }).then(() => {
|
rootState.api.backendInteractor.readChat({ id }).then(() => {
|
||||||
// dispatch('refreshCurrentUser')
|
// dispatch('refreshCurrentUser')
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
deleteChatMessage ({ rootState, commit, dispatch }, value) {
|
||||||
|
rootState.api.backendInteractor.deleteChatMessage(value)
|
||||||
|
commit('deleteChatMessage', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
|
@ -97,10 +102,10 @@ const chats = {
|
||||||
},
|
},
|
||||||
addOpenedChat (state, { _dispatch, chat }) {
|
addOpenedChat (state, { _dispatch, chat }) {
|
||||||
state.currentChatId = chat.id
|
state.currentChatId = chat.id
|
||||||
state.openedChats[chat.id] = chat
|
set(state.openedChats, chat.id, chat)
|
||||||
|
|
||||||
if (!state.openedChatMessageServices[chat.id]) {
|
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 }) {
|
setCurrentChatId (state, { chatId }) {
|
||||||
|
@ -152,6 +157,12 @@ const chats = {
|
||||||
chatService.add(chatMessageService, { messages: messages.map(parseChatMessage) })
|
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) {
|
resetChatNewMessageCount (state, _value) {
|
||||||
const chatMessageService = state.openedChatMessageServices[state.currentChatId]
|
const chatMessageService = state.openedChatMessageServices[state.currentChatId]
|
||||||
chatService.resetNewMessageCount(chatMessageService)
|
chatService.resetNewMessageCount(chatMessageService)
|
||||||
|
|
|
@ -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_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_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
|
||||||
const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read`
|
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
|
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 = {
|
const apiService = {
|
||||||
verifyCredentials,
|
verifyCredentials,
|
||||||
fetchTimeline,
|
fetchTimeline,
|
||||||
|
@ -1273,7 +1282,8 @@ const apiService = {
|
||||||
getOrCreateChat,
|
getOrCreateChat,
|
||||||
chatMessages,
|
chatMessages,
|
||||||
postChatMessage,
|
postChatMessage,
|
||||||
readChat
|
readChat,
|
||||||
|
deleteChatMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
export default apiService
|
export default apiService
|
||||||
|
|
|
@ -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 }) => {
|
const add = (storage, { messages: newMessages }) => {
|
||||||
if (!storage) { return }
|
if (!storage) { return }
|
||||||
for (let i = 0; i < newMessages.length; i++) {
|
for (let i = 0; i < newMessages.length; i++) {
|
||||||
|
@ -99,6 +105,7 @@ const ChatService = {
|
||||||
add,
|
add,
|
||||||
empty,
|
empty,
|
||||||
getView,
|
getView,
|
||||||
|
deleteMessage,
|
||||||
resetNewMessageCount
|
resetNewMessageCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -389,7 +389,9 @@ export const parseChatMessage = (message) => {
|
||||||
output.chat_id = parseInt(message.chat_id, 10)
|
output.chat_id = parseInt(message.chat_id, 10)
|
||||||
output.content = addEmojis(message.content, message.emojis)
|
output.content = addEmojis(message.content, message.emojis)
|
||||||
if (message.attachment) {
|
if (message.attachment) {
|
||||||
output.attachment = parseAttachment(message.attachment)
|
output.attachments = [parseAttachment(message.attachment)]
|
||||||
|
} else {
|
||||||
|
output.attachments = []
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue