diff --git a/.changeset/clever-pumas-build.md b/.changeset/clever-pumas-build.md new file mode 100644 index 000000000..cf850dc09 --- /dev/null +++ b/.changeset/clever-pumas-build.md @@ -0,0 +1,5 @@ +--- +"nostrudel": minor +--- + +Add option to set zap splits when creating note diff --git a/src/components/event-zap-modal/input-step.tsx b/src/components/event-zap-modal/input-step.tsx index 45c402c2a..16c50dead 100644 --- a/src/components/event-zap-modal/input-step.tsx +++ b/src/components/event-zap-modal/input-step.tsx @@ -98,7 +98,7 @@ export default function InputStep({ /> )} - setValue("amount", amount)} /> + setValue("amount", amount, { shouldDirty: true })} /> & { variant?: CardProps["variant"]; showReplyButton?: boolean; hideDrawerButton?: boolean; + hideThreadLink?: boolean; registerIntersectionEntity?: boolean; }; export const Note = React.memo( @@ -58,6 +59,7 @@ export const Note = React.memo( variant = "outline", showReplyButton, hideDrawerButton, + hideThreadLink, registerIntersectionEntity = true, ...props }: NoteProps) => { @@ -96,6 +98,11 @@ export const Note = React.memo( + {!hideThreadLink && ( + + thread + + )} {showSignatureVerification && } {!hideDrawerButton && ( diff --git a/src/components/post-modal/index.tsx b/src/components/post-modal/index.tsx index 44c682c23..2d27d4e2d 100644 --- a/src/components/post-modal/index.tsx +++ b/src/components/post-modal/index.tsx @@ -22,10 +22,10 @@ import dayjs from "dayjs"; import { useForm } from "react-hook-form"; import { Kind } from "nostr-tools"; +import { ArrowDownSIcon, ArrowUpSIcon, ImageIcon } from "../icons"; import NostrPublishAction from "../../classes/nostr-publish-action"; import { useWriteRelayUrls } from "../../hooks/use-client-relays"; import { useSigningContext } from "../../providers/signing-provider"; -import { ArrowDownSIcon, ArrowUpSIcon, ImageIcon } from "../icons"; import { NoteContents } from "../note/note-contents"; import { PublishDetails } from "../publish-details"; import { TrustProvider } from "../../providers/trust"; @@ -35,12 +35,25 @@ import { ensureNotifyPubkeys, finalizeNote, getContentMentions, + setZapSplit, } from "../../helpers/nostr/post"; import { UserAvatarStack } from "../compact-user-stack"; import MagicTextArea, { RefType } from "../magic-textarea"; import { useContextEmojis } from "../../providers/emoji-provider"; import { nostrBuildUploadImage } from "../../helpers/nostr-build"; import CommunitySelect from "./community-select"; +import ZapSplitCreator, { fillRemainingPercent } from "./zap-split-creator"; +import { EventSplit } from "../../helpers/nostr/zaps"; +import { useCurrentAccount } from "../../hooks/use-current-account"; +import useCacheForm from "../../hooks/use-cache-form"; + +type FormValues = { + content: string; + nsfw: boolean; + nsfwReason: string; + community: string; + split: EventSplit; +}; export default function PostModal({ isOpen, @@ -48,23 +61,30 @@ export default function PostModal({ initContent = "", }: Omit & { initContent?: string }) { const toast = useToast(); + const account = useCurrentAccount()!; const { requestSignature } = useSigningContext(); const writeRelays = useWriteRelayUrls(); const [publishAction, setPublishAction] = useState(); const emojis = useContextEmojis(); const moreOptions = useDisclosure(); - const { getValues, setValue, watch, register, handleSubmit, formState } = useForm({ + const { getValues, setValue, watch, register, handleSubmit, formState, reset } = useForm({ defaultValues: { content: initContent, nsfw: false, nsfwReason: "", community: "", + split: [] as EventSplit, }, + mode: "all", }); watch("content"); watch("nsfw"); watch("nsfwReason"); + watch("split"); + + // cache form to localStorage + useCacheForm("new-note", getValues, setValue, formState); const textAreaRef = useRef(null); const imageUploadRef = useRef(null); @@ -81,8 +101,10 @@ export default function PostModal({ const content = getValues().content; const position = textAreaRef.current?.getCaretPosition(); if (position !== undefined) { - setValue("content", content.slice(0, position) + imageUrl + " " + content.slice(position)); - } else setValue("content", content + imageUrl + " "); + setValue("content", content.slice(0, position) + imageUrl + " " + content.slice(position), { + shouldDirty: true, + }); + } else setValue("content", content + imageUrl + " ", { shouldDirty: true }); } catch (e) { if (e instanceof Error) toast({ description: e.message, status: "error" }); } @@ -92,7 +114,7 @@ export default function PostModal({ ); const getDraft = useCallback(() => { - const { content, nsfw, nsfwReason, community } = getValues(); + const { content, nsfw, nsfwReason, community, split } = getValues(); let updatedDraft = finalizeNote({ content: content, @@ -113,6 +135,9 @@ export default function PostModal({ const contentMentions = getContentMentions(updatedDraft.content); updatedDraft = createEmojiTags(updatedDraft, emojis); updatedDraft = ensureNotifyPubkeys(updatedDraft, contentMentions); + if (split.length > 0) { + updatedDraft = setZapSplit(updatedDraft, fillRemainingPercent(split, account.pubkey)); + } return updatedDraft; }, [getValues, emojis]); @@ -146,7 +171,7 @@ export default function PostModal({ autoFocus mb="2" value={getValues().content} - onChange={(e) => setValue("content", e.target.value)} + onChange={(e) => setValue("content", e.target.value, { shouldDirty: true })} rows={5} isRequired instanceRef={(inst) => (textAreaRef.current = inst)} @@ -192,9 +217,14 @@ export default function PostModal({ {mentions.length > 0 && } - + +