mirror of
https://github.com/edufeed-org/polloer.git
synced 2025-12-10 00:34:31 +00:00
add basic reactions
This commit is contained in:
parent
7a0d33fa9d
commit
bc23755758
6 changed files with 185 additions and 62 deletions
81
package-lock.json
generated
81
package-lock.json
generated
|
|
@ -11,7 +11,9 @@
|
||||||
"@nostr-dev-kit/ndk": "^2.14.5",
|
"@nostr-dev-kit/ndk": "^2.14.5",
|
||||||
"@nostr-dev-kit/ndk-svelte": "^2.4.10",
|
"@nostr-dev-kit/ndk-svelte": "^2.4.10",
|
||||||
"daisyui": "^5.0.28",
|
"daisyui": "^5.0.28",
|
||||||
"qrcode": "^1.5.4"
|
"emoji-picker-element": "^1.26.3",
|
||||||
|
"qrcode": "^1.5.4",
|
||||||
|
"svelte-emoji-selector": "^1.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.2.5",
|
"@eslint/compat": "^1.2.5",
|
||||||
|
|
@ -603,6 +605,39 @@
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fortawesome/fontawesome-common-types": {
|
||||||
|
"version": "0.2.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
|
||||||
|
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/free-regular-svg-icons": {
|
||||||
|
"version": "5.15.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz",
|
||||||
|
"integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/free-solid-svg-icons": {
|
||||||
|
"version": "5.15.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
|
||||||
|
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanfs/core": {
|
"node_modules/@humanfs/core": {
|
||||||
"version": "0.19.1",
|
"version": "0.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||||
|
|
@ -1814,6 +1849,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
|
||||||
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
|
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/emoji-picker-element": {
|
||||||
|
"version": "1.26.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-picker-element/-/emoji-picker-element-1.26.3.tgz",
|
||||||
|
"integrity": "sha512-fOMG44d/3OqTe1pPqlu5H4ZtWg7gK4Le6Bt24JTKtDyce5+EO3Mo8WA95cKHbPSsSsg7ehM12M1x3Y6U6fgvTQ=="
|
||||||
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
|
@ -2088,6 +2128,11 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fa-svelte": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fa-svelte/-/fa-svelte-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-RqBOWwt7sc+ta9GFjbu5GOwKFRzn3rMPPSqvSGpIwsfVnpMjiI5ttv84lwNsCMEYI6/lu/iH21HUcE3TLz8RGQ=="
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
|
|
@ -2930,6 +2975,16 @@
|
||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/popper.js": {
|
||||||
|
"version": "1.16.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
||||||
|
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
|
||||||
|
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/popperjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.3",
|
"version": "8.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
||||||
|
|
@ -3446,6 +3501,25 @@
|
||||||
"typescript": ">=5.0.0"
|
"typescript": ">=5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-click-outside": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-click-outside/-/svelte-click-outside-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-TVDn5Vd8L0WI0Y9BFh/2I7judkIqYCbFKkGwGl/f8D0inwBFNyU0weKhrbJY4VQtYnWriq0NPl+mIYGisgALbw=="
|
||||||
|
},
|
||||||
|
"node_modules/svelte-emoji-selector": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-emoji-selector/-/svelte-emoji-selector-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-gGjDydt+79YQIdUyz/r1sHSkjLko2rb9qHNiBveC5RSl6rJ0mob4T5DrADRArjQ/HA8kNfEJFyqbnLoA+dyLqA==",
|
||||||
|
"deprecated": "This package is no longer supported",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^5.10.1",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^5.10.1",
|
||||||
|
"fa-svelte": "^3.0.0",
|
||||||
|
"popper.js": "^1.15.0",
|
||||||
|
"svelte-click-outside": "^1.0.0",
|
||||||
|
"svelte-tabs": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/svelte-eslint-parser": {
|
"node_modules/svelte-eslint-parser": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.3.tgz",
|
||||||
|
|
@ -3474,6 +3548,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-tabs": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-tabs/-/svelte-tabs-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-bCynxgET2uvqpB6xf/dVyqHjzmumRURQyh2QqXlrki8NxzO7h2WghF8qgpb5qeB5NTX1bMU+9Q5Hf5ey2WLaMg=="
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.4.tgz",
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@
|
||||||
"@nostr-dev-kit/ndk": "^2.14.5",
|
"@nostr-dev-kit/ndk": "^2.14.5",
|
||||||
"@nostr-dev-kit/ndk-svelte": "^2.4.10",
|
"@nostr-dev-kit/ndk-svelte": "^2.4.10",
|
||||||
"daisyui": "^5.0.28",
|
"daisyui": "^5.0.28",
|
||||||
"qrcode": "^1.5.4"
|
"emoji-picker-element": "^1.26.3",
|
||||||
|
"qrcode": "^1.5.4",
|
||||||
|
"svelte-emoji-selector": "^1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,43 @@
|
||||||
<script>
|
<script>
|
||||||
export let event;
|
let { event } = $props();
|
||||||
|
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||||
|
import { ndk, ndkReady, user } from '$lib/stores';
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
import { login } from '$lib';
|
||||||
|
|
||||||
|
let reactions = writable([]);
|
||||||
|
|
||||||
|
async function sendReaction() {
|
||||||
|
const reactionEvent = new NDKEvent($ndk, {
|
||||||
|
kind: 7,
|
||||||
|
content: '👍',
|
||||||
|
tags: [['e', event.id]]
|
||||||
|
});
|
||||||
|
await reactionEvent.publish();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (!$user) {
|
||||||
|
console.log('no user, logging in');
|
||||||
|
login();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if ($ndkReady) {
|
||||||
|
const sub = $ndk.subscribe({ kinds: [7], '#e': [event.id] });
|
||||||
|
sub.on('event', (e) => {
|
||||||
|
$reactions = [...$reactions, e];
|
||||||
|
console.log(`${e.content}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div class="w-full border p-2">
|
||||||
<p>{event.content}</p>
|
<p>{event.content}</p>
|
||||||
|
<button onclick={() => sendReaction()}>👍</button>
|
||||||
|
<p>Reaction Count: {$reactions.length}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1 +1,35 @@
|
||||||
// place files you want to import through the `$lib` alias in this folder.
|
import { NDKNip07Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||||
|
import { ndk as ndkStore, user as userStore } from "$lib/stores";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
|
export async function login() {
|
||||||
|
let ndk = get(ndkStore)
|
||||||
|
let user = get(userStore)
|
||||||
|
if (window.nostr) {
|
||||||
|
const signer = new NDKNip07Signer();
|
||||||
|
ndk.signer = signer;
|
||||||
|
const signedUser = await signer.user();
|
||||||
|
userStore.set(signedUser)
|
||||||
|
} else {
|
||||||
|
const storedPrivateKey = window.localStorage.getItem('nostrPrivateKey');
|
||||||
|
if (storedPrivateKey) {
|
||||||
|
const privateKey = JSON.parse(storedPrivateKey);
|
||||||
|
console.log("stored private key", privateKey)
|
||||||
|
const signer = new NDKPrivateKeySigner(privateKey);
|
||||||
|
ndk.signer = signer;
|
||||||
|
const signedUser = await signer.user();
|
||||||
|
userStore.set(signedUser)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log('No private key found, generating a new one...');
|
||||||
|
const privateKey = NDKPrivateKeySigner.generate();
|
||||||
|
const signer = new NDKPrivateKeySigner(privateKey.privateKey);
|
||||||
|
console.log('Generated Private Key:', privateKey);
|
||||||
|
ndk.signer = signer;
|
||||||
|
const signedUser = await signer.user();
|
||||||
|
userStore.set(signedUser)
|
||||||
|
|
||||||
|
window.localStorage.setItem('nostrPrivateKey', JSON.stringify(privateKey.privateKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
import { NDKEvent, NDKNip07Signer, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk';
|
import { NDKEvent, NDKNip07Signer, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk';
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
import QRCode from 'qrcode';
|
import QRCode from 'qrcode';
|
||||||
|
import { login } from '$lib';
|
||||||
|
|
||||||
let question = '';
|
let question = '';
|
||||||
let questionId = writable(''); ;
|
let questionId = writable(''); ;
|
||||||
|
|
@ -49,30 +50,6 @@
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function login() {
|
|
||||||
if (window.nostr) {
|
|
||||||
const signer = new NDKNip07Signer();
|
|
||||||
$ndk.signer = signer;
|
|
||||||
$user = await signer.user();
|
|
||||||
} else {
|
|
||||||
const storedPrivateKey = window.localStorage.getItem('nostrPrivateKey');
|
|
||||||
if (storedPrivateKey) {
|
|
||||||
const privateKey = JSON.parse(storedPrivateKey);
|
|
||||||
console.log("stored private key", privateKey)
|
|
||||||
const signer = new NDKPrivateKeySigner(privateKey);
|
|
||||||
$ndk.signer = signer;
|
|
||||||
$user = await signer.user();
|
|
||||||
} else {
|
|
||||||
console.log('No private key found, generating a new one...');
|
|
||||||
const privateKey = NDKPrivateKeySigner.generate();
|
|
||||||
const signer = new NDKPrivateKeySigner(privateKey.privateKey);
|
|
||||||
console.log('Generated Private Key:', privateKey);
|
|
||||||
$ndk.signer = signer;
|
|
||||||
$user = await signer.user();
|
|
||||||
window.localStorage.setItem('nostrPrivateKey', JSON.stringify(privateKey.privateKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if ($ndkReady) {
|
if ($ndkReady) {
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,18 @@
|
||||||
const commentEvent = new NDKEvent($ndk, {
|
const commentEvent = new NDKEvent($ndk, {
|
||||||
kind: 2222,
|
kind: 2222,
|
||||||
content: comment,
|
content: comment,
|
||||||
tags: [["E", data.id]]
|
tags: [['E', data.id]]
|
||||||
});
|
});
|
||||||
commentEvent.publish();
|
commentEvent.publish();
|
||||||
}
|
}
|
||||||
|
|
||||||
let comment = ""
|
let comment = '';
|
||||||
let comments = writable([]);
|
let comments = writable([]);
|
||||||
let question = writable("")
|
let question = writable('');
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if ($ndkReady) {
|
if ($ndkReady) {
|
||||||
const sub = $ndk.subscribe({ kinds: [2222], "#E": [data.id] });
|
const sub = $ndk.subscribe({ kinds: [2222], '#E': [data.id] });
|
||||||
sub.on('event', (event) => {
|
sub.on('event', (event) => {
|
||||||
$comments = [...$comments, event];
|
$comments = [...$comments, event];
|
||||||
console.log(`${event.content}`);
|
console.log(`${event.content}`);
|
||||||
|
|
@ -31,33 +31,28 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full flex flex-col justify-center mx-auto items-center">
|
<div class="mx-auto flex flex-col items-center justify-center w-3/4">
|
||||||
|
{#await $ndk.fetchEvent(data.id) then question}
|
||||||
<h1 class="">Identifier: {data.id}</h1>
|
|
||||||
<div>{@html data.id}</div>
|
|
||||||
|
|
||||||
{#await $ndk.fetchEvent(data.id) then question}
|
|
||||||
{#if question}
|
{#if question}
|
||||||
<div class="mb-4 w-full rounded border p-2">
|
<div class="mb-4 w-full rounded border p-2">
|
||||||
<h2>Question: {question.content}</h2>
|
<h2>Question: {question.content}</h2>
|
||||||
<p>Tags: {question.tags}</p>
|
|
||||||
<p>Created At: {new Date(question.created_at * 1000).toLocaleString()}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
|
<div class="w-full flex flex-col items-center justify-center gap-2 mb-2">
|
||||||
<h1 class="text-xl">Ideensammlung</h1>
|
<h1 class="text-xl">Ideensammlung</h1>
|
||||||
<textarea bind:value={comment} placeholder="Mein Kommentar"></textarea>
|
<textarea class="w-full border" bind:value={comment} placeholder="Mein Kommentar"></textarea>
|
||||||
<button class="btn btn-error" onclick={() => submitComment()}>Absenden</button>
|
<button class="btn btn-success" onclick={() => submitComment()}>Absenden</button>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<p>Loading...</p>
|
<p>Loading...</p>
|
||||||
{/if}
|
{/if}
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<p>Error fetching question: {error.message}</p>
|
<p>Error fetching question: {error.message}</p>
|
||||||
{/await}
|
{/await}
|
||||||
|
|
||||||
{#each $comments as event}
|
<div class="mx-auto flex w-full flex-col items-center justify-center gap-2">
|
||||||
|
{#each $comments as event}
|
||||||
<Comment {event} />
|
<Comment {event} />
|
||||||
{/each}
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue