Only allow admins to change room mode
This commit is contained in:
parent
31b7c4ed26
commit
cfc14f05a0
6 changed files with 90 additions and 48 deletions
|
|
@ -358,6 +358,7 @@ import AudioLayout from "./AudioLayout.vue";
|
||||||
import FileDropLayout from "./file_mode/FileDropLayout";
|
import FileDropLayout from "./file_mode/FileDropLayout";
|
||||||
import { requestNotificationAndServiceWorker, windowNotificationPermission, notificationCount } from "../plugins/notificationAndServiceWorker.js"
|
import { requestNotificationAndServiceWorker, windowNotificationPermission, notificationCount } from "../plugins/notificationAndServiceWorker.js"
|
||||||
import logoMixin from "./logoMixin";
|
import logoMixin from "./logoMixin";
|
||||||
|
import roomTypeMixin from "./roomTypeMixin";
|
||||||
|
|
||||||
const sizeOf = require("image-size");
|
const sizeOf = require("image-size");
|
||||||
const dataUriToBuffer = require("data-uri-to-buffer");
|
const dataUriToBuffer = require("data-uri-to-buffer");
|
||||||
|
|
@ -393,7 +394,7 @@ ScrollPosition.prototype.prepareFor = function (direction) {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Chat",
|
name: "Chat",
|
||||||
mixins: [chatMixin, logoMixin],
|
mixins: [chatMixin, logoMixin, roomTypeMixin],
|
||||||
components: {
|
components: {
|
||||||
ChatHeader,
|
ChatHeader,
|
||||||
MessageOperations,
|
MessageOperations,
|
||||||
|
|
@ -652,13 +653,13 @@ export default {
|
||||||
useVoiceMode: {
|
useVoiceMode: {
|
||||||
get: function () {
|
get: function () {
|
||||||
if (!this.$config.experimental_voice_mode) return false;
|
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: {
|
useFileModeNonAdmin: {
|
||||||
get: function() {
|
get: function() {
|
||||||
if (!this.$config.experimental_file_mode) return false;
|
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
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,9 +138,9 @@
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<v-card class="account ma-3" flat v-if="availableRoomTypes.length > 1 || canChangeReadOnly()">
|
<v-card class="account ma-3" flat v-if="(iAmAdmin() && availableRoomTypes.length > 1) || canChangeReadOnly()">
|
||||||
<v-card-title class="h2 with-right-label"><div>{{ $t("room_info.experimental_features") }}</div><div></div></v-card-title>
|
<v-card-title class="h2 with-right-label"><div>{{ $t("room_info.experimental_features") }}</div><div></div></v-card-title>
|
||||||
<v-card-text class="with-right-label" v-if="availableRoomTypes.length > 1">
|
<v-card-text class="with-right-label" v-if="iAmAdmin() && availableRoomTypes.length > 1">
|
||||||
<div>
|
<div>
|
||||||
<div class="option-title">{{ $t('room_info.room_type') }}</div>
|
<div class="option-title">{{ $t('room_info.room_type') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -257,7 +257,7 @@ import CopyLink from "../components/CopyLink.vue"
|
||||||
import RoomTypeSelector from "./RoomTypeSelector.vue";
|
import RoomTypeSelector from "./RoomTypeSelector.vue";
|
||||||
import roomInfoMixin from "./roomInfoMixin";
|
import roomInfoMixin from "./roomInfoMixin";
|
||||||
import roomTypeMixin from "./roomTypeMixin";
|
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 {
|
export default {
|
||||||
name: "RoomInfo",
|
name: "RoomInfo",
|
||||||
|
|
@ -337,25 +337,29 @@ export default {
|
||||||
|
|
||||||
roomType: {
|
roomType: {
|
||||||
get: function () {
|
get: function () {
|
||||||
if (this.room && this.room.tags) {
|
// if (this.room && this.room.tags) {
|
||||||
let options = this.room.tags["ui_options"] || {}
|
// let options = this.room.tags["ui_options"] || {}
|
||||||
if (options["voice_mode"]) {
|
// if (options["voice_mode"]) {
|
||||||
return ROOM_TYPE_VOICE_MODE;
|
// return ROOM_TYPE_VOICE_MODE;
|
||||||
} else if (options["file_mode"]) {
|
// } else if (options["file_mode"]) {
|
||||||
return ROOM_TYPE_FILE_MODE;
|
// return ROOM_TYPE_FILE_MODE;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return ROOM_TYPE_DEFAULT;
|
// return ROOM_TYPE_DEFAULT;
|
||||||
|
return util.roomDisplayTypeOverride(this.room) || this.roomDisplayType;
|
||||||
},
|
},
|
||||||
set: function (roomType) {
|
set: function (roomType) {
|
||||||
if (this.room) {
|
if (this.room) {
|
||||||
let tags = this.room.tags || {};
|
// let tags = this.room.tags || {};
|
||||||
let options = tags["ui_options"] || {}
|
// let options = tags["ui_options"] || {}
|
||||||
options["voice_mode"] = (roomType == ROOM_TYPE_VOICE_MODE ? 1 : 0);
|
// options["voice_mode"] = (roomType == ROOM_TYPE_VOICE_MODE ? 1 : 0);
|
||||||
options["file_mode"] = (roomType == ROOM_TYPE_FILE_MODE ? 1 : 0);
|
// options["file_mode"] = (roomType == ROOM_TYPE_FILE_MODE ? 1 : 0);
|
||||||
tags["ui_options"] = options;
|
// tags["ui_options"] = options;
|
||||||
this.room.tags = tags;
|
// this.room.tags = tags;
|
||||||
this.$matrix.matrixClient.setRoomTag(this.room.roomId, "ui_options", options);
|
// 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;
|
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!
|
// TODO - following power level comparisons assume that default power levels are used in the room!
|
||||||
isAdmin(member) {
|
isAdmin(member) {
|
||||||
return member.powerLevelNorm > 50;
|
return member.powerLevelNorm > 50;
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ export default {
|
||||||
id: attachment.name,
|
id: attachment.name,
|
||||||
status: this.statuses.INITIAL,
|
status: this.statuses.INITIAL,
|
||||||
statusDate: Date.now,
|
statusDate: Date.now,
|
||||||
attachment: attachment,
|
attachment: attachment.actualFile || attachment,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
randomRotation: 0,
|
randomRotation: 0,
|
||||||
randomTranslationX: 0,
|
randomTranslationX: 0,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import utils from "../plugins/utils";
|
import utils from "../plugins/utils";
|
||||||
|
import roomTypeMixin from "./roomTypeMixin";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [roomTypeMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
roomJoinRule: null,
|
roomJoinRule: null,
|
||||||
|
|
@ -59,7 +61,7 @@ export default {
|
||||||
publicRoomLink() {
|
publicRoomLink() {
|
||||||
if (this.room && this.roomJoinRule == "public") {
|
if (this.room && this.roomJoinRule == "public") {
|
||||||
return this.$router.getRoomLink(
|
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;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
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: {
|
computed: {
|
||||||
availableRoomTypes() {
|
availableRoomTypes() {
|
||||||
let types = [{ title: this.$t("room_info.room_type_default"), description: "", value: ROOM_TYPE_DEFAULT }];
|
let types = [{ title: this.$t("room_info.room_type_default"), description: "", value: ROOM_TYPE_DEFAULT }];
|
||||||
|
|
|
||||||
|
|
@ -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_VOICE_MODE = "im.keanu.room_type_voice";
|
||||||
export const ROOM_TYPE_FILE_MODE = "im.keanu.room_type_file";
|
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");
|
const sizeOf = require("image-size");
|
||||||
|
|
||||||
var dayjs = require('dayjs');
|
var dayjs = require('dayjs');
|
||||||
|
|
@ -482,19 +484,19 @@ class Util {
|
||||||
/**
|
/**
|
||||||
* Return what "mode" to use for the given room.
|
* Return what "mode" to use for the given room.
|
||||||
*
|
*
|
||||||
* The default value is given by the room itself. If the "type" of the
|
* The default value is given by the room itself (as state events, see roomTypeMixin).
|
||||||
* room is set to 'im.keanu.room_type_voice' then we default to voice mode,
|
* This method just returns if the user has overridden this in room settings (this
|
||||||
* else if set to 'im.keanu.room_type_file' we default to file mode.
|
* fact will be persisted as a user specific tag on the room). Note: currently override
|
||||||
* The user can then override this default by changing the "room type"
|
* is disabled in the UI...
|
||||||
* in room settings (it will be persisted as a user specific tag on the room)
|
|
||||||
*/
|
*/
|
||||||
roomDisplayType(roomOrNull) {
|
roomDisplayTypeOverride(roomOrNull) {
|
||||||
if (roomOrNull) {
|
if (roomOrNull) {
|
||||||
const room = roomOrNull;
|
const room = roomOrNull;
|
||||||
|
|
||||||
// Have we changed our local view mode of this room?
|
// Have we changed our local view mode of this room?
|
||||||
const tags = room.tags;
|
const tags = room.tags;
|
||||||
if (tags && tags["ui_options"]) {
|
if (tags && tags["ui_options"]) {
|
||||||
|
console.error("We have a tag!");
|
||||||
if (tags["ui_options"]["voice_mode"] === 1) {
|
if (tags["ui_options"]["voice_mode"] === 1) {
|
||||||
return ROOM_TYPE_VOICE_MODE;
|
return ROOM_TYPE_VOICE_MODE;
|
||||||
} else if (tags["ui_options"]["file_mode"] === 1) {
|
} else if (tags["ui_options"]["file_mode"] === 1) {
|
||||||
|
|
@ -504,30 +506,16 @@ class Util {
|
||||||
return ROOM_TYPE_DEFAULT;
|
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
|
* Return the room type for the current room
|
||||||
* @param {*} roomOrNull
|
* @param {*} roomOrNull
|
||||||
*/
|
*/
|
||||||
roomDisplayTypeToQueryParam(roomOrNull) {
|
roomDisplayTypeToQueryParam(roomOrNull, roomDisplayType) {
|
||||||
const roomType = this.roomDisplayType(roomOrNull);
|
const roomType = this.roomDisplayTypeOverride(roomOrNull) || roomDisplayType;
|
||||||
if (roomType === ROOM_TYPE_FILE_MODE) {
|
if (roomType === ROOM_TYPE_FILE_MODE) {
|
||||||
// Send "file" here, so the receiver of the invite link knows to display the "file drop" join page
|
// Send "file" here, so the receiver of the invite link knows to display the "file drop" join page
|
||||||
// instead of the standard one.
|
// instead of the standard one.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue