diff --git a/src/domain/session/JoinRoomViewModel.ts b/src/domain/session/JoinRoomViewModel.ts new file mode 100644 index 00000000..a4be548b --- /dev/null +++ b/src/domain/session/JoinRoomViewModel.ts @@ -0,0 +1,63 @@ +/* +Copyright 2022 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, Options as BaseOptions} from "../ViewModel"; +import {SegmentType} from "../navigation/index"; +import type {Session} from "../../matrix/Session.js"; +import {joinRoom} from "../../matrix/room/joinRoom"; + +type Options = BaseOptions & { + session: Session; +}; + +export class JoinRoomViewModel extends ViewModel { + private _session: Session; + private _joinInProgress: boolean = false; + private _error: Error | undefined; + + constructor(options: Readonly) { + super(options); + this._session = options.session; + } + + async join(roomId: string) { + this._error = undefined; + this._joinInProgress = true; + this.emitChange("joinInProgress"); + try { + const id = await joinRoom(roomId, this._session); + this.navigation.push("room", id); + } + catch (e) { + this._error = e; + this._joinInProgress = false; + this.emitChange("error"); + } + } + + get joinInProgress(): boolean { + return this._joinInProgress; + } + + get status(): string | undefined { + if (this._error) { + return this._error.message; + } + else if(this._joinInProgress){ + return "Joining room"; + } + } +} diff --git a/src/platform/web/ui/session/JoinRoomView.ts b/src/platform/web/ui/session/JoinRoomView.ts new file mode 100644 index 00000000..bc6d751f --- /dev/null +++ b/src/platform/web/ui/session/JoinRoomView.ts @@ -0,0 +1,63 @@ +/* +Copyright 2022 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"; +import type {JoinRoomViewModel} from "../../../../domain/session/JoinRoomViewModel"; +import {spinner} from "../common.js"; + +export class JoinRoomView extends TemplateView { + render(t, vm) { + const input = t.input({ + type: "text", + name: "id", + id: "id", + placeholder: vm.i18n`Enter a room id`, + disabled: vm => vm.joinInProgress, + }); + return t.main({className: "middle"}, + t.div({className: "JoinRoomView centered-column"}, [ + t.h2("Join room"), + t.form({className: "JoinRoomView_detailsForm form", onSubmit: evt => this.onSubmit(evt, input.value)}, [ + t.div({className: "vertical-layout"}, [ + t.div({className: "stretch form-row text"}, [ + t.label({for: "id"}, vm.i18n`Room id`), + input, + ]), + ]), + t.div({className: "button-row"}, [ + t.button({ + className: "button-action primary", + type: "submit", + disabled: vm => vm.joinInProgress + }, vm.i18n`Join`), + ]), + t.map(vm => vm.status, (status, t) => { + return t.div({ className: "JoinRoomView_status" }, [ + spinner(t, { hidden: vm => !vm.joinInProgress }), + t.span(status), + ]); + }) + ]) + ]) + ); + } + + onSubmit(evt, id) { + evt.preventDefault(); + this.value.join(id); + } +} +