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.
@@ -0,0 +1,9 @@
1
+ import {build} from 'esbuild'
2
+
3
+ build({
4
+ entryPoints: ['iframe/iframe.ts'],
5
+ bundle: true,
6
+ sourcemap: 'external',
7
+ outfile: 'dist/iframe.js',
8
+ format: 'iife'
9
+ }).then(() => console.log('iframe built'))
@@ -0,0 +1 @@
1
+ <script src="iframe.js"></script>
@@ -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.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.5.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 items-center">
529
+ <div class="flex items-center px-2">
536
530
  Connecting to bunker
537
531
  <Spinner />
538
532
  </div>
539
- {:else if !identity && !compactMode}
540
- <div class="flex px-2 items-center">
541
- Connect with Nostr
542
- </div>
543
- {:else if !identity && compactMode}
544
- <div class="w-6 text-center">N</div>
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 items-center">
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 class="max-w-56 overflow-hidden whitespace-nowrap overflow-ellipsis inline-block">
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>{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/>
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>{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/>
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">An action requires your confirmation</div>
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>{new URL(showConfirmAction).host}</strong> where you can approve the current action. If nothing happens check that if your browser is blocking popups, pleaase.<br/>
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={() => {openAuthURLPopup(showConfirmAction)}}>
632
+ on:click={() => {
633
+ openAuthURLPopup(showConfirmAction)
634
+ }}
635
+ >
627
636
  Confirm action »
628
637
  </button>
629
638
  </div>
package/src/lib.ts ADDED
@@ -0,0 +1,7 @@
1
+ export const localStorageKeys = {
2
+ ORIGIN: 'wnj:origin',
3
+ CLIENT_SECRET: 'wnj:clientSecret',
4
+ Y_POS: 'wnj:ypos',
5
+ CALLBACK_TOKEN: 'wnj:callbackToken',
6
+ BUNKER_POINTER: 'wnj:bunkerPointer'
7
+ }
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 ? true : false,
41
- compactMode: win.wnjParams?.compactMode ? true : false,
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
- var styleElement = document.createElement('style');
50
- var cssCode = `
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": [{ "path": "./tsconfig.node.json" }]
19
+ "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "iframe/*.ts"],
20
+ "references": [{"path": "./tsconfig.node.json"}]
20
21
  }
@@ -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
- }