window.nostr.js 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc.yaml +1 -1
- package/README.md +15 -0
- package/dist/index.html +1 -1
- package/dist/window.nostr.js +13 -5
- package/package.json +1 -1
- package/src/App.svelte +178 -80
- package/src/Spinner.svelte +3 -3
- package/src/app.css +1 -0
- package/tailwind.config.js +10 -1
package/package.json
CHANGED
package/src/App.svelte
CHANGED
|
@@ -25,14 +25,23 @@
|
|
|
25
25
|
import Spinner from './Spinner.svelte'
|
|
26
26
|
|
|
27
27
|
const mobileMode = mediaQueryStore('only screen and (max-width: 640px)')
|
|
28
|
+
const localStorageKeys = {
|
|
29
|
+
ORIGIN: 'wnj:origin',
|
|
30
|
+
CLIENT_SECRET: 'wnj:clientSecret',
|
|
31
|
+
Y_POS: 'wnj:ypos',
|
|
32
|
+
CALLBACK_TOKEN: 'wnj:callbackToken',
|
|
33
|
+
BUNKER_POINTER: 'wnj:bunkerPointer'
|
|
34
|
+
}
|
|
28
35
|
|
|
29
36
|
let myself: HTMLDivElement
|
|
30
37
|
export let accent: string
|
|
31
38
|
export let position: 'top' | 'bottom' = 'top'
|
|
32
39
|
$: origin = $mobileMode
|
|
33
40
|
? 'bottom'
|
|
34
|
-
: (localStorage.getItem(
|
|
35
|
-
|
|
41
|
+
: (localStorage.getItem(localStorageKeys.ORIGIN) as
|
|
42
|
+
| 'top'
|
|
43
|
+
| 'bottom'
|
|
44
|
+
| null) || position
|
|
36
45
|
|
|
37
46
|
const win = window as any
|
|
38
47
|
const pool = new SimplePool()
|
|
@@ -42,12 +51,15 @@
|
|
|
42
51
|
let nameInputValue: string
|
|
43
52
|
let chosenProvider: BunkerProfile | undefined
|
|
44
53
|
let clientSecret: Uint8Array
|
|
45
|
-
const local = localStorage.getItem(
|
|
54
|
+
const local = localStorage.getItem(localStorageKeys.CLIENT_SECRET)
|
|
46
55
|
if (local) {
|
|
47
56
|
clientSecret = hexToBytes(local)
|
|
48
57
|
} else {
|
|
49
58
|
clientSecret = generateSecretKey()
|
|
50
|
-
localStorage.setItem(
|
|
59
|
+
localStorage.setItem(
|
|
60
|
+
localStorageKeys.CLIENT_SECRET,
|
|
61
|
+
bytesToHex(clientSecret)
|
|
62
|
+
)
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
let state: 'opened' | 'closed' | 'justopened' | 'justclosed' = 'closed'
|
|
@@ -57,9 +69,13 @@
|
|
|
57
69
|
let bunker: Promise<BunkerSigner>
|
|
58
70
|
let connecting: boolean
|
|
59
71
|
let connected: boolean
|
|
72
|
+
let showAuth: string | null = null
|
|
73
|
+
let showLogin: string | null = null
|
|
60
74
|
let takingTooLong = false
|
|
61
75
|
let creating: boolean
|
|
76
|
+
let awaitingCreation: boolean
|
|
62
77
|
let errorMessage: string
|
|
78
|
+
let showInfo = false
|
|
63
79
|
let identity: null | {
|
|
64
80
|
pubkey: string
|
|
65
81
|
npub: string
|
|
@@ -78,7 +94,7 @@
|
|
|
78
94
|
export let right = 20
|
|
79
95
|
$: ypos = $mobileMode
|
|
80
96
|
? BASE_YPOS
|
|
81
|
-
: parseInt(localStorage.getItem(
|
|
97
|
+
: parseInt(localStorage.getItem(localStorageKeys.Y_POS) || '0') || BASE_YPOS
|
|
82
98
|
let dragStarted = false
|
|
83
99
|
let hasMoved = false
|
|
84
100
|
let insidePosition: number
|
|
@@ -88,10 +104,10 @@
|
|
|
88
104
|
$: opened = state === 'justopened' || state === 'opened'
|
|
89
105
|
|
|
90
106
|
$: movingStyle = hasMoved
|
|
91
|
-
? '
|
|
107
|
+
? 'cursor-grabbing outline-dashed outline-' +
|
|
92
108
|
accent +
|
|
93
|
-
'-500
|
|
94
|
-
: '
|
|
109
|
+
'-500 outline-1 outline-offset-4'
|
|
110
|
+
: 'outline-none'
|
|
95
111
|
|
|
96
112
|
$: bunkerInputValueIsGood =
|
|
97
113
|
bunkerInputValue &&
|
|
@@ -101,10 +117,18 @@
|
|
|
101
117
|
const bunkerSignerParams: BunkerSignerParams = {
|
|
102
118
|
pool,
|
|
103
119
|
onauth(url: string) {
|
|
104
|
-
|
|
120
|
+
if (creating) {
|
|
121
|
+
showAuth = url
|
|
122
|
+
} else {
|
|
123
|
+
showLogin = url
|
|
124
|
+
}
|
|
105
125
|
}
|
|
106
126
|
}
|
|
107
127
|
|
|
128
|
+
function openAuthURLPopup(url: string | null): Window | null {
|
|
129
|
+
return window.open(url!, 'window.nostr', `width=600,height=800,popup=yes`)
|
|
130
|
+
}
|
|
131
|
+
|
|
108
132
|
const delayedUpdateState = debounce(() => {
|
|
109
133
|
switch (state) {
|
|
110
134
|
case 'justopened':
|
|
@@ -182,13 +206,14 @@
|
|
|
182
206
|
}
|
|
183
207
|
|
|
184
208
|
onMount(() => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
209
|
+
if (!bunkerPointer) {
|
|
210
|
+
let data = localStorage.getItem(localStorageKeys.BUNKER_POINTER)
|
|
211
|
+
if (data) {
|
|
212
|
+
bunkerPointer = JSON.parse(data)
|
|
213
|
+
// we have a pointer, which means we can get the public key right away
|
|
214
|
+
// but we will only try to connect when any other method is called on window.nostr
|
|
215
|
+
identify()
|
|
216
|
+
}
|
|
192
217
|
}
|
|
193
218
|
|
|
194
219
|
if (win.nostr && !win.nostr.isWnj) {
|
|
@@ -234,6 +259,18 @@
|
|
|
234
259
|
function handleCloseModal(ev: MouseEvent) {
|
|
235
260
|
close()
|
|
236
261
|
creating = false
|
|
262
|
+
showAuth = null
|
|
263
|
+
showLogin = null
|
|
264
|
+
ev.stopPropagation()
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function handleShowInfo(ev: MouseEvent) {
|
|
268
|
+
showInfo = true
|
|
269
|
+
ev.stopPropagation()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function handleCloseInfo(ev: MouseEvent) {
|
|
273
|
+
showInfo = false
|
|
237
274
|
ev.stopPropagation()
|
|
238
275
|
}
|
|
239
276
|
|
|
@@ -269,7 +306,7 @@
|
|
|
269
306
|
|
|
270
307
|
async function handleDisconnect(ev: MouseEvent) {
|
|
271
308
|
ev.preventDefault()
|
|
272
|
-
localStorage.removeItem(
|
|
309
|
+
localStorage.removeItem(localStorageKeys.BUNKER_POINTER)
|
|
273
310
|
reset()
|
|
274
311
|
}
|
|
275
312
|
|
|
@@ -294,12 +331,14 @@
|
|
|
294
331
|
ev.preventDefault()
|
|
295
332
|
if (!chosenProvider) return
|
|
296
333
|
|
|
334
|
+
awaitingCreation = true
|
|
297
335
|
let bunker = await createAccount(
|
|
298
336
|
chosenProvider,
|
|
299
337
|
bunkerSignerParams,
|
|
300
338
|
nameInput.value,
|
|
301
339
|
chosenProvider.domain
|
|
302
340
|
)
|
|
341
|
+
awaitingCreation = false
|
|
303
342
|
|
|
304
343
|
open()
|
|
305
344
|
creating = false
|
|
@@ -338,7 +377,10 @@
|
|
|
338
377
|
try {
|
|
339
378
|
await b.connect()
|
|
340
379
|
connected = true
|
|
341
|
-
localStorage.setItem(
|
|
380
|
+
localStorage.setItem(
|
|
381
|
+
localStorageKeys.BUNKER_POINTER,
|
|
382
|
+
JSON.stringify(bunkerPointer)
|
|
383
|
+
)
|
|
342
384
|
close()
|
|
343
385
|
resolveBunker(b)
|
|
344
386
|
} catch (err: any) {
|
|
@@ -348,11 +390,13 @@
|
|
|
348
390
|
clearTimeout(connectionTimeout)
|
|
349
391
|
connecting = false
|
|
350
392
|
takingTooLong = false
|
|
393
|
+
showAuth = null
|
|
394
|
+
showLogin = null
|
|
351
395
|
}
|
|
352
396
|
}
|
|
353
397
|
|
|
354
|
-
function identify() {
|
|
355
|
-
let pubkey = bunkerPointer
|
|
398
|
+
function identify(onFirstMetadata: (() => void) | null = null) {
|
|
399
|
+
let pubkey = bunkerPointer!.pubkey
|
|
356
400
|
|
|
357
401
|
identity = {
|
|
358
402
|
pubkey: pubkey,
|
|
@@ -375,6 +419,8 @@
|
|
|
375
419
|
identity!.event = evt
|
|
376
420
|
identity!.name = name
|
|
377
421
|
identity!.picture = picture
|
|
422
|
+
onFirstMetadata?.()
|
|
423
|
+
onFirstMetadata = null
|
|
378
424
|
} catch (err) {
|
|
379
425
|
/***/
|
|
380
426
|
}
|
|
@@ -436,8 +482,8 @@
|
|
|
436
482
|
ypos = BASE_YPOS
|
|
437
483
|
}
|
|
438
484
|
|
|
439
|
-
localStorage.setItem(
|
|
440
|
-
localStorage.setItem(
|
|
485
|
+
localStorage.setItem(localStorageKeys.ORIGIN, origin)
|
|
486
|
+
localStorage.setItem(localStorageKeys.Y_POS, ypos.toString())
|
|
441
487
|
}
|
|
442
488
|
}
|
|
443
489
|
</script>
|
|
@@ -450,8 +496,8 @@
|
|
|
450
496
|
|
|
451
497
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
452
498
|
<div
|
|
453
|
-
class="
|
|
454
|
-
class:
|
|
499
|
+
class="draggable animate-fadein font-sans text-white"
|
|
500
|
+
class:cursor-pointer={!identity && !opened}
|
|
455
501
|
style="position: fixed; {opened && $mobileMode
|
|
456
502
|
? 'width: 100%;'
|
|
457
503
|
: ''}; right: {opened && $mobileMode
|
|
@@ -465,23 +511,23 @@
|
|
|
465
511
|
<!-- Close status ################### -->
|
|
466
512
|
{#if !opened}
|
|
467
513
|
<div
|
|
468
|
-
class="
|
|
514
|
+
class="rounded px-4 py-2 shadow-[0_0px_10px_0px_rgba(0,0,0,0.3)] transition-all duration-200 bg-{accent}-700 hover:bg-{accent}-800 {movingStyle}"
|
|
469
515
|
>
|
|
470
516
|
<!-- Connecting view ################### -->
|
|
471
517
|
{#if connecting}
|
|
472
|
-
<div class="
|
|
518
|
+
<div class="flex items-center">
|
|
473
519
|
Connecting to bunker
|
|
474
520
|
<Spinner />
|
|
475
521
|
</div>
|
|
476
522
|
{:else if !identity}
|
|
477
523
|
Connect with Nostr
|
|
478
524
|
{:else}
|
|
479
|
-
<div class="
|
|
525
|
+
<div class="flex items-center">
|
|
480
526
|
{#if identity.picture}
|
|
481
527
|
<img
|
|
482
528
|
src={identity.picture}
|
|
483
529
|
alt=""
|
|
484
|
-
class="
|
|
530
|
+
class="mr-2 h-5 w-5 rounded-full"
|
|
485
531
|
/>
|
|
486
532
|
{:else}
|
|
487
533
|
☉
|
|
@@ -495,84 +541,148 @@
|
|
|
495
541
|
<!-- Open status ################### -->
|
|
496
542
|
{:else}
|
|
497
543
|
<div
|
|
498
|
-
class="
|
|
544
|
+
class="animate-show rounded-md bg-gradient-to-b px-8 py-8 shadow-[0_0px_30px_0px_rgba(0,0,0,0.6)] transition-all sm:w-96 from-{accent}-900 to-{accent}-700 {movingStyle}"
|
|
499
545
|
>
|
|
500
546
|
<button
|
|
501
|
-
on:click={handleCloseModal}
|
|
502
|
-
class="
|
|
547
|
+
on:click={showInfo ? handleCloseInfo : handleCloseModal}
|
|
548
|
+
class="absolute right-2 top-0 cursor-pointer bg-transparent text-3xl text-{accent}-600"
|
|
503
549
|
>⤫</button
|
|
504
550
|
>
|
|
505
|
-
|
|
506
|
-
{#if
|
|
507
|
-
<
|
|
508
|
-
|
|
509
|
-
|
|
551
|
+
|
|
552
|
+
{#if !showInfo && !showAuth && !showLogin}
|
|
553
|
+
<button
|
|
554
|
+
on:click={handleShowInfo}
|
|
555
|
+
class="absolute bottom-1 right-3 cursor-pointer bg-transparent text-xl text-{accent}-600"
|
|
556
|
+
>?</button
|
|
557
|
+
>
|
|
558
|
+
{/if}
|
|
559
|
+
|
|
560
|
+
{#if showAuth}
|
|
561
|
+
<div class="m-auto w-full">
|
|
562
|
+
<div class="text-center text-lg">Create a Nostr account</div>
|
|
563
|
+
<div class="mt-4 text-center text-sm leading-4">
|
|
564
|
+
Now you a new window will bring you to <strong>{new URL(showAuth).host}</strong> where the account creation will take place. If nothing happens check that if your browser is blocking popups, pleaase.<br/>
|
|
565
|
+
After that you will be returned to this page.
|
|
566
|
+
</div>
|
|
567
|
+
<button
|
|
568
|
+
class="mt-4 block w-full cursor-pointer rounded border-0 px-2 py-1 text-lg text-white disabled:cursor-default disabled:bg-neutral-400 disabled:text-neutral-200 bg-{accent}-900 hover:bg-{accent}-950"
|
|
569
|
+
on:click={() => openAuthURLPopup(showAuth)}>
|
|
570
|
+
Start account creation »
|
|
571
|
+
</button>
|
|
572
|
+
</div>
|
|
573
|
+
|
|
574
|
+
{:else if showLogin}
|
|
575
|
+
<div class="m-auto w-full">
|
|
576
|
+
<div class="text-center text-lg">Login into a Nostr account</div>
|
|
577
|
+
<div class="mt-4 text-center text-sm leading-4">
|
|
578
|
+
Now you a new window will bring you to <strong>{new URL(showLogin).host}</strong> where you can login and approve the permissions. If nothing happens check that if your browser is blocking popups, pleaase.<br/>
|
|
579
|
+
After that you will be returned to this page.
|
|
580
|
+
</div>
|
|
581
|
+
<button
|
|
582
|
+
class="mt-4 block w-full cursor-pointer rounded border-0 px-2 py-1 text-lg text-white disabled:cursor-default disabled:bg-neutral-400 disabled:text-neutral-200 bg-{accent}-900 hover:bg-{accent}-950"
|
|
583
|
+
on:click={() => openAuthURLPopup(showLogin)}>
|
|
584
|
+
Login now »
|
|
585
|
+
</button>
|
|
586
|
+
</div>
|
|
587
|
+
|
|
588
|
+
<!-- Show info ################### -->
|
|
589
|
+
{:else if showInfo}
|
|
590
|
+
<div class="text-center text-lg">What is that?</div>
|
|
591
|
+
<div class="text-base leading-5">
|
|
592
|
+
<p class="mb mt-4">
|
|
593
|
+
This widget is created with <i>window.nostr.js</i>, a small script
|
|
594
|
+
you can drop in any page that already uses NIP-07 and make it also
|
|
595
|
+
work with NIP-46 automatically when the user doesn't have an
|
|
596
|
+
extension installed.
|
|
597
|
+
<br />
|
|
598
|
+
It adds a small floating button on the side of the window that users
|
|
599
|
+
can use to create Nostr accuonts or connect to their NIP-46 bunkers.
|
|
600
|
+
</p>
|
|
601
|
+
<p class="mt-4">
|
|
602
|
+
This tool is opensource, get the code from the <a
|
|
603
|
+
target="_blank"
|
|
604
|
+
class="underline"
|
|
605
|
+
href="https://github.com/fiatjaf/window.nostr.js"
|
|
606
|
+
>project's page</a
|
|
607
|
+
>.
|
|
608
|
+
</p>
|
|
609
|
+
<p class="mt-4">
|
|
610
|
+
You don't know what Nostr is?
|
|
611
|
+
<a target="_blank" class="underline" href="https://www.nostr.com"
|
|
612
|
+
>Learn more</a
|
|
613
|
+
>.
|
|
614
|
+
</p>
|
|
615
|
+
</div>
|
|
616
|
+
|
|
617
|
+
<!-- Create account view ################### -->
|
|
618
|
+
{:else if creating}
|
|
619
|
+
<div class="text-center text-lg">Create a Nostr account</div>
|
|
620
|
+
<form class="mb-1 mt-4" on:submit={handleCreate}>
|
|
621
|
+
<div class="flex flex-row">
|
|
510
622
|
<!-- svelte-ignore a11y-autofocus -->
|
|
511
623
|
<input
|
|
512
|
-
class="
|
|
624
|
+
class="box-border w-40 rounded px-2 py-1 text-lg text-neutral-800 outline-none"
|
|
513
625
|
placeholder="bob"
|
|
514
626
|
bind:this={nameInput}
|
|
515
627
|
bind:value={nameInputValue}
|
|
516
628
|
on:input={checkNameInput}
|
|
517
629
|
autofocus
|
|
630
|
+
autocapitalize="none"
|
|
518
631
|
/>
|
|
519
|
-
<div class="
|
|
632
|
+
<div class="mx-2 text-2xl">@</div>
|
|
520
633
|
<select
|
|
521
|
-
class="
|
|
634
|
+
class="box-border w-full rounded px-2 py-1 text-lg text-neutral-800 outline-none"
|
|
522
635
|
bind:value={chosenProvider}
|
|
523
636
|
>
|
|
524
637
|
{#each providers as prov}
|
|
525
638
|
<option
|
|
526
639
|
label={prov.domain}
|
|
527
640
|
value={prov}
|
|
528
|
-
class="
|
|
641
|
+
class="px-2 py-1 text-lg"
|
|
529
642
|
/>
|
|
530
643
|
{/each}
|
|
531
644
|
</select>
|
|
532
645
|
</div>
|
|
533
|
-
<div class="tw-text-sm tw-text-center tw-mt-4 tw-leading-4">
|
|
534
|
-
A window from the selected provider will pop up to finalize the
|
|
535
|
-
creation; if it doesn't display check if the browser is blocking it
|
|
536
|
-
</div>
|
|
537
646
|
<button
|
|
538
|
-
class="
|
|
539
|
-
disabled={!chosenProvider || !nameInputValue}
|
|
647
|
+
class="mt-4 block w-full cursor-pointer rounded border-0 px-2 py-1 text-lg text-white disabled:cursor-default disabled:bg-neutral-400 disabled:text-neutral-200 bg-{accent}-900 hover:bg-{accent}-950"
|
|
648
|
+
disabled={!chosenProvider || !nameInputValue || awaitingCreation}
|
|
540
649
|
>
|
|
541
|
-
|
|
650
|
+
Continue »
|
|
542
651
|
</button>
|
|
543
652
|
</form>
|
|
544
|
-
<div class="
|
|
653
|
+
<div class="mt-6 text-center text-sm leading-3">
|
|
545
654
|
Do you already have a Nostr address?<br />
|
|
546
655
|
<button
|
|
547
|
-
class="
|
|
656
|
+
class="cursor-pointer border-0 bg-transparent text-sm text-white underline"
|
|
548
657
|
on:click={handleOpenLogin}>Login now</button
|
|
549
658
|
>
|
|
550
659
|
</div>
|
|
551
660
|
|
|
552
661
|
<!-- Login view ################### -->
|
|
553
662
|
{:else if !identity}
|
|
554
|
-
<div class="
|
|
663
|
+
<div class="text-center text-lg">
|
|
555
664
|
How do you want to connect to Nostr?
|
|
556
665
|
</div>
|
|
557
|
-
<form class="
|
|
666
|
+
<form class="mb-1 mt-4 flex flex-col" on:submit={handleConnect}>
|
|
558
667
|
<!-- svelte-ignore a11y-autofocus -->
|
|
559
668
|
<input
|
|
560
|
-
class="
|
|
669
|
+
class="box-border w-full rounded px-2 py-1 text-lg text-neutral-800 outline-none"
|
|
561
670
|
placeholder="user@provider or bunker://..."
|
|
562
671
|
bind:this={bunkerInput}
|
|
563
672
|
bind:value={bunkerInputValue}
|
|
564
673
|
autofocus
|
|
565
674
|
disabled={connecting}
|
|
675
|
+
autocapitalize="none"
|
|
566
676
|
/>
|
|
567
677
|
{#if errorMessage}
|
|
568
678
|
<div
|
|
569
|
-
class="
|
|
679
|
+
class="my-2 rounded bg-yellow-100 p-2 text-center text-sm leading-4 text-red-400"
|
|
570
680
|
>
|
|
571
681
|
{errorMessage}
|
|
572
682
|
</div>
|
|
573
683
|
{/if}
|
|
574
684
|
<button
|
|
575
|
-
class="
|
|
685
|
+
class="mt-4 flex w-full cursor-pointer items-center justify-center rounded border-0 px-2 py-1 text-lg text-white disabled:cursor-default disabled:bg-neutral-400 disabled:text-neutral-200 bg-{accent}-900 hover:bg-{accent}-950"
|
|
576
686
|
disabled={!bunkerInputValueIsGood || connecting}
|
|
577
687
|
>
|
|
578
688
|
{#if connecting}
|
|
@@ -583,62 +693,60 @@
|
|
|
583
693
|
{/if}
|
|
584
694
|
</button>
|
|
585
695
|
{#if connecting && takingTooLong}
|
|
586
|
-
<div class="
|
|
696
|
+
<div class="mt-6 text-center text-sm leading-3">
|
|
587
697
|
Waiting too much?
|
|
588
698
|
<button
|
|
589
|
-
class="
|
|
699
|
+
class="cursor-pointer border-0 bg-transparent text-sm text-white underline"
|
|
590
700
|
on:click={handleAbortConnection}>Cancel the connection</button
|
|
591
701
|
>
|
|
592
702
|
</div>
|
|
593
703
|
{/if}
|
|
594
704
|
</form>
|
|
595
705
|
{#if !connecting}
|
|
596
|
-
<div class="
|
|
706
|
+
<div class="mt-6 text-center text-sm leading-3">
|
|
597
707
|
Do you need a Nostr account?<br />
|
|
598
708
|
<button
|
|
599
|
-
class="
|
|
709
|
+
class="cursor-pointer border-0 bg-transparent text-sm text-white underline"
|
|
600
710
|
on:click={handleOpenCreate}>Sign up now</button
|
|
601
711
|
>
|
|
602
712
|
</div>
|
|
603
713
|
{/if}
|
|
604
714
|
|
|
605
715
|
<!-- Connected view ################### -->
|
|
606
|
-
{:else
|
|
607
|
-
<div class="
|
|
608
|
-
<div class="
|
|
716
|
+
{:else}
|
|
717
|
+
<div class="text-center">
|
|
718
|
+
<div class="mb-4 text-sm">You are connected to Nostr as</div>
|
|
609
719
|
<a
|
|
610
720
|
target="_blank"
|
|
611
721
|
href={'https://nosta.me/' + identity.npub}
|
|
612
|
-
class="
|
|
722
|
+
class="group text-white no-underline"
|
|
613
723
|
>
|
|
614
724
|
{#if identity.picture || identity.name}
|
|
615
|
-
<div
|
|
616
|
-
class="tw-flex tw-items-center tw-justify-center tw-gap-2 tw-mb-2"
|
|
617
|
-
>
|
|
725
|
+
<div class="mb-2 flex items-center justify-center gap-2">
|
|
618
726
|
{#if identity.picture}
|
|
619
727
|
<img
|
|
620
728
|
src={identity.picture}
|
|
621
729
|
alt=""
|
|
622
|
-
class="
|
|
730
|
+
class="h-10 w-10 rounded-full border-2 border-solid border-transparent group-hover:border-{accent}-100"
|
|
623
731
|
/>
|
|
624
732
|
{/if}
|
|
625
733
|
{#if identity.name}
|
|
626
734
|
<div
|
|
627
|
-
class="
|
|
735
|
+
class="text-3xl decoration-2 underline-offset-4 group-hover:underline"
|
|
628
736
|
>
|
|
629
737
|
{identity.name}
|
|
630
738
|
</div>
|
|
631
739
|
{/if}
|
|
632
740
|
</div>
|
|
633
741
|
{/if}
|
|
634
|
-
<div class="
|
|
742
|
+
<div class="block break-all">{identity.npub}</div>
|
|
635
743
|
</a>
|
|
636
744
|
</div>
|
|
637
745
|
<button
|
|
638
|
-
class="
|
|
746
|
+
class="my-2 mt-6 block w-full cursor-pointer rounded border-0 px-2 py-1 text-lg text-white bg-{accent}-900 hover:bg-{accent}-950"
|
|
639
747
|
on:click={handleDisconnect}>Disconnect</button
|
|
640
748
|
>
|
|
641
|
-
<div class="
|
|
749
|
+
<div class="mt-6 block break-all text-center text-sm">
|
|
642
750
|
This webpage is using the public key:<br />
|
|
643
751
|
{getPublicKey(clientSecret)}
|
|
644
752
|
</div>
|
|
@@ -646,13 +754,3 @@
|
|
|
646
754
|
</div>
|
|
647
755
|
{/if}
|
|
648
756
|
</div>
|
|
649
|
-
|
|
650
|
-
<!-- hack to preload tailwind colors:
|
|
651
|
-
tw-bg-cyan-700 tw-bg-cyan-800 tw-bg-cyan-900 tw-bg-cyan-950 tw-text-cyan-950 tw-outline-cyan-500
|
|
652
|
-
tw-bg-green-700 tw-bg-green-800 tw-bg-green-900 tw-bg-green-950 tw-text-green-950 tw-outline-green-500
|
|
653
|
-
tw-bg-purple-700 tw-bg-purple-800 tw-bg-purple-900 tw-bg-purple-950 tw-text-purple-950 tw-outline-purple-500
|
|
654
|
-
tw-bg-red-700 tw-bg-red-800 tw-bg-red-900 tw-bg-red-950 tw-text-red-950 tw-outline-red-500
|
|
655
|
-
tw-bg-orange-700 tw-bg-orange-800 tw-bg-orange-900 tw-bg-orange-950 tw-text-orange-950 tw-outline-orange-500
|
|
656
|
-
tw-bg-neutral-700 tw-bg-neutral-800 tw-bg-neutral-900 tw-bg-neutral-950 tw-text-neutral-950 tw-outline-neutral-500
|
|
657
|
-
tw-bg-stone-700 tw-bg-stone-800 tw-bg-stone-900 tw-bg-stone-950 tw-text-stone-950 tw-outline-stone-500
|
|
658
|
-
-->
|
package/src/Spinner.svelte
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<svg
|
|
2
|
-
class="
|
|
2
|
+
class="ml-2 h-5 w-5 animate-spin text-white"
|
|
3
3
|
xmlns="http://www.w3.org/2000/svg"
|
|
4
4
|
fill="none"
|
|
5
5
|
viewBox="0 0 24 24"
|
|
6
6
|
>
|
|
7
7
|
<circle
|
|
8
|
-
class="
|
|
8
|
+
class="opacity-25"
|
|
9
9
|
cx="12"
|
|
10
10
|
cy="12"
|
|
11
11
|
r="10"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
stroke-width="4"
|
|
14
14
|
></circle>
|
|
15
15
|
<path
|
|
16
|
-
class="
|
|
16
|
+
class="opacity-75"
|
|
17
17
|
fill="currentColor"
|
|
18
18
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
19
19
|
></path>
|
package/src/app.css
CHANGED
package/tailwind.config.js
CHANGED
|
@@ -21,5 +21,14 @@ export default {
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
plugins: [],
|
|
24
|
-
prefix: '
|
|
24
|
+
prefix: '',
|
|
25
|
+
safelist: [
|
|
26
|
+
'bg-cyan-700', 'hover:bg-cyan-700', 'bg-cyan-800', 'hover:bg-cyan-800', 'bg-cyan-900', 'hover:bg-cyan-900', 'bg-cyan-950', 'hover:bg-cyan-950', 'text-cyan-600', 'outline-cyan-500', 'from-cyan-900', 'to-cyan-700',
|
|
27
|
+
'bg-green-700', 'hover:bg-green-700', 'bg-green-800', 'hover:bg-green-800', 'bg-green-900', 'hover:bg-green-900', 'bg-green-950', 'hover:bg-green-950', 'text-green-600', 'outline-green-500', 'from-green-900', 'to-green-700',
|
|
28
|
+
'bg-purple-700', 'hover:bg-purple-700', 'bg-purple-800', 'hover:bg-purple-800', 'bg-purple-900', 'hover:bg-purple-900', 'bg-purple-950', 'hover:bg-purple-950', 'text-purple-600', 'outline-purple-500', 'from-purple-900', 'to-purple-700',
|
|
29
|
+
'bg-red-700', 'hover:bg-red-700', 'bg-red-800', 'hover:bg-red-800', 'bg-red-900', 'hover:bg-red-900', 'bg-red-950', 'hover:bg-red-950', 'text-red-600', 'outline-red-500', 'from-red-900', 'to-red-700',
|
|
30
|
+
'bg-orange-700', 'hover:bg-orange-700', 'bg-orange-800', 'hover:bg-orange-800', 'bg-orange-900', 'hover:bg-orange-900', 'bg-orange-950', 'hover:bg-orange-950', 'text-orange-600', 'outline-orange-500', 'from-orange-900', 'to-orange-700',
|
|
31
|
+
'bg-neutral-700', 'hover:bg-neutral-700', 'bg-neutral-800', 'hover:bg-neutral-800', 'bg-neutral-900', 'hover:bg-neutral-900', 'bg-neutral-950', 'hover:bg-neutral-950', 'text-neutral-600', 'outline-neutral-500', 'from-neutral-900', 'to-neutral-700',
|
|
32
|
+
'bg-stone-700', 'hover:bg-stone-700', 'bg-stone-800', 'hover:bg-stone-800', 'bg-stone-900', 'hover:bg-stone-900', 'bg-stone-950', 'hover:bg-stone-950', 'text-stone-600', 'outline-stone-500', 'from-stone-900', 'to-stone-700',
|
|
33
|
+
]
|
|
25
34
|
}
|