Implement new "read only" room flag

While still maintaining the ability to answer polls and send reactions in channels (when "read only" is false)
This commit is contained in:
N-Pex 2024-04-26 16:44:06 +02:00
parent 1e31b0c24e
commit 371a5069af
10 changed files with 112 additions and 68 deletions

View file

@ -2,12 +2,21 @@ import olm from "@matrix-org/olm/olm";
global.Olm = olm;
import * as sdk from "matrix-js-sdk";
import { TimelineWindow, EventTimeline, EventStatus } from "matrix-js-sdk";
import util, { STATE_EVENT_ROOM_DELETED } from "../plugins/utils";
import util, { STATE_EVENT_ROOM_DELETED, STATE_EVENT_ROOM_TYPE, ROOM_TYPE_CHANNEL, ROOM_TYPE_FILE_MODE, ROOM_TYPE_VOICE_MODE, ROOM_TYPE_DEFAULT } from "../plugins/utils";
import User from "../models/user";
const LocalStorageCryptoStore =
require("matrix-js-sdk/lib/crypto/store/localStorage-crypto-store").LocalStorageCryptoStore;
export const CHANNEL_POWER_LEVELS = {
"m.room.encrypted": 0, // NOTE! Since practically all events in encrypted rooms get sent as "m.room.encrypted" we need to set
// power to 0 here. Otherwise we would not be able to send quick reactions or poll responses...
"m.poll.response": 0,
"org.matrix.msc3381.poll.response": 0,
"m.reaction": 0,
"m.room.redaction": 0,
};
export default {
install(Vue, options) {
if (!options || !options.store) {
@ -37,7 +46,8 @@ export default {
userDisplayName: null,
userAvatar: null,
currentRoom: null,
currentRoomIsReadOnlyForUser: false,
userCanSendMessageInCurrentRoom: true,
userCanSendReactionAndAnswerPollInCurrentRoom: true,
currentRoomBeingPurged: false,
notificationCount: 0,
};
@ -106,9 +116,11 @@ export default {
immediate: true,
handler(room) {
if (room) {
this.currentRoomIsReadOnlyForUser = this.isReadOnlyRoomForUser(room.roomId, this.currentUserId);
this.userCanSendMessageInCurrentRoom = this.userCanSendMessageInRoom(room.roomId, this.currentUserId);
this.userCanSendReactionAndAnswerPollInCurrentRoom = this.userCanSendReactionAndAnswerPollInRoom(room.roomId, this.currentUserId);
} else {
this.currentRoomIsReadOnlyForUser = false;
this.userCanSendMessageInCurrentRoom = true;
this.userCanSendReactionAndAnswerPollInCurrentRoom = true;
}
},
},
@ -388,7 +400,8 @@ export default {
case "m.room.power_levels":
{
if (this.currentRoom && event.getRoomId() == this.currentRoom.roomId) {
this.currentRoomIsReadOnlyForUser = this.isReadOnlyRoomForUser(event.getRoomId(), this.currentUserId);
this.userCanSendMessageInCurrentRoom = this.userCanSendMessageInRoom(event.getRoomId(), this.currentUserId);
this.userCanSendReactionAndAnswerPollInCurrentRoom = this.userCanSendReactionAndAnswerPollInRoom(event.getRoomId(), this.currentUserId);
}
}
break;
@ -673,6 +686,9 @@ export default {
if (room && room.currentState) {
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
if (powerLevelEvent) {
if (this.roomType(roomId) == ROOM_TYPE_CHANNEL) {
return Object.keys(powerLevelEvent.getContent().events).length == 0;
}
return powerLevelEvent.getContent().events_default > 0;
}
}
@ -680,16 +696,6 @@ export default {
return false;
},
isReadOnlyRoomForUser(roomId, userId) {
if (this.matrixClient && roomId && userId) {
const room = this.getRoom(roomId);
if (room && room.currentState) {
return !room.currentState.maySendMessage(userId);
}
}
return false;
},
setReadOnlyRoom(roomId, readOnly) {
if (this.matrixClient && roomId) {
const room = this.getRoom(roomId);
@ -697,13 +703,55 @@ export default {
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
if (powerLevelEvent) {
let content = powerLevelEvent.getContent();
content.events_default = readOnly ? 50 : 0;
if (this.roomType(roomId) == ROOM_TYPE_CHANNEL) {
content.events = readOnly ? {} : CHANNEL_POWER_LEVELS
} else {
content.events_default = readOnly ? 50 : 0;
}
this.matrixClient.sendStateEvent(room.roomId, "m.room.power_levels", content);
}
}
}
},
userCanSendMessageInRoom(roomId, userId) {
if (this.matrixClient && roomId && userId) {
const room = this.getRoom(roomId);
if (room && room.currentState) {
let isAdmin = room.currentState.maySendEvent("m.room.power_levels", this.currentUserId);
return isAdmin || (this.roomType(roomId) != ROOM_TYPE_CHANNEL && !this.isReadOnlyRoom(roomId));
}
}
return true;
},
userCanSendReactionAndAnswerPollInRoom(roomId, userId) {
if (this.matrixClient && roomId && userId) {
const room = this.getRoom(roomId);
if (room && room.currentState) {
let isAdmin = room.currentState.maySendEvent("m.room.power_levels", this.currentUserId);
return isAdmin || !this.isReadOnlyRoom(roomId);
}
}
return true;
},
roomType(roomId) {
if (this.matrixClient && roomId) {
const room = this.getRoom(roomId);
if (room && room.currentState) {
const roomTypeEvent = room.currentState.getStateEvents(STATE_EVENT_ROOM_TYPE, "") || room.currentState.getStateEvents("m.room.create", "");
if (roomTypeEvent) {
const roomType = roomTypeEvent.getContent().type;
if ([ROOM_TYPE_FILE_MODE, ROOM_TYPE_VOICE_MODE, ROOM_TYPE_CHANNEL].includes(roomType)) {
return roomType;
}
}
}
}
return ROOM_TYPE_DEFAULT;
},
/**
* Purge the room with the given id! This means:
* - Make room invite only