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 id() { return this._roomBeingCreated.id; }
|
||||
get isEncrypted() { return this._roomBeingCreated.isEncrypted; }
|
||||
|
||||
get avatarLetter() {
|
||||
return avatarInitials(this.name);
|
||||
}
|
||||
|
||||
get avatarColorNumber() {
|
||||
return getIdentifierColorNumber(this._roomBeingCreated.avatarColorId);
|
||||
}
|
||||
get error() { return this._roomBeingCreated.error?.message; }
|
||||
get avatarLetter() { return avatarInitials(this.name); }
|
||||
get avatarColorNumber() { return getIdentifierColorNumber(this._roomBeingCreated.avatarColorId); }
|
||||
get avatarTitle() { return this.name; }
|
||||
|
||||
avatarUrl(size) {
|
||||
return getAvatarHttpUrl(this._roomBeingCreated.avatarUrl, size, this.platform, this._mediaRepository);
|
||||
}
|
||||
|
||||
get avatarTitle() {
|
||||
return this.name;
|
||||
// allow blob url which doesn't need mxc => http resolution
|
||||
return this._roomBeingCreated.avatarBlobUrl ??
|
||||
getAvatarHttpUrl(this._roomBeingCreated.avatarUrl, size, this.platform, this._mediaRepository);
|
||||
}
|
||||
|
||||
focus() {}
|
||||
|
@ -57,6 +51,12 @@ export class RoomBeingCreatedViewModel extends ViewModel {
|
|||
this.emitChange();
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._roomBeingCreated.cancel();
|
||||
// navigate away from the room
|
||||
this.navigation.applyPath(this.navigation.path.until("session"));
|
||||
}
|
||||
|
||||
dispose() {
|
||||
super.dispose();
|
||||
this._roomBeingCreated.off("change", this._onRoomChange);
|
||||
|
|
|
@ -92,6 +92,7 @@ export class RoomBeingCreated extends EventEmitter<{change: never}> {
|
|||
public readonly isEncrypted: boolean;
|
||||
private _calculatedName: string;
|
||||
private _error?: Error;
|
||||
private _isCancelled = false;
|
||||
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
|
@ -189,17 +190,25 @@ export class RoomBeingCreated extends EventEmitter<{change: never}> {
|
|||
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 avatarUrl(): string | undefined { return this.profiles?.[0]?.avatarUrl; }
|
||||
get avatarBlobUrl(): string | undefined { return this.options.avatar?.blob?.url; }
|
||||
get roomId(): string | undefined { return this._roomId; }
|
||||
get name() { return this._calculatedName; }
|
||||
get isBeingCreated(): boolean { return true; }
|
||||
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() {
|
||||
if (this.options.avatar) {
|
||||
this.options.avatar.blob.dispose();
|
||||
|
|
|
@ -1095,10 +1095,17 @@ button.RoomDetailsView_row::after {
|
|||
gap: 12px;
|
||||
}
|
||||
|
||||
.CreateRoomView {
|
||||
padding: 0 12px;
|
||||
justify-self: center;
|
||||
.CreateRoomView, .RoomBeingCreated_error {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.RoomBeingCreated_error {
|
||||
margin-top: 48px;
|
||||
}
|
||||
|
||||
.centered-column {
|
||||
padding: 0 12px;
|
||||
align-self: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
|
|
@ -21,70 +21,72 @@ import {StaticView} from "../general/StaticView";
|
|||
|
||||
export class CreateRoomView extends TemplateView {
|
||||
render(t, vm) {
|
||||
return t.main({className: "CreateRoomView middle"}, [
|
||||
t.h2("Create room"),
|
||||
//t.div({className: "RoomView_error"}, vm => vm.error),
|
||||
t.form({className: "CreateRoomView_detailsForm form", onChange: evt => this.onFormChange(evt), onSubmit: evt => this.onSubmit(evt)}, [
|
||||
t.div({className: "vertical-layout"}, [
|
||||
t.button({type: "button", className: "CreateRoomView_selectAvatar", onClick: () => vm.selectAvatar()},
|
||||
t.mapView(vm => vm.hasAvatar, hasAvatar => {
|
||||
if (hasAvatar) {
|
||||
return new AvatarView(vm, 64);
|
||||
} else {
|
||||
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`),
|
||||
return t.main({className: "middle"},
|
||||
t.div({className: "CreateRoomView centered-column"}, [
|
||||
t.h2("Create room"),
|
||||
//t.div({className: "RoomView_error"}, vm => vm.error),
|
||||
t.form({className: "CreateRoomView_detailsForm form", onChange: evt => this.onFormChange(evt), onSubmit: evt => this.onSubmit(evt)}, [
|
||||
t.div({className: "vertical-layout"}, [
|
||||
t.button({type: "button", className: "CreateRoomView_selectAvatar", onClick: () => vm.selectAvatar()},
|
||||
t.mapView(vm => vm.hasAvatar, hasAvatar => {
|
||||
if (hasAvatar) {
|
||||
return new AvatarView(vm, 64);
|
||||
} else {
|
||||
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.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({
|
||||
onInput: evt => vm.setName(evt.target.value),
|
||||
type: "text", name: "name", id: "name",
|
||||
placeholder: vm.i18n`Enter a room name`
|
||||
}, vm => vm.name),
|
||||
onInput: evt => vm.setRoomAlias(evt.target.value),
|
||||
type: "text", name: "roomAlias", id: "roomAlias",
|
||||
placeholder: vm.i18n`Room alias
|
||||
`}),
|
||||
]),
|
||||
]),
|
||||
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: "button-row"}, [
|
||||
t.button({
|
||||
className: "button-action primary",
|
||||
type: "submit",
|
||||
disabled: vm => !vm.canCreate
|
||||
}, vm.i18n`Create room`),
|
||||
]),
|
||||
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) {
|
||||
|
|
|
@ -16,10 +16,43 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {TemplateView} from "../../general/TemplateView";
|
||||
import {LoadingView} from "../../general/LoadingView";
|
||||
import {AvatarView} from "../../AvatarView";
|
||||
import {renderStaticAvatar} from "../../avatar.js";
|
||||
|
||||
export class RoomBeingCreatedView extends TemplateView {
|
||||
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