improve RoomBeingCreatedView, allow removing the roombeingcreated

This commit is contained in:
Bruno Windels 2022-02-10 11:07:29 +01:00
parent 20493f9e87
commit b5536830d0
5 changed files with 132 additions and 81 deletions

View file

@ -34,21 +34,15 @@ export class RoomBeingCreatedViewModel extends ViewModel {
get name() { return this._roomBeingCreated.name; } get name() { return this._roomBeingCreated.name; }
get id() { return this._roomBeingCreated.id; } get id() { return this._roomBeingCreated.id; }
get isEncrypted() { return this._roomBeingCreated.isEncrypted; } get isEncrypted() { return this._roomBeingCreated.isEncrypted; }
get error() { return this._roomBeingCreated.error?.message; }
get avatarLetter() { get avatarLetter() { return avatarInitials(this.name); }
return avatarInitials(this.name); get avatarColorNumber() { return getIdentifierColorNumber(this._roomBeingCreated.avatarColorId); }
} get avatarTitle() { return this.name; }
get avatarColorNumber() {
return getIdentifierColorNumber(this._roomBeingCreated.avatarColorId);
}
avatarUrl(size) { avatarUrl(size) {
return getAvatarHttpUrl(this._roomBeingCreated.avatarUrl, size, this.platform, this._mediaRepository); // allow blob url which doesn't need mxc => http resolution
} return this._roomBeingCreated.avatarBlobUrl ??
getAvatarHttpUrl(this._roomBeingCreated.avatarUrl, size, this.platform, this._mediaRepository);
get avatarTitle() {
return this.name;
} }
focus() {} focus() {}
@ -57,6 +51,12 @@ export class RoomBeingCreatedViewModel extends ViewModel {
this.emitChange(); this.emitChange();
} }
cancel() {
this._roomBeingCreated.cancel();
// navigate away from the room
this.navigation.applyPath(this.navigation.path.until("session"));
}
dispose() { dispose() {
super.dispose(); super.dispose();
this._roomBeingCreated.off("change", this._onRoomChange); this._roomBeingCreated.off("change", this._onRoomChange);

View file

@ -92,6 +92,7 @@ export class RoomBeingCreated extends EventEmitter<{change: never}> {
public readonly isEncrypted: boolean; public readonly isEncrypted: boolean;
private _calculatedName: string; private _calculatedName: string;
private _error?: Error; private _error?: Error;
private _isCancelled = false;
constructor( constructor(
public readonly id: string, public readonly id: string,
@ -189,17 +190,25 @@ export class RoomBeingCreated extends EventEmitter<{change: never}> {
this.emit("change"); this.emit("change");
} }
get avatarUrl(): string | undefined { return this.profiles?.[0].avatarUrl; }
get avatarColorId(): string { return this.options.invites?.[0] ?? this._roomId ?? this.id; } get avatarColorId(): string { return this.options.invites?.[0] ?? this._roomId ?? this.id; }
get avatarUrl(): string | undefined { return this.profiles?.[0]?.avatarUrl; }
get avatarBlobUrl(): string | undefined { return this.options.avatar?.blob?.url; } get avatarBlobUrl(): string | undefined { return this.options.avatar?.blob?.url; }
get roomId(): string | undefined { return this._roomId; } get roomId(): string | undefined { return this._roomId; }
get name() { return this._calculatedName; } get name() { return this._calculatedName; }
get isBeingCreated(): boolean { return true; } get isBeingCreated(): boolean { return true; }
get error(): Error | undefined { return this._error; } get error(): Error | undefined { return this._error; }
cancel() {
// TODO: remove from collection somehow
}
cancel() {
if (!this._isCancelled) {
this.dispose();
this._isCancelled = true;
this.emitChange("isCancelled");
}
}
// called from Session when updateCallback is invoked to remove it from the collection
get isCancelled() { return this._isCancelled; }
/** @internal */
dispose() { dispose() {
if (this.options.avatar) { if (this.options.avatar) {
this.options.avatar.blob.dispose(); this.options.avatar.blob.dispose();

View file

@ -1095,10 +1095,17 @@ button.RoomDetailsView_row::after {
gap: 12px; gap: 12px;
} }
.CreateRoomView { .CreateRoomView, .RoomBeingCreated_error {
padding: 0 12px;
justify-self: center;
max-width: 400px; max-width: 400px;
}
.RoomBeingCreated_error {
margin-top: 48px;
}
.centered-column {
padding: 0 12px;
align-self: center;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
} }

View file

@ -21,70 +21,72 @@ import {StaticView} from "../general/StaticView";
export class CreateRoomView extends TemplateView { export class CreateRoomView extends TemplateView {
render(t, vm) { render(t, vm) {
return t.main({className: "CreateRoomView middle"}, [ return t.main({className: "middle"},
t.h2("Create room"), t.div({className: "CreateRoomView centered-column"}, [
//t.div({className: "RoomView_error"}, vm => vm.error), t.h2("Create room"),
t.form({className: "CreateRoomView_detailsForm form", onChange: evt => this.onFormChange(evt), onSubmit: evt => this.onSubmit(evt)}, [ //t.div({className: "RoomView_error"}, vm => vm.error),
t.div({className: "vertical-layout"}, [ t.form({className: "CreateRoomView_detailsForm form", onChange: evt => this.onFormChange(evt), onSubmit: evt => this.onSubmit(evt)}, [
t.button({type: "button", className: "CreateRoomView_selectAvatar", onClick: () => vm.selectAvatar()}, t.div({className: "vertical-layout"}, [
t.mapView(vm => vm.hasAvatar, hasAvatar => { t.button({type: "button", className: "CreateRoomView_selectAvatar", onClick: () => vm.selectAvatar()},
if (hasAvatar) { t.mapView(vm => vm.hasAvatar, hasAvatar => {
return new AvatarView(vm, 64); if (hasAvatar) {
} else { return new AvatarView(vm, 64);
return new StaticView(undefined, t => { } else {
return t.div({className: "CreateRoomView_selectAvatarPlaceholder"}) return new StaticView(undefined, t => {
}); return t.div({className: "CreateRoomView_selectAvatarPlaceholder"})
} });
}) }
), })
t.div({className: "stretch form-row text"}, [ ),
t.label({for: "name"}, vm.i18n`Room name`), t.div({className: "stretch form-row text"}, [
t.label({for: "name"}, vm.i18n`Room name`),
t.input({
onInput: evt => vm.setName(evt.target.value),
type: "text", name: "name", id: "name",
placeholder: vm.i18n`Enter a room name`
}, vm => vm.name),
]),
]),
t.div({className: "form-row text"}, [
t.label({for: "topic"}, vm.i18n`Topic (optional)`),
t.textarea({
onInput: evt => vm.setTopic(evt.target.value),
name: "topic", id: "topic",
placeholder: vm.i18n`Topic`
}),
]),
t.div({className: "form-group"}, [
t.div({className: "form-row check"}, [
t.input({type: "radio", name: "isPublic", id: "isPrivate", value: "false", checked: !vm.isPublic}),
t.label({for: "isPrivate"}, vm.i18n`Private room, only upon invitation.`)
]),
t.div({className: "form-row check"}, [
t.input({type: "radio", name: "isPublic", id: "isPublic", value: "true", checked: vm.isPublic}),
t.label({for: "isPublic"}, vm.i18n`Public room, anyone can join`)
]),
]),
t.div({className: {"form-row check": true, hidden: vm => vm.isPublic}}, [
t.input({type: "checkbox", name: "isEncrypted", id: "isEncrypted", checked: vm.isEncrypted}),
t.label({for: "isEncrypted"}, vm.i18n`Enable end-to-end encryption`)
]),
t.div({className: {"form-row text": true, hidden: vm => !vm.isPublic}}, [
t.label({for: "roomAlias"}, vm.i18n`Room alias`),
t.input({ t.input({
onInput: evt => vm.setName(evt.target.value), onInput: evt => vm.setRoomAlias(evt.target.value),
type: "text", name: "name", id: "name", type: "text", name: "roomAlias", id: "roomAlias",
placeholder: vm.i18n`Enter a room name` placeholder: vm.i18n`Room alias
}, vm => vm.name), `}),
]), ]),
]), t.div({className: "button-row"}, [
t.div({className: "form-row text"}, [ t.button({
t.label({for: "topic"}, vm.i18n`Topic (optional)`), className: "button-action primary",
t.textarea({ type: "submit",
onInput: evt => vm.setTopic(evt.target.value), disabled: vm => !vm.canCreate
name: "topic", id: "topic", }, vm.i18n`Create room`),
placeholder: vm.i18n`Topic`
}),
]),
t.div({className: "form-group"}, [
t.div({className: "form-row check"}, [
t.input({type: "radio", name: "isPublic", id: "isPrivate", value: "false", checked: !vm.isPublic}),
t.label({for: "isPrivate"}, vm.i18n`Private room, only upon invitation.`)
]), ]),
t.div({className: "form-row check"}, [ ])
t.input({type: "radio", name: "isPublic", id: "isPublic", value: "true", checked: vm.isPublic}),
t.label({for: "isPublic"}, vm.i18n`Public room, anyone can join`)
]),
]),
t.div({className: {"form-row check": true, hidden: vm => vm.isPublic}}, [
t.input({type: "checkbox", name: "isEncrypted", id: "isEncrypted", checked: vm.isEncrypted}),
t.label({for: "isEncrypted"}, vm.i18n`Enable end-to-end encryption`)
]),
t.div({className: {"form-row text": true, hidden: vm => !vm.isPublic}}, [
t.label({for: "roomAlias"}, vm.i18n`Room alias`),
t.input({
onInput: evt => vm.setRoomAlias(evt.target.value),
type: "text", name: "roomAlias", id: "roomAlias",
placeholder: vm.i18n`Room alias
`}),
]),
t.div({className: "button-row"}, [
t.button({
className: "button-action primary",
type: "submit",
disabled: vm => !vm.canCreate
}, vm.i18n`Create room`),
]),
]) ])
]); );
} }
onFormChange(evt) { onFormChange(evt) {

View file

@ -16,10 +16,43 @@ limitations under the License.
*/ */
import {TemplateView} from "../../general/TemplateView"; import {TemplateView} from "../../general/TemplateView";
import {LoadingView} from "../../general/LoadingView";
import {AvatarView} from "../../AvatarView";
import {renderStaticAvatar} from "../../avatar.js"; import {renderStaticAvatar} from "../../avatar.js";
export class RoomBeingCreatedView extends TemplateView { export class RoomBeingCreatedView extends TemplateView {
render(t, vm) { render(t, vm) {
return t.h1({className: "middle"}, ["creating room", vm => vm.name]); return t.main({className: "RoomView middle"}, [
t.div({className: "RoomHeader middle-header"}, [
t.a({className: "button-utility close-middle", href: vm.closeUrl, title: vm.i18n`Close room`}),
t.view(new AvatarView(vm, 32)),
t.div({className: "room-description"}, [
t.h2(vm => vm.name),
])
]),
t.div({className: "RoomView_body"}, [
t.mapView(vm => vm.error, error => {
if (error) {
return new ErrorView(vm);
} else {
return new LoadingView(vm.i18n`Setting up the room…`);
}
})
])
]);
}
}
class ErrorView extends TemplateView {
render(t,vm) {
return t.div({className: "RoomBeingCreated_error centered-column"}, [
t.h3(vm.i18n`Could not create the room, something went wrong:`),
t.div({className: "RoomView_error form-group"}, vm.error),
t.div({className: "button-row"},
t.button({
className: "button-action primary destructive",
onClick: () => vm.cancel()
}, vm.i18n`Cancel`))
]);
} }
} }