diff --git a/src/domain/session/rightpanel/MemberDetailsViewModel.js b/src/domain/session/rightpanel/MemberDetailsViewModel.js index df622aae..0eabf33a 100644 --- a/src/domain/session/rightpanel/MemberDetailsViewModel.js +++ b/src/domain/session/rightpanel/MemberDetailsViewModel.js @@ -17,6 +17,7 @@ limitations under the License. import {ViewModel} from "../../ViewModel"; import {RoomType} from "../../../matrix/room/common"; import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar"; +import {UserTrust} from "../../../matrix/verification/CrossSigning"; export class MemberDetailsViewModel extends ViewModel { constructor(options) { @@ -29,14 +30,14 @@ export class MemberDetailsViewModel extends ViewModel { this._session = options.session; this.track(this._powerLevelsObservable.subscribe(() => this._onPowerLevelsChange())); this.track(this._observableMember.subscribe( () => this._onMemberChange())); - this._isTrusted = false; + this._userTrust = undefined; this.init(); // TODO: call this from parent view model and do something smart with error view model if it fails async? } async init() { if (this.features.crossSigning) { - this._isTrusted = await this.logger.run({l: "MemberDetailsViewModel.verify user", id: this._member.userId}, log => { - return this._session.crossSigning.isUserTrusted(this._member.userId, log); + this._userTrust = await this.logger.run({l: "MemberDetailsViewModel.get user trust", id: this._member.userId}, log => { + return this._session.crossSigning.getUserTrust(this._member.userId, log); }); this.emitChange("isTrusted"); } @@ -44,7 +45,35 @@ export class MemberDetailsViewModel extends ViewModel { get name() { return this._member.name; } get userId() { return this._member.userId; } - get isTrusted() { return this._isTrusted; } + get isTrusted() { return this._userTrust === UserTrust.Trusted; } + get trustDescription() { + switch (this._userTrust) { + case UserTrust.Trusted: return this.i18n`You have verified this user. This user has verified all of their sessions.`; + case UserTrust.UserNotSigned: return this.i18n`You have not verified this user.`; + case UserTrust.UserSignatureMismatch: return this.i18n`You appear to have signed this user, but the signature is invalid.`; + case UserTrust.UserDeviceNotSigned: return this.i18n`You have verified this user, but they have one or more unverified sessions.`; + case UserTrust.UserDeviceSignatureMismatch: return this.i18n`This user has a session signature that is invalid.`; + case UserTrust.UserSetupError: return this.i18n`This user hasn't set up cross-signing correctly`; + case UserTrust.OwnSetupError: return this.i18n`Cross-signing wasn't set up correctly on your side.`; + default: return this.i18n`Pending…`; + } + } + get trustShieldColor() { + if (!this._isEncrypted) { + return undefined; + } + switch (this._userTrust) { + case undefined: + case UserTrust.OwnSetupError: + return undefined; + case UserTrust.Trusted: + return "green"; + case UserTrust.UserNotSigned: + return "black"; + default: + return "red"; + } + } get type() { return "member-details"; } get shouldShowBackButton() { return true; } diff --git a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js index 45504a74..aa70d5b4 100644 --- a/src/platform/web/ui/session/rightpanel/MemberDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/MemberDetailsView.js @@ -27,6 +27,8 @@ export class MemberDetailsView extends TemplateView { if (vm.features.crossSigning) { securityNodes.push(t.p(vm => vm.isTrusted ? vm.i18n`This user is trusted` : vm.i18n`This user is not trusted`)); + securityNodes.push(t.p(vm => vm.trustDescription)); + securityNodes.push(t.p(["Shield color: ", vm => vm.trustShieldColor])); } return t.div({className: "MemberDetailsView"},