window.nostr.js 0.3.0 → 0.4.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/dist/iframe.html +1 -0
- package/dist/iframe.js +4333 -0
- package/dist/iframe.js.map +7 -0
- package/dist/index.html +1 -1
- package/dist/window.nostr.js +15 -9
- package/iframe/build.js +9 -0
- package/iframe/iframe.html +1 -0
- package/iframe/iframe.ts +21 -0
- package/justfile +9 -2
- package/package.json +3 -2
- package/src/App.svelte +42 -33
- package/src/lib.ts +7 -0
- package/src/main.ts +8 -8
- package/src/mediaQueryStore.ts +25 -0
- package/tsconfig.json +4 -3
- package/src/mediaQueryStore.js +0 -33
package/iframe/build.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<script src="iframe.js"></script>
|
package/iframe/iframe.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {parseBunkerInput} from 'nostr-tools/nip46'
|
|
2
|
+
import {localStorageKeys} from '../src/lib'
|
|
3
|
+
|
|
4
|
+
window.onmessage = async (ev: MessageEvent) => {
|
|
5
|
+
if (
|
|
6
|
+
!ev.origin.startsWith('https://join.the-nostr.org') &&
|
|
7
|
+
!ev.origin.startsWith('http://localhost:6711')
|
|
8
|
+
) {
|
|
9
|
+
return
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const {bunker} = ev.data
|
|
13
|
+
if (bunker) {
|
|
14
|
+
const bp = await parseBunkerInput(bunker)
|
|
15
|
+
if (bp) {
|
|
16
|
+
localStorage.setItem(localStorageKeys.BUNKER_POINTER, JSON.stringify(bp))
|
|
17
|
+
} else {
|
|
18
|
+
console.error('wnj iframe got an invalid bunker url:', bunker)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/justfile
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
export PATH := "./node_modules/.bin:" + env_var('PATH')
|
|
2
|
+
set unstable
|
|
2
3
|
|
|
3
4
|
dev:
|
|
4
|
-
vite
|
|
5
|
+
vite --port 13471
|
|
5
6
|
|
|
6
|
-
build:
|
|
7
|
+
build: wnj iframe
|
|
8
|
+
|
|
9
|
+
wnj:
|
|
7
10
|
vite build
|
|
8
11
|
mv dist/assets/*.js dist/window.nostr.js
|
|
9
12
|
|
|
13
|
+
iframe:
|
|
14
|
+
node ./iframe/build.js
|
|
15
|
+
cp ./iframe/iframe.html dist/
|
|
16
|
+
|
|
10
17
|
demo:
|
|
11
18
|
xdg-open demo/index.html
|
|
12
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "window.nostr.js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/window.nostr.js",
|
|
6
6
|
"devDependencies": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"@tsconfig/svelte": "^5.0.2",
|
|
9
9
|
"@typescript-eslint/eslint-plugin": "^7.0.1",
|
|
10
10
|
"autoprefixer": "^10.4.17",
|
|
11
|
+
"esbuild": "^0.24.0",
|
|
11
12
|
"eslint-config-prettier": "^9.1.0",
|
|
12
13
|
"eslint-plugin-svelte": "^2.35.1",
|
|
13
14
|
"postcss": "^8.4.35",
|
|
@@ -23,6 +24,6 @@
|
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
26
|
"debounce": "^2.0.0",
|
|
26
|
-
"nostr-tools": "2.
|
|
27
|
+
"nostr-tools": "^2.8.1"
|
|
27
28
|
}
|
|
28
29
|
}
|
package/src/App.svelte
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
type BunkerProfile,
|
|
19
19
|
BUNKER_REGEX
|
|
20
20
|
} from 'nostr-tools/nip46'
|
|
21
|
+
import {localStorageKeys} from './lib'
|
|
21
22
|
import {NIP05_REGEX, queryProfile} from 'nostr-tools/nip05'
|
|
22
23
|
import {npubEncode} from 'nostr-tools/nip19'
|
|
23
24
|
import {onMount} from 'svelte'
|
|
@@ -25,13 +26,6 @@
|
|
|
25
26
|
import Spinner from './Spinner.svelte'
|
|
26
27
|
|
|
27
28
|
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
|
-
}
|
|
35
29
|
|
|
36
30
|
let myself: HTMLDivElement
|
|
37
31
|
export let accent: string
|
|
@@ -122,7 +116,7 @@
|
|
|
122
116
|
onauth(url: string) {
|
|
123
117
|
if (creating) {
|
|
124
118
|
showAuth = url
|
|
125
|
-
} else if(identity) {
|
|
119
|
+
} else if (identity) {
|
|
126
120
|
showConfirmAction = url
|
|
127
121
|
opened = true
|
|
128
122
|
} else {
|
|
@@ -532,18 +526,18 @@
|
|
|
532
526
|
>
|
|
533
527
|
<!-- Connecting view ################### -->
|
|
534
528
|
{#if connecting}
|
|
535
|
-
<div class="flex px-2
|
|
529
|
+
<div class="flex items-center px-2">
|
|
536
530
|
Connecting to bunker
|
|
537
531
|
<Spinner />
|
|
538
532
|
</div>
|
|
539
|
-
{:else if !identity
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
533
|
+
{:else if !identity}
|
|
534
|
+
{#if compactMode}
|
|
535
|
+
<div class="w-6 text-center">N</div>
|
|
536
|
+
{:else}
|
|
537
|
+
<div class="flex items-center px-2">Connect with Nostr</div>
|
|
538
|
+
{/if}
|
|
545
539
|
{:else if !compactMode}
|
|
546
|
-
<div class="flex px-2
|
|
540
|
+
<div class="flex items-center px-2">
|
|
547
541
|
{#if identity.picture}
|
|
548
542
|
<img
|
|
549
543
|
src={identity.picture}
|
|
@@ -551,19 +545,17 @@
|
|
|
551
545
|
class="mr-2 h-5 w-5 rounded-full"
|
|
552
546
|
/>
|
|
553
547
|
{:else}
|
|
554
|
-
|
|
548
|
+
<span class="mr-2">☉</span>
|
|
555
549
|
{/if}
|
|
556
|
-
<div
|
|
550
|
+
<div
|
|
551
|
+
class="inline-block max-w-56 overflow-hidden overflow-ellipsis whitespace-nowrap"
|
|
552
|
+
>
|
|
557
553
|
{identity.name ||
|
|
558
554
|
identity.npub.slice(0, 7) + '…' + identity.npub.slice(-4)}
|
|
559
555
|
</div>
|
|
560
556
|
</div>
|
|
561
557
|
{:else}
|
|
562
|
-
<img
|
|
563
|
-
src={identity.picture}
|
|
564
|
-
alt=""
|
|
565
|
-
class="h-6 w-6 rounded-full"
|
|
566
|
-
/>
|
|
558
|
+
<img src={identity.picture} alt="" class="h-6 w-6 rounded-full" />
|
|
567
559
|
{/if}
|
|
568
560
|
</div>
|
|
569
561
|
|
|
@@ -590,40 +582,57 @@
|
|
|
590
582
|
<div class="m-auto w-full">
|
|
591
583
|
<div class="text-center text-lg">Create a Nostr account</div>
|
|
592
584
|
<div class="mt-4 text-center text-sm leading-4">
|
|
593
|
-
Now you a new window will bring you to <strong
|
|
585
|
+
Now you a new window will bring you to <strong
|
|
586
|
+
>{new URL(showAuth).host}</strong
|
|
587
|
+
>
|
|
588
|
+
where the account creation will take place. If nothing happens check
|
|
589
|
+
that if your browser is blocking popups, pleaase.<br />
|
|
594
590
|
After that you will be returned to this page.
|
|
595
591
|
</div>
|
|
596
592
|
<button
|
|
597
593
|
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"
|
|
598
|
-
on:click={() => openAuthURLPopup(showAuth)}
|
|
594
|
+
on:click={() => openAuthURLPopup(showAuth)}
|
|
595
|
+
>
|
|
599
596
|
Start account creation »
|
|
600
597
|
</button>
|
|
601
598
|
</div>
|
|
602
|
-
|
|
603
599
|
{:else if showLogin}
|
|
604
600
|
<div class="m-auto w-full">
|
|
605
601
|
<div class="text-center text-lg">Login into a Nostr account</div>
|
|
606
602
|
<div class="mt-4 text-center text-sm leading-4">
|
|
607
|
-
Now you a new window will bring you to <strong
|
|
603
|
+
Now you a new window will bring you to <strong
|
|
604
|
+
>{new URL(showLogin).host}</strong
|
|
605
|
+
>
|
|
606
|
+
where you can login and approve the permissions. If nothing happens check
|
|
607
|
+
that if your browser is blocking popups, pleaase.<br />
|
|
608
608
|
After that you will be returned to this page.
|
|
609
609
|
</div>
|
|
610
610
|
<button
|
|
611
611
|
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"
|
|
612
|
-
on:click={() => openAuthURLPopup(showLogin)}
|
|
612
|
+
on:click={() => openAuthURLPopup(showLogin)}
|
|
613
|
+
>
|
|
613
614
|
Login now »
|
|
614
615
|
</button>
|
|
615
616
|
</div>
|
|
616
|
-
|
|
617
|
-
{:else if showConfirmAction}
|
|
617
|
+
{:else if showConfirmAction}
|
|
618
618
|
<div class="m-auto w-full">
|
|
619
|
-
<div class="text-center text-lg">
|
|
619
|
+
<div class="text-center text-lg">
|
|
620
|
+
An action requires your confirmation
|
|
621
|
+
</div>
|
|
620
622
|
<div class="mt-4 text-center text-sm leading-4">
|
|
621
|
-
Now you a new window will bring you to <strong
|
|
623
|
+
Now you a new window will bring you to <strong
|
|
624
|
+
>{new URL(showConfirmAction).host}</strong
|
|
625
|
+
>
|
|
626
|
+
where you can approve the current action. If nothing happens check that
|
|
627
|
+
if your browser is blocking popups, pleaase.<br />
|
|
622
628
|
After that you will be returned to this page.
|
|
623
629
|
</div>
|
|
624
630
|
<button
|
|
625
631
|
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"
|
|
626
|
-
on:click={() => {
|
|
632
|
+
on:click={() => {
|
|
633
|
+
openAuthURLPopup(showConfirmAction)
|
|
634
|
+
}}
|
|
635
|
+
>
|
|
627
636
|
Confirm action »
|
|
628
637
|
</button>
|
|
629
638
|
</div>
|
package/src/lib.ts
ADDED
package/src/main.ts
CHANGED
|
@@ -37,24 +37,24 @@ const app = new App({
|
|
|
37
37
|
props: {
|
|
38
38
|
accent: win.wnjParams?.accent || 'cyan',
|
|
39
39
|
position: win.wnjParams?.position === 'bottom' ? 'bottom' : 'top',
|
|
40
|
-
startHidden: win.wnjParams?.startHidden
|
|
41
|
-
compactMode: win.wnjParams?.compactMode
|
|
40
|
+
startHidden: win.wnjParams?.startHidden,
|
|
41
|
+
compactMode: win.wnjParams?.compactMode
|
|
42
42
|
}
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
-
if (!win.wnjParams?.disableOverflowFix){
|
|
45
|
+
if (!win.wnjParams?.disableOverflowFix) {
|
|
46
46
|
// Inject on the host page a style to avoid weird scrolling on the
|
|
47
47
|
// right/bottom on mobile, if the underlying page has some horizontal
|
|
48
48
|
// scrolling
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const styleElement = document.createElement('style')
|
|
50
|
+
const cssCode = `
|
|
51
51
|
html, body {
|
|
52
52
|
overflow: auto;
|
|
53
53
|
height: 100%;
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
styleElement.innerHTML = cssCode
|
|
57
|
-
document.head.appendChild(styleElement)
|
|
55
|
+
`
|
|
56
|
+
styleElement.innerHTML = cssCode
|
|
57
|
+
document.head.appendChild(styleElement)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export default app
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {writable} from 'svelte/store'
|
|
2
|
+
|
|
3
|
+
export default (mediaQueryString: string) => {
|
|
4
|
+
const {subscribe, set} = writable<boolean>(undefined, () => {
|
|
5
|
+
// start observing media query
|
|
6
|
+
const mql = window.matchMedia(mediaQueryString)
|
|
7
|
+
|
|
8
|
+
// set first media query result to the store
|
|
9
|
+
set(mql.matches)
|
|
10
|
+
|
|
11
|
+
// called when media query state changes
|
|
12
|
+
const onchange = () => set(mql.matches)
|
|
13
|
+
|
|
14
|
+
// listen for changes (need to support old `addListener` interface)
|
|
15
|
+
mql.addEventListener('change', onchange)
|
|
16
|
+
|
|
17
|
+
// when no more listeners
|
|
18
|
+
return () => {
|
|
19
|
+
// stop listening (need to support old `removeListener` interface)
|
|
20
|
+
mql.removeEventListener('change', onchange)
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
return {subscribe}
|
|
25
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
*/
|
|
14
14
|
"allowJs": true,
|
|
15
15
|
"checkJs": true,
|
|
16
|
-
"isolatedModules": true
|
|
16
|
+
"isolatedModules": true,
|
|
17
|
+
"moduleDetection": "force"
|
|
17
18
|
},
|
|
18
|
-
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
|
|
19
|
-
"references": [{
|
|
19
|
+
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "iframe/*.ts"],
|
|
20
|
+
"references": [{"path": "./tsconfig.node.json"}]
|
|
20
21
|
}
|
package/src/mediaQueryStore.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {writable} from 'svelte/store'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Svelte Media Query Store
|
|
5
|
-
* @param mediaQueryString { string }
|
|
6
|
-
*/
|
|
7
|
-
export default mediaQueryString => {
|
|
8
|
-
const {subscribe, set} = writable(undefined, () => {
|
|
9
|
-
// Start observing media query
|
|
10
|
-
let mql = window.matchMedia(mediaQueryString)
|
|
11
|
-
|
|
12
|
-
// Set first media query result to the store
|
|
13
|
-
set(mql.matches)
|
|
14
|
-
|
|
15
|
-
// Called when media query state changes
|
|
16
|
-
const onchange = () => set(mql.matches)
|
|
17
|
-
|
|
18
|
-
// Listen for changes (need to support old `addListener` interface)
|
|
19
|
-
'addEventListener' in mql
|
|
20
|
-
? mql.addEventListener('change', onchange)
|
|
21
|
-
: mql.addListener(onchange)
|
|
22
|
-
|
|
23
|
-
// when no more listeners
|
|
24
|
-
return () => {
|
|
25
|
-
// stop listening (need to support old `removeListener` interface)
|
|
26
|
-
'removeEventListener' in mql
|
|
27
|
-
? mql.removeEventListener('change', onchange)
|
|
28
|
-
: mql.removeListener(onchange)
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
return {subscribe}
|
|
33
|
-
}
|