Share menu

This commit is contained in:
Kieran 2023-07-20 16:27:10 +01:00
parent da190423bc
commit 8d43ac3768
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
8 changed files with 163 additions and 51 deletions

View File

@ -49,6 +49,10 @@
<path d="M3 20.5C5.33579 18.0226 8.50702 16.5 12 16.5C15.493 16.5 18.6642 18.0226 21 20.5M16.5 8C16.5 10.4853 14.4853 12.5 12 12.5C9.51472 12.5 7.5 10.4853 7.5 8C7.5 5.51472 9.51472 3.5 12 3.5C14.4853 3.5 16.5 5.51472 16.5 8Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</symbol>
<symbol id="nostrich" viewBox="0 0 24 24" fill="none">
<g>
<path d="M17.7084 10.1607C18.1683 13.3466 14.8705 14.0207 12.9733 13.9618C12.8515 13.958 12.7366 14.0173 12.6647 14.1157C12.4684 14.384 12.1547 14.7309 11.9125 14.7309C11.6405 14.7309 11.3957 15.254 11.284 15.5795C11.2723 15.6137 11.3059 15.6452 11.3403 15.634C14.345 14.6584 15.5241 14.3238 16.032 14.4178C16.4421 14.4937 17.209 15.8665 17.5413 16.5434C16.7155 16.5909 16.4402 15.8507 16.2503 15.7178C16.0985 15.6116 16.0415 16.0974 16.032 16.3536C15.8517 16.2587 15.6239 16.1259 15.6049 15.7178C15.5859 15.3098 15.3771 15.4142 15.2157 15.4332C15.0544 15.4521 12.5769 16.2493 12.2067 16.3536C11.8366 16.458 11.4094 16.6004 11.0582 16.8471C10.4697 17.1318 10.09 16.9325 9.98561 16.4485C9.90208 16.0614 10.4444 14.8701 10.726 14.3229C10.3779 14.4526 9.65529 14.7158 9.54898 14.7309C9.44588 14.7457 8.13815 15.7552 7.43879 16.3038C7.398 16.3358 7.37174 16.3827 7.36236 16.4336C7.25047 17.0416 6.89335 17.2118 6.27423 17.5303C5.77602 17.7867 4.036 20.4606 3.14127 21.9041C3.0794 22.0039 2.9886 22.0806 2.8911 22.1461C2.32279 22.5276 1.74399 23.4985 1.50923 23.9737C1.17511 23.0095 1.61048 22.1802 1.86993 21.886C1.75602 21.7873 1.49341 21.8449 1.37634 21.886C1.69907 20.7757 2.82862 20.7757 2.79066 20.7757C2.99948 20.5954 5.44842 17.0938 5.50538 16.9325C5.56187 16.7725 5.46892 16.0242 6.69975 15.6139C6.7193 15.6073 6.73868 15.5984 6.75601 15.5873C7.71493 14.971 8.43427 13.9774 8.67571 13.5542C7.39547 13.4662 5.92943 12.7525 5.16289 12.294C4.99765 12.1952 4.8224 12.1092 4.63108 12.0875C3.58154 11.9687 2.53067 12.6401 2.10723 13.0228C1.93258 12.7799 2.12938 12.0739 2.24961 11.7513C1.82437 11.6905 1.19916 12.308 0.939711 12.6243C0.658747 12.184 0.904907 11.397 1.06311 11.0585C0.501179 11.0737 0.120232 11.3306 0 11.4571C0.465109 7.99343 4.02275 9.00076 4.06259 9.04675C3.87275 8.84937 3.88857 8.59126 3.92021 8.48688C6.0749 8.54381 7.08105 8.18321 7.71702 7.81313C12.7288 5.01374 14.8882 6.73133 15.6856 7.1631C16.4829 7.59487 17.9304 7.77042 18.9318 7.37187C20.1278 6.83097 19.9478 5.43673 19.7054 4.90461C19.4397 4.32101 17.9399 3.51438 17.4084 2.49428C16.8768 1.47418 17.34 0.233672 17.9558 0.0607684C18.5425 -0.103972 18.9615 0.0876835 19.2831 0.378128C19.4974 0.571763 20.0994 0.710259 20.3509 0.800409C20.6024 0.890558 21.0201 1.00918 20.9964 1.08035C20.9726 1.15152 20.5699 1.14202 20.5075 1.14202C20.3794 1.14202 20.2275 1.161 20.3794 1.23217C20.5575 1.30439 20.8263 1.40936 20.955 1.47846C20.9717 1.48744 20.9683 1.51084 20.95 1.51577C20.0765 1.75085 19.2966 1.26578 18.7183 1.82526C18.1298 2.39463 19.3827 2.83114 20.0282 3.51438C20.6736 4.19762 21.3381 5.01372 20.8065 6.87365C20.395 8.31355 18.6703 9.53781 17.7795 10.0167C17.7282 10.0442 17.7001 10.1031 17.7084 10.1607Z" fill="currentColor"/>
</g>
</symbol>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -215,7 +215,7 @@ export function SendZapsDialog(props: Omit<SendZapsProps, "onFinish">) {
) : (
<button className="btn btn-primary zap">
<span className="hide-on-mobile">Zap</span>
<Icon name="zap" size={16} />
<Icon name="zap-filled" size={16} />
</button>
)}
</Dialog.Trigger>

