Support room version 12 and the "creator power level"

This commit is contained in:
N-Pex 2025-08-06 12:07:50 +02:00
parent f804e0377b
commit c36deef7e2
13 changed files with 351 additions and 113 deletions

View file

@ -45,6 +45,7 @@
"loading": "Loading {appName}",
"user_kick_and_ban": "Kick out",
"user_make_admin": "Make admin",
"user_revoke_admin": "Revoke admin",
"user_make_moderator": "Make moderator",
"user_revoke_moderator": "Revoke moderator",
"pin": "Pin post",
@ -354,6 +355,7 @@
"version_info": "Powered by Guardian Project. Version: {version}",
"scan_code": "Scan to join the room",
"export_room": "Save chat",
"user_creator": "Creator",
"user_admin": "Administrator",
"user_moderator": "Moderator",
"moderation": "Moderation",
@ -388,6 +390,7 @@
"report_info": "Report this room to service administrators for illegal, abusive or otherwise harmful content",
"report_reason": "Reason",
"confirm_make_admin": "Do you want to make this user an administrator?",
"confirm_revoke_admin": "Do you want to remove administrator rights from this user?",
"confirm_make_moderator": "Do you want to make this user a moderator?",
"confirm_revoke_moderator": "Do you want to remove moderator rights from this user?",
"confirm_ban": "Do you want to kick this user from the room?"

View file

