feat: in-chat mute button

resolves #73
This commit is contained in:
2023-08-04 18:28:08 +02:00
parent 22a799aac7
commit 78d9a2779a
5 changed files with 46 additions and 17 deletions

View File

@ -13,6 +13,7 @@ import { Icon } from "element/icon";
import { Emoji as EmojiComponent } from "element/emoji";
import { Profile } from "./profile";
import { Text } from "element/text";
import { useMute } from "element/mute-button";
import { SendZapsDialog } from "element/send-zap";
import { CollapsibleEvent } from "element/collapsible";
import { useLogin } from "hooks/login";
@ -55,6 +56,7 @@ export function ChatMessage({
const emojiRef = useRef(null);
const isTablet = useMediaQuery("(max-width: 1020px)");
const isHovering = useHover(ref);
const { mute } = useMute(ev.pubkey);
const [showZapDialog, setShowZapDialog] = useState(false);
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
const login = useLogin();
@ -62,6 +64,8 @@ export function ChatMessage({
System,
inView?.isIntersecting ? ev.pubkey : undefined
);
const shouldShowMuteButton =
ev.pubkey !== streamer && ev.pubkey != login?.pubkey;
const zapTarget = profile?.lud16 ?? profile?.lud06;
const zaps = useMemo(() => {
return reactions
@ -132,11 +136,16 @@ export function ChatMessage({
const topOffset = ref.current?.getBoundingClientRect().top;
const leftOffset = ref.current?.getBoundingClientRect().left;
function pickEmoji(ev: React.MouseEvent) {
ev.stopPropagation();
function pickEmoji(e: React.MouseEvent) {
e.stopPropagation();
setShowEmojiPicker(!showEmojiPicker);
}
async function muteUser(e: React.MouseEvent) {
e.stopPropagation();
mute();
}
return (
<>
<div
@ -229,6 +238,11 @@ export function ChatMessage({
<button className="message-zap-button" onClick={pickEmoji}>
<Icon name="face" className="message-zap-button-icon" />
</button>
{shouldShowMuteButton && (
<button className="message-zap-button" onClick={muteUser}>
<Icon name="user-x" className="message-zap-button-icon" />
</button>
)}
</div>
)}
</div>

View File

@ -1,13 +1,17 @@
import { useMemo } from "react";
import { useLogin } from "hooks/login";
import AsyncButton from "element/async-button";
import { Login, System } from "index";
import { MUTED } from "const";
export function LoggedInMuteButton({ pubkey }: { pubkey: string }) {
export function useMute(pubkey: string) {
const login = useLogin();
const { tags, content } = login!.muted;
const muted = tags.filter((t) => t.at(0) === "p");
const isMuted = muted.find((t) => t.at(1) === pubkey);
const muted = useMemo(() => tags.filter((t) => t.at(0) === "p"), [tags]);
const isMuted = useMemo(
() => muted.find((t) => t.at(1) === pubkey),
[pubkey, muted]
);
async function unmute() {
const pub = login?.publisher();
@ -43,6 +47,12 @@ export function LoggedInMuteButton({ pubkey }: { pubkey: string }) {
}
}
return { isMuted, mute, unmute };
}
export function LoggedInMuteButton({ pubkey }: { pubkey: string }) {
const { isMuted, mute, unmute } = useMute(pubkey);
return (
<AsyncButton
type="button"

View File

@ -42,17 +42,19 @@ export function useStreamsFeed(tag?: string) {
return [];
}, [feed.data]);
const live = feedSorted.filter(
(a) => findTag(a, "status") === StreamState.Live
).sort(sortStarts);
const planned = feedSorted.filter(
(a) => findTag(a, "status") === StreamState.Planned
).sort(sortStarts);
const ended = feedSorted.filter((a) => {
const hasEnded = findTag(a, "status") === StreamState.Ended;
const recording = findTag(a, "recording") ?? "";
return hasEnded && recording?.length > 0;
}).sort(sortCreatedAt);
const live = feedSorted
.filter((a) => findTag(a, "status") === StreamState.Live)
.sort(sortStarts);
const planned = feedSorted
.filter((a) => findTag(a, "status") === StreamState.Planned)
.sort(sortStarts);
const ended = feedSorted
.filter((a) => {
const hasEnded = findTag(a, "status") === StreamState.Ended;
const recording = findTag(a, "recording") ?? "";
return hasEnded && recording?.length > 0;
})
.sort(sortCreatedAt);
return { live, planned, ended };
}

View File

@ -10,7 +10,7 @@ export enum LoginType {
}
interface ReplaceableTags {
tags: Array<string[]>;
tags: Tags;
content?: string;
timestamp: number;
}