forked from mystiq/hydrogen-web
improve RoomBeingCreatedView, allow removing the roombeingcreated
This commit is contained in:
parent
20493f9e87
commit
b5536830d0
5 changed files with 132 additions and 81 deletions
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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`))
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue