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'
|
2026-07-22 16:03:48 +03:00
|
|
|
import MentionLink from 'src/components/mention_link/mention_link.vue'
|
2026-06-02 18:09:12 +03:00
|
|
|
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-07-22 16:03:48 +03:00
|
|
|
import StatusPopover from 'src/components/status_popover/status_popover.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'
|
2026-07-22 21:42:59 +03:00
|
|
|
import Timeago from 'src/components/timeago/timeago.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'
|
2026-03-24 21:42:22 +02:00
|
|
|
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,
|
2026-07-22 16:03:48 +03:00
|
|
|
faReply,
|
2026-07-08 20:29:59 +03:00
|
|
|
} from '@fortawesome/free-solid-svg-icons'
|
2026-01-08 17:26:52 +02:00
|
|
|
|
2026-07-22 16:03:48 +03:00
|
|
|
library.add(faTimes, faEllipsisH, faCircleNotch, faReply)
|
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-22 16:03:48 +03:00
|
|
|
'focused',
|
|
|
|
|
'repliedTo',
|
2026-07-21 18:25:56 +03:00
|
|
|
],
|
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,
|
2026-06-04 20:49:43 +03:00
|
|
|
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,
|
2026-07-22 16:03:48 +03:00
|
|
|
StatusPopover,
|
|
|
|
|
MentionLink,
|
2026-07-22 21:42:59 +03:00
|
|
|
Timeago,
|
2026-07-21 18:25:56 +03:00
|
|
|
},
|
2020-05-07 16:10:53 +03:00
|
|
|
computed: {
|
2026-07-08 19:34:09 +03:00
|
|
|
isStatus() {
|
|
|
|
|
// ChatMessage only has account_id while Status has full user data
|
|
|
|
|
return !!this.message.user
|
|
|
|
|
},
|
2026-07-07 20:44:13 +03:00
|
|
|
author() {
|
2026-07-07 21:15:15 +03:00
|
|
|
const accountId = this.message.account_id || this.message.user.id
|
|
|
|
|
|
|
|
|
|
return this.$store.getters.findUser(accountId)
|
2026-07-07 20:44:13 +03:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
isCurrentUser() {
|
2026-07-07 21:15:15 +03:00
|
|
|
return this.author.id === this.currentUser.id
|
2020-05-07 16:10:53 +03:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
message() {
|
2026-07-07 21:15:15 +03:00
|
|
|
return this.isMessage ? this.chatItem.data : null
|
2020-05-07 16:10:53 +03:00
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
isMessage() {
|
2026-07-07 20:44:13 +03:00
|
|
|
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
|
|
|
},
|
2026-07-22 21:38:49 +03:00
|
|
|
isBrokenReply() {
|
|
|
|
|
if (!this.previousItem) return false
|
|
|
|
|
return !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-07-22 16:03:48 +03:00
|
|
|
replyToName() {
|
|
|
|
|
if (this.message.in_reply_to_screen_name) {
|
|
|
|
|
return this.message.in_reply_to_screen_name
|
|
|
|
|
} else {
|
|
|
|
|
const user = this.$store.getters.findUser(
|
|
|
|
|
this.status.in_reply_to_user_id,
|
|
|
|
|
)
|
|
|
|
|
return user && user.screen_name_ui
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
replyProfileLink() {
|
|
|
|
|
if (this.isCustomReply) {
|
|
|
|
|
const user = this.$store.getters.findUser(
|
|
|
|
|
this.message.in_reply_to_user_id,
|
|
|
|
|
)
|
|
|
|
|
// FIXME Why user not found sometimes???
|
|
|
|
|
return user ? user.statusnet_profile_url : 'NOT_FOUND'
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-01-06 16:22:52 +02:00
|
|
|
messageForStatusContent() {
|
2020-05-07 16:10:53 +03:00
|
|
|
return {
|
|
|
|
|
summary: '',
|
2021-06-07 19:50:26 +03:00
|
|
|
emojis: this.message.emojis,
|
2026-07-07 21:15:15 +03:00
|
|
|
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
|
|
|
|
|
},
|
2026-07-22 16:03:48 +03:00
|
|
|
classnames() {
|
|
|
|
|
return {
|
|
|
|
|
'-outgoing': this.isCurrentUser,
|
|
|
|
|
'-incoming': !this.isCurrentUser,
|
|
|
|
|
'-pending': this.message.pending,
|
|
|
|
|
'-focused': this.focused,
|
|
|
|
|
}
|
|
|
|
|
},
|
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,
|
2026-01-29 00:49:26 +02:00
|
|
|
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 }
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-03-24 21:42:22 +02:00
|
|
|
...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,
|
2026-07-07 20:44:13 +03:00
|
|
|
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-07-21 23:22:34 +03:00
|
|
|
visibilityLocalized() {
|
|
|
|
|
return this.$i18n.t('general.scope_in_timeline.' + this.status.visibility)
|
|
|
|
|
},
|
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', {
|
2026-07-07 20:44:13 +03:00
|
|
|
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
|