Restore matrix impl and remove $tc
This commit is contained in:
parent
c47b975723
commit
7a801f3ec3
8 changed files with 1140 additions and 696 deletions
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="num-members">{{ $tc("room.members", memberCount) }}</div>
|
<div class="num-members">{{ $t("room.members", memberCount) }}</div>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="auto" class="text-end ma-0 pa-0 ms-1">
|
<v-col cols="auto" class="text-end ma-0 pa-0 ms-1">
|
||||||
<v-avatar :class="{ 'avatar-32': true, 'clickable': true, 'popup-open': showProfileInfo }" size="26"
|
<v-avatar :class="{ 'avatar-32': true, 'clickable': true, 'popup-open': showProfileInfo }" size="26"
|
||||||
|
|
@ -117,11 +117,11 @@ export default {
|
||||||
notificationsText() {
|
notificationsText() {
|
||||||
const invitationCount = this.$matrix.invites.length
|
const invitationCount = this.$matrix.invites.length
|
||||||
if (invitationCount > 0) {
|
if (invitationCount > 0) {
|
||||||
return this.$tc('room.invitations', invitationCount);
|
return this.$t('room.invitations', invitationCount);
|
||||||
}
|
}
|
||||||
const missedMessagesCount = this.$matrix.joinedRooms.reduce((value, r) => ((r.roomId !== this.$matrix.currentRoomId && r.getCanonicalAlias() !== this.$matrix.currentRoomId) ? (value + r.getUnreadNotificationCount("total")) : value), 0);
|
const missedMessagesCount = this.$matrix.joinedRooms.reduce((value, r) => ((r.roomId !== this.$matrix.currentRoomId && r.getCanonicalAlias() !== this.$matrix.currentRoomId) ? (value + r.getUnreadNotificationCount("total")) : value), 0);
|
||||||
if (missedMessagesCount > 0) {
|
if (missedMessagesCount > 0) {
|
||||||
return this.$tc('room.unseen_messages', missedMessagesCount);
|
return this.$t('room.unseen_messages', missedMessagesCount);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<div class="room-name-inline text-truncate" :title="room.name">
|
<div class="room-name-inline text-truncate" :title="room.name">
|
||||||
{{ room.name }}
|
{{ room.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="num-members">{{ $tc("room.members", room.getJoinedMemberCount()) }}</div>
|
<div class="num-members">{{ $t("room.members", room.getJoinedMemberCount()) }}</div>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="auto" class="text-end ma-0 pa-0">{{ exportDate }}</v-col>
|
<v-col cols="auto" class="text-end ma-0 pa-0">{{ exportDate }}</v-col>
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ export default {
|
||||||
dayForEvent(event) {
|
dayForEvent(event) {
|
||||||
let dayDiff = util.dayDiffToday(event.getTs());
|
let dayDiff = util.dayDiffToday(event.getTs());
|
||||||
if (dayDiff < 7) {
|
if (dayDiff < 7) {
|
||||||
return this.$tc("message.time_ago", dayDiff);
|
return this.$t("message.time_ago", dayDiff);
|
||||||
} else {
|
} else {
|
||||||
return util.formatDay(event.getTs());
|
return util.formatDay(event.getTs());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="status == mainStatuses.SENT" class="file-drop-sending-container">
|
<div v-else-if="status == mainStatuses.SENT" class="file-drop-sending-container">
|
||||||
<div class="file-drop-files-sent">{{ $tc((this.messageInput && this.messageInput.length > 0) ?
|
<div class="file-drop-files-sent">{{ $t((this.messageInput && this.messageInput.length > 0) ?
|
||||||
"file_mode.files_sent_with_note" : "file_mode.files_sent", attachmentsSent.length) }}</div>
|
"file_mode.files_sent_with_note" : "file_mode.files_sent", attachmentsSent.length) }}</div>
|
||||||
<div class="file-drop-section">
|
<div class="file-drop-section">
|
||||||
<v-textarea disabled full-width solo flat auto-grow v-model="messageInput" no-resize class="input-area-text"
|
<v-textarea disabled full-width solo flat auto-grow v-model="messageInput" no-resize class="input-area-text"
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span>{{ $tc("message.seen_by_count", seenBy.length) }}</span>
|
<span>{{ $t("message.seen_by_count", seenBy.length) }}</span>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<BottomSheet
|
<BottomSheet
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
ref="seenByListBottomSheet"
|
ref="seenByListBottomSheet"
|
||||||
>
|
>
|
||||||
<v-list>
|
<v-list>
|
||||||
<v-subheader class="text-uppercase"> {{ $tc("message.seen_by") }}</v-subheader>
|
<v-subheader class="text-uppercase"> {{ $t("message.seen_by") }}</v-subheader>
|
||||||
<v-list-item v-for="(member, index) in seenBy" :key="index" class="text-left">
|
<v-list-item v-for="(member, index) in seenBy" :key="index" class="text-left">
|
||||||
<v-list-item-icon>
|
<v-list-item-icon>
|
||||||
<v-avatar size="40" color="grey">
|
<v-avatar size="40" color="grey">
|
||||||
|
|
@ -96,7 +96,7 @@ export default {
|
||||||
seenByTimeStamp(timestamp) {
|
seenByTimeStamp(timestamp) {
|
||||||
let dayDiff = utils.dayDiffToday(timestamp);
|
let dayDiff = utils.dayDiffToday(timestamp);
|
||||||
if (dayDiff < 3) {
|
if (dayDiff < 3) {
|
||||||
return this.$tc("message.time_ago", dayDiff) + ' '+utils.formatTime(timestamp);
|
return this.$t("message.time_ago", dayDiff) + ' '+utils.formatTime(timestamp);
|
||||||
} else {
|
} else {
|
||||||
return utils.formatTime(timestamp);
|
return utils.formatTime(timestamp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -306,11 +306,11 @@ export default {
|
||||||
if (ti < 60) {
|
if (ti < 60) {
|
||||||
s = this.$t("global.time.recently");
|
s = this.$t("global.time.recently");
|
||||||
} else if (ti < 3600 && Math.round(ti / 60) < 60) {
|
} else if (ti < 3600 && Math.round(ti / 60) < 60) {
|
||||||
s = this.$tc("global.time.minutes", Math.round(ti / 60));
|
s = this.$t("global.time.minutes", Math.round(ti / 60));
|
||||||
} else if (ti < 86400 && Math.round(ti / 60 / 60) < 24) {
|
} else if (ti < 86400 && Math.round(ti / 60 / 60) < 24) {
|
||||||
s = this.$tc("global.time.hours", Math.round(ti / 60 / 60));
|
s = this.$t("global.time.hours", Math.round(ti / 60 / 60));
|
||||||
} else {
|
} else {
|
||||||
s = this.$tc("global.time.days", Math.round(ti / 60 / 60 / 24));
|
s = this.$t("global.time.days", Math.round(ti / 60 / 60 / 24));
|
||||||
}
|
}
|
||||||
return this.toLocalNumbers(s);
|
return this.toLocalNumbers(s);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,8 @@ app.use(i18n);
|
||||||
|
|
||||||
app.use(matrix, { store: store, i18n: i18n });
|
app.use(matrix, { store: store, i18n: i18n });
|
||||||
|
|
||||||
|
app.config.globalProperties.$root = app;
|
||||||
|
|
||||||
//app.use(matrix);
|
//app.use(matrix);
|
||||||
//app.use(config);
|
//app.use(config);
|
||||||
// app.use(analytics);
|
// app.use(analytics);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { reactive, createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
// import olm from "@matrix-org/olm/olm_legacy";
|
|
||||||
// global.Olm = olm;
|
|
||||||
import * as sdk from "matrix-js-sdk";
|
import * as sdk from "matrix-js-sdk";
|
||||||
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
import { TimelineWindow, EventTimeline, EventStatus } from "matrix-js-sdk";
|
||||||
import util 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";
|
import User from "../models/user";
|
||||||
import { LocalStorageCryptoStore } from "matrix-js-sdk/lib/crypto/store/localStorage-crypto-store";
|
import * as LocalStorageCryptoStoreClass from "matrix-js-sdk/lib/crypto/store/localStorage-crypto-store";
|
||||||
|
|
||||||
|
const LocalStorageCryptoStore = LocalStorageCryptoStoreClass.LocalStorageCryptoStore;
|
||||||
|
|
||||||
export const CHANNEL_POWER_LEVELS = {
|
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
|
"m.room.encrypted": 0, // NOTE! Since practically all events in encrypted rooms get sent as "m.room.encrypted" we need to set
|
||||||
|
|
@ -72,8 +72,8 @@ export default {
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
currentUserHomeServer() {
|
currentUserMXDomain() {
|
||||||
return this.$config.homeServer ? this.$config.homeServer : User.serverName(this.currentUserId);
|
return User.domainPart(this.currentUserId) || this.$config.defaultMatrixDomainPart;
|
||||||
},
|
},
|
||||||
|
|
||||||
currentRoomId() {
|
currentRoomId() {
|
||||||
|
|
@ -91,6 +91,12 @@ export default {
|
||||||
return room.selfMembership === "invite";
|
return room.selfMembership === "invite";
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
joinedAndInvitedRooms() {
|
||||||
|
return this.rooms.filter((room) => {
|
||||||
|
return room.selfMembership === "join" || room.selfMembership === "invite";
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -100,6 +106,18 @@ export default {
|
||||||
this.currentRoom = this.getRoom(roomId);
|
this.currentRoom = this.getRoom(roomId);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
currentRoom: {
|
||||||
|
immediate: true,
|
||||||
|
handler(room) {
|
||||||
|
if (room) {
|
||||||
|
this.userCanSendMessageInCurrentRoom = this.userCanSendMessageInRoom(room.roomId, this.currentUserId);
|
||||||
|
this.userCanSendReactionAndAnswerPollInCurrentRoom = this.userCanSendReactionAndAnswerPollInRoom(room.roomId, this.currentUserId);
|
||||||
|
} else {
|
||||||
|
this.userCanSendMessageInCurrentRoom = true;
|
||||||
|
this.userCanSendReactionAndAnswerPollInCurrentRoom = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -107,9 +125,11 @@ export default {
|
||||||
console.log("create crypto store");
|
console.log("create crypto store");
|
||||||
return new LocalStorageCryptoStore(this.$store.getters.storage);
|
return new LocalStorageCryptoStore(this.$store.getters.storage);
|
||||||
},
|
},
|
||||||
login(user) {
|
login(user, registrationFlowHandler, createUser = false) {
|
||||||
|
return util.getMatrixBaseUrl(user, this.$config).then((baseUrl) => {
|
||||||
const tempMatrixClient = sdk.createClient({
|
const tempMatrixClient = sdk.createClient({
|
||||||
baseUrl: user.home_server,
|
baseUrl: baseUrl,
|
||||||
|
idBaseUrl: this.$config.identityServer,
|
||||||
});
|
});
|
||||||
var promiseLogin;
|
var promiseLogin;
|
||||||
|
|
||||||
|
|
@ -117,27 +137,52 @@ export default {
|
||||||
if (user.access_token) {
|
if (user.access_token) {
|
||||||
// Logged in on "real" account
|
// Logged in on "real" account
|
||||||
promiseLogin = Promise.resolve(user);
|
promiseLogin = Promise.resolve(user);
|
||||||
} else if (user.is_guest && !user.user_id) {
|
} else if (createUser || (user.is_guest && (!user.user_id || user.registration_session))) {
|
||||||
// Generate random username and password. We don't user REAL matrix
|
// Generate random username and password. We don't user REAL matrix
|
||||||
// guest accounts because 1. They are not allowed to post media, 2. They
|
// guest accounts because 1. They are not allowed to post media, 2. They
|
||||||
// can not use avatars and 3. They can not seamlessly be upgraded to real accounts.
|
// can not use avatars and 3. They can not seamlessly be upgraded to real accounts.
|
||||||
//
|
//
|
||||||
// Instead, we use an ILAG approach, Improved Landing as Guest.
|
// Instead, we use an ILAG approach, Improved Landing as Guest.
|
||||||
const user = util.randomUser(this.$config.userIdPrefix);
|
const userId =
|
||||||
const pass = util.randomPass();
|
createUser || user.registration_session ? user.user_id : util.randomUser(this.$config.userIdPrefix);
|
||||||
promiseLogin = tempMatrixClient
|
const pass = createUser || user.registration_session ? user.password : util.randomPass();
|
||||||
.register(user, pass, null, {
|
|
||||||
type: "m.login.dummy",
|
const extractAndSaveUser = (response) => {
|
||||||
initial_device_display_name: this.$config.appName,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
console.log("Response", response);
|
|
||||||
var u = Object.assign({}, response);
|
var u = Object.assign({}, response);
|
||||||
u.home_server = tempMatrixClient.baseUrl; // Don't use deprecated field from response.
|
|
||||||
u.password = pass;
|
u.password = pass;
|
||||||
u.is_guest = true;
|
u.is_guest = true;
|
||||||
this.$store.commit("setUser", u);
|
this.$store.commit("setUser", u);
|
||||||
return u;
|
return u;
|
||||||
|
};
|
||||||
|
|
||||||
|
promiseLogin = tempMatrixClient
|
||||||
|
.register(userId, pass, user.registration_session || null, {
|
||||||
|
type: "m.login.dummy",
|
||||||
|
initial_device_display_name: this.$config.appName,
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
return extractAndSaveUser(response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (registrationFlowHandler && error.httpStatus == 401 && error.data) {
|
||||||
|
const registrationSession = error.data.session;
|
||||||
|
|
||||||
|
// Store user, pass and session, so we can resume if network failure occurs etc.
|
||||||
|
//
|
||||||
|
var u = {};
|
||||||
|
u.user_id = userId;
|
||||||
|
u.password = pass;
|
||||||
|
u.is_guest = true;
|
||||||
|
u.registration_session = registrationSession;
|
||||||
|
this.$store.commit("setUser", u);
|
||||||
|
|
||||||
|
return registrationFlowHandler(tempMatrixClient, error.data).then((response) =>
|
||||||
|
extractAndSaveUser(response)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var data = {
|
var data = {
|
||||||
|
|
@ -155,7 +200,6 @@ export default {
|
||||||
// Copy over needed properties
|
// Copy over needed properties
|
||||||
u = Object.assign(user, response);
|
u = Object.assign(user, response);
|
||||||
}
|
}
|
||||||
u.home_server = tempMatrixClient.baseUrl; // Don't use deprecated field from response.
|
|
||||||
this.$store.commit("setUser", u);
|
this.$store.commit("setUser", u);
|
||||||
return u;
|
return u;
|
||||||
});
|
});
|
||||||
|
|
@ -164,6 +208,7 @@ export default {
|
||||||
return promiseLogin.then((user) => {
|
return promiseLogin.then((user) => {
|
||||||
return self.getMatrixClient(user);
|
return self.getMatrixClient(user);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
clearCryptoStore() {
|
clearCryptoStore() {
|
||||||
|
|
@ -237,24 +282,25 @@ export default {
|
||||||
|
|
||||||
const matrixStore = new sdk.MemoryStore(this.$store.getters.storage);
|
const matrixStore = new sdk.MemoryStore(this.$store.getters.storage);
|
||||||
|
|
||||||
|
return util.getMatrixBaseUrl(user, this.$config).then((baseUrl) => {
|
||||||
var opts = {
|
var opts = {
|
||||||
baseUrl: user.home_server,
|
baseUrl: baseUrl,
|
||||||
userId: user.user_id,
|
userId: user.user_id,
|
||||||
store: matrixStore,
|
store: matrixStore,
|
||||||
deviceId: user.device_id,
|
deviceId: user.device_id,
|
||||||
accessToken: user.access_token,
|
accessToken: user.access_token,
|
||||||
timelineSupport: true,
|
timelineSupport: true,
|
||||||
unstableClientRelationAggregation: true,
|
unstableClientRelationAggregation: true,
|
||||||
|
cryptoStore: this.createCryptoStore()
|
||||||
//useAuthorizationHeader: true
|
//useAuthorizationHeader: true
|
||||||
};
|
};
|
||||||
this.matrixClient = sdk.createClient(opts);
|
this.matrixClient = sdk.createClient(opts);
|
||||||
// if (user.is_guest) {
|
// if (user.is_guest) {
|
||||||
// this.matrixClient.setGuest(true);
|
// this.matrixClient.setGuest(true);
|
||||||
// }
|
// }
|
||||||
console.log("MATRIX CLIENT", this.matrixClient);
|
console.error("Created client", this.matrixClient);
|
||||||
|
|
||||||
return this.matrixClient
|
return this.matrixClient
|
||||||
.initCrypto()
|
.initRustCrypto()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log("Crypto initialized");
|
console.log("Crypto initialized");
|
||||||
|
|
||||||
|
|
@ -281,10 +327,16 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
return this.matrixClient.isVersionSupported("v1.11");
|
||||||
|
})
|
||||||
|
.then((authedMediaSupported) => {
|
||||||
|
this.useAuthedMedia = authedMediaSupported;
|
||||||
|
|
||||||
// Ready to use! Start by loading rooms.
|
// Ready to use! Start by loading rooms.
|
||||||
this.initClient();
|
this.initClient();
|
||||||
return user;
|
return user;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -293,11 +345,14 @@ export default {
|
||||||
* Will use a real account, if we have one, otherwise will create
|
* Will use a real account, if we have one, otherwise will create
|
||||||
* a random account.
|
* a random account.
|
||||||
*/
|
*/
|
||||||
getLoginPromise() {
|
getLoginPromise(registrationFlowHandler) {
|
||||||
if (this.ready) {
|
if (this.ready) {
|
||||||
return Promise.resolve(this.currentUser);
|
return Promise.resolve(this.currentUser);
|
||||||
}
|
}
|
||||||
return this.$store.dispatch("login", this.currentUser || new User(this.$config.defaultServer, "", "", true));
|
return this.$store.dispatch("login", {
|
||||||
|
user: this.currentUser || new User("", "", true),
|
||||||
|
registrationFlowHandler,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addMatrixClientListeners(client) {
|
addMatrixClientListeners(client) {
|
||||||
|
|
@ -325,7 +380,7 @@ export default {
|
||||||
{
|
{
|
||||||
const room = this.matrixClient.getRoom(event.getRoomId());
|
const room = this.matrixClient.getRoom(event.getRoomId());
|
||||||
if (room) {
|
if (room) {
|
||||||
room.topic = event.getContent().topic;
|
room["topic"] = event.getContent().topic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -334,24 +389,56 @@ export default {
|
||||||
{
|
{
|
||||||
const room = this.matrixClient.getRoom(event.getRoomId());
|
const room = this.matrixClient.getRoom(event.getRoomId());
|
||||||
if (room) {
|
if (room) {
|
||||||
room.avatar = room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true);
|
Vue.set(
|
||||||
|
room,
|
||||||
|
"avatar",
|
||||||
|
room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true, this.useAuthedMedia)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "m.room.member":
|
case "m.room.power_levels":
|
||||||
{
|
{
|
||||||
if (this.currentRoom && event.getRoomId() == this.currentRoom.roomId) {
|
if (this.currentRoom && event.getRoomId() == this.currentRoom.roomId) {
|
||||||
// Don't use this.currentRoomId, may be an alias. We need the real id!
|
this.userCanSendMessageInCurrentRoom = this.userCanSendMessageInRoom(event.getRoomId(), this.currentUserId);
|
||||||
if (
|
this.userCanSendReactionAndAnswerPollInCurrentRoom = this.userCanSendReactionAndAnswerPollInRoom(event.getRoomId(), this.currentUserId);
|
||||||
event.getContent().membership == "leave" &&
|
}
|
||||||
(event.getPrevContent() || {}).membership == "join" &&
|
}
|
||||||
event.getStateKey() == this.currentUserId &&
|
break;
|
||||||
event.getSender() != this.currentUserId
|
|
||||||
) {
|
case "m.room.join_rules":
|
||||||
// We were kicked
|
{
|
||||||
const wasPurged = event.getContent().reason == "Room Deleted";
|
const room = this.matrixClient.getRoom(event.getRoomId());
|
||||||
this.$navigation.push({ name: "Goodbye", params: { roomWasPurged: wasPurged } }, -1);
|
if (room && room.getJoinRule() == "private" && room.selfMembership == "invite") {
|
||||||
|
// We have an invite to a room that's now "private"? This is most probably a deleted DM room.
|
||||||
|
// Reject the invite, i.e. call "leave" on it.
|
||||||
|
this.matrixClient.leave(room.roomId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "m.room.canonical_alias":
|
||||||
|
{
|
||||||
|
if (this.currentRoomId && this.currentRoomId.startsWith("#") && !this.currentRoom) {
|
||||||
|
this.currentRoom = this.getRoom(this.currentRoomId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_EVENT_ROOM_DELETED:
|
||||||
|
{
|
||||||
|
const room = this.matrixClient.getRoom(event.getRoomId());
|
||||||
|
if (room && room.currentState) {
|
||||||
|
// Before we do anything, make sure the sender is an admin!
|
||||||
|
// Also, do not react if WE are the sender, since we are probably
|
||||||
|
// busy doing the rest of the purging process...
|
||||||
|
if (room.currentState.maySendStateEvent("m.room.power_levels", event.getSender())) {
|
||||||
|
if (event.getSender() !== this.currentUserId) {
|
||||||
|
this.leaveRoomAndNavigate(room.roomId).then(() => {
|
||||||
|
this.matrixClient.forget(room.roomId, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -360,8 +447,19 @@ export default {
|
||||||
this.updateNotificationCount();
|
this.updateNotificationCount();
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoom(ignoredroom) {
|
onRoom(room) {
|
||||||
console.log("Got room", ignoredroom);
|
if (room.selfMembership === "invite") {
|
||||||
|
this.matrixClient
|
||||||
|
.getRoomTags(room.roomId)
|
||||||
|
.then((reply) => {
|
||||||
|
if (Object.keys(reply.tags).includes("m.server_notice")) {
|
||||||
|
room["isServiceNoticeRoom"] = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
this.reloadRooms();
|
this.reloadRooms();
|
||||||
this.updateNotificationCount();
|
this.updateNotificationCount();
|
||||||
},
|
},
|
||||||
|
|
@ -416,19 +514,25 @@ export default {
|
||||||
// each time!
|
// each time!
|
||||||
var updatedRooms = this.matrixClient.getVisibleRooms();
|
var updatedRooms = this.matrixClient.getVisibleRooms();
|
||||||
updatedRooms = updatedRooms.filter((room) => {
|
updatedRooms = updatedRooms.filter((room) => {
|
||||||
return room.selfMembership && (room.selfMembership == "invite" || room.selfMembership == "join");
|
return room.selfMembership && (room.selfMembership == "invite" || room.selfMembership == "join") && room.currentState.getStateEvents(STATE_EVENT_ROOM_DELETED).length == 0;
|
||||||
});
|
});
|
||||||
updatedRooms.forEach((room) => {
|
updatedRooms.forEach((room) => {
|
||||||
if (!room.avatar) {
|
room["avatar"] = room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true, this.useAuthedMedia);
|
||||||
room.avatar = room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
console.log("Reload rooms", updatedRooms);
|
this["rooms"] = updatedRooms;
|
||||||
this.rooms = updatedRooms;
|
|
||||||
const currentRoom = this.getRoom(this.$store.state.currentRoomId);
|
const resolvedId =
|
||||||
|
this.currentRoomId && this.currentRoomId.startsWith("#")
|
||||||
|
? this.matrixClient.getRoomIdForAlias(this.currentRoomId).then((r) => r.room_id)
|
||||||
|
: Promise.resolve(this.currentRoomId);
|
||||||
|
resolvedId
|
||||||
|
.then((roomId) => {
|
||||||
|
const currentRoom = this.getRoom(roomId);
|
||||||
if (this.currentRoom != currentRoom) {
|
if (this.currentRoom != currentRoom) {
|
||||||
this.currentRoom = currentRoom;
|
this.currentRoom = currentRoom;
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch((ignorederror) => { });
|
||||||
},
|
},
|
||||||
|
|
||||||
setCurrentRoomId(roomId) {
|
setCurrentRoomId(roomId) {
|
||||||
|
|
@ -494,15 +598,178 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
leaveRoom(roomId) {
|
leaveRoom(roomId) {
|
||||||
return this.matrixClient.leave(roomId, undefined).then(() => {
|
return this.matrixClient.leave(roomId).then(() => {
|
||||||
|
this.$store.commit("setCurrentRoomId", null);
|
||||||
this.rooms = this.rooms.filter((room) => {
|
this.rooms = this.rooms.filter((room) => {
|
||||||
room.roomId != roomId;
|
room.roomId != roomId;
|
||||||
});
|
});
|
||||||
this.matrixClient.store.removeRoom(roomId);
|
//this.matrixClient.store.removeRoom(roomId);
|
||||||
//this.matrixClient.forget(roomId, true, undefined);
|
//this.matrixClient.forget(roomId, true, undefined);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leave the room, and if this is the last room we are in, navigate to the "goodbye" page.
|
||||||
|
* Otherwise, navigate to home.
|
||||||
|
* @param roomId
|
||||||
|
*/
|
||||||
|
leaveRoomAndNavigate(roomId) {
|
||||||
|
const joinedRooms = this.joinedRooms;
|
||||||
|
const isLastRoomWeAreJoinedTo = joinedRooms && joinedRooms.length == 1 && joinedRooms[0].roomId == roomId;
|
||||||
|
return this.leaveRoom(roomId).then(() => {
|
||||||
|
if (isLastRoomWeAreJoinedTo) {
|
||||||
|
this.$navigation.push({ name: "Goodbye" }, -1);
|
||||||
|
} else {
|
||||||
|
this.$navigation.push({ name: "Home", params: { roomId: null } }, -1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
kickUser(roomId, userId) {
|
||||||
|
if (this.matrixClient && roomId && userId) {
|
||||||
|
this.matrixClient.kick(roomId, userId, "");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
banUser(roomId, userId) {
|
||||||
|
if (this.matrixClient && roomId && userId) {
|
||||||
|
this.matrixClient.ban(roomId, userId, "");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
makeAdmin(roomId, userId) {
|
||||||
|
if (this.matrixClient && roomId && userId) {
|
||||||
|
const room = this.getRoom(roomId);
|
||||||
|
if (room && room.currentState) {
|
||||||
|
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
|
||||||
|
if (powerLevelEvent) {
|
||||||
|
this.matrixClient.setPowerLevel(roomId, userId, 100, powerLevelEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
makeModerator(roomId, userId) {
|
||||||
|
if (this.matrixClient && roomId && userId) {
|
||||||
|
const room = this.getRoom(roomId);
|
||||||
|
console.log("Room", room);
|
||||||
|
if (room && room.currentState) {
|
||||||
|
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
|
||||||
|
if (powerLevelEvent) {
|
||||||
|
this.matrixClient.setPowerLevel(roomId, userId, 50, powerLevelEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
revokeModerator(roomId, userId) {
|
||||||
|
if (this.matrixClient && roomId && userId) {
|
||||||
|
const room = this.getRoom(roomId);
|
||||||
|
if (room && room.currentState) {
|
||||||
|
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
|
||||||
|
if (powerLevelEvent) {
|
||||||
|
this.matrixClient.setPowerLevel(roomId, userId, 0, powerLevelEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the current user is joined to the given room.
|
||||||
|
* @param roomIdOrAlias
|
||||||
|
* @returns Promise<Bool> - Whether the user is joined to the room or not
|
||||||
|
*/
|
||||||
|
isJoinedToRoom(roomIdOrAlias) {
|
||||||
|
if (roomIdOrAlias && this.matrixClient) {
|
||||||
|
try {
|
||||||
|
const resolvedRoomId = roomIdOrAlias.startsWith("#")
|
||||||
|
? this.matrixClient.getRoomIdForAlias(roomIdOrAlias).then((res) => res.room_id)
|
||||||
|
: Promise.resolve(roomIdOrAlias);
|
||||||
|
return resolvedRoomId.then((roomId) => {
|
||||||
|
return this.matrixClient.getJoinedRooms().then((rooms) => {
|
||||||
|
return rooms.joined_rooms.includes(roomId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (ignorederror) {
|
||||||
|
console.error(ignorederror);
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.resolve(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
isReadOnlyRoom(roomId) {
|
||||||
|
if (this.matrixClient && roomId) {
|
||||||
|
const room = this.getRoom(roomId);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
setReadOnlyRoom(roomId, readOnly) {
|
||||||
|
if (this.matrixClient && roomId) {
|
||||||
|
const room = this.getRoom(roomId);
|
||||||
|
if (room && room.currentState) {
|
||||||
|
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
|
||||||
|
if (powerLevelEvent) {
|
||||||
|
let content = powerLevelEvent.getContent();
|
||||||
|
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:
|
* Purge the room with the given id! This means:
|
||||||
* - Make room invite only
|
* - Make room invite only
|
||||||
|
|
@ -513,6 +780,30 @@ export default {
|
||||||
* @param roomId
|
* @param roomId
|
||||||
*/
|
*/
|
||||||
purgeRoom(roomId, statusCallback) {
|
purgeRoom(roomId, statusCallback) {
|
||||||
|
this.currentRoomBeingPurged = true;
|
||||||
|
|
||||||
|
//console.log("Purge room");
|
||||||
|
|
||||||
|
const sleep = (ms) => {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
};
|
||||||
|
|
||||||
|
const withRetry = (codeBlock) => {
|
||||||
|
return codeBlock().catch((error) => {
|
||||||
|
if (error && error.errcode == "M_LIMIT_EXCEEDED") {
|
||||||
|
var retry = 1000;
|
||||||
|
if (error.data) {
|
||||||
|
const retryIn = error.data.retry_after_ms;
|
||||||
|
retry = Math.max(retry, retryIn ? retryIn : 0);
|
||||||
|
}
|
||||||
|
console.log("Rate limited, retry in", retry);
|
||||||
|
return sleep(retry).then(() => withRetry(codeBlock));
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const oldGlobalErrorSetting = this.matrixClient.getGlobalErrorOnUnknownDevices();
|
const oldGlobalErrorSetting = this.matrixClient.getGlobalErrorOnUnknownDevices();
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const room = this.getRoom(roomId);
|
const room = this.getRoom(roomId);
|
||||||
|
|
@ -521,22 +812,39 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove any possible pending events
|
||||||
|
room.getLiveTimeline().getEvents().filter((e) => [EventStatus.ENCRYPTING, sdk.EventStatus.QUEUED].includes(e.status)).forEach((e) => {
|
||||||
|
//console.log("Cancel pending event!");
|
||||||
|
this.matrixClient.cancelPendingEvent(e);
|
||||||
|
});
|
||||||
|
|
||||||
const timelineWindow = new TimelineWindow(this.matrixClient, room.getUnfilteredTimelineSet(), {});
|
const timelineWindow = new TimelineWindow(this.matrixClient, room.getUnfilteredTimelineSet(), {});
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
//console.log("Purge: set invite only");
|
//console.log("Purge: set invite only");
|
||||||
statusCallback(this.$t("room.purge_set_room_state"));
|
statusCallback(this.$t("room.purge_set_room_state"));
|
||||||
this.matrixClient
|
withRetry(() => this.matrixClient.sendStateEvent(roomId, "m.room.join_rules", { join_rule: "private" }, ""))
|
||||||
.sendStateEvent(roomId, "m.room.join_rules", { join_rule: "invite" }, "")
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
//console.log("Purge: forbid guest access");
|
//console.log("Purge: forbid guest access");
|
||||||
return this.matrixClient.sendStateEvent(roomId, "m.room.guest_access", { guest_access: "forbidden" }, "");
|
return withRetry(() => this.matrixClient.sendStateEvent(
|
||||||
|
roomId,
|
||||||
|
"m.room.guest_access",
|
||||||
|
{ guest_access: "forbidden" },
|
||||||
|
""
|
||||||
|
));
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
//console.log("Purge: set history visibility to 'joined'");
|
//console.log("Purge: set history visibility to 'joined'");
|
||||||
return this.matrixClient.sendStateEvent(roomId, "m.room.history_visibility", {
|
return withRetry(() => this.matrixClient.sendStateEvent(roomId, "m.room.history_visibility", {
|
||||||
history_visibility: "joined",
|
history_visibility: "joined",
|
||||||
});
|
}));
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return withRetry(() => this.matrixClient.sendStateEvent(roomId, STATE_EVENT_ROOM_DELETED, { status: "deleted" }));
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Set message retention 1 minute (may be limited by server)
|
||||||
|
return withRetry(() => this.matrixClient.sendStateEvent(roomId, "m.room.retention", { max_lifetime: 60000 }));
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
//console.log("Purge: create timeline");
|
//console.log("Purge: create timeline");
|
||||||
|
|
@ -546,8 +854,11 @@ export default {
|
||||||
const getMoreIfAvailable = function _getMoreIfAvailable() {
|
const getMoreIfAvailable = function _getMoreIfAvailable() {
|
||||||
if (timelineWindow.canPaginate(EventTimeline.BACKWARDS)) {
|
if (timelineWindow.canPaginate(EventTimeline.BACKWARDS)) {
|
||||||
//console.log("Purge: page back");
|
//console.log("Purge: page back");
|
||||||
return timelineWindow.paginate(EventTimeline.BACKWARDS, 100, true, 5).then((ignoredsuccess) => {
|
return timelineWindow.paginate(EventTimeline.BACKWARDS, 100, true, 5).then((gotmore) => {
|
||||||
|
if (gotmore) {
|
||||||
return _getMoreIfAvailable.call(self);
|
return _getMoreIfAvailable.call(self);
|
||||||
|
}
|
||||||
|
return Promise.resolve("Done");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve("Done");
|
return Promise.resolve("Done");
|
||||||
|
|
@ -560,40 +871,92 @@ export default {
|
||||||
statusCallback(this.$t("room.purge_redacting_events"));
|
statusCallback(this.$t("room.purge_redacting_events"));
|
||||||
// First ignore unknown device errors
|
// First ignore unknown device errors
|
||||||
this.matrixClient.setGlobalErrorOnUnknownDevices(false);
|
this.matrixClient.setGlobalErrorOnUnknownDevices(false);
|
||||||
var redactionPromises = [];
|
const allEvents = timelineWindow.getEvents().filter((event) => {
|
||||||
timelineWindow.getEvents().forEach((event) => {
|
return (
|
||||||
if (!event.isRedacted() && !event.isRedaction() && !event.isState()) {
|
!event.isRedacted() &&
|
||||||
// Redact!
|
!event.isRedaction() &&
|
||||||
redactionPromises.push(this.matrixClient.redactEvent(event.getRoomId(), event.getId()));
|
!event.isState() &&
|
||||||
}
|
(!room.currentState || room.currentState.maySendRedactionForEvent(event, this.currentUserId))
|
||||||
|
);
|
||||||
});
|
});
|
||||||
return Promise.all(redactionPromises);
|
|
||||||
|
const redactFirstEvent = (events) => {
|
||||||
|
statusCallback(
|
||||||
|
this.$t("room.purge_redacting_events", {
|
||||||
|
count: allEvents.length - events.length + 1,
|
||||||
|
total: allEvents.length,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
if (events.length == 0) {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
const event = events[0];
|
||||||
|
return withRetry(() => this.matrixClient.redactEvent(event.getRoomId(), event.getId())).then(() =>
|
||||||
|
redactFirstEvent(events.slice(1))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return redactFirstEvent(allEvents);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
//console.log("Purge: kick members");
|
//console.log("Purge: kick members");
|
||||||
statusCallback(this.$t("room.purge_removing_members"));
|
statusCallback(this.$t("room.purge_removing_members"));
|
||||||
var joined = room.getMembersWithMembership("join");
|
var joined = room.getMembersWithMembership("join");
|
||||||
var invited = room.getMembersWithMembership("invite");
|
var invited = room.getMembersWithMembership("invite");
|
||||||
var members = joined.concat(invited);
|
var allMembers = joined.concat(invited);
|
||||||
|
|
||||||
var kickPromises = [];
|
const me = allMembers.find((m) => m.userId == self.currentUserId);
|
||||||
members.forEach((member) => {
|
|
||||||
if (member.userId != self.currentUserId) {
|
const kickFirstMember = (members) => {
|
||||||
kickPromises.push(this.matrixClient.kick(roomId, member.userId, "Room Deleted"));
|
//console.log(`Kicking ${members.length} members`);
|
||||||
|
statusCallback(
|
||||||
|
this.$t("room.purge_removing_members", {
|
||||||
|
count: allMembers.length - members.length + 1,
|
||||||
|
total: allMembers.length,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
if (members.length == 0) {
|
||||||
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
});
|
const member = members[0];
|
||||||
return Promise.all(kickPromises);
|
if (member.userId == self.currentUserId) {
|
||||||
|
return kickFirstMember(members.slice(1));
|
||||||
|
} else {
|
||||||
|
// Slight pause to avoid rate limiting.
|
||||||
|
return sleep(0.1)
|
||||||
|
.then(() => withRetry(() => {
|
||||||
|
if (member.membership == "invite" && me && me.powerLevel <= member.powerLevel) {
|
||||||
|
// The user is invited, but we can't kick them because of power levels.
|
||||||
|
// Send a new invite with reason set to "Room Deleted".
|
||||||
|
// The client will be sent stripped room state, and can from that see the
|
||||||
|
// join_rule of "private". It will then "leave", i.e. reject the invite.
|
||||||
|
return this.matrixClient.invite(roomId, member.userId, "Room Deleted");
|
||||||
|
}
|
||||||
|
return this.matrixClient.kick(roomId, member.userId, "Room Deleted")
|
||||||
|
}))
|
||||||
|
.then(() => kickFirstMember(members.slice(1)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return kickFirstMember(allMembers);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return withRetry(() =>
|
||||||
|
this.matrixClient.sendStateEvent(roomId, STATE_EVENT_ROOM_DELETED, { status: "deleted" })
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
statusCallback(null);
|
statusCallback(null);
|
||||||
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
|
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
|
||||||
return this.leaveRoom(roomId);
|
return withRetry(() => this.leaveRoom(roomId));
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
this.currentRoomBeingPurged = false;
|
||||||
resolve(true); // Done!
|
resolve(true); // Done!
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Error purging room", err);
|
console.error("Error purging room", err);
|
||||||
|
this.currentRoomBeingPurged = false;
|
||||||
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
|
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
|
|
@ -649,7 +1012,17 @@ export default {
|
||||||
type: "m.room.history_visibility",
|
type: "m.room.history_visibility",
|
||||||
state_key: "",
|
state_key: "",
|
||||||
content: {
|
content: {
|
||||||
history_visibility: "joined",
|
history_visibility: "invited",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "m.room.power_levels",
|
||||||
|
state_key: "",
|
||||||
|
content: {
|
||||||
|
users: {
|
||||||
|
[this.currentUserId]: 100,
|
||||||
|
[userId]: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -672,7 +1045,7 @@ export default {
|
||||||
* @param {*} userId
|
* @param {*} userId
|
||||||
*/
|
*/
|
||||||
isDirectRoomWith(room, userId) {
|
isDirectRoomWith(room, userId) {
|
||||||
if (room.getJoinRule() == "invite" && room.getMembers().length == 2) {
|
if (room && room.getJoinRule() == "invite" && room.getMembers().length == 2) {
|
||||||
let other = room.getMember(userId);
|
let other = room.getMember(userId);
|
||||||
if (other) {
|
if (other) {
|
||||||
if (room.getMyMembership() == "invite" && other.membership == "join") {
|
if (room.getMyMembership() == "invite" && other.membership == "join") {
|
||||||
|
|
@ -687,6 +1060,20 @@ export default {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if this room is a direct room with one other user. NOTE: this currently
|
||||||
|
* only checks number of members, not any is_direct flag.
|
||||||
|
* @param { } room
|
||||||
|
*/
|
||||||
|
isDirectRoom(room) {
|
||||||
|
// TODO - Use the is_direct accountData flag (m.direct). WE (as the client)
|
||||||
|
// apprently need to set this...
|
||||||
|
if (room && room.getJoinRule() == "invite" && room.getMembers().length == 2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
on(event, handler) {
|
on(event, handler) {
|
||||||
if (this.matrixClient) {
|
if (this.matrixClient) {
|
||||||
this.matrixClient.on(event, handler);
|
this.matrixClient.on(event, handler);
|
||||||
|
|
@ -699,6 +1086,17 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setUserDisplayName(name) {
|
||||||
|
if (this.matrixClient) {
|
||||||
|
return this.matrixClient
|
||||||
|
.setDisplayName(name || this.user.userId)
|
||||||
|
.then(() => (this.userDisplayName = name))
|
||||||
|
.catch((err) => console.err("Failed to set display name", err));
|
||||||
|
} else {
|
||||||
|
return Promise.reject("No matrix client");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
setPassword(oldPassword, newPassword) {
|
setPassword(oldPassword, newPassword) {
|
||||||
if (this.matrixClient && this.currentUser) {
|
if (this.matrixClient && this.currentUser) {
|
||||||
const authDict = {
|
const authDict = {
|
||||||
|
|
@ -732,31 +1130,26 @@ export default {
|
||||||
return this.matrixClient.uploadContent(file, opts);
|
return this.matrixClient.uploadContent(file, opts);
|
||||||
},
|
},
|
||||||
|
|
||||||
getPublicRoomInfo(roomId) {
|
/**
|
||||||
if (!roomId) {
|
* Get a matrix client that can be used for public queries. If we are logged in, this is the normal
|
||||||
return Promise.reject("Invalid parameters");
|
* matrix client. If not, we create a temp one with a temp password.
|
||||||
}
|
* @returns A MatrixClient that can be used for public queries
|
||||||
|
*/
|
||||||
const parts = roomId.split(":");
|
getPublicQueryMatrixClient() {
|
||||||
if (parts.length != 2) {
|
|
||||||
return Promise.reject("Unknown room server");
|
|
||||||
}
|
|
||||||
const server = parts[1];
|
|
||||||
|
|
||||||
var clientPromise;
|
|
||||||
if (this.matrixClient) {
|
if (this.matrixClient) {
|
||||||
clientPromise = this.getMatrixClient().then(() => {
|
return this.getMatrixClient().then(() => {
|
||||||
return this.matrixClient;
|
return this.matrixClient;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const tempMatrixClient = sdk.createClient({
|
|
||||||
baseUrl: this.$config.defaultServer,
|
|
||||||
});
|
|
||||||
var tempUserString = this.$store.state.tempuser;
|
var tempUserString = this.$store.state.tempuser;
|
||||||
var tempUser = null;
|
var tempUser = null;
|
||||||
if (tempUserString) {
|
if (tempUserString) {
|
||||||
tempUser = JSON.parse(tempUserString);
|
tempUser = JSON.parse(tempUserString);
|
||||||
}
|
}
|
||||||
|
return util.getMatrixBaseUrl(tempUser, this.$config).then((baseUrl) => {
|
||||||
|
const tempMatrixClient = sdk.createClient({ baseUrl: baseUrl });
|
||||||
|
|
||||||
|
var clientPromise;
|
||||||
|
|
||||||
// Need to create an account?
|
// Need to create an account?
|
||||||
//
|
//
|
||||||
|
|
@ -799,7 +1192,7 @@ export default {
|
||||||
// Only used to get public room info from.
|
// Only used to get public room info from.
|
||||||
clientPromise = clientPromise.then((user) => {
|
clientPromise = clientPromise.then((user) => {
|
||||||
var opts = {
|
var opts = {
|
||||||
baseUrl: this.$config.defaultServer,
|
baseUrl: baseUrl,
|
||||||
userId: user.user_id,
|
userId: user.user_id,
|
||||||
accessToken: user.access_token,
|
accessToken: user.access_token,
|
||||||
timelineSupport: false,
|
timelineSupport: false,
|
||||||
|
|
@ -808,16 +1201,33 @@ export default {
|
||||||
matrixClient.startClient();
|
matrixClient.startClient();
|
||||||
return matrixClient;
|
return matrixClient;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return clientPromise;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getPublicRoomInfo(roomId) {
|
||||||
|
if (!roomId) {
|
||||||
|
return Promise.reject("Invalid parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
const findOrGetMore = function _findOrGetMore(client, response) {
|
const parts = roomId.split(":");
|
||||||
|
if (parts.length != 2) {
|
||||||
|
return Promise.reject("Unknown room server");
|
||||||
|
}
|
||||||
|
const server = parts[1];
|
||||||
|
|
||||||
|
const clientPromise = this.getPublicQueryMatrixClient();
|
||||||
|
|
||||||
|
const findOrGetMore = function _findOrGetMore(client, useAuthedMedia, response) {
|
||||||
for (var room of response.chunk) {
|
for (var room of response.chunk) {
|
||||||
if (
|
if (
|
||||||
(roomId.startsWith("#") && room.canonical_alias == roomId) ||
|
(roomId.startsWith("#") && room.canonical_alias == roomId) ||
|
||||||
(roomId.startsWith("!") && room.room_id == roomId)
|
(roomId.startsWith("!") && room.room_id == roomId)
|
||||||
) {
|
) {
|
||||||
if (room.avatar_url) {
|
if (room.avatar_url) {
|
||||||
room.avatar = client.mxcUrlToHttp(room.avatar_url, 80, 80, "scale", true);
|
room["avatar"] = client.mxcUrlToHttp(room.avatar_url, 80, 80, "scale", false, undefined, useAuthedMedia);
|
||||||
}
|
}
|
||||||
return Promise.resolve(room);
|
return Promise.resolve(room);
|
||||||
}
|
}
|
||||||
|
|
@ -841,13 +1251,18 @@ export default {
|
||||||
};
|
};
|
||||||
|
|
||||||
var matrixClient;
|
var matrixClient;
|
||||||
|
let useAuthedMedia = false;
|
||||||
return clientPromise
|
return clientPromise
|
||||||
.then((client) => {
|
.then((client) => {
|
||||||
matrixClient = client;
|
matrixClient = client;
|
||||||
|
return client.isVersionSupported("v1.11");
|
||||||
|
})
|
||||||
|
.then((version1_11) => {
|
||||||
|
useAuthedMedia = version1_11;
|
||||||
return matrixClient.publicRooms({ server: server, limit: 1000 });
|
return matrixClient.publicRooms({ server: server, limit: 1000 });
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
return findOrGetMore(matrixClient, response);
|
return findOrGetMore(matrixClient, useAuthedMedia, response);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
return Promise.reject("Failed to find room: " + err);
|
return Promise.reject("Failed to find room: " + err);
|
||||||
|
|
@ -861,6 +1276,33 @@ export default {
|
||||||
});
|
});
|
||||||
this.notificationCount = count;
|
this.notificationCount = count;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setEventPinned(room, event, pinned) {
|
||||||
|
if (room && room.currentState && event) {
|
||||||
|
const pinnedMessagesEvent = room.currentState.getStateEvents("m.room.pinned_events", "");
|
||||||
|
const content = pinnedMessagesEvent ? pinnedMessagesEvent.getContent() : {}
|
||||||
|
let pinnedEvents = content["pinned"] || [];
|
||||||
|
if (pinned && !pinnedEvents.includes(event.getId())) {
|
||||||
|
pinnedEvents.push(event.getId());
|
||||||
|
} else if (!pinned && pinnedEvents.includes(event.getId())) {
|
||||||
|
pinnedEvents = pinnedEvents.filter((e) => e != event.getId());
|
||||||
|
} else {
|
||||||
|
return; // no change
|
||||||
|
}
|
||||||
|
content.pinned = pinnedEvents;
|
||||||
|
this.matrixClient.sendStateEvent(room.roomId, "m.room.pinned_events", content);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getPinnedEvents(room) {
|
||||||
|
if (room && room.currentState) {
|
||||||
|
const pinnedMessagesEvent = room.currentState.getStateEvents("m.room.pinned_events", "");
|
||||||
|
const content = pinnedMessagesEvent ? pinnedMessagesEvent.getContent() : {}
|
||||||
|
return content["pinned"] || [];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
render: () => {}
|
render: () => {}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue