Knock support
Also, fix token refresh functionality
This commit is contained in:
parent
cfabd8be08
commit
e8f04d79c9
11 changed files with 310 additions and 75 deletions
|
|
@ -1015,6 +1015,12 @@ body {
|
|||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.member .knock-reason {
|
||||
margin-left: 38px;
|
||||
font-size: 0.7em;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.member .user-power {
|
||||
margin-left: 6px;
|
||||
color: #aaa;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@
|
|||
"user_make_moderator": "Make moderator",
|
||||
"user_revoke_moderator": "Revoke moderator",
|
||||
"pin": "Pin post",
|
||||
"unpin": "Unpin post"
|
||||
"unpin": "Unpin post",
|
||||
"cancel_knock": "Cancel knock"
|
||||
},
|
||||
"message": {
|
||||
"you": "You",
|
||||
|
|
@ -138,6 +139,7 @@
|
|||
"room_history_joined": "People can only see the messages sent after they join.",
|
||||
"join_public": "Anyone can join by opening this link: {link}.",
|
||||
"join_invite": "Only people you invite can join.",
|
||||
"join_knock": "People can request to join by ´knocking´.",
|
||||
"info_permissions": "You can change ‘join permissions’ at any time in the room settings.",
|
||||
"got_it": "Got it",
|
||||
"no_past_messages": "Welcome! For your security, past messages are not available.",
|
||||
|
|
@ -277,10 +279,14 @@
|
|||
"joining_as": "You are joining as:",
|
||||
"join": "Join room",
|
||||
"join_user": "Start chat",
|
||||
"knock": "Knock",
|
||||
"knock_reason": "Knock reason (optional)",
|
||||
"enter_room": "Enter room",
|
||||
"enter_room_user": "Start chat",
|
||||
"enter_knock": "Request to join",
|
||||
"status_logging_in": "Logging in...",
|
||||
"status_joining": "Joining room...",
|
||||
"status_knocking": "Knocking...",
|
||||
"join_failed": "Failed to join room.",
|
||||
"choose_name": "Choose a name to use",
|
||||
"you_have_been_banned": "You have been banned from this room.",
|
||||
|
|
@ -328,11 +334,15 @@
|
|||
"permissions": "Join Permissions",
|
||||
"join_invite": "Only People Added",
|
||||
"join_public": "Anyone with a link",
|
||||
"join_knock": "People can ´knock´.",
|
||||
"copy_invite_link": "Copy invite link",
|
||||
"copy_link": "Copy link",
|
||||
"link_copied": "Link copied!",
|
||||
"purge": "Delete room",
|
||||
"members": "Members",
|
||||
"knocks": "Knocks",
|
||||
"accept_knock": "Accept",
|
||||
"reject_knock": "Deny",
|
||||
"user": "{user}",
|
||||
"user_you": "{user} (you)",
|
||||
"hide_all": "Hide",
|
||||
|
|
|
|||
|
|
@ -1178,7 +1178,11 @@ export default {
|
|||
this.$navigation.push(
|
||||
{
|
||||
name: "Join",
|
||||
params: { roomId: util.sanitizeRoomId(this.roomAliasOrId), join: this.$route.params.join },
|
||||
params: {
|
||||
roomId: util.sanitizeRoomId(this.roomAliasOrId),
|
||||
join: this.$route.params.join
|
||||
},
|
||||
query: this.$route.query
|
||||
},
|
||||
0
|
||||
);
|
||||
|
|
|
|||
|
|
@ -90,13 +90,22 @@
|
|||
|
||||
<interactive-auth ref="interactiveAuth" />
|
||||
|
||||
<v-text-field
|
||||
v-if="roomNeedsKnock"
|
||||
variant="solo"
|
||||
density="compact"
|
||||
:label="$t('join.knock_reason')"
|
||||
counter="100"
|
||||
maxlength="100"
|
||||
v-model="knockReason" />
|
||||
|
||||
<v-btn id="btn-join" class="btn-dark" :disabled="!acceptUA || (room && room.getMyMembership() == 'ban')" size="large"
|
||||
@click.stop="handleJoin" :loading="loading" v-if="!currentUser">{{
|
||||
roomId && roomId.startsWith("@") ? $t("join.enter_room_user") : $t("join.enter_room")
|
||||
roomId && roomId.startsWith("@") ? $t("join.enter_room_user") : this.roomNeedsKnock ? $t("join.enter_knock") : $t("join.enter_room")
|
||||
}}</v-btn>
|
||||
<v-btn id="btn-join" class="btn-dark" :disabled="!acceptUA || (room && room.getMyMembership() == 'ban')" size="large"
|
||||
block @click.stop="handleJoin" :loading="loading" v-else>{{
|
||||
roomId && roomId.startsWith("@") ? $t("join.join_user") : $t("join.join")
|
||||
roomId && roomId.startsWith("@") ? $t("join.join_user") : this.roomNeedsKnock ? $t("join.knock") : $t("join.join")
|
||||
}}</v-btn>
|
||||
|
||||
<div v-if="loadingMessage" class="text-center">{{ loadingMessage }}</div>
|
||||
|
|
@ -164,6 +173,20 @@ export default {
|
|||
InteractiveAuth,
|
||||
AuthedImage
|
||||
},
|
||||
props: {
|
||||
roomDisplayName: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
roomNeedsKnock: {
|
||||
type: Boolean,
|
||||
default: function () {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
roomName: null,
|
||||
|
|
@ -178,6 +201,7 @@ export default {
|
|||
showEditDisplaynameDialog: false,
|
||||
showSelectLanguageDialog: false,
|
||||
acceptUA: false,
|
||||
knockReason: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -233,14 +257,6 @@ export default {
|
|||
let activeLanguages = [...this.getLanguages()];
|
||||
return activeLanguages.filter((lang) => lang.value === this.$i18n.locale);
|
||||
},
|
||||
roomDisplayName() {
|
||||
// If there is a display name in to invite link, use that!
|
||||
try {
|
||||
return new URL(location.href).searchParams.get('roomName');
|
||||
} catch(ignoredError) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roomId: {
|
||||
|
|
@ -312,8 +328,13 @@ export default {
|
|||
this.$nextTick(() => {
|
||||
this.handleJoin();
|
||||
});
|
||||
}
|
||||
else if (this.roomId.startsWith("#")) {
|
||||
} else if (this.roomId.startsWith("@")) {
|
||||
// Direct chat with user
|
||||
this.waitingForRoomCreation = true;
|
||||
this.$nextTick(() => {
|
||||
this.handleJoin();
|
||||
});
|
||||
} else {
|
||||
this.$matrix
|
||||
.getPublicRoomInfo(this.roomId)
|
||||
.then((room) => {
|
||||
|
|
@ -323,25 +344,18 @@ export default {
|
|||
})
|
||||
.catch((err) => {
|
||||
console.log("Could not find room info", err);
|
||||
|
||||
// Private room, try to get name
|
||||
const room = this.$matrix.getRoom(this.roomId);
|
||||
if (room) {
|
||||
this.roomName = this.removeHomeServer(room.name || this.roomName);
|
||||
} else {
|
||||
this.roomName = this.removeHomeServer(this.roomAliasOrId);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.waitingForInfo = false;
|
||||
});
|
||||
} else if (this.roomId.startsWith("@")) {
|
||||
// Direct chat with user
|
||||
this.waitingForRoomCreation = true;
|
||||
this.$nextTick(() => {
|
||||
this.handleJoin();
|
||||
});
|
||||
} else {
|
||||
// Private room, try to get name
|
||||
const room = this.$matrix.getRoom(this.roomId);
|
||||
if (room) {
|
||||
this.roomName = this.removeHomeServer(room.name || this.roomName);
|
||||
} else {
|
||||
this.roomName = this.removeHomeServer(this.roomAliasOrId);
|
||||
}
|
||||
this.waitingForInfo = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -359,10 +373,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
handleOpenApp() {
|
||||
console.log("Open app..."); //TODO
|
||||
},
|
||||
|
||||
handleJoin() {
|
||||
this.loading = true;
|
||||
this.loadingMessage = this.$t("join.status_logging_in");
|
||||
|
|
@ -412,6 +422,11 @@ export default {
|
|||
this.$matrix.setCurrentRoomId(room.roomId);
|
||||
return room;
|
||||
});
|
||||
} else if (this.roomNeedsKnock) {
|
||||
console.log("Join: knocking room");
|
||||
this.$analytics.event("Invitations", "Room Knocked");
|
||||
this.loadingMessage = this.$t("join.status_knocking");
|
||||
return this.$matrix.matrixClient.knockRoom(this.roomId, this.knockReason.length > 0 ? { reason: this.knockReason} : undefined);
|
||||
} else {
|
||||
console.log("Join: joining room");
|
||||
this.$analytics.event("Invitations", "Room Joined");
|
||||
|
|
@ -423,13 +438,23 @@ export default {
|
|||
this.loading = false;
|
||||
this.loadingMessage = null;
|
||||
this.$nextTick(() => {
|
||||
this.$navigation.push(
|
||||
{
|
||||
name: "Chat",
|
||||
params: { roomId: util.sanitizeRoomId(room.roomId) },
|
||||
},
|
||||
-1
|
||||
);
|
||||
if (this.roomNeedsKnock) {
|
||||
// For knocks, send to room list
|
||||
this.$navigation.push(
|
||||
{
|
||||
name: "Home",
|
||||
},
|
||||
-1
|
||||
);
|
||||
} else {
|
||||
this.$navigation.push(
|
||||
{
|
||||
name: "Chat",
|
||||
params: { roomId: util.sanitizeRoomId(room.roomId) },
|
||||
},
|
||||
-1
|
||||
);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@
|
|||
<v-list-item
|
||||
class="member"
|
||||
v-show="showAllMembers || index < SHOW_MEMBER_LIMIT"
|
||||
@click="onListItemClick(member)"
|
||||
@click="onMemberClick(member)"
|
||||
>
|
||||
<div>
|
||||
<div class="user-icon-with-badge">
|
||||
|
|
@ -236,6 +236,81 @@
|
|||
</div>
|
||||
</v-card>
|
||||
|
||||
<!-- KNOCKS, only shown is joinRule is knock -->
|
||||
<v-card class="members ma-3" variant="flat" v-if="iAmAdmin && roomJoinRule == 'knock'">
|
||||
<v-card-title class="h2"
|
||||
>{{ $t("room_info.knocks") }}<v-spacer></v-spacer>
|
||||
<div>{{ knocks.length }}</div></v-card-title
|
||||
>
|
||||
<v-list>
|
||||
<template v-for="(member, index) in knocks" :key="member.userId">
|
||||
<v-list-item
|
||||
class="member"
|
||||
v-show="showAllKnocks || index < SHOW_MEMBER_LIMIT"
|
||||
@click="onKnockClick(member)"
|
||||
>
|
||||
<div>
|
||||
<div class="user-icon-with-badge">
|
||||
<v-avatar class="avatar" size="32" color="grey">
|
||||
<AuthedImage v-if="memberAvatar(member)" :src="memberAvatar(member)" />
|
||||
<span v-else class="text-white headline">{{
|
||||
member.name.substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
<v-avatar circle class="user-badge" size="15" v-if="isAdmin(member) || isModerator(member)">
|
||||
<v-icon style="min-width: 15px;min-height: 15px;">{{ `$vuetify.icons.${isAdmin(member)? 'make_admin' : 'make_moderator'}` }}</v-icon>
|
||||
</v-avatar>
|
||||
</div>
|
||||
<span class="user-name">
|
||||
{{
|
||||
member.userId == $matrix.currentUserId
|
||||
? $t("room_info.user_you", {
|
||||
user: member.user ? member.user.displayName : member.name,
|
||||
})
|
||||
: $t("room_info.user", {
|
||||
user: member.user ? member.user.displayName : member.name,
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
<span v-if="isAdmin(member)" class="user-power">
|
||||
{{ $t("room_info.user_admin") }}
|
||||
</span>
|
||||
<span v-else-if="isModerator(member)" class="user-power">
|
||||
{{ $t("room_info.user_moderator") }}
|
||||
</span>
|
||||
<div class="knock-reason">{{ member.events?.member ? member.events?.member.getContent().reason : "" }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Accept/Deny knock buttons-->
|
||||
<template v-slot:append>
|
||||
<v-list-item-action>
|
||||
<v-tooltip location="top">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn color="transparent" v-bind="props" @click.stop="acceptKnock(member)" icon="thumb_up"></v-btn>
|
||||
</template>
|
||||
<span>{{ $t("room_info.accept_knock") }}</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip location="top">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn color="transparent" v-bind="props" @click.stop="rejectKnock(member)" icon="block"></v-btn>
|
||||
</template>
|
||||
<span>{{ $t("room_info.reject_knock") }}</span>
|
||||
</v-tooltip>
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
|
||||
</v-list-item>
|
||||
<v-divider
|
||||
v-if="(showAllKnocks || index < SHOW_MEMBER_LIMIT) && index < knocks.length - 1"
|
||||
:key="index"
|
||||
></v-divider>
|
||||
</template>
|
||||
</v-list>
|
||||
<div class="show-all p-2" @click="showAllKnocks = !showAllKnocks" v-if="knocks.length > SHOW_MEMBER_LIMIT">
|
||||
{{ showAllKnocks ? $t("room_info.hide_all") : $t("room_info.show_all") }}
|
||||
</div>
|
||||
</v-card>
|
||||
|
||||
<!-- EXPORT CHAT -->
|
||||
<div style="text-align: center">
|
||||
<v-btn
|
||||
|
|
@ -314,8 +389,10 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
members: [],
|
||||
knocks: [],
|
||||
user: null,
|
||||
showAllMembers: false,
|
||||
showAllKnocks: false,
|
||||
showMemberActionConfirmation: false,
|
||||
showLeaveConfirmation: false,
|
||||
showPurgeConfirmation: false,
|
||||
|
|
@ -334,6 +411,11 @@ export default {
|
|||
text: this.$t("room_info.join_invite"),
|
||||
icon: "person_add",
|
||||
},
|
||||
{
|
||||
id: "knock",
|
||||
text: this.$t("room_info.join_knock"),
|
||||
icon: "doorbell",
|
||||
},
|
||||
],
|
||||
SHOW_MEMBER_LIMIT: 5,
|
||||
exporting: false,
|
||||
|
|
@ -430,10 +512,21 @@ export default {
|
|||
const retentionPeriodsFound = this.retentionPeriods.find(rp => rp.value===retention)
|
||||
this.messageRetentionDisplay = retentionPeriodsFound.text
|
||||
},
|
||||
onListItemClick(member) {
|
||||
onMemberClick(member) {
|
||||
this.activeMember = member
|
||||
this.showMemberActionConfirmation = true
|
||||
},
|
||||
onKnockClick(member) {
|
||||
this.activeMember = member
|
||||
this.showMemberActionConfirmation = true
|
||||
},
|
||||
acceptKnock(member) {
|
||||
this.$matrix.answerKnock(member.roomId, member.userId, true, undefined);
|
||||
},
|
||||
rejectKnock(member) {
|
||||
this.$matrix.answerKnock(member.roomId, member.userId, false, undefined);
|
||||
},
|
||||
|
||||
onEvent(event) {
|
||||
if (this.room && this.room.roomId == event.getRoomId()) {
|
||||
// For this room
|
||||
|
|
@ -466,8 +559,30 @@ export default {
|
|||
const bName = b.user ? b.user.displayName : b.name;
|
||||
return aName.localeCompare(bName);
|
||||
});
|
||||
this.knocks = this.room.getMembersWithMembership("knock").sort((a, b) => {
|
||||
// Place ourselves at the top!
|
||||
if (a.userId == myUserId) {
|
||||
return -1;
|
||||
} else if (b.userId == myUserId) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Then sort by power level
|
||||
if (a.powerLevel > b.powerLevel) {
|
||||
return -1;
|
||||
} else if (b.powerLevel > a.powerLevel) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Then by name
|
||||
const aName = a.user ? a.user.displayName : a.name;
|
||||
const bName = b.user ? b.user.displayName : b.name;
|
||||
return aName.localeCompare(bName);
|
||||
});
|
||||
|
||||
} else {
|
||||
this.members = [];
|
||||
this.knocks = [];
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,29 @@
|
|||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<!-- Knocked rooms -->
|
||||
<v-list-item :disabled="roomsProcessing[room.roomId]" v-for="room in knockedRooms" :key="room.roomId"
|
||||
:value="room.roomId" class="room-list-room">
|
||||
<template v-slot:prepend>
|
||||
<v-avatar size="42" color="#d9d9d9">
|
||||
<AuthedImage v-if="roomAvatar(room)" :src="roomAvatar(room)" />
|
||||
<span v-else class="text-white headline">{{
|
||||
room.name.substring(0, 1).toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
</template>
|
||||
|
||||
<v-list-item-title class="room-list-name">{{ room.name }}</v-list-item-title>
|
||||
<v-list-item-subtitle>{{ room.topic }}</v-list-item-subtitle>
|
||||
<template v-slot:append>
|
||||
<v-list-item-action>
|
||||
<v-btn id="btn-reject" class="filled-button" color="black"
|
||||
@click.stop="rejectInvitation(room)" variant="text">{{
|
||||
$t("menu.cancel_knock") }}</v-btn>
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item v-for="room in joinedRooms" :key="room.roomId" :value="room.roomId"
|
||||
@click="currentRoomId = room.roomId" class="room-list-room">
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -96,6 +119,9 @@ export default {
|
|||
invitedRooms() {
|
||||
return this.sortItemsOnName(this.$matrix.invites);
|
||||
},
|
||||
knockedRooms() {
|
||||
return this.sortItemsOnName(this.$matrix.knockedRooms);
|
||||
},
|
||||
joinedRooms() {
|
||||
// show room with notification on top, followed by room decending order by active Timestamp
|
||||
return [...this.$matrix.joinedRooms].sort((a, b) => {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@
|
|||
</div>
|
||||
<DeviceList :member="activeMember" />
|
||||
<div class="py-3" v-if="activeMember.userId != $matrix.currentUserId">
|
||||
<div v-if="activeMember.membership == 'knock'">
|
||||
</div>
|
||||
<div v-else>
|
||||
<v-btn variant="text" size="x-large" block v-if="activeMember.userId != $matrix.currentUserId && !$matrix.isDirectRoomWith(room, activeMember.userId)" class="start-private-chat clickable d-block text-none justify-start" @click="startPrivateChat(activeMember.userId)">
|
||||
<v-icon start>$vuetify.icons.direct_chat</v-icon> {{ $t("menu.direct_chat") }}
|
||||
</v-btn>
|
||||
|
|
@ -54,6 +57,7 @@
|
|||
<v-btn variant="text" size="x-large" block v-if="activeMember.userId != $matrix.currentUserId && isModeratorComp && canRevokeModeratorComp" class="start-private-chat clickable d-block text-none justify-start" @click="revokeModerator(activeMember)">
|
||||
<v-icon start>$vuetify.icons.revoke</v-icon> {{ $t("menu.user_revoke_moderator") }}
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-dialog>
|
||||
|
|
|
|||
|
|
@ -162,10 +162,12 @@ export default {
|
|||
return ContactJoin;
|
||||
}
|
||||
} else if (event.getContent().membership == "leave") {
|
||||
if ((event.getPrevContent() || {}).membership == "join" &&
|
||||
event.getStateKey() != event.getSender()) {
|
||||
return ContactKicked;
|
||||
}
|
||||
if ((event.getPrevContent() || {}).membership == "join" && event.getStateKey() != event.getSender()) {
|
||||
return ContactKicked;
|
||||
}
|
||||
if ((event.getPrevContent() || {}).membership == "knock") {
|
||||
return null; // A knock that was rejected
|
||||
}
|
||||
return ContactLeave;
|
||||
} else if (this.showAllStatusMessages) {
|
||||
if (event.getContent().membership == "invite") {
|
||||
|
|
|
|||
|
|
@ -62,13 +62,14 @@ export default {
|
|||
},
|
||||
|
||||
publicRoomLink() {
|
||||
if (this.room && this.roomJoinRule == "public") {
|
||||
if (this.room && (this.roomJoinRule == "public" || this.roomJoinRule == "knock")) {
|
||||
return this.$router.getRoomLink(
|
||||
this.room.getCanonicalAlias(),
|
||||
this.room.roomId,
|
||||
this.room.name,
|
||||
utils.roomDisplayTypeToQueryParam(this.room, this.roomDisplayType),
|
||||
this.roomDisplayType == ROOM_TYPE_CHANNEL /* Auto join for channels */
|
||||
this.roomDisplayType == ROOM_TYPE_CHANNEL, /* Auto join for channels */
|
||||
this.roomJoinRule == "knock"
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ const routes = [
|
|||
{
|
||||
path: '/info',
|
||||
name: 'RoomInfo',
|
||||
component: defineAsyncComponent(() => import('../components/RoomInfo.vue')),
|
||||
component: () => import('../components/RoomInfo.vue'),
|
||||
props: true,
|
||||
meta: {
|
||||
title: 'Info',
|
||||
|
|
@ -85,7 +85,13 @@ const routes = [
|
|||
{
|
||||
path: '/join/:join(join/)?:roomId?',
|
||||
name: 'Join',
|
||||
component: Join
|
||||
component: Join,
|
||||
props: route => {
|
||||
return {
|
||||
roomNeedsKnock: (route.query.knock ? true : false),
|
||||
roomDisplayName: route.query.roomName
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/user/:userId?',
|
||||
|
|
@ -202,7 +208,7 @@ router.beforeEach((to, from, next) => {
|
|||
}
|
||||
});
|
||||
|
||||
router.getRoomLink = function (alias, roomId, roomName, mode, autojoin) {
|
||||
router.getRoomLink = function (alias, roomId, roomName, mode, autojoin, knock) {
|
||||
let params = {};
|
||||
if ((!alias || roomName.replace(/\s/g, "").toLowerCase() !== util.getRoomNameFromAlias(alias)) && roomName) {
|
||||
// There is no longer a correlation between alias and room name, probably because room name has
|
||||
|
|
@ -213,14 +219,17 @@ router.getRoomLink = function (alias, roomId, roomName, mode, autojoin) {
|
|||
// Optional mode given, append as "m" query param
|
||||
params["m"] = mode;
|
||||
}
|
||||
if (knock) {
|
||||
params["knock"] = "1";
|
||||
}
|
||||
const autoJoinSegment = autojoin ? "join/" : "";
|
||||
let queryString = "";
|
||||
if (Object.entries(params).length > 0) {
|
||||
const queryString = Object.entries(params)
|
||||
queryString = "?" + Object.entries(params)
|
||||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
||||
.join('&')
|
||||
return window.location.origin + window.location.pathname + "?" + queryString + "#/room/" + autoJoinSegment + encodeURIComponent(util.sanitizeRoomId(alias || roomId));
|
||||
}
|
||||
return window.location.origin + window.location.pathname + "#/room/" + autoJoinSegment + encodeURIComponent(util.sanitizeRoomId(alias || roomId));
|
||||
return window.location.origin + window.location.pathname + "#/room/" + autoJoinSegment + encodeURIComponent(util.sanitizeRoomId(alias || roomId)) + queryString;
|
||||
}
|
||||
|
||||
router.getDMLink = function (user, config) {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export default {
|
|||
currentRoom: null,
|
||||
notificationCount: 0,
|
||||
legacyCryptoStore: undefined,
|
||||
tokenRefreshPromise: undefined,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -95,6 +96,12 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
knockedRooms() {
|
||||
return this.rooms.filter((room) => {
|
||||
return room.getMyMembership() === "knock";
|
||||
});
|
||||
},
|
||||
|
||||
joinedAndInvitedRooms() {
|
||||
return this.rooms.filter((room) => {
|
||||
return room.getMyMembership() === "join" || room.getMyMembership() === "invite";
|
||||
|
|
@ -196,6 +203,7 @@ export default {
|
|||
password: user.password,
|
||||
type: "m.login.password",
|
||||
initial_device_display_name: this.$config.appName,
|
||||
refresh_token: true
|
||||
};
|
||||
if (user.device_id) {
|
||||
data.device_id = user.device_id;
|
||||
|
|
@ -420,6 +428,7 @@ export default {
|
|||
// Reject the invite, i.e. call "leave" on it.
|
||||
this.matrixClient.leave(room.roomId);
|
||||
}
|
||||
// TODO - handle knocks
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -469,8 +478,12 @@ export default {
|
|||
this.updateNotificationCount();
|
||||
},
|
||||
|
||||
onRoomMyMembership(room) {
|
||||
if (room.getMyMembership() === "invite") {
|
||||
onRoomMyMembership(room, membership, prevMembership) {
|
||||
if (membership === "invite") {
|
||||
if (prevMembership === "knock") {
|
||||
// This is someone accepting our knock! Auto-join.
|
||||
this.matrixClient.joinRoom(room.roomId);
|
||||
}
|
||||
// Invitation. Need to call "recalculate" to pick
|
||||
// up room name, not sure why exactly.
|
||||
room.recalculate();
|
||||
|
|
@ -479,25 +492,36 @@ export default {
|
|||
},
|
||||
|
||||
onSessionRefresh(refreshToken) {
|
||||
if (this.tokenRefreshPromise) {
|
||||
return this.tokenRefreshPromise;
|
||||
}
|
||||
const now = Date.now();
|
||||
return this.matrixClient.refreshToken(refreshToken).then((result) => {
|
||||
// Store new one!
|
||||
var user = this.$store.state.auth.user;
|
||||
user.access_token = result.access_token;
|
||||
user.refresh_token = result.refresh_token;
|
||||
user.expires_in_ms = result.expires_in_ms;
|
||||
this.$store.commit("setUser", user);
|
||||
this.tokenRefreshPromise =
|
||||
this.matrixClient.http.request(sdk.Method.Post, "/refresh", undefined, { refresh_token: refreshToken}, { prefix: sdk.ClientPrefix.V3, inhibitLogoutEmit: true }).then((result) => {
|
||||
// Store new one!
|
||||
var user = this.$store.state.auth.user;
|
||||
user.access_token = result.access_token;
|
||||
user.refresh_token = result.refresh_token;
|
||||
user.expires_in_ms = result.expires_in_ms;
|
||||
this.$store.commit("setUser", user);
|
||||
|
||||
// Return AccessTokens struct
|
||||
let accesssTokens = {
|
||||
accessToken: result.access_token,
|
||||
refreshToken: result.refresh_token
|
||||
};
|
||||
if (result.expires_in_ms) {
|
||||
accesssTokens.expiry = new Date(now + result.expires_in_ms);
|
||||
};
|
||||
return accesssTokens;
|
||||
});
|
||||
// Return AccessTokens struct
|
||||
let accessTokens = {
|
||||
accessToken: result.access_token,
|
||||
refreshToken: result.refresh_token
|
||||
};
|
||||
if (result.expires_in_ms) {
|
||||
accessTokens.expiry = new Date(now + result.expires_in_ms);
|
||||
};
|
||||
return accessTokens;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw new sdk.TokenRefreshLogoutError(error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.tokenRefreshPromise = undefined;
|
||||
});
|
||||
return this.tokenRefreshPromise;
|
||||
},
|
||||
|
||||
onSessionLoggedOut() {
|
||||
|
|
@ -541,7 +565,7 @@ export default {
|
|||
// each time!
|
||||
var updatedRooms = this.matrixClient.getVisibleRooms();
|
||||
updatedRooms = updatedRooms.filter((room) => {
|
||||
return room.getMyMembership() && (room.getMyMembership() == "invite" || room.getMyMembership() == "join") && room.currentState.getStateEvents(STATE_EVENT_ROOM_DELETED).length == 0;
|
||||
return room.getMyMembership() && ["invite", "join", "knock"].includes(room.getMyMembership()) && room.currentState.getStateEvents(STATE_EVENT_ROOM_DELETED).length == 0;
|
||||
});
|
||||
updatedRooms.forEach((room) => {
|
||||
room["avatar"] = room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true, this.useAuthedMedia);
|
||||
|
|
@ -692,6 +716,14 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
answerKnock(roomId, userId, allowAccess, reason) {
|
||||
if (allowAccess) {
|
||||
this.matrixClient.invite(roomId, userId, reason);
|
||||
} else {
|
||||
this.matrixClient.kick(roomId, userId, reason);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the current user is joined to the given room.
|
||||
* @param roomIdOrAlias
|
||||
|
|
@ -921,7 +953,8 @@ export default {
|
|||
statusCallback(this.$t("room.purge_removing_members"));
|
||||
var joined = room.getMembersWithMembership("join");
|
||||
var invited = room.getMembersWithMembership("invite");
|
||||
var allMembers = joined.concat(invited);
|
||||
var knocked = room.getMembersWithMembership("knock");
|
||||
var allMembers = joined.concat(invited).concat(knocked);
|
||||
|
||||
const me = allMembers.find((m) => m.userId == self.currentUserId);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue