diff --git a/public/icons.svg b/public/icons.svg
index 8de597e..a7420d8 100644
--- a/public/icons.svg
+++ b/public/icons.svg
@@ -85,5 +85,8 @@
+
+
+
diff --git a/src/element/chat-message.tsx b/src/element/chat-message.tsx
index 858d16d..f472c23 100644
--- a/src/element/chat-message.tsx
+++ b/src/element/chat-message.tsx
@@ -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 (
<>
+ {shouldShowMuteButton && (
+
+ )}
)}
diff --git a/src/element/mute-button.tsx b/src/element/mute-button.tsx
index b008813..a992469 100644
--- a/src/element/mute-button.tsx
+++ b/src/element/mute-button.tsx
@@ -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 (
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 };
}
diff --git a/src/login.ts b/src/login.ts
index d06ecb0..dbb5b7a 100644
--- a/src/login.ts
+++ b/src/login.ts
@@ -10,7 +10,7 @@ export enum LoginType {
}
interface ReplaceableTags {
- tags: Array;
+ tags: Tags;
content?: string;
timestamp: number;
}