Release v1.0.7 - Move lock button to page headers
- Move lock button from bottom navigation bar to each page header - Add lock button styling to common SCSS with hover effect - Remove logs and info tabs from bottom navigation - Standardize header height to 48px across all pages - Simplify home component by removing lock logic Files modified: - package.json, manifest.json (both browsers) - home.component.html/ts (both browsers) - identities, identity, bookmarks, logs, info, settings components - projects/common/src/lib/styles/_common.scss 🤖 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,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "plebeian-signer",
|
"name": "plebeian-signer",
|
||||||
"version": "v1.0.6",
|
"version": "v1.0.7",
|
||||||
"custom": {
|
"custom": {
|
||||||
"chrome": {
|
"chrome": {
|
||||||
"version": "v1.0.6"
|
"version": "v1.0.7"
|
||||||
},
|
},
|
||||||
"firefox": {
|
"firefox": {
|
||||||
"version": "v1.0.6"
|
"version": "v1.0.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Plebeian Signer - Nostr Identity Manager & Signer",
|
"name": "Plebeian Signer - Nostr Identity Manager & Signer",
|
||||||
"description": "Manage and switch between multiple identities while interacting with Nostr apps",
|
"description": "Manage and switch between multiple identities while interacting with Nostr apps",
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"homepage_url": "https://git.mleku.dev/mleku/plebeian-signer",
|
"homepage_url": "https://git.mleku.dev/mleku/plebeian-signer",
|
||||||
"options_page": "options.html",
|
"options_page": "options.html",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||||
<div class="bookmarks-header">
|
<div class="sam-text-header">
|
||||||
<span class="bookmarks-title">Bookmarks</span>
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
<button class="btn btn-primary btn-sm" (click)="onBookmarkThisPage()">
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
|
<span>Bookmarks</span>
|
||||||
|
<button class="action-btn btn btn-primary btn-sm" (click)="onBookmarkThisPage()">
|
||||||
<span class="emoji">🔖</span> Bookmark This Page
|
<span class="emoji">🔖</span> Bookmark This Page
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,21 +2,24 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: var(--size);
|
padding-top: var(--size);
|
||||||
|
padding-bottom: var(--size);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
.bookmarks-header {
|
> *:not(.sam-text-header) {
|
||||||
display: flex;
|
margin-left: var(--size);
|
||||||
justify-content: space-between;
|
margin-right: var(--size);
|
||||||
align-items: center;
|
}
|
||||||
|
|
||||||
|
.sam-text-header {
|
||||||
margin-bottom: var(--size);
|
margin-bottom: var(--size);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.bookmarks-title {
|
.action-btn {
|
||||||
font-weight: 600;
|
position: absolute;
|
||||||
font-size: 1.1rem;
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmarks-container {
|
.bookmarks-container {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Component, inject, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
import { Bookmark, LoggerService, SignerMetaData } from '@common';
|
import { Router } from '@angular/router';
|
||||||
|
import { Bookmark, LoggerService, SignerMetaData, StorageService } from '@common';
|
||||||
import { ChromeMetaHandler } from '../../../common/data/chrome-meta-handler';
|
import { ChromeMetaHandler } from '../../../common/data/chrome-meta-handler';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -11,6 +12,8 @@ import { ChromeMetaHandler } from '../../../common/data/chrome-meta-handler';
|
|||||||
export class BookmarksComponent implements OnInit {
|
export class BookmarksComponent implements OnInit {
|
||||||
readonly #logger = inject(LoggerService);
|
readonly #logger = inject(LoggerService);
|
||||||
readonly #metaHandler = new ChromeMetaHandler();
|
readonly #metaHandler = new ChromeMetaHandler();
|
||||||
|
readonly #storage = inject(StorageService);
|
||||||
|
readonly #router = inject(Router);
|
||||||
|
|
||||||
bookmarks: Bookmark[] = [];
|
bookmarks: Bookmark[] = [];
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
@@ -87,4 +90,10 @@ export class BookmarksComponent implements OnInit {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,16 +33,4 @@
|
|||||||
<a class="tab" routerLink="/home/bookmarks" routerLinkActive="active" title="Bookmarks">
|
<a class="tab" routerLink="/home/bookmarks" routerLinkActive="active" title="Bookmarks">
|
||||||
<span class="emoji">🔖</span>
|
<span class="emoji">🔖</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="tab" routerLink="/home/logs" routerLinkActive="active" title="Logs">
|
|
||||||
<span class="emoji">🪵</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a class="tab" routerLink="/home/info" routerLinkActive="active" title="Info">
|
|
||||||
<span class="emoji">💡</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<button class="tab" (click)="onClickLock()" title="Lock">
|
|
||||||
<span class="emoji">🔒</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Component, inject } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Router, RouterModule, RouterOutlet } from '@angular/router';
|
import { RouterModule, RouterOutlet } from '@angular/router';
|
||||||
import { LoggerService, StorageService } from '@common';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
@@ -8,14 +7,4 @@ import { LoggerService, StorageService } from '@common';
|
|||||||
styleUrl: './home.component.scss',
|
styleUrl: './home.component.scss',
|
||||||
imports: [RouterOutlet, RouterModule],
|
imports: [RouterOutlet, RouterModule],
|
||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {}
|
||||||
readonly #storage = inject(StorageService);
|
|
||||||
readonly #router = inject(Router);
|
|
||||||
readonly #logger = inject(LoggerService);
|
|
||||||
|
|
||||||
async onClickLock() {
|
|
||||||
this.#logger.logVaultLock();
|
|
||||||
await this.#storage.lockVault();
|
|
||||||
this.#router.navigateByUrl('/vault-login');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||||
<div class="custom-header" style="position: sticky; top: 0">
|
<div class="custom-header" style="position: sticky; top: 0">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span class="text">Identities</span>
|
<span class="text">Identities</span>
|
||||||
|
|
||||||
<button class="button btn btn-primary btn-sm" (click)="onClickNewIdentity()">
|
<button class="button btn btn-primary btn-sm" (click)="onClickNewIdentity()">
|
||||||
|
|||||||
@@ -3,37 +3,55 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-left: var(--size);
|
|
||||||
padding-right: var(--size);
|
> *:not(.custom-header) {
|
||||||
|
margin-left: var(--size);
|
||||||
|
margin-right: var(--size);
|
||||||
|
}
|
||||||
|
|
||||||
.custom-header {
|
.custom-header {
|
||||||
padding-top: var(--size);
|
height: 48px;
|
||||||
padding-bottom: var(--size);
|
min-height: 48px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: auto;
|
grid-template-rows: auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.lock-btn {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--background-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
grid-column-start: 1;
|
position: absolute;
|
||||||
grid-column-end: 2;
|
right: 0;
|
||||||
grid-row-start: 1;
|
|
||||||
grid-row-end: 2;
|
|
||||||
justify-self: end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
grid-column-start: 1;
|
|
||||||
grid-column-end: 2;
|
|
||||||
grid-row-start: 1;
|
|
||||||
grid-row-end: 2;
|
|
||||||
font-family: var(--font-heading);
|
font-family: var(--font-heading);
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.1rem;
|
letter-spacing: 0.1rem;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
height: 32px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Router } from '@angular/router';
|
|||||||
import {
|
import {
|
||||||
IconButtonComponent,
|
IconButtonComponent,
|
||||||
Identity_DECRYPTED,
|
Identity_DECRYPTED,
|
||||||
|
LoggerService,
|
||||||
NostrHelper,
|
NostrHelper,
|
||||||
ProfileMetadata,
|
ProfileMetadata,
|
||||||
ProfileMetadataService,
|
ProfileMetadataService,
|
||||||
@@ -20,6 +21,7 @@ export class IdentitiesComponent implements OnInit {
|
|||||||
readonly storage = inject(StorageService);
|
readonly storage = inject(StorageService);
|
||||||
readonly #router = inject(Router);
|
readonly #router = inject(Router);
|
||||||
readonly #profileMetadata = inject(ProfileMetadataService);
|
readonly #profileMetadata = inject(ProfileMetadataService);
|
||||||
|
readonly #logger = inject(LoggerService);
|
||||||
|
|
||||||
// Cache of pubkey -> profile for quick lookup
|
// Cache of pubkey -> profile for quick lookup
|
||||||
#profileCache = new Map<string, ProfileMetadata | null>();
|
#profileCache = new Map<string, ProfileMetadata | null>();
|
||||||
@@ -73,4 +75,10 @@ export class IdentitiesComponent implements OnInit {
|
|||||||
onClickWhitelistedApps() {
|
onClickWhitelistedApps() {
|
||||||
this.#router.navigateByUrl('/whitelisted-apps');
|
this.#router.navigateByUrl('/whitelisted-apps');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||||
<div class="sam-text-header">
|
<div class="sam-text-header">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span>You</span>
|
<span>You</span>
|
||||||
<button class="edit-btn" title="Edit profile" (click)="onClickEditProfile()">
|
<button class="edit-btn" title="Edit profile" (click)="onClickEditProfile()">
|
||||||
<img src="edit.svg" alt="Edit" class="edit-icon" />
|
<img src="edit.svg" alt="Edit" class="edit-icon" />
|
||||||
|
|||||||
@@ -4,14 +4,12 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.sam-text-header {
|
.sam-text-header {
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.edit-btn {
|
.edit-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: var(--size);
|
right: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 4px;
|
padding: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ export class IdentityComponent implements OnInit {
|
|||||||
this.#router.navigateByUrl('/profile-edit');
|
this.#router.navigateByUrl('/profile-edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
|
|
||||||
async #loadData() {
|
async #loadData() {
|
||||||
try {
|
try {
|
||||||
const selectedIdentityId =
|
const selectedIdentityId =
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<div class="sam-text-header">
|
<div class="sam-text-header">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span> Plebeian Signer </span>
|
<span> Plebeian Signer </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-left: var(--size);
|
|
||||||
padding-right: var(--size);
|
> *:not(.sam-text-header) {
|
||||||
|
margin-left: var(--size);
|
||||||
|
margin-right: var(--size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sam-text-header {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { LoggerService, StorageService } from '@common';
|
||||||
import packageJson from '../../../../../../../package.json';
|
import packageJson from '../../../../../../../package.json';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -7,5 +9,15 @@ import packageJson from '../../../../../../../package.json';
|
|||||||
styleUrl: './info.component.scss',
|
styleUrl: './info.component.scss',
|
||||||
})
|
})
|
||||||
export class InfoComponent {
|
export class InfoComponent {
|
||||||
|
readonly #logger = inject(LoggerService);
|
||||||
|
readonly #storage = inject(StorageService);
|
||||||
|
readonly #router = inject(Router);
|
||||||
|
|
||||||
version = packageJson.custom.chrome.version;
|
version = packageJson.custom.chrome.version;
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<div class="logs-header">
|
<div class="sam-text-header">
|
||||||
<span class="logs-title">Logs</span>
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
|
<span>Logs</span>
|
||||||
<div class="logs-actions">
|
<div class="logs-actions">
|
||||||
<button class="btn btn-sm btn-secondary" (click)="onRefresh()">Refresh</button>
|
<button class="btn btn-sm btn-secondary" (click)="onRefresh()">Refresh</button>
|
||||||
<button class="btn btn-sm btn-secondary" (click)="onClear()">Clear</button>
|
<button class="btn btn-sm btn-secondary" (click)="onClear()">Clear</button>
|
||||||
|
|||||||
@@ -2,26 +2,26 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: var(--size);
|
padding-top: var(--size);
|
||||||
|
padding-bottom: var(--size);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
.logs-header {
|
> *:not(.sam-text-header) {
|
||||||
display: flex;
|
margin-left: var(--size);
|
||||||
justify-content: space-between;
|
margin-right: var(--size);
|
||||||
align-items: center;
|
}
|
||||||
|
|
||||||
|
.sam-text-header {
|
||||||
margin-bottom: var(--size);
|
margin-bottom: var(--size);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.logs-actions {
|
.logs-actions {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.logs-title {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logs-container {
|
.logs-container {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Component, inject, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
import { LoggerService, LogEntry } from '@common';
|
import { Router } from '@angular/router';
|
||||||
|
import { LoggerService, LogEntry, StorageService } from '@common';
|
||||||
import { DatePipe } from '@angular/common';
|
import { DatePipe } from '@angular/common';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -10,6 +11,8 @@ import { DatePipe } from '@angular/common';
|
|||||||
})
|
})
|
||||||
export class LogsComponent implements OnInit {
|
export class LogsComponent implements OnInit {
|
||||||
readonly #logger = inject(LoggerService);
|
readonly #logger = inject(LoggerService);
|
||||||
|
readonly #storage = inject(StorageService);
|
||||||
|
readonly #router = inject(Router);
|
||||||
|
|
||||||
get logs(): LogEntry[] {
|
get logs(): LogEntry[] {
|
||||||
return this.#logger.logs;
|
return this.#logger.logs;
|
||||||
@@ -40,4 +43,10 @@ export class LogsComponent implements OnInit {
|
|||||||
return 'log-info';
|
return 'log-info';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<div class="sam-text-header">
|
<div class="sam-text-header">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span> Settings </span>
|
<span> Settings </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -12,6 +15,9 @@
|
|||||||
Import Vault
|
Import Vault
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<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>
|
<div class="sam-flex-grow"></div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
row-gap: var(--size);
|
row-gap: var(--size);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-left: var(--size);
|
|
||||||
padding-right: var(--size);
|
> *:not(.sam-text-header) {
|
||||||
|
margin-left: var(--size);
|
||||||
|
margin-right: var(--size);
|
||||||
|
}
|
||||||
|
|
||||||
.file-input {
|
.file-input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Component, inject, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
import {
|
import {
|
||||||
BrowserSyncData,
|
BrowserSyncData,
|
||||||
BrowserSyncFlow,
|
BrowserSyncFlow,
|
||||||
@@ -6,6 +7,7 @@ import {
|
|||||||
DateHelper,
|
DateHelper,
|
||||||
LoggerService,
|
LoggerService,
|
||||||
NavComponent,
|
NavComponent,
|
||||||
|
NavItemComponent,
|
||||||
StartupService,
|
StartupService,
|
||||||
StorageService,
|
StorageService,
|
||||||
} from '@common';
|
} from '@common';
|
||||||
@@ -13,11 +15,12 @@ import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
imports: [ConfirmComponent],
|
imports: [ConfirmComponent, NavItemComponent],
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: './settings.component.html',
|
||||||
styleUrl: './settings.component.scss',
|
styleUrl: './settings.component.scss',
|
||||||
})
|
})
|
||||||
export class SettingsComponent extends NavComponent implements OnInit {
|
export class SettingsComponent extends NavComponent implements OnInit {
|
||||||
|
readonly #router = inject(Router);
|
||||||
syncFlow: string | undefined;
|
syncFlow: string | undefined;
|
||||||
|
|
||||||
readonly #storage = inject(StorageService);
|
readonly #storage = inject(StorageService);
|
||||||
@@ -101,4 +104,10 @@ export class SettingsComponent extends NavComponent implements OnInit {
|
|||||||
downloadAnchorNode.click();
|
downloadAnchorNode.click();
|
||||||
downloadAnchorNode.remove();
|
downloadAnchorNode.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
.sam-text-header {
|
.sam-text-header {
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
padding-top: var(--size);
|
height: 48px;
|
||||||
padding-bottom: var(--size);
|
min-height: 48px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-family: var(--font-heading);
|
font-family: var(--font-heading);
|
||||||
@@ -14,6 +15,28 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.1rem;
|
letter-spacing: 0.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lock-btn {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--background-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sam-footer-grid-2 {
|
.sam-footer-grid-2 {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Plebeian Signer",
|
"name": "Plebeian Signer",
|
||||||
"description": "Nostr Identity Manager & Signer",
|
"description": "Nostr Identity Manager & Signer",
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"homepage_url": "https://git.mleku.dev/mleku/plebeian-signer",
|
"homepage_url": "https://git.mleku.dev/mleku/plebeian-signer",
|
||||||
"options_page": "options.html",
|
"options_page": "options.html",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||||
<div class="bookmarks-header">
|
<div class="sam-text-header">
|
||||||
<span class="bookmarks-title">Bookmarks</span>
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
<button class="btn btn-primary btn-sm" (click)="onBookmarkThisPage()">
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
|
<span>Bookmarks</span>
|
||||||
|
<button class="action-btn btn btn-primary btn-sm" (click)="onBookmarkThisPage()">
|
||||||
<span class="emoji">🔖</span> Bookmark This Page
|
<span class="emoji">🔖</span> Bookmark This Page
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,21 +2,24 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: var(--size);
|
padding-top: var(--size);
|
||||||
|
padding-bottom: var(--size);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
.bookmarks-header {
|
> *:not(.sam-text-header) {
|
||||||
display: flex;
|
margin-left: var(--size);
|
||||||
justify-content: space-between;
|
margin-right: var(--size);
|
||||||
align-items: center;
|
}
|
||||||
|
|
||||||
|
.sam-text-header {
|
||||||
margin-bottom: var(--size);
|
margin-bottom: var(--size);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.bookmarks-title {
|
.action-btn {
|
||||||
font-weight: 600;
|
position: absolute;
|
||||||
font-size: 1.1rem;
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmarks-container {
|
.bookmarks-container {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Component, inject, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
import { Bookmark, LoggerService, SignerMetaData } from '@common';
|
import { Router } from '@angular/router';
|
||||||
|
import { Bookmark, LoggerService, SignerMetaData, StorageService } from '@common';
|
||||||
import { FirefoxMetaHandler } from '../../../common/data/firefox-meta-handler';
|
import { FirefoxMetaHandler } from '../../../common/data/firefox-meta-handler';
|
||||||
import browser from 'webextension-polyfill';
|
import browser from 'webextension-polyfill';
|
||||||
|
|
||||||
@@ -12,6 +13,8 @@ import browser from 'webextension-polyfill';
|
|||||||
export class BookmarksComponent implements OnInit {
|
export class BookmarksComponent implements OnInit {
|
||||||
readonly #logger = inject(LoggerService);
|
readonly #logger = inject(LoggerService);
|
||||||
readonly #metaHandler = new FirefoxMetaHandler();
|
readonly #metaHandler = new FirefoxMetaHandler();
|
||||||
|
readonly #storage = inject(StorageService);
|
||||||
|
readonly #router = inject(Router);
|
||||||
|
|
||||||
bookmarks: Bookmark[] = [];
|
bookmarks: Bookmark[] = [];
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
@@ -88,4 +91,10 @@ export class BookmarksComponent implements OnInit {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,16 +33,4 @@
|
|||||||
<a class="tab" routerLink="/home/bookmarks" routerLinkActive="active" title="Bookmarks">
|
<a class="tab" routerLink="/home/bookmarks" routerLinkActive="active" title="Bookmarks">
|
||||||
<span class="emoji">🔖</span>
|
<span class="emoji">🔖</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="tab" routerLink="/home/logs" routerLinkActive="active" title="Logs">
|
|
||||||
<span class="emoji">🪵</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a class="tab" routerLink="/home/info" routerLinkActive="active" title="Info">
|
|
||||||
<span class="emoji">💡</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<button class="tab" (click)="onClickLock()" title="Lock">
|
|
||||||
<span class="emoji">🔒</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Component, inject } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Router, RouterModule, RouterOutlet } from '@angular/router';
|
import { RouterModule, RouterOutlet } from '@angular/router';
|
||||||
import { LoggerService, StorageService } from '@common';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
@@ -8,14 +7,4 @@ import { LoggerService, StorageService } from '@common';
|
|||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
styleUrl: './home.component.scss',
|
styleUrl: './home.component.scss',
|
||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {}
|
||||||
readonly #storage = inject(StorageService);
|
|
||||||
readonly #router = inject(Router);
|
|
||||||
readonly #logger = inject(LoggerService);
|
|
||||||
|
|
||||||
async onClickLock() {
|
|
||||||
this.#logger.logVaultLock();
|
|
||||||
await this.#storage.lockVault();
|
|
||||||
this.#router.navigateByUrl('/vault-login');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||||
<div class="custom-header" style="position: sticky; top: 0">
|
<div class="custom-header" style="position: sticky; top: 0">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span class="text">Identities</span>
|
<span class="text">Identities</span>
|
||||||
|
|
||||||
<button class="button btn btn-primary btn-sm" (click)="onClickNewIdentity()">
|
<button class="button btn btn-primary btn-sm" (click)="onClickNewIdentity()">
|
||||||
|
|||||||
@@ -3,37 +3,55 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-left: var(--size);
|
|
||||||
padding-right: var(--size);
|
> *:not(.custom-header) {
|
||||||
|
margin-left: var(--size);
|
||||||
|
margin-right: var(--size);
|
||||||
|
}
|
||||||
|
|
||||||
.custom-header {
|
.custom-header {
|
||||||
padding-top: var(--size);
|
height: 48px;
|
||||||
padding-bottom: var(--size);
|
min-height: 48px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: auto;
|
grid-template-rows: auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.lock-btn {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--background-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
grid-column-start: 1;
|
position: absolute;
|
||||||
grid-column-end: 2;
|
right: 0;
|
||||||
grid-row-start: 1;
|
|
||||||
grid-row-end: 2;
|
|
||||||
justify-self: end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
grid-column-start: 1;
|
|
||||||
grid-column-end: 2;
|
|
||||||
grid-row-start: 1;
|
|
||||||
grid-row-end: 2;
|
|
||||||
font-family: var(--font-heading);
|
font-family: var(--font-heading);
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.1rem;
|
letter-spacing: 0.1rem;
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
height: 32px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Router } from '@angular/router';
|
|||||||
import {
|
import {
|
||||||
IconButtonComponent,
|
IconButtonComponent,
|
||||||
Identity_DECRYPTED,
|
Identity_DECRYPTED,
|
||||||
|
LoggerService,
|
||||||
NostrHelper,
|
NostrHelper,
|
||||||
ProfileMetadata,
|
ProfileMetadata,
|
||||||
ProfileMetadataService,
|
ProfileMetadataService,
|
||||||
@@ -20,6 +21,7 @@ export class IdentitiesComponent implements OnInit {
|
|||||||
readonly storage = inject(StorageService);
|
readonly storage = inject(StorageService);
|
||||||
readonly #router = inject(Router);
|
readonly #router = inject(Router);
|
||||||
readonly #profileMetadata = inject(ProfileMetadataService);
|
readonly #profileMetadata = inject(ProfileMetadataService);
|
||||||
|
readonly #logger = inject(LoggerService);
|
||||||
|
|
||||||
// Cache of pubkey -> profile for quick lookup
|
// Cache of pubkey -> profile for quick lookup
|
||||||
#profileCache = new Map<string, ProfileMetadata | null>();
|
#profileCache = new Map<string, ProfileMetadata | null>();
|
||||||
@@ -73,4 +75,10 @@ export class IdentitiesComponent implements OnInit {
|
|||||||
onClickWhitelistedApps() {
|
onClickWhitelistedApps() {
|
||||||
this.#router.navigateByUrl('/whitelisted-apps');
|
this.#router.navigateByUrl('/whitelisted-apps');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->
|
||||||
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->
|
||||||
<div class="sam-text-header">
|
<div class="sam-text-header">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span>You</span>
|
<span>You</span>
|
||||||
<button class="edit-btn" title="Edit profile" (click)="onClickEditProfile()">
|
<button class="edit-btn" title="Edit profile" (click)="onClickEditProfile()">
|
||||||
<img src="edit.svg" alt="Edit" class="edit-icon" />
|
<img src="edit.svg" alt="Edit" class="edit-icon" />
|
||||||
|
|||||||
@@ -4,14 +4,12 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.sam-text-header {
|
.sam-text-header {
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.edit-btn {
|
.edit-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: var(--size);
|
right: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 4px;
|
padding: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ export class IdentityComponent implements OnInit {
|
|||||||
this.#router.navigateByUrl('/profile-edit');
|
this.#router.navigateByUrl('/profile-edit');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
|
|
||||||
async #loadData() {
|
async #loadData() {
|
||||||
try {
|
try {
|
||||||
const selectedIdentityId =
|
const selectedIdentityId =
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<div class="sam-text-header">
|
<div class="sam-text-header">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span> Plebeian Signer </span>
|
<span> Plebeian Signer </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-left: var(--size);
|
|
||||||
padding-right: var(--size);
|
> *:not(.sam-text-header) {
|
||||||
|
margin-left: var(--size);
|
||||||
|
margin-right: var(--size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sam-text-header {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { LoggerService, StorageService } from '@common';
|
||||||
import packageJson from '../../../../../../../package.json';
|
import packageJson from '../../../../../../../package.json';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -7,5 +9,15 @@ import packageJson from '../../../../../../../package.json';
|
|||||||
styleUrl: './info.component.scss',
|
styleUrl: './info.component.scss',
|
||||||
})
|
})
|
||||||
export class InfoComponent {
|
export class InfoComponent {
|
||||||
|
readonly #logger = inject(LoggerService);
|
||||||
|
readonly #storage = inject(StorageService);
|
||||||
|
readonly #router = inject(Router);
|
||||||
|
|
||||||
version = packageJson.custom.firefox.version;
|
version = packageJson.custom.firefox.version;
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<div class="logs-header">
|
<div class="sam-text-header">
|
||||||
<span class="logs-title">Logs</span>
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
|
<span>Logs</span>
|
||||||
<div class="logs-actions">
|
<div class="logs-actions">
|
||||||
<button class="btn btn-sm btn-secondary" (click)="onRefresh()">Refresh</button>
|
<button class="btn btn-sm btn-secondary" (click)="onRefresh()">Refresh</button>
|
||||||
<button class="btn btn-sm btn-secondary" (click)="onClear()">Clear</button>
|
<button class="btn btn-sm btn-secondary" (click)="onClear()">Clear</button>
|
||||||
|
|||||||
@@ -2,26 +2,26 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: var(--size);
|
padding-top: var(--size);
|
||||||
|
padding-bottom: var(--size);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
.logs-header {
|
> *:not(.sam-text-header) {
|
||||||
display: flex;
|
margin-left: var(--size);
|
||||||
justify-content: space-between;
|
margin-right: var(--size);
|
||||||
align-items: center;
|
}
|
||||||
|
|
||||||
|
.sam-text-header {
|
||||||
margin-bottom: var(--size);
|
margin-bottom: var(--size);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.logs-actions {
|
.logs-actions {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.logs-title {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logs-container {
|
.logs-container {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Component, inject, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
import { LoggerService, LogEntry } from '@common';
|
import { Router } from '@angular/router';
|
||||||
|
import { LoggerService, LogEntry, StorageService } from '@common';
|
||||||
import { DatePipe } from '@angular/common';
|
import { DatePipe } from '@angular/common';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -10,6 +11,8 @@ import { DatePipe } from '@angular/common';
|
|||||||
})
|
})
|
||||||
export class LogsComponent implements OnInit {
|
export class LogsComponent implements OnInit {
|
||||||
readonly #logger = inject(LoggerService);
|
readonly #logger = inject(LoggerService);
|
||||||
|
readonly #storage = inject(StorageService);
|
||||||
|
readonly #router = inject(Router);
|
||||||
|
|
||||||
get logs(): LogEntry[] {
|
get logs(): LogEntry[] {
|
||||||
return this.#logger.logs;
|
return this.#logger.logs;
|
||||||
@@ -40,4 +43,10 @@ export class LogsComponent implements OnInit {
|
|||||||
return 'log-info';
|
return 'log-info';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<div class="sam-text-header">
|
<div class="sam-text-header">
|
||||||
|
<button class="lock-btn" title="Lock" (click)="onClickLock()">
|
||||||
|
<span class="emoji">🔒</span>
|
||||||
|
</button>
|
||||||
<span> Settings </span>
|
<span> Settings </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -12,6 +15,9 @@
|
|||||||
Import Vault
|
Import Vault
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<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>
|
<div class="sam-flex-grow"></div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
row-gap: var(--size);
|
row-gap: var(--size);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-left: var(--size);
|
|
||||||
padding-right: var(--size);
|
> *:not(.sam-text-header) {
|
||||||
|
margin-left: var(--size);
|
||||||
|
margin-right: var(--size);
|
||||||
|
}
|
||||||
|
|
||||||
.file-input {
|
.file-input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { Component, inject, OnInit } from '@angular/core';
|
import { Component, inject, OnInit } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
import {
|
import {
|
||||||
BrowserSyncFlow,
|
BrowserSyncFlow,
|
||||||
ConfirmComponent,
|
ConfirmComponent,
|
||||||
DateHelper,
|
DateHelper,
|
||||||
LoggerService,
|
LoggerService,
|
||||||
NavComponent,
|
NavComponent,
|
||||||
|
NavItemComponent,
|
||||||
StartupService,
|
StartupService,
|
||||||
StorageService,
|
StorageService,
|
||||||
} from '@common';
|
} from '@common';
|
||||||
@@ -12,11 +14,12 @@ import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
imports: [ConfirmComponent],
|
imports: [ConfirmComponent, NavItemComponent],
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: './settings.component.html',
|
||||||
styleUrl: './settings.component.scss',
|
styleUrl: './settings.component.scss',
|
||||||
})
|
})
|
||||||
export class SettingsComponent extends NavComponent implements OnInit {
|
export class SettingsComponent extends NavComponent implements OnInit {
|
||||||
|
readonly #router = inject(Router);
|
||||||
syncFlow: string | undefined;
|
syncFlow: string | undefined;
|
||||||
|
|
||||||
readonly #storage = inject(StorageService);
|
readonly #storage = inject(StorageService);
|
||||||
@@ -74,4 +77,10 @@ export class SettingsComponent extends NavComponent implements OnInit {
|
|||||||
downloadAnchorNode.click();
|
downloadAnchorNode.click();
|
||||||
downloadAnchorNode.remove();
|
downloadAnchorNode.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickLock() {
|
||||||
|
this.#logger.logVaultLock();
|
||||||
|
await this.#storage.lockVault();
|
||||||
|
this.#router.navigateByUrl('/vault-login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user