feat: mute/unmute on profile
This commit is contained in:
@ -151,7 +151,7 @@ export function ChatMessage({
|
|||||||
pubkey={ev.pubkey}
|
pubkey={ev.pubkey}
|
||||||
profile={profile}
|
profile={profile}
|
||||||
/>
|
/>
|
||||||
<Text content={ev.content} tags={ev.tags} />
|
<Text tags={ev.tags} content={ev.content} />
|
||||||
{(hasReactions || hasZaps) && (
|
{(hasReactions || hasZaps) && (
|
||||||
<div className="message-reactions">
|
<div className="message-reactions">
|
||||||
{hasZaps && (
|
{hasZaps && (
|
||||||
|
@ -16,7 +16,7 @@ export function LoggedInFollowButton({ pubkey }: { pubkey: string }) {
|
|||||||
if (pub) {
|
if (pub) {
|
||||||
const newFollows = tags.filter((t) => t.at(1) !== pubkey);
|
const newFollows = tags.filter((t) => t.at(1) !== pubkey);
|
||||||
const ev = await pub.generic((eb) => {
|
const ev = await pub.generic((eb) => {
|
||||||
eb.kind(EventKind.ContactList).content(JSON.stringify(login.relays));
|
eb.kind(EventKind.ContactList).content(login.follows.content);
|
||||||
for (const t of newFollows) {
|
for (const t of newFollows) {
|
||||||
eb.tag(t);
|
eb.tag(t);
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ export function LoggedInFollowButton({ pubkey }: { pubkey: string }) {
|
|||||||
});
|
});
|
||||||
console.debug(ev);
|
console.debug(ev);
|
||||||
System.BroadcastEvent(ev);
|
System.BroadcastEvent(ev);
|
||||||
Login.setFollows(newFollows, unixNow());
|
Login.setFollows(newFollows, login.follows.content, unixNow());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ export function LoggedInFollowButton({ pubkey }: { pubkey: string }) {
|
|||||||
if (pub) {
|
if (pub) {
|
||||||
const newFollows = [...tags, ["p", pubkey]];
|
const newFollows = [...tags, ["p", pubkey]];
|
||||||
const ev = await pub.generic((eb) => {
|
const ev = await pub.generic((eb) => {
|
||||||
eb.kind(EventKind.ContactList).content(JSON.stringify(login.relays));
|
eb.kind(EventKind.ContactList).content(login.follows.content);
|
||||||
for (const tag of newFollows) {
|
for (const tag of newFollows) {
|
||||||
eb.tag(tag);
|
eb.tag(tag);
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ export function LoggedInFollowButton({ pubkey }: { pubkey: string }) {
|
|||||||
});
|
});
|
||||||
console.debug(ev);
|
console.debug(ev);
|
||||||
System.BroadcastEvent(ev);
|
System.BroadcastEvent(ev);
|
||||||
Login.setFollows(newFollows, unixNow());
|
Login.setFollows(newFollows, login.follows.content, unixNow());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,3 +357,17 @@
|
|||||||
height: 18px;
|
height: 18px;
|
||||||
border-radius: unset;
|
border-radius: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message .message-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message .message-container .markdown p {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message .message-container .markdown > p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
65
src/element/mute-button.tsx
Normal file
65
src/element/mute-button.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { unixNow } from "@snort/shared";
|
||||||
|
|
||||||
|
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 }) {
|
||||||
|
const login = useLogin();
|
||||||
|
const tags = login.muted.tags;
|
||||||
|
const muted = tags.filter((t) => t.at(0) === "p");
|
||||||
|
const isMuted = muted.find((t) => t.at(1) === pubkey);
|
||||||
|
|
||||||
|
async function unmute() {
|
||||||
|
const pub = login?.publisher();
|
||||||
|
if (pub) {
|
||||||
|
const newMuted = tags.filter((t) => t.at(1) !== pubkey);
|
||||||
|
const ev = await pub.generic((eb) => {
|
||||||
|
eb.kind(MUTED).content(login.muted.content);
|
||||||
|
for (const t of newMuted) {
|
||||||
|
eb.tag(t);
|
||||||
|
}
|
||||||
|
return eb;
|
||||||
|
});
|
||||||
|
console.debug(ev);
|
||||||
|
System.BroadcastEvent(ev);
|
||||||
|
Login.setMuted(newMuted, login.muted.content, unixNow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mute() {
|
||||||
|
const pub = login?.publisher();
|
||||||
|
if (pub) {
|
||||||
|
const newMuted = [...tags, ["p", pubkey]];
|
||||||
|
const ev = await pub.generic((eb) => {
|
||||||
|
eb.kind(MUTED).content(login.muted.content);
|
||||||
|
for (const tag of newMuted) {
|
||||||
|
eb.tag(tag);
|
||||||
|
}
|
||||||
|
return eb;
|
||||||
|
});
|
||||||
|
console.debug(ev);
|
||||||
|
System.BroadcastEvent(ev);
|
||||||
|
Login.setMuted(newMuted, login.muted.content, unixNow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AsyncButton
|
||||||
|
disabled={login.muted.timestamp === 0}
|
||||||
|
type="button"
|
||||||
|
className="btn delete-button"
|
||||||
|
onClick={isMuted ? unmute : mute}
|
||||||
|
>
|
||||||
|
{isMuted ? "Unmute" : "Mute"}
|
||||||
|
</AsyncButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MuteButton({ pubkey }: { pubkey: string }) {
|
||||||
|
const login = useLogin();
|
||||||
|
return login?.pubkey ? (
|
||||||
|
<LoggedInMuteButton loggedIn={login.pubkey} pubkey={pubkey} />
|
||||||
|
) : null;
|
||||||
|
}
|
@ -65,11 +65,10 @@ export function useLoginEvents(pubkey?: string, leaveOpen = false) {
|
|||||||
setUserEmojis(ev.tags);
|
setUserEmojis(ev.tags);
|
||||||
}
|
}
|
||||||
if (ev?.kind === MUTED) {
|
if (ev?.kind === MUTED) {
|
||||||
// todo: decrypt ev.content tags
|
Login.setMuted(ev.tags, ev.content, ev.created_at);
|
||||||
Login.setMuted(ev.tags, ev.created_at);
|
|
||||||
}
|
}
|
||||||
if (ev?.kind === EventKind.ContactList) {
|
if (ev?.kind === EventKind.ContactList) {
|
||||||
Login.setFollows(ev.tags, ev.created_at);
|
Login.setFollows(ev.tags, ev.content, ev.created_at);
|
||||||
}
|
}
|
||||||
if (ev?.kind === EventKind.Relays) {
|
if (ev?.kind === EventKind.Relays) {
|
||||||
Login.setRelays(ev.tags, ev.created_at);
|
Login.setRelays(ev.tags, ev.created_at);
|
||||||
|
@ -12,6 +12,7 @@ export enum LoginType {
|
|||||||
|
|
||||||
interface ReplaceableTags {
|
interface ReplaceableTags {
|
||||||
tags: Array<string[]>;
|
tags: Array<string[]>;
|
||||||
|
content: "";
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +73,12 @@ export class LoginStore extends ExternalStore<LoginSession | undefined> {
|
|||||||
return this.#session ? { ...this.#session } : undefined;
|
return this.#session ? { ...this.#session } : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
setFollows(follows: Array<string>, ts: number) {
|
setFollows(follows: Array<string>, content: string, ts: number) {
|
||||||
if (this.#session.follows.timestamp >= ts) {
|
if (this.#session.follows.timestamp >= ts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.#session.follows.tags = follows;
|
this.#session.follows.tags = follows;
|
||||||
|
this.#session.follows.content = content;
|
||||||
this.#session.follows.timestamp = ts;
|
this.#session.follows.timestamp = ts;
|
||||||
this.#save();
|
this.#save();
|
||||||
}
|
}
|
||||||
@ -86,11 +88,12 @@ export class LoginStore extends ExternalStore<LoginSession | undefined> {
|
|||||||
this.#save();
|
this.#save();
|
||||||
}
|
}
|
||||||
|
|
||||||
setMuted(muted: Array<string[]>, ts: number) {
|
setMuted(muted: Array<string[]>, content: string, ts: number) {
|
||||||
if (this.#session.muted.timestamp >= ts) {
|
if (this.#session.muted.timestamp >= ts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.#session.muted.tags = muted;
|
this.#session.muted.tags = muted;
|
||||||
|
this.#session.muted.content = content;
|
||||||
this.#session.muted.timestamp = ts;
|
this.#session.muted.timestamp = ts;
|
||||||
this.#save();
|
this.#save();
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import { Icon } from "element/icon";
|
|||||||
import { SendZapsDialog } from "element/send-zap";
|
import { SendZapsDialog } from "element/send-zap";
|
||||||
import { VideoTile } from "element/video-tile";
|
import { VideoTile } from "element/video-tile";
|
||||||
import { FollowButton } from "element/follow-button";
|
import { FollowButton } from "element/follow-button";
|
||||||
|
import { MuteButton } from "element/mute-button";
|
||||||
import { useProfile } from "hooks/profile";
|
import { useProfile } from "hooks/profile";
|
||||||
import useTopZappers from "hooks/top-zappers";
|
import useTopZappers from "hooks/top-zappers";
|
||||||
import { Text } from "element/text";
|
import { Text } from "element/text";
|
||||||
@ -131,6 +132,7 @@ export function ProfilePage() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<FollowButton pubkey={link.id} />
|
<FollowButton pubkey={link.id} />
|
||||||
|
<MuteButton pubkey={link.id} />
|
||||||
</div>
|
</div>
|
||||||
<div className="profile-information">
|
<div className="profile-information">
|
||||||
{profile?.name && <h1 className="name">{profile.name}</h1>}
|
{profile?.name && <h1 className="name">{profile.name}</h1>}
|
||||||
|
Reference in New Issue
Block a user