From fc2304c9faf4d5167df0d7d26db87bd91de0962a Mon Sep 17 00:00:00 2001 From: Kieran Date: Mon, 19 Jun 2023 14:16:02 +0100 Subject: [PATCH] Update live stream page --- packages/app/src/Element/LiveChat.css | 37 +++++++++++++++- packages/app/src/Element/LiveChat.tsx | 59 +++++++++++++++++++------- packages/app/src/Element/Text.tsx | 2 +- packages/app/src/Feed/LiveChatFeed.tsx | 3 +- packages/app/src/Pages/LivePage.css | 25 ++++++++++- packages/app/src/Pages/LivePage.tsx | 38 ++++++++++++++++- packages/app/src/index.css | 8 ++++ 7 files changed, 152 insertions(+), 20 deletions(-) diff --git a/packages/app/src/Element/LiveChat.css b/packages/app/src/Element/LiveChat.css index 5423adf51..ee99c3af3 100644 --- a/packages/app/src/Element/LiveChat.css +++ b/packages/app/src/Element/LiveChat.css @@ -1,11 +1,46 @@ .live-chat { - height: calc(100vh - 73px); + height: 100%; display: flex; flex-direction: column; } .live-chat > div:nth-child(1) { + font-size: 24px; + line-height: 29px; + font-weight: bold; +} + +.live-chat > div:nth-child(2) { flex-grow: 1; display: flex; + gap: 16px; flex-direction: column-reverse; + margin-block-end: 20px; +} + +.live-chat > div:nth-child(3) { + display: flex; + gap: 10px; +} + +.live-chat .message { + display: inline-flex; + align-items: center; + gap: 8px; +} + +.live-chat .message .name { + display: inline-flex; + align-items: center; + color: var(--highlight); + font-weight: 600; + cursor: pointer; + user-select: none; +} + +.live-chat .message .avatar { + width: 24px; + height: 24px; + display: inline-block; + margin-right: 8px; } diff --git a/packages/app/src/Element/LiveChat.tsx b/packages/app/src/Element/LiveChat.tsx index 306dc9cd7..60fb83e97 100644 --- a/packages/app/src/Element/LiveChat.tsx +++ b/packages/app/src/Element/LiveChat.tsx @@ -1,30 +1,47 @@ import "./LiveChat.css"; -import { NostrLink, TaggedRawEvent } from "@snort/system"; +import { EventKind, NostrLink, TaggedRawEvent } from "@snort/system"; import { useUserProfile } from "@snort/system-react"; import { useState } from "react"; -import Textarea from "./Textarea"; +import { useNavigate } from "react-router-dom"; +import { FormattedMessage, useIntl } from "react-intl"; + +import Textarea from "Element/Textarea"; import { useLiveChatFeed } from "Feed/LiveChatFeed"; import useEventPublisher from "Feed/EventPublisher"; -import { System } from "index"; import { getDisplayName } from "Element/ProfileImage"; +import Avatar from "Element/Avatar"; +import AsyncButton from "Element/AsyncButton"; +import Text from "Element/Text"; +import { System } from "index"; +import { profileLink } from "SnortUtils"; export function LiveChat({ ev, link }: { ev: TaggedRawEvent; link: NostrLink }) { const [chat, setChat] = useState(""); const messages = useLiveChatFeed(link); const pub = useEventPublisher(); + const { formatMessage } = useIntl(); async function sendChatMessage() { - const reply = await pub?.note(chat, eb => { - return eb.tag(["a", `${link.kind}:${link.author}:${link.id}`]); - }); - if (reply) { - console.debug(reply); - System.BroadcastEvent(reply); + if (chat.length > 1) { + const reply = await pub?.generic(eb => { + return eb + .kind(1311 as EventKind) + .content(chat) + .tag(["a", `${link.kind}:${link.author}:${link.id}`]) + .processContent(); + }); + if (reply) { + console.debug(reply); + System.BroadcastEvent(reply); + } + setChat(""); } - setChat(""); } return (
+
+ +
{[...(messages.data ?? [])] .sort((a, b) => b.created_at - a.created_at) @@ -39,13 +56,19 @@ export function LiveChat({ ev, link }: { ev: TaggedRawEvent; link: NostrLink }) onChange={v => setChat(v.target.value)} value={chat} onFocus={() => {}} - placeholder="" + placeholder={formatMessage({ + defaultMessage: "Message...", + })} onKeyDown={async e => { if (e.code === "Enter") { + e.preventDefault(); await sendChatMessage(); } }} /> + + +
); @@ -53,11 +76,17 @@ export function LiveChat({ ev, link }: { ev: TaggedRawEvent; link: NostrLink }) function ChatMessage({ ev }: { ev: TaggedRawEvent }) { const profile = useUserProfile(System, ev.pubkey); + const navigate = useNavigate(); + return ( -
- {getDisplayName(profile, ev.pubkey)} - :  - {ev.content} +
+
navigate(profileLink(ev.pubkey, ev.relays))}> + + {getDisplayName(profile, ev.pubkey)}: +
+ + +
); } diff --git a/packages/app/src/Element/Text.tsx b/packages/app/src/Element/Text.tsx index 779c35b89..40601e260 100644 --- a/packages/app/src/Element/Text.tsx +++ b/packages/app/src/Element/Text.tsx @@ -50,7 +50,7 @@ export default function Text({ content, tags, creator, disableMedia, depth }: Te }; if (validateLink()) { - if (disableMedia ?? false) { + if ((disableMedia ?? false) && !a.startsWith("nostr:")) { return ( e.stopPropagation()} target="_blank" rel="noreferrer" className="ext"> {a} diff --git a/packages/app/src/Feed/LiveChatFeed.tsx b/packages/app/src/Feed/LiveChatFeed.tsx index 3bb40a857..b7f154ecc 100644 --- a/packages/app/src/Feed/LiveChatFeed.tsx +++ b/packages/app/src/Feed/LiveChatFeed.tsx @@ -1,4 +1,4 @@ -import { FlatNoteStore, NostrLink, RequestBuilder } from "@snort/system"; +import { EventKind, FlatNoteStore, NostrLink, RequestBuilder } from "@snort/system"; import { useRequestBuilder } from "@snort/system-react"; import { System } from "index"; import { useMemo } from "react"; @@ -10,6 +10,7 @@ export function useLiveChatFeed(link: NostrLink) { leaveOpen: true, }); rb.withFilter() + .kinds([EventKind.ZapReceipt, 1311 as EventKind]) .tag("a", [`${link.kind}:${link.author}:${link.id}`]) .limit(100); return rb; diff --git a/packages/app/src/Pages/LivePage.css b/packages/app/src/Pages/LivePage.css index 3b9898932..63e00e192 100644 --- a/packages/app/src/Pages/LivePage.css +++ b/packages/app/src/Pages/LivePage.css @@ -1,8 +1,31 @@ .live-page { display: grid; - grid-template-columns: auto 250px; + height: calc(100% - 105px); + padding: 24px; + grid-template-columns: auto 350px; + gap: 16px; +} + +@media (min-width: 2000px) { + .live-page { + grid-template-columns: auto 450px; + } +} + +.live-page > div:nth-child(1) { + overflow-y: auto; } .live-page video { width: 100%; + aspect-ratio: 16/9; +} + +.live-page .pill { + padding: 4px 8px; + border-radius: 20px; + font-size: 12px; + line-height: 16px; + font-weight: 600; + color: var(--font-secondary-color); } diff --git a/packages/app/src/Pages/LivePage.tsx b/packages/app/src/Pages/LivePage.tsx index 0b94c9b98..6b0d4d665 100644 --- a/packages/app/src/Pages/LivePage.tsx +++ b/packages/app/src/Pages/LivePage.tsx @@ -7,6 +7,10 @@ import { findTag, unwrap } from "SnortUtils"; import PageSpinner from "Element/PageSpinner"; import { LiveChat } from "Element/LiveChat"; import useEventFeed from "Feed/EventFeed"; +import ProfilePreview from "Element/ProfilePreview"; +import AsyncButton from "Element/AsyncButton"; +import { FormattedMessage } from "react-intl"; +import Icon from "Icons/Icon"; export function LivePage() { const params = useParams(); @@ -20,8 +24,40 @@ export function LivePage() { return (
-

{findTag(thisEvent.data, "title")}

+
+
+

{findTag(thisEvent.data, "title")}

+

{findTag(thisEvent.data, "summary")}

+
+ {thisEvent.data?.tags + .filter(a => a[0] === "t") + .map(a => a[1]) + .map(a => ( +
+ {a} +
+ ))} +
+
+
+ + {}}> + + + +
+ } + /> +
+
diff --git a/packages/app/src/index.css b/packages/app/src/index.css index 3b67e1826..17795e047 100644 --- a/packages/app/src/index.css +++ b/packages/app/src/index.css @@ -498,6 +498,14 @@ small.xs { margin-right: auto; } +.g5 { + gap: 5px; +} + +.g10 { + gap: 10px; +} + .error { color: var(--error); }