Merge pull request 'feat: popout chat link' (#22) from verbiricha/stream:feat/chat-link into main

Reviewed-on: Kieran/stream#22
This commit is contained in:
Kieran 2023-07-05 20:10:00 +00:00
commit 61c981b220
4 changed files with 80 additions and 29 deletions

View File

@ -24,5 +24,9 @@
<symbol id="face" viewBox="0 0 24 24" fill="none">
<path d="M15 9H15.01M9 9H9.01M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12ZM15.5 9C15.5 9.27614 15.2761 9.5 15 9.5C14.7239 9.5 14.5 9.27614 14.5 9C14.5 8.72386 14.7239 8.5 15 8.5C15.2761 8.5 15.5 8.72386 15.5 9ZM9.5 9C9.5 9.27614 9.27614 9.5 9 9.5C8.72386 9.5 8.5 9.27614 8.5 9C8.5 8.72386 8.72386 8.5 9 8.5C9.27614 8.5 9.5 8.72386 9.5 9ZM12 17.5C14.5005 17.5 16.5 15.667 16.5 14H7.5C7.5 15.667 9.4995 17.5 12 17.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="link" viewBox="0 0 32 32" fill="none">
<path d="M22 14L22 10M22 10H18M22 10L16 16M14.6667 10H13.2C12.0799 10 11.5198 10 11.092 10.218C10.7157 10.4097 10.4097 10.7157 10.218 11.092C10 11.5198 10 12.0799 10 13.2V18.8C10 19.9201 10 20.4802 10.218 20.908C10.4097 21.2843 10.7157 21.5903 11.092 21.782C11.5198 22 12.0799 22 13.2 22H18.8C19.9201 22 20.4802 22 20.908 21.782C21.2843 21.5903 21.5903 21.2843 21.782 20.908C22 20.4802 22 19.9201 22 18.8V17.3333" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</symbol>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -12,8 +12,13 @@ export function Icon(props: Props) {
const href = `/icons.svg#` + props.name;
return (
<svg width={size} height={size} className={props.className} onClick={props.onClick}>
<svg
width={size}
height={size}
className={props.className}
onClick={props.onClick}
>
<use href={href} />
</svg>
);
};
}

View File

@ -47,10 +47,20 @@
}
}
.live-chat>.header {
font-weight: 600;
.live-chat > .header {
display: flex;
justify-content: space-between
}
.live-chat .header .title {
font-size: 24px;
line-height: 30px;
font-weight: 600;
line-height: normal;
margin: 0;
}
.live-chat .header .popout-link {
color: #FFFFFF80;
}
.live-chat>.messages {

View File

@ -1,14 +1,13 @@
import "./live-chat.css";
import {
EventKind,
NostrPrefix,
NostrLink,
ParsedZap,
parseZap,
encodeTLV,
} from "@snort/system";
import {
useEffect,
useMemo,
} from "react";
import { useEffect, useMemo } from "react";
import { System } from "../index";
import { useLiveChatFeed } from "../hooks/live-chat";
@ -54,11 +53,21 @@ function TopZappers({ zaps }: { zaps: ParsedZap[] }) {
);
}
export function LiveChat({ link, options, height, }: { link: NostrLink, options?: LiveChatOptions, height?: number }) {
export function LiveChat({
link,
options,
height,
}: {
link: NostrLink;
options?: LiveChatOptions;
height?: number;
}) {
const feed = useLiveChatFeed(link);
const login = useLogin();
useEffect(() => {
const pubkeys = [...new Set(feed.zaps.flatMap(a => [a.pubkey, findTag(a, "p")!]))];
const pubkeys = [
...new Set(feed.zaps.flatMap((a) => [a.pubkey, findTag(a, "p")!])),
];
System.ProfileLoader.TrackMetadata(pubkeys);
return () => System.ProfileLoader.UntrackMetadata(pubkeys);
}, [feed.zaps]);
@ -73,11 +82,30 @@ export function LiveChat({ link, options, height, }: { link: NostrLink, options?
}, [feed.messages, feed.zaps]);
const { data: ev } = useEventFeed(link);
const streamer = getHost(ev);
const naddr = useMemo(() => {
return encodeTLV(
NostrPrefix.Address,
link.id,
undefined,
link.kind,
link.author
);
}, [link]);
return (
<div className="live-chat" style={height ? { height: `${height}px` } : {}}>
{(options?.showHeader ?? true) && (
<div className="header">Stream Chat</div>
<div className="header">
<h2 className="title">Stream Chat</h2>
<a
href={`/chat/${naddr}`}
className="popout-link"
target="_blank"
rel="noopener noreferrer"
>
<Icon name="link" size={32} />
</a>
</div>
)}
{zaps.length > 0 && (
<div className="top-zappers">
@ -98,7 +126,9 @@ export function LiveChat({ link, options, height, }: { link: NostrLink, options?
);
}
case EventKind.ZapReceipt: {
const zap = zaps.find(b => b.id === a.id && b.receiver === streamer);
const zap = zaps.find(
(b) => b.id === a.id && b.receiver === streamer
);
if (zap) {
return <ChatZap zap={zap} key={a.id} />;
}
@ -126,20 +156,22 @@ function ChatZap({ zap }: { zap: ParsedZap }) {
return null;
}
return <div className="zap-container">
<div className="zap">
<Icon name="zap-filled" className="zap-icon" />
<Profile
pubkey={zap.anonZap ? "anon" : zap.sender ?? "anon"}
options={{
showAvatar: !zap.anonZap,
overrideName: zap.anonZap ? "Anon" : undefined,
}}
/>
zapped
<span className="zap-amount">{formatSats(zap.amount)}</span>
sats
return (
<div className="zap-container">
<div className="zap">
<Icon name="zap-filled" className="zap-icon" />
<Profile
pubkey={zap.anonZap ? "anon" : zap.sender ?? "anon"}
options={{
showAvatar: !zap.anonZap,
overrideName: zap.anonZap ? "Anon" : undefined,
}}
/>
zapped
<span className="zap-amount">{formatSats(zap.amount)}</span>
sats
</div>
{zap.content && <div className="zap-content">{zap.content}</div>}
</div>
{zap.content && <div className="zap-content">{zap.content}</div>}
</div>
}
);
}