Merge pull request #358 from vector-im/bwindels/joinroom

Offer to join unknown room
This commit is contained in:
Bruno Windels 2021-05-18 09:59:35 +00:00 committed by GitHub
commit 63620ce59a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 159 additions and 7 deletions

View file

@ -36,6 +36,7 @@ This is also why there is an explicit initialize method, see comment there.
export class RoomViewModelObservable extends ObservableValue {
constructor(sessionViewModel, roomId) {
super(null);
this._statusSubscription = null;
this._sessionViewModel = sessionViewModel;
this.id = roomId;
}
@ -48,9 +49,9 @@ export class RoomViewModelObservable extends ObservableValue {
*/
async initialize() {
const {session} = this._sessionViewModel._sessionContainer;
this._statusObservable = await session.observeRoomStatus(this.id);
this.set(await this._statusToViewModel(this._statusObservable.get()));
this._statusObservable.subscribe(async status => {
const statusObservable = await session.observeRoomStatus(this.id);
this.set(await this._statusToViewModel(statusObservable.get()));
this._statusSubscription = statusObservable.subscribe(async status => {
// first dispose existing VM, if any
this.get()?.dispose();
this.set(await this._statusToViewModel(status));
@ -64,8 +65,9 @@ export class RoomViewModelObservable extends ObservableValue {
return this._sessionViewModel._createRoomViewModel(this.id);
} else if (status.archived) {
return await this._sessionViewModel._createArchivedRoomViewModel(this.id);
} else {
return this._sessionViewModel._createUnknownRoomViewModel(this.id);
}
return null;
}
dispose() {

View file

@ -17,6 +17,7 @@ limitations under the License.
import {LeftPanelViewModel} from "./leftpanel/LeftPanelViewModel.js";
import {RoomViewModel} from "./room/RoomViewModel.js";
import {UnknownRoomViewModel} from "./room/UnknownRoomViewModel.js";
import {InviteViewModel} from "./room/InviteViewModel.js";
import {LightboxViewModel} from "./room/LightboxViewModel.js";
import {SessionStatusViewModel} from "./SessionStatusViewModel.js";
@ -162,6 +163,13 @@ export class SessionViewModel extends ViewModel {
return null;
}
_createUnknownRoomViewModel(roomIdOrAlias) {
return new UnknownRoomViewModel(this.childOptions({
roomIdOrAlias,
session: this._sessionContainer.session,
}));
}
async _createArchivedRoomViewModel(roomId) {
const room = await this._sessionContainer.session.loadArchivedRoom(roomId);
if (room) {

View file

@ -147,6 +147,14 @@ export class RoomViewModel extends ViewModel {
forgetRoom() {
this._room.forget();
}
get canRejoin() {
return this._room.isArchived;
}
rejoinRoom() {
this._room.join();
}
async _sendMessage(message) {
if (!this._room.isArchived && message) {

View file

@ -0,0 +1,58 @@
/*
Copyright 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {ViewModel} from "../../ViewModel.js";
export class UnknownRoomViewModel extends ViewModel {
constructor(options) {
super(options);
const {roomIdOrAlias, session} = options;
this._session = session;
this.roomIdOrAlias = roomIdOrAlias;
this._error = null;
this._busy = false;
}
get error() {
return this._error?.message;
}
async join() {
this._busy = true;
this.emitChange("busy");
try {
const roomId = await this._session.joinRoom(this.roomIdOrAlias);
// navigate to roomId if we were at the alias
// so we're subscribed to the right room status
// and we'll switch to the room view model once
// the join is synced
this.navigation.push("room", roomId);
// keep busy on true while waiting for the join to sync
} catch (err) {
this._error = err;
this._busy = false;
this.emitChange("error");
}
}
get busy() {
return this._busy;
}
get kind() {
return "unknown";
}
}

View file

@ -717,6 +717,13 @@ export class Session {
}
});
}
joinRoom(roomIdOrAlias, log = null) {
return this._platform.logger.wrapOrRun(log, "joinRoom", async log => {
const body = await this._hsApi.joinIdOrAlias(roomIdOrAlias, {log}).response();
return body.room_id;
});
}
}
export function tests() {

View file

@ -190,6 +190,10 @@ export class HomeServerApi {
return this._post(`/rooms/${encodeURIComponent(roomId)}/join`, null, null, options);
}
joinIdOrAlias(roomIdOrAlias, options = null) {
return this._post(`/join/${encodeURIComponent(roomIdOrAlias)}`, null, null, options);
}
leave(roomId, options = null) {
return this._post(`/rooms/${encodeURIComponent(roomId)}/leave`, null, null, options);
}

View file

@ -162,6 +162,12 @@ export class ArchivedRoom extends BaseRoom {
this._forgetCallback(this.id);
});
}
join(log = null) {
return this._platform.logger.wrapOrRun(log, "rejoin archived room", async log => {
await this._hsApi.join(this.id, {log}).response();
});
}
}
function findKickDetails(roomResponse, ownUserId) {

View file

@ -910,4 +910,22 @@ button.link {
.RoomArchivedView h3 {
margin: 0;
}
.UnknownRoomView {
align-items: center;
justify-content: center;
text-align: center;
padding: 16px;
box-sizing: border-box;
}
.UnknownRoomView h2 {
word-break: break-all;
word-break: break-word;
}
.UnknownRoomView button {
max-width: 200px;
width: 100%;
}

View file

@ -17,6 +17,7 @@ limitations under the License.
import {LeftPanelView} from "./leftpanel/LeftPanelView.js";
import {RoomView} from "./room/RoomView.js";
import {UnknownRoomView} from "./room/UnknownRoomView.js";
import {InviteView} from "./room/InviteView.js";
import {LightboxView} from "./room/LightboxView.js";
import {TemplateView} from "../general/TemplateView.js";
@ -43,8 +44,10 @@ export class SessionView extends TemplateView {
} else if (vm.currentRoomViewModel) {
if (vm.currentRoomViewModel.kind === "invite") {
return new InviteView(vm.currentRoomViewModel);
} else {
} else if (vm.currentRoomViewModel.kind === "room") {
return new RoomView(vm.currentRoomViewModel);
} else {
return new UnknownRoomView(vm.currentRoomViewModel);
}
} else {
return new StaticView(t => t.div({className: "room-placeholder"}, t.h2(vm.i18n`Choose a room on the left side.`)));

View file

@ -73,6 +73,9 @@ export class RoomView extends TemplateView {
if (vm.canForget) {
options.push(Menu.option(vm.i18n`Forget room`, () => vm.forgetRoom()));
}
if (vm.canRejoin) {
options.push(Menu.option(vm.i18n`Rejoin room`, () => vm.rejoinRoom()));
}
if (!options.length) {
return;
}
@ -86,8 +89,8 @@ export class RoomView extends TemplateView {
},
vertical: {
relativeTo: "start",
align: "start",
after: 40 + 4
align: "end",
before: -32 - 4
}
});
}

View file

@ -0,0 +1,35 @@
/*
Copyright 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {TemplateView} from "../../general/TemplateView.js";
export class UnknownRoomView extends TemplateView {
render(t, vm) {
return t.main({className: "UnknownRoomView middle"}, t.div([
t.h2([
vm.i18n`You are currently not in ${vm.roomIdOrAlias}.`,
t.br(),
vm.i18n`Want to join it?`
]),
t.button({
className: "button-action primary",
onClick: () => vm.join(),
disabled: vm => vm.busy,
}, vm.i18n`Join room`),
t.if(vm => vm.error, t => t.p({className: "error"}, vm.error))
]));
}
}