forked from Kieran/zap.stream
style tweaks
This commit is contained in:
parent
af14b92ab4
commit
4f254d96ff
@ -3,7 +3,8 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 6px 0;
|
background: transparent;
|
||||||
|
margin: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge .badge-details {
|
.badge .badge-details {
|
||||||
@ -23,6 +24,7 @@
|
|||||||
.badge .badge-description {
|
.badge .badge-description {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge .badge-thumbnail {
|
.badge .badge-thumbnail {
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
.emoji-pack-title {
|
.emoji-pack {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-pack .emoji-pack-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-pack-title .name {
|
.emoji-pack .emoji-pack-title .name {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-pack-title a {
|
.emoji-pack .emoji-pack-title a {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-pack-emojis {
|
.emoji-pack .emoji-pack-emojis {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -20,14 +24,14 @@
|
|||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-definition {
|
.emoji-pack .emoji-definition {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-name {
|
.emoji-pack .emoji-name {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import { type NostrEvent } from "@snort/system";
|
|||||||
import { useLogin } from "hooks/login";
|
import { useLogin } from "hooks/login";
|
||||||
import { toEmojiPack } from "hooks/emoji";
|
import { toEmojiPack } from "hooks/emoji";
|
||||||
import AsyncButton from "element/async-button";
|
import AsyncButton from "element/async-button";
|
||||||
import { Mention } from "element/mention";
|
|
||||||
import { findTag } from "utils";
|
import { findTag } from "utils";
|
||||||
import { USER_EMOJIS } from "const";
|
import { USER_EMOJIS } from "const";
|
||||||
import { Login, System } from "index";
|
import { Login, System } from "index";
|
||||||
@ -44,12 +43,9 @@ export function EmojiPack({ ev }: { ev: NostrEvent }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="emoji-pack">
|
<div className="outline emoji-pack">
|
||||||
<div className="emoji-pack-title">
|
<div className="emoji-pack-title">
|
||||||
<div>
|
<h4>{name}</h4>
|
||||||
<h4>{name}</h4>
|
|
||||||
<Mention pubkey={ev.pubkey} />
|
|
||||||
</div>
|
|
||||||
{login?.pubkey && (
|
{login?.pubkey && (
|
||||||
<AsyncButton
|
<AsyncButton
|
||||||
className={`btn btn-primary ${isUsed ? "delete-button" : ""}`}
|
className={`btn btn-primary ${isUsed ? "delete-button" : ""}`}
|
||||||
|
@ -15,6 +15,7 @@ export function ExternalLink({ children, href }: ExternalLinkProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ExternalIconLinkProps extends Omit<ExternalLinkProps, "children"> {
|
interface ExternalIconLinkProps extends Omit<ExternalLinkProps, "children"> {
|
||||||
|
className?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +141,7 @@ export function LiveChat({
|
|||||||
<h2 className="title">Stream Chat</h2>
|
<h2 className="title">Stream Chat</h2>
|
||||||
<Icon
|
<Icon
|
||||||
name="link"
|
name="link"
|
||||||
|
className="secondary"
|
||||||
size={32}
|
size={32}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
window.open(
|
window.open(
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
line-height: 29px; /* 161.111% */
|
line-height: 29px; /* 161.111% */
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown > img {
|
.markdown img:not(.emoji):not(.note-avatar) {
|
||||||
max-height: 230px;
|
max-height: 720px;
|
||||||
|
margin-top: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ export function LoggedInMuteButton({ pubkey }: { pubkey: string }) {
|
|||||||
<AsyncButton
|
<AsyncButton
|
||||||
type="button"
|
type="button"
|
||||||
className="btn delete-button"
|
className="btn delete-button"
|
||||||
onClick={() => isMuted ? unmute() : mute()}
|
onClick={() => (isMuted ? unmute() : mute())}
|
||||||
>
|
>
|
||||||
{isMuted ? "Unmute" : "Mute"}
|
{isMuted ? "Unmute" : "Mute"}
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
.note {
|
.note {
|
||||||
padding: 12px;
|
margin: 8px 0;
|
||||||
border: 1px solid var(--border);
|
color: #fff;
|
||||||
border-radius: 10px;
|
font-size: 15px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note .note-header {
|
.note .note-header {
|
||||||
@ -10,23 +12,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.note .note-header .profile {
|
.note .note-header .profile {
|
||||||
font-size: 14px;
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note .note-avatar {
|
.note .note-header .note-avatar {
|
||||||
width: 18px;
|
width: 24px;
|
||||||
height: 18px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note .note-content {
|
.note .note-header .note-link-icon {
|
||||||
margin-left: 30px;
|
color: #909090;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note .note-content .markdown > * {
|
.note .note-content .markdown > * {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note .note-content .markdown > ul,
|
.note .note-content .markdown > *:last-child {
|
||||||
.note .note-content .markdown ol {
|
margin-bottom: 0;
|
||||||
margin-left: 30px;
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
import "./note.css";
|
import "./note.css";
|
||||||
import { type NostrEvent } from "@snort/system";
|
import { type NostrEvent, NostrPrefix } from "@snort/system";
|
||||||
|
|
||||||
import { Markdown } from "element/markdown";
|
import { Markdown } from "element/markdown";
|
||||||
import { ExternalIconLink } from "element/external-link";
|
import { ExternalIconLink } from "element/external-link";
|
||||||
import { Profile } from "element/profile";
|
import { Profile } from "element/profile";
|
||||||
|
import { hexToBech32 } from "utils";
|
||||||
|
|
||||||
export function Note({ ev }: { ev: NostrEvent }) {
|
export function Note({ ev }: { ev: NostrEvent }) {
|
||||||
return (
|
return (
|
||||||
<div className="note">
|
<div className="surface note">
|
||||||
<div className="note-header">
|
<div className="note-header">
|
||||||
<Profile avatarClassname="note-avatar" pubkey={ev.pubkey} />
|
<Profile avatarClassname="note-avatar" pubkey={ev.pubkey} />
|
||||||
<ExternalIconLink size={25} href={`https://snort.social/e/${ev.id}`} />
|
<ExternalIconLink
|
||||||
|
size={24}
|
||||||
|
className="note-link-icon"
|
||||||
|
href={`https://snort.social/e/${hexToBech32(
|
||||||
|
NostrPrefix.Event,
|
||||||
|
ev.id
|
||||||
|
)}`}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="note-content">
|
<div className="note-content">
|
||||||
<Markdown tags={ev.tags} content={ev.content} />
|
<Markdown tags={ev.tags} content={ev.content} />
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
.stream-cards {
|
.stream-cards,
|
||||||
|
.edit-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1020px) {
|
@media (min-width: 1020px) {
|
||||||
|
.edit-container {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
.stream-cards {
|
.stream-cards {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@ -86,6 +90,7 @@
|
|||||||
.new-card h3 {
|
.new-card h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-card input[type="text"] {
|
.new-card input[type="text"] {
|
||||||
@ -169,3 +174,73 @@
|
|||||||
.stream-card {
|
.stream-card {
|
||||||
max-width: 343px;
|
max-width: 343px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-zappers-card .top-zappers-leaderboard {
|
||||||
|
border: 1px solid;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border-color: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zappers-card .top-zapper-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zapper-container .zap-amount {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zapper-container .top-zapper-amount {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zappers-card .top-zappers-leaderboard {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zapper-container.first .profile {
|
||||||
|
background: var(--gradient-purple);
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zapper-container.second .profile {
|
||||||
|
background: var(--gradient-yellow);
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zapper-container.third .profile {
|
||||||
|
background: var(--gradient-orange);
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-zapper-container.live .profile {
|
||||||
|
background-size: 300% 300%;
|
||||||
|
animation: animatedgradient 3s ease alternate infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes animatedgradient {
|
||||||
|
0% {
|
||||||
|
background-position: 0% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
background-position: 100% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
background-position: 0% 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -12,12 +12,16 @@ import { Icon } from "element/icon";
|
|||||||
import { ExternalLink } from "element/external-link";
|
import { ExternalLink } from "element/external-link";
|
||||||
import { FileUploader } from "element/file-uploader";
|
import { FileUploader } from "element/file-uploader";
|
||||||
import { Markdown } from "element/markdown";
|
import { Markdown } from "element/markdown";
|
||||||
|
import { Profile } from "element/profile";
|
||||||
import { useLogin } from "hooks/login";
|
import { useLogin } from "hooks/login";
|
||||||
import { useCards, useUserCards } from "hooks/cards";
|
import { useCards, useUserCards } from "hooks/cards";
|
||||||
|
import { useZaps } from "hooks/zaps";
|
||||||
|
import useTopZappers from "hooks/top-zappers";
|
||||||
import { CARD, USER_CARDS } from "const";
|
import { CARD, USER_CARDS } from "const";
|
||||||
import { toTag, findTag } from "utils";
|
import { toTag, findTag } from "utils";
|
||||||
import { Login, System } from "index";
|
import { Login, System } from "index";
|
||||||
import type { Tags } from "types";
|
import type { Tags } from "types";
|
||||||
|
import { formatSats } from "number";
|
||||||
|
|
||||||
interface CardType {
|
interface CardType {
|
||||||
identifier: string;
|
identifier: string;
|
||||||
@ -426,12 +430,14 @@ export function StreamCardEditor({ pubkey, tags }: StreamCardEditorProps) {
|
|||||||
|
|
||||||
interface StreamCardsProps {
|
interface StreamCardsProps {
|
||||||
host: string;
|
host: string;
|
||||||
|
isLive: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ReadOnlyStreamCards({ host }: StreamCardsProps) {
|
export function ReadOnlyStreamCards({ host, isLive }: StreamCardsProps) {
|
||||||
const cards = useCards(host);
|
const cards = useCards(host);
|
||||||
return (
|
return (
|
||||||
<div className="stream-cards">
|
<div className="stream-cards">
|
||||||
|
{cards.length === 99 && <TopZappers host={host} isLive={isLive} />}
|
||||||
{cards.map((ev) => (
|
{cards.map((ev) => (
|
||||||
<Card cards={cards} key={ev!.id} ev={ev!} />
|
<Card cards={cards} key={ev!.id} ev={ev!} />
|
||||||
))}
|
))}
|
||||||
@ -439,7 +445,42 @@ export function ReadOnlyStreamCards({ host }: StreamCardsProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StreamCards({ host }: StreamCardsProps) {
|
interface TopZappersProps {
|
||||||
|
host: string;
|
||||||
|
isLive: boolean;
|
||||||
|
n?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TopZappers({ host, isLive, n = 5 }: TopZappersProps) {
|
||||||
|
const zaps = useZaps(host);
|
||||||
|
const topZappers = useTopZappers(zaps);
|
||||||
|
return topZappers.length > 0 ? (
|
||||||
|
<div className="stream-card top-zappers-card">
|
||||||
|
<h1 className="card-title">Top Zappers</h1>
|
||||||
|
<div className="top-zappers-leaderboard">
|
||||||
|
{topZappers
|
||||||
|
.filter((z) => z.pubkey !== "anon")
|
||||||
|
.slice(0, n)
|
||||||
|
.map((z, idx) => (
|
||||||
|
<div
|
||||||
|
className={`top-zapper-container ${idx === 0 ? "first" : ""} ${
|
||||||
|
idx === 1 ? "second" : ""
|
||||||
|
} ${idx === 2 ? "third" : ""}
|
||||||
|
${isLive && idx < 3 ? "live" : ""}`}
|
||||||
|
>
|
||||||
|
<Profile pubkey={z.pubkey} />
|
||||||
|
<div className="zap-amount">
|
||||||
|
<Icon name="zap-filled" className="zap-icon" />
|
||||||
|
<p className="top-zapper-amount">{formatSats(z.total)}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function StreamCards({ host, isLive }: StreamCardsProps) {
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
const canEdit = login?.pubkey === host;
|
const canEdit = login?.pubkey === host;
|
||||||
return (
|
return (
|
||||||
@ -447,7 +488,7 @@ export function StreamCards({ host }: StreamCardsProps) {
|
|||||||
{canEdit ? (
|
{canEdit ? (
|
||||||
<StreamCardEditor tags={login.cards.tags} pubkey={login.pubkey} />
|
<StreamCardEditor tags={login.cards.tags} pubkey={login.pubkey} />
|
||||||
) : (
|
) : (
|
||||||
<ReadOnlyStreamCards host={host} />
|
<ReadOnlyStreamCards isLive={isLive} host={host} />
|
||||||
)}
|
)}
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
.custom-emoji {
|
.text img:not(.emoji):not(.note-avatar) {
|
||||||
width: 21px;
|
max-height: 720px;
|
||||||
height: 21px;
|
margin-top: 8px;
|
||||||
display: inline-block;
|
width: 100%;
|
||||||
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import "./text.css";
|
||||||
import { useMemo, type ReactNode } from "react";
|
import { useMemo, type ReactNode } from "react";
|
||||||
|
|
||||||
import { parseNostrLink, validateNostrLink } from "@snort/system";
|
import { parseNostrLink, validateNostrLink } from "@snort/system";
|
||||||
@ -31,25 +32,11 @@ function extractLinks(fragments: Fragment[]) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
normalizedStr.startsWith("http:") ||
|
normalizedStr.startsWith("http:") ||
|
||||||
normalizedStr.startsWith("https:") ||
|
normalizedStr.startsWith("https:")
|
||||||
normalizedStr.startsWith("magnet:")
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (validateLink()) {
|
if (validateLink()) {
|
||||||
if (!a.startsWith("nostr:")) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={a}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="ext"
|
|
||||||
>
|
|
||||||
{a}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return <HyperText link={a}>{a}</HyperText>;
|
return <HyperText link={a}>{a}</HyperText>;
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
@ -204,7 +191,7 @@ export function transformText(ps: Fragment[], tags: Array<string[]>) {
|
|||||||
export function Text({ content, tags }: { content: string; tags: string[][] }) {
|
export function Text({ content, tags }: { content: string; tags: string[][] }) {
|
||||||
// todo: RTL langugage support
|
// todo: RTL langugage support
|
||||||
const element = useMemo(() => {
|
const element = useMemo(() => {
|
||||||
return <span>{transformText([content], tags)}</span>;
|
return <span className="text">{transformText([content], tags)}</span>;
|
||||||
}, [content, tags]);
|
}, [content, tags]);
|
||||||
|
|
||||||
return <>{element}</>;
|
return <>{element}</>;
|
||||||
|
32
src/hooks/zaps.ts
Normal file
32
src/hooks/zaps.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
EventKind,
|
||||||
|
NoteCollection,
|
||||||
|
RequestBuilder,
|
||||||
|
parseZap,
|
||||||
|
} from "@snort/system";
|
||||||
|
import { useRequestBuilder } from "@snort/system-react";
|
||||||
|
|
||||||
|
import { System } from "index";
|
||||||
|
|
||||||
|
export function useZaps(pubkey: string, leaveOpen = false) {
|
||||||
|
const rb = useMemo(() => {
|
||||||
|
const rb = new RequestBuilder(`profile-zaps:${pubkey.slice(0, 12)}`);
|
||||||
|
rb.withOptions({ leaveOpen });
|
||||||
|
rb.withFilter().kinds([EventKind.ZapReceipt]).tag("p", [pubkey]);
|
||||||
|
return rb;
|
||||||
|
}, [pubkey]);
|
||||||
|
|
||||||
|
const { data } = useRequestBuilder<NoteCollection>(
|
||||||
|
System,
|
||||||
|
NoteCollection,
|
||||||
|
rb
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
data
|
||||||
|
?.map((ev) => parseZap(ev, System.ProfileLoader.Cache))
|
||||||
|
.filter((z) => z && z.valid) ?? []
|
||||||
|
);
|
||||||
|
}
|
@ -15,7 +15,15 @@ body {
|
|||||||
--text-muted: #797979;
|
--text-muted: #797979;
|
||||||
--text-link: #f838d9;
|
--text-link: #f838d9;
|
||||||
--text-danger: #ff563f;
|
--text-danger: #ff563f;
|
||||||
--border: #333;
|
--surface: #222;
|
||||||
|
--border: #171717;
|
||||||
|
--gradient-purple: linear-gradient(135deg, #882bff 0%, #f83838 100%);
|
||||||
|
--gradient-yellow: linear-gradient(270deg, #adff27 0%, #ffd027 100%);
|
||||||
|
--gradient-orange: linear-gradient(
|
||||||
|
270deg,
|
||||||
|
#ff5b27 0%,
|
||||||
|
rgba(255, 182, 39, 0.99) 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1020px) {
|
@media (max-width: 1020px) {
|
||||||
@ -277,3 +285,19 @@ div.paper {
|
|||||||
height: 15px;
|
height: 15px;
|
||||||
margin-bottom: -2px;
|
margin-bottom: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.surface {
|
||||||
|
padding: 8px 12px 12px 12px;
|
||||||
|
background: var(--surface);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outline {
|
||||||
|
padding: 8px 12px 12px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary {
|
||||||
|
color: #909090;
|
||||||
|
}
|
||||||
|
@ -187,9 +187,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-page .zapper .zapper-amount {
|
.profile-page .zapper .zapper-amount {
|
||||||
@ -197,7 +195,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@ import { parseNostrLink, TaggedRawEvent } from "@snort/system";
|
|||||||
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
|
|
||||||
|
import { NostrEvent } from "@snort/system";
|
||||||
|
import { useUserProfile } from "@snort/system-react";
|
||||||
|
|
||||||
import { LiveVideoPlayer } from "element/live-video-player";
|
import { LiveVideoPlayer } from "element/live-video-player";
|
||||||
import {
|
import {
|
||||||
createNostrLink,
|
createNostrLink,
|
||||||
@ -17,13 +20,10 @@ import { useLogin } from "hooks/login";
|
|||||||
import { useZapGoal } from "hooks/goals";
|
import { useZapGoal } from "hooks/goals";
|
||||||
import { StreamState, System } from "index";
|
import { StreamState, System } from "index";
|
||||||
import { SendZapsDialog } from "element/send-zap";
|
import { SendZapsDialog } from "element/send-zap";
|
||||||
import { NostrEvent } from "@snort/system";
|
|
||||||
import { useUserProfile } from "@snort/system-react";
|
|
||||||
import { NewStreamDialog } from "element/new-stream";
|
import { NewStreamDialog } from "element/new-stream";
|
||||||
import { Tags } from "element/tags";
|
import { Tags } from "element/tags";
|
||||||
import { StatePill } from "element/state-pill";
|
import { StatePill } from "element/state-pill";
|
||||||
import { StreamCards } from "element/stream-cards";
|
import { StreamCards } from "element/stream-cards";
|
||||||
import { formatSats } from "number";
|
|
||||||
import { StreamTimer } from "element/stream-time";
|
import { StreamTimer } from "element/stream-time";
|
||||||
import { ShareMenu } from "element/share-menu";
|
import { ShareMenu } from "element/share-menu";
|
||||||
import {
|
import {
|
||||||
@ -31,6 +31,7 @@ import {
|
|||||||
isContentWarningAccepted,
|
isContentWarningAccepted,
|
||||||
} from "element/content-warning";
|
} from "element/content-warning";
|
||||||
import { useCurrentStreamFeed } from "hooks/current-stream-feed";
|
import { useCurrentStreamFeed } from "hooks/current-stream-feed";
|
||||||
|
import { formatSats } from "number";
|
||||||
|
|
||||||
function ProfileInfo({ ev, goal }: { ev?: NostrEvent; goal?: TaggedRawEvent }) {
|
function ProfileInfo({ ev, goal }: { ev?: NostrEvent; goal?: TaggedRawEvent }) {
|
||||||
const login = useLogin();
|
const login = useLogin();
|
||||||
@ -156,7 +157,7 @@ export function StreamPage() {
|
|||||||
<div className="video-content">
|
<div className="video-content">
|
||||||
<LiveVideoPlayer stream={stream} poster={image} status={status} />
|
<LiveVideoPlayer stream={stream} poster={image} status={status} />
|
||||||
<ProfileInfo ev={ev} goal={goal} />
|
<ProfileInfo ev={ev} goal={goal} />
|
||||||
<StreamCards host={host} />
|
<StreamCards host={host} isLive={status === StreamState.Live} />
|
||||||
</div>
|
</div>
|
||||||
<LiveChat link={createNostrLink(ev) ?? link} ev={ev} goal={goal} />
|
<LiveChat link={createNostrLink(ev) ?? link} ev={ev} goal={goal} />
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user