Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b8fc1abdb | |||
|
|
9cd73c12db | ||
| 68600a4c4b | |||
|
|
b1066a1584 | ||
|
|
4712566d20 | ||
|
|
b5612876be | ||
|
|
a7ec9a5100 | ||
|
|
13ea2ccd9e |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ pnpm-lock.yaml
|
|||||||
!.env.example
|
!.env.example
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
.vscode
|
||||||
|
|||||||
83
package-lock.json
generated
83
package-lock.json
generated
@@ -8,15 +8,20 @@
|
|||||||
"name": "cofabricate",
|
"name": "cofabricate",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@noble/hashes": "^1.4.0",
|
||||||
"@nostr-dev-kit/ndk": "^2.8.2",
|
"@nostr-dev-kit/ndk": "^2.8.2",
|
||||||
"@nostr-dev-kit/ndk-svelte": "^2.2.15",
|
"@nostr-dev-kit/ndk-svelte": "^2.2.15",
|
||||||
"@nostr-dev-kit/ndk-svelte-components": "^2.2.16"
|
"@nostr-dev-kit/ndk-svelte-components": "^2.2.16",
|
||||||
|
"markdown-it": "^14.1.0",
|
||||||
|
"sanitize-html": "^2.13.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@types/eslint": "^8.56.7",
|
"@types/eslint": "^8.56.7",
|
||||||
|
"@types/markdown-it": "^14.1.1",
|
||||||
|
"@types/sanitize-html": "^2.11.0",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^9.0.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.36.0",
|
"eslint-plugin-svelte": "^2.36.0",
|
||||||
@@ -1212,11 +1217,42 @@
|
|||||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/linkify-it": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/markdown-it": {
|
||||||
|
"version": "14.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz",
|
||||||
|
"integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/linkify-it": "^5",
|
||||||
|
"@types/mdurl": "^2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/mdurl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/pug": {
|
"node_modules/@types/pug": {
|
||||||
"version": "2.0.10",
|
"version": "2.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz",
|
||||||
"integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA=="
|
"integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/sanitize-html": {
|
||||||
|
"version": "2.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.11.0.tgz",
|
||||||
|
"integrity": "sha512-7oxPGNQHXLHE48r/r/qjn7q0hlrs3kL7oZnGj0Wf/h9tj/6ibFyRkNbsDxaBBZ4XUZ0Dx5LGCyDJ04ytSofacQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"htmlparser2": "^8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/unist": {
|
"node_modules/@types/unist": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz",
|
||||||
@@ -1626,8 +1662,7 @@
|
|||||||
"node_modules/argparse": {
|
"node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/aria-query": {
|
"node_modules/aria-query": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
@@ -3082,6 +3117,14 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/linkify-it": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"uc.micro": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/local-pkg": {
|
"node_modules/local-pkg": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
|
||||||
@@ -3149,6 +3192,22 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/markdown-it": {
|
||||||
|
"version": "14.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||||
|
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1",
|
||||||
|
"entities": "^4.4.0",
|
||||||
|
"linkify-it": "^5.0.0",
|
||||||
|
"mdurl": "^2.0.0",
|
||||||
|
"punycode.js": "^2.3.1",
|
||||||
|
"uc.micro": "^2.1.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"markdown-it": "bin/markdown-it.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/marked": {
|
"node_modules/marked": {
|
||||||
"version": "9.1.6",
|
"version": "9.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
|
||||||
@@ -3192,6 +3251,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/mdurl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
|
||||||
|
},
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
@@ -3829,6 +3893,14 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/punycode.js": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/queue-microtask": {
|
"node_modules/queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
@@ -4591,6 +4663,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/typescript-lru-cache/-/typescript-lru-cache-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-lru-cache/-/typescript-lru-cache-2.0.0.tgz",
|
||||||
"integrity": "sha512-Jp57Qyy8wXeMkdNuZiglE6v2Cypg13eDA1chHwDG6kq51X7gk4K7P7HaDdzZKCxkegXkVHNcPD0n5aW6OZH3aA=="
|
"integrity": "sha512-Jp57Qyy8wXeMkdNuZiglE6v2Cypg13eDA1chHwDG6kq51X7gk4K7P7HaDdzZKCxkegXkVHNcPD0n5aW6OZH3aA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/uc.micro": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
|
||||||
|
},
|
||||||
"node_modules/ufo": {
|
"node_modules/ufo": {
|
||||||
"version": "1.5.3",
|
"version": "1.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev --host 0.0.0.0 --port 8091",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
|
|||||||
29
src/app.html
29
src/app.html
@@ -1,18 +1,17 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html data-theme="dark" lang="en">
|
<html data-theme="dark" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
%sveltekit.head%
|
||||||
|
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css" /> -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
<head>
|
<body data-sveltekit-preload-data="hover">
|
||||||
<meta charset="utf-8" />
|
<div style="display: contents">
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<div class="container is-fluid">%sveltekit.body%</div>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
</div>
|
||||||
%sveltekit.head%
|
</body>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css" />
|
</html>
|
||||||
</head>
|
|
||||||
|
|
||||||
<body data-sveltekit-preload-data="hover">
|
|
||||||
<main class="container">
|
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|||||||
18
src/lib/app.d.ts
vendored
Normal file
18
src/lib/app.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
declare global {
|
||||||
|
namespace App {
|
||||||
|
interface UserProfile {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
displayName?: string;
|
||||||
|
image?: string;
|
||||||
|
banner?: string;
|
||||||
|
bio?: string;
|
||||||
|
nip05?: string;
|
||||||
|
lud16?: string;
|
||||||
|
about?: string;
|
||||||
|
zapService?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
51
src/lib/components/Avatar.svelte
Normal file
51
src/lib/components/Avatar.svelte
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ndk } from '$lib/stores/nostr';
|
||||||
|
import { currentUser } from '$lib/store';
|
||||||
|
import NDK, { NDKUser } from '@nostr-dev-kit/ndk';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
let image: string | undefined;
|
||||||
|
let _ndk = get(ndk);
|
||||||
|
let sessionProfile: NDKUser | null = null;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const sessionProfileObj = sessionStorage.getItem('user');
|
||||||
|
sessionProfile = sessionProfileObj ? JSON.parse(sessionProfileObj) : null;
|
||||||
|
if (sessionProfile) {
|
||||||
|
image = sessionProfile.profile?.image;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const _currentUser = get(currentUser);
|
||||||
|
|
||||||
|
let random = (Math.random() + 1).toString(36).substring(6);
|
||||||
|
let defaultImage = `https://robohash.org/${random}`;
|
||||||
|
|
||||||
|
image = defaultImage;
|
||||||
|
|
||||||
|
$: {
|
||||||
|
console.debug(sessionProfile);
|
||||||
|
image = sessionProfile?.profile?.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
$: ndkUpdated(_ndk);
|
||||||
|
|
||||||
|
function ndkUpdated(_ndk: NDK) {
|
||||||
|
console.debug('NDK updated');
|
||||||
|
if (_ndk.activeUser && _ndk.activeUser.profile && _ndk.activeUser.profile.image) {
|
||||||
|
image = _ndk.activeUser.profile.image;
|
||||||
|
} else {
|
||||||
|
image = defaultImage;
|
||||||
|
}
|
||||||
|
_ndk = _ndk;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<figure class="image">
|
||||||
|
{#if !_ndk.activeUser}
|
||||||
|
<img src={defaultImage} alt="Generic Avatar" class="is-rounded" />
|
||||||
|
{:else}
|
||||||
|
<img src={image} alt="User Avatar" class="is-rounded" />
|
||||||
|
{/if}
|
||||||
|
</figure>
|
||||||
9
src/lib/components/LoginDropdown.svelte
Normal file
9
src/lib/components/LoginDropdown.svelte
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<!-- ndk-svelte-components/LoginDropdown.svelte -->
|
||||||
|
<script lang="ts">
|
||||||
|
import { ndk } from '$lib/stores/nostr';
|
||||||
|
import Nip07Button from './LoginModal/Nip07Button.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !$ndk.signer}
|
||||||
|
<div></div>
|
||||||
|
{/if}
|
||||||
9
src/lib/components/LoginModal/CollapsableDropdown.svelte
Normal file
9
src/lib/components/LoginModal/CollapsableDropdown.svelte
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<!--lib/components/CollapsableDropdown.svelte-->
|
||||||
|
<script lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="dropdown">
|
||||||
|
<div class="dropdown-trigger">
|
||||||
|
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu"> </button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
25
src/lib/components/LoginModal/Modal.svelte
Normal file
25
src/lib/components/LoginModal/Modal.svelte
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
import Nip07Button from "./Nip07Button.svelte";
|
||||||
|
|
||||||
|
export let active = false;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function toggleModal() {
|
||||||
|
dispatch('toggleModal');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="modal" class:is-active={active}>
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-card">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title">Login</p>
|
||||||
|
<button class="delete" aria-label="close" on:click={toggleModal}></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<Nip07Button on:closeModal={toggleModal}/>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
42
src/lib/components/LoginModal/Nip07Button.svelte
Normal file
42
src/lib/components/LoginModal/Nip07Button.svelte
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ndk } from '$lib/stores/nostr';
|
||||||
|
import { login } from '$lib/utils/login';
|
||||||
|
import { currentUser } from '$lib/store';
|
||||||
|
import { browser } from '$app/environment';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
|
let noNip07: boolean;
|
||||||
|
let _ndk = get(ndk);
|
||||||
|
|
||||||
|
$: if (browser) {
|
||||||
|
noNip07 = !window.nostr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
async function nip07Login() {
|
||||||
|
const user = await login('nip07', undefined);
|
||||||
|
if (!user) alert('Nip07 Login Failed');
|
||||||
|
else {
|
||||||
|
$currentUser = user;
|
||||||
|
await $currentUser.fetchProfile();
|
||||||
|
localStorage.setItem('nostr-key-method', 'nip07');
|
||||||
|
localStorage.setItem('nostr-target-npub', $currentUser.npub);
|
||||||
|
_ndk.activeUser = $currentUser;
|
||||||
|
dispatch('closeModal');
|
||||||
|
console.debug($currentUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if noNip07}
|
||||||
|
<div class="alert">
|
||||||
|
<span>No Nostr extension in your browser</span>
|
||||||
|
<div class="hidden">
|
||||||
|
<button class="button is-small">Need Help?</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<button on:click={nip07Login}>Use Browser Extension</button>
|
||||||
|
{/if}
|
||||||
61
src/lib/components/NavBar.svelte
Normal file
61
src/lib/components/NavBar.svelte
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Avatar from '$lib/components/Avatar.svelte';
|
||||||
|
import { ndk } from '$lib/stores/nostr';
|
||||||
|
import { currentUser } from '$lib/store';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
let active = false;
|
||||||
|
|
||||||
|
function signIn() {
|
||||||
|
console.debug('signing in');
|
||||||
|
dispatch('signin');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav class="navbar" aria-label="main navigation">
|
||||||
|
<div class="navbar-brand">
|
||||||
|
<h1 class="title is-1">CoFabricate</h1>
|
||||||
|
<!-- svelte-ignore a11y-missing-attribute -->
|
||||||
|
<button
|
||||||
|
class="navbar-burger"
|
||||||
|
class:is-active={active}
|
||||||
|
aria-label="menu"
|
||||||
|
aria-expanded="false"
|
||||||
|
data-target="mainMenu"
|
||||||
|
on:click={() => (active = !active)}
|
||||||
|
>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="mainMenu" class="navbar-menu" class:is-active={active}>
|
||||||
|
<div class="navbar-end">
|
||||||
|
<div class="navbar-item">
|
||||||
|
<a class="button" href="/">Home</a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-item">
|
||||||
|
<a class="button" href="/about">About</a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-item">
|
||||||
|
<button on:click={signIn}>
|
||||||
|
<Avatar />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div id="mobileMenu" class="navbar-menu is-hidden-desktop" class:is-active={active}>
|
||||||
|
<aside class="menu">
|
||||||
|
</aside>
|
||||||
|
</div> -->
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.nav-menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
10
src/lib/components/User/UserProfile.svelte
Normal file
10
src/lib/components/User/UserProfile.svelte
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { currentUser } from '$lib/store';
|
||||||
|
import { ndk } from '$lib/stores/nostr';
|
||||||
|
import { NDKList } from '@nostr-dev-kit/ndk';
|
||||||
|
import { get, writable } from 'svelte/store';
|
||||||
|
|
||||||
|
const $ndk = get(ndk);
|
||||||
|
|
||||||
|
export const userBlossom = writable<NDKList | null>(null);
|
||||||
|
</script>
|
||||||
22
src/lib/interfaces/user.ts
Normal file
22
src/lib/interfaces/user.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { get as getStore } from 'svelte/store';
|
||||||
|
import { ndk as ndkStore } from '$lib/stores/nostr';
|
||||||
|
import GetUserParams, { type NDKUserParams } from '@nostr-dev-kit/ndk';
|
||||||
|
// import { liveQuery, type Observable } from 'dexie';
|
||||||
|
import { browser } from '$app/environment';
|
||||||
|
// import { db } from '$lib/interfaces/db';
|
||||||
|
|
||||||
|
const UserInterface = {
|
||||||
|
//get: (opts: GetUserParams): Observable<App.UserProfile> => {
|
||||||
|
get: (opts: NDKUserParams): App.UserProfile => {
|
||||||
|
const ndk = getStore(ndkStore);
|
||||||
|
const user = ndk.getUser(opts);
|
||||||
|
console.log('get user', opts);
|
||||||
|
let userProfile = { ...(user.profile || {}), id: user.pubkey };
|
||||||
|
user.fetchProfile().then(async () => {
|
||||||
|
userProfile = { ...userProfile, ...(user.profile || {}) };
|
||||||
|
});
|
||||||
|
return userProfile;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserInterface;
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from 'svelte/store';
|
||||||
import { NDKUser } from "@nostr-dev-kit/ndk";
|
import { NDKUser } from '@nostr-dev-kit/ndk';
|
||||||
|
|
||||||
export const currentUser = writable<NDKUser | null>(null);
|
export const currentUser = writable<NDKUser | null>(null);
|
||||||
export const currentUserFollowPubkeys = writable<string[] | undefined>(undefined);
|
export const currentUserFollowPubkeys = writable<string[] | undefined>(undefined);
|
||||||
export const backgroundBanner = writable<string | null>(null);
|
export const backgroundBanner = writable<string | null>(null);
|
||||||
|
|
||||||
export type ScopeSelection = {
|
export type ScopeSelection = {
|
||||||
label: string;
|
label: string;
|
||||||
id: string;
|
id: string;
|
||||||
pubkeys: string[] | undefined;
|
pubkeys: string[] | undefined;
|
||||||
};
|
};
|
||||||
export const currentScope = writable<ScopeSelection>({
|
export const currentScope = writable<ScopeSelection>({
|
||||||
label: 'global',
|
label: 'global',
|
||||||
id: 'global',
|
id: 'global',
|
||||||
pubkeys: undefined,
|
pubkeys: undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
let zapEvent: any;
|
let zapEvent: any;
|
||||||
@@ -21,4 +21,4 @@ let zapEvent: any;
|
|||||||
export const zap = writable(zapEvent);
|
export const zap = writable(zapEvent);
|
||||||
|
|
||||||
export const pageTitle = writable<string | null>(null);
|
export const pageTitle = writable<string | null>(null);
|
||||||
export const pageSubtitle = writable<string | null>(null);
|
export const pageSubtitle = writable<string | null>(null);
|
||||||
|
|||||||
@@ -1,35 +1,47 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from 'svelte/store';
|
||||||
import NDK from "@nostr-dev-kit/ndk";
|
//import NDKSvelte from '@nostr-dev-kit/ndk-svelte';
|
||||||
import NDKSvelte from "@nostr-dev-kit/ndk-svelte";
|
import NDK from '@nostr-dev-kit/ndk';
|
||||||
import { RelayList } from "@nostr-dev-kit/ndk-svelte-components";
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
let relays;
|
let relays;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
relays = localStorage.getItem('relays');
|
if (browser) relays = localStorage.getItem('relays');
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
let relayList: string[] = [];
|
let relayList: string[] = [];
|
||||||
|
|
||||||
if (relays) {
|
if (relays) {
|
||||||
relayList = JSON.parse(relays);
|
relayList = JSON.parse(relays);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultRelays = [
|
export const defaultRelays = ['wss://purplepag.es', 'wss://relay.damus.io', 'wss://relay.f7z.io'];
|
||||||
'wss://purplepag.es',
|
|
||||||
'wss://relay.damus.io'
|
|
||||||
]
|
|
||||||
|
|
||||||
if (!relayList || !Array.isArray(relayList) || relayList.length === 0) {
|
if (!relayList || !Array.isArray(relayList) || relayList.length === 0) {
|
||||||
relayList = defaultRelays;
|
relayList = defaultRelays;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _ndk: NDKSvelte = new NDKSvelte({
|
const _ndk: NDK = new NDK({
|
||||||
devWriteRelayUrls: ['wss://relay.strfront.com'],
|
devWriteRelayUrls: ['wss://relay.strfront.com'],
|
||||||
explicitRelayUrls: relayList,
|
explicitRelayUrls: relayList,
|
||||||
enableOutboxModel: true,
|
enableOutboxModel: true,
|
||||||
}) as NDKSvelte;
|
autoConnectUserRelays: true,
|
||||||
|
autoFetchUserMutelist: true,
|
||||||
|
clientName: 'cofabricate'
|
||||||
|
}) as NDK;
|
||||||
|
|
||||||
const ndk = writable(_ndk);
|
_ndk.connect();
|
||||||
|
|
||||||
export default ndk;
|
console.debug('Nostr store current user: ', _ndk.activeUser?.profile);
|
||||||
|
|
||||||
|
const ndkStore = writable(_ndk);
|
||||||
|
|
||||||
|
export const ndk = ndkStore;
|
||||||
|
|
||||||
|
const _bunkerNDK = new NDK({
|
||||||
|
explicitRelayUrls: [...defaultRelays, 'wss://relay.nsecbunker.com', 'wss://nostr.vulpem.com']
|
||||||
|
});
|
||||||
|
|
||||||
|
export const bunkerNDK = writable(_bunkerNDK);
|
||||||
|
|||||||
12
src/lib/stores/sesson.ts
Normal file
12
src/lib/stores/sesson.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
// import { ndk } from "$lib/stores/nostr";
|
||||||
|
// import type { NDKUser } from "@nostr-dev-kit/ndk";
|
||||||
|
|
||||||
|
// let $ndk = get(ndk);
|
||||||
|
|
||||||
|
// export let user: NDKUser | undefined = undefined;
|
||||||
|
|
||||||
|
export type LoginState = 'logging-in' | 'logged-in' | 'contacting-remote-signer' | 'logged-out';
|
||||||
|
export const loginState = writable<LoginState | null>(null);
|
||||||
|
|
||||||
|
// if ($ndk.cacheAdapter?.fetchProfile)
|
||||||
@@ -1,82 +1,82 @@
|
|||||||
import { findEphemeralSigner } from "$lib/signers/ephemeral";
|
import { findEphemeralSigner } from '$lib/signers/ephemeral';
|
||||||
import { NDKPrivateKeySigner, type NDKSigner, type NDKUser } from "@nostr-dev-kit/ndk";
|
import NDK, { NDKPrivateKeySigner, type NDKSigner, type NDKUser } from '@nostr-dev-kit/ndk';
|
||||||
import { writable, get as getStore, derived } from "svelte/store";
|
import { writable, get as getStore, derived } from 'svelte/store';
|
||||||
import ndkStore from "./nostr";
|
import { ndk } from './nostr';
|
||||||
import { currentUser as currentUserStore } from "../store";
|
import { currentUser as currentUserStore } from '../store';
|
||||||
import type NDKList from "$lib/ndk-kinds/lists";
|
import type NDKList from '$lib/ndk-kinds/lists';
|
||||||
|
|
||||||
export type SignerStoreItem = {
|
export type SignerStoreItem = {
|
||||||
signer: NDKPrivateKeySigner;
|
signer: NDKPrivateKeySigner;
|
||||||
user: NDKUser;
|
user: NDKUser;
|
||||||
saved: boolean;
|
saved: boolean;
|
||||||
name?: string;
|
name?: string;
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SignerItems = Map<string, SignerStoreItem>;
|
type SignerItems = Map<string, SignerStoreItem>;
|
||||||
|
|
||||||
export const signers = writable<SignerItems>(new Map());
|
export const signers = writable<SignerItems>(new Map());
|
||||||
export const npubSigners = derived(signers, ($signers) => {
|
export const npubSigners = derived(signers, ($signers) => {
|
||||||
const npubs = new Map<string, NDKSigner>();
|
const npubs = new Map<string, NDKSigner>();
|
||||||
|
|
||||||
for (const entry of $signers) {
|
for (const entry of $signers) {
|
||||||
const { user, signer } = entry[1];
|
const { user, signer } = entry[1];
|
||||||
|
|
||||||
npubs.set(user.npub, signer);
|
npubs.set(user.npub, signer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return npubs;
|
return npubs;
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getDelegatedSignerName(list: NDKList) {
|
async function getDelegatedSignerName(list: NDKList) {
|
||||||
let name = '';
|
let name = '';
|
||||||
const currentUser: NDKUser = getStore(currentUserStore);
|
const currentUser = getStore(currentUserStore);
|
||||||
|
|
||||||
if (!currentUser?.profile) {
|
if (currentUser && !currentUser.profile) {
|
||||||
currentUser.ndk = getStore(ndkStore);
|
currentUser.ndk = getStore(ndk);
|
||||||
await currentUser?.fetchProfile();
|
await currentUser?.fetchProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUser?.profile?.name) {
|
if (currentUser?.profile?.name) {
|
||||||
name = currentUser.profile.displayName + `'s `;
|
name = currentUser.profile.displayName + `'s `;
|
||||||
}
|
}
|
||||||
|
|
||||||
return name + list.name;
|
return name + list.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSigner(list: NDKList): Promise<SignerStoreItem> {
|
export async function getSigner(list: NDKList): Promise<SignerStoreItem> {
|
||||||
const store = getStore(signers);
|
const store = getStore(signers);
|
||||||
const id = list.encode();
|
const id = list.encode();
|
||||||
let item = store.get(id);
|
let item = store.get(id);
|
||||||
|
|
||||||
if (item) return item;
|
if (item) return item;
|
||||||
|
|
||||||
const ndk = getStore(ndkStore);
|
const _ndk: NDK = getStore(ndk);
|
||||||
let signer = await findEphemeralSigner(ndk, ndk.signer!, {
|
let signer = await findEphemeralSigner(_ndk, _ndk.signer!, {
|
||||||
associatedEventNip19: list.encode(),
|
associatedEventNip19: list.encode()
|
||||||
});
|
});
|
||||||
|
|
||||||
if (signer) {
|
if (signer) {
|
||||||
console.log(`found a signer for list ${list.name}`);
|
console.log(`found a signer for list ${list.name}`);
|
||||||
item = {
|
item = {
|
||||||
signer: signer!,
|
signer: signer!,
|
||||||
user: await signer.user(),
|
user: await signer.user(),
|
||||||
saved: true,
|
saved: true,
|
||||||
id,
|
id
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
signer = NDKPrivateKeySigner.generate();
|
signer = NDKPrivateKeySigner.generate();
|
||||||
item = {
|
item = {
|
||||||
signer,
|
signer,
|
||||||
user: await signer.user(),
|
user: await signer.user(),
|
||||||
saved: false,
|
saved: false,
|
||||||
name: await getDelegatedSignerName(list),
|
name: await getDelegatedSignerName(list),
|
||||||
id,
|
id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
item.user.ndk = ndk;
|
item.user.ndk = _ndk;
|
||||||
|
|
||||||
store.set(id, item);
|
store.set(id, item);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/lib/types.ts
Normal file
4
src/lib/types.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export enum CofabKind {
|
||||||
|
Supplier = 30000,
|
||||||
|
Order = 30001
|
||||||
|
}
|
||||||
167
src/lib/utils/login.ts
Normal file
167
src/lib/utils/login.ts
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
import type NDK from '@nostr-dev-kit/ndk';
|
||||||
|
import {
|
||||||
|
NDKNip07Signer,
|
||||||
|
NDKNip46Signer,
|
||||||
|
NDKPrivateKeySigner,
|
||||||
|
NDKUser,
|
||||||
|
type Hexpubkey,
|
||||||
|
type NDKSigner
|
||||||
|
} from '@nostr-dev-kit/ndk';
|
||||||
|
import { bunkerNDK, ndk } from '$lib/stores/nostr';
|
||||||
|
import { currentUser } from '$lib/store';
|
||||||
|
import { loginState } from '$lib/stores/sesson';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
|
export type LoginMethod = 'none' | 'pk' | 'nip07' | 'nip46';
|
||||||
|
|
||||||
|
let $ndk: NDK;
|
||||||
|
const $bunkerNDK: NDK = get(bunkerNDK);
|
||||||
|
|
||||||
|
|
||||||
|
export async function login(method: LoginMethod, userPubkey?: string): Promise<NDKUser | null> {
|
||||||
|
console.debug(`logging in with ${method}`);
|
||||||
|
let u: NDKUser | null | undefined;
|
||||||
|
$ndk = get(ndk);
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case 'none':
|
||||||
|
loginState.set(null);
|
||||||
|
return null;
|
||||||
|
case 'pk':
|
||||||
|
return await pkLogin();
|
||||||
|
case 'nip07':
|
||||||
|
u = await nip07Login($ndk);
|
||||||
|
console.debug('Logged in as: ', u);
|
||||||
|
loginState.set('logged-in');
|
||||||
|
return u;
|
||||||
|
case 'nip46':
|
||||||
|
return await nip46Login(userPubkey);
|
||||||
|
default: {
|
||||||
|
const promise = new Promise<NDKUser | null>((resolve) => {
|
||||||
|
let loadAttempts = 0;
|
||||||
|
const loadNip07Interval = setInterval(async () => {
|
||||||
|
if (window.nostr) {
|
||||||
|
clearInterval(loadNip07Interval);
|
||||||
|
const user = await nip07Login($ndk);
|
||||||
|
resolve(user);
|
||||||
|
}
|
||||||
|
if (loadAttempts++ > 10) clearInterval(loadNip07Interval);
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pkLogin(): Promise<NDKUser | null> {
|
||||||
|
const key = localStorage.getItem('nostr-key');
|
||||||
|
if (!key) return null;
|
||||||
|
else return await pkSignin(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pkSignin(key: string): Promise<NDKUser | null> {
|
||||||
|
const signer = new NDKPrivateKeySigner(key);
|
||||||
|
const user = await signer.user();
|
||||||
|
if (user) loggedIn(signer, user!, 'pk');
|
||||||
|
await user.fetchProfile();
|
||||||
|
currentUser.set(user);
|
||||||
|
sessionStorage.setItem('user', JSON.stringify(user));
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function nip07Login(ndk: NDK): Promise<NDKUser | null> {
|
||||||
|
const storedNpub = browser ? localStorage.getItem('pubkey') : '';
|
||||||
|
let user: NDKUser | null = null;
|
||||||
|
|
||||||
|
if (storedNpub) {
|
||||||
|
user = new NDKUser({ npub: storedNpub });
|
||||||
|
user.ndk = ndk;
|
||||||
|
console.debug('Nip07 - logging in with stored npub', storedNpub);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.nostr) {
|
||||||
|
try {
|
||||||
|
ndk.signer = new NDKNip07Signer();
|
||||||
|
user = await ndk.signer?.blockUntilReady();
|
||||||
|
user.ndk = ndk;
|
||||||
|
user.fetchProfile();
|
||||||
|
ndk.activeUser = user;
|
||||||
|
user.ndk = ndk;
|
||||||
|
console.debug('Nip07 Login user:', user);
|
||||||
|
console.debug('NDK: ', ndk);
|
||||||
|
if (user) localStorage.setItem('nostr-key-method', 'nip07');
|
||||||
|
localStorage.setItem('pubkey', user.pubkey);
|
||||||
|
await user.fetchProfile();
|
||||||
|
currentUser.set(user);
|
||||||
|
sessionStorage.setItem('user', JSON.stringify(user));
|
||||||
|
$ndk = ndk;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`NIP-07 login error: ${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (user) await user.fetchProfile();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function nip46Login(remotePubkey?: Hexpubkey): Promise<NDKUser | null> {
|
||||||
|
const existingPrivateKey = localStorage.getItem('nostr-nsecbunker-key')!;
|
||||||
|
let remoteUser: NDKUser | undefined;
|
||||||
|
|
||||||
|
console.debug({ existingPrivateKey, remotePubkey });
|
||||||
|
|
||||||
|
if (!existingPrivateKey) return null;
|
||||||
|
|
||||||
|
if (remotePubkey) remoteUser = $ndk.getUser({ pubkey: remotePubkey });
|
||||||
|
|
||||||
|
if (!remoteUser) return null;
|
||||||
|
|
||||||
|
currentUser.set(remoteUser);
|
||||||
|
|
||||||
|
console.debug('NIP46 setting user: ', remoteUser);
|
||||||
|
|
||||||
|
$bunkerNDK.pool.on('relay:ready', async () => {
|
||||||
|
console.debug('bunker relay ready');
|
||||||
|
loginState.set('contacting-remote-signer');
|
||||||
|
await nip46SignIn(existingPrivateKey, remoteUser!);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.debug('connecting to nsecbunker relay');
|
||||||
|
$bunkerNDK.connect(2500);
|
||||||
|
return remoteUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function nip46SignIn(existingPrivateKey: string, remoteUser: NDKUser) {
|
||||||
|
remoteUser.ndk = $bunkerNDK;
|
||||||
|
let localSigner: NDKPrivateKeySigner | null = null;
|
||||||
|
|
||||||
|
if (existingPrivateKey) localSigner = new NDKPrivateKeySigner(existingPrivateKey);
|
||||||
|
else {
|
||||||
|
alert('Local signer not available');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const remoteSigner = new NDKNip46Signer($bunkerNDK, remoteUser.pubkey, localSigner!);
|
||||||
|
|
||||||
|
console.debug('contacting remote signer');
|
||||||
|
remoteSigner.blockUntilReady();
|
||||||
|
console.debug('Remote signer connected');
|
||||||
|
|
||||||
|
localStorage.setItem('nostr-nsecbunker-key', localSigner.privateKey!);
|
||||||
|
|
||||||
|
loggedIn(remoteSigner, remoteUser, 'nip46');
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function loggedIn(signer: NDKSigner, u: NDKUser, method: LoginMethod) {
|
||||||
|
const _ndk = get(ndk);
|
||||||
|
_ndk.signer = signer;
|
||||||
|
u.ndk = _ndk;
|
||||||
|
await u.fetchProfile();
|
||||||
|
currentUser.set(u);
|
||||||
|
_ndk.activeUser = u;
|
||||||
|
console.log('DEBUG setting user (loggedIn)', u);
|
||||||
|
loginState.set('logged-in');
|
||||||
|
|
||||||
|
localStorage.setItem('pubkey', u.pubkey);
|
||||||
|
localStorage.setItem('nostr-key-method', method);
|
||||||
|
}
|
||||||
0
src/lib/utils/modal.ts
Normal file
0
src/lib/utils/modal.ts
Normal file
@@ -1,11 +1,24 @@
|
|||||||
<nav>
|
<script lang="ts">
|
||||||
<ul>
|
import NavBar from '$lib/components/NavBar.svelte';
|
||||||
<li><h1>Welcome to CoFabricate</h1></li>
|
import LoginModal from '$lib/components/LoginModal/Modal.svelte';
|
||||||
</ul>
|
import { login } from "$lib/utils/login";
|
||||||
<ul>
|
import { browserSetup } from "./browser-setup";
|
||||||
<li><a href="/">Home</a></li>
|
import { onMount } from 'svelte';
|
||||||
<li><a href="/about">About</a></li>
|
|
||||||
<li><a href="/login">Sign In</a></li>
|
let modalActive = false;
|
||||||
</ul>
|
|
||||||
</nav>
|
onMount(async () => {
|
||||||
|
await signIn();
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleModal() {
|
||||||
|
modalActive=!modalActive;
|
||||||
|
}
|
||||||
|
async function signIn() {
|
||||||
|
browserSetup();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<NavBar on:signin={toggleModal} />
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
<LoginModal active={modalActive} on:toggleModal={toggleModal} />
|
||||||
|
|||||||
5
src/routes/+page.server.ts
Normal file
5
src/routes/+page.server.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// import {ndk} from "$lib/stores/nostr";
|
||||||
|
|
||||||
|
// export function load({params}) {
|
||||||
|
// return ndk;
|
||||||
|
// }
|
||||||
@@ -1,5 +1,31 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
const img = 'https://picsum.photos/800/500';
|
||||||
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>Decentralized Manufacturing</title>
|
<title>Decentralized Manufacturing</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<h1>Home</h1>
|
<p>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
|
||||||
|
labore et dolore magna aliqua. Consequat id porta nibh venenatis cras sed felis eget. Fermentum et
|
||||||
|
sollicitudin ac orci phasellus egestas tellus rutrum tellus. Lobortis mattis aliquam faucibus
|
||||||
|
purus in massa tempor nec. In nisl nisi scelerisque eu ultrices vitae. Dui sapien eget mi proin
|
||||||
|
sed libero enim. Pharetra massa massa ultricies mi quis. Quam viverra orci sagittis eu volutpat
|
||||||
|
odio. Et malesuada fames ac turpis egestas integer eget. Tellus elementum sagittis vitae et leo.
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipiscing elit pellentesque. Nulla posuere sollicitudin
|
||||||
|
aliquam ultrices sagittis orci a scelerisque purus.
|
||||||
|
</p>
|
||||||
|
<img src={img} alt="placeholder" />
|
||||||
|
<p>
|
||||||
|
Imperdiet dui accumsan sit amet nulla. At erat pellentesque adipiscing commodo elit at. Eu mi
|
||||||
|
bibendum neque egestas. Leo vel orci porta non pulvinar neque laoreet. Quam pellentesque nec nam
|
||||||
|
aliquam sem et tortor consequat. Blandit volutpat maecenas volutpat blandit. Praesent semper
|
||||||
|
feugiat nibh sed pulvinar proin gravida hendrerit lectus. Malesuada proin libero nunc consequat
|
||||||
|
interdum. Risus pretium quam vulputate dignissim. Sollicitudin nibh sit amet commodo nulla. Et
|
||||||
|
netus et malesuada fames ac turpis egestas sed. Enim sed faucibus turpis in eu mi bibendum neque.
|
||||||
|
Blandit massa enim nec dui nunc. Aliquam ultrices sagittis orci a scelerisque purus. Pharetra diam
|
||||||
|
sit amet nisl suscipit adipiscing bibendum. Lorem donec massa sapien faucibus et molestie. Enim
|
||||||
|
tortor at auctor urna nunc id cursus metus. A erat nam at lectus urna duis convallis convallis.
|
||||||
|
Tempor id eu nisl nunc mi ipsum.
|
||||||
|
</p>
|
||||||
|
|||||||
22
src/routes/[id]/(profile)/+layout.svelte
Normal file
22
src/routes/[id]/(profile)/+layout.svelte
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import { ndk } from "$lib/stores/nostr";
|
||||||
|
import type NDK from "@nostr-dev-kit/ndk";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
|
let id: string;
|
||||||
|
let { user } = $page.data;
|
||||||
|
let _ndk: NDK;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
_ndk = get(ndk);
|
||||||
|
})
|
||||||
|
|
||||||
|
$: if (id !== $page.params.id){
|
||||||
|
id = $page.params.id;
|
||||||
|
user.ndk = _ndk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
22
src/routes/[id]/(profile)/+page.svelte
Normal file
22
src/routes/[id]/(profile)/+page.svelte
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import { ndk } from "$lib/stores/nostr";
|
||||||
|
import type NDK from "@nostr-dev-kit/ndk";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
|
let id: string;
|
||||||
|
let { user } = $page.data;
|
||||||
|
let _ndk: NDK;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
_ndk = get(ndk);
|
||||||
|
})
|
||||||
|
|
||||||
|
$: if (id !== $page.params.id){
|
||||||
|
id = $page.params.id;
|
||||||
|
user.ndk = _ndk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
4
src/routes/[id]/+layout.svelte
Normal file
4
src/routes/[id]/+layout.svelte
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import type { NDKUser } from "@nostr-dev-kit/ndk";
|
||||||
|
</script>
|
||||||
48
src/routes/browser-setup.ts
Normal file
48
src/routes/browser-setup.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { loginState } from '$lib/stores/sesson';
|
||||||
|
import { loggedIn, login, type LoginMethod } from '$lib/utils/login';
|
||||||
|
import { ndk } from '$lib/stores/nostr';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import { currentUser } from '$lib/store';
|
||||||
|
import { NDKNip07Signer, NDKUser } from '@nostr-dev-kit/ndk';
|
||||||
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
|
const _ndk = get(ndk);
|
||||||
|
|
||||||
|
export async function browserSetup() {
|
||||||
|
const pubkey = browser ? localStorage.getItem('pubkey') : '';
|
||||||
|
|
||||||
|
if (pubkey) {
|
||||||
|
const u = _ndk.getUser({ pubkey });
|
||||||
|
u.fetchProfile();
|
||||||
|
loginState.set('logging-in');
|
||||||
|
currentUser.set(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
const method = localStorage.getItem('nostr-key-method') as LoginMethod;
|
||||||
|
|
||||||
|
if (!pubkey && method !== 'none') return newSessionTryNip07();
|
||||||
|
|
||||||
|
if (method && pubkey) {
|
||||||
|
console.debug(`logging in with ${method} as ${pubkey}`);
|
||||||
|
return await login(method, pubkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function newSessionTryNip07() {
|
||||||
|
let signer: NDKNip07Signer | undefined;
|
||||||
|
let u: NDKUser | null | undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.debug('trying nip07 signer');
|
||||||
|
signer = new NDKNip07Signer();
|
||||||
|
u = await signer.blockUntilReady();
|
||||||
|
u.fetchProfile();
|
||||||
|
} catch (e) {
|
||||||
|
console.debug('nip07Signer failed', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u && signer) {
|
||||||
|
console.debug('nip07Signer succeeded');
|
||||||
|
await loggedIn(signer, u, 'nip07');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,4 +2,4 @@
|
|||||||
<title>Log In</title>
|
<title>Log In</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<p>Log In</p>n
|
<p>Log In</p>
|
||||||
@@ -11,7 +11,12 @@ const config = {
|
|||||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||||
adapter: adapter()
|
adapter: adapter(),
|
||||||
|
alias: {
|
||||||
|
$lib: 'src/lib',
|
||||||
|
$utils: 'src/lib/utils',
|
||||||
|
$comp: 'src/lib/components'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user