forked from mystiq/hydrogen-web
add backupWriteStatus so binding can take multiple fields into account
This commit is contained in:
parent
6541aacf98
commit
06a1421e97
2 changed files with 68 additions and 17 deletions
|
@ -18,7 +18,8 @@ import {ViewModel} from "../../ViewModel.js";
|
||||||
import {KeyType} from "../../../matrix/ssss/index";
|
import {KeyType} from "../../../matrix/ssss/index";
|
||||||
import {createEnum} from "../../../utils/enum";
|
import {createEnum} from "../../../utils/enum";
|
||||||
|
|
||||||
export const Status = createEnum("Enabled", "SetupKey", "SetupPhrase", "Pending", "NewVersionAvailable");
|
export const Status = createEnum("Enabled", "SetupKey", "SetupPhrase", "Pending", "NewVersionAvailable", "Error", "Cancelled");
|
||||||
|
export const BackupWriteStatus = createEnum("Writing", "Stopped", "Done", "Pending");
|
||||||
|
|
||||||
export class KeyBackupViewModel extends ViewModel {
|
export class KeyBackupViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
@ -30,7 +31,11 @@ export class KeyBackupViewModel extends ViewModel {
|
||||||
this._status = undefined;
|
this._status = undefined;
|
||||||
this._backupOperation = this._session.keyBackup.flatMap(keyBackup => keyBackup.operationInProgress);
|
this._backupOperation = this._session.keyBackup.flatMap(keyBackup => keyBackup.operationInProgress);
|
||||||
this._progress = this._backupOperation.flatMap(op => op.progress);
|
this._progress = this._backupOperation.flatMap(op => op.progress);
|
||||||
this.track(this._backupOperation.subscribe(() => this.emitChange("isBackingUp")));
|
this.track(this._backupOperation.subscribe(() => {
|
||||||
|
// see if needsNewKey might be set
|
||||||
|
this._reevaluateStatus();
|
||||||
|
this.emitChange("isBackingUp");
|
||||||
|
}));
|
||||||
this.track(this._progress.subscribe(() => this.emitChange("backupPercentage")));
|
this.track(this._progress.subscribe(() => this.emitChange("backupPercentage")));
|
||||||
this._reevaluateStatus();
|
this._reevaluateStatus();
|
||||||
this.track(this._session.keyBackup.subscribe(() => {
|
this.track(this._session.keyBackup.subscribe(() => {
|
||||||
|
@ -47,7 +52,7 @@ export class KeyBackupViewModel extends ViewModel {
|
||||||
let status;
|
let status;
|
||||||
const keyBackup = this._session.keyBackup.get();
|
const keyBackup = this._session.keyBackup.get();
|
||||||
if (keyBackup) {
|
if (keyBackup) {
|
||||||
status = keyBackup.needsNewKey.get() ? Status.NewVersionAvailable : Status.Enabled;
|
status = keyBackup.needsNewKey ? Status.NewVersionAvailable : Status.Enabled;
|
||||||
} else {
|
} else {
|
||||||
status = this.showPhraseSetup() ? Status.SetupPhrase : Status.SetupKey;
|
status = this.showPhraseSetup() ? Status.SetupPhrase : Status.SetupKey;
|
||||||
} /* TODO: bring back "waiting to get online"
|
} /* TODO: bring back "waiting to get online"
|
||||||
|
@ -83,6 +88,27 @@ export class KeyBackupViewModel extends ViewModel {
|
||||||
return this._session.keyBackup.get()?.version;
|
return this._session.keyBackup.get()?.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get backupWriteStatus() {
|
||||||
|
const keyBackup = this._session.keyBackup.get();
|
||||||
|
if (!keyBackup) {
|
||||||
|
return BackupWriteStatus.Pending;
|
||||||
|
} else if (keyBackup.hasStopped) {
|
||||||
|
return BackupWriteStatus.Stopped;
|
||||||
|
}
|
||||||
|
const operation = keyBackup.operationInProgress.get();
|
||||||
|
if (operation) {
|
||||||
|
return BackupWriteStatus.Writing;
|
||||||
|
} else if (keyBackup.hasBackedUpAllKeys) {
|
||||||
|
return BackupWriteStatus.Done;
|
||||||
|
} else {
|
||||||
|
return BackupWriteStatus.Pending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get backupError() {
|
||||||
|
return this._session.keyBackup.get()?.error?.message;
|
||||||
|
}
|
||||||
|
|
||||||
get status() {
|
get status() {
|
||||||
return this._status;
|
return this._status;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +197,11 @@ export class KeyBackupViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelBackup() {
|
cancelBackup() {
|
||||||
this._session.keyBackup.get()?.operationInProgress.get()?.abort();
|
this._backupOperation.get()?.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
startBackup() {
|
||||||
|
this._session.keyBackup.get()?.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,22 +22,36 @@ export class KeyBackupSettingsView extends TemplateView {
|
||||||
t.map(vm => vm.status, (status, t, vm) => {
|
t.map(vm => vm.status, (status, t, vm) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "Enabled": return renderEnabled(t, vm);
|
case "Enabled": return renderEnabled(t, vm);
|
||||||
|
case "NewVersionAvailable": return renderNewVersionAvailable(t, vm);
|
||||||
case "SetupKey": return renderEnableFromKey(t, vm);
|
case "SetupKey": return renderEnableFromKey(t, vm);
|
||||||
case "SetupPhrase": return renderEnableFromPhrase(t, vm);
|
case "SetupPhrase": return renderEnableFromPhrase(t, vm);
|
||||||
case "NewVersionAvailable": return t.p(vm.i18n`A new backup version has been created. Disable key backup and enable it again with the new key.`);
|
|
||||||
case "Pending": return t.p(vm.i18n`Waiting to go online…`);
|
case "Pending": return t.p(vm.i18n`Waiting to go online…`);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
t.map(vm => vm.isBackingUp, (backingUp, t, vm) => {
|
t.map(vm => vm.backupWriteStatus, (status, t, vm) => {
|
||||||
if (backingUp) {
|
switch (status) {
|
||||||
const progress = t.progress({
|
case "Writing": {
|
||||||
min: 0,
|
const progress = t.progress({
|
||||||
max: 100,
|
min: 0,
|
||||||
value: vm => vm.backupPercentage,
|
max: 100,
|
||||||
});
|
value: vm => vm.backupPercentage,
|
||||||
return t.div([`Backup in progress `, progress, " ", vm => vm.backupInProgressLabel]);
|
});
|
||||||
} else {
|
return t.div([`Backup in progress `, progress, " ", vm => vm.backupInProgressLabel]);
|
||||||
return t.p("All keys are backed up.");
|
}
|
||||||
|
case "Stopped": {
|
||||||
|
let label;
|
||||||
|
const error = vm.backupError;
|
||||||
|
if (error) {
|
||||||
|
label = `Backup has stopped because of an error: ${vm.backupError}`;
|
||||||
|
} else {
|
||||||
|
label = `Backup has stopped`;
|
||||||
|
}
|
||||||
|
return t.p(label, " ", t.button({onClick: () => vm.startBackup()}, `Backup now`));
|
||||||
|
}
|
||||||
|
case "Done":
|
||||||
|
return t.p(`All keys are backed up.`);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
@ -46,7 +60,7 @@ export class KeyBackupSettingsView extends TemplateView {
|
||||||
|
|
||||||
function renderEnabled(t, vm) {
|
function renderEnabled(t, vm) {
|
||||||
const items = [
|
const items = [
|
||||||
t.p([vm.i18n`Session backup is enabled, using backup version ${vm.backupVersion}. `, t.button({onClick: () => vm.disable()}, vm.i18n`Disable`)])
|
t.p([vm.i18n`Key backup is enabled, using backup version ${vm.backupVersion}. `, t.button({onClick: () => vm.disable()}, vm.i18n`Disable`)])
|
||||||
];
|
];
|
||||||
if (vm.dehydratedDeviceId) {
|
if (vm.dehydratedDeviceId) {
|
||||||
items.push(t.p(vm.i18n`A dehydrated device id was set up with id ${vm.dehydratedDeviceId} which you can use during your next login with your secret storage key.`));
|
items.push(t.p(vm.i18n`A dehydrated device id was set up with id ${vm.dehydratedDeviceId} which you can use during your next login with your secret storage key.`));
|
||||||
|
@ -54,6 +68,13 @@ function renderEnabled(t, vm) {
|
||||||
return t.div(items);
|
return t.div(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderNewVersionAvailable(t, vm) {
|
||||||
|
const items = [
|
||||||
|
t.p([vm.i18n`A new backup version has been created from another device. Disable key backup and enable it again with the new key.`, t.button({onClick: () => vm.disable()}, vm.i18n`Disable`)])
|
||||||
|
];
|
||||||
|
return t.div(items);
|
||||||
|
}
|
||||||
|
|
||||||
function renderEnableFromKey(t, vm) {
|
function renderEnableFromKey(t, vm) {
|
||||||
const useASecurityPhrase = t.button({className: "link", onClick: () => vm.showPhraseSetup()}, vm.i18n`use a security phrase`);
|
const useASecurityPhrase = t.button({className: "link", onClick: () => vm.showPhraseSetup()}, vm.i18n`use a security phrase`);
|
||||||
return t.div([
|
return t.div([
|
||||||
|
@ -101,7 +122,7 @@ function renderEnableFieldRow(t, vm, label, callback) {
|
||||||
function renderError(t) {
|
function renderError(t) {
|
||||||
return t.if(vm => vm.error, (t, vm) => {
|
return t.if(vm => vm.error, (t, vm) => {
|
||||||
return t.div([
|
return t.div([
|
||||||
t.p({className: "error"}, vm => vm.i18n`Could not enable session backup: ${vm.error}.`),
|
t.p({className: "error"}, vm => vm.i18n`Could not enable key backup: ${vm.error}.`),
|
||||||
t.p(vm.i18n`Try double checking that you did not mix up your security key, security phrase and login password as explained above.`)
|
t.p(vm.i18n`Try double checking that you did not mix up your security key, security phrase and login password as explained above.`)
|
||||||
])
|
])
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue