mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 05:54:19 +01:00
update
This commit is contained in:
@@ -12,9 +12,9 @@ const RelayConfig = () => {
|
|||||||
|
|
||||||
const handleClickAddRelay: JSX.EventHandler<HTMLFormElement, Event> = (ev) => {
|
const handleClickAddRelay: JSX.EventHandler<HTMLFormElement, Event> = (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const relayUrl = ev.currentTarget?.relayUrl?.value as string | undefined;
|
if (relayUrlInput().length > 0) return;
|
||||||
if (relayUrl == null) return;
|
|
||||||
addRelay(relayUrlInput());
|
addRelay(relayUrlInput());
|
||||||
|
setRelayUrlInput('');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -80,13 +80,13 @@ const DateFormatConfig = () => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3 class="font-bold">時刻の表記</h3>
|
<h3 class="font-bold">時刻の表記</h3>
|
||||||
<div class="flex flex-col justify-evenly gap-2 md:flex-row">
|
<div class="flex flex-col justify-evenly gap-2 sm:flex-row">
|
||||||
<For each={dateFormats}>
|
<For each={dateFormats}>
|
||||||
{({ id, name, example }) => (
|
{({ id, name, example }) => (
|
||||||
<div class="flex flex-1 flex-row items-center gap-1 md:flex-col">
|
<div class="flex flex-1 flex-row items-center gap-1 sm:flex-col">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="w-48 rounded border border-rose-300 p-2 font-bold md:w-full"
|
class="w-48 rounded border border-rose-300 p-2 font-bold sm:w-full"
|
||||||
classList={{
|
classList={{
|
||||||
'bg-rose-300': config().dateFormat === id,
|
'bg-rose-300': config().dateFormat === id,
|
||||||
'text-white': config().dateFormat === id,
|
'text-white': config().dateFormat === id,
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import {
|
|||||||
type JSX,
|
type JSX,
|
||||||
type Accessor,
|
type Accessor,
|
||||||
} from 'solid-js';
|
} from 'solid-js';
|
||||||
|
import { createMutation } from '@tanstack/solid-query';
|
||||||
import { Event as NostrEvent } from 'nostr-tools';
|
import { Event as NostrEvent } from 'nostr-tools';
|
||||||
|
import uniq from 'lodash/uniq';
|
||||||
|
|
||||||
import PaperAirplane from 'heroicons/24/solid/paper-airplane.svg';
|
import PaperAirplane from 'heroicons/24/solid/paper-airplane.svg';
|
||||||
import XMark from 'heroicons/24/outline/x-mark.svg';
|
import XMark from 'heroicons/24/outline/x-mark.svg';
|
||||||
@@ -41,26 +43,35 @@ const placeholder = (mode: NotePostFormProps['mode']) => {
|
|||||||
const NotePostForm: Component<NotePostFormProps> = (props) => {
|
const NotePostForm: Component<NotePostFormProps> = (props) => {
|
||||||
let textAreaRef: HTMLTextAreaElement | undefined;
|
let textAreaRef: HTMLTextAreaElement | undefined;
|
||||||
|
|
||||||
|
const [text, setText] = createSignal<string>('');
|
||||||
|
const clearText = () => setText('');
|
||||||
|
|
||||||
const { config } = useConfig();
|
const { config } = useConfig();
|
||||||
const getPubkey = usePubkey();
|
const getPubkey = usePubkey();
|
||||||
const commands = useCommands();
|
const commands = useCommands();
|
||||||
|
|
||||||
const [text, setText] = createSignal<string>('');
|
|
||||||
const clearText = () => setText('');
|
|
||||||
|
|
||||||
const replyTo = () => props.replyTo && eventWrapper(props.replyTo);
|
const replyTo = () => props.replyTo && eventWrapper(props.replyTo);
|
||||||
const mode = () => props.mode ?? 'normal';
|
const mode = () => props.mode ?? 'normal';
|
||||||
|
|
||||||
|
const publishTextNoteMutation = createMutation({
|
||||||
|
mutationKey: ['publishTextNote'],
|
||||||
|
mutationFn: commands.publishTextNote.bind(commands),
|
||||||
|
onSuccess: () => {
|
||||||
|
console.log('succeeded to post');
|
||||||
|
clearText();
|
||||||
|
props?.onClose();
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
console.error('error', err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const mentionedPubkeys: Accessor<string[]> = createMemo(
|
const mentionedPubkeys: Accessor<string[]> = createMemo(
|
||||||
() => replyTo()?.mentionedPubkeysWithoutAuthor() ?? [],
|
() => replyTo()?.mentionedPubkeysWithoutAuthor() ?? [],
|
||||||
);
|
);
|
||||||
const notifyPubkeys = (pubkey: string): string[] | undefined => {
|
const notifyPubkeys = (pubkey: string): string[] | undefined => {
|
||||||
if (mentionedPubkeys().length === 0) return undefined;
|
if (props.replyTo === undefined) return undefined;
|
||||||
return [...mentionedPubkeys(), pubkey];
|
return uniq([props.replyTo.pubkey, ...mentionedPubkeys(), pubkey]);
|
||||||
};
|
|
||||||
|
|
||||||
const handleChangeText: JSX.EventHandler<HTMLTextAreaElement, Event> = (ev) => {
|
|
||||||
setText(ev.currentTarget.value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
@@ -69,23 +80,14 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
console.error('pubkey is not available');
|
console.error('pubkey is not available');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
commands
|
publishTextNoteMutation.mutate({
|
||||||
.publishTextNote({
|
relayUrls: config().relayUrls,
|
||||||
relayUrls: config().relayUrls,
|
pubkey,
|
||||||
pubkey,
|
content: text(),
|
||||||
content: text(),
|
notifyPubkeys: notifyPubkeys(pubkey),
|
||||||
notifyPubkeys: notifyPubkeys(pubkey),
|
rootEventId: replyTo()?.rootEvent()?.id ?? replyTo()?.id,
|
||||||
rootEventId: replyTo()?.rootEvent()?.id ?? replyTo()?.id,
|
replyEventId: replyTo()?.id,
|
||||||
replyEventId: replyTo()?.id,
|
});
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
console.log('succeeded to post');
|
|
||||||
clearText();
|
|
||||||
props?.onClose();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error('error', err);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit: JSX.EventHandler<HTMLFormElement, Event> = (ev) => {
|
const handleSubmit: JSX.EventHandler<HTMLFormElement, Event> = (ev) => {
|
||||||
@@ -101,7 +103,9 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitDisabled = createMemo(() => text().trim().length === 0);
|
const submitDisabled = createMemo(
|
||||||
|
() => text().trim().length === 0 || publishTextNoteMutation.isLoading,
|
||||||
|
);
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -130,7 +134,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
class="rounded border-none"
|
class="rounded border-none"
|
||||||
rows={4}
|
rows={4}
|
||||||
placeholder={placeholder(mode())}
|
placeholder={placeholder(mode())}
|
||||||
onInput={handleChangeText}
|
onInput={(ev) => setText(ev.currentTarget.value)}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
value={text()}
|
value={text()}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ export type MentionedEventDisplayProps = {
|
|||||||
const MentionedEventDisplay = (props: MentionedEventDisplayProps) => {
|
const MentionedEventDisplay = (props: MentionedEventDisplayProps) => {
|
||||||
return (
|
return (
|
||||||
<Show
|
<Show
|
||||||
when={
|
when={props.mentionedEvent.marker != null && props.mentionedEvent.marker.length > 0}
|
||||||
props.mentionedEvent.marker == null ||
|
|
||||||
props.mentionedEvent.marker.length === 0 ||
|
|
||||||
props.mentionedEvent.marker === 'mention'
|
|
||||||
}
|
|
||||||
fallback={() => <EventLink eventId={props.mentionedEvent.eventId} />}
|
fallback={() => <EventLink eventId={props.mentionedEvent.eventId} />}
|
||||||
>
|
>
|
||||||
<div class="my-1 rounded border p-1">
|
<div class="my-1 rounded border p-1">
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
import {
|
import { Show, For, createSignal, createMemo, type JSX, type Component } from 'solid-js';
|
||||||
Show,
|
|
||||||
For,
|
|
||||||
createSignal,
|
|
||||||
createMemo,
|
|
||||||
type JSX,
|
|
||||||
type Component,
|
|
||||||
Match,
|
|
||||||
Switch,
|
|
||||||
} from 'solid-js';
|
|
||||||
import type { Event as NostrEvent } from 'nostr-tools';
|
import type { Event as NostrEvent } from 'nostr-tools';
|
||||||
|
import { createMutation } from '@tanstack/solid-query';
|
||||||
|
|
||||||
import HeartOutlined from 'heroicons/24/outline/heart.svg';
|
import HeartOutlined from 'heroicons/24/outline/heart.svg';
|
||||||
import HeartSolid from 'heroicons/24/solid/heart.svg';
|
import HeartSolid from 'heroicons/24/solid/heart.svg';
|
||||||
@@ -47,13 +39,10 @@ export type TextNoteDisplayProps = {
|
|||||||
const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
||||||
const { config } = useConfig();
|
const { config } = useConfig();
|
||||||
const formatDate = useFormatDate();
|
const formatDate = useFormatDate();
|
||||||
const commands = useCommands();
|
|
||||||
const pubkey = usePubkey();
|
const pubkey = usePubkey();
|
||||||
|
|
||||||
const [showReplyForm, setShowReplyForm] = createSignal(false);
|
const [showReplyForm, setShowReplyForm] = createSignal(false);
|
||||||
const [showMenu, setShowMenu] = createSignal(false);
|
const [showMenu, setShowMenu] = createSignal(false);
|
||||||
const [postingRepost, setPostingRepost] = createSignal(false);
|
|
||||||
const [postingReaction, setPostingReaction] = createSignal(false);
|
|
||||||
|
|
||||||
const event = createMemo(() => eventWrapper(props.event));
|
const event = createMemo(() => eventWrapper(props.event));
|
||||||
|
|
||||||
@@ -75,6 +64,34 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
eventId: props.event.id as string, // TODO いつかなおす
|
eventId: props.event.id as string, // TODO いつかなおす
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const commands = useCommands();
|
||||||
|
|
||||||
|
const publishReactionMutation = createMutation({
|
||||||
|
mutationKey: ['publishReaction', event().id],
|
||||||
|
mutationFn: commands.publishReaction.bind(commands),
|
||||||
|
onSuccess: () => {
|
||||||
|
console.log('succeeded to publish reaction');
|
||||||
|
invalidateReactions().catch((err) => console.error('failed to refetch reactions', err));
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
console.error('failed to publish reaction: ', err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const publishDeprecatedRepostMutation = createMutation({
|
||||||
|
mutationKey: ['publishDeprecatedRepost', event().id],
|
||||||
|
mutationFn: commands.publishDeprecatedRepost.bind(commands),
|
||||||
|
onSuccess: () => {
|
||||||
|
console.log('succeeded to publish deprecated reposts');
|
||||||
|
invalidateDeprecatedReposts().catch((err) =>
|
||||||
|
console.error('failed to refetch deprecated reposts', err),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
console.error('failed to publish deprecated repost: ', err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const isReactedByMe = createMemo(() => isReactedBy(pubkey()));
|
const isReactedByMe = createMemo(() => isReactedBy(pubkey()));
|
||||||
const isRepostedByMe = createMemo(() => isRepostedBy(pubkey()));
|
const isRepostedByMe = createMemo(() => isRepostedBy(pubkey()));
|
||||||
|
|
||||||
@@ -97,22 +114,14 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
// TODO remove reaction
|
// TODO remove reaction
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (postingRepost()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPostingRepost(true);
|
|
||||||
ensureNonNull([pubkey(), props.event.id] as const)(([pubkeyNonNull, eventIdNonNull]) => {
|
ensureNonNull([pubkey(), props.event.id] as const)(([pubkeyNonNull, eventIdNonNull]) => {
|
||||||
commands
|
publishDeprecatedRepostMutation.mutate({
|
||||||
.publishDeprecatedRepost({
|
relayUrls: config().relayUrls,
|
||||||
relayUrls: config().relayUrls,
|
pubkey: pubkeyNonNull,
|
||||||
pubkey: pubkeyNonNull,
|
eventId: eventIdNonNull,
|
||||||
eventId: eventIdNonNull,
|
notifyPubkey: props.event.pubkey,
|
||||||
notifyPubkey: props.event.pubkey,
|
});
|
||||||
})
|
|
||||||
.then(() => invalidateDeprecatedReposts())
|
|
||||||
.catch((err) => console.error('failed to repost: ', err))
|
|
||||||
.finally(() => setPostingRepost(false));
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,23 +130,15 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
// TODO remove reaction
|
// TODO remove reaction
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (postingReaction()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPostingReaction(true);
|
|
||||||
ensureNonNull([pubkey(), props.event.id] as const)(([pubkeyNonNull, eventIdNonNull]) => {
|
ensureNonNull([pubkey(), props.event.id] as const)(([pubkeyNonNull, eventIdNonNull]) => {
|
||||||
commands
|
publishReactionMutation.mutate({
|
||||||
.publishReaction({
|
relayUrls: config().relayUrls,
|
||||||
relayUrls: config().relayUrls,
|
pubkey: pubkeyNonNull,
|
||||||
pubkey: pubkeyNonNull,
|
content: '+',
|
||||||
content: '+',
|
eventId: eventIdNonNull,
|
||||||
eventId: eventIdNonNull,
|
notifyPubkey: props.event.pubkey,
|
||||||
notifyPubkey: props.event.pubkey,
|
});
|
||||||
})
|
|
||||||
.then(() => invalidateReactions())
|
|
||||||
.catch((err) => console.error('failed to publish reaction: ', err))
|
|
||||||
.finally(() => setPostingReaction(false));
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,14 +174,14 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<Show when={showReplyEvent()} keyed>
|
<Show when={showReplyEvent()} keyed>
|
||||||
{(id) => (
|
{(id) => (
|
||||||
<div class="border p-1">
|
<div class="mt-1 rounded border p-1">
|
||||||
<TextNoteDisplayById eventId={id} actions={false} embedding={false} />
|
<TextNoteDisplayById eventId={id} actions={false} embedding={false} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={event().mentionedPubkeysWithoutAuthor().length > 0}>
|
<Show when={event().mentionedPubkeys().length > 0}>
|
||||||
<div class="text-xs">
|
<div class="text-xs">
|
||||||
<For each={event().mentionedPubkeysWithoutAuthor()}>
|
<For each={event().mentionedPubkeys()}>
|
||||||
{(replyToPubkey: string) => (
|
{(replyToPubkey: string) => (
|
||||||
<span class="pr-1 text-blue-500 underline">
|
<span class="pr-1 text-blue-500 underline">
|
||||||
<GeneralUserMentionDisplay pubkey={replyToPubkey} />
|
<GeneralUserMentionDisplay pubkey={replyToPubkey} />
|
||||||
@@ -207,10 +208,14 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
class="flex shrink-0 items-center gap-1"
|
class="flex shrink-0 items-center gap-1"
|
||||||
classList={{
|
classList={{
|
||||||
'text-zinc-400': !isRepostedByMe(),
|
'text-zinc-400': !isRepostedByMe(),
|
||||||
'text-green-400': isRepostedByMe(),
|
'text-green-400': isRepostedByMe() || publishDeprecatedRepostMutation.isLoading,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button class="h-4 w-4" onClick={handleRepost} disabled={postingRepost()}>
|
<button
|
||||||
|
class="h-4 w-4"
|
||||||
|
onClick={handleRepost}
|
||||||
|
disabled={publishDeprecatedRepostMutation.isLoading}
|
||||||
|
>
|
||||||
<ArrowPathRoundedSquare />
|
<ArrowPathRoundedSquare />
|
||||||
</button>
|
</button>
|
||||||
<Show when={reposts().length > 0}>
|
<Show when={reposts().length > 0}>
|
||||||
@@ -221,10 +226,14 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
class="flex shrink-0 items-center gap-1"
|
class="flex shrink-0 items-center gap-1"
|
||||||
classList={{
|
classList={{
|
||||||
'text-zinc-400': !isReactedByMe(),
|
'text-zinc-400': !isReactedByMe(),
|
||||||
'text-rose-400': isReactedByMe(),
|
'text-rose-400': isReactedByMe() || publishReactionMutation.isLoading,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button class="h-4 w-4" onClick={handleReaction} disabled={postingReaction()}>
|
<button
|
||||||
|
class="h-4 w-4"
|
||||||
|
onClick={handleReaction}
|
||||||
|
disabled={publishReactionMutation.isLoading}
|
||||||
|
>
|
||||||
<Show when={isReactedByMe()} fallback={<HeartOutlined />}>
|
<Show when={isReactedByMe()} fallback={<HeartOutlined />}>
|
||||||
<HeartSolid />
|
<HeartSolid />
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export type MentionedEvent = {
|
|||||||
content: string;
|
content: string;
|
||||||
tagIndex: number;
|
tagIndex: number;
|
||||||
eventId: string;
|
eventId: string;
|
||||||
marker: string | null; // TODO 'reply' | 'root' | 'mention' | null;
|
marker: 'reply' | 'root' | 'mention' | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MentionedUser = {
|
export type MentionedUser = {
|
||||||
@@ -98,22 +98,21 @@ export const parseTextNote = (event: NostrEvent): ParsedTextNote => {
|
|||||||
result.push(mentionedUser);
|
result.push(mentionedUser);
|
||||||
} else if (tagName === 'e') {
|
} else if (tagName === 'e') {
|
||||||
const mention = eventWrapper(event)
|
const mention = eventWrapper(event)
|
||||||
.mentionedEvents()
|
.taggedEvents()
|
||||||
.find((ev) => ev.index === tagIndex);
|
.find((ev) => ev.index === tagIndex);
|
||||||
if (mention == null) return;
|
|
||||||
|
|
||||||
const mentionedEvent: MentionedEvent = {
|
const mentionedEvent: MentionedEvent = {
|
||||||
type: 'MentionedEvent',
|
type: 'MentionedEvent',
|
||||||
tagIndex,
|
tagIndex,
|
||||||
content: match[0],
|
content: match[0],
|
||||||
eventId: tag[1],
|
eventId: tag[1],
|
||||||
marker: mention.marker,
|
marker: mention?.marker,
|
||||||
};
|
};
|
||||||
result.push(mentionedEvent);
|
result.push(mentionedEvent);
|
||||||
}
|
}
|
||||||
} else if (match.groups?.nip19 && match.index >= pos) {
|
} else if (match.groups?.nip19 && match.index >= pos) {
|
||||||
try {
|
try {
|
||||||
const decoded = decode(match[0]);
|
const decoded = decode(match[0].toLowerCase());
|
||||||
const bech32Entity: Bech32Entity = {
|
const bech32Entity: Bech32Entity = {
|
||||||
type: 'Bech32Entity',
|
type: 'Bech32Entity',
|
||||||
content: match[0],
|
content: match[0],
|
||||||
|
|||||||
@@ -45,4 +45,3 @@ const applyContentFilter = (contentFilter: ContentFilter): boolean => {
|
|||||||
// DOUBLEQUOTE
|
// DOUBLEQUOTE
|
||||||
// A filter '"HELLO WORLD"' should match 'HELLO WORLD'
|
// A filter '"HELLO WORLD"' should match 'HELLO WORLD'
|
||||||
// A filter '"HELLO WORLD"' should not match 'hello world'
|
// A filter '"HELLO WORLD"' should not match 'hello world'
|
||||||
|
|
||||||
|
|||||||
@@ -38,46 +38,48 @@ const useCommands = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
// NIP-01
|
||||||
// NIP-01
|
const publishTextNote = ({
|
||||||
publishTextNote({
|
relayUrls,
|
||||||
relayUrls,
|
pubkey,
|
||||||
|
content,
|
||||||
|
tags,
|
||||||
|
notifyPubkeys,
|
||||||
|
rootEventId,
|
||||||
|
mentionEventIds,
|
||||||
|
replyEventId,
|
||||||
|
}: {
|
||||||
|
relayUrls: string[];
|
||||||
|
pubkey: string;
|
||||||
|
content: string;
|
||||||
|
tags?: string[][];
|
||||||
|
notifyPubkeys?: string[];
|
||||||
|
rootEventId?: string;
|
||||||
|
mentionEventIds?: string[];
|
||||||
|
replyEventId?: string;
|
||||||
|
}): Promise<Promise<void>[]> => {
|
||||||
|
const pTags = notifyPubkeys?.map((p) => ['p', p]) ?? [];
|
||||||
|
const eTags = [];
|
||||||
|
// NIP-10
|
||||||
|
if (rootEventId != null) eTags.push(['e', rootEventId, '', 'root']);
|
||||||
|
if (mentionEventIds != null)
|
||||||
|
mentionEventIds.forEach((id) => eTags.push(['e', id, '', 'mention']));
|
||||||
|
if (replyEventId != null) eTags.push(['e', replyEventId, '', 'reply']);
|
||||||
|
|
||||||
|
const mergedTags = [...eTags, ...pTags, ...(tags ?? [])];
|
||||||
|
|
||||||
|
const preSignedEvent: NostrEvent = {
|
||||||
|
kind: 1,
|
||||||
pubkey,
|
pubkey,
|
||||||
|
created_at: currentDate(),
|
||||||
|
tags: mergedTags,
|
||||||
content,
|
content,
|
||||||
tags,
|
};
|
||||||
notifyPubkeys,
|
return publishEvent(relayUrls, preSignedEvent);
|
||||||
rootEventId,
|
};
|
||||||
mentionEventIds,
|
|
||||||
replyEventId,
|
|
||||||
}: {
|
|
||||||
relayUrls: string[];
|
|
||||||
pubkey: string;
|
|
||||||
content: string;
|
|
||||||
tags?: string[][];
|
|
||||||
notifyPubkeys?: string[];
|
|
||||||
rootEventId?: string;
|
|
||||||
mentionEventIds?: string[];
|
|
||||||
replyEventId?: string;
|
|
||||||
}): Promise<Promise<void>[]> {
|
|
||||||
const pTags = notifyPubkeys?.map((p) => ['p', p]) ?? [];
|
|
||||||
const eTags = [];
|
|
||||||
// NIP-10
|
|
||||||
if (rootEventId != null) eTags.push(['e', rootEventId, '', 'root']);
|
|
||||||
if (mentionEventIds != null)
|
|
||||||
mentionEventIds.forEach((id) => eTags.push(['e', id, '', 'mention']));
|
|
||||||
if (replyEventId != null) eTags.push(['e', replyEventId, '', 'reply']);
|
|
||||||
|
|
||||||
const mergedTags = [...eTags, ...pTags, ...(tags ?? [])];
|
return {
|
||||||
|
publishTextNote,
|
||||||
const preSignedEvent: NostrEvent = {
|
|
||||||
kind: 1,
|
|
||||||
pubkey,
|
|
||||||
created_at: currentDate(),
|
|
||||||
tags: mergedTags,
|
|
||||||
content,
|
|
||||||
};
|
|
||||||
return publishEvent(relayUrls, preSignedEvent);
|
|
||||||
},
|
|
||||||
// NIP-25
|
// NIP-25
|
||||||
publishReaction({
|
publishReaction({
|
||||||
relayUrls,
|
relayUrls,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export type UseDeprecatedReposts = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { exec } = useBatchedEvents<UseDeprecatedRepostsProps>(() => ({
|
const { exec } = useBatchedEvents<UseDeprecatedRepostsProps>(() => ({
|
||||||
interval: 5000,
|
interval: 3400,
|
||||||
generateKey: ({ eventId }) => eventId,
|
generateKey: ({ eventId }) => eventId,
|
||||||
mergeFilters: (args) => {
|
mergeFilters: (args) => {
|
||||||
const eventIds = args.map((arg) => arg.eventId);
|
const eventIds = args.map((arg) => arg.eventId);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export type UseReactions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { exec } = useBatchedEvents<UseReactionsProps>(() => ({
|
const { exec } = useBatchedEvents<UseReactionsProps>(() => ({
|
||||||
interval: 5000,
|
interval: 3400,
|
||||||
generateKey: ({ eventId }) => eventId,
|
generateKey: ({ eventId }) => eventId,
|
||||||
mergeFilters: (args) => {
|
mergeFilters: (args) => {
|
||||||
const eventIds = args.map((arg) => arg.eventId);
|
const eventIds = args.map((arg) => arg.eventId);
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
const filter = {
|
const filter = {
|
||||||
kinds: [1],
|
kinds: [1],
|
||||||
'#e': [
|
'#e': [rootEventId, currentEventId],
|
||||||
rootEventId,
|
|
||||||
currentEventId,
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ const Home: Component = () => {
|
|||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
kinds: [1, 6],
|
kinds: [1, 6],
|
||||||
authors: [...followingPubkeys(), pubkeyNonNull],
|
authors: followingPubkeys(),
|
||||||
limit: 25,
|
limit: 25,
|
||||||
since: Math.floor(Date.now() / 1000) - 12 * 60 * 60,
|
since: Math.floor(Date.now() / 1000) - 12 * 60 * 60,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const defaultAbsoluteDateShortFormatter = (parsedDate: AbsoluteDate): string =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const calcDiffSec = (date: Date, currentDate: Date): number =>
|
const calcDiffSec = (date: Date, currentDate: Date): number =>
|
||||||
(Number(currentDate) - Number(date)) / 1000;
|
Math.round(Number(currentDate) - Number(date)) / 1000;
|
||||||
|
|
||||||
const parseDateDiff = (date: Date, currentDate: Date): RelativeDate => {
|
const parseDateDiff = (date: Date, currentDate: Date): RelativeDate => {
|
||||||
const diffSec = calcDiffSec(date, currentDate);
|
const diffSec = calcDiffSec(date, currentDate);
|
||||||
|
|||||||
Reference in New Issue
Block a user