window.nostr.js 0.2.2 → 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/README.md +5 -0
- 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 +49 -26
- package/src/lib.ts +7 -0
- package/src/main.ts +9 -7
- 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
|
|
@@ -42,6 +36,8 @@
|
|
|
42
36
|
| 'top'
|
|
43
37
|
| 'bottom'
|
|
44
38
|
| null) || position
|
|
39
|
+
export let startHidden: boolean
|
|
40
|
+
export let compactMode: boolean
|
|
45
41
|
|
|
46
42
|
const win = window as any
|
|
47
43
|
const pool = new SimplePool()
|
|
@@ -120,7 +116,7 @@
|
|
|
120
116
|
onauth(url: string) {
|
|
121
117
|
if (creating) {
|
|
122
118
|
showAuth = url
|
|
123
|
-
} else if(identity) {
|
|
119
|
+
} else if (identity) {
|
|
124
120
|
showConfirmAction = url
|
|
125
121
|
opened = true
|
|
126
122
|
} else {
|
|
@@ -522,20 +518,26 @@
|
|
|
522
518
|
bind:this={myself}
|
|
523
519
|
>
|
|
524
520
|
<!-- Close status ################### -->
|
|
525
|
-
{#if !opened}
|
|
521
|
+
{#if !opened && !identity && startHidden}
|
|
522
|
+
<!-- Show nothing -->
|
|
523
|
+
{:else if !opened}
|
|
526
524
|
<div
|
|
527
|
-
class="rounded px-
|
|
525
|
+
class="rounded px-2 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}"
|
|
528
526
|
>
|
|
529
527
|
<!-- Connecting view ################### -->
|
|
530
528
|
{#if connecting}
|
|
531
|
-
<div class="flex items-center">
|
|
529
|
+
<div class="flex items-center px-2">
|
|
532
530
|
Connecting to bunker
|
|
533
531
|
<Spinner />
|
|
534
532
|
</div>
|
|
535
533
|
{:else if !identity}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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}
|
|
539
|
+
{:else if !compactMode}
|
|
540
|
+
<div class="flex items-center px-2">
|
|
539
541
|
{#if identity.picture}
|
|
540
542
|
<img
|
|
541
543
|
src={identity.picture}
|
|
@@ -543,13 +545,17 @@
|
|
|
543
545
|
class="mr-2 h-5 w-5 rounded-full"
|
|
544
546
|
/>
|
|
545
547
|
{:else}
|
|
546
|
-
|
|
548
|
+
<span class="mr-2">☉</span>
|
|
547
549
|
{/if}
|
|
548
|
-
<div
|
|
550
|
+
<div
|
|
551
|
+
class="inline-block max-w-56 overflow-hidden overflow-ellipsis whitespace-nowrap"
|
|
552
|
+
>
|
|
549
553
|
{identity.name ||
|
|
550
554
|
identity.npub.slice(0, 7) + '…' + identity.npub.slice(-4)}
|
|
551
555
|
</div>
|
|
552
556
|
</div>
|
|
557
|
+
{:else}
|
|
558
|
+
<img src={identity.picture} alt="" class="h-6 w-6 rounded-full" />
|
|
553
559
|
{/if}
|
|
554
560
|
</div>
|
|
555
561
|
|
|
@@ -576,40 +582,57 @@
|
|
|
576
582
|
<div class="m-auto w-full">
|
|
577
583
|
<div class="text-center text-lg">Create a Nostr account</div>
|
|
578
584
|
<div class="mt-4 text-center text-sm leading-4">
|
|
579
|
-
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 />
|
|
580
590
|
After that you will be returned to this page.
|
|
581
591
|
</div>
|
|
582
592
|
<button
|
|
583
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"
|
|
584
|
-
on:click={() => openAuthURLPopup(showAuth)}
|
|
594
|
+
on:click={() => openAuthURLPopup(showAuth)}
|
|
595
|
+
>
|
|
585
596
|
Start account creation »
|
|
586
597
|
</button>
|
|
587
598
|
</div>
|
|
588
|
-
|
|
589
599
|
{:else if showLogin}
|
|
590
600
|
<div class="m-auto w-full">
|
|
591
601
|
<div class="text-center text-lg">Login into a Nostr account</div>
|
|
592
602
|
<div class="mt-4 text-center text-sm leading-4">
|
|
593
|
-
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 />
|
|
594
608
|
After that you will be returned to this page.
|
|
595
609
|
</div>
|
|
596
610
|
<button
|
|
597
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"
|
|
598
|
-
on:click={() => openAuthURLPopup(showLogin)}
|
|
612
|
+
on:click={() => openAuthURLPopup(showLogin)}
|
|
613
|
+
>
|
|
599
614
|
Login now »
|
|
600
615
|
</button>
|
|
601
616
|
</div>
|
|
602
|
-
|
|
603
|
-
{:else if showConfirmAction}
|
|
617
|
+
{:else if showConfirmAction}
|
|
604
618
|
<div class="m-auto w-full">
|
|
605
|
-
<div class="text-center text-lg">
|
|
619
|
+
<div class="text-center text-lg">
|
|
620
|
+
An action requires your confirmation
|
|
621
|
+
</div>
|
|
606
622
|
<div class="mt-4 text-center text-sm leading-4">
|
|
607
|
-
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 />
|
|
608
628
|
After that you will be returned to this page.
|
|
609
629
|
</div>
|
|
610
630
|
<button
|
|
611
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"
|
|
612
|
-
on:click={() => {
|
|
632
|
+
on:click={() => {
|
|
633
|
+
openAuthURLPopup(showConfirmAction)
|
|
634
|
+
}}
|
|
635
|
+
>
|
|
613
636
|
Confirm action »
|
|
614
637
|
</button>
|
|
615
638
|
</div>
|
package/src/lib.ts
ADDED
package/src/main.ts
CHANGED
|
@@ -36,23 +36,25 @@ const app = new App({
|
|
|
36
36
|
target: mountPoint,
|
|
37
37
|
props: {
|
|
38
38
|
accent: win.wnjParams?.accent || 'cyan',
|
|
39
|
-
position: win.wnjParams?.position === 'bottom' ? 'bottom' : 'top'
|
|
39
|
+
position: win.wnjParams?.position === 'bottom' ? 'bottom' : 'top',
|
|
40
|
+
startHidden: win.wnjParams?.startHidden,
|
|
41
|
+
compactMode: win.wnjParams?.compactMode
|
|
40
42
|
}
|
|
41
43
|
})
|
|
42
44
|
|
|
43
|
-
if (!win.wnjParams?.disableOverflowFix){
|
|
45
|
+
if (!win.wnjParams?.disableOverflowFix) {
|
|
44
46
|
// Inject on the host page a style to avoid weird scrolling on the
|
|
45
47
|
// right/bottom on mobile, if the underlying page has some horizontal
|
|
46
48
|
// scrolling
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
const styleElement = document.createElement('style')
|
|
50
|
+
const cssCode = `
|
|
49
51
|
html, body {
|
|
50
52
|
overflow: auto;
|
|
51
53
|
height: 100%;
|
|
52
54
|
}
|
|
53
|
-
|
|
54
|
-
styleElement.innerHTML = cssCode
|
|
55
|
-
document.head.appendChild(styleElement)
|
|
55
|
+
`
|
|
56
|
+
styleElement.innerHTML = cssCode
|
|
57
|
+
document.head.appendChild(styleElement)
|
|
56
58
|
}
|
|
57
59
|
|
|
58
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
|
-
}
|