diff --git a/package.json b/package.json index 14b4654..33b6026 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "react": "^18.2.0", "react-confetti": "^6.1.0", "react-dom": "^18.2.0", + "react-helmet": "^6.1.0", "react-intersection-observer": "^9.5.1", "react-router-dom": "^6.13.0", "react-tag-input-component": "^2.0.2", @@ -81,6 +82,7 @@ "@types/lodash.uniqby": "^4.7.7", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", + "@types/react-helmet": "^6.1.6", "@typescript-eslint/eslint-plugin": "^6.1.0", "@typescript-eslint/parser": "^6.1.0", "@webbtc/webln-types": "^1.0.12", diff --git a/src/element/live-chat.tsx b/src/element/live-chat.tsx index 28dde72..34a18fb 100644 --- a/src/element/live-chat.tsx +++ b/src/element/live-chat.tsx @@ -89,7 +89,12 @@ export function LiveChat({ .filter((z) => z && z.valid); const goalZaps = feed.zaps - .filter((ev) => (goal ? ev.created_at > goal.created_at && ev.tags.some(t => t[0] === "e" && t[1] === goal.id) : false)) + .filter((ev) => + goal + ? ev.created_at > goal.created_at && + ev.tags.some((t) => t[0] === "e" && t[1] === goal.id) + : false + ) .map((ev) => parseZap(ev, System.ProfileLoader.Cache)) .filter((z) => z && z.valid); @@ -116,14 +121,11 @@ export function LiveChat({ {(options?.showHeader ?? true) && (

Stream Chat

- - - + window.open(`/chat/${naddr}?chat=true`, "_blank", "popup,width=400,height=800")} + />
)} {zaps.length > 0 && ( @@ -132,7 +134,7 @@ export function LiveChat({
- {goal && } + {goal && } {login?.pubkey === streamer && } )} diff --git a/src/pages/chat-popout.tsx b/src/pages/chat-popout.tsx index 9661121..88cd682 100644 --- a/src/pages/chat-popout.tsx +++ b/src/pages/chat-popout.tsx @@ -9,13 +9,14 @@ export function ChatPopout() { const link = parseNostrLink(params.id!); const { data: ev } = useEventFeed(link, true); + const chat = new URL(window.location.href).searchParams.get("chat"); return (
diff --git a/src/pages/layout.tsx b/src/pages/layout.tsx index a54eaf6..83eeb12 100644 --- a/src/pages/layout.tsx +++ b/src/pages/layout.tsx @@ -2,6 +2,7 @@ import "./layout.css"; import { useState } from "react"; import * as Dialog from "@radix-ui/react-dialog"; import { Outlet, useNavigate, useLocation, Link } from "react-router-dom"; +import { Helmet } from "react-helmet"; import { Icon } from "element/icon"; import { useLogin } from "hooks/login"; @@ -95,6 +96,9 @@ export function LayoutPage() { : "page" } > + + Home - zap.stream +
navigate("/")}>
diff --git a/src/pages/stream-page.tsx b/src/pages/stream-page.tsx index 0c34f0a..7c81f7b 100644 --- a/src/pages/stream-page.tsx +++ b/src/pages/stream-page.tsx @@ -1,6 +1,7 @@ import "./stream-page.css"; import { parseNostrLink, TaggedRawEvent } from "@snort/system"; import { useNavigate, useParams } from "react-router-dom"; +import { Helmet } from "react-helmet"; import useEventFeed from "hooks/event-feed"; import { LiveVideoPlayer } from "element/live-video-player"; @@ -118,8 +119,30 @@ export function StreamPage() { const host = getHost(ev); const goal = useZapGoal(host, link, true); + const title = findTag(ev, "title"); + const summary = findTag(ev, "summary"); + const image = findTag(ev, "image"); + const tags = ev?.tags.filter((a) => a[0] === "t").map((a) => a[1]) ?? []; + + const descriptionContent = [ + title, + (summary?.length ?? 0) > 0 ? summary : "Nostr live streaming", + ...tags, + ].join(", "); return ( <> + + {`${title} - zap.stream`} + + + + + + + diff --git a/yarn.lock b/yarn.lock index 240286d..aebcfe2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2988,6 +2988,15 @@ __metadata: languageName: node linkType: hard +"@types/react-helmet@npm:^6.1.6": + version: 6.1.6 + resolution: "@types/react-helmet@npm:6.1.6" + dependencies: + "@types/react": "*" + checksum: 81560c56bfe854b6a43aee31360862588ac875d1177b975da5ce049ac9aa2f7c98dcde65d4397bfaa04e468f40cf3ab2975a2ef966a69d64a60493422898698d + languageName: node + linkType: hard + "@types/react@npm:*": version: 18.2.13 resolution: "@types/react@npm:18.2.13" @@ -8423,6 +8432,27 @@ __metadata: languageName: node linkType: hard +"react-fast-compare@npm:^3.1.1": + version: 3.2.2 + resolution: "react-fast-compare@npm:3.2.2" + checksum: 2071415b4f76a3e6b55c84611c4d24dcb12ffc85811a2840b5a3f1ff2d1a99be1020d9437ee7c6e024c9f4cbb84ceb35e48cf84f28fcb00265ad2dfdd3947704 + languageName: node + linkType: hard + +"react-helmet@npm:^6.1.0": + version: 6.1.0 + resolution: "react-helmet@npm:6.1.0" + dependencies: + object-assign: ^4.1.1 + prop-types: ^15.7.2 + react-fast-compare: ^3.1.1 + react-side-effect: ^2.1.0 + peerDependencies: + react: ">=16.3.0" + checksum: a4998479dab7fc1c2799eddefb1870a9d881b5f71cfdf97979a9882e42f4bb50402d55335f308f461e735e01a06f46b16cc7b4e6bcb22c7a4a6f85a753c5c106 + languageName: node + linkType: hard + "react-intersection-observer@npm:^9.5.1": version: 9.5.1 resolution: "react-intersection-observer@npm:9.5.1" @@ -8512,6 +8542,15 @@ __metadata: languageName: node linkType: hard +"react-side-effect@npm:^2.1.0": + version: 2.1.2 + resolution: "react-side-effect@npm:2.1.2" + peerDependencies: + react: ^16.3.0 || ^17.0.0 || ^18.0.0 + checksum: c5eb1f42b464fb093bca59aaae0f1b2060373a2aaff95275b8781493628cdbbb6acdd6014e7883782c65c361f35a30f28cc515d68a1263ddb39cbbc47110be53 + languageName: node + linkType: hard + "react-style-singleton@npm:^2.2.1": version: 2.2.1 resolution: "react-style-singleton@npm:2.2.1" @@ -9365,6 +9404,7 @@ __metadata: "@types/lodash.uniqby": ^4.7.7 "@types/react": ^18.2.15 "@types/react-dom": ^18.2.7 + "@types/react-helmet": ^6.1.6 "@types/webscopeio__react-textarea-autocomplete": ^4.7.2 "@typescript-eslint/eslint-plugin": ^6.1.0 "@typescript-eslint/parser": ^6.1.0 @@ -9393,6 +9433,7 @@ __metadata: react: ^18.2.0 react-confetti: ^6.1.0 react-dom: ^18.2.0 + react-helmet: ^6.1.0 react-intersection-observer: ^9.5.1 react-router-dom: ^6.13.0 react-tag-input-component: ^2.0.2