@ -699,7 +699,7 @@ export default {
roomCreatedByUsRecently() {
const createEvent = this.room && this.room.currentState.getStateEvents("m.room.create", "");
if (createEvent) {
const creatorId = createEvent.getContent().creator;
const creatorId = createEvent.getSender();
return (creatorId == this.$matrix.currentUserId && createEvent.getLocalAge() < 5 * 60000 /* 5 minutes */);
}
return false;
@ -1367,6 +1367,24 @@ export default {
},
sendMessage(text) {
//TEMP TEMP TEMP
if (text.startsWith("/version") && this.room && this.room.userMayUpgradeRoom(this.$matrix.currentUserId)) {
this.room.getRecommendedVersion().then((v) => {
console.error("Room version:", this.room.getVersion());
console.error("Recommended:", v);
});
this.$matrix.matrixClient.getCapabilities().then((c) => {
console.error("Capabilities:", c);
});
return;
}
if (text.startsWith("/upgrade ") && this.room && this.room.userMayUpgradeRoom(this.$matrix.currentUserId)) {
const version = text.substring(9);
this.$matrix.matrixClient.upgradeRoom(this.roomId, version).then((r) => {
console.error("Upgrade result", JSON.stringify(r));
})
return;
}
if (text && text.length > 0) {
util
.sendTextMessage(this.$matrix.matrixClient, this.roomId, text, this.editedEvent, this.replyToEvent)

View file

@ -98,7 +98,7 @@ export default {
generateAliasForRoom() {
return true;
},
getRoomCreationOptions() {
getRoomCreationOptions(roomVersion) {
const createRoomOptions = {
visibility: "private", // Not listed!
name: this.roomName,
@ -132,7 +132,9 @@ export default {
// Set power level event. Need to do that here, because we might not have the userId when the options object is created.
const powerLevels = {};
powerLevels[this.$matrix.currentUserId] = 100;
if (roomVersion < 12) {
powerLevels[this.$matrix.currentUserId] = 100;
}
let powerLevelContent = {
users: powerLevels,
events_default: 50,

View file

@ -95,7 +95,7 @@ export default {
generateAliasForRoom() {
return true;
},
getRoomCreationOptions() {
getRoomCreationOptions(roomVersion) {
const createRoomOptions = {
visibility: "private", // Not listed!
name: this.roomName,
@ -142,7 +142,9 @@ export default {
// Set power level event. Need to do that here, because we might not have the userId when the options object is created.
const powerLevels = {};
powerLevels[this.$matrix.currentUserId] = 100;
if (roomVersion < 12) {
powerLevels[this.$matrix.currentUserId] = 100;
}
let powerLevelContent = {
users: powerLevels,
events_default: 0,

View file

@ -277,7 +277,7 @@ export default {
generateAliasForRoom() {
return this.publicRoom;
},
getRoomCreationOptions() {
getRoomCreationOptions(roomVersion) {
var createRoomOptions = {};
if (this.publicRoom) {
createRoomOptions = {
@ -342,7 +342,9 @@ export default {
// Set power level event. Need to do that here, because we might not have the userId when the options object is created.
const powerLevels = {};
powerLevels[this.$matrix.currentUserId] = 100;
if (roomVersion < 12) {
powerLevels[this.$matrix.currentUserId] = 100;
}
let powerLevelContent = {
users: powerLevels,
events_default: 0

View file

@ -217,7 +217,10 @@
})
}}
</span>
<span v-if="isAdmin(member)" class="user-power">
<span v-if="this.room && this.room.getCreator() === member.userId" class="user-power">
{{ $t("room_info.user_creator") }}
</span>
<span v-else-if="isAdmin(member)" class="user-power">
{{ $t("room_info.user_admin") }}
</span>
<span v-else-if="isModerator(member)" class="user-power">
@ -441,18 +444,8 @@ export default {
computed: {
creator() {
if (this.room) {
const createEvent = this.room.currentState.getStateEvents(
"m.room.create",
""
);
if (!createEvent) {
console.warn(
"Room " + this.roomId + " does not have an m.room.create event"
);
return "";
}
const creatorId = createEvent.getContent().creator;
const member = this.room.getMember(creatorId);
const creatorId = this.room.getCreator();
const member = creatorId ? this.room.getMember(creatorId) : undefined;
if (!member) {
return creatorId;
}
@ -540,6 +533,7 @@ export default {
updateMembers() {
if (this.room) {
const creator = this.room.getCreator();
const myUserId = this.$matrix.currentUserId;
this.members = this.room.getJoinedMembers().sort((a, b) => {
// Place ourselves at the top!
@ -549,6 +543,13 @@ export default {
return 1;
}
// Then the creator
if (a.userId === creator) {
return -1;
} else if (b.userId === creator) {
return 1;
}
// Then sort by power level
if (a.powerLevel > b.powerLevel) {
return -1;

View file

@ -53,6 +53,9 @@
<v-btn variant="text" size="x-large" block v-if="activeMember.userId != $matrix.currentUserId && !isAdminComp && canMakeAdminComp" class="start-private-chat clickable d-block text-none justify-start" @click="makeAdmin">
<v-icon start>$vuetify.icons.make_admin</v-icon> {{ $t("menu.user_make_admin") }}
</v-btn>
<v-btn variant="text" size="x-large" block v-if="activeMember.userId != $matrix.currentUserId && isAdminComp && canRevokeAdminComp" class="start-private-chat clickable d-block text-none justify-start" @click="revokeAdmin">
<v-icon start>$vuetify.icons.make_admin</v-icon> {{ $t("menu.user_revoke_admin") }}
</v-btn>
<v-btn variant="text" size="x-large" block v-if="activeMember.userId != $matrix.currentUserId && !isModeratorComp && !isAdminComp && canMakeModeratorComp" class="start-private-chat clickable d-block text-none justify-start" @click="makeModerator">
<v-icon start>$vuetify.icons.make_moderator</v-icon> {{ $t("menu.user_make_moderator") }}
</v-btn>
@ -65,6 +68,7 @@
</v-dialog>
<ConfirmationDialog :message="$t('room_info.confirm_make_admin')" v-model="showConfirmMakeAdmin" v-on:ok="doMakeAdmin" />
<ConfirmationDialog :message="$t('room_info.confirm_revoke_admin')" v-model="showConfirmRevokeAdmin" v-on:ok="doRevokeAdmin" />
<ConfirmationDialog :message="$t('room_info.confirm_make_moderator')" v-model="showConfirmMakeModerator" v-on:ok="doMakeModerator" />
<ConfirmationDialog :message="$t('room_info.confirm_revoke_moderator')" v-model="showConfirmRevokeModerator" v-on:ok="doRevokeModerator" />
<ConfirmationDialog :message="$t('room_info.confirm_ban')" v-model="showConfirmBan" v-on:ok="doBanUser" />
@ -76,6 +80,7 @@ import AuthedImage from "./AuthedImage.vue";
import util from "../plugins/utils";
import RoomDialogBase from "./RoomDialogBase.vue";
import ConfirmationDialog from "./ConfirmationDialog.vue";
import { consoleError } from "vuetify/lib/util/console.mjs";
export default {
name: "UserProfileDialog",
@ -96,12 +101,16 @@ export default {
data() {
return {
showConfirmMakeAdmin: false,
showConfirmRevokeAdmin: false,
showConfirmMakeModerator: false,
showConfirmRevokeModerator: false,
showConfirmBan: false
};
},
computed: {
canRevokeAdminComp () {
return this.canRevokeAdmin(this.activeMember)
},
canRevokeModeratorComp () {
return this.canRevokeModerator(this.activeMember)
},
@ -198,6 +207,19 @@ export default {
}
return false;
},
/**
* Return true if WE can "unmake" the member an administraor (= we are creator of the room)
* @param member
*/
canRevokeAdmin(member) {
if (this.room) {
// TODO - not supposed to parse room versions as int.
const roomVersion = parseInt(this.room.getVersion()?.split(".").reverse()[0] ?? "0");
const myUserId = this.$matrix.currentUserId;
return roomVersion > 11 && this.room.getCreator() === myUserId;
}
return false;
},
/**
* Return true if WE can make the member a moderator
@ -235,6 +257,19 @@ export default {
this.showDialog = false;
}
},
revokeAdmin() {
if (this.room && this.activeMember) {
this.showConfirmRevokeAdmin = true;
this.showDialog = false;
}
},
doRevokeAdmin() {
if (this.room && this.activeMember) {
this.$matrix.revokeAdmin(this.room.roomId, this.activeMember.userId)
this.showDialog = false;
}
},
makeModerator() {
if (this.room && this.activeMember) {
this.showConfirmMakeModerator = true;

View file

@ -88,7 +88,12 @@ export default {
this.preCreateRoom()
.then(() => {
let createRoomOptions = this.getRoomCreationOptions();
return this.$matrix.matrixClient.getCapabilities();
})
.then((caps) => {
const defaultRoomVersion = parseInt(caps["m.room_versions"]?.default ?? "0");
let createRoomOptions = this.getRoomCreationOptions(defaultRoomVersion);
if (this.generateAliasForRoom()) {
// Promise to get a unique alias and use it in room creation options.
//

View file

@ -219,9 +219,16 @@ export default {
updatePermissions() {
if (this.room) {
this.roomJoinRule = this.getRoomJoinRule();
const canChangeAccess =
let canChangeAccess =
this.room.currentState.mayClientSendStateEvent("m.room.join_rules", this.$matrix.matrixClient) &&
this.room.currentState.mayClientSendStateEvent("m.room.guest_access", this.$matrix.matrixClient);
// TODO - not supposed to parse room versions as int.
const roomVersion = parseInt(this.room.getVersion()?.split(".").reverse()[0] ?? "0");
if (roomVersion >= 11 && this.room.getCreator() === this.$matrix.currentUserId) {
canChangeAccess = true;
}
this.userCanChangeJoinRule = canChangeAccess;
this.userCanPurgeRoom = canChangeAccess; //TODO - need different permissions here?
} else {

View file

@ -723,6 +723,15 @@ export default {
}
},
revokeAdmin(roomId, userId) {
if (this.matrixClient && roomId && userId) {
const room = this.getRoom(roomId);
if (room && room.currentState) {
this.matrixClient.setPowerLevel(roomId, userId, 0);
}
}
},
makeModerator(roomId, userId) {
if (this.matrixClient && roomId && userId) {
const room = this.getRoom(roomId);