notify UI when we need session backup

This commit is contained in:
Bruno Windels 2020-09-17 18:00:00 +02:00
parent 06ccd74680
commit 494c5cbcf0
5 changed files with 37 additions and 7 deletions

View File

@ -31,10 +31,11 @@ const SessionStatus = createEnum(
export class SessionStatusViewModel extends ViewModel { export class SessionStatusViewModel extends ViewModel {
constructor(options) { constructor(options) {
super(options); super(options);
const {sync, reconnector} = options; const {sync, reconnector, session} = options;
this._sync = sync; this._sync = sync;
this._reconnector = reconnector; this._reconnector = reconnector;
this._status = this._calculateState(reconnector.connectionStatus.get(), sync.status.get()); this._status = this._calculateState(reconnector.connectionStatus.get(), sync.status.get());
this._session = session;
} }
@ -42,10 +43,13 @@ export class SessionStatusViewModel extends ViewModel {
const update = () => this._updateStatus(); const update = () => this._updateStatus();
this.track(this._sync.status.subscribe(update)); this.track(this._sync.status.subscribe(update));
this.track(this._reconnector.connectionStatus.subscribe(update)); this.track(this._reconnector.connectionStatus.subscribe(update));
this.track(this._session.needsSessionBackup.subscribe(() => {
this.emitChange();
}));
} }
get isShown() { get isShown() {
return this._status !== SessionStatus.Syncing; return this._session.needsSessionBackup.get() || this._status !== SessionStatus.Syncing;
} }
get statusLabel() { get statusLabel() {
@ -61,6 +65,9 @@ export class SessionStatusViewModel extends ViewModel {
case SessionStatus.SyncError: case SessionStatus.SyncError:
return this.i18n`Sync failed because of ${this._sync.error}`; return this.i18n`Sync failed because of ${this._sync.error}`;
} }
if (this._session.needsSessionBackup.get()) {
return this.i18n`Some messages could not be decrypted. Connect to your secret storage to decrypt them.`;
}
return ""; return "";
} }
@ -122,9 +129,19 @@ export class SessionStatusViewModel extends ViewModel {
return this._status === SessionStatus.Disconnected; return this._status === SessionStatus.Disconnected;
} }
get isSecretStorageShown() {
return this._session.needsSessionBackup.get();
}
connectNow() { connectNow() {
if (this.isConnectNowShown) { if (this.isConnectNowShown) {
this._reconnector.tryNow(); this._reconnector.tryNow();
} }
} }
enterPassphrase(passphrase) {
if (passphrase) {
this._session.enableSecretStorage("passphrase", passphrase);
}
}
} }

View File

@ -26,7 +26,8 @@ export class SessionViewModel extends ViewModel {
this._session = sessionContainer.session; this._session = sessionContainer.session;
this._sessionStatusViewModel = this.track(new SessionStatusViewModel(this.childOptions({ this._sessionStatusViewModel = this.track(new SessionStatusViewModel(this.childOptions({
sync: sessionContainer.sync, sync: sessionContainer.sync,
reconnector: sessionContainer.reconnector reconnector: sessionContainer.reconnector,
session: sessionContainer.session,
}))); })));
this._currentRoomTileViewModel = null; this._currentRoomTileViewModel = null;
this._currentRoomViewModel = null; this._currentRoomViewModel = null;

View File

@ -36,6 +36,7 @@ import {
writeKey as ssssWriteKey, writeKey as ssssWriteKey,
} from "./ssss/index.js"; } from "./ssss/index.js";
import {SecretStorage} from "./ssss/SecretStorage.js"; import {SecretStorage} from "./ssss/SecretStorage.js";
import {ObservableValue} from "../observable/ObservableValue.js";
const PICKLE_KEY = "DEFAULT_KEY"; const PICKLE_KEY = "DEFAULT_KEY";
@ -74,6 +75,7 @@ export class Session {
}); });
} }
this._createRoomEncryption = this._createRoomEncryption.bind(this); this._createRoomEncryption = this._createRoomEncryption.bind(this);
this.needsSessionBackup = new ObservableValue(false);
} }
// called once this._e2eeAccount is assigned // called once this._e2eeAccount is assigned
@ -140,6 +142,11 @@ export class Session {
storage: this._storage, storage: this._storage,
sessionBackup: this._sessionBackup, sessionBackup: this._sessionBackup,
encryptionParams, encryptionParams,
notifyMissingMegolmSession: () => {
if (!this._sessionBackup) {
this.needsSessionBackup.set(true)
}
},
}); });
} }
@ -185,6 +192,7 @@ export class Session {
} }
} }
} }
this.needsSessionBackup.set(false);
} }
// called after load // called after load

View File

@ -22,7 +22,7 @@ import {makeTxnId} from "../common.js";
const ENCRYPTED_TYPE = "m.room.encrypted"; const ENCRYPTED_TYPE = "m.room.encrypted";
export class RoomEncryption { export class RoomEncryption {
constructor({room, deviceTracker, olmEncryption, megolmEncryption, megolmDecryption, encryptionParams, storage, sessionBackup}) { constructor({room, deviceTracker, olmEncryption, megolmEncryption, megolmDecryption, encryptionParams, storage, sessionBackup, notifyMissingMegolmSession}) {
this._room = room; this._room = room;
this._deviceTracker = deviceTracker; this._deviceTracker = deviceTracker;
this._olmEncryption = olmEncryption; this._olmEncryption = olmEncryption;
@ -38,15 +38,18 @@ export class RoomEncryption {
this._senderDeviceCache = new Map(); this._senderDeviceCache = new Map();
this._storage = storage; this._storage = storage;
this._sessionBackup = sessionBackup; this._sessionBackup = sessionBackup;
this._notifyMissingMegolmSession = notifyMissingMegolmSession;
} }
enableSessionBackup(sessionBackup) { async enableSessionBackup(sessionBackup) {
if (this._sessionBackup) { if (this._sessionBackup) {
return; return;
} }
this._sessionBackup = sessionBackup; this._sessionBackup = sessionBackup;
// TODO: query session backup for all missing sessions so far for(const key of this._eventIdsByMissingSession.keys()) {
// can we query multiple? no, only for sessionId, all for room, or all const [senderKey, sessionId] = key.split("|");
await this._requestMissingSessionFromBackup(senderKey, sessionId);
}
} }
notifyTimelineClosed() { notifyTimelineClosed() {

View File

@ -26,6 +26,7 @@ export class SessionStatusView extends TemplateView {
spinner(t, {hidden: vm => !vm.isWaiting}), spinner(t, {hidden: vm => !vm.isWaiting}),
t.p(vm => vm.statusLabel), t.p(vm => vm.statusLabel),
t.if(vm => vm.isConnectNowShown, t.createTemplate(t => t.button({onClick: () => vm.connectNow()}, "Retry now"))), t.if(vm => vm.isConnectNowShown, t.createTemplate(t => t.button({onClick: () => vm.connectNow()}, "Retry now"))),
t.if(vm => vm.isSecretStorageShown, t.createTemplate(t => t.button({onClick: () => vm.enterPassphrase(prompt("passphrase"))}, "Enter passphrase"))),
window.DEBUG ? t.button({id: "showlogs"}, "Show logs") : "" window.DEBUG ? t.button({id: "showlogs"}, "Show logs") : ""
]); ]);
} }