import { markRaw } from "vue"; import util, { ROOM_TYPE_CHANNEL, STATE_EVENT_ROOM_DELETION_NOTICE } from "../plugins/utils"; import MessageIncomingText from "./messages/MessageIncomingText"; import MessageIncomingFile from "./messages/MessageIncomingFile"; import MessageIncomingImage from "./messages/MessageIncomingImage.vue"; import MessageIncomingAudio from "./messages/MessageIncomingAudio.vue"; import MessageIncomingVideo from "./messages/MessageIncomingVideo.vue"; import MessageIncomingSticker from "./messages/MessageIncomingSticker.vue"; import MessageIncomingPoll from "./messages/MessageIncomingPoll.vue"; import MessageIncomingThread from "./messages/MessageIncomingThread.vue"; import MessageOutgoingText from "./messages/MessageOutgoingText"; import MessageOutgoingFile from "./messages/MessageOutgoingFile"; import MessageOutgoingImage from "./messages/MessageOutgoingImage.vue"; import MessageOutgoingAudio from "./messages/MessageOutgoingAudio.vue"; import MessageOutgoingVideo from "./messages/MessageOutgoingVideo.vue"; import MessageOutgoingSticker from "./messages/MessageOutgoingSticker.vue"; import MessageOutgoingPoll from "./messages/MessageOutgoingPoll.vue"; import MessageOutgoingThread from "./messages/MessageOutgoingThread.vue"; import MessageIncomingImageExport from "./messages/export/MessageIncomingImageExport"; import MessageIncomingAudioExport from "./messages/export/MessageIncomingAudioExport"; import MessageIncomingVideoExport from "./messages/export/MessageIncomingVideoExport"; import MessageIncomingThreadExport from "./messages/export/MessageIncomingThreadExport"; import MessageIncomingFileExport from "./messages/export/MessageIncomingFileExport"; import MessageOutgoingImageExport from "./messages/export/MessageOutgoingImageExport"; import MessageOutgoingAudioExport from "./messages/export/MessageOutgoingAudioExport"; import MessageOutgoingVideoExport from "./messages/export/MessageOutgoingVideoExport"; import MessageOutgoingThreadExport from "./messages/export/MessageOutgoingThreadExport"; import MessageOutgoingFileExport from "./messages/export/MessageOutgoingFileExport"; import ContactJoin from "./messages/ContactJoin.vue"; import ContactLeave from "./messages/ContactLeave.vue"; import ContactInvited from "./messages/ContactInvited.vue"; import ContactKicked from "./messages/ContactKicked.vue"; import ContactBanned from "./messages/ContactBanned.vue"; import ContactChanged from "./messages/ContactChanged.vue"; import RoomCreated from "./messages/RoomCreated.vue"; import RoomAliased from "./messages/RoomAliased.vue"; import RoomNameChanged from "./messages/RoomNameChanged.vue"; import RoomTopicChanged from "./messages/RoomTopicChanged.vue"; import RoomAvatarChanged from "./messages/RoomAvatarChanged.vue"; import RoomHistoryVisibility from "./messages/RoomHistoryVisibility.vue"; import MessageOperations from "./messages/MessageOperations.vue"; import ChatHeader from "./ChatHeader"; import VoiceRecorder from "./VoiceRecorder"; import RoomInfoBottomSheet from "./RoomInfoBottomSheet"; import WelcomeHeaderRoom from "./welcome_headers/WelcomeHeaderRoom.vue"; import MessageOperationsBottomSheet from "./MessageOperationsBottomSheet"; import stickers from "../plugins/stickers"; import StickerPickerBottomSheet from "./StickerPickerBottomSheet"; import BottomSheet from "./BottomSheet.vue"; import CreatePollDialog from "./CreatePollDialog.vue"; import RoomJoinRules from "./messages/RoomJoinRules.vue"; import RoomPowerLevelsChanged from "./messages/RoomPowerLevelsChanged.vue"; import RoomGuestAccessChanged from "./messages/RoomGuestAccessChanged.vue"; import RoomEncrypted from "./messages/RoomEncrypted.vue"; import RoomDeletionNotice from "./messages/RoomDeletionNotice.vue"; import DebugEvent from "./messages/DebugEvent.vue"; import ReadMarker from "./messages/ReadMarker.vue"; import roomDisplayOptionsMixin from "./roomDisplayOptionsMixin"; import roomTypeMixin from "./roomTypeMixin"; export const ROOM_READ_MARKER_EVENT_PLACEHOLDER = { getId: () => "ROOM_READ_MARKER", getTs: () => Date.now() }; export default { mixins: [roomDisplayOptionsMixin, roomTypeMixin], components: { ChatHeader, MessageIncomingText, MessageIncomingFile, MessageIncomingImage, MessageIncomingAudio, MessageIncomingVideo, MessageIncomingSticker, MessageIncomingThread, MessageOutgoingText, MessageOutgoingFile, MessageOutgoingImage, MessageOutgoingAudio, MessageOutgoingVideo, MessageOutgoingSticker, MessageOutgoingThread, MessageOutgoingPoll, ContactJoin, ContactLeave, ContactInvited, ContactKicked, ContactBanned, ContactChanged, RoomCreated, RoomAliased, RoomNameChanged, RoomTopicChanged, RoomAvatarChanged, RoomHistoryVisibility, RoomJoinRules, RoomPowerLevelsChanged, RoomGuestAccessChanged, RoomEncrypted, RoomDeletionNotice, DebugEvent, MessageOperations, VoiceRecorder, RoomInfoBottomSheet, WelcomeHeaderRoom, MessageOperationsBottomSheet, StickerPickerBottomSheet, BottomSheet, CreatePollDialog, ReadMarker, }, computed: { debugging() { return false; //(window.location.host || "").startsWith("localhost"); }, }, methods: { showDayMarkerBeforeEvent(event) { const idx = this.events.indexOf(event); if (idx <= 0) { return true; } const previousEvent = this.events[idx - 1]; return util.dayDiff(previousEvent.getTs(), event.getTs()) > 0; }, dayForEvent(event) { let dayDiff = util.dayDiffToday(event.getTs()); if (dayDiff < 7) { return this.$t("message.time_ago", dayDiff); } else { return util.formatDay(event.getTs()); } }, dateForEvent(event) { return util.formatDay(event.getTs()); }, componentForEvent(event, isForExport = false) { let component = this.componentForEventInternal(event, isForExport); if (component) { return markRaw(component); } return component; }, componentForEventInternal(event, isForExport = false) { const isChannel = this.roomDisplayType === ROOM_TYPE_CHANNEL; if (event === ROOM_READ_MARKER_EVENT_PLACEHOLDER) { return ReadMarker; } switch (event.getType()) { case "m.room.member": if (isChannel) break; if (event.getContent().membership == "join") { if (event.getPrevContent() && event.getPrevContent().membership == "join") { // We we already joined, so this must be a display name and/or avatar update! return ContactChanged; } else { if (event.getSender() == this.$matrix.currentUserId && !this.showOwnJoins) { return null; } return ContactJoin; } } else if (event.getContent().membership == "leave") { if ((event.getPrevContent() || {}).membership == "join" && event.getStateKey() != event.getSender()) { return ContactKicked; } if ((event.getPrevContent() || {}).membership == "knock") { return null; // A knock that was rejected } return ContactLeave; } else if (this.showAllStatusMessages) { if (event.getContent().membership == "invite") { return ContactInvited; } else if (event.getContent().membership == "ban") { return ContactBanned; } } break; case "m.room.message": if (event.getSender() != this.$matrix.currentUserId) { if (event.isRedacted()) { // Redacted thread, show as text (and hide all media)! if (event.getUnsigned().redacted_because.content.reason == "redactedThread") { return MessageIncomingText; } return null; } if (event.isMxThread) { // Incoming thread, e.g. a file drop! return isForExport ? MessageIncomingThreadExport : MessageIncomingThread; } if (event.getContent().msgtype == "m.image") { // For SVG, make downloadable if ( event.getContent().info && event.getContent().info.mimetype && event.getContent().info.mimetype.startsWith("image/svg") ) { if (isForExport) { return MessageIncomingFileExport; } return MessageIncomingFile; } if (isForExport) { return MessageIncomingImageExport; } return MessageIncomingImage; } else if (event.getContent().msgtype == "m.audio") { if (isForExport) { return MessageIncomingAudioExport; } return MessageIncomingAudio; } else if (event.getContent().msgtype == "m.video") { if (isForExport) { return MessageIncomingVideoExport; } return MessageIncomingVideo; } else if (event.getContent().msgtype == "m.file") { if (isForExport) { return MessageIncomingFileExport; } return MessageIncomingFile; } else if (stickers.isStickerShortcode(event.getContent().body)) { return MessageIncomingSticker; } return MessageIncomingText; } else { if (event.isRedacted()) { // Redacted thread, show as text (and hide all media)! if (event.getUnsigned().redacted_because.content.reason == "redactedThread") { return MessageOutgoingText; } return null; } if (event.isMxThread) { // Outgoing thread return isForExport ? MessageOutgoingThreadExport : MessageOutgoingThread; } if (event.getContent().msgtype == "m.image") { // For SVG, make downloadable if ( event.getContent().info && event.getContent().info.mimetype && event.getContent().info.mimetype.startsWith("image/svg") ) { return MessageOutgoingImage; } if (isForExport) { return MessageOutgoingImageExport; } return MessageOutgoingImage; } else if (event.getContent().msgtype == "m.audio") { if (isForExport) { return MessageOutgoingAudioExport; } return MessageOutgoingAudio; } else if (event.getContent().msgtype == "m.video") { if (isForExport) { return MessageOutgoingVideoExport; } return MessageOutgoingVideo; } else if (event.getContent().msgtype == "m.file") { if (isForExport) { return MessageOutgoingFileExport; } return MessageOutgoingFile; } else if (stickers.isStickerShortcode(event.getContent().body)) { return MessageOutgoingSticker; } return MessageOutgoingText; } case "m.room.create": if (this.showAllStatusMessages) { return RoomCreated; } break; case "m.room.canonical_alias": if (this.showAllStatusMessages) { return RoomAliased; } break; case "m.room.name": if (this.showAllStatusMessages) { return RoomNameChanged; } break; case "m.room.topic": if (this.showAllStatusMessages) { return RoomTopicChanged; } break; case "m.room.avatar": if (this.showAllStatusMessages) { return RoomAvatarChanged; } break; case "m.room.history_visibility": if (this.showAllStatusMessages) { return RoomHistoryVisibility; } break; case "m.room.join_rules": if (this.showAllStatusMessages) { return RoomJoinRules; } break; case "m.room.power_levels": if (this.showAllStatusMessages) { return RoomPowerLevelsChanged; } break; case "m.room.guest_access": if (this.showAllStatusMessages) { return RoomGuestAccessChanged; } break; case "m.room.encryption": if (this.showAllStatusMessages) { return RoomEncrypted; } break; case "m.poll.start": case "org.matrix.msc3381.poll.start": if (event.getSender() != this.$matrix.currentUserId) { return MessageIncomingPoll; } else { return MessageOutgoingPoll; } case STATE_EVENT_ROOM_DELETION_NOTICE: { // Custom event for notice 30 seconds before a room is deleted/purged. const deletionNotices = this.room.currentState.getStateEvents(STATE_EVENT_ROOM_DELETION_NOTICE); if (deletionNotices && deletionNotices.length > 0 && deletionNotices[deletionNotices.length - 1] == event) { // This is the latest/last one. Look at the status flag. Show nothing if it is "cancel". if (event.getContent().status != "cancel") { return RoomDeletionNotice; } } } break; case "m.room.encrypted": if (event.isRedacted()) { // Redacted thread, show as text (and hide all media)! if (event.getUnsigned().redacted_because.content.reason == "redactedThread") { return MessageOutgoingText; } return null; } return event.getSender() != this.$matrix.currentUserId ? MessageIncomingText : MessageOutgoingText; } return this.debugging ? DebugEvent : null; }, }, };