pleroma-fe/src/components/chat_message/chat_message.js

161 lines
4.5 KiB
JavaScript
Raw Normal View History

2026-07-10 17:09:17 +03:00
import { find } from 'lodash'
2023-04-05 21:06:37 -06:00
import { mapState as mapPiniaState } from 'pinia'
2026-06-25 13:46:27 +03:00
import { mapState } from 'vuex'
2026-01-08 17:26:52 +02:00
2026-06-02 18:09:12 +03:00
import Attachment from 'src/components/attachment/attachment.vue'
import ChatMessageDate from 'src/components/chat_message_date/chat_message_date.vue'
2026-06-04 21:59:09 +03:00
import Gallery from 'src/components/gallery/gallery.vue'
2026-06-02 18:09:12 +03:00
import LinkPreview from 'src/components/link-preview/link-preview.vue'
import Popover from 'src/components/popover/popover.vue'
2026-07-10 17:09:17 +03:00
import StatusActionButtons from 'src/components/status_action_buttons/status_action_buttons.vue'
2026-07-21 18:25:56 +03:00
import StatusBody from 'src/components/status_body/status_body.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
2026-06-02 18:09:12 +03:00
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserPopover from 'src/components/user_popover/user_popover.vue'
2020-10-20 21:18:23 +03:00
2026-01-29 20:40:00 +02:00
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
2026-01-29 20:40:00 +02:00
2026-01-08 17:26:52 +02:00
import { library } from '@fortawesome/fontawesome-svg-core'
2026-07-08 20:29:59 +03:00
import {
faCircleNotch,
faEllipsisH,
faTimes,
} from '@fortawesome/free-solid-svg-icons'
2026-01-08 17:26:52 +02:00
library.add(faTimes, faEllipsisH, faCircleNotch)
2020-05-07 16:10:53 +03:00
const ChatMessage = {
name: 'ChatMessage',
2026-07-21 18:25:56 +03:00
props: [
'edited',
'noHeading',
'previousItem',
'chatItem',
'previousItem',
'hoveredMessageChain',
],
2026-07-10 17:09:17 +03:00
emits: ['hover', 'replyRequested'],
2020-05-07 16:10:53 +03:00
components: {
Popover,
Attachment,
StatusContent,
2026-07-10 17:09:17 +03:00
StatusBody,
StatusActionButtons,
2020-05-07 16:10:53 +03:00
UserAvatar,
Gallery,
2020-05-07 16:10:53 +03:00
LinkPreview,
2022-07-20 12:54:51 +03:00
ChatMessageDate,
2026-07-21 18:25:56 +03:00
UserPopover,
},
2020-05-07 16:10:53 +03:00
computed: {
// Returns HH:MM (hours and minutes) in local time.
2026-01-06 16:22:52 +02:00
createdAt() {
const time = this.chatItem.data.created_at
2026-01-06 16:22:52 +02:00
return time.toLocaleTimeString('en', {
hour: '2-digit',
minute: '2-digit',
hour12: false,
})
2020-05-07 16:10:53 +03:00
},
2026-07-08 19:34:09 +03:00
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
return this.$store.getters.findUser(accountId)
},
2026-01-06 16:22:52 +02:00
isCurrentUser() {
return this.author.id === this.currentUser.id
2020-05-07 16:10:53 +03:00
},
2026-01-06 16:22:52 +02:00
message() {
return this.isMessage ? this.chatItem.data : null
2020-05-07 16:10:53 +03:00
},
2026-01-06 16:22:52 +02:00
isMessage() {
return this.chatItem.type === 'message'
2020-05-07 16:10:53 +03:00
},
2026-07-10 17:09:17 +03:00
isCustomReply() {
if (!this.previousItem) return false
2026-07-21 18:56:20 +03:00
if (!this.chatItem.data.in_reply_to_status_id) return false
2026-07-21 18:25:56 +03:00
return (
this.previousItem.data.id !== this.chatItem.data.in_reply_to_status_id
)
2026-07-10 17:09:17 +03:00
},
customReplyTo() {
2026-07-21 18:56:20 +03:00
return this.$store.state.statuses.allStatusesObject[
this.chatItem.data.in_reply_to_status_id
]
2026-07-10 17:09:17 +03:00
},
2026-01-06 16:22:52 +02:00
messageForStatusContent() {
2020-05-07 16:10:53 +03:00
return {
summary: '',
emojis: this.message.emojis,
raw_html: this.message.content || this.message.raw_html || '',
2021-06-13 21:42:25 +03:00
text: this.message.content || '',
2026-01-06 16:22:52 +02:00
attachments: this.message.attachments,
2020-05-07 16:10:53 +03:00
}
},
2026-01-06 16:22:52 +02:00
hasAttachment() {
2020-05-07 16:10:53 +03:00
return this.message.attachments.length > 0
},
2023-04-05 21:06:37 -06:00
...mapPiniaState(useInterfaceStore, {
2026-01-06 16:22:52 +02:00
betterShadow: (store) => store.browserSupport.cssFilter,
2023-04-05 21:06:37 -06:00
}),
2020-05-07 16:10:53 +03:00
...mapState({
2026-01-06 16:22:52 +02:00
currentUser: (state) => state.users.currentUser,
restrictedNicknames: (state) => useInstanceStore().restrictedNicknames,
2020-05-07 16:10:53 +03:00
}),
2026-01-06 16:22:52 +02:00
popoverMarginStyle() {
2020-05-07 16:10:53 +03:00
if (this.isCurrentUser) {
return {}
} else {
return { left: 50 }
}
},
...mapPiniaState(useMergedConfigStore, ['mergedConfig', 'findUser']),
2020-05-07 16:10:53 +03:00
},
2026-01-06 16:22:52 +02:00
data() {
2020-05-07 16:10:53 +03:00
return {
hovered: false,
2026-01-06 16:22:52 +02:00
menuOpened: false,
2020-05-07 16:10:53 +03:00
}
},
methods: {
2026-01-06 16:22:52 +02:00
onHover(bool) {
this.$emit('hover', {
isHovered: bool,
messageChainId: this.chatItem.messageChainId,
2026-01-06 16:22:52 +02:00
})
2020-05-07 16:10:53 +03:00
},
2026-07-09 01:07:59 +03:00
visibilityIcon(visibility) {
switch (visibility) {
case 'private':
return 'lock'
case 'unlisted':
return 'lock-open'
case 'direct':
return 'envelope'
case 'local':
return 'igloo'
default:
return 'globe'
}
},
2026-01-06 16:22:52 +02:00
async deleteMessage() {
2020-05-07 16:10:53 +03:00
const confirmed = window.confirm(this.$t('chats.delete_confirm'))
if (confirmed) {
2026-07-08 19:34:09 +03:00
await this.$emit('delete', {
messageId: this.chatItem.data.id,
chatId: this.chatItem.data.chat_id,
2020-05-07 16:10:53 +03:00
})
}
this.hovered = false
this.menuOpened = false
2026-01-06 16:22:52 +02:00
},
},
2020-05-07 16:10:53 +03:00
}
export default ChatMessage