mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 05:54:19 +01:00
update nostr-tools
This commit is contained in:
77
package-lock.json
generated
77
package-lock.json
generated
@@ -26,7 +26,7 @@
|
|||||||
"i18next-browser-languagedetector": "^7.2.0",
|
"i18next-browser-languagedetector": "^7.2.0",
|
||||||
"idb-keyval": "^6.2.1",
|
"idb-keyval": "^6.2.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nostr-tools": "^1.16.0",
|
"nostr-tools": "^2.0.3",
|
||||||
"solid-js": "^1.8.7",
|
"solid-js": "^1.8.7",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.0",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
@@ -5494,16 +5494,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nostr-tools": {
|
"node_modules/nostr-tools": {
|
||||||
"version": "1.16.0",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.0.3.tgz",
|
||||||
"integrity": "sha512-sx/aOl0gmkeHVoIVbyOhEQhzF88NsrBXMC8bsjhPASqA6oZ8uSOAyEGgRLMfC3SKgzQD5Gr6KvDoAahaD6xKcg==",
|
"integrity": "sha512-A7/sBaeBA7Vmi3q1Or62FYbU4OuNBOfQmSxn4/sEK5Z6L4Ql9dwSq8H/mrxsiCQHfbLaVHBOmxLOOd3070/xCA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/ciphers": "^0.2.0",
|
"@noble/ciphers": "0.2.0",
|
||||||
"@noble/curves": "1.1.0",
|
"@noble/curves": "1.2.0",
|
||||||
"@noble/hashes": "1.3.1",
|
"@noble/hashes": "1.3.1",
|
||||||
"@scure/base": "1.1.1",
|
"@scure/base": "1.1.1",
|
||||||
"@scure/bip32": "1.3.1",
|
"@scure/bip32": "1.3.1",
|
||||||
"@scure/bip39": "1.2.1"
|
"@scure/bip39": "1.2.1",
|
||||||
|
"nostr-wasm": "v0.0.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": ">=5.0.0"
|
"typescript": ">=5.0.0"
|
||||||
@@ -5514,6 +5515,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@noble/curves": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "1.3.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-wasm": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-zz5INXiuya10s+zsNmW2k4xH47j+Ikgxn5SL8xt/quGBNWn/A6+blVqT3J6yjkZim/gyVC/9GXd0jH4w3w1HZA=="
|
||||||
|
},
|
||||||
"node_modules/npm-normalize-package-bin": {
|
"node_modules/npm-normalize-package-bin": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||||
@@ -12599,18 +12627,41 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"nostr-tools": {
|
"nostr-tools": {
|
||||||
"version": "1.16.0",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.0.3.tgz",
|
||||||
"integrity": "sha512-sx/aOl0gmkeHVoIVbyOhEQhzF88NsrBXMC8bsjhPASqA6oZ8uSOAyEGgRLMfC3SKgzQD5Gr6KvDoAahaD6xKcg==",
|
"integrity": "sha512-A7/sBaeBA7Vmi3q1Or62FYbU4OuNBOfQmSxn4/sEK5Z6L4Ql9dwSq8H/mrxsiCQHfbLaVHBOmxLOOd3070/xCA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@noble/ciphers": "^0.2.0",
|
"@noble/ciphers": "0.2.0",
|
||||||
"@noble/curves": "1.1.0",
|
"@noble/curves": "1.2.0",
|
||||||
"@noble/hashes": "1.3.1",
|
"@noble/hashes": "1.3.1",
|
||||||
"@scure/base": "1.1.1",
|
"@scure/base": "1.1.1",
|
||||||
"@scure/bip32": "1.3.1",
|
"@scure/bip32": "1.3.1",
|
||||||
"@scure/bip39": "1.2.1"
|
"@scure/bip39": "1.2.1",
|
||||||
|
"nostr-wasm": "v0.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/curves": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/hashes": "1.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nostr-wasm": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-zz5INXiuya10s+zsNmW2k4xH47j+Ikgxn5SL8xt/quGBNWn/A6+blVqT3J6yjkZim/gyVC/9GXd0jH4w3w1HZA=="
|
||||||
|
},
|
||||||
"npm-normalize-package-bin": {
|
"npm-normalize-package-bin": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
"i18next-browser-languagedetector": "^7.2.0",
|
"i18next-browser-languagedetector": "^7.2.0",
|
||||||
"idb-keyval": "^6.2.1",
|
"idb-keyval": "^6.2.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nostr-tools": "^1.16.0",
|
"nostr-tools": "^2.0.3",
|
||||||
"solid-js": "^1.8.7",
|
"solid-js": "^1.8.7",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.0",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import EllipsisHorizontal from 'heroicons/24/outline/ellipsis-horizontal.svg';
|
|||||||
import HeartOutlined from 'heroicons/24/outline/heart.svg';
|
import HeartOutlined from 'heroicons/24/outline/heart.svg';
|
||||||
import Plus from 'heroicons/24/outline/plus.svg';
|
import Plus from 'heroicons/24/outline/plus.svg';
|
||||||
import HeartSolid from 'heroicons/24/solid/heart.svg';
|
import HeartSolid from 'heroicons/24/solid/heart.svg';
|
||||||
import { type Event as NostrEvent, nip19 } from 'nostr-tools';
|
import { noteEncode } from 'nostr-tools/nip19';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import ContextMenu, { MenuItem } from '@/components/ContextMenu';
|
import ContextMenu, { MenuItem } from '@/components/ContextMenu';
|
||||||
import EmojiDisplay from '@/components/EmojiDisplay';
|
import EmojiDisplay from '@/components/EmojiDisplay';
|
||||||
@@ -41,8 +42,6 @@ export type ActionProps = {
|
|||||||
onClickReply: () => void;
|
onClickReply: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const { noteEncode } = nip19;
|
|
||||||
|
|
||||||
const emojiDataToReactionTypes = (emoji: EmojiData): ReactionTypes => {
|
const emojiDataToReactionTypes = (emoji: EmojiData): ReactionTypes => {
|
||||||
if (emoji.native != null) {
|
if (emoji.native != null) {
|
||||||
return { type: 'Emoji', content: emoji.native };
|
return { type: 'Emoji', content: emoji.native };
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { Show, type Component } from 'solid-js';
|
import { Show, type Component } from 'solid-js';
|
||||||
|
|
||||||
import { Kind, nip19 } from 'nostr-tools';
|
import { noteEncode, neventEncode } from 'nostr-tools/nip19';
|
||||||
|
|
||||||
const { noteEncode, neventEncode } = nip19;
|
|
||||||
|
|
||||||
type EventLinkProps = {
|
type EventLinkProps = {
|
||||||
eventId: string;
|
eventId: string;
|
||||||
kind?: Kind;
|
kind?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tryEncodeNote = (eventId: string) => {
|
const tryEncodeNote = (eventId: string) => {
|
||||||
@@ -29,10 +27,7 @@ const tryEncodeNevent = (eventId: string) => {
|
|||||||
|
|
||||||
const EventLink: Component<EventLinkProps> = (props) => (
|
const EventLink: Component<EventLinkProps> = (props) => (
|
||||||
<button class="text-blue-500 underline">
|
<button class="text-blue-500 underline">
|
||||||
<Show
|
<Show when={props.kind == null || props.kind === 1} fallback={tryEncodeNevent(props.eventId)}>
|
||||||
when={props.kind == null || props.kind === Kind.Text}
|
|
||||||
fallback={tryEncodeNevent(props.eventId)}
|
|
||||||
>
|
|
||||||
{tryEncodeNote(props.eventId)}
|
{tryEncodeNote(props.eventId)}
|
||||||
</Show>
|
</Show>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Photo from 'heroicons/24/outline/photo.svg';
|
|||||||
import XMark from 'heroicons/24/outline/x-mark.svg';
|
import XMark from 'heroicons/24/outline/x-mark.svg';
|
||||||
import PaperAirplane from 'heroicons/24/solid/paper-airplane.svg';
|
import PaperAirplane from 'heroicons/24/solid/paper-airplane.svg';
|
||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import EmojiPicker, { EmojiData } from '@/components/EmojiPicker';
|
import EmojiPicker, { EmojiData } from '@/components/EmojiPicker';
|
||||||
import UserNameDisplay from '@/components/UserDisplayName';
|
import UserNameDisplay from '@/components/UserDisplayName';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component } from 'solid-js';
|
import { Component } from 'solid-js';
|
||||||
|
|
||||||
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
||||||
import { Kind } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
|
||||||
import BasicColumnHeader from '@/components/column/BasicColumnHeader';
|
import BasicColumnHeader from '@/components/column/BasicColumnHeader';
|
||||||
import Column from '@/components/column/Column';
|
import Column from '@/components/column/Column';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Component, Show } from 'solid-js';
|
import { Component, Show } from 'solid-js';
|
||||||
|
|
||||||
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import { parseChannelMeta } from '@/nostr/event/channel';
|
import { parseChannelMeta } from '@/nostr/event/channel';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Switch, Match, Component } from 'solid-js';
|
import { Switch, Match, Component } from 'solid-js';
|
||||||
|
|
||||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
// import ChannelInfo from '@/components/event/ChannelInfo';
|
// import ChannelInfo from '@/components/event/ChannelInfo';
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
@@ -13,7 +14,7 @@ export type EventDisplayProps = {
|
|||||||
event: NostrEvent;
|
event: NostrEvent;
|
||||||
embedding?: boolean;
|
embedding?: boolean;
|
||||||
actions?: boolean;
|
actions?: boolean;
|
||||||
ensureKinds?: Kind[];
|
ensureKinds?: number[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const EventDisplay: Component<EventDisplayProps> = (props) => {
|
const EventDisplay: Component<EventDisplayProps> = (props) => {
|
||||||
@@ -39,10 +40,10 @@ const EventDisplay: Component<EventDisplayProps> = (props) => {
|
|||||||
<EventLink eventId={props.event.id} kind={props.event.kind} />
|
<EventLink eventId={props.event.id} kind={props.event.kind} />
|
||||||
</span>
|
</span>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={props.event.kind === (Kind.Text as number)}>
|
<Match when={props.event.kind === Kind.ShortTextNote}>
|
||||||
<TextNote event={props.event} embedding={props.actions} actions={props.actions} />
|
<TextNote event={props.event} embedding={props.actions} actions={props.actions} />
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={props.event.kind === (Kind.Repost as number)}>
|
<Match when={props.event.kind === Kind.Repost}>
|
||||||
<Repost event={props.event} />
|
<Repost event={props.event} />
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { type Component, Show } from 'solid-js';
|
import { type Component, Show } from 'solid-js';
|
||||||
|
|
||||||
import { type Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import EmojiDisplay from '@/components/EmojiDisplay';
|
import EmojiDisplay from '@/components/EmojiDisplay';
|
||||||
import TextNote from '@/components/event/TextNote';
|
import TextNote from '@/components/event/TextNote';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { type Component, createMemo } from 'solid-js';
|
import { type Component, createMemo } from 'solid-js';
|
||||||
|
|
||||||
import ArrowPathRoundedSquare from 'heroicons/24/outline/arrow-path-rounded-square.svg';
|
import ArrowPathRoundedSquare from 'heroicons/24/outline/arrow-path-rounded-square.svg';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Show, For, createSignal, createMemo, type Component } from 'solid-js';
|
import { Show, For, createSignal, createMemo, type Component } from 'solid-js';
|
||||||
|
|
||||||
import { type Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import Actions from '@/components/Actions';
|
import Actions from '@/components/Actions';
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Show } from 'solid-js';
|
import { Show } from 'solid-js';
|
||||||
|
|
||||||
import { Kind } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||||
@@ -24,7 +24,7 @@ const MentionedEventDisplay = (props: MentionedEventDisplayProps) => (
|
|||||||
eventId={props.mentionedEvent.eventId}
|
eventId={props.mentionedEvent.eventId}
|
||||||
embedding={false}
|
embedding={false}
|
||||||
actions={false}
|
actions={false}
|
||||||
ensureKinds={[Kind.Text]}
|
ensureKinds={[Kind.ShortTextNote]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</LazyLoad>
|
</LazyLoad>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { For } from 'solid-js';
|
import { For } from 'solid-js';
|
||||||
|
|
||||||
import { Kind } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||||
@@ -88,7 +88,7 @@ const TextNoteContentDisplay = (props: TextNoteContentDisplayProps) => {
|
|||||||
eventId={item.data.data}
|
eventId={item.data.data}
|
||||||
actions={false}
|
actions={false}
|
||||||
embedding={false}
|
embedding={false}
|
||||||
ensureKinds={[Kind.Text]}
|
ensureKinds={[Kind.ShortTextNote]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component, createMemo } from 'solid-js';
|
import { Component, createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { type Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import BasicModal from '@/components/modal/BasicModal';
|
import BasicModal from '@/components/modal/BasicModal';
|
||||||
import Copy from '@/components/utils/Copy';
|
import Copy from '@/components/utils/Copy';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { For, type Component, createMemo } from 'solid-js';
|
import { For, type Component, createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import ColumnItem from '@/components/ColumnItem';
|
import ColumnItem from '@/components/ColumnItem';
|
||||||
import EventDisplayById from '@/components/event/EventDisplayById';
|
import EventDisplayById from '@/components/event/EventDisplayById';
|
||||||
@@ -40,7 +41,7 @@ const Bookmark: Component<BookmarkProps> = (props) => {
|
|||||||
<For each={[...bookmarkedEventIds(), ...bookmarkedEventIdsPrivate()]}>
|
<For each={[...bookmarkedEventIds(), ...bookmarkedEventIdsPrivate()]}>
|
||||||
{(eventId) => (
|
{(eventId) => (
|
||||||
<ColumnItem>
|
<ColumnItem>
|
||||||
<EventDisplayById eventId={eventId} ensureKinds={[Kind.Text]} />
|
<EventDisplayById eventId={eventId} ensureKinds={[Kind.ShortTextNote]} />
|
||||||
</ColumnItem>
|
</ColumnItem>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { For, Switch, Match, type Component, Show } from 'solid-js';
|
import { For, Switch, Match, type Component, Show } from 'solid-js';
|
||||||
|
|
||||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import ColumnItem from '@/components/ColumnItem';
|
import ColumnItem from '@/components/ColumnItem';
|
||||||
import Reaction from '@/components/event/Reaction';
|
import Reaction from '@/components/event/Reaction';
|
||||||
@@ -20,18 +21,18 @@ const Notification: Component<NotificationProps> = (props) => {
|
|||||||
{(event) => (
|
{(event) => (
|
||||||
<Show when={!shouldMuteEvent(event)}>
|
<Show when={!shouldMuteEvent(event)}>
|
||||||
<Switch fallback={<div>unknown event</div>}>
|
<Switch fallback={<div>unknown event</div>}>
|
||||||
<Match when={event.kind === (Kind.Text as number)}>
|
<Match when={event.kind === Kind.ShortTextNote}>
|
||||||
<ColumnItem>
|
<ColumnItem>
|
||||||
<TextNote event={event} />
|
<TextNote event={event} />
|
||||||
</ColumnItem>
|
</ColumnItem>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={event.kind === (Kind.Reaction as number)}>
|
<Match when={event.kind === Kind.Reaction}>
|
||||||
<ColumnItem>
|
<ColumnItem>
|
||||||
<Reaction event={event} />
|
<Reaction event={event} />
|
||||||
</ColumnItem>
|
</ColumnItem>
|
||||||
</Match>
|
</Match>
|
||||||
{/* TODO ちゃんとnotification用のコンポーネント使う */}
|
{/* TODO ちゃんとnotification用のコンポーネント使う */}
|
||||||
<Match when={event.kind === (Kind.Repost as number)}>
|
<Match when={event.kind === Kind.Repost}>
|
||||||
<ColumnItem>
|
<ColumnItem>
|
||||||
<Repost event={event} />
|
<Repost event={event} />
|
||||||
</ColumnItem>
|
</ColumnItem>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { For, type Component, Show } from 'solid-js';
|
import { For, type Component, Show } from 'solid-js';
|
||||||
|
|
||||||
import { type Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import ColumnItem from '@/components/ColumnItem';
|
import ColumnItem from '@/components/ColumnItem';
|
||||||
import EventDisplay from '@/components/event/EventDisplay';
|
import EventDisplay from '@/components/event/EventDisplay';
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Switch, Match, type Component } from 'solid-js';
|
import { Switch, Match, type Component } from 'solid-js';
|
||||||
|
|
||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import { Filter, Event as NostrEvent } from 'nostr-tools';
|
import { type Filter } from 'nostr-tools/filter';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import Timeline from '@/components/timeline/Timeline';
|
import Timeline from '@/components/timeline/Timeline';
|
||||||
import { type TimelineContent } from '@/components/timeline/TimelineContext';
|
import { type TimelineContent } from '@/components/timeline/TimelineContext';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createContext, useContext } from 'solid-js';
|
import { createContext, useContext } from 'solid-js';
|
||||||
|
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
import { createStore } from 'solid-js/store';
|
import { createStore } from 'solid-js/store';
|
||||||
|
|
||||||
export type TimelineContent = {
|
export type TimelineContent = {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// import { z } from 'zod';
|
// import { z } from 'zod';
|
||||||
import { type Filter } from 'nostr-tools';
|
import { type Filter } from 'nostr-tools/filter';
|
||||||
|
|
||||||
import { type ColumnProps } from '@/components/column/Column';
|
import { type ColumnProps } from '@/components/column/Column';
|
||||||
import { ContentFilter } from '@/core/contentFilter';
|
import { ContentFilter } from '@/core/contentFilter';
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { type Accessor, type Setter } from 'solid-js';
|
|||||||
|
|
||||||
import { sortBy } from 'lodash';
|
import { sortBy } from 'lodash';
|
||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import { Kind, type Event as NostrEvent } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ColumnType,
|
ColumnType,
|
||||||
@@ -194,7 +195,7 @@ const useConfig = (): UseConfig => {
|
|||||||
const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey);
|
const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey);
|
||||||
|
|
||||||
const hasMutedKeyword = (event: NostrEvent) => {
|
const hasMutedKeyword = (event: NostrEvent) => {
|
||||||
if (event.kind === (Kind.Text as number)) {
|
if (event.kind === Kind.ShortTextNote) {
|
||||||
return config.mutedKeywords.some((keyword) => event.content.includes(keyword));
|
return config.mutedKeywords.some((keyword) => event.content.includes(keyword));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -205,7 +206,7 @@ const useConfig = (): UseConfig => {
|
|||||||
return (
|
return (
|
||||||
isPubkeyMuted(event.pubkey) ||
|
isPubkeyMuted(event.pubkey) ||
|
||||||
ev.taggedPubkeys().some(isPubkeyMuted) ||
|
ev.taggedPubkeys().some(isPubkeyMuted) ||
|
||||||
(event.kind === (Kind.Text as number) && hasMutedKeyword(event))
|
(event.kind === Kind.ShortTextNote && hasMutedKeyword(event))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import GenericEvent from '@/nostr/event/GenericEvent';
|
import GenericEvent from '@/nostr/event/GenericEvent';
|
||||||
import Reaction from '@/nostr/event/Reaction';
|
import Reaction from '@/nostr/event/Reaction';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Kind, Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import TagsBase from '@/nostr/event/TagsBase';
|
import TagsBase from '@/nostr/event/TagsBase';
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ export default class GenericEvent extends TagsBase {
|
|||||||
return this.rawEvent.sig;
|
return this.rawEvent.sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
get kind(): Kind {
|
get kind(): number {
|
||||||
return this.rawEvent.kind;
|
return this.rawEvent.kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Event as NostrEvent, Kind } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import GenericEvent from '@/nostr/event/GenericEvent';
|
import GenericEvent from '@/nostr/event/GenericEvent';
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ const reactionToReactionTypes = (event: Reaction): ReactionTypes => {
|
|||||||
|
|
||||||
export default class Reaction extends GenericEvent {
|
export default class Reaction extends GenericEvent {
|
||||||
constructor(rawEvent: NostrEvent) {
|
constructor(rawEvent: NostrEvent) {
|
||||||
if (rawEvent.kind !== (Kind.Reaction as number)) {
|
if (rawEvent.kind !== Kind.Reaction) {
|
||||||
throw new TypeError('kind should be 7');
|
throw new TypeError('kind should be 7');
|
||||||
}
|
}
|
||||||
super(rawEvent);
|
super(rawEvent);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
|
||||||
import { Kind } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
import { describe, it } from 'vitest';
|
import { describe, it } from 'vitest';
|
||||||
|
|
||||||
import TextNote from '@/nostr/event/TextNote';
|
import TextNote from '@/nostr/event/TextNote';
|
||||||
@@ -142,7 +142,7 @@ describe('TextNote', () => {
|
|||||||
it('should return true if content of the event includes a NIP-19-styled note ID', () => {
|
it('should return true if content of the event includes a NIP-19-styled note ID', () => {
|
||||||
const textnote = new TextNote({
|
const textnote = new TextNote({
|
||||||
id: '',
|
id: '',
|
||||||
kind: Kind.Text,
|
kind: Kind.ShortTextNote,
|
||||||
content: 'nostr:note1qpwq08jv0sgrz68qev6eyu9vj6n2gmjl7n8g73jruzp37mguy3gq8d7asa',
|
content: 'nostr:note1qpwq08jv0sgrz68qev6eyu9vj6n2gmjl7n8g73jruzp37mguy3gq8d7asa',
|
||||||
created_at: 0,
|
created_at: 0,
|
||||||
pubkey: '',
|
pubkey: '',
|
||||||
@@ -159,7 +159,7 @@ describe('TextNote', () => {
|
|||||||
it('should return true if content of the event includes a NIP-19-styled nevent ID', () => {
|
it('should return true if content of the event includes a NIP-19-styled nevent ID', () => {
|
||||||
const textnote = new TextNote({
|
const textnote = new TextNote({
|
||||||
id: '',
|
id: '',
|
||||||
kind: Kind.Text,
|
kind: Kind.ShortTextNote,
|
||||||
content: 'nostr:nevent1qqsttdc4rmxn8fqmk9s6823fqvpcmlm8ry6dmtu4m2snv0cm9sv70kq6urpy5',
|
content: 'nostr:nevent1qqsttdc4rmxn8fqmk9s6823fqvpcmlm8ry6dmtu4m2snv0cm9sv70kq6urpy5',
|
||||||
created_at: 0,
|
created_at: 0,
|
||||||
pubkey: '',
|
pubkey: '',
|
||||||
@@ -178,7 +178,7 @@ describe('TextNote', () => {
|
|||||||
it('should return a reply MarkedEventTag if the event has a reply tag', () => {
|
it('should return a reply MarkedEventTag if the event has a reply tag', () => {
|
||||||
const textnote = new TextNote({
|
const textnote = new TextNote({
|
||||||
id: '',
|
id: '',
|
||||||
kind: Kind.Text,
|
kind: Kind.ShortTextNote,
|
||||||
content: '',
|
content: '',
|
||||||
created_at: 0,
|
created_at: 0,
|
||||||
pubkey: '',
|
pubkey: '',
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { type Event as NostrEvent, Kind } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import TextNoteLike from '@/nostr/event/TextNoteLike';
|
import TextNoteLike from '@/nostr/event/TextNoteLike';
|
||||||
|
|
||||||
export default class TextNote extends TextNoteLike {
|
export default class TextNote extends TextNoteLike {
|
||||||
constructor(rawEvent: NostrEvent) {
|
constructor(rawEvent: NostrEvent) {
|
||||||
if (rawEvent.kind !== (Kind.Text as number)) {
|
if (rawEvent.kind !== Kind.ShortTextNote) {
|
||||||
throw new TypeError('kind should be 1');
|
throw new TypeError(`kind should be 1 but it was ${rawEvent.kind}`);
|
||||||
}
|
}
|
||||||
super(rawEvent);
|
super(rawEvent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
import { describe, it } from 'vitest';
|
import { describe, it } from 'vitest';
|
||||||
|
|
||||||
import { compareEvents, pickLatestEvent } from '@/nostr/event/comparator';
|
import { compareEvents, pickLatestEvent } from '@/nostr/event/comparator';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* compareEvents compares events by created_at and id.
|
* compareEvents compares events by created_at and id.
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import { nip19 } from 'nostr-tools';
|
import { decode, type DecodeResult } from 'nostr-tools/nip19';
|
||||||
import { DecodeResult } from 'nostr-tools/lib/nip19';
|
|
||||||
|
|
||||||
import isValidId from '@/nostr/event/isValidId';
|
import isValidId from '@/nostr/event/isValidId';
|
||||||
import TagsBase from '@/nostr/event/TagsBase';
|
import TagsBase from '@/nostr/event/TagsBase';
|
||||||
|
|
||||||
const { decode } = nip19;
|
|
||||||
|
|
||||||
export type PlainText = {
|
export type PlainText = {
|
||||||
type: 'PlainText';
|
type: 'PlainText';
|
||||||
content: string;
|
content: string;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { QueryClient, QueryKey } from '@tanstack/solid-query';
|
import { QueryClient, QueryKey } from '@tanstack/solid-query';
|
||||||
import { uniqBy } from 'lodash';
|
import { uniqBy } from 'lodash';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import { compareEvents, pickLatestEvent, sortEvents } from '@/nostr/event/comparator';
|
import { compareEvents, pickLatestEvent, sortEvents } from '@/nostr/event/comparator';
|
||||||
import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents';
|
import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents';
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { type Event as NostrEvent, type Filter, Kind, utils } from 'nostr-tools';
|
import { type Filter } from 'nostr-tools/filter';
|
||||||
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
import { insertEventIntoDescendingList } from 'nostr-tools/utils';
|
||||||
|
|
||||||
import useConfig from '@/core/useConfig';
|
import useConfig from '@/core/useConfig';
|
||||||
import { genericEvent } from '@/nostr/event';
|
import { genericEvent } from '@/nostr/event';
|
||||||
@@ -35,7 +38,7 @@ type TaskArg = TaskArgs[number];
|
|||||||
|
|
||||||
export class BatchedEventsTask<T = TaskArg> extends ObservableTask<T, NostrEvent[]> {
|
export class BatchedEventsTask<T = TaskArg> extends ObservableTask<T, NostrEvent[]> {
|
||||||
addEvent(event: NostrEvent) {
|
addEvent(event: NostrEvent) {
|
||||||
this.updateWith((current) => utils.insertEventIntoDescendingList(current ?? [], event));
|
this.updateWith((current) => insertEventIntoDescendingList(current ?? [], event));
|
||||||
}
|
}
|
||||||
|
|
||||||
firstEventPromise(): Promise<NostrEvent> {
|
firstEventPromise(): Promise<NostrEvent> {
|
||||||
@@ -64,9 +67,6 @@ setInterval(() => {
|
|||||||
setActiveBatchSubscriptions(count);
|
setActiveBatchSubscriptions(count);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
const isParameterizedReplaceableEvent = (event: NostrEvent) =>
|
|
||||||
event.kind >= 30000 && event.kind < 40000;
|
|
||||||
|
|
||||||
const keyForParameterizedReplaceableEvent = ({
|
const keyForParameterizedReplaceableEvent = ({
|
||||||
kind,
|
kind,
|
||||||
author,
|
author,
|
||||||
@@ -220,22 +220,22 @@ export const tasksRequestBuilder = (tasks: BatchedEventsTask[]) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const resolve = (event: NostrEvent) => {
|
const resolve = (event: NostrEvent) => {
|
||||||
if (event.kind === (Kind.Metadata as number)) {
|
if (event.kind === Kind.Metadata) {
|
||||||
if (profileTasks.resolve(event)) return;
|
if (profileTasks.resolve(event)) return;
|
||||||
}
|
}
|
||||||
if (event.kind === (Kind.Contacts as number)) {
|
if (event.kind === Kind.Contacts) {
|
||||||
if (followingsTasks.resolve(event)) return;
|
if (followingsTasks.resolve(event)) return;
|
||||||
}
|
}
|
||||||
if (event.kind === (Kind.Repost as number)) {
|
if (event.kind === Kind.Repost) {
|
||||||
if (repostsTasks.resolve(event)) return;
|
if (repostsTasks.resolve(event)) return;
|
||||||
}
|
}
|
||||||
if (event.kind === (Kind.Reaction as number)) {
|
if (event.kind === Kind.Reaction) {
|
||||||
if (reactionsTasks.resolve(event)) return;
|
if (reactionsTasks.resolve(event)) return;
|
||||||
}
|
}
|
||||||
if (event.kind === (Kind.Zap as number)) {
|
if (event.kind === Kind.Zap) {
|
||||||
if (zapReceiptsTasks.resolve(event)) return;
|
if (zapReceiptsTasks.resolve(event)) return;
|
||||||
}
|
}
|
||||||
if (isParameterizedReplaceableEvent(event)) {
|
if (Kind.isParameterizedReplaceableKind(event.kind)) {
|
||||||
if (parameterizedReplaceableEventsTasks.resolve(event)) return;
|
if (parameterizedReplaceableEventsTasks.resolve(event)) return;
|
||||||
}
|
}
|
||||||
eventTasks.resolve(event);
|
eventTasks.resolve(event);
|
||||||
@@ -279,18 +279,17 @@ const { addTask, removeTask } = useBatch<BatchedEventsTask>(() => ({
|
|||||||
const { config } = useConfig();
|
const { config } = useConfig();
|
||||||
const pool = usePool();
|
const pool = usePool();
|
||||||
|
|
||||||
const sub = pool().sub(config().relayUrls, filters, {});
|
|
||||||
|
|
||||||
count += 1;
|
count += 1;
|
||||||
|
const sub = pool().subscribeMany(config().relayUrls, filters, {
|
||||||
sub.on('event', (event: NostrEvent & { id: string }) => {
|
eoseTimeout: 15000,
|
||||||
builder.resolve(event);
|
onevent: (event: NostrEvent) => {
|
||||||
});
|
builder.resolve(event);
|
||||||
|
},
|
||||||
sub.on('eose', () => {
|
oneose: () => {
|
||||||
finalizeTasks();
|
finalizeTasks();
|
||||||
sub.unsub();
|
sub.close();
|
||||||
count -= 1;
|
count -= 1;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { Kind } from 'nostr-tools';
|
|
||||||
|
|
||||||
import useConfig from '@/core/useConfig';
|
import useConfig from '@/core/useConfig';
|
||||||
import useSubscription from '@/nostr/useSubscription';
|
import useSubscription from '@/nostr/useSubscription';
|
||||||
|
|
||||||
@@ -15,7 +13,7 @@ export default function useBookmarks(propsProvider: () => UseBookmarksProps) {
|
|||||||
|
|
||||||
const { events } = useSubscription(() => ({
|
const { events } = useSubscription(() => ({
|
||||||
relayUrls: config().relayUrls,
|
relayUrls: config().relayUrls,
|
||||||
filters: [{ kinds: [30001 as Kind], authors: [props().pubkey] }],
|
filters: [{ kinds: [30001], authors: [props().pubkey] }],
|
||||||
continuous: true,
|
continuous: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getEventHash, Kind, verifySignature, type UnsignedEvent } from 'nostr-tools';
|
import * as Kind from 'nostr-tools/kinds';
|
||||||
|
import { verifyEvent, getEventHash, type UnsignedEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
// import '@/types/nostr.d';
|
|
||||||
import { ProfileWithOtherProperties, Profile } from '@/nostr/event/Profile';
|
import { ProfileWithOtherProperties, Profile } from '@/nostr/event/Profile';
|
||||||
import { ReactionTypes } from '@/nostr/event/Reaction';
|
import { ReactionTypes } from '@/nostr/event/Reaction';
|
||||||
import usePool from '@/nostr/usePool';
|
import usePool from '@/nostr/usePool';
|
||||||
@@ -87,7 +87,7 @@ const useCommands = () => {
|
|||||||
throw new Error('NIP-07 implementation not found');
|
throw new Error('NIP-07 implementation not found');
|
||||||
}
|
}
|
||||||
const signedEvent = await window.nostr.signEvent(preSignedEvent);
|
const signedEvent = await window.nostr.signEvent(preSignedEvent);
|
||||||
if (!verifySignature({ ...signedEvent, id })) {
|
if (!verifyEvent({ ...signedEvent, id })) {
|
||||||
throw new Error('nostr.signEvent returned invalid data');
|
throw new Error('nostr.signEvent returned invalid data');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ const useCommands = () => {
|
|||||||
const tags = buildTags(params);
|
const tags = buildTags(params);
|
||||||
|
|
||||||
const preSignedEvent: UnsignedEvent = {
|
const preSignedEvent: UnsignedEvent = {
|
||||||
kind: 1,
|
kind: Kind.ShortTextNote,
|
||||||
pubkey,
|
pubkey,
|
||||||
created_at: epoch(),
|
created_at: epoch(),
|
||||||
tags,
|
tags,
|
||||||
@@ -145,7 +145,7 @@ const useCommands = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const preSignedEvent: UnsignedEvent = {
|
const preSignedEvent: UnsignedEvent = {
|
||||||
kind: 7,
|
kind: Kind.Reaction,
|
||||||
pubkey,
|
pubkey,
|
||||||
created_at: epoch(),
|
created_at: epoch(),
|
||||||
tags,
|
tags,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
|
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import { registerTask, BatchedEventsTask, EventTask } from '@/nostr/useBatchedEvents';
|
import { registerTask, BatchedEventsTask, EventTask } from '@/nostr/useBatchedEvents';
|
||||||
import timeout from '@/utils/timeout';
|
import timeout from '@/utils/timeout';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import { Kind } from 'nostr-tools';
|
import { Metadata } from 'nostr-tools/kinds';
|
||||||
|
|
||||||
import useConfig from '@/core/useConfig';
|
import useConfig from '@/core/useConfig';
|
||||||
import useSubscription from '@/nostr/useSubscription';
|
import useSubscription from '@/nostr/useSubscription';
|
||||||
@@ -16,7 +16,7 @@ export default function useFollowers(propsProvider: () => UseFollowersProps) {
|
|||||||
|
|
||||||
const { events } = useSubscription(() => ({
|
const { events } = useSubscription(() => ({
|
||||||
relayUrls: config().relayUrls,
|
relayUrls: config().relayUrls,
|
||||||
filters: [{ kinds: [Kind.Contacts], '#p': [props().pubkey] }],
|
filters: [{ kinds: [Metadata], '#p': [props().pubkey] }],
|
||||||
limit: Number.MAX_SAFE_INTEGER,
|
limit: Number.MAX_SAFE_INTEGER,
|
||||||
continuous: true,
|
continuous: true,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import { genericEvent } from '@/nostr/event';
|
import { genericEvent } from '@/nostr/event';
|
||||||
import { latestEventQuery } from '@/nostr/query';
|
import { latestEventQuery } from '@/nostr/query';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import { pickLatestEvent } from '@/nostr/event/comparator';
|
import { pickLatestEvent } from '@/nostr/event/comparator';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createSignal } from 'solid-js';
|
import { createSignal } from 'solid-js';
|
||||||
|
|
||||||
import { SimplePool } from 'nostr-tools';
|
import { SimplePool } from 'nostr-tools/pool';
|
||||||
|
|
||||||
const [pool] = createSignal<SimplePool>(new SimplePool({ eoseSubTimeout: 12000 }));
|
const [pool] = createSignal<SimplePool>(new SimplePool());
|
||||||
|
|
||||||
const usePool = () => pool;
|
const usePool = () => pool;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import { Profile, ProfileWithOtherProperties, safeParseProfile } from '@/nostr/event/Profile';
|
import { Profile, ProfileWithOtherProperties, safeParseProfile } from '@/nostr/event/Profile';
|
||||||
import { latestEventQuery } from '@/nostr/query';
|
import { latestEventQuery } from '@/nostr/query';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import useConfig from '@/core/useConfig';
|
import useConfig from '@/core/useConfig';
|
||||||
import { reaction } from '@/nostr/event';
|
import { reaction } from '@/nostr/event';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createMemo } from 'solid-js';
|
import { createMemo } from 'solid-js';
|
||||||
|
|
||||||
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
import useConfig from '@/core/useConfig';
|
import useConfig from '@/core/useConfig';
|
||||||
import { eventsQuery } from '@/nostr/query';
|
import { eventsQuery } from '@/nostr/query';
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { createSignal, createEffect, onMount, onCleanup, on } from 'solid-js';
|
import { createSignal, createEffect, onMount, onCleanup, on } from 'solid-js';
|
||||||
|
|
||||||
import uniqBy from 'lodash/uniqBy';
|
import uniqBy from 'lodash/uniqBy';
|
||||||
import { utils } from 'nostr-tools';
|
import { type Filter } from 'nostr-tools/filter';
|
||||||
|
import { type SubscribeManyParams } from 'nostr-tools/pool';
|
||||||
|
import { type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
import { insertEventIntoDescendingList } from 'nostr-tools/utils';
|
||||||
|
|
||||||
import useConfig from '@/core/useConfig';
|
import useConfig from '@/core/useConfig';
|
||||||
import { sortEvents } from '@/nostr/event/comparator';
|
import { sortEvents } from '@/nostr/event/comparator';
|
||||||
@@ -9,12 +12,10 @@ import usePool from '@/nostr/usePool';
|
|||||||
import useStats from '@/nostr/useStats';
|
import useStats from '@/nostr/useStats';
|
||||||
import epoch from '@/utils/epoch';
|
import epoch from '@/utils/epoch';
|
||||||
|
|
||||||
import type { Event as NostrEvent, Filter, SubscriptionOptions } from 'nostr-tools';
|
|
||||||
|
|
||||||
export type UseSubscriptionProps = {
|
export type UseSubscriptionProps = {
|
||||||
relayUrls: string[];
|
relayUrls: string[];
|
||||||
filters: Filter[];
|
filters: Filter[];
|
||||||
options?: SubscriptionOptions;
|
options?: SubscribeManyParams;
|
||||||
/**
|
/**
|
||||||
* subscribe not only stored events but also new events published after the subscription
|
* subscribe not only stored events but also new events published after the subscription
|
||||||
* default is true
|
* default is true
|
||||||
@@ -72,7 +73,7 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setEvents((current) => {
|
setEvents((current) => {
|
||||||
const sorted = utils.insertEventIntoDescendingList(current, event).slice(0, limit);
|
const sorted = insertEventIntoDescendingList(current, event).slice(0, limit);
|
||||||
// FIXME なぜか重複して取得される問題があるが一旦uniqByで対処
|
// FIXME なぜか重複して取得される問題があるが一旦uniqByで対処
|
||||||
// https://github.com/syusui-s/rabbit/issues/5
|
// https://github.com/syusui-s/rabbit/issues/5
|
||||||
const deduped = uniqBy(sorted, (e) => e.id);
|
const deduped = uniqBy(sorted, (e) => e.id);
|
||||||
@@ -89,8 +90,6 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
|||||||
const props = propsProvider();
|
const props = propsProvider();
|
||||||
if (props == null) return;
|
if (props == null) return;
|
||||||
const { relayUrls, filters, options, onEvent, onEOSE, continuous = true } = props;
|
const { relayUrls, filters, options, onEvent, onEOSE, continuous = true } = props;
|
||||||
|
|
||||||
const sub = pool().sub(relayUrls, filters, options);
|
|
||||||
let subscribing = true;
|
let subscribing = true;
|
||||||
count += 1;
|
count += 1;
|
||||||
|
|
||||||
@@ -98,38 +97,45 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
|||||||
let eose = false;
|
let eose = false;
|
||||||
const storedEvents: NostrEvent[] = [];
|
const storedEvents: NostrEvent[] = [];
|
||||||
|
|
||||||
sub.on('event', (event: NostrEvent) => {
|
const sub = pool().subscribeMany(
|
||||||
if (onEvent != null) {
|
relayUrls,
|
||||||
onEvent(event as NostrEvent & { id: string });
|
filters,
|
||||||
}
|
options ?? {
|
||||||
if (props.clientEventFilter != null && !props.clientEventFilter(event)) {
|
eoseTimeout: 12000,
|
||||||
return;
|
maxWait: 6000,
|
||||||
}
|
onevent: (event: NostrEvent) => {
|
||||||
|
if (onEvent != null) {
|
||||||
|
onEvent(event as NostrEvent & { id: string });
|
||||||
|
}
|
||||||
|
if (props.clientEventFilter != null && !props.clientEventFilter(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!eose) {
|
if (!eose) {
|
||||||
pushed = true;
|
pushed = true;
|
||||||
storedEvents.push(event);
|
storedEvents.push(event);
|
||||||
} else {
|
} else {
|
||||||
addEvent(event);
|
addEvent(event);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
oneose: () => {
|
||||||
|
if (onEOSE != null) {
|
||||||
|
onEOSE();
|
||||||
|
}
|
||||||
|
|
||||||
sub.on('eose', () => {
|
eose = true;
|
||||||
if (onEOSE != null) {
|
setEvents(sortEvents(storedEvents));
|
||||||
onEOSE();
|
|
||||||
}
|
|
||||||
|
|
||||||
eose = true;
|
if (!continuous) {
|
||||||
setEvents(sortEvents(storedEvents));
|
sub.close();
|
||||||
|
if (subscribing) {
|
||||||
if (!continuous) {
|
subscribing = false;
|
||||||
sub.unsub();
|
count -= 1;
|
||||||
if (subscribing) {
|
}
|
||||||
subscribing = false;
|
}
|
||||||
count -= 1;
|
},
|
||||||
}
|
},
|
||||||
}
|
);
|
||||||
});
|
|
||||||
|
|
||||||
// avoid updating an array too rapidly while this is fetching stored events
|
// avoid updating an array too rapidly while this is fetching stored events
|
||||||
let updating = false;
|
let updating = false;
|
||||||
@@ -150,7 +156,7 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
|||||||
|
|
||||||
onCleanup(() => {
|
onCleanup(() => {
|
||||||
console.debug('startSubscription: end');
|
console.debug('startSubscription: end');
|
||||||
sub.unsub();
|
sub.close();
|
||||||
if (subscribing) {
|
if (subscribing) {
|
||||||
subscribing = false;
|
subscribing = false;
|
||||||
count -= 1;
|
count -= 1;
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import { createMemo, type Accessor } from 'solid-js';
|
import { createMemo, type Accessor } from 'solid-js';
|
||||||
|
|
||||||
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
|
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
|
||||||
import { nip05, nip19 } from 'nostr-tools';
|
import { queryProfile } from 'nostr-tools/nip05';
|
||||||
|
import { type ProfilePointer } from 'nostr-tools/nip19';
|
||||||
|
|
||||||
export type UseVerificationProps = {
|
export type UseVerificationProps = {
|
||||||
nip05: string;
|
nip05: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UseVerification = {
|
export type UseVerification = {
|
||||||
verification: Accessor<nip19.ProfilePointer | null>;
|
verification: Accessor<ProfilePointer | null>;
|
||||||
query: CreateQueryResult<nip19.ProfilePointer | null>;
|
query: CreateQueryResult<ProfilePointer | null>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useVerification = (propsProvider: () => UseVerificationProps | null): UseVerification => {
|
const useVerification = (propsProvider: () => UseVerificationProps | null): UseVerification => {
|
||||||
@@ -22,7 +23,7 @@ const useVerification = (propsProvider: () => UseVerificationProps | null): UseV
|
|||||||
const [, currentProps] = queryKey;
|
const [, currentProps] = queryKey;
|
||||||
if (currentProps == null) return Promise.resolve(null);
|
if (currentProps == null) return Promise.resolve(null);
|
||||||
const { nip05: nip05string } = currentProps;
|
const { nip05: nip05string } = currentProps;
|
||||||
return nip05.queryProfile(nip05string);
|
return queryProfile(nip05string);
|
||||||
},
|
},
|
||||||
staleTime: 30 * 60 * 1000, // 30 min
|
staleTime: 30 * 60 * 1000, // 30 min
|
||||||
cacheTime: 24 * 60 * 60 * 1000, // 24 hour
|
cacheTime: 24 * 60 * 60 * 1000, // 24 hour
|
||||||
|
|||||||
@@ -25,9 +25,12 @@ const Home: Component = () => {
|
|||||||
config().relayUrls.map(async (relayUrl) => {
|
config().relayUrls.map(async (relayUrl) => {
|
||||||
try {
|
try {
|
||||||
const relay = await pool().ensureRelay(relayUrl);
|
const relay = await pool().ensureRelay(relayUrl);
|
||||||
relay.on('notice', (msg: string) => {
|
relay.onnotice = (msg: string) => {
|
||||||
console.error(`NOTICE: ${relayUrl}: ${msg}`);
|
console.error(`NOTICE: ${relayUrl}: ${msg}`);
|
||||||
});
|
};
|
||||||
|
relay.onclose = () => {
|
||||||
|
console.warn(`CLOSE: ${relayUrl}`);
|
||||||
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('ensureRelay failed', err);
|
console.error('ensureRelay failed', err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createEffect, onMount } from 'solid-js';
|
import { createEffect, onMount } from 'solid-js';
|
||||||
|
|
||||||
import { useNavigate, useParams } from '@solidjs/router';
|
import { useNavigate, useParams } from '@solidjs/router';
|
||||||
import { nip19 } from 'nostr-tools';
|
import { decode } from 'nostr-tools/nip19';
|
||||||
|
|
||||||
import GlobalModal from '@/components/modal/GlobalModal';
|
import GlobalModal from '@/components/modal/GlobalModal';
|
||||||
import SideBar from '@/components/SideBar';
|
import SideBar from '@/components/SideBar';
|
||||||
@@ -25,7 +25,7 @@ const Permalink = () => {
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (params.id != null) {
|
if (params.id != null) {
|
||||||
try {
|
try {
|
||||||
const decoded = nip19.decode(params.id);
|
const decoded = decode(params.id);
|
||||||
if (decoded.type === 'npub') {
|
if (decoded.type === 'npub') {
|
||||||
showProfile(decoded.data);
|
showProfile(decoded.data);
|
||||||
}
|
}
|
||||||
|
|||||||
2
src/types/nostr.d.ts
vendored
2
src/types/nostr.d.ts
vendored
@@ -1,6 +1,6 @@
|
|||||||
// The original code was published under the public domain license (CC0-1.0).
|
// The original code was published under the public domain license (CC0-1.0).
|
||||||
// https://gist.github.com/syusui-s/cd5482ddfc83792b54a756759acbda55
|
// https://gist.github.com/syusui-s/cd5482ddfc83792b54a756759acbda55
|
||||||
import { type UnsignedEvent, type Event as NostrEvent } from 'nostr-tools';
|
import { type UnsignedEvent, type Event as NostrEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
type NostrAPI = {
|
type NostrAPI = {
|
||||||
/** returns a public key as hex */
|
/** returns a public key as hex */
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { nip19 } from 'nostr-tools';
|
import { npubEncode } from 'nostr-tools/nip19';
|
||||||
|
|
||||||
const { npubEncode } = nip19;
|
|
||||||
|
|
||||||
const npubEncodeFallback = (pubkey: string): string => {
|
const npubEncodeFallback = (pubkey: string): string => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user