View File

@ -0,0 +1,89 @@
import { Menu, MenuItem } from "@szhsin/react-menu";
import * as Dialog from "@radix-ui/react-dialog";
import { Icon } from "./icon";
import { useState } from "react";
import { Textarea } from "./textarea";
import { NostrEvent, NostrPrefix, encodeTLV } from "@snort/system";
import { findTag } from "utils";
import AsyncButton from "./async-button";
import { useLogin } from "hooks/login";
import { System } from "index";
type ShareOn = "nostr" | "twitter";
export function ShareMenu({ ev }: { ev: NostrEvent }) {
const [share, setShare] = useState<ShareOn>();
const [message, setMessage] = useState("");
const login = useLogin();
const naddr = encodeTLV(
NostrPrefix.Address,
findTag(ev, "d")!,
undefined,
ev.kind,
ev.pubkey
);
const link = `https://zap.stream/${naddr}`;
async function sendMessage() {
const pub = login?.publisher();
if (pub) {
const ev = await pub.note(message);
console.debug(ev);
System.BroadcastEvent(ev);
setShare(undefined);
}
}
return (
<>
<Menu
align="end"
gap={5}
menuClassName="ctx-menu"
menuButton={
<button type="button" className="btn btn-secondary">
Share
</button>
}
>
<MenuItem
onClick={() => {
setMessage(
`Come check out my stream on zap.stream!\n\n${link}\n\nnostr:${naddr}`
);
setShare("nostr");
}}
>
<Icon name="nostrich" size={24} />
Broadcast on Nostr
</MenuItem>
</Menu>
<Dialog.Root
open={Boolean(share)}
onOpenChange={() => setShare(undefined)}
>
<Dialog.Portal>
<Dialog.Overlay className="dialog-overlay" />
<Dialog.Content className="dialog-content">
<h2>Share</h2>
<div className="paper">
<Textarea
emojis={[]}
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={() => {
//noop
}}
rows={15}
/>
</div>
<AsyncButton className="btn btn-primary" onClick={sendMessage}>
Send
</AsyncButton>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
</>
);
}

View File

