@ -95,6 +95,22 @@ export function NoteCreator() {
|
|||||||
extraTags ??= [];
|
extraTags ??= [];
|
||||||
extraTags.push(...note.pollOptions.map((a, i) => ["poll_option", i.toString(), a]));
|
extraTags.push(...note.pollOptions.map((a, i) => ["poll_option", i.toString(), a]));
|
||||||
}
|
}
|
||||||
|
// add quote repost
|
||||||
|
if (note.quote) {
|
||||||
|
if (!note.note.endsWith("\n")) {
|
||||||
|
note.note += "\n";
|
||||||
|
}
|
||||||
|
const link = NostrLink.fromEvent(note.quote);
|
||||||
|
note.note += `nostr:${link.encode()}`;
|
||||||
|
const quoteTag = link.toEventTag();
|
||||||
|
if (quoteTag) {
|
||||||
|
extraTags ??= [];
|
||||||
|
if (quoteTag[0] === "e") {
|
||||||
|
quoteTag[0] = "q"; // how to 'q' tag replacable events?
|
||||||
|
}
|
||||||
|
extraTags.push(quoteTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
const hk = (eb: EventBuilder) => {
|
const hk = (eb: EventBuilder) => {
|
||||||
extraTags?.forEach(t => eb.tag(t));
|
extraTags?.forEach(t => eb.tag(t));
|
||||||
eb.kind(kind);
|
eb.kind(kind);
|
||||||
@ -464,6 +480,10 @@ export function NoteCreator() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{note.replyTo && (
|
{note.replyTo && (
|
||||||
|
<>
|
||||||
|
<h4>
|
||||||
|
<FormattedMessage defaultMessage="Reply To" />
|
||||||
|
</h4>
|
||||||
<Note
|
<Note
|
||||||
data={note.replyTo}
|
data={note.replyTo}
|
||||||
related={[]}
|
related={[]}
|
||||||
@ -476,6 +496,26 @@ export function NoteCreator() {
|
|||||||
longFormPreview: true,
|
longFormPreview: true,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{note.quote && (
|
||||||
|
<>
|
||||||
|
<h4>
|
||||||
|
<FormattedMessage defaultMessage="Quote Repost" />
|
||||||
|
</h4>
|
||||||
|
<Note
|
||||||
|
data={note.quote}
|
||||||
|
related={[]}
|
||||||
|
options={{
|
||||||
|
showFooter: false,
|
||||||
|
showContextMenu: false,
|
||||||
|
showTime: false,
|
||||||
|
canClick: false,
|
||||||
|
showMedia: false,
|
||||||
|
longFormPreview: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{note.preview && getPreviewNote()}
|
{note.preview && getPreviewNote()}
|
||||||
{!note.preview && (
|
{!note.preview && (
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { HTMLProps, useContext, useEffect, useState } from "react";
|
import React, { HTMLProps, useContext, useEffect, useState } from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { useLongPress } from "use-long-press";
|
import { useLongPress } from "use-long-press";
|
||||||
import { TaggedNostrEvent, ParsedZap, countLeadingZeros, NostrLink } from "@snort/system";
|
import { TaggedNostrEvent, ParsedZap, countLeadingZeros, NostrLink } from "@snort/system";
|
||||||
import { SnortContext, useUserProfile } from "@snort/system-react";
|
import { SnortContext, useUserProfile } from "@snort/system-react";
|
||||||
|
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||||
|
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "Number";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "Hooks/useEventPublisher";
|
||||||
@ -20,6 +21,7 @@ import { System } from "index";
|
|||||||
import { Zapper, ZapTarget } from "Zapper";
|
import { Zapper, ZapTarget } from "Zapper";
|
||||||
import { getDisplayName } from "Element/User/DisplayName";
|
import { getDisplayName } from "Element/User/DisplayName";
|
||||||
import { useNoteCreator } from "State/NoteCreator";
|
import { useNoteCreator } from "State/NoteCreator";
|
||||||
|
import Icon from "Icons/Icon";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
@ -56,8 +58,8 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
const author = useUserProfile(ev.pubkey);
|
const author = useUserProfile(ev.pubkey);
|
||||||
const interactionCache = useInteractionCache(publicKey, ev.id);
|
const interactionCache = useInteractionCache(publicKey, ev.id);
|
||||||
const publisher = useEventPublisher();
|
const publisher = useEventPublisher();
|
||||||
const note = useNoteCreator(n => ({ show: n.show, replyTo: n.replyTo, update: n.update }));
|
const note = useNoteCreator(n => ({ show: n.show, replyTo: n.replyTo, update: n.update, quote: n.quote }));
|
||||||
const willRenderNoteCreator = note.show && note.replyTo?.id === ev.id;
|
const willRenderNoteCreator = note.show && (note.replyTo?.id === ev.id || note.quote);
|
||||||
const [tip, setTip] = useState(false);
|
const [tip, setTip] = useState(false);
|
||||||
const [zapping, setZapping] = useState(false);
|
const [zapping, setZapping] = useState(false);
|
||||||
const walletState = useWallet();
|
const walletState = useWallet();
|
||||||
@ -211,16 +213,40 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
function repostIcon() {
|
function repostIcon() {
|
||||||
if (readonly) return;
|
if (readonly) return;
|
||||||
return (
|
return (
|
||||||
|
<Menu
|
||||||
|
menuButton={
|
||||||
<AsyncFooterIcon
|
<AsyncFooterIcon
|
||||||
className={hasReposted() ? "reacted" : ""}
|
className={hasReposted() ? "reacted" : ""}
|
||||||
iconName="repeat"
|
iconName="repeat"
|
||||||
title={formatMessage({ defaultMessage: "Repost" })}
|
title={formatMessage({ defaultMessage: "Repost" })}
|
||||||
value={reposts.length}
|
value={reposts.length}
|
||||||
onClick={async () => {
|
|
||||||
if (readonly) return;
|
|
||||||
await repost();
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
|
menuClassName="ctx-menu"
|
||||||
|
align="start">
|
||||||
|
<div className="close-menu-container">
|
||||||
|
{/* This menu item serves as a "close menu" button;
|
||||||
|
it allows the user to click anywhere nearby the menu to close it. */}
|
||||||
|
<MenuItem>
|
||||||
|
<div className="close-menu" />
|
||||||
|
</MenuItem>
|
||||||
|
</div>
|
||||||
|
<MenuItem onClick={() => repost()} disabled={hasReposted()}>
|
||||||
|
<Icon name="repeat" />
|
||||||
|
<FormattedMessage defaultMessage="Repost" />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() =>
|
||||||
|
note.update(n => {
|
||||||
|
n.reset();
|
||||||
|
n.quote = ev;
|
||||||
|
n.show = true;
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
<Icon name="edit" />
|
||||||
|
<FormattedMessage defaultMessage="Quote Repost" />
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ interface NoteCreatorDataSnapshot {
|
|||||||
advanced: boolean;
|
advanced: boolean;
|
||||||
preview?: NostrEvent;
|
preview?: NostrEvent;
|
||||||
replyTo?: TaggedNostrEvent;
|
replyTo?: TaggedNostrEvent;
|
||||||
|
quote?: TaggedNostrEvent;
|
||||||
selectedCustomRelays?: Array<string>;
|
selectedCustomRelays?: Array<string>;
|
||||||
zapSplits?: Array<ZapTarget>;
|
zapSplits?: Array<ZapTarget>;
|
||||||
sensitive?: string;
|
sensitive?: string;
|
||||||
@ -55,6 +56,7 @@ class NoteCreatorStore extends ExternalStore<NoteCreatorDataSnapshot> {
|
|||||||
d.sendStarted = false;
|
d.sendStarted = false;
|
||||||
d.preview = undefined;
|
d.preview = undefined;
|
||||||
d.replyTo = undefined;
|
d.replyTo = undefined;
|
||||||
|
d.quote = undefined;
|
||||||
d.selectedCustomRelays = undefined;
|
d.selectedCustomRelays = undefined;
|
||||||
d.zapSplits = undefined;
|
d.zapSplits = undefined;
|
||||||
d.sensitive = undefined;
|
d.sensitive = undefined;
|
||||||
|
@ -241,6 +241,9 @@
|
|||||||
"89q5wc": {
|
"89q5wc": {
|
||||||
"defaultMessage": "Confirm Reposts"
|
"defaultMessage": "Confirm Reposts"
|
||||||
},
|
},
|
||||||
|
"8ED/4u": {
|
||||||
|
"defaultMessage": "Reply To"
|
||||||
|
},
|
||||||
"8Kboo2": {
|
"8Kboo2": {
|
||||||
"defaultMessage": "Scan this QR code with your signer app to get started"
|
"defaultMessage": "Scan this QR code with your signer app to get started"
|
||||||
},
|
},
|
||||||
@ -344,6 +347,9 @@
|
|||||||
"C5xzTC": {
|
"C5xzTC": {
|
||||||
"defaultMessage": "Premium"
|
"defaultMessage": "Premium"
|
||||||
},
|
},
|
||||||
|
"C7642/": {
|
||||||
|
"defaultMessage": "Quote Repost"
|
||||||
|
},
|
||||||
"C81/uG": {
|
"C81/uG": {
|
||||||
"defaultMessage": "Logout"
|
"defaultMessage": "Logout"
|
||||||
},
|
},
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
"7hp70g": "NIP-05",
|
"7hp70g": "NIP-05",
|
||||||
"8/vBbP": "Reposts ({n})",
|
"8/vBbP": "Reposts ({n})",
|
||||||
"89q5wc": "Confirm Reposts",
|
"89q5wc": "Confirm Reposts",
|
||||||
|
"8ED/4u": "Reply To",
|
||||||
"8Kboo2": "Scan this QR code with your signer app to get started",
|
"8Kboo2": "Scan this QR code with your signer app to get started",
|
||||||
"8QDesP": "Zap {n} sats",
|
"8QDesP": "Zap {n} sats",
|
||||||
"8Rkoyb": "Recipient",
|
"8Rkoyb": "Recipient",
|
||||||
@ -112,6 +113,7 @@
|
|||||||
"BjNwZW": "Nostr address (nip05)",
|
"BjNwZW": "Nostr address (nip05)",
|
||||||
"C1LjMx": "Lightning Donation",
|
"C1LjMx": "Lightning Donation",
|
||||||
"C5xzTC": "Premium",
|
"C5xzTC": "Premium",
|
||||||
|
"C7642/": "Quote Repost",
|
||||||
"C81/uG": "Logout",
|
"C81/uG": "Logout",
|
||||||
"C8HhVE": "Suggested Follows",
|
"C8HhVE": "Suggested Follows",
|
||||||
"CHTbO3": "Failed to load invoice",
|
"CHTbO3": "Failed to load invoice",
|
||||||
|
Reference in New Issue
Block a user