From 27abb20fd7c720c69f4f1d854d1814cdc2812063 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Thu, 31 Aug 2023 13:55:32 -0500 Subject: [PATCH] Show host emojis when writing stream chat message --- .changeset/nervous-ladybugs-drop.md | 5 + src/providers/emoji-provider.tsx | 6 +- src/views/streams/stream/index.tsx | 5 +- .../stream/stream-chat/chat-message-form.tsx | 95 ++++++++++ .../streams/stream/stream-chat/index.tsx | 170 +++++------------- 5 files changed, 146 insertions(+), 135 deletions(-) create mode 100644 .changeset/nervous-ladybugs-drop.md create mode 100644 src/views/streams/stream/stream-chat/chat-message-form.tsx diff --git a/.changeset/nervous-ladybugs-drop.md b/.changeset/nervous-ladybugs-drop.md new file mode 100644 index 000000000..808d87fd3 --- /dev/null +++ b/.changeset/nervous-ladybugs-drop.md @@ -0,0 +1,5 @@ +--- +"nostrudel": minor +--- + +Show host emojis when writing stream chat message diff --git a/src/providers/emoji-provider.tsx b/src/providers/emoji-provider.tsx index 627e5fddd..836ba663d 100644 --- a/src/providers/emoji-provider.tsx +++ b/src/providers/emoji-provider.tsx @@ -23,9 +23,9 @@ export function DefaultEmojiProvider({ children }: PropsWithChildren) { return {children}; } -export function UserEmojiProvider({ children }: PropsWithChildren) { +export function UserEmojiProvider({ children, pubkey }: PropsWithChildren & { pubkey?: string }) { const account = useCurrentAccount(); - const userPacks = useUserEmojiPacks(account?.pubkey); + const userPacks = useUserEmojiPacks(pubkey || account?.pubkey); const events = useReplaceableEvents(userPacks?.packs); const emojis = events @@ -34,8 +34,6 @@ export function UserEmojiProvider({ children }: PropsWithChildren) { ) .flat(); - console.log(userPacks, emojis); - return {children}; } diff --git a/src/views/streams/stream/index.tsx b/src/views/streams/stream/index.tsx index 95baea8ed..1482a1db3 100644 --- a/src/views/streams/stream/index.tsx +++ b/src/views/streams/stream/index.tsx @@ -35,6 +35,7 @@ import RelaySelectionProvider from "../../../providers/relay-selection-provider" import StreamerCards from "../components/streamer-cards"; import { useAppTitle } from "../../../hooks/use-app-title"; import StreamSatsPerMinute from "../components/stream-sats-per-minute"; +import { UserEmojiProvider } from "../../../providers/emoji-provider"; function StreamPage({ stream, displayMode }: { stream: ParsedStream; displayMode?: ChatDisplayMode }) { useAppTitle(stream.title); @@ -194,7 +195,9 @@ export default function StreamView() { return ( // add snort and damus relays so zap.stream will always see zaps - + + + ); } diff --git a/src/views/streams/stream/stream-chat/chat-message-form.tsx b/src/views/streams/stream/stream-chat/chat-message-form.tsx new file mode 100644 index 000000000..9e5542944 --- /dev/null +++ b/src/views/streams/stream/stream-chat/chat-message-form.tsx @@ -0,0 +1,95 @@ +import { useMemo } from "react"; +import { Box, Button, IconButton, useDisclosure, useToast } from "@chakra-ui/react"; +import { useForm } from "react-hook-form"; + +import { ParsedStream, buildChatMessage } from "../../../../helpers/nostr/stream"; +import { useRelaySelectionRelays } from "../../../../providers/relay-selection-provider"; +import { useUserRelays } from "../../../../hooks/use-user-relays"; +import { RelayMode } from "../../../../classes/relay"; +import { unique } from "../../../../helpers/array"; +import { LightningIcon } from "../../../../components/icons"; +import useUserLNURLMetadata from "../../../../hooks/use-user-lnurl-metadata"; +import ZapModal from "../../../../components/zap-modal"; +import { useInvoiceModalContext } from "../../../../providers/invoice-modal"; +import { useSigningContext } from "../../../../providers/signing-provider"; +import NostrPublishAction from "../../../../classes/nostr-publish-action"; +import { createEmojiTags, ensureNotifyContentMentions } from "../../../../helpers/nostr/post"; +import { useContextEmojis } from "../../../../providers/emoji-provider"; +import MagicTextArea from "../../../../components/magic-textarea"; + +export default function ChatMessageForm({ stream }: { stream: ParsedStream }) { + const toast = useToast(); + const emojis = useContextEmojis(); + const streamRelays = useRelaySelectionRelays(); + const hostReadRelays = useUserRelays(stream.host) + .filter((r) => r.mode & RelayMode.READ) + .map((r) => r.url); + + const relays = useMemo(() => unique([...streamRelays, ...hostReadRelays]), [hostReadRelays, streamRelays]); + + const { requestSignature } = useSigningContext(); + const { setValue, handleSubmit, formState, reset, getValues, watch } = useForm({ + defaultValues: { content: "" }, + }); + const sendMessage = handleSubmit(async (values) => { + try { + let draft = buildChatMessage(stream, values.content); + draft = ensureNotifyContentMentions(draft); + draft = createEmojiTags(draft, emojis); + const signed = await requestSignature(draft); + new NostrPublishAction("Send Chat", relays, signed); + reset(); + } catch (e) { + if (e instanceof Error) toast({ description: e.message, status: "error" }); + } + }); + + const { requestPay } = useInvoiceModalContext(); + const zapModal = useDisclosure(); + const zapMetadata = useUserLNURLMetadata(stream.host); + + watch("content"); + + return ( + <> + + setValue("content", e.target.value)} + rows={1} + /> + + {zapMetadata.metadata?.allowsNostr && ( + } + aria-label="Zap stream" + borderColor="yellow.400" + variant="outline" + onClick={zapModal.onOpen} + /> + )} + + + {zapModal.isOpen && ( + { + reset(); + zapModal.onClose(); + await requestPay(invoice); + }} + onClose={zapModal.onClose} + initialComment={getValues().content} + additionalRelays={relays} + /> + )} + + ); +} diff --git a/src/views/streams/stream/stream-chat/index.tsx b/src/views/streams/stream/stream-chat/index.tsx index c1a1ff723..bc68841d0 100644 --- a/src/views/streams/stream/stream-chat/index.tsx +++ b/src/views/streams/stream/stream-chat/index.tsx @@ -1,47 +1,24 @@ import { useCallback, useMemo, useRef } from "react"; -import { - Box, - Button, - Card, - CardBody, - CardHeader, - CardProps, - Flex, - Heading, - IconButton, - Input, - useDisclosure, - useToast, -} from "@chakra-ui/react"; +import { Card, CardBody, CardHeader, CardProps, Flex, Heading } from "@chakra-ui/react"; +import { css } from "@emotion/react"; +import { Kind } from "nostr-tools"; -import { ParsedStream, STREAM_CHAT_MESSAGE_KIND, buildChatMessage, getATag } from "../../../../helpers/nostr/stream"; -import { useUserRelays } from "../../../../hooks/use-user-relays"; -import { RelayMode } from "../../../../classes/relay"; -import ZapModal from "../../../../components/zap-modal"; -import { LightningIcon } from "../../../../components/icons"; +import { ParsedStream, STREAM_CHAT_MESSAGE_KIND, getATag } from "../../../../helpers/nostr/stream"; import ChatMessage from "./chat-message"; import ZapMessage from "./zap-message"; import { LightboxProvider } from "../../../../components/lightbox-provider"; import IntersectionObserverProvider from "../../../../providers/intersection-observer"; -import useUserLNURLMetadata from "../../../../hooks/use-user-lnurl-metadata"; -import { useInvoiceModalContext } from "../../../../providers/invoice-modal"; -import { unique } from "../../../../helpers/array"; -import { useForm } from "react-hook-form"; -import { useSigningContext } from "../../../../providers/signing-provider"; import { useTimelineCurserIntersectionCallback } from "../../../../hooks/use-timeline-cursor-intersection-callback"; import useSubject from "../../../../hooks/use-subject"; import useTimelineLoader from "../../../../hooks/use-timeline-loader"; import { truncatedId } from "../../../../helpers/nostr/events"; -import { css } from "@emotion/react"; import TopZappers from "./top-zappers"; import { parseZapEvent } from "../../../../helpers/zaps"; -import { Kind } from "nostr-tools"; import { useRelaySelectionRelays } from "../../../../providers/relay-selection-provider"; import useUserMuteList from "../../../../hooks/use-user-mute-list"; import { NostrEvent, isPTag } from "../../../../types/nostr-event"; import { useCurrentAccount } from "../../../../hooks/use-current-account"; -import NostrPublishAction from "../../../../classes/nostr-publish-action"; -import { ensureNotifyContentMentions } from "../../../../helpers/nostr/post"; +import ChatMessageForm from "./chat-message-form"; const hideScrollbar = css` scrollbar-width: 0; @@ -59,14 +36,8 @@ export default function StreamChat({ displayMode, ...props }: CardProps & { stream: ParsedStream; actions?: React.ReactNode; displayMode?: ChatDisplayMode }) { - const toast = useToast(); const account = useCurrentAccount(); const streamRelays = useRelaySelectionRelays(); - const hostReadRelays = useUserRelays(stream.host) - .filter((r) => r.mode & RelayMode.READ) - .map((r) => r.url); - - const relays = useMemo(() => unique([...streamRelays, ...hostReadRelays]), [hostReadRelays, streamRelays]); const hostMuteList = useUserMuteList(stream.host); const muteList = useUserMuteList(account?.pubkey); @@ -101,106 +72,45 @@ export default function StreamChat({ const scrollBox = useRef(null); const callback = useTimelineCurserIntersectionCallback(timeline); - const { requestSignature } = useSigningContext(); - const { register, handleSubmit, formState, reset, getValues } = useForm({ - defaultValues: { content: "" }, - }); - const sendMessage = handleSubmit(async (values) => { - try { - const draft = buildChatMessage(stream, values.content); - const signed = await requestSignature(draft); - new NostrPublishAction("Send Chat", relays, signed); - reset(); - } catch (e) { - if (e instanceof Error) toast({ description: e.message, status: "error" }); - } - }); - - const zapModal = useDisclosure(); - const { requestPay } = useInvoiceModalContext(); - const zapMetadata = useUserLNURLMetadata(stream.host); - const isPopup = !!displayMode; const isChatLog = displayMode === "log"; return ( - <> - - - - {!isPopup && ( - - Stream Chat - {actions} - - )} - - - - {events.map((event) => - event.kind === STREAM_CHAT_MESSAGE_KIND ? ( - - ) : ( - - ), - )} - - {!isChatLog && ( - - - - {zapMetadata.metadata?.allowsNostr && ( - } - aria-label="Zap stream" - borderColor="yellow.400" - variant="outline" - onClick={zapModal.onOpen} - /> - )} - + + + + {!isPopup && ( + + Stream Chat + {actions} + + )} + + + + {events.map((event) => + event.kind === STREAM_CHAT_MESSAGE_KIND ? ( + + ) : ( + + ), )} - - - - - {zapModal.isOpen && ( - { - reset(); - zapModal.onClose(); - await requestPay(invoice); - }} - onClose={zapModal.onClose} - initialComment={getValues().content} - additionalRelays={relays} - /> - )} - + + {!isChatLog && } + + + + ); }