- Add Dev Mode toggle to settings that persists in vault metadata - Add test permission prompt button (✨) to all page headers when dev mode enabled - Move devMode and onTestPrompt to NavComponent base class for inheritance - Refactor all home components to extend NavComponent - Simplify permission prompt layout: remove duplicate domain from header - Convert permission descriptions to flowing single paragraphs - Update header-buttons styling for consistent lock/magic button layout Files modified: - projects/common/src/lib/common/nav-component.ts (devMode, onTestPrompt) - projects/common/src/lib/services/storage/types.ts (devMode property) - projects/common/src/lib/services/storage/signer-meta-handler.ts (setDevMode) - projects/common/src/lib/styles/_common.scss (header-buttons styling) - projects/*/src/app/components/home/*/settings.component.* (dev mode UI) - projects/*/src/app/components/home/*/*.component.* (extend NavComponent) - projects/*/public/prompt.html (simplified layout) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
126 lines
3.6 KiB
TypeScript
126 lines
3.6 KiB
TypeScript
import { Component, inject, OnInit } from '@angular/core';
|
|
import { Router } from '@angular/router';
|
|
import {
|
|
ConfirmComponent,
|
|
LoggerService,
|
|
NavComponent,
|
|
SignerMetaData_VaultSnapshot,
|
|
StartupService,
|
|
} from '@common';
|
|
import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage-service-config';
|
|
|
|
@Component({
|
|
selector: 'app-backups',
|
|
templateUrl: './backups.component.html',
|
|
styleUrl: './backups.component.scss',
|
|
imports: [ConfirmComponent],
|
|
})
|
|
export class BackupsComponent extends NavComponent implements OnInit {
|
|
readonly #router = inject(Router);
|
|
readonly #startup = inject(StartupService);
|
|
readonly #logger = inject(LoggerService);
|
|
|
|
backups: SignerMetaData_VaultSnapshot[] = [];
|
|
maxBackups = 5;
|
|
restoringBackupId: string | null = null;
|
|
|
|
ngOnInit(): void {
|
|
this.loadBackups();
|
|
this.maxBackups = this.storage.getSignerMetaHandler().getMaxBackups();
|
|
}
|
|
|
|
loadBackups(): void {
|
|
this.backups = this.storage.getSignerMetaHandler().getBackups();
|
|
}
|
|
|
|
async onMaxBackupsChange(event: Event): Promise<void> {
|
|
const input = event.target as HTMLInputElement;
|
|
const value = parseInt(input.value, 10);
|
|
if (!isNaN(value) && value >= 1 && value <= 20) {
|
|
this.maxBackups = value;
|
|
await this.storage.getSignerMetaHandler().setMaxBackups(value);
|
|
}
|
|
}
|
|
|
|
async createManualBackup(): Promise<void> {
|
|
const browserSyncData = this.storage.getBrowserSyncHandler().browserSyncData;
|
|
if (browserSyncData) {
|
|
await this.storage.getSignerMetaHandler().createBackup(browserSyncData, 'manual');
|
|
this.loadBackups();
|
|
}
|
|
}
|
|
|
|
async restoreBackup(backupId: string): Promise<void> {
|
|
this.restoringBackupId = backupId;
|
|
try {
|
|
// First, create a pre-restore backup of current state
|
|
const currentData = this.storage.getBrowserSyncHandler().browserSyncData;
|
|
if (currentData) {
|
|
await this.storage.getSignerMetaHandler().createBackup(currentData, 'pre-restore');
|
|
}
|
|
|
|
// Get the backup data
|
|
const backupData = this.storage.getSignerMetaHandler().getBackupData(backupId);
|
|
if (!backupData) {
|
|
throw new Error('Backup not found');
|
|
}
|
|
|
|
// Import the backup
|
|
await this.storage.deleteVault(true);
|
|
await this.storage.importVault(backupData);
|
|
this.#logger.logVaultImport('Backup Restore');
|
|
this.storage.isInitialized = false;
|
|
this.#startup.startOver(getNewStorageServiceConfig());
|
|
} catch (error) {
|
|
console.error('Failed to restore backup:', error);
|
|
this.restoringBackupId = null;
|
|
}
|
|
}
|
|
|
|
async deleteBackup(backupId: string): Promise<void> {
|
|
await this.storage.getSignerMetaHandler().deleteBackup(backupId);
|
|
this.loadBackups();
|
|
}
|
|
|
|
formatDate(isoDate: string): string {
|
|
const date = new Date(isoDate);
|
|
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
|
|
}
|
|
|
|
getReasonLabel(reason?: string): string {
|
|
switch (reason) {
|
|
case 'auto':
|
|
return 'Auto';
|
|
case 'manual':
|
|
return 'Manual';
|
|
case 'pre-restore':
|
|
return 'Pre-Restore';
|
|
default:
|
|
return 'Unknown';
|
|
}
|
|
}
|
|
|
|
getReasonClass(reason?: string): string {
|
|
switch (reason) {
|
|
case 'auto':
|
|
return 'reason-auto';
|
|
case 'manual':
|
|
return 'reason-manual';
|
|
case 'pre-restore':
|
|
return 'reason-prerestore';
|
|
default:
|
|
return '';
|
|
}
|
|
}
|
|
|
|
goBack(): void {
|
|
this.#router.navigateByUrl('/home/settings');
|
|
}
|
|
|
|
async onClickLock(): Promise<void> {
|
|
this.#logger.logVaultLock();
|
|
await this.storage.lockVault();
|
|
this.#router.navigateByUrl('/vault-login');
|
|
}
|
|
}
|