Release v1.0.11 - Add dev mode with test prompt button on all headers
- 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>
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
<div class="sam-text-header">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<button class="back-btn" title="Go Back" (click)="goBack()">
|
||||
<span class="emoji">←</span>
|
||||
</button>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { Router } from '@angular/router';
|
||||
import {
|
||||
ConfirmComponent,
|
||||
LoggerService,
|
||||
NavComponent,
|
||||
SignerMetaData_VaultSnapshot,
|
||||
StartupService,
|
||||
StorageService,
|
||||
} from '@common';
|
||||
import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage-service-config';
|
||||
|
||||
@@ -15,9 +15,8 @@ import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage
|
||||
styleUrl: './backups.component.scss',
|
||||
imports: [ConfirmComponent],
|
||||
})
|
||||
export class BackupsComponent implements OnInit {
|
||||
export class BackupsComponent extends NavComponent implements OnInit {
|
||||
readonly #router = inject(Router);
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #startup = inject(StartupService);
|
||||
readonly #logger = inject(LoggerService);
|
||||
|
||||
@@ -27,11 +26,11 @@ export class BackupsComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadBackups();
|
||||
this.maxBackups = this.#storage.getSignerMetaHandler().getMaxBackups();
|
||||
this.maxBackups = this.storage.getSignerMetaHandler().getMaxBackups();
|
||||
}
|
||||
|
||||
loadBackups(): void {
|
||||
this.backups = this.#storage.getSignerMetaHandler().getBackups();
|
||||
this.backups = this.storage.getSignerMetaHandler().getBackups();
|
||||
}
|
||||
|
||||
async onMaxBackupsChange(event: Event): Promise<void> {
|
||||
@@ -39,14 +38,14 @@ export class BackupsComponent implements OnInit {
|
||||
const value = parseInt(input.value, 10);
|
||||
if (!isNaN(value) && value >= 1 && value <= 20) {
|
||||
this.maxBackups = value;
|
||||
await this.#storage.getSignerMetaHandler().setMaxBackups(value);
|
||||
await this.storage.getSignerMetaHandler().setMaxBackups(value);
|
||||
}
|
||||
}
|
||||
|
||||
async createManualBackup(): Promise<void> {
|
||||
const browserSyncData = this.#storage.getBrowserSyncHandler().browserSyncData;
|
||||
const browserSyncData = this.storage.getBrowserSyncHandler().browserSyncData;
|
||||
if (browserSyncData) {
|
||||
await this.#storage.getSignerMetaHandler().createBackup(browserSyncData, 'manual');
|
||||
await this.storage.getSignerMetaHandler().createBackup(browserSyncData, 'manual');
|
||||
this.loadBackups();
|
||||
}
|
||||
}
|
||||
@@ -55,22 +54,22 @@ export class BackupsComponent implements OnInit {
|
||||
this.restoringBackupId = backupId;
|
||||
try {
|
||||
// First, create a pre-restore backup of current state
|
||||
const currentData = this.#storage.getBrowserSyncHandler().browserSyncData;
|
||||
const currentData = this.storage.getBrowserSyncHandler().browserSyncData;
|
||||
if (currentData) {
|
||||
await this.#storage.getSignerMetaHandler().createBackup(currentData, 'pre-restore');
|
||||
await this.storage.getSignerMetaHandler().createBackup(currentData, 'pre-restore');
|
||||
}
|
||||
|
||||
// Get the backup data
|
||||
const backupData = this.#storage.getSignerMetaHandler().getBackupData(backupId);
|
||||
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);
|
||||
await this.storage.deleteVault(true);
|
||||
await this.storage.importVault(backupData);
|
||||
this.#logger.logVaultImport('Backup Restore');
|
||||
this.#storage.isInitialized = false;
|
||||
this.storage.isInitialized = false;
|
||||
this.#startup.startOver(getNewStorageServiceConfig());
|
||||
} catch (error) {
|
||||
console.error('Failed to restore backup:', error);
|
||||
@@ -79,7 +78,7 @@ export class BackupsComponent implements OnInit {
|
||||
}
|
||||
|
||||
async deleteBackup(backupId: string): Promise<void> {
|
||||
await this.#storage.getSignerMetaHandler().deleteBackup(backupId);
|
||||
await this.storage.getSignerMetaHandler().deleteBackup(backupId);
|
||||
this.loadBackups();
|
||||
}
|
||||
|
||||
@@ -120,7 +119,7 @@ export class BackupsComponent implements OnInit {
|
||||
|
||||
async onClickLock(): Promise<void> {
|
||||
this.#logger.logVaultLock();
|
||||
await this.#storage.lockVault();
|
||||
await this.storage.lockVault();
|
||||
this.#router.navigateByUrl('/vault-login');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||
<div class="sam-text-header">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<span>Bookmarks</span>
|
||||
<button class="add-btn" title="Bookmark This Page" (click)="onBookmarkThisPage()">
|
||||
<span class="emoji">➕</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Bookmark, LoggerService, SignerMetaData, StorageService } from '@common';
|
||||
import { Bookmark, LoggerService, NavComponent, SignerMetaData } from '@common';
|
||||
import { ChromeMetaHandler } from '../../../common/data/chrome-meta-handler';
|
||||
|
||||
@Component({
|
||||
@@ -9,10 +9,9 @@ import { ChromeMetaHandler } from '../../../common/data/chrome-meta-handler';
|
||||
styleUrl: './bookmarks.component.scss',
|
||||
imports: [],
|
||||
})
|
||||
export class BookmarksComponent implements OnInit {
|
||||
export class BookmarksComponent extends NavComponent implements OnInit {
|
||||
readonly #logger = inject(LoggerService);
|
||||
readonly #metaHandler = new ChromeMetaHandler();
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #router = inject(Router);
|
||||
|
||||
bookmarks: Bookmark[] = [];
|
||||
@@ -93,7 +92,7 @@ export class BookmarksComponent implements OnInit {
|
||||
|
||||
async onClickLock() {
|
||||
this.#logger.logVaultLock();
|
||||
await this.#storage.lockVault();
|
||||
await this.storage.lockVault();
|
||||
this.#router.navigateByUrl('/vault-login');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||
<div class="custom-header" style="position: sticky; top: 0">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<span class="text">Identities</span>
|
||||
|
||||
<button class="add-btn" title="New Identity" (click)="onClickNewIdentity()">
|
||||
|
||||
@@ -19,9 +19,16 @@
|
||||
background: var(--background);
|
||||
position: relative;
|
||||
|
||||
.lock-btn,
|
||||
.add-btn {
|
||||
.header-buttons {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-btn,
|
||||
.add-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 8px;
|
||||
@@ -41,11 +48,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.lock-btn {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
IconButtonComponent,
|
||||
Identity_DECRYPTED,
|
||||
LoggerService,
|
||||
NavComponent,
|
||||
NostrHelper,
|
||||
ProfileMetadata,
|
||||
ProfileMetadataService,
|
||||
@@ -17,8 +18,8 @@ import {
|
||||
styleUrl: './identities.component.scss',
|
||||
imports: [IconButtonComponent, ToastComponent],
|
||||
})
|
||||
export class IdentitiesComponent implements OnInit {
|
||||
readonly storage = inject(StorageService);
|
||||
export class IdentitiesComponent extends NavComponent implements OnInit {
|
||||
override readonly storage = inject(StorageService);
|
||||
readonly #router = inject(Router);
|
||||
readonly #profileMetadata = inject(ProfileMetadataService);
|
||||
readonly #logger = inject(LoggerService);
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||
<div class="sam-text-header">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<span>You</span>
|
||||
<button class="edit-btn" title="Edit profile" (click)="onClickEditProfile()">
|
||||
<span class="emoji">📝</span>
|
||||
|
||||
@@ -3,11 +3,11 @@ import { Router } from '@angular/router';
|
||||
import {
|
||||
Identity_DECRYPTED,
|
||||
LoggerService,
|
||||
NavComponent,
|
||||
NostrHelper,
|
||||
ProfileMetadata,
|
||||
ProfileMetadataService,
|
||||
PubkeyComponent,
|
||||
StorageService,
|
||||
ToastComponent,
|
||||
VisualNip05Pipe,
|
||||
validateNip05,
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
templateUrl: './identity.component.html',
|
||||
styleUrl: './identity.component.scss',
|
||||
})
|
||||
export class IdentityComponent implements OnInit {
|
||||
export class IdentityComponent extends NavComponent implements OnInit {
|
||||
selectedIdentity: Identity_DECRYPTED | undefined;
|
||||
selectedIdentityNpub: string | undefined;
|
||||
profile: ProfileMetadata | null = null;
|
||||
@@ -27,7 +27,6 @@ export class IdentityComponent implements OnInit {
|
||||
validating = false;
|
||||
loading = true;
|
||||
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #router = inject(Router);
|
||||
readonly #profileMetadata = inject(ProfileMetadataService);
|
||||
readonly #logger = inject(LoggerService);
|
||||
@@ -82,17 +81,17 @@ export class IdentityComponent implements OnInit {
|
||||
|
||||
async onClickLock() {
|
||||
this.#logger.logVaultLock();
|
||||
await this.#storage.lockVault();
|
||||
await this.storage.lockVault();
|
||||
this.#router.navigateByUrl('/vault-login');
|
||||
}
|
||||
|
||||
async #loadData() {
|
||||
try {
|
||||
const selectedIdentityId =
|
||||
this.#storage.getBrowserSessionHandler().browserSessionData
|
||||
this.storage.getBrowserSessionHandler().browserSessionData
|
||||
?.selectedIdentityId ?? null;
|
||||
|
||||
const identity = this.#storage
|
||||
const identity = this.storage
|
||||
.getBrowserSessionHandler()
|
||||
.browserSessionData?.identities.find(
|
||||
(x) => x.id === selectedIdentityId
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<div class="sam-text-header">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<span> Plebeian Signer </span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { LoggerService, StorageService } from '@common';
|
||||
import { LoggerService, NavComponent } from '@common';
|
||||
import packageJson from '../../../../../../../package.json';
|
||||
|
||||
@Component({
|
||||
@@ -8,16 +8,15 @@ import packageJson from '../../../../../../../package.json';
|
||||
templateUrl: './info.component.html',
|
||||
styleUrl: './info.component.scss',
|
||||
})
|
||||
export class InfoComponent {
|
||||
export class InfoComponent extends NavComponent {
|
||||
readonly #logger = inject(LoggerService);
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #router = inject(Router);
|
||||
|
||||
version = packageJson.custom.chrome.version;
|
||||
|
||||
async onClickLock() {
|
||||
this.#logger.logVaultLock();
|
||||
await this.#storage.lockVault();
|
||||
await this.storage.lockVault();
|
||||
this.#router.navigateByUrl('/vault-login');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<div class="sam-text-header">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<span>Logs</span>
|
||||
<div class="logs-actions">
|
||||
<button class="btn btn-sm btn-secondary" title="Refresh logs" (click)="onRefresh()">Refresh</button>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { LoggerService, LogEntry, StorageService } from '@common';
|
||||
import { LoggerService, LogEntry, NavComponent } from '@common';
|
||||
import { DatePipe } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
@@ -9,9 +9,8 @@ import { DatePipe } from '@angular/common';
|
||||
styleUrl: './logs.component.scss',
|
||||
imports: [DatePipe],
|
||||
})
|
||||
export class LogsComponent implements OnInit {
|
||||
export class LogsComponent extends NavComponent implements OnInit {
|
||||
readonly #logger = inject(LoggerService);
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #router = inject(Router);
|
||||
|
||||
get logs(): LogEntry[] {
|
||||
@@ -46,7 +45,7 @@ export class LogsComponent implements OnInit {
|
||||
|
||||
async onClickLock() {
|
||||
this.#logger.logVaultLock();
|
||||
await this.#storage.lockVault();
|
||||
await this.storage.lockVault();
|
||||
this.#router.navigateByUrl('/vault-login');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,39 @@
|
||||
<div class="sam-text-header">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<span> Settings </span>
|
||||
</div>
|
||||
|
||||
<div class="vault-buttons">
|
||||
<button class="btn btn-primary" (click)="onClickExportVault()">
|
||||
Export Vault
|
||||
</button>
|
||||
<button class="btn btn-primary" (click)="navigate('/vault-import')">
|
||||
Import Vault
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<lib-nav-item text="💾 Backups" (click)="navigate('/home/backups')"></lib-nav-item>
|
||||
<lib-nav-item text="🪵 Logs" (click)="navigate('/home/logs')"></lib-nav-item>
|
||||
<lib-nav-item text="💡 Info" (click)="navigate('/home/info')"></lib-nav-item>
|
||||
|
||||
<div class="dev-mode-row">
|
||||
<label class="toggle-label">
|
||||
<input type="checkbox" [checked]="devMode" (change)="onToggleDevMode($event)" />
|
||||
<span>Dev Mode</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="sam-flex-grow"></div>
|
||||
|
||||
<div class="sync-info">
|
||||
<span class="sync-label">SYNC: {{ syncFlow }}</span>
|
||||
<p class="sync-note">
|
||||
@@ -13,20 +42,6 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" (click)="onClickExportVault()">
|
||||
Export Vault
|
||||
</button>
|
||||
|
||||
<button class="btn btn-primary" (click)="navigate('/vault-import')">
|
||||
Import Vault
|
||||
</button>
|
||||
|
||||
<lib-nav-item text="💾 Backups" (click)="navigate('/home/backups')"></lib-nav-item>
|
||||
<lib-nav-item text="🪵 Logs" (click)="navigate('/home/logs')"></lib-nav-item>
|
||||
<lib-nav-item text="💡 Info" (click)="navigate('/home/info')"></lib-nav-item>
|
||||
|
||||
<div class="sam-flex-grow"></div>
|
||||
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
(click)="
|
||||
|
||||
@@ -16,6 +16,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
.vault-buttons {
|
||||
display: flex;
|
||||
gap: var(--size);
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.dev-mode-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--size);
|
||||
|
||||
.toggle-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--size-h);
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sync-info {
|
||||
.sync-label {
|
||||
display: block;
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
StorageService,
|
||||
} from '@common';
|
||||
import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage-service-config';
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
@@ -22,6 +23,7 @@ import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage
|
||||
export class SettingsComponent extends NavComponent implements OnInit {
|
||||
readonly #router = inject(Router);
|
||||
syncFlow: string | undefined;
|
||||
override devMode = false;
|
||||
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #startup = inject(StartupService);
|
||||
@@ -45,6 +47,44 @@ export class SettingsComponent extends NavComponent implements OnInit {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Load dev mode setting
|
||||
this.devMode = this.#storage.getSignerMetaHandler().signerMetaData?.devMode ?? false;
|
||||
}
|
||||
|
||||
async onToggleDevMode(event: Event) {
|
||||
const checked = (event.target as HTMLInputElement).checked;
|
||||
this.devMode = checked;
|
||||
await this.#storage.getSignerMetaHandler().setDevMode(checked);
|
||||
}
|
||||
|
||||
override async onTestPrompt() {
|
||||
// Open a test permission prompt window
|
||||
const testEvent = {
|
||||
kind: 1,
|
||||
content: 'This is a test note for permission prompt preview.',
|
||||
tags: [],
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
};
|
||||
const base64Event = Buffer.from(JSON.stringify(testEvent, null, 2)).toString('base64');
|
||||
const currentIdentity = this.#storage.getBrowserSessionHandler().browserSessionData?.identities.find(
|
||||
i => i.id === this.#storage.getBrowserSessionHandler().browserSessionData?.selectedIdentityId
|
||||
);
|
||||
const nick = currentIdentity?.nick ?? 'Test Identity';
|
||||
|
||||
const width = 375;
|
||||
const height = 600;
|
||||
const left = Math.round((screen.width - width) / 2);
|
||||
const top = Math.round((screen.height - height) / 2);
|
||||
|
||||
chrome.windows.create({
|
||||
type: 'popup',
|
||||
url: `prompt.html?method=signEvent&host=example.com&id=test-${Date.now()}&nick=${encodeURIComponent(nick)}&event=${base64Event}`,
|
||||
width,
|
||||
height,
|
||||
left,
|
||||
top,
|
||||
});
|
||||
}
|
||||
|
||||
async onResetExtension() {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<div class="sam-text-header">
|
||||
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
<div class="header-buttons">
|
||||
<button class="header-btn" title="Lock" (click)="onClickLock()">
|
||||
<span class="emoji">🔒</span>
|
||||
</button>
|
||||
@if (devMode) {
|
||||
<button class="header-btn" title="Test Permission Prompt" (click)="onTestPrompt()">
|
||||
<span class="emoji">✨</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@if (showBackButton) {
|
||||
<button class="back-btn" title="Go Back" (click)="goBack()">
|
||||
<span class="emoji">←</span>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
LoggerService,
|
||||
StorageService,
|
||||
NavComponent,
|
||||
NwcService,
|
||||
NwcConnection_DECRYPTED,
|
||||
CashuService,
|
||||
@@ -35,9 +35,8 @@ type WalletSection =
|
||||
styleUrl: './wallet.component.scss',
|
||||
imports: [CommonModule, FormsModule],
|
||||
})
|
||||
export class WalletComponent implements OnInit, OnDestroy {
|
||||
export class WalletComponent extends NavComponent implements OnInit, OnDestroy {
|
||||
readonly #logger = inject(LoggerService);
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #router = inject(Router);
|
||||
readonly nwcService = inject(NwcService);
|
||||
readonly cashuService = inject(CashuService);
|
||||
@@ -195,7 +194,7 @@ export class WalletComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit(): void {
|
||||
// Load current sync flow setting
|
||||
this.currentSyncFlow = this.#storage.getSyncFlow();
|
||||
this.currentSyncFlow = this.storage.getSyncFlow();
|
||||
|
||||
// Refresh balances on init if we have connections
|
||||
if (this.connections.length > 0) {
|
||||
@@ -937,7 +936,7 @@ export class WalletComponent implements OnInit, OnDestroy {
|
||||
|
||||
async onClickLock() {
|
||||
this.#logger.logVaultLock();
|
||||
await this.#storage.lockVault();
|
||||
await this.storage.lockVault();
|
||||
this.#router.navigateByUrl('/vault-login');
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export class WhitelistedAppsComponent extends NavComponent {
|
||||
@ViewChild('toast') toast!: ToastComponent;
|
||||
@ViewChild('confirm') confirm!: ConfirmComponent;
|
||||
|
||||
readonly storage = inject(StorageService);
|
||||
override readonly storage = inject(StorageService);
|
||||
readonly #router = inject(Router);
|
||||
|
||||
get whitelistedHosts(): string[] {
|
||||
|
||||
Reference in New Issue
Block a user