Release v1.1.4 - Improve ncryptsec export page UX

- Auto-focus password input when page loads
- Move QR code above password input form (displays after generation)
- Move explanation text below the form
- Replace ncryptsec text output with clickable QR code button
- Add hover/active effects and "Copy to clipboard" tooltip to QR code
- Remove redundant copy button and text display

Files modified:
- package.json (version bump)
- projects/chrome/public/manifest.json
- projects/chrome/src/app/components/edit-identity/ncryptsec/*
- projects/firefox/public/manifest.json
- projects/firefox/src/app/components/edit-identity/ncryptsec/*

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 10:04:07 +02:00
parent 2074c409f0
commit a2e47d8612
13 changed files with 117 additions and 153 deletions

View File

@@ -1,12 +1,12 @@
{
"name": "plebeian-signer",
"version": "v1.1.3",
"version": "v1.1.4",
"custom": {
"chrome": {
"version": "v1.1.3"
"version": "v1.1.4"
},
"firefox": {
"version": "v1.1.3"
"version": "v1.1.4"
}
},
"scripts": {

View File

@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Plebeian Signer - Nostr Identity Manager & Signer",
"description": "Manage and switch between multiple identities while interacting with Nostr apps",
"version": "1.1.3",
"version": "1.1.4",
"homepage_url": "https://github.com/PlebeianApp/plebeian-signer",
"options_page": "options.html",
"permissions": [

View File

@@ -6,16 +6,26 @@
<span>Get ncryptsec</span>
</div>
<p class="description">
Enter a password to encrypt your private key. The resulting ncryptsec can be
used to securely backup or transfer your key.
</p>
<!-- QR Code (shown after generation) -->
@if (ncryptsec) {
<div class="qr-container">
<button
type="button"
class="qr-button"
title="Copy to clipboard"
(click)="copyToClipboard(ncryptsec); toast.show('Copied to clipboard')"
>
<img [src]="ncryptsecQr" alt="ncryptsec QR code" class="qr-code" />
</button>
</div>
}
<!-- PASSWORD INPUT -->
<div class="password-section">
<label for="ncryptsecPasswordInput">Password</label>
<div class="input-group sam-mt-h">
<input
#passwordInput
id="ncryptsecPasswordInput"
type="password"
class="form-control"
@@ -41,35 +51,10 @@
}
</button>
<!-- NCRYPTSEC OUTPUT -->
@if (ncryptsec) {
<div class="result-section">
<!-- QR Code -->
<div class="qr-container">
<img [src]="ncryptsecQr" alt="ncryptsec QR code" class="qr-code" />
</div>
<!-- ncryptsec text -->
<div class="ncryptsec-container">
<input
type="text"
class="form-control ncryptsec-output"
[value]="ncryptsec"
readonly
(click)="copyToClipboard(ncryptsec); toast.show('Copied to clipboard')"
title="Click to copy"
/>
<button
class="btn btn-outline-secondary"
type="button"
(click)="copyToClipboard(ncryptsec); toast.show('Copied to clipboard')"
>
<i class="bi bi-copy"></i> Copy
</button>
</div>
<p class="hint">Tap the text or button to copy to clipboard</p>
</div>
}
<p class="description">
Enter a password to encrypt your private key. The resulting ncryptsec can be
used to securely backup or transfer your key.
</p>
<lib-toast #toast [bottom]="16"></lib-toast>

View File

@@ -38,52 +38,33 @@
margin-bottom: var(--size);
}
.result-section {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--size);
margin-top: var(--size);
}
.qr-container {
background: white;
padding: var(--size);
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: var(--size);
}
.qr-button {
background: white;
padding: var(--size);
border-radius: 8px;
border: none;
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.15s ease;
&:hover {
transform: scale(1.02);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
&:active {
transform: scale(0.98);
}
}
.qr-code {
width: 250px;
height: 250px;
}
.ncryptsec-container {
width: 100%;
display: flex;
flex-direction: column;
gap: var(--size-h);
.ncryptsec-output {
font-family: monospace;
font-size: 0.75rem;
word-break: break-all;
cursor: pointer;
&:hover {
background-color: var(--bs-gray-100);
}
}
button {
width: 100%;
}
}
.hint {
color: var(--text-muted);
font-size: 0.8rem;
text-align: center;
display: block;
}

View File

@@ -1,4 +1,11 @@
import { Component, inject, OnInit } from '@angular/core';
import {
AfterViewInit,
Component,
ElementRef,
inject,
OnInit,
ViewChild,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import {
IconButtonComponent,
@@ -16,7 +23,12 @@ import * as QRCode from 'qrcode';
templateUrl: './ncryptsec.component.html',
styleUrl: './ncryptsec.component.scss',
})
export class NcryptsecComponent extends NavComponent implements OnInit {
export class NcryptsecComponent
extends NavComponent
implements OnInit, AfterViewInit
{
@ViewChild('passwordInput') passwordInput!: ElementRef<HTMLInputElement>;
privkeyHex = '';
ncryptsecPassword = '';
ncryptsec = '';
@@ -35,6 +47,10 @@ export class NcryptsecComponent extends NavComponent implements OnInit {
this.#initialize(identityId);
}
ngAfterViewInit(): void {
this.passwordInput.nativeElement.focus();
}
async generateNcryptsec() {
if (!this.privkeyHex || !this.ncryptsecPassword) {
return;

View File

@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Plebeian Signer",
"description": "Nostr Identity Manager & Signer",
"version": "1.1.3",
"version": "1.1.4",
"homepage_url": "https://github.com/PlebeianApp/plebeian-signer",
"options_page": "options.html",
"permissions": [

View File

@@ -6,16 +6,26 @@
<span>Get ncryptsec</span>
</div>
<p class="description">
Enter a password to encrypt your private key. The resulting ncryptsec can be
used to securely backup or transfer your key.
</p>
<!-- QR Code (shown after generation) -->
@if (ncryptsec) {
<div class="qr-container">
<button
type="button"
class="qr-button"
title="Copy to clipboard"
(click)="copyToClipboard(ncryptsec); toast.show('Copied to clipboard')"
>
<img [src]="ncryptsecQr" alt="ncryptsec QR code" class="qr-code" />
</button>
</div>
}
<!-- PASSWORD INPUT -->
<div class="password-section">
<label for="ncryptsecPasswordInput">Password</label>
<div class="input-group sam-mt-h">
<input
#passwordInput
id="ncryptsecPasswordInput"
type="password"
class="form-control"
@@ -41,35 +51,10 @@
}
</button>
<!-- NCRYPTSEC OUTPUT -->
@if (ncryptsec) {
<div class="result-section">
<!-- QR Code -->
<div class="qr-container">
<img [src]="ncryptsecQr" alt="ncryptsec QR code" class="qr-code" />
</div>
<!-- ncryptsec text -->
<div class="ncryptsec-container">
<input
type="text"
class="form-control ncryptsec-output"
[value]="ncryptsec"
readonly
(click)="copyToClipboard(ncryptsec); toast.show('Copied to clipboard')"
title="Click to copy"
/>
<button
class="btn btn-outline-secondary"
type="button"
(click)="copyToClipboard(ncryptsec); toast.show('Copied to clipboard')"
>
<i class="bi bi-copy"></i> Copy
</button>
</div>
<p class="hint">Tap the text or button to copy to clipboard</p>
</div>
}
<p class="description">
Enter a password to encrypt your private key. The resulting ncryptsec can be
used to securely backup or transfer your key.
</p>
<lib-toast #toast [bottom]="16"></lib-toast>

View File

@@ -38,52 +38,33 @@
margin-bottom: var(--size);
}
.result-section {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--size);
margin-top: var(--size);
}
.qr-container {
background: white;
padding: var(--size);
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: var(--size);
}
.qr-button {
background: white;
padding: var(--size);
border-radius: 8px;
border: none;
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.15s ease;
&:hover {
transform: scale(1.02);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
&:active {
transform: scale(0.98);
}
}
.qr-code {
width: 250px;
height: 250px;
}
.ncryptsec-container {
width: 100%;
display: flex;
flex-direction: column;
gap: var(--size-h);
.ncryptsec-output {
font-family: monospace;
font-size: 0.75rem;
word-break: break-all;
cursor: pointer;
&:hover {
background-color: var(--bs-gray-100);
}
}
button {
width: 100%;
}
}
.hint {
color: var(--text-muted);
font-size: 0.8rem;
text-align: center;
display: block;
}

View File

@@ -1,4 +1,11 @@
import { Component, inject, OnInit } from '@angular/core';
import {
AfterViewInit,
Component,
ElementRef,
inject,
OnInit,
ViewChild,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import {
IconButtonComponent,
@@ -16,7 +23,12 @@ import * as QRCode from 'qrcode';
templateUrl: './ncryptsec.component.html',
styleUrl: './ncryptsec.component.scss',
})
export class NcryptsecComponent extends NavComponent implements OnInit {
export class NcryptsecComponent
extends NavComponent
implements OnInit, AfterViewInit
{
@ViewChild('passwordInput') passwordInput!: ElementRef<HTMLInputElement>;
privkeyHex = '';
ncryptsecPassword = '';
ncryptsec = '';
@@ -35,6 +47,10 @@ export class NcryptsecComponent extends NavComponent implements OnInit {
this.#initialize(identityId);
}
ngAfterViewInit(): void {
this.passwordInput.nativeElement.focus();
}
async generateNcryptsec() {
if (!this.privkeyHex || !this.ncryptsecPassword) {
return;

Binary file not shown.

Binary file not shown.