diff --git a/src/components/Chat.vue b/src/components/Chat.vue index 6f294a2..7cbb7c3 100644 --- a/src/components/Chat.vue +++ b/src/components/Chat.vue @@ -358,6 +358,7 @@ import AudioLayout from "./AudioLayout.vue"; import FileDropLayout from "./file_mode/FileDropLayout"; import { requestNotificationAndServiceWorker, windowNotificationPermission, notificationCount } from "../plugins/notificationAndServiceWorker.js" import logoMixin from "./logoMixin"; +import roomTypeMixin from "./roomTypeMixin"; const sizeOf = require("image-size"); const dataUriToBuffer = require("data-uri-to-buffer"); @@ -393,7 +394,7 @@ ScrollPosition.prototype.prepareFor = function (direction) { export default { name: "Chat", - mixins: [chatMixin, logoMixin], + mixins: [chatMixin, logoMixin, roomTypeMixin], components: { ChatHeader, MessageOperations, @@ -652,13 +653,13 @@ export default { useVoiceMode: { get: function () { if (!this.$config.experimental_voice_mode) return false; - return util.roomDisplayType(this.room) === ROOM_TYPE_VOICE_MODE; + return (util.roomDisplayTypeOverride(this.room) || this.roomDisplayType) === ROOM_TYPE_VOICE_MODE; }, }, useFileModeNonAdmin: { get: function() { if (!this.$config.experimental_file_mode) return false; - return util.roomDisplayType(this.room) === ROOM_TYPE_FILE_MODE && !this.canCreatePoll; // TODO - Check user or admin + return (util.roomDisplayTypeOverride(this.room) || this.roomDisplayType) === ROOM_TYPE_FILE_MODE && !this.canCreatePoll; // TODO - Check user or admin } }, diff --git a/src/components/RoomInfo.vue b/src/components/RoomInfo.vue index 0468e81..8fc0fa3 100644 --- a/src/components/RoomInfo.vue +++ b/src/components/RoomInfo.vue @@ -138,9 +138,9 @@ - +
{{ $t("room_info.experimental_features") }}
- +
{{ $t('room_info.room_type') }}
@@ -257,7 +257,7 @@ import CopyLink from "../components/CopyLink.vue" import RoomTypeSelector from "./RoomTypeSelector.vue"; import roomInfoMixin from "./roomInfoMixin"; import roomTypeMixin from "./roomTypeMixin"; -import util, { ROOM_TYPE_DEFAULT, ROOM_TYPE_FILE_MODE, ROOM_TYPE_VOICE_MODE } from "../plugins/utils"; +import util, { STATE_EVENT_ROOM_TYPE } from "../plugins/utils"; export default { name: "RoomInfo", @@ -337,25 +337,29 @@ export default { roomType: { get: function () { - if (this.room && this.room.tags) { - let options = this.room.tags["ui_options"] || {} - if (options["voice_mode"]) { - return ROOM_TYPE_VOICE_MODE; - } else if (options["file_mode"]) { - return ROOM_TYPE_FILE_MODE; - } - } - return ROOM_TYPE_DEFAULT; + // if (this.room && this.room.tags) { + // let options = this.room.tags["ui_options"] || {} + // if (options["voice_mode"]) { + // return ROOM_TYPE_VOICE_MODE; + // } else if (options["file_mode"]) { + // return ROOM_TYPE_FILE_MODE; + // } + // } + // return ROOM_TYPE_DEFAULT; + return util.roomDisplayTypeOverride(this.room) || this.roomDisplayType; }, set: function (roomType) { if (this.room) { - let tags = this.room.tags || {}; - let options = tags["ui_options"] || {} - options["voice_mode"] = (roomType == ROOM_TYPE_VOICE_MODE ? 1 : 0); - options["file_mode"] = (roomType == ROOM_TYPE_FILE_MODE ? 1 : 0); - tags["ui_options"] = options; - this.room.tags = tags; - this.$matrix.matrixClient.setRoomTag(this.room.roomId, "ui_options", options); + // let tags = this.room.tags || {}; + // let options = tags["ui_options"] || {} + // options["voice_mode"] = (roomType == ROOM_TYPE_VOICE_MODE ? 1 : 0); + // options["file_mode"] = (roomType == ROOM_TYPE_FILE_MODE ? 1 : 0); + // tags["ui_options"] = options; + // this.room.tags = tags; + // this.$matrix.matrixClient.setRoomTag(this.room.roomId, "ui_options", options); + if (this.iAmAdmin()) { + this.$matrix.matrixClient.sendStateEvent(this.room.roomId, STATE_EVENT_ROOM_TYPE, { type: roomType }); + } } }, }, @@ -539,6 +543,12 @@ export default { } return false; }, + iAmAdmin() { + if (this.room) { + return this.room.currentState && this.room.currentState.maySendStateEvent("m.room.power_levels", this.$matrix.currentUserId); + } + return false; + }, // TODO - following power level comparisons assume that default power levels are used in the room! isAdmin(member) { return member.powerLevelNorm > 50; diff --git a/src/components/file_mode/FileDropLayout.vue b/src/components/file_mode/FileDropLayout.vue index a1b7d12..02c9806 100644 --- a/src/components/file_mode/FileDropLayout.vue +++ b/src/components/file_mode/FileDropLayout.vue @@ -225,7 +225,7 @@ export default { id: attachment.name, status: this.statuses.INITIAL, statusDate: Date.now, - attachment: attachment, + attachment: attachment.actualFile || attachment, progress: 0, randomRotation: 0, randomTranslationX: 0, diff --git a/src/components/roomInfoMixin.js b/src/components/roomInfoMixin.js index f4c3657..518e57d 100644 --- a/src/components/roomInfoMixin.js +++ b/src/components/roomInfoMixin.js @@ -1,6 +1,8 @@ import utils from "../plugins/utils"; +import roomTypeMixin from "./roomTypeMixin"; export default { + mixins: [roomTypeMixin], data() { return { roomJoinRule: null, @@ -59,7 +61,7 @@ export default { publicRoomLink() { if (this.room && this.roomJoinRule == "public") { return this.$router.getRoomLink( - this.room.getCanonicalAlias(), this.room.roomId, this.room.name, utils.roomDisplayTypeToQueryParam(this.room) + this.room.getCanonicalAlias(), this.room.roomId, this.room.name, utils.roomDisplayTypeToQueryParam(this.room, this.roomDisplayType) ); } return null; diff --git a/src/components/roomTypeMixin.js b/src/components/roomTypeMixin.js index 57ac6df..24cef13 100644 --- a/src/components/roomTypeMixin.js +++ b/src/components/roomTypeMixin.js @@ -1,6 +1,47 @@ -import { ROOM_TYPE_VOICE_MODE, ROOM_TYPE_FILE_MODE, ROOM_TYPE_DEFAULT } from "../plugins/utils"; +import { ROOM_TYPE_VOICE_MODE, ROOM_TYPE_FILE_MODE, ROOM_TYPE_DEFAULT, STATE_EVENT_ROOM_TYPE } from "../plugins/utils"; export default { + data() { + return { + roomDisplayType: ROOM_TYPE_DEFAULT, + }; + }, + mounted() { + this.$matrix.on("Room.timeline", this.onRoomTypeMixinEvent); + }, + destroyed() { + this.$matrix.off("Room.timeline", this.onRoomTypeMixinEvent); + }, + watch: { + room: { + immediate: true, + handler(newVal) { + if (newVal) { + this.onRoomTypeMixinTypeEvent(newVal.currentState.getStateEvents(STATE_EVENT_ROOM_TYPE, "") || newVal.currentState.getStateEvents("m.room.create", "")); + } else { + this.roomDisplayType = ROOM_TYPE_DEFAULT; + } + }, + }, + }, + methods: { + onRoomTypeMixinEvent(e) { + if (this.room && this.room.roomId == e.getRoomId() && e && e.getType() == STATE_EVENT_ROOM_TYPE) { + this.onRoomTypeMixinTypeEvent(e); + } + }, + onRoomTypeMixinTypeEvent(e) { + if (e) { + const roomType = e.getContent().type; + // Validate value, or return default + if ([ROOM_TYPE_FILE_MODE, ROOM_TYPE_VOICE_MODE].includes(roomType)) { + this.roomDisplayType = roomType; + } else { + this.roomDisplayType = ROOM_TYPE_DEFAULT; + } + } + }, + }, computed: { availableRoomTypes() { let types = [{ title: this.$t("room_info.room_type_default"), description: "", value: ROOM_TYPE_DEFAULT }]; diff --git a/src/plugins/utils.js b/src/plugins/utils.js index 803148a..4aa58d4 100644 --- a/src/plugins/utils.js +++ b/src/plugins/utils.js @@ -7,6 +7,8 @@ export const ROOM_TYPE_DEFAULT = "im.keanu.room_type_default"; export const ROOM_TYPE_VOICE_MODE = "im.keanu.room_type_voice"; export const ROOM_TYPE_FILE_MODE = "im.keanu.room_type_file"; +export const STATE_EVENT_ROOM_TYPE = "im.keanu.room_type"; + const sizeOf = require("image-size"); var dayjs = require('dayjs'); @@ -482,19 +484,19 @@ class Util { /** * Return what "mode" to use for the given room. * - * The default value is given by the room itself. If the "type" of the - * room is set to 'im.keanu.room_type_voice' then we default to voice mode, - * else if set to 'im.keanu.room_type_file' we default to file mode. - * The user can then override this default by changing the "room type" - * in room settings (it will be persisted as a user specific tag on the room) + * The default value is given by the room itself (as state events, see roomTypeMixin). + * This method just returns if the user has overridden this in room settings (this + * fact will be persisted as a user specific tag on the room). Note: currently override + * is disabled in the UI... */ - roomDisplayType(roomOrNull) { + roomDisplayTypeOverride(roomOrNull) { if (roomOrNull) { const room = roomOrNull; // Have we changed our local view mode of this room? const tags = room.tags; if (tags && tags["ui_options"]) { + console.error("We have a tag!"); if (tags["ui_options"]["voice_mode"] === 1) { return ROOM_TYPE_VOICE_MODE; } else if (tags["ui_options"]["file_mode"] === 1) { @@ -504,30 +506,16 @@ class Util { return ROOM_TYPE_DEFAULT; } } - - // Was the room created with a voice mode type? - const createEvent = room.currentState.getStateEvents( - "m.room.create", - "" - ); - if (createEvent) { - const roomType = createEvent.getContent().type; - - // Validate value, or return default - if ([ROOM_TYPE_FILE_MODE, ROOM_TYPE_VOICE_MODE].includes(roomType)) { - return roomType; - } - } } - return ROOM_TYPE_DEFAULT; + return null; } /** * Return the room type for the current room * @param {*} roomOrNull */ - roomDisplayTypeToQueryParam(roomOrNull) { - const roomType = this.roomDisplayType(roomOrNull); + roomDisplayTypeToQueryParam(roomOrNull, roomDisplayType) { + const roomType = this.roomDisplayTypeOverride(roomOrNull) || roomDisplayType; if (roomType === ROOM_TYPE_FILE_MODE) { // Send "file" here, so the receiver of the invite link knows to display the "file drop" join page // instead of the standard one.