fix: note broadcaster bug / createPortal for modal

This commit is contained in:
Kieran 2023-10-21 21:45:50 +01:00
parent c1ea68b296
commit 0e3661afc6
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
5 changed files with 37 additions and 39 deletions

View File

@ -307,18 +307,18 @@ export function NoteCreator() {
onChange={e => { onChange={e => {
note.update( note.update(
v => v =>
(v.selectedCustomRelays = (v.selectedCustomRelays =
// set false if all relays selected // set false if all relays selected
e.target.checked && e.target.checked &&
note.selectedCustomRelays && note.selectedCustomRelays &&
note.selectedCustomRelays.length == a.length - 1 note.selectedCustomRelays.length == a.length - 1
? undefined ? undefined
: // otherwise return selectedCustomRelays with target relay added / removed : // otherwise return selectedCustomRelays with target relay added / removed
a.filter(el => a.filter(el =>
el === r el === r
? e.target.checked ? e.target.checked
: !note.selectedCustomRelays || note.selectedCustomRelays.includes(el), : !note.selectedCustomRelays || note.selectedCustomRelays.includes(el),
)), )),
); );
}} }}
/> />
@ -387,9 +387,9 @@ export function NoteCreator() {
onChange={e => onChange={e =>
note.update( note.update(
v => v =>
(v.zapSplits = arr.map((vv, ii) => (v.zapSplits = arr.map((vv, ii) =>
ii === i ? { ...vv, weight: Number(e.target.value) } : vv, ii === i ? { ...vv, weight: Number(e.target.value) } : vv,
)), )),
) )
} }
/> />
@ -570,18 +570,20 @@ export function NoteCreator() {
); );
} }
function reset() {
note.update(v => {
v.reset();
v.show = false;
});
}
if (!note.show) return null; if (!note.show) return null;
return ( return (
<Modal id="note-creator" className="note-creator-modal" onClose={() => note.update(v => (v.show = false))}> <Modal id="note-creator" className="note-creator-modal" onClose={reset}>
{note.sending && ( {note.sending && (
<NoteBroadcaster <NoteBroadcaster
evs={note.sending} evs={note.sending}
onClose={() => { onClose={reset}
note.update(n => {
n.reset();
n.show = false;
});
}}
customRelays={note.selectedCustomRelays} customRelays={note.selectedCustomRelays}
/> />
)} )}

View File

@ -1,6 +1,7 @@
import "./NoteCreatorButton.css"; import "./NoteCreatorButton.css";
import { useRef, useMemo } from "react"; import { useRef, useMemo } from "react";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import classNames from "classnames";
import { isFormElement } from "SnortUtils"; import { isFormElement } from "SnortUtils";
import useKeyboardShortcut from "Hooks/useKeyboardShortcut"; import useKeyboardShortcut from "Hooks/useKeyboardShortcut";
@ -8,7 +9,6 @@ import useLogin from "Hooks/useLogin";
import Icon from "Icons/Icon"; import Icon from "Icons/Icon";
import { useNoteCreator } from "State/NoteCreator"; import { useNoteCreator } from "State/NoteCreator";
import { NoteCreator } from "./NoteCreator"; import { NoteCreator } from "./NoteCreator";
import classNames from "classnames";
export const NoteCreatorButton = ({ className }: { className?: string }) => { export const NoteCreatorButton = ({ className }: { className?: string }) => {
const buttonRef = useRef<HTMLButtonElement>(null); const buttonRef = useRef<HTMLButtonElement>(null);
@ -27,15 +27,14 @@ export const NoteCreatorButton = ({ className }: { className?: string }) => {
}); });
const shouldHideNoteCreator = useMemo(() => { const shouldHideNoteCreator = useMemo(() => {
const isReplyNoteCreatorShowing = replyTo && show; const isReply = replyTo && show;
const hideOn = ["/settings", "/messages", "/new", "/login", "/donate", "/e", "/subscribe"]; const hideOn = ["/settings", "/messages", "/new", "/login", "/donate", "/e", "/nevent", "/note1", "/naddr", "/subscribe"];
return readonly || isReplyNoteCreatorShowing || hideOn.some(a => location.pathname.startsWith(a)); return (readonly || hideOn.some(a => location.pathname.startsWith(a))) && !isReply;
}, [location, readonly]); }, [location, readonly]);
if (shouldHideNoteCreator) return null;
return ( return (
<> <>
<button {!shouldHideNoteCreator && <button
ref={buttonRef} ref={buttonRef}
className={classNames("primary circle", className)} className={classNames("primary circle", className)}
onClick={() => onClick={() =>
@ -45,7 +44,7 @@ export const NoteCreatorButton = ({ className }: { className?: string }) => {
}) })
}> }>
<Icon name="plus" size={16} /> <Icon name="plus" size={16} />
</button> </button>}
<NoteCreator key="global-note-creator" /> <NoteCreator key="global-note-creator" />
</> </>
); );

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react"; import React, { forwardRef, useEffect, useState } from "react";
import { FormattedMessage, 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";
@ -10,7 +10,6 @@ import classNames from "classnames";
import { formatShort } from "Number"; import { formatShort } from "Number";
import useEventPublisher from "Hooks/useEventPublisher"; import useEventPublisher from "Hooks/useEventPublisher";
import { delay, findTag, getDisplayName } from "SnortUtils"; import { delay, findTag, getDisplayName } from "SnortUtils";
import { NoteCreator } from "Element/Event/NoteCreator";
import SendSats from "Element/SendSats"; import SendSats from "Element/SendSats";
import { ZapsSummary } from "Element/Event/Zap"; import { ZapsSummary } from "Element/Event/Zap";
import { AsyncIcon, AsyncIconProps } from "Element/AsyncIcon"; import { AsyncIcon, AsyncIconProps } from "Element/AsyncIcon";
@ -58,7 +57,6 @@ export default function NoteFooter(props: NoteFooterProps) {
const interactionCache = useInteractionCache(publicKey, ev.id); const interactionCache = useInteractionCache(publicKey, ev.id);
const { publisher, system } = useEventPublisher(); const { publisher, system } = useEventPublisher();
const note = useNoteCreator(n => ({ show: n.show, replyTo: n.replyTo, update: n.update, quote: n.quote })); 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 || 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();
@ -303,7 +301,6 @@ export default function NoteFooter(props: NoteFooterProps) {
{tipButton()} {tipButton()}
{powIcon()} {powIcon()}
</div> </div>
{willRenderNoteCreator && <NoteCreator key={`note-creator-${ev.id}`} />}
<SendSats targets={getZapTarget()} onClose={() => setTip(false)} show={tip} note={ev.id} allocatePool={true} /> <SendSats targets={getZapTarget()} onClose={() => setTip(false)} show={tip} note={ev.id} allocatePool={true} />
</div> </div>
<ZapsSummary zaps={zaps} /> <ZapsSummary zaps={zaps} />
@ -311,7 +308,7 @@ export default function NoteFooter(props: NoteFooterProps) {
); );
} }
function AsyncFooterIcon(props: AsyncIconProps & { value: number }) { const AsyncFooterIcon = forwardRef((props: AsyncIconProps & { value: number }) => {
const mergedProps = { const mergedProps = {
...props, ...props,
iconSize: 18, iconSize: 18,
@ -322,4 +319,4 @@ function AsyncFooterIcon(props: AsyncIconProps & { value: number }) {
{props.value > 0 && <div className="reaction-pill-number">{formatShort(props.value)}</div>} {props.value > 0 && <div className="reaction-pill-number">{formatShort(props.value)}</div>}
</AsyncIcon> </AsyncIcon>
); );
} });

View File

@ -1,3 +1,4 @@
import { createPortal } from "react-dom";
import "./Modal.css"; import "./Modal.css";
import { ReactNode, useEffect } from "react"; import { ReactNode, useEffect } from "react";
@ -26,7 +27,7 @@ export default function Modal(props: ModalProps) {
}; };
}, []); }, []);
return ( return createPortal(
<div className={`modal${props.className ? ` ${props.className}` : ""}`} onClick={props.onClose}> <div className={`modal${props.className ? ` ${props.className}` : ""}`} onClick={props.onClose}>
<div className="modal-body" onClick={props.onClose}> <div className="modal-body" onClick={props.onClose}>
<div <div
@ -37,6 +38,5 @@ export default function Modal(props: ModalProps) {
{props.children} {props.children}
</div> </div>
</div> </div>
</div> </div>, document.body);
);
} }

View File

@ -1,4 +1,5 @@
import { ReactNode, useSyncExternalStore } from "react"; import { ReactNode, useSyncExternalStore } from "react";
import { createPortal } from "react-dom";
import { v4 as uuid } from "uuid"; import { v4 as uuid } from "uuid";
import { ExternalStore, unixNow } from "@snort/shared"; import { ExternalStore, unixNow } from "@snort/shared";
@ -42,7 +43,7 @@ export default function Toaster() {
() => Toastore.snapshot(), () => Toastore.snapshot(),
); );
return ( return createPortal(
<div className="toaster"> <div className="toaster">
{toast.map(a => ( {toast.map(a => (
<div className="card flex" key={a.id}> <div className="card flex" key={a.id}>
@ -50,6 +51,5 @@ export default function Toaster() {
{a.element} {a.element}
</div> </div>
))} ))}
</div> </div>, document.body);
);
} }