✨ feat: replace seed phrase input with animated spinner
This commit is contained in:
parent
740921132a
commit
0bde5a4ef3
2 changed files with 163 additions and 16 deletions
|
@ -20,6 +20,7 @@ import '@components/LoadingView';
|
|||
import '@components/ProgressSteps';
|
||||
import '@components/RelayLogs';
|
||||
import '@components/Setup/CCNList';
|
||||
import '@components/Setup/SeedPhraseSpinner';
|
||||
import { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKRelay, NDKRelaySet } from '@nostr-dev-kit/ndk';
|
||||
import { nip19 } from '@nostr/tools';
|
||||
|
||||
|
@ -300,7 +301,7 @@ export class InitialSetup extends LitElement {
|
|||
<main ${animate()}>
|
||||
<section>
|
||||
<h1>Welcome to Eve</h1>
|
||||
<h2>Your Private Community Network</h2>
|
||||
<h2>Your Closed Community Network</h2>
|
||||
<p>
|
||||
Connect, share, and engage with your community in a secure,
|
||||
members-only space designed just for you.
|
||||
|
@ -539,21 +540,7 @@ export class InitialSetup extends LitElement {
|
|||
Security) to enable simpler invitation-based community access, as
|
||||
well as improve your community's security.
|
||||
</p>
|
||||
<div class="input-group">
|
||||
<arx-input
|
||||
@change=${this.onSeedPhraseInput}
|
||||
.value=${this.seedPhrase}
|
||||
id="seed-input"
|
||||
type="text"
|
||||
placeholder="Enter seed phrase..."
|
||||
></arx-input>
|
||||
<arx-button
|
||||
@click=${() => this.generateSeedPhrase()}
|
||||
label="Generate"
|
||||
variant="secondary"
|
||||
>
|
||||
</arx-button>
|
||||
</div>
|
||||
<arx-seed-phrase-spinner @change=${this.onSeedPhraseInput}></arx-seed-phrase-spinner>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Community Name</h3>
|
||||
|
|
160
src/components/Setup/SeedPhraseSpinner.ts
Normal file
160
src/components/Setup/SeedPhraseSpinner.ts
Normal file
|
@ -0,0 +1,160 @@
|
|||
import { ArxInputChangeEvent } from '@/components/General/Input';
|
||||
import * as nip06 from '@nostr/tools/nip06';
|
||||
import { wordlist } from '@scure/bip39/wordlists/english';
|
||||
import { LitElement, css, html } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { map } from 'lit/directives/map.js';
|
||||
import { when } from 'lit/directives/when.js';
|
||||
|
||||
import '@components/General/Button';
|
||||
|
||||
@customElement('arx-seed-phrase-spinner')
|
||||
export class SeedPhraseSpinner extends LitElement {
|
||||
@state()
|
||||
private words: (string | null)[] = [null, null, null, null, null, null, null, null, null, null, null, null];
|
||||
|
||||
@state()
|
||||
private animating = false;
|
||||
|
||||
@state()
|
||||
private tempWords: (string | null)[] = [null, null, null, null, null, null, null, null, null, null, null, null];
|
||||
|
||||
private getRandomWord() {
|
||||
return wordlist[Math.floor(Math.random() * wordlist.length)];
|
||||
}
|
||||
|
||||
static override styles = css`
|
||||
.words-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 0.8rem;
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.word {
|
||||
width: 100%;
|
||||
height: 3.5rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
border-radius: 0.5rem;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.word::before, .word::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 0.5rem;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.word::before {
|
||||
top: 0;
|
||||
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.7), transparent);
|
||||
}
|
||||
|
||||
.word::after {
|
||||
bottom: 0;
|
||||
background: linear-gradient(to top, rgba(255, 255, 255, 0.7), transparent);
|
||||
}
|
||||
|
||||
.word-inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.word-item {
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 0 0.25rem;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: translateY(0); }
|
||||
100% { transform: translateY(-3.5rem); }
|
||||
}
|
||||
|
||||
.spinning .word-inner {
|
||||
animation: spin var(--animation-duration) var(--animation-curve) infinite;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
opacity: 0.5;
|
||||
}
|
||||
`;
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<div class="words-list ${this.animating ? 'spinning' : ''}">
|
||||
${map(
|
||||
this.tempWords,
|
||||
(word) =>
|
||||
html`
|
||||
<div class="word">
|
||||
<div class="word-inner">
|
||||
${when(
|
||||
this.animating,
|
||||
() => html`
|
||||
<div class="word-item placeholder">${word}</div>
|
||||
<div class="word-item placeholder">${word}</div>
|
||||
`,
|
||||
() =>
|
||||
html`
|
||||
<div class="word-item ${!word ? 'placeholder' : ''}">${word || 'tap generate'}</div>
|
||||
`,
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
)}
|
||||
</div>
|
||||
<div class="controls">
|
||||
<arx-button
|
||||
variant="primary"
|
||||
label="Generate Seed Phrase"
|
||||
?disabled=${this.animating}
|
||||
?loading=${this.animating}
|
||||
@click=${this.generateSeedPhrase}
|
||||
></arx-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private generateSeedPhrase() {
|
||||
if (this.animating) return;
|
||||
|
||||
this.animating = true;
|
||||
|
||||
const intervalId = window.setInterval(() => {
|
||||
this.tempWords = this.tempWords.map(() => this.getRandomWord());
|
||||
}, 50);
|
||||
|
||||
setTimeout(() => {
|
||||
const newWords = nip06.generateSeedWords().split(' ');
|
||||
clearInterval(intervalId);
|
||||
this.tempWords = newWords;
|
||||
this.words = newWords;
|
||||
this.animating = false;
|
||||
this.dispatchEvent(new ArxInputChangeEvent(this.words.join(' ')));
|
||||
}, 1500);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue