@threenine/nuxstr-comments 1.5.0 → 1.5.2
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 +30 -25
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -2
- package/dist/runtime/components/CommentView.d.vue.ts +1 -1
- package/dist/runtime/components/CommentView.vue +13 -9
- package/dist/runtime/components/CommentView.vue.d.ts +1 -1
- package/dist/runtime/components/NuxstrComments.vue +2 -2
- package/dist/runtime/components/PostComment.vue +1 -1
- package/dist/runtime/components/PostReply.vue +4 -4
- package/dist/runtime/components/{CommentCommandBar.vue → ReplyButton.vue} +13 -11
- package/dist/runtime/components/ReplyView.vue +4 -2
- package/dist/runtime/composables/useComments.d.ts +6 -20
- package/dist/runtime/composables/useComments.js +18 -8
- package/dist/runtime/composables/useNuxstr.d.ts +5 -4
- package/dist/runtime/composables/useNuxstr.js +18 -12
- package/dist/runtime/composables/useReplies.d.ts +2 -2
- package/dist/runtime/composables/useReplies.js +6 -12
- package/package.json +5 -5
- /package/dist/runtime/components/{CommentCommandBar.d.vue.ts → ReplyButton.d.vue.ts} +0 -0
- /package/dist/runtime/components/{CommentCommandBar.vue.d.ts → ReplyButton.vue.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -38,38 +38,43 @@ npx nuxi module add @threenine/nuxstr-comments
|
|
|
38
38
|
That's it! You can now use Nuxstr Comments in your Nuxt app ✨
|
|
39
39
|
|
|
40
40
|
### Usage
|
|
41
|
-
|
|
42
|
-
1. Ensure @nuxt/content is enabled and your blog post pages use ContentDoc or render content files.
|
|
43
|
-
2. Add the comments component where you want comments to appear (usually below a ContentDoc):
|
|
44
|
-
|
|
45
|
-
```vue
|
|
46
|
-
<template>
|
|
47
|
-
<div>
|
|
48
|
-
<ContentDoc />
|
|
49
|
-
<NuxstrComments />
|
|
50
|
-
</div>
|
|
51
|
-
</template>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
41
|
By default, the component tags comments by the current route path (e.g., content:/blog/my-post) and fetches them from configured relays.
|
|
55
42
|
|
|
56
|
-
|
|
43
|
+
1. Configuration (nuxt.config.ts):
|
|
57
44
|
|
|
58
45
|
```ts
|
|
59
46
|
export default defineNuxtConfig({
|
|
60
47
|
modules: [
|
|
61
|
-
'@nuxt/content',
|
|
62
48
|
'@threenine/nuxstr-comments',
|
|
63
49
|
],
|
|
64
50
|
nuxstrComments: {
|
|
65
51
|
relays: ['wss://relay.damus.io', 'wss://relay.nostr.band'],
|
|
66
52
|
tagStrategy: 'path',
|
|
67
|
-
tagPrefix: '
|
|
53
|
+
tagPrefix: 'comment:',
|
|
68
54
|
},
|
|
69
55
|
})
|
|
70
56
|
```
|
|
71
57
|
|
|
72
|
-
|
|
58
|
+
|
|
59
|
+
2. Add the comments component where you want comments to appear (usually below a ContentDoc):
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<template>
|
|
63
|
+
<div>
|
|
64
|
+
<NuxstrComments />
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Select your preferred relays from the list of [relays](https://nostrwat.ch/) and configure the tag strategy and tag prefix.
|
|
70
|
+
|
|
71
|
+
When a user attempts to post, they will be prompted to log in with their Nostr browser extension [NIP-07](https://github.com/nostr-protocol/nips/blob/master/07.md).
|
|
72
|
+
|
|
73
|
+
Comments are published as kind: 1111 as defined in [NIP-22](https://github.com/nostr-protocol/nips/blob/master/22.md)
|
|
74
|
+
notes tagged with a `t` tag containing the content tag (e.g., `comment:/blog/my-post`).
|
|
75
|
+
|
|
76
|
+
Replys to comments are enabled, and are also published as kind: 1111, as defined in [NIP-22](https://github.com/nostr-protocol/nips/blob/master/22.md)
|
|
77
|
+
|
|
73
78
|
|
|
74
79
|
|
|
75
80
|
## Contribution
|
|
@@ -79,26 +84,26 @@ When a user attempts to post, they will be prompted to log in with their Nostr b
|
|
|
79
84
|
|
|
80
85
|
```bash
|
|
81
86
|
# Install dependencies
|
|
82
|
-
|
|
87
|
+
pnpm install
|
|
83
88
|
|
|
84
89
|
# Generate type stubs
|
|
85
|
-
|
|
90
|
+
pnpm run dev:prepare
|
|
86
91
|
|
|
87
92
|
# Develop with the playground
|
|
88
|
-
|
|
93
|
+
pnpm run dev
|
|
89
94
|
|
|
90
95
|
# Build the playground
|
|
91
|
-
|
|
96
|
+
pnpm run dev:build
|
|
92
97
|
|
|
93
98
|
# Run ESLint
|
|
94
|
-
|
|
99
|
+
pnpm run lint
|
|
95
100
|
|
|
96
101
|
# Run Vitest
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
pnpm run test
|
|
103
|
+
pnpm run test:watch
|
|
99
104
|
|
|
100
105
|
# Release new version
|
|
101
|
-
|
|
106
|
+
pnpm run release
|
|
102
107
|
```
|
|
103
108
|
|
|
104
109
|
</details>
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -55,8 +55,8 @@ const module = defineNuxtModule({
|
|
|
55
55
|
filePath: resolver.resolve("./runtime/components/ScaffoldComment.vue")
|
|
56
56
|
});
|
|
57
57
|
addComponent({
|
|
58
|
-
name: "
|
|
59
|
-
filePath: resolver.resolve("./runtime/components/
|
|
58
|
+
name: "ReplyButton",
|
|
59
|
+
filePath: resolver.resolve("./runtime/components/ReplyButton.vue")
|
|
60
60
|
});
|
|
61
61
|
addComponent({
|
|
62
62
|
name: "CommentView",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
content: string;
|
|
3
|
-
id
|
|
3
|
+
id: string;
|
|
4
4
|
};
|
|
5
5
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
6
|
export default _default;
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { onMounted } from "vue";
|
|
2
3
|
import { marked } from "marked";
|
|
3
4
|
const props = defineProps({
|
|
4
5
|
content: { type: String, required: true },
|
|
5
|
-
id: { type: String, required:
|
|
6
|
+
id: { type: String, required: true }
|
|
7
|
+
});
|
|
8
|
+
async function renderMarkdown(md) {
|
|
9
|
+
return marked.parse(md);
|
|
10
|
+
}
|
|
11
|
+
onMounted(async () => {
|
|
12
|
+
const targetEl = document.getElementById("comment-content");
|
|
13
|
+
if (!targetEl) return;
|
|
14
|
+
targetEl.innerHTML = await renderMarkdown(props.content);
|
|
6
15
|
});
|
|
7
16
|
</script>
|
|
8
17
|
|
|
9
18
|
<template>
|
|
10
|
-
<div class="
|
|
11
|
-
|
|
12
|
-
<
|
|
13
|
-
class="mb-4"
|
|
14
|
-
v-html="marked.parse(props.content)"
|
|
15
|
-
/>
|
|
16
|
-
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
17
|
-
<comment-command-bar :content-id="props.id" />
|
|
19
|
+
<div class="mt-2 mb-2">
|
|
20
|
+
<div id="comment-content" />
|
|
21
|
+
<ReplyButton :content-id="props.id" />
|
|
18
22
|
</div>
|
|
19
23
|
</template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
content: string;
|
|
3
|
-
id
|
|
3
|
+
id: string;
|
|
4
4
|
};
|
|
5
5
|
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
6
|
export default _default;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { onMounted } from "vue";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import useNuxstr from "../composables/useNuxstr";
|
|
4
|
+
import useComments from "../composables/useComments";
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
contentId: { type: String, required: false }
|
|
7
7
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import
|
|
2
|
+
import useReplies from "../composables/useReplies";
|
|
3
3
|
import { ref } from "vue";
|
|
4
4
|
const props = defineProps({
|
|
5
5
|
rootId: { type: String, required: true }
|
|
@@ -23,7 +23,7 @@ async function postReply(comment) {
|
|
|
23
23
|
</script>
|
|
24
24
|
|
|
25
25
|
<template>
|
|
26
|
-
<div class="text-sm text-muted-foreground mt-
|
|
26
|
+
<div class="text-sm text-muted-foreground mt-4 p-6">
|
|
27
27
|
<div class="flex gap-2">
|
|
28
28
|
<div class="flex-1">
|
|
29
29
|
<UTextarea
|
|
@@ -33,13 +33,13 @@ async function postReply(comment) {
|
|
|
33
33
|
:rows="4"
|
|
34
34
|
/>
|
|
35
35
|
</div>
|
|
36
|
-
<div class="flex flex-col justify-center items-
|
|
36
|
+
<div class="flex flex-col justify-center items-centerp-2">
|
|
37
37
|
<UButton
|
|
38
38
|
icon="mingcute:send-line"
|
|
39
39
|
size="xl"
|
|
40
40
|
color="primary"
|
|
41
41
|
variant="solid"
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
@click="postReply(content)"
|
|
44
44
|
/>
|
|
45
45
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { onMounted, ref } from "vue";
|
|
2
|
+
import useNuxstr from "../composables/useNuxstr";
|
|
3
|
+
import useReplies from "../composables/useReplies";
|
|
4
|
+
import { computed, onMounted, ref } from "vue";
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
contentId: { type: String, required: true }
|
|
7
7
|
});
|
|
@@ -14,42 +14,44 @@ function toggleReply() {
|
|
|
14
14
|
onMounted(() => {
|
|
15
15
|
subscribeReplies();
|
|
16
16
|
});
|
|
17
|
+
const showChip = computed(() => replies.value.length > 0);
|
|
17
18
|
</script>
|
|
18
19
|
|
|
19
20
|
<template>
|
|
20
21
|
<div>
|
|
21
|
-
<div class="flex items-center gap-4 mx-auto mt-
|
|
22
|
+
<div class="flex items-center gap-4 mx-auto mt-2 mb-1">
|
|
22
23
|
<u-chip
|
|
24
|
+
:show="showChip"
|
|
23
25
|
:text="replies.length"
|
|
24
26
|
size="3xl"
|
|
25
27
|
inset
|
|
26
28
|
>
|
|
27
29
|
<u-button
|
|
28
|
-
variant="
|
|
30
|
+
variant="subtle"
|
|
29
31
|
icon="mdi:message-reply-text-outline"
|
|
30
32
|
title="Reply"
|
|
31
|
-
|
|
33
|
+
color="primary"
|
|
32
34
|
class="rounded-full hover:bg-gray-900"
|
|
33
35
|
@click="toggleReply"
|
|
34
36
|
/>
|
|
35
37
|
</u-chip>
|
|
36
38
|
</div>
|
|
37
|
-
<
|
|
38
|
-
class="flex flex-col gap-2 w-48 p-
|
|
39
|
+
<u-collapsible
|
|
40
|
+
class="flex flex-col gap-2 w-48 p-4"
|
|
39
41
|
:open
|
|
40
42
|
>
|
|
41
43
|
<template #content>
|
|
42
|
-
<div>
|
|
44
|
+
<div class="space-y-4">
|
|
43
45
|
<reply-view :replies="replies" />
|
|
44
46
|
</div>
|
|
45
47
|
|
|
46
48
|
<div
|
|
47
49
|
v-if="isLoggedIn"
|
|
48
|
-
class="mt-
|
|
50
|
+
class="mt-2"
|
|
49
51
|
>
|
|
50
52
|
<post-reply :root-id="props.contentId" />
|
|
51
53
|
</div>
|
|
52
54
|
</template>
|
|
53
|
-
</
|
|
55
|
+
</u-collapsible>
|
|
54
56
|
</div>
|
|
55
57
|
</template>
|
|
@@ -9,14 +9,16 @@ const props = defineProps({
|
|
|
9
9
|
<div
|
|
10
10
|
v-for="reply in props.replies"
|
|
11
11
|
:key="reply.id"
|
|
12
|
-
class="rounded border
|
|
12
|
+
class="rounded-md border p-3 mt-2 mb-2"
|
|
13
13
|
>
|
|
14
14
|
<div>
|
|
15
15
|
<comment-author
|
|
16
16
|
:profile="reply.profile"
|
|
17
17
|
:created-at="reply.created_at"
|
|
18
18
|
/>
|
|
19
|
-
<p
|
|
19
|
+
<p class="p-2 text-base">
|
|
20
|
+
{{ reply.content }}
|
|
21
|
+
</p>
|
|
20
22
|
</div>
|
|
21
23
|
</div>
|
|
22
24
|
</div>
|
|
@@ -1,23 +1,8 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
loading:
|
|
4
|
-
error:
|
|
5
|
-
comments: import("vue").
|
|
6
|
-
id: string;
|
|
7
|
-
pubkey: string;
|
|
8
|
-
created_at: number;
|
|
9
|
-
content: string;
|
|
10
|
-
profile?: {
|
|
11
|
-
pubkey: string;
|
|
12
|
-
display_name?: string | undefined;
|
|
13
|
-
about?: string | undefined;
|
|
14
|
-
image?: string | undefined;
|
|
15
|
-
nip05?: string | undefined;
|
|
16
|
-
lud06?: string | undefined;
|
|
17
|
-
lud16?: string | undefined;
|
|
18
|
-
website?: string | undefined;
|
|
19
|
-
} | undefined;
|
|
20
|
-
}[], Comment[] | {
|
|
1
|
+
import { type Ref, type UnwrapRef } from 'vue';
|
|
2
|
+
declare function useComments(customContentId?: string): {
|
|
3
|
+
loading: Ref<boolean, boolean>;
|
|
4
|
+
error: Ref<UnwrapRef<string | null>, UnwrapRef<string | null>>;
|
|
5
|
+
comments: import("vue").ComputedRef<{
|
|
21
6
|
id: string;
|
|
22
7
|
pubkey: string;
|
|
23
8
|
created_at: number;
|
|
@@ -37,3 +22,4 @@ export declare function useComments(customContentId?: string): {
|
|
|
37
22
|
subscribeComments: () => Promise<void>;
|
|
38
23
|
postComment: (comment: string) => Promise<boolean>;
|
|
39
24
|
};
|
|
25
|
+
export default useComments;
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { computed, ref } from "vue";
|
|
2
|
-
import { useRoute, useRuntimeConfig
|
|
3
|
-
import
|
|
2
|
+
import { useRequestURL, useRoute, useRuntimeConfig } from "#imports";
|
|
3
|
+
import useNuxstr from "./useNuxstr.js";
|
|
4
4
|
import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
|
|
5
|
-
|
|
5
|
+
function useComments(customContentId) {
|
|
6
6
|
const { ndk, connect, isLoggedIn, mapComment, pubkey, fetchProfile } = useNuxstr();
|
|
7
7
|
const route = useRoute();
|
|
8
8
|
const config = useRuntimeConfig();
|
|
9
9
|
const opts = config.public?.nuxstrComments || {};
|
|
10
10
|
const loading = ref(false);
|
|
11
11
|
const error = ref(null);
|
|
12
|
-
const
|
|
12
|
+
const commentsData = ref([]);
|
|
13
|
+
const comments = computed(() => {
|
|
14
|
+
return commentsData.value.slice().sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
|
|
15
|
+
});
|
|
13
16
|
const contentId = computed(() => {
|
|
14
17
|
if (customContentId) return customContentId;
|
|
15
18
|
return route.path;
|
|
@@ -27,12 +30,18 @@ export function useComments(customContentId) {
|
|
|
27
30
|
}
|
|
28
31
|
async function subscribeComments() {
|
|
29
32
|
await connect();
|
|
30
|
-
const filter = {
|
|
31
|
-
|
|
33
|
+
const filter = {
|
|
34
|
+
kinds: [NDKKind.GenericReply],
|
|
35
|
+
["#t"]: [tagValue()],
|
|
36
|
+
limit: 100,
|
|
37
|
+
["#k"]: ["web"],
|
|
38
|
+
["#A"]: [fullUrl(contentId.value)]
|
|
39
|
+
};
|
|
40
|
+
const sub = ndk.subscribe(filter);
|
|
32
41
|
sub.on("event", async (event) => {
|
|
33
42
|
const comment = mapComment(event);
|
|
34
43
|
comment.profile = await fetchProfile(event.pubkey);
|
|
35
|
-
|
|
44
|
+
commentsData.value.push(comment);
|
|
36
45
|
});
|
|
37
46
|
}
|
|
38
47
|
async function postComment(comment) {
|
|
@@ -58,9 +67,10 @@ export function useComments(customContentId) {
|
|
|
58
67
|
// Defined NIP 73
|
|
59
68
|
["K", "web"],
|
|
60
69
|
// Defined NIP 73,
|
|
61
|
-
["p", pubkey
|
|
70
|
+
["p", pubkey ?? ""]
|
|
62
71
|
];
|
|
63
72
|
return event;
|
|
64
73
|
}
|
|
65
74
|
return { loading, error, comments, isLoggedIn, subscribeComments, postComment };
|
|
66
75
|
}
|
|
76
|
+
export default useComments;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import NDK, { type NDKEvent } from '@nostr-dev-kit/ndk';
|
|
1
|
+
import NDK, { type NDKEvent, type NDKUserProfile } from '@nostr-dev-kit/ndk';
|
|
2
2
|
import type { Comment, Profile } from '../types/index.js';
|
|
3
|
-
|
|
3
|
+
declare function useNuxstr(): {
|
|
4
4
|
readonly ndk: NDK;
|
|
5
5
|
connect: () => Promise<NDK>;
|
|
6
6
|
login: () => Promise<void>;
|
|
7
7
|
logout: () => void;
|
|
8
8
|
isLoggedIn: import("vue").ComputedRef<boolean>;
|
|
9
|
-
pubkey:
|
|
10
|
-
mapProfile: (profile: NDKUserProfile) => Profile;
|
|
9
|
+
pubkey: string | undefined;
|
|
10
|
+
mapProfile: (profile: NDKUserProfile | null) => Profile;
|
|
11
11
|
mapComment: (event: NDKEvent) => Comment;
|
|
12
12
|
fetchProfile: (pubkey: string) => Promise<Profile | undefined>;
|
|
13
13
|
};
|
|
14
|
+
export default useNuxstr;
|
|
@@ -2,19 +2,21 @@ import { computed, ref } from "vue";
|
|
|
2
2
|
import { useRuntimeConfig } from "#imports";
|
|
3
3
|
import NDK, { NDKNip07Signer } from "@nostr-dev-kit/ndk";
|
|
4
4
|
import { useToast } from "#ui/composables/useToast";
|
|
5
|
-
|
|
5
|
+
function useNuxstr() {
|
|
6
|
+
const DEFAULT_PUBKEY = "";
|
|
6
7
|
const w = globalThis;
|
|
7
8
|
if (!w.__nuxstr) {
|
|
8
9
|
w.__nuxstr = {
|
|
9
10
|
ndk: null,
|
|
10
11
|
signer: null,
|
|
11
|
-
pubkey: ref(
|
|
12
|
+
pubkey: ref(DEFAULT_PUBKEY),
|
|
12
13
|
isConnecting: ref(false),
|
|
13
14
|
isConnected: ref(false),
|
|
14
|
-
userProfile: ref(
|
|
15
|
+
userProfile: ref(void 0)
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
const state = w.__nuxstr;
|
|
19
|
+
const DEFAULT_TIMESTAMP = 0;
|
|
18
20
|
const config = useRuntimeConfig();
|
|
19
21
|
const opts = config.public?.nuxstrComments || {};
|
|
20
22
|
function initializeNDK() {
|
|
@@ -52,13 +54,14 @@ export function useNuxstr() {
|
|
|
52
54
|
async function login() {
|
|
53
55
|
if (await checkExtension()) {
|
|
54
56
|
const ndk = initializeNDK();
|
|
57
|
+
await connect();
|
|
55
58
|
const signer = new NDKNip07Signer();
|
|
56
59
|
ndk.signer = signer;
|
|
57
|
-
const
|
|
60
|
+
const account = await signer.user();
|
|
58
61
|
state.signer = signer;
|
|
59
|
-
state.pubkey.value =
|
|
60
|
-
|
|
61
|
-
const profile = await
|
|
62
|
+
state.pubkey.value = account.pubkey;
|
|
63
|
+
const user = ndk.getUser({ pubkey: account.pubkey });
|
|
64
|
+
const profile = await user.fetchProfile();
|
|
62
65
|
state.userProfile.value = mapProfile(profile);
|
|
63
66
|
}
|
|
64
67
|
}
|
|
@@ -66,14 +69,15 @@ export function useNuxstr() {
|
|
|
66
69
|
return {
|
|
67
70
|
id: event.id,
|
|
68
71
|
pubkey: event.pubkey,
|
|
69
|
-
created_at: event.created_at ||
|
|
72
|
+
created_at: event.created_at || DEFAULT_TIMESTAMP,
|
|
70
73
|
content: event.content,
|
|
71
|
-
profile:
|
|
74
|
+
profile: void 0
|
|
72
75
|
};
|
|
73
76
|
}
|
|
74
77
|
async function fetchProfile(pubkey) {
|
|
75
78
|
try {
|
|
76
|
-
const
|
|
79
|
+
const ndk = initializeNDK();
|
|
80
|
+
const user = ndk.getUser({ pubkey });
|
|
77
81
|
const profile = await user.fetchProfile();
|
|
78
82
|
return mapProfile(profile);
|
|
79
83
|
} catch (error) {
|
|
@@ -82,6 +86,7 @@ export function useNuxstr() {
|
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
function mapProfile(profile) {
|
|
89
|
+
if (profile === null) return {};
|
|
85
90
|
return {
|
|
86
91
|
display_name: profile.displayName,
|
|
87
92
|
about: profile.about,
|
|
@@ -94,7 +99,7 @@ export function useNuxstr() {
|
|
|
94
99
|
}
|
|
95
100
|
function logout() {
|
|
96
101
|
state.signer = null;
|
|
97
|
-
state.pubkey.value =
|
|
102
|
+
state.pubkey.value = DEFAULT_PUBKEY;
|
|
98
103
|
}
|
|
99
104
|
return {
|
|
100
105
|
get ndk() {
|
|
@@ -104,9 +109,10 @@ export function useNuxstr() {
|
|
|
104
109
|
login,
|
|
105
110
|
logout,
|
|
106
111
|
isLoggedIn,
|
|
107
|
-
pubkey: state.pubkey,
|
|
112
|
+
pubkey: state.pubkey.value,
|
|
108
113
|
mapProfile,
|
|
109
114
|
mapComment,
|
|
110
115
|
fetchProfile
|
|
111
116
|
};
|
|
112
117
|
}
|
|
118
|
+
export default useNuxstr;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
declare function useReplies(rootCommentId: string): {
|
|
2
2
|
subscribeReplies: () => Promise<void>;
|
|
3
3
|
replies: import("vue").ComputedRef<{
|
|
4
4
|
id: string;
|
|
@@ -17,5 +17,5 @@ export declare function useReplies(rootCommentId?: string): {
|
|
|
17
17
|
} | undefined;
|
|
18
18
|
}[]>;
|
|
19
19
|
reply: (comment: string) => Promise<boolean>;
|
|
20
|
-
count: import("vue").ComputedRef<Promise<string>>;
|
|
21
20
|
};
|
|
21
|
+
export default useReplies;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { computed, ref } from "vue";
|
|
2
|
-
import
|
|
2
|
+
import useNuxstr from "./useNuxstr.js";
|
|
3
3
|
import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
|
|
4
|
-
|
|
4
|
+
function useReplies(rootCommentId) {
|
|
5
5
|
const { ndk, connect, mapComment, pubkey, fetchProfile } = useNuxstr();
|
|
6
6
|
const repliesData = ref([]);
|
|
7
7
|
const error = ref(null);
|
|
@@ -11,7 +11,7 @@ export function useReplies(rootCommentId) {
|
|
|
11
11
|
async function subscribeReplies() {
|
|
12
12
|
await connect();
|
|
13
13
|
const filter = { kinds: [NDKKind.GenericReply], limit: 100, ["#e"]: [rootCommentId] };
|
|
14
|
-
const sub =
|
|
14
|
+
const sub = ndk.subscribe(filter);
|
|
15
15
|
sub.on("event", async (event) => {
|
|
16
16
|
const reply2 = mapComment(event);
|
|
17
17
|
reply2.profile = await fetchProfile(event.pubkey);
|
|
@@ -33,16 +33,10 @@ export function useReplies(rootCommentId) {
|
|
|
33
33
|
["e", `${rootCommentId}`],
|
|
34
34
|
["k", `${NDKKind.GenericReply}`],
|
|
35
35
|
// The parent kind
|
|
36
|
-
["p", pubkey
|
|
36
|
+
["p", pubkey ?? ""]
|
|
37
37
|
];
|
|
38
38
|
return event;
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
await connect();
|
|
42
|
-
const filter = { kinds: [NDKKind.GenericReply], limit: 100, ["#e"]: [rootCommentId] };
|
|
43
|
-
const events = await ndk.fetchEvents(filter);
|
|
44
|
-
console.log(events);
|
|
45
|
-
return `${Array.from(events).length}`;
|
|
46
|
-
});
|
|
47
|
-
return { subscribeReplies, replies, reply, count };
|
|
40
|
+
return { subscribeReplies, replies, reply };
|
|
48
41
|
}
|
|
42
|
+
export default useReplies;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threenine/nuxstr-comments",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "Nuxt module to enable Nostr Comments on Nuxt 4 based websites",
|
|
5
5
|
"repository": "threenine/nuxstr-comments",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,7 +24,6 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@nostr-dev-kit/ndk": "^2.14.33",
|
|
27
|
-
"@nuxt/kit": "^4.0.3",
|
|
28
27
|
"defu": "^6.1.4",
|
|
29
28
|
"marked": "^16.2.1"
|
|
30
29
|
},
|
|
@@ -32,13 +31,15 @@
|
|
|
32
31
|
"@nuxt/devtools": "^2.6.2",
|
|
33
32
|
"@nuxt/eslint": "1.9.0",
|
|
34
33
|
"@nuxt/eslint-config": "^1.9.0",
|
|
34
|
+
"@nuxt/kit": "^4.1.2",
|
|
35
35
|
"@nuxt/module-builder": "^1.0.2",
|
|
36
|
-
"@nuxt/schema": "^4.1.
|
|
36
|
+
"@nuxt/schema": "^4.1.2",
|
|
37
37
|
"@nuxt/scripts": "0.11.10",
|
|
38
38
|
"@nuxt/test-utils": "^3.19.2",
|
|
39
39
|
"@nuxt/ui": "^3.3.3",
|
|
40
40
|
"@testing-library/jest-dom": "^6.8.0",
|
|
41
41
|
"@testing-library/vue": "^8.1.0",
|
|
42
|
+
"@types/node": "latest",
|
|
42
43
|
"@unhead/vue": "^2.0.14",
|
|
43
44
|
"changelogen": "^0.6.2",
|
|
44
45
|
"eslint": "^9.35.0",
|
|
@@ -46,8 +47,7 @@
|
|
|
46
47
|
"nuxt": "^4.1.2",
|
|
47
48
|
"typescript": "~5.9.2",
|
|
48
49
|
"vitest": "^3.2.4",
|
|
49
|
-
"vue-tsc": "^3.0.6"
|
|
50
|
-
"@types/node": "latest"
|
|
50
|
+
"vue-tsc": "^3.0.6"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"dev": "pnpm run dev:prepare && nuxi dev playground",
|
|
File without changes
|
|
File without changes
|