From fdd4caa0b76b5093722f4d359481586ed11121dc Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 19 Jul 2021 21:03:42 +0530 Subject: [PATCH 01/28] Create vm and view Signed-off-by: RMidhunSuresh --- .../rightpanel/MemberDetailsViewModel.js | 38 +++++++++++++++++++ .../session/rightpanel/MemberDetailsView.js | 12 ++++++ 2 files changed, 50 insertions(+) create mode 100644 src/domain/session/rightpanel/MemberDetailsViewModel.js create mode 100644 src/platform/web/ui/session/rightpanel/MemberDetailsView.js diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js new file mode 100644 index 00000000..a51015b4 --- /dev/null +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -0,0 +1,38 @@ +import {ViewModel} from "../../ViewModel.js"; +import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; + +export class MemberDetailsViewModel extends ViewModel { + constructor(options) { + super(options); + this._observableMember = options.observableMember; + this._mediaRepository = options.mediaRepository; + this._member = this._observableMember.get(); + this.track(this._observableMember.subscribe( () => this._onMemberChange())); + } + + get name() { return this._member.name; } + get userId() { return this._member.userId; } + + get type() { return "member-details"; } + + _onMemberChange() { + this._member = this._observableMember.get(); + this.emitChange(); + } + + get avatarLetter() { + return avatarInitials(this.name); + } + + get avatarColorNumber() { + return getIdentifierColorNumber(this.userId) + } + + avatarUrl(size) { + return getAvatarHttpUrl(this._member.avatarUrl, size, this.platform, this._mediaRepository); + } + + get avatarTitle() { + return this.name; + } +} diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js new file mode 100644 index 00000000..125f938c --- /dev/null +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -0,0 +1,12 @@ +import {AvatarView} from "../../AvatarView.js"; +import {TemplateView} from "../../general/TemplateView.js"; + +export class MemberDetailsView extends TemplateView { + render(t, vm) { + return t.div({ className: "MemberDetailsView" }, + [ t.view(new AvatarView(vm, 128)), + t.div({ className: "MemberDetailsView_name" }, vm.name), + t.div({ className: "MemberDetailsView_userId" }, vm.userId) + ]); + } +} From e4bb20575b3bc21ec3eabca078d07c2135f9124d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 19 Jul 2021 21:04:32 +0530 Subject: [PATCH 02/28] Create navigation and add to right panel Signed-off-by: RMidhunSuresh --- src/domain/navigation/index.js | 10 +++++++--- .../session/rightpanel/RightPanelViewModel.js | 13 +++++++++++-- .../web/ui/session/rightpanel/RightPanelView.js | 4 +++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/domain/navigation/index.js b/src/domain/navigation/index.js index 6ce63ffd..b315e187 100644 --- a/src/domain/navigation/index.js +++ b/src/domain/navigation/index.js @@ -39,7 +39,7 @@ function allowsChild(parent, child) { case "room": return type === "lightbox" || type === "right-panel"; case "right-panel": - return type === "details"|| type === "members"; + return type === "details"|| type === "members" || type === "member"; default: return false; } @@ -87,9 +87,9 @@ function roomsSegmentWithRoom(rooms, roomId, path) { } } -function pushRightPanelSegment(array, segment) { +function pushRightPanelSegment(array, segment, value = true) { array.push(new Segment("right-panel")); - array.push(new Segment(segment)); + array.push(new Segment(segment, value)); } export function addPanelIfNeeded(navigation, path) { @@ -147,6 +147,10 @@ export function parseUrlPath(urlPath, currentNavPath, defaultSessionId) { } } else if (type === "details" || type === "members") { pushRightPanelSegment(segments, type); + } else if (type === "member") { + const userId = iterator.next().value; + if (!userId) { break; } + pushRightPanelSegment(segments, type, userId); } else { // might be undefined, which will be turned into true by Segment const value = iterator.next().value; diff --git a/src/domain/session/rightpanel/RightPanelViewModel.js b/src/domain/session/rightpanel/RightPanelViewModel.js index c56080a8..87809eb8 100644 --- a/src/domain/session/rightpanel/RightPanelViewModel.js +++ b/src/domain/session/rightpanel/RightPanelViewModel.js @@ -1,6 +1,7 @@ import {ViewModel} from "../../ViewModel.js"; import {RoomDetailsViewModel} from "./RoomDetailsViewModel.js"; import {MemberListViewModel} from "./MemberListViewModel.js"; +import {MemberDetailsViewModel} from "./MemberDetailsViewModel.js"; export class RightPanelViewModel extends ViewModel { constructor(options) { @@ -11,16 +12,24 @@ export class RightPanelViewModel extends ViewModel { get activeViewModel() { return this._activeViewModel; } - async _getMemberArguments() { + async _getMemberListArguments() { const members = await this._room.loadMemberList(); const room = this._room; const powerLevelsObservable = await this._room.observePowerLevels(); return {members, powerLevelsObservable, mediaRepository: room.mediaRepository}; } + async _getMemberDetailsArguments() { + const segment = this.navigation.path.get("member"); + const userId = segment.value; + const observableMember = await this._room.observeMember(userId); + return {observableMember, mediaRepository: this._room.mediaRepository}; + } + _setupNavigation() { this._hookUpdaterToSegment("details", RoomDetailsViewModel, () => { return {room: this._room}; }); - this._hookUpdaterToSegment("members", MemberListViewModel, () => this._getMemberArguments()); + this._hookUpdaterToSegment("members", MemberListViewModel, () => this._getMemberListArguments()); + this._hookUpdaterToSegment("member", MemberDetailsViewModel, () => this._getMemberDetailsArguments()); } _hookUpdaterToSegment(segment, viewmodel, argCreator) { diff --git a/src/platform/web/ui/session/rightpanel/RightPanelView.js b/src/platform/web/ui/session/rightpanel/RightPanelView.js index f812d6aa..69b81f49 100644 --- a/src/platform/web/ui/session/rightpanel/RightPanelView.js +++ b/src/platform/web/ui/session/rightpanel/RightPanelView.js @@ -2,12 +2,14 @@ import {TemplateView} from "../../general/TemplateView.js"; import {RoomDetailsView} from "./RoomDetailsView.js"; import {MemberListView} from "./MemberListView.js"; import {LoadingView} from "../../general/LoadingView.js"; +import {MemberDetailsView} from "./MemberDetailsView.js"; export class RightPanelView extends TemplateView { render(t) { const viewFromType = { "room-details": RoomDetailsView, - "member-list": MemberListView + "member-list": MemberListView, + "member-details": MemberDetailsView }; return t.div({ className: "RightPanelView" }, [ From acdba8fc026474765e352b122a0dedd6279db5ba Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 20 Jul 2021 13:22:17 +0530 Subject: [PATCH 03/28] Add license headers Signed-off-by: RMidhunSuresh --- .../session/rightpanel/MemberDetailsViewModel.js | 16 ++++++++++++++++ .../ui/session/rightpanel/MemberDetailsView.js | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index a51015b4..6aa211ff 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -1,3 +1,19 @@ +/* +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"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js"; diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index 125f938c..418f3975 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -1,3 +1,19 @@ +/* +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 {AvatarView} from "../../AvatarView.js"; import {TemplateView} from "../../general/TemplateView.js"; From 7ef7c419e3b44d96da0c140fc3d641a3091c6675 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 20 Jul 2021 16:45:02 +0530 Subject: [PATCH 04/28] Add basic UI and styling Signed-off-by: RMidhunSuresh --- .../rightpanel/MemberDetailsViewModel.js | 4 ++++ src/platform/web/ui/css/right-panel.css | 6 ++--- .../web/ui/css/themes/element/theme.css | 22 +++++++++++++++++-- .../session/rightpanel/MemberDetailsView.js | 16 +++++++++++--- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 6aa211ff..61313c04 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -30,6 +30,10 @@ export class MemberDetailsViewModel extends ViewModel { get userId() { return this._member.userId; } get type() { return "member-details"; } + + get role() { + return "Admin"; + } _onMemberChange() { this._member = this._observableMember.get(); diff --git a/src/platform/web/ui/css/right-panel.css b/src/platform/web/ui/css/right-panel.css index 937fa944..423ca1aa 100644 --- a/src/platform/web/ui/css/right-panel.css +++ b/src/platform/web/ui/css/right-panel.css @@ -6,7 +6,7 @@ flex-direction: column; } -.RoomDetailsView { +.RoomDetailsView, .MemberDetailsView { flex-direction: column; flex: 1; } @@ -15,11 +15,11 @@ display: flex; } -.RoomDetailsView_name h2 { +.RoomDetailsView_name h2, .MemberDetailsView_name h2 { text-align: center; } -.RoomDetailsView_label, .RoomDetailsView_row, .RoomDetailsView, .EncryptionIconView { +.RoomDetailsView_label, .RoomDetailsView_row, .RoomDetailsView, .MemberDetailsView, .EncryptionIconView { display: flex; align-items: center; } diff --git a/src/platform/web/ui/css/themes/element/theme.css b/src/platform/web/ui/css/themes/element/theme.css index 56eaf224..82e0e6b4 100644 --- a/src/platform/web/ui/css/themes/element/theme.css +++ b/src/platform/web/ui/css/themes/element/theme.css @@ -807,7 +807,7 @@ button.link { padding-top: 0; } -.RoomDetailsView_id { +.RoomDetailsView_id, .MemberDetailsView_id { color: #737D8C; font-size: 12px; } @@ -817,7 +817,7 @@ button.link { width: 100%; } -.RoomDetailsView_name h2 { +.RoomDetailsView_name h2, .MemberDetailsView_name h2 { margin-bottom: 4px; font-size: 1.8rem; } @@ -929,6 +929,24 @@ button.RoomDetailsView_row::after { flex: 1; } +/* Member details panel */ +.MemberDetailsView_section { + box-sizing: border-box; + padding: 16px; + width: 100%; +} + +.MemberDetailsView_label { + font-size: 12px; + font-weight: 600; + color: #8d99a5; +} + +.MemberDetailsView_value { + margin-left: 8px; + font-size: 12px; +} + .LazyListParent { overflow-y: auto; } diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index 418f3975..0014f626 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -15,14 +15,24 @@ limitations under the License. */ import {AvatarView} from "../../AvatarView.js"; +import {classNames} from "../../general/html.js"; import {TemplateView} from "../../general/TemplateView.js"; export class MemberDetailsView extends TemplateView { render(t, vm) { - return t.div({ className: "MemberDetailsView" }, + return t.div({className: "MemberDetailsView"}, [ t.view(new AvatarView(vm, 128)), - t.div({ className: "MemberDetailsView_name" }, vm.name), - t.div({ className: "MemberDetailsView_userId" }, vm.userId) + t.div({className: "MemberDetailsView_name"}, [t.h2(vm.name)]), + t.div({ className: "MemberDetailsView_id" }, vm.userId), + this._createSection(t, "ROLE", {}, vm.role) ]); } + + _createSection(t, label, labelClass, value) { + const labelClassString = classNames({MemberDetailsView_label: true, ...labelClass}); + return t.div({className: "MemberDetailsView_section"}, [ + t.div({className: labelClassString}, [label]), + t.div({className: "MemberDetailsView_value"}, value) + ]); + } } From c2b9c3f726e82f21ff8dbea69f86ddd3020750d3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 20 Jul 2021 21:36:07 +0530 Subject: [PATCH 05/28] Add isEncrypted to vm Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 5 +++++ src/domain/session/rightpanel/RightPanelViewModel.js | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 61313c04..0c526130 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -23,6 +23,7 @@ export class MemberDetailsViewModel extends ViewModel { this._observableMember = options.observableMember; this._mediaRepository = options.mediaRepository; this._member = this._observableMember.get(); + this._isEncrypted = options.isEncrypted; this.track(this._observableMember.subscribe( () => this._onMemberChange())); } @@ -55,4 +56,8 @@ export class MemberDetailsViewModel extends ViewModel { get avatarTitle() { return this.name; } + + get isEncrypted() { + return this._isEncrypted; + } } diff --git a/src/domain/session/rightpanel/RightPanelViewModel.js b/src/domain/session/rightpanel/RightPanelViewModel.js index 87809eb8..1e058674 100644 --- a/src/domain/session/rightpanel/RightPanelViewModel.js +++ b/src/domain/session/rightpanel/RightPanelViewModel.js @@ -23,7 +23,8 @@ export class RightPanelViewModel extends ViewModel { const segment = this.navigation.path.get("member"); const userId = segment.value; const observableMember = await this._room.observeMember(userId); - return {observableMember, mediaRepository: this._room.mediaRepository}; + const isEncrypted = this._room.isEncrypted; + return {observableMember, isEncrypted, mediaRepository: this._room.mediaRepository}; } _setupNavigation() { From c9224c13a707feca6e41c7d299fd3e3b126a1e5e Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 20 Jul 2021 21:36:58 +0530 Subject: [PATCH 06/28] Improve code and css Signed-off-by: RMidhunSuresh --- .../web/ui/css/themes/element/theme.css | 14 ++++++- .../session/rightpanel/MemberDetailsView.js | 37 ++++++++++++++----- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/platform/web/ui/css/themes/element/theme.css b/src/platform/web/ui/css/themes/element/theme.css index 82e0e6b4..699759b3 100644 --- a/src/platform/web/ui/css/themes/element/theme.css +++ b/src/platform/web/ui/css/themes/element/theme.css @@ -942,11 +942,23 @@ button.RoomDetailsView_row::after { color: #8d99a5; } -.MemberDetailsView_value { +.MemberDetailsView_value, .MemberDetailsView_options { margin-left: 8px; + margin-top: 5px; font-size: 12px; } +.MemberDetailsView_options { + display: inline-flex; + flex-direction: column; +} + +.MemberDetailsView_options a{ + color: #0dbd8b; + text-decoration: none; + margin-bottom: 3px; +} + .LazyListParent { overflow-y: auto; } diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index 0014f626..bff07ff1 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -15,24 +15,41 @@ limitations under the License. */ import {AvatarView} from "../../AvatarView.js"; -import {classNames} from "../../general/html.js"; import {TemplateView} from "../../general/TemplateView.js"; export class MemberDetailsView extends TemplateView { render(t, vm) { + const encryptionMessages = { + true: vm.i18n`Messages in this room are end-to-end encrypted.`, + false: vm.i18n`Messages in this room are not end-to-end encrypted.` + }; return t.div({className: "MemberDetailsView"}, [ t.view(new AvatarView(vm, 128)), - t.div({className: "MemberDetailsView_name"}, [t.h2(vm.name)]), - t.div({ className: "MemberDetailsView_id" }, vm.userId), - this._createSection(t, "ROLE", {}, vm.role) + t.div({className: "MemberDetailsView_name"}, t.h2(vm.name)), + t.div({className: "MemberDetailsView_id"}, vm.userId), + this._createSection(t, vm.i18n`ROLE`, vm.role), + this._createSection(t, vm.i18n`SECURITY`, encryptionMessages[vm.isEncrypted]), + this._createOptions(t, vm) ]); } - _createSection(t, label, labelClass, value) { - const labelClassString = classNames({MemberDetailsView_label: true, ...labelClass}); - return t.div({className: "MemberDetailsView_section"}, [ - t.div({className: labelClassString}, [label]), - t.div({className: "MemberDetailsView_value"}, value) - ]); + _createSection(t, label, value) { + return t.div({ className: "MemberDetailsView_section" }, + [ + t.div({className: "MemberDetailsView_label"}, label), + t.div({className: "MemberDetailsView_value"}, value) + ]); + } + + _createOptions(t, vm) { + return t.div({ className: "MemberDetailsView_section" }, + [ + t.div({className: "MemberDetailsView_label"}, vm.i18n`OPTIONS`), + t.div({ className: "MemberDetailsView_options" }, + [ + t.a({href: "#"}, vm.i18n`Direct Message`), + t.a({href: "#"}, vm.i18n`Open Link to User`) + ]) + ]); } } From fe6551ff3c35e9c6e3bbf780b10e6b7c84600250 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 21 Jul 2021 13:51:57 +0530 Subject: [PATCH 07/28] Use powerlevel Signed-off-by: RMidhunSuresh --- .../session/rightpanel/MemberDetailsViewModel.js | 14 +++++++++++++- .../session/rightpanel/RightPanelViewModel.js | 3 ++- .../web/ui/session/rightpanel/MemberDetailsView.js | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 0c526130..dad65d64 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -24,6 +24,9 @@ export class MemberDetailsViewModel extends ViewModel { this._mediaRepository = options.mediaRepository; this._member = this._observableMember.get(); this._isEncrypted = options.isEncrypted; + this._powerLevelsObservable = options.powerLevelsObservable; + this._powerLevel = this._powerLevelFromObservable(this._powerLevelsObservable); + this.track(this._powerLevelsObservable.subscribe(() => this._onPowerLevelsChange())); this.track(this._observableMember.subscribe( () => this._onMemberChange())); } @@ -33,7 +36,10 @@ export class MemberDetailsViewModel extends ViewModel { get type() { return "member-details"; } get role() { - return "Admin"; + if (this._powerLevel >= 100) { return "Admin"; } + else if (this._powerLevel >= 50) { return "Moderator"; } + else if (this._powerLevel === 0) { return "Default"; } + else { return `Custom (${this._powerLevel})`; } } _onMemberChange() { @@ -41,6 +47,12 @@ export class MemberDetailsViewModel extends ViewModel { this.emitChange(); } + _onPowerLevelsChange() { + const powerLevels = this._powerLevelsObservable.get(); + this._powerLevel = powerLevels.getUserLevel(this._member.userId); + this.emitChange(); + } + get avatarLetter() { return avatarInitials(this.name); } diff --git a/src/domain/session/rightpanel/RightPanelViewModel.js b/src/domain/session/rightpanel/RightPanelViewModel.js index 1e058674..77291082 100644 --- a/src/domain/session/rightpanel/RightPanelViewModel.js +++ b/src/domain/session/rightpanel/RightPanelViewModel.js @@ -24,7 +24,8 @@ export class RightPanelViewModel extends ViewModel { const userId = segment.value; const observableMember = await this._room.observeMember(userId); const isEncrypted = this._room.isEncrypted; - return {observableMember, isEncrypted, mediaRepository: this._room.mediaRepository}; + const powerLevelsObservable = await this._room.observePowerLevels(); + return {observableMember, isEncrypted, powerLevelsObservable, mediaRepository: this._room.mediaRepository}; } _setupNavigation() { diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index bff07ff1..0d9c38f8 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -25,9 +25,9 @@ export class MemberDetailsView extends TemplateView { }; return t.div({className: "MemberDetailsView"}, [ t.view(new AvatarView(vm, 128)), - t.div({className: "MemberDetailsView_name"}, t.h2(vm.name)), + t.div({className: "MemberDetailsView_name"}, t.h2(vm => vm.name)), t.div({className: "MemberDetailsView_id"}, vm.userId), - this._createSection(t, vm.i18n`ROLE`, vm.role), + this._createSection(t, vm.i18n`ROLE`, vm => vm.role), this._createSection(t, vm.i18n`SECURITY`, encryptionMessages[vm.isEncrypted]), this._createOptions(t, vm) ]); From f9b1068baebcca38410106b73d2bd01be1a9f97b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 21 Jul 2021 14:36:26 +0530 Subject: [PATCH 08/28] Add links Signed-off-by: RMidhunSuresh --- .../session/rightpanel/MemberDetailsViewModel.js | 10 +++++++++- .../web/ui/session/rightpanel/MemberDetailsView.js | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index dad65d64..4e870ae8 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -25,7 +25,7 @@ export class MemberDetailsViewModel extends ViewModel { this._member = this._observableMember.get(); this._isEncrypted = options.isEncrypted; this._powerLevelsObservable = options.powerLevelsObservable; - this._powerLevel = this._powerLevelFromObservable(this._powerLevelsObservable); + this._powerLevel = this._powerLevelsObservable.get().getUserLevel(this._member.userId); this.track(this._powerLevelsObservable.subscribe(() => this._onPowerLevelsChange())); this.track(this._observableMember.subscribe( () => this._onMemberChange())); } @@ -72,4 +72,12 @@ export class MemberDetailsViewModel extends ViewModel { get isEncrypted() { return this._isEncrypted; } + + get dmLink() { + return `${this.urlCreator.urlUntilSegment("session")}/open-room/${this._member.userId}`; + } + + get linkToUser() { + return `https://matrix.to/#/${this._member.userId}`; + } } diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index 0d9c38f8..33589531 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -45,10 +45,10 @@ export class MemberDetailsView extends TemplateView { return t.div({ className: "MemberDetailsView_section" }, [ t.div({className: "MemberDetailsView_label"}, vm.i18n`OPTIONS`), - t.div({ className: "MemberDetailsView_options" }, + t.div({className: "MemberDetailsView_options"}, [ - t.a({href: "#"}, vm.i18n`Direct Message`), - t.a({href: "#"}, vm.i18n`Open Link to User`) + t.a({href: vm.dmLink}, vm.i18n`Direct Message`), + t.a({href: vm.linkToUser, target: "_blank", rel: "noopener"}, vm.i18n`Open Link to User`) ]) ]); } From ef17808fbdb2c70afba9fd2e8db3885188d06208 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Wed, 21 Jul 2021 22:09:35 +0530 Subject: [PATCH 09/28] Fallback to memberlist if member not available Signed-off-by: RMidhunSuresh --- .../session/rightpanel/RightPanelViewModel.js | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/domain/session/rightpanel/RightPanelViewModel.js b/src/domain/session/rightpanel/RightPanelViewModel.js index 77291082..5564fd8d 100644 --- a/src/domain/session/rightpanel/RightPanelViewModel.js +++ b/src/domain/session/rightpanel/RightPanelViewModel.js @@ -23,6 +23,9 @@ export class RightPanelViewModel extends ViewModel { const segment = this.navigation.path.get("member"); const userId = segment.value; const observableMember = await this._room.observeMember(userId); + if (!observableMember) { + return false; + } const isEncrypted = this._room.isEncrypted; const powerLevelsObservable = await this._room.observePowerLevels(); return {observableMember, isEncrypted, powerLevelsObservable, mediaRepository: this._room.mediaRepository}; @@ -31,16 +34,22 @@ export class RightPanelViewModel extends ViewModel { _setupNavigation() { this._hookUpdaterToSegment("details", RoomDetailsViewModel, () => { return {room: this._room}; }); this._hookUpdaterToSegment("members", MemberListViewModel, () => this._getMemberListArguments()); - this._hookUpdaterToSegment("member", MemberDetailsViewModel, () => this._getMemberDetailsArguments()); + this._hookUpdaterToSegment("member", MemberDetailsViewModel, () => this._getMemberDetailsArguments(), + () => { + // If we fail to create the member details panel, fallback to memberlist + const url = `${this.urlCreator.urlUntilSegment("room")}/members`; + this.urlCreator.pushUrl(url); + } + ); } - _hookUpdaterToSegment(segment, viewmodel, argCreator) { + _hookUpdaterToSegment(segment, viewmodel, argCreator, failCallback) { const observable = this.navigation.observe(segment); - const updater = this._setupUpdater(segment, viewmodel, argCreator); + const updater = this._setupUpdater(segment, viewmodel, argCreator, failCallback); this.track(observable.subscribe(() => updater())); } - _setupUpdater(segment, viewmodel, argCreator) { + _setupUpdater(segment, viewmodel, argCreator, failCallback) { const updater = async (skipDispose = false) => { if (!skipDispose) { this._activeViewModel = this.disposeTracked(this._activeViewModel); @@ -48,6 +57,10 @@ export class RightPanelViewModel extends ViewModel { const enable = !!this.navigation.path.get(segment)?.value; if (enable) { const args = await argCreator(); + if (!args && failCallback) { + failCallback(); + return; + } this._activeViewModel = this.track(new viewmodel(this.childOptions(args))); } this.emitChange("activeViewModel"); From 7530b281305a351fa32274cc88011ee7148363a0 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 22 Jul 2021 16:24:06 +0530 Subject: [PATCH 10/28] Improve segment adding logic Signed-off-by: RMidhunSuresh --- src/domain/navigation/index.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/domain/navigation/index.js b/src/domain/navigation/index.js index b315e187..f443d415 100644 --- a/src/domain/navigation/index.js +++ b/src/domain/navigation/index.js @@ -132,10 +132,12 @@ export function parseUrlPath(urlPath, currentNavPath, defaultSessionId) { segments.push(roomsSegmentWithRoom(rooms, roomId, currentNavPath)); } segments.push(new Segment("room", roomId)); - if (currentNavPath.get("details")?.value) { - pushRightPanelSegment(segments, "details"); - } else if (currentNavPath.get("members")?.value) { - pushRightPanelSegment(segments, "members"); + // Add right-panel segments from previous path + const previousSegments = currentNavPath.segments; + const i = previousSegments.findIndex(s => s.type === "right-panel"); + if (i !== -1) { + segments.push(previousSegments[i]); + segments.push(previousSegments[i + 1]); } } else if (type === "last-session") { let sessionSegment = currentNavPath.get("session"); From 7dacbdb700c4e71fe008d48274b4119fab0bfb03 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 22 Jul 2021 16:30:22 +0530 Subject: [PATCH 11/28] Show back button Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 4e870ae8..52cb046f 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -34,6 +34,8 @@ export class MemberDetailsViewModel extends ViewModel { get userId() { return this._member.userId; } get type() { return "member-details"; } + get shouldShowBackButton() { return true; } + get previousSegmentName() { return "members"; } get role() { if (this._powerLevel >= 100) { return "Admin"; } From 65b1a1958ae8509273395ec9765dd8ca8a77a7ea Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 22 Jul 2021 19:57:25 +0530 Subject: [PATCH 12/28] Add link to open member details Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberTileViewModel.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/domain/session/rightpanel/MemberTileViewModel.js b/src/domain/session/rightpanel/MemberTileViewModel.js index 23a7eeef..4dacdf43 100644 --- a/src/domain/session/rightpanel/MemberTileViewModel.js +++ b/src/domain/session/rightpanel/MemberTileViewModel.js @@ -30,6 +30,10 @@ export class MemberTileViewModel extends ViewModel { return this._nameChanged; } + get detailsUrl() { + return `${this.urlCreator.urlUntilSegment("room")}/member/${this._member.userId}`; + } + _updatePreviousName(newName) { const currentName = this._member.name; if (currentName !== newName) { From 4784bcc59085ccf5eb8247eb8487b95b81fa65d4 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 22 Jul 2021 19:58:04 +0530 Subject: [PATCH 13/28] Make the tiles link to details Signed-off-by: RMidhunSuresh --- src/platform/web/ui/session/rightpanel/MemberTileView.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/platform/web/ui/session/rightpanel/MemberTileView.js b/src/platform/web/ui/session/rightpanel/MemberTileView.js index 95b04719..31cb532a 100644 --- a/src/platform/web/ui/session/rightpanel/MemberTileView.js +++ b/src/platform/web/ui/session/rightpanel/MemberTileView.js @@ -3,9 +3,10 @@ import {AvatarView} from "../../AvatarView.js"; export class MemberTileView extends TemplateView { render(t, vm) { - return t.li({ className: "MemberTileView" }, [ - t.view(new AvatarView(vm, 32)), - t.div({ className: "MemberTileView_name" }, (vm) => vm.name), - ]); + return t.li({ className: "MemberTileView" }, t.a({href: vm.detailsUrl}, [ + t.view(new AvatarView(vm, 32)), + t.div({ className: "MemberTileView_name" }, (vm) => vm.name), + ]) + ); } } From 448bf3cb3f7a765f4f9319123e19798f70149246 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 22 Jul 2021 19:58:55 +0530 Subject: [PATCH 14/28] Style tile Signed-off-by: RMidhunSuresh --- src/platform/web/ui/css/right-panel.css | 2 +- src/platform/web/ui/css/themes/element/theme.css | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platform/web/ui/css/right-panel.css b/src/platform/web/ui/css/right-panel.css index 423ca1aa..95fd9cae 100644 --- a/src/platform/web/ui/css/right-panel.css +++ b/src/platform/web/ui/css/right-panel.css @@ -45,7 +45,7 @@ visibility: hidden; } -.MemberTileView { +.MemberTileView a { display: flex; align-items: center; } diff --git a/src/platform/web/ui/css/themes/element/theme.css b/src/platform/web/ui/css/themes/element/theme.css index 699759b3..e0709475 100644 --- a/src/platform/web/ui/css/themes/element/theme.css +++ b/src/platform/web/ui/css/themes/element/theme.css @@ -916,6 +916,11 @@ button.RoomDetailsView_row::after { .MemberTileView { margin-bottom: 8px; + list-style: none; +} + +.MemberTileView a { + text-decoration: none; } .MemberTileView .avatar { From 16887c3c33bf5c66aba7229379b1e1795bdb01ae Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 22 Jul 2021 19:59:58 +0530 Subject: [PATCH 15/28] Better formatting Signed-off-by: RMidhunSuresh --- src/platform/web/ui/session/rightpanel/MemberTileView.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platform/web/ui/session/rightpanel/MemberTileView.js b/src/platform/web/ui/session/rightpanel/MemberTileView.js index 31cb532a..af0f2407 100644 --- a/src/platform/web/ui/session/rightpanel/MemberTileView.js +++ b/src/platform/web/ui/session/rightpanel/MemberTileView.js @@ -3,7 +3,9 @@ import {AvatarView} from "../../AvatarView.js"; export class MemberTileView extends TemplateView { render(t, vm) { - return t.li({ className: "MemberTileView" }, t.a({href: vm.detailsUrl}, [ + return t.li({ className: "MemberTileView" }, + t.a({ href: vm.detailsUrl }, + [ t.view(new AvatarView(vm, 32)), t.div({ className: "MemberTileView_name" }, (vm) => vm.name), ]) From d056a9f961835da5ff769cd5d1e3e06a1e7e9e72 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 22 Jul 2021 20:33:27 +0530 Subject: [PATCH 16/28] Keep memberlist until rightpanel is closed - This should make switching between memberlist and member-details panel smoother for large rooms Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberListViewModel.js | 1 - src/domain/session/rightpanel/RightPanelViewModel.js | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/domain/session/rightpanel/MemberListViewModel.js b/src/domain/session/rightpanel/MemberListViewModel.js index ce0fff40..a6f58f5d 100644 --- a/src/domain/session/rightpanel/MemberListViewModel.js +++ b/src/domain/session/rightpanel/MemberListViewModel.js @@ -7,7 +7,6 @@ export class MemberListViewModel extends ViewModel { constructor(options) { super(options); const list = options.members; - this.track(() => list.release()); const powerLevelsObservable = options.powerLevelsObservable; this.track(powerLevelsObservable.subscribe(() => { /*resort based on new power levels here*/ })); diff --git a/src/domain/session/rightpanel/RightPanelViewModel.js b/src/domain/session/rightpanel/RightPanelViewModel.js index 5564fd8d..86225ca9 100644 --- a/src/domain/session/rightpanel/RightPanelViewModel.js +++ b/src/domain/session/rightpanel/RightPanelViewModel.js @@ -7,16 +7,20 @@ export class RightPanelViewModel extends ViewModel { constructor(options) { super(options); this._room = options.room; + this._members = null; this._setupNavigation(); } get activeViewModel() { return this._activeViewModel; } async _getMemberListArguments() { - const members = await this._room.loadMemberList(); + if (!this._members) { + this._members = await this._room.loadMemberList(); + this.track(() => this._members.release()); + } const room = this._room; const powerLevelsObservable = await this._room.observePowerLevels(); - return {members, powerLevelsObservable, mediaRepository: room.mediaRepository}; + return {members: this._members, powerLevelsObservable, mediaRepository: room.mediaRepository}; } async _getMemberDetailsArguments() { From 0ff0850979f0a00a8403769094063733166df475 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 23 Jul 2021 12:43:16 +0530 Subject: [PATCH 17/28] Remove dm user option - I don't know why but I thought .../open-room/ would open an invite view to a room with the specified user. - Does not work like that, so removed. Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 4 ---- src/platform/web/ui/session/rightpanel/MemberDetailsView.js | 1 - 2 files changed, 5 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 52cb046f..bf6f0b34 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -75,10 +75,6 @@ export class MemberDetailsViewModel extends ViewModel { return this._isEncrypted; } - get dmLink() { - return `${this.urlCreator.urlUntilSegment("session")}/open-room/${this._member.userId}`; - } - get linkToUser() { return `https://matrix.to/#/${this._member.userId}`; } diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index 33589531..c40b9173 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -47,7 +47,6 @@ export class MemberDetailsView extends TemplateView { t.div({className: "MemberDetailsView_label"}, vm.i18n`OPTIONS`), t.div({className: "MemberDetailsView_options"}, [ - t.a({href: vm.dmLink}, vm.i18n`Direct Message`), t.a({href: vm.linkToUser, target: "_blank", rel: "noopener"}, vm.i18n`Open Link to User`) ]) ]); From 28a0a0830f6726b8b838dbb2057a74d698b8dd94 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 3 Aug 2021 13:42:27 +0530 Subject: [PATCH 18/28] Copy over all segments after right-panel Signed-off-by: RMidhunSuresh --- src/domain/navigation/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/domain/navigation/index.js b/src/domain/navigation/index.js index f443d415..dbac16ac 100644 --- a/src/domain/navigation/index.js +++ b/src/domain/navigation/index.js @@ -136,8 +136,7 @@ export function parseUrlPath(urlPath, currentNavPath, defaultSessionId) { const previousSegments = currentNavPath.segments; const i = previousSegments.findIndex(s => s.type === "right-panel"); if (i !== -1) { - segments.push(previousSegments[i]); - segments.push(previousSegments[i + 1]); + segments.push(...previousSegments.slice(i)); } } else if (type === "last-session") { let sessionSegment = currentNavPath.get("session"); From a16c3aacab3aaaad36f0454f09415d8da7851695 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 3 Aug 2021 14:51:46 +0530 Subject: [PATCH 19/28] Create getter Signed-off-by: RMidhunSuresh --- .../rightpanel/MemberDetailsViewModel.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index bf6f0b34..f10f3678 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -25,7 +25,7 @@ export class MemberDetailsViewModel extends ViewModel { this._member = this._observableMember.get(); this._isEncrypted = options.isEncrypted; this._powerLevelsObservable = options.powerLevelsObservable; - this._powerLevel = this._powerLevelsObservable.get().getUserLevel(this._member.userId); + this._powerLevel = null; this.track(this._powerLevelsObservable.subscribe(() => this._onPowerLevelsChange())); this.track(this._observableMember.subscribe( () => this._onMemberChange())); } @@ -38,10 +38,10 @@ export class MemberDetailsViewModel extends ViewModel { get previousSegmentName() { return "members"; } get role() { - if (this._powerLevel >= 100) { return "Admin"; } - else if (this._powerLevel >= 50) { return "Moderator"; } - else if (this._powerLevel === 0) { return "Default"; } - else { return `Custom (${this._powerLevel})`; } + if (this.powerLevel >= 100) { return "Admin"; } + else if (this.powerLevel >= 50) { return "Moderator"; } + else if (this.powerLevel === 0) { return "Default"; } + else { return `Custom (${this.powerLevel})`; } } _onMemberChange() { @@ -75,6 +75,14 @@ export class MemberDetailsViewModel extends ViewModel { return this._isEncrypted; } + get powerLevel() { + if (!this._powerLevel) { + const powerLevels = this._powerLevelsObservable.get(); + this._powerLevel = powerLevels.getUserLevel(this._member.userId); + } + return this._powerLevel; + } + get linkToUser() { return `https://matrix.to/#/${this._member.userId}`; } From 862e8569a9c2b3713ae977fc114a34e4f9f49767 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 3 Aug 2021 14:52:20 +0530 Subject: [PATCH 20/28] Describe what changed in emitChange() Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index f10f3678..8f3d5add 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -46,13 +46,13 @@ export class MemberDetailsViewModel extends ViewModel { _onMemberChange() { this._member = this._observableMember.get(); - this.emitChange(); + this.emitChange("member"); } _onPowerLevelsChange() { const powerLevels = this._powerLevelsObservable.get(); this._powerLevel = powerLevels.getUserLevel(this._member.userId); - this.emitChange(); + this.emitChange("role"); } get avatarLetter() { From d3ea26a38ac0b6cbfa753559092c31c4cea65c5b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 3 Aug 2021 15:12:47 +0530 Subject: [PATCH 21/28] Use i8n in role Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 8f3d5add..55a448de 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -38,10 +38,10 @@ export class MemberDetailsViewModel extends ViewModel { get previousSegmentName() { return "members"; } get role() { - if (this.powerLevel >= 100) { return "Admin"; } - else if (this.powerLevel >= 50) { return "Moderator"; } - else if (this.powerLevel === 0) { return "Default"; } - else { return `Custom (${this.powerLevel})`; } + if (this.powerLevel >= 100) { return this.i18n`Admin`; } + else if (this.powerLevel >= 50) { return this.i18n`Moderator`; } + else if (this.powerLevel === 0) { return this.i18n`Default`; } + else { return this.i18n`Custom (${this.powerLevel})`; } } _onMemberChange() { From fea4143af9c2d5d74d6b97649339558b525ed402 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 3 Aug 2021 15:16:47 +0530 Subject: [PATCH 22/28] Use texttransform Signed-off-by: RMidhunSuresh --- src/platform/web/ui/css/themes/element/theme.css | 1 + src/platform/web/ui/session/rightpanel/MemberDetailsView.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/platform/web/ui/css/themes/element/theme.css b/src/platform/web/ui/css/themes/element/theme.css index e0709475..b1ef7ab8 100644 --- a/src/platform/web/ui/css/themes/element/theme.css +++ b/src/platform/web/ui/css/themes/element/theme.css @@ -945,6 +945,7 @@ button.RoomDetailsView_row::after { font-size: 12px; font-weight: 600; color: #8d99a5; + text-transform: uppercase; } .MemberDetailsView_value, .MemberDetailsView_options { diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index c40b9173..32cdd0b6 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -27,8 +27,8 @@ export class MemberDetailsView extends TemplateView { [ t.view(new AvatarView(vm, 128)), t.div({className: "MemberDetailsView_name"}, t.h2(vm => vm.name)), t.div({className: "MemberDetailsView_id"}, vm.userId), - this._createSection(t, vm.i18n`ROLE`, vm => vm.role), - this._createSection(t, vm.i18n`SECURITY`, encryptionMessages[vm.isEncrypted]), + this._createSection(t, vm.i18n`Role`, vm => vm.role), + this._createSection(t, vm.i18n`Security`, encryptionMessages[vm.isEncrypted]), this._createOptions(t, vm) ]); } @@ -44,7 +44,7 @@ export class MemberDetailsView extends TemplateView { _createOptions(t, vm) { return t.div({ className: "MemberDetailsView_section" }, [ - t.div({className: "MemberDetailsView_label"}, vm.i18n`OPTIONS`), + t.div({className: "MemberDetailsView_label"}, vm.i18n`Options`), t.div({className: "MemberDetailsView_options"}, [ t.a({href: vm.linkToUser, target: "_blank", rel: "noopener"}, vm.i18n`Open Link to User`) From 49be4e64ca9cc3006f47d86f185098c84058f460 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 3 Aug 2021 15:28:08 +0530 Subject: [PATCH 23/28] Remove object Signed-off-by: RMidhunSuresh --- .../web/ui/session/rightpanel/MemberDetailsView.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index 32cdd0b6..5ada0912 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -19,16 +19,15 @@ import {TemplateView} from "../../general/TemplateView.js"; export class MemberDetailsView extends TemplateView { render(t, vm) { - const encryptionMessages = { - true: vm.i18n`Messages in this room are end-to-end encrypted.`, - false: vm.i18n`Messages in this room are not end-to-end encrypted.` - }; return t.div({className: "MemberDetailsView"}, [ t.view(new AvatarView(vm, 128)), t.div({className: "MemberDetailsView_name"}, t.h2(vm => vm.name)), t.div({className: "MemberDetailsView_id"}, vm.userId), this._createSection(t, vm.i18n`Role`, vm => vm.role), - this._createSection(t, vm.i18n`Security`, encryptionMessages[vm.isEncrypted]), + this._createSection(t, vm.i18n`Security`, vm.isEncrypted ? + vm.i18n`Messages in this room are end-to-end encrypted.` : + vm.i18n`Messages in this room are not end-to-end encrypted.` + ), this._createOptions(t, vm) ]); } From 974d9bf199144641579af7eb4d7d9fdef1ddd0fa Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Fri, 6 Aug 2021 13:02:58 +0530 Subject: [PATCH 24/28] Don't cache powerlevel value Co-authored-by: Bruno Windels --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 55a448de..d7b4e366 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -76,11 +76,7 @@ export class MemberDetailsViewModel extends ViewModel { } get powerLevel() { - if (!this._powerLevel) { - const powerLevels = this._powerLevelsObservable.get(); - this._powerLevel = powerLevels.getUserLevel(this._member.userId); - } - return this._powerLevel; + return this._powerLevelsObservable.get()?.getUserLevel(this._member.userId); } get linkToUser() { From 86ddfc1e9ec4c2d3ebcf6a9001908950a562037d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 6 Aug 2021 13:06:38 +0530 Subject: [PATCH 25/28] Only need to emit Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index d7b4e366..45f6005e 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -50,8 +50,6 @@ export class MemberDetailsViewModel extends ViewModel { } _onPowerLevelsChange() { - const powerLevels = this._powerLevelsObservable.get(); - this._powerLevel = powerLevels.getUserLevel(this._member.userId); this.emitChange("role"); } From dbd205701c701b5f5bb9a00d9a4e9d68155f0d3b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 6 Aug 2021 16:03:19 +0530 Subject: [PATCH 26/28] Remove unused prop Signed-off-by: RMidhunSuresh --- src/domain/session/rightpanel/MemberDetailsViewModel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index 45f6005e..0303e05d 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -25,7 +25,6 @@ export class MemberDetailsViewModel extends ViewModel { this._member = this._observableMember.get(); this._isEncrypted = options.isEncrypted; this._powerLevelsObservable = options.powerLevelsObservable; - this._powerLevel = null; this.track(this._powerLevelsObservable.subscribe(() => this._onPowerLevelsChange())); this.track(this._observableMember.subscribe( () => this._onMemberChange())); } From 3ff55204f364c8f6e181dc548eaf212c9e364eba Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Fri, 6 Aug 2021 16:04:51 +0530 Subject: [PATCH 27/28] No need for lambda here Co-authored-by: Bruno Windels --- src/domain/session/rightpanel/RightPanelViewModel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/session/rightpanel/RightPanelViewModel.js b/src/domain/session/rightpanel/RightPanelViewModel.js index 86225ca9..d1b20a82 100644 --- a/src/domain/session/rightpanel/RightPanelViewModel.js +++ b/src/domain/session/rightpanel/RightPanelViewModel.js @@ -50,7 +50,7 @@ export class RightPanelViewModel extends ViewModel { _hookUpdaterToSegment(segment, viewmodel, argCreator, failCallback) { const observable = this.navigation.observe(segment); const updater = this._setupUpdater(segment, viewmodel, argCreator, failCallback); - this.track(observable.subscribe(() => updater())); + this.track(observable.subscribe(updater)); } _setupUpdater(segment, viewmodel, argCreator, failCallback) { From 7e8d76a95ee17623a08034b06c50733b609c0284 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 6 Aug 2021 16:21:31 +0530 Subject: [PATCH 28/28] Refactor map into switch-case Signed-off-by: RMidhunSuresh --- .../ui/session/rightpanel/RightPanelView.js | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/platform/web/ui/session/rightpanel/RightPanelView.js b/src/platform/web/ui/session/rightpanel/RightPanelView.js index 69b81f49..645cc22f 100644 --- a/src/platform/web/ui/session/rightpanel/RightPanelView.js +++ b/src/platform/web/ui/session/rightpanel/RightPanelView.js @@ -6,18 +6,27 @@ import {MemberDetailsView} from "./MemberDetailsView.js"; export class RightPanelView extends TemplateView { render(t) { - const viewFromType = { - "room-details": RoomDetailsView, - "member-list": MemberListView, - "member-details": MemberDetailsView - }; return t.div({ className: "RightPanelView" }, [ t.ifView(vm => vm.activeViewModel, vm => new ButtonsView(vm)), - t.mapView(vm => vm.activeViewModel, vm => vm ? new viewFromType[vm.type](vm) : new LoadingView()) + t.mapView(vm => vm.activeViewModel, vm => this._viewFromType(vm)) ] ); } + + _viewFromType(vm) { + const type = vm?.type; + switch (type) { + case "room-details": + return new RoomDetailsView(vm); + case "member-list": + return new MemberListView(vm); + case "member-details": + return new MemberDetailsView(vm); + default: + return new LoadingView(); + } + } } class ButtonsView extends TemplateView {