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.
@@ -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.2.2",
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
@@ -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-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}"
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
- Connect with Nostr
537
- {:else}
538
- <div class="flex items-center">
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 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
+ >
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>{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 />
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>{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 />
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">An action requires your confirmation</div>
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>{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 />
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={() => {openAuthURLPopup(showConfirmAction)}}>
632
+ on:click={() => {
633
+ openAuthURLPopup(showConfirmAction)
634
+ }}
635
+ >
613
636
  Confirm action »
614
637
  </button>
615
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
@@ -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
- var styleElement = document.createElement('style');
48
- var cssCode = `
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": [{ "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
- }