keanu-weblite/src/components/chatMixin.js

369 lines
14 KiB
JavaScript
Raw Normal View History

2025-05-06 12:02:56 +02:00
import { markRaw } from "vue";
import util, { ROOM_TYPE_CHANNEL, STATE_EVENT_ROOM_DELETION_NOTICE } from "../plugins/utils";
2022-05-23 15:19:55 +00:00
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";
2023-06-28 12:14:44 +00:00
import MessageIncomingThread from "./messages/MessageIncomingThread.vue";
2022-05-23 15:19:55 +00:00
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";
2022-05-23 15:19:55 +00:00
import MessageIncomingImageExport from "./messages/export/MessageIncomingImageExport";
import MessageIncomingAudioExport from "./messages/export/MessageIncomingAudioExport";
import MessageIncomingVideoExport from "./messages/export/MessageIncomingVideoExport";
2023-11-06 15:28:26 +00:00
import MessageIncomingThreadExport from "./messages/export/MessageIncomingThreadExport";
2023-12-04 11:29:23 +01:00
import MessageIncomingFileExport from "./messages/export/MessageIncomingFileExport";
2022-05-23 15:19:55 +00:00
import MessageOutgoingImageExport from "./messages/export/MessageOutgoingImageExport";
import MessageOutgoingAudioExport from "./messages/export/MessageOutgoingAudioExport";
import MessageOutgoingVideoExport from "./messages/export/MessageOutgoingVideoExport";
2023-11-06 15:28:26 +00:00
import MessageOutgoingThreadExport from "./messages/export/MessageOutgoingThreadExport";
2023-12-04 11:29:23 +01:00
import MessageOutgoingFileExport from "./messages/export/MessageOutgoingFileExport";
2022-05-23 15:19:55 +00:00
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";
2022-05-23 15:19:55 +00:00
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";
2022-05-23 15:19:55 +00:00
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";
2022-05-23 15:19:55 +00:00
2025-05-12 17:15:11 +02:00
export const ROOM_READ_MARKER_EVENT_PLACEHOLDER = { getId: () => "ROOM_READ_MARKER", getTs: () => Date.now() };
2022-05-23 15:19:55 +00:00
export default {
2025-06-09 09:44:37 +02:00
mixins: [roomDisplayOptionsMixin, roomTypeMixin],
2022-05-23 15:19:55 +00:00
components: {
ChatHeader,
MessageIncomingText,
MessageIncomingFile,
MessageIncomingImage,
MessageIncomingAudio,
MessageIncomingVideo,
MessageIncomingSticker,
2023-06-28 12:14:44 +00:00
MessageIncomingThread,
2022-05-23 15:19:55 +00:00
MessageOutgoingText,
MessageOutgoingFile,
MessageOutgoingImage,
MessageOutgoingAudio,
MessageOutgoingVideo,
MessageOutgoingSticker,
MessageOutgoingThread,
2022-05-23 15:19:55 +00:00
MessageOutgoingPoll,
ContactJoin,
ContactLeave,
ContactInvited,
ContactKicked,
ContactBanned,
2022-05-23 15:19:55 +00:00
ContactChanged,
RoomCreated,
RoomAliased,
RoomNameChanged,
RoomTopicChanged,
RoomAvatarChanged,
RoomHistoryVisibility,
RoomJoinRules,
RoomPowerLevelsChanged,
RoomGuestAccessChanged,
RoomEncrypted,
RoomDeletionNotice,
DebugEvent,
MessageOperations,
VoiceRecorder,
RoomInfoBottomSheet,
WelcomeHeaderRoom,
2022-05-23 15:19:55 +00:00
MessageOperationsBottomSheet,
StickerPickerBottomSheet,
BottomSheet,
CreatePollDialog,
2025-06-09 09:44:37 +02:00
ReadMarker,
2022-05-23 15:19:55 +00:00
},
2025-05-14 10:47:21 +02:00
computed: {
debugging() {
return false; //(window.location.host || "").startsWith("localhost");
},
},
2022-05-23 15:19:55 +00:00
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) {
2025-05-06 11:28:47 +02:00
return this.$t("message.time_ago", dayDiff);
2022-05-23 15:19:55 +00:00
} else {
return util.formatDay(event.getTs());
}
},
dateForEvent(event) {
2025-06-09 09:44:37 +02:00
return util.formatDay(event.getTs());
2022-05-23 15:19:55 +00:00
},
2022-11-30 08:16:23 +00:00
2022-05-23 15:19:55 +00:00
componentForEvent(event, isForExport = false) {
2025-05-06 12:02:56 +02:00
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;
}
2022-05-23 15:19:55 +00:00
switch (event.getType()) {
case "m.room.member":
if (isChannel) break;
2022-05-23 15:19:55 +00:00
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;
}
2022-05-23 15:19:55 +00:00
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
}
2022-05-23 15:19:55 +00:00
return ContactLeave;
} else if (this.showAllStatusMessages) {
if (event.getContent().membership == "invite") {
return ContactInvited;
} else if (event.getContent().membership == "ban") {
return ContactBanned;
}
2022-05-23 15:19:55 +00:00
}
break;
case "m.room.message":
if (event.getSender() != this.$matrix.currentUserId) {
2025-06-09 09:44:37 +02:00
if (event.isRedacted()) {
// Redacted thread, show as text (and hide all media)!
if (event.getUnsigned().redacted_because.content.reason == "redactedThread") {
return MessageIncomingText;
2023-06-28 12:14:44 +00:00
}
2025-06-09 09:44:37 +02:00
return null;
}
if (event.isMxThread) {
// Incoming thread, e.g. a file drop!
return isForExport ? MessageIncomingThreadExport : MessageIncomingThread;
}
if (event.getContent().msgtype == "m.image") {
2022-05-23 15:19:55 +00:00
// For SVG, make downloadable
if (
event.getContent().info &&
event.getContent().info.mimetype &&
event.getContent().info.mimetype.startsWith("image/svg")
) {
2023-12-04 11:29:23 +01:00
if (isForExport) {
return MessageIncomingFileExport;
}
2022-05-23 15:19:55 +00:00
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") {
2023-12-04 11:29:23 +01:00
if (isForExport) {
return MessageIncomingFileExport;
}
2022-05-23 15:19:55 +00:00
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
2023-11-06 15:28:26 +00:00
return isForExport ? MessageOutgoingThreadExport : MessageOutgoingThread;
}
2022-05-23 15:19:55 +00:00
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") {
2023-12-04 11:29:23 +01:00
if (isForExport) {
return MessageOutgoingFileExport;
}
2022-05-23 15:19:55 +00:00
return MessageOutgoingFile;
} else if (stickers.isStickerShortcode(event.getContent().body)) {
return MessageOutgoingSticker;
}
return MessageOutgoingText;
}
case "m.room.create":
if (this.showAllStatusMessages) {
return RoomCreated;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.canonical_alias":
if (this.showAllStatusMessages) {
return RoomAliased;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.name":
if (this.showAllStatusMessages) {
return RoomNameChanged;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.topic":
if (this.showAllStatusMessages) {
return RoomTopicChanged;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.avatar":
if (this.showAllStatusMessages) {
return RoomAvatarChanged;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.history_visibility":
if (this.showAllStatusMessages) {
return RoomHistoryVisibility;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.join_rules":
if (this.showAllStatusMessages) {
return RoomJoinRules;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.power_levels":
if (this.showAllStatusMessages) {
return RoomPowerLevelsChanged;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.guest_access":
if (this.showAllStatusMessages) {
return RoomGuestAccessChanged;
}
break;
2022-05-23 15:19:55 +00:00
case "m.room.encryption":
if (this.showAllStatusMessages) {
return RoomEncrypted;
}
break;
2022-05-23 15:19:55 +00:00
case "m.poll.start":
case "org.matrix.msc3381.poll.start":
if (event.getSender() != this.$matrix.currentUserId) {
return MessageIncomingPoll;
} else {
return MessageOutgoingPoll;
}
2025-06-09 09:44:37 +02:00
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;
}
2022-05-23 15:19:55 +00:00
}
}
2022-11-30 08:16:23 +00:00
break;
case "m.room.encrypted":
2025-06-09 09:44:37 +02:00
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;
2022-05-23 15:19:55 +00:00
}
return this.debugging ? DebugEvent : null;
},
},
};