@ -1,6 +1,8 @@
import "./textarea.css";
import type { KeyboardEvent, ChangeEvent } from "react";
import ReactTextareaAutocomplete, { TriggerType } from "@webscopeio/react-textarea-autocomplete";
import ReactTextareaAutocomplete, {
TriggerType,
} from "@webscopeio/react-textarea-autocomplete";
import "@webscopeio/react-textarea-autocomplete/style.css";
import uniqWith from "lodash/uniqWith";
import isEqual from "lodash/isEqual";
@ -41,6 +43,7 @@ interface TextareaProps {
value: string;
onChange: (e: ChangeEvent<HTMLTextAreaElement>) => void;
onKeyDown: (e: KeyboardEvent<Element>) => void;
rows?: number;
}
export function Textarea({ emojis, ...props }: TextareaProps) {

View File

@ -62,6 +62,12 @@ a {
gap: 12px;
}
.w-max {
width: stretch;
width: -webkit-fill-available;
width: -moz-available;
}
.btn {
border: none;
outline: none;
@ -71,6 +77,10 @@ a {
line-height: 20px;
padding: 8px 16px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.btn-border {
@ -95,6 +105,11 @@ a {
opacity: 0.9;
}
.btn-secondary {
color: white;
background: #222;
}
.btn-warning {
background: #ff563f;
color: white;
@ -171,10 +186,29 @@ div.paper {
border: 1px solid #ff563f;
}
.dialog-overlay {
background-color: rgba(0, 0, 0, 0.8);
position: fixed;
inset: 0;
z-index: 1;
}
.dialog-content {
display: flex;
flex-direction: column;
gap: 12px;
z-index: 2;
background-color: #171717;
border-radius: 24px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90vw;
max-width: 450px;
max-height: 85vh;
padding: 25px;
overflow-y: auto;
}
.dialog-content div.paper {

View File

@ -177,28 +177,6 @@ button span.hide-on-mobile {
}
}
.dialog-overlay {
background-color: rgba(0, 0, 0, 0.8);
position: fixed;
inset: 0;
z-index: 1;
}
.dialog-content {
z-index: 2;
background-color: #171717;
border-radius: 6px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90vw;
max-width: 450px;
max-height: 85vh;
padding: 25px;
overflow-y: auto;
}
.zap-icon {
color: #FF8D2B;
}

View File

@ -2,7 +2,6 @@
grid-area: main-content;
}
.video-content video {
max-height: 230px;
width: 100vw;
@ -18,7 +17,11 @@
display: flex;
justify-content: space-between;
padding: 0 16px;
width: 100%;
gap: 24px;
}
.profile-info .btn {
padding: 12px 16px;
}
@media (min-width: 768px) {
@ -39,7 +42,7 @@
font-weight: 700;
font-size: 14px;
line-height: 18px;
color: #A7A7A7;
color: #a7a7a7;
}
.pill.live {
@ -49,7 +52,7 @@
.pill.viewers {
color: white;
background: rgba(23, 23, 23, 0.70);
background: rgba(23, 23, 23, 0.7);
}
@media (min-width: 1020px) {
@ -96,7 +99,7 @@
.info {
grid-area: profile;
margin-top: 8px
margin-top: 8px;
}
.info h1 {
@ -116,13 +119,6 @@
gap: 12px;
}
.info .btn.zap {
padding: 12px 16px;
display: flex;
align-items: center;
gap: 12px;
}
.offline {
background: rgba(0, 0, 0, 0.5);
display: flex;
@ -130,11 +126,11 @@
align-items: center;
}
.online>div {
.online > div {
display: none;
}
.offline>div {
.offline > div {
position: fixed;
top: 5em;
text-transform: uppercase;
@ -143,12 +139,12 @@
}
@media (min-width: 768px) {
.offline>div {
.offline > div {
top: 10em;
}
}
.offline>video {
.offline > video {
z-index: -1;
position: relative;
}

View File

@ -19,6 +19,7 @@ import { Tags } from "element/tags";
import { StatePill } from "element/state-pill";
import { formatSats } from "number";
import { StreamTimer } from "element/stream-time";
import { ShareMenu } from "element/share-menu";
function ProfileInfo({ ev, goal }: { ev?: NostrEvent; goal?: TaggedRawEvent }) {
const login = useLogin();
@ -74,17 +75,24 @@ function ProfileInfo({ ev, goal }: { ev?: NostrEvent; goal?: TaggedRawEvent }) {
</div>
)}
</div>
<div className="profile-info flex g24">
<div className="profile-info w-max">
<Profile pubkey={host ?? ""} />
{zapTarget && ev && (
<SendZapsDialog
lnurl={zapTarget}
pubkey={host}
aTag={`${ev.kind}:${ev.pubkey}:${findTag(ev, "d")}`}
eTag={goal?.id}
targetName={getName(ev.pubkey, profile)}
/>
)}
<div className="flex g12">
{ev && (
<>
<ShareMenu ev={ev} />
{zapTarget && (
<SendZapsDialog
lnurl={zapTarget}
pubkey={host}
aTag={`${ev.kind}:${ev.pubkey}:${findTag(ev, "d")}`}
eTag={goal?.id}
targetName={getName(ev.pubkey, profile)}
/>
)}
</>
)}
</div>
</div>
</div>
</>