notify UI when we need session backup
This commit is contained in:
parent
06ccd74680
commit
494c5cbcf0
5 changed files with 37 additions and 7 deletions
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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") : ""
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue