mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-19 19:46:34 +00:00
added mute button to channel
This commit is contained in:
parent
d8d3113fb9
commit
5b953b9ed4
@ -15,6 +15,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emoji-mart/data": "^1.1.2",
|
"@emoji-mart/data": "^1.1.2",
|
||||||
"@emoji-mart/react": "^1.1.1",
|
"@emoji-mart/react": "^1.1.1",
|
||||||
|
"@radix-ui/react-alert-dialog": "^1.0.3",
|
||||||
"@radix-ui/react-collapsible": "^1.0.2",
|
"@radix-ui/react-collapsible": "^1.0.2",
|
||||||
"@radix-ui/react-dialog": "^1.0.3",
|
"@radix-ui/react-dialog": "^1.0.3",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
||||||
|
@ -3,6 +3,7 @@ lockfileVersion: 5.4
|
|||||||
specifiers:
|
specifiers:
|
||||||
'@emoji-mart/data': ^1.1.2
|
'@emoji-mart/data': ^1.1.2
|
||||||
'@emoji-mart/react': ^1.1.1
|
'@emoji-mart/react': ^1.1.1
|
||||||
|
'@radix-ui/react-alert-dialog': ^1.0.3
|
||||||
'@radix-ui/react-collapsible': ^1.0.2
|
'@radix-ui/react-collapsible': ^1.0.2
|
||||||
'@radix-ui/react-dialog': ^1.0.3
|
'@radix-ui/react-dialog': ^1.0.3
|
||||||
'@radix-ui/react-dropdown-menu': ^2.0.4
|
'@radix-ui/react-dropdown-menu': ^2.0.4
|
||||||
@ -56,6 +57,7 @@ specifiers:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@emoji-mart/data': 1.1.2
|
'@emoji-mart/data': 1.1.2
|
||||||
'@emoji-mart/react': 1.1.1_kyrnz3vmphzqyjjk2ivrm6bcsu
|
'@emoji-mart/react': 1.1.1_kyrnz3vmphzqyjjk2ivrm6bcsu
|
||||||
|
'@radix-ui/react-alert-dialog': 1.0.3_zn3vyfk3tbnwebg5ldvieekjaq
|
||||||
'@radix-ui/react-collapsible': 1.0.2_biqbaboplfbrettd7655fr4n2y
|
'@radix-ui/react-collapsible': 1.0.2_biqbaboplfbrettd7655fr4n2y
|
||||||
'@radix-ui/react-dialog': 1.0.3_zn3vyfk3tbnwebg5ldvieekjaq
|
'@radix-ui/react-dialog': 1.0.3_zn3vyfk3tbnwebg5ldvieekjaq
|
||||||
'@radix-ui/react-dropdown-menu': 2.0.4_zn3vyfk3tbnwebg5ldvieekjaq
|
'@radix-ui/react-dropdown-menu': 2.0.4_zn3vyfk3tbnwebg5ldvieekjaq
|
||||||
@ -563,6 +565,26 @@ packages:
|
|||||||
'@babel/runtime': 7.21.0
|
'@babel/runtime': 7.21.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-alert-dialog/1.0.3_zn3vyfk3tbnwebg5ldvieekjaq:
|
||||||
|
resolution:
|
||||||
|
{ integrity: sha512-QXFy7+bhGi0u+paF2QbJeSCHZs4gLMJIPm6sajUamyW0fro6g1CaSGc5zmc4QmK2NlSGUrq8m+UsUqJYtzvXow== }
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.21.0
|
||||||
|
'@radix-ui/primitive': 1.0.0
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.0_react@18.2.0
|
||||||
|
'@radix-ui/react-context': 1.0.0_react@18.2.0
|
||||||
|
'@radix-ui/react-dialog': 1.0.3_zn3vyfk3tbnwebg5ldvieekjaq
|
||||||
|
'@radix-ui/react-primitive': 1.0.2_biqbaboplfbrettd7655fr4n2y
|
||||||
|
'@radix-ui/react-slot': 1.0.1_react@18.2.0
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0_react@18.2.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-arrow/1.0.2_biqbaboplfbrettd7655fr4n2y:
|
/@radix-ui/react-arrow/1.0.2_biqbaboplfbrettd7655fr4n2y:
|
||||||
resolution:
|
resolution:
|
||||||
{ integrity: sha512-fqYwhhI9IarZ0ll2cUSfKuXHlJK0qE4AfnRrPBbRwEH/4mGQn04/QFGomLi8TXWIdv9WJk//KgGm+aDxVIr1wA== }
|
{ integrity: sha512-fqYwhhI9IarZ0ll2cUSfKuXHlJK0qE4AfnRrPBbRwEH/4mGQn04/QFGomLi8TXWIdv9WJk//KgGm+aDxVIr1wA== }
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
import { MuteButton } from '@components/channels/messages/muteButton';
|
||||||
import { ReplyButton } from '@components/channels/messages/replyButton';
|
import { ReplyButton } from '@components/channels/messages/replyButton';
|
||||||
import { MessageUser } from '@components/chats/messageUser';
|
import { MessageUser } from '@components/chats/messageUser';
|
||||||
|
|
||||||
import HideIcon from '@assets/icons/hide';
|
import HideIcon from '@assets/icons/hide';
|
||||||
import MuteIcon from '@assets/icons/mute';
|
|
||||||
|
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
|
|
||||||
@ -25,9 +25,7 @@ const ChannelMessageItem = ({ data }: { data: any }) => {
|
|||||||
<button className="inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-800">
|
<button className="inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-800">
|
||||||
<HideIcon className="h-4 w-4 text-zinc-400" />
|
<HideIcon className="h-4 w-4 text-zinc-400" />
|
||||||
</button>
|
</button>
|
||||||
<button className="inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-800">
|
<MuteButton pubkey={data.pubkey} />
|
||||||
<MuteIcon className="h-4 w-4 text-zinc-400" />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
85
src/components/channels/messages/muteButton.tsx
Normal file
85
src/components/channels/messages/muteButton.tsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { RelayContext } from '@components/relaysProvider';
|
||||||
|
|
||||||
|
import { dateToUnix } from '@utils/getDate';
|
||||||
|
|
||||||
|
import MuteIcon from '@assets/icons/mute';
|
||||||
|
|
||||||
|
import * as AlertDialog from '@radix-ui/react-alert-dialog';
|
||||||
|
import * as Tooltip from '@radix-ui/react-tooltip';
|
||||||
|
import useLocalStorage from '@rehooks/local-storage';
|
||||||
|
import { getEventHash, signEvent } from 'nostr-tools';
|
||||||
|
import { useCallback, useContext } from 'react';
|
||||||
|
|
||||||
|
export const MuteButton = ({ pubkey }: { pubkey: string }) => {
|
||||||
|
const [pool, relays]: any = useContext(RelayContext);
|
||||||
|
const [activeAccount]: any = useLocalStorage('activeAccount', {});
|
||||||
|
|
||||||
|
const muteUser = useCallback(() => {
|
||||||
|
const event: any = {
|
||||||
|
content: '',
|
||||||
|
created_at: dateToUnix(),
|
||||||
|
kind: 44,
|
||||||
|
pubkey: activeAccount.pubkey,
|
||||||
|
tags: [['p', pubkey]],
|
||||||
|
};
|
||||||
|
event.id = getEventHash(event);
|
||||||
|
event.sig = signEvent(event, activeAccount.privkey);
|
||||||
|
|
||||||
|
// publish note
|
||||||
|
pool.publish(event, relays);
|
||||||
|
}, [pubkey, activeAccount.privkey, activeAccount.pubkey, pool, relays]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AlertDialog.Root>
|
||||||
|
<Tooltip.Provider>
|
||||||
|
<Tooltip.Root>
|
||||||
|
<AlertDialog.Trigger asChild>
|
||||||
|
<Tooltip.Trigger asChild>
|
||||||
|
<button className="inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-800">
|
||||||
|
<MuteIcon className="h-4 w-4 text-zinc-400" />
|
||||||
|
</button>
|
||||||
|
</Tooltip.Trigger>
|
||||||
|
</AlertDialog.Trigger>
|
||||||
|
<Tooltip.Portal>
|
||||||
|
<Tooltip.Content
|
||||||
|
className="select-none rounded-md bg-zinc-800 px-4 py-2 text-sm leading-none text-zinc-100 shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] will-change-[transform,opacity] data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade"
|
||||||
|
sideOffset={4}
|
||||||
|
>
|
||||||
|
Mute user
|
||||||
|
<Tooltip.Arrow className="fill-zinc-800" />
|
||||||
|
</Tooltip.Content>
|
||||||
|
</Tooltip.Portal>
|
||||||
|
</Tooltip.Root>
|
||||||
|
</Tooltip.Provider>
|
||||||
|
<AlertDialog.Portal>
|
||||||
|
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black bg-opacity-30 backdrop-blur-sm data-[state=open]:animate-overlayShow" />
|
||||||
|
<AlertDialog.Content className="fixed left-[50%] top-[50%] z-50 max-h-[85vh] w-[90vw] max-w-[500px] translate-x-[-50%] translate-y-[-50%] rounded-md bg-zinc-900 p-6 shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] ring-1 ring-zinc-800 focus:outline-none data-[state=open]:animate-contentShow">
|
||||||
|
<AlertDialog.Title className="m-0 font-medium text-zinc-100">Are you absolutely sure?</AlertDialog.Title>
|
||||||
|
<AlertDialog.Description className="mb-5 mt-4 text-zinc-400">
|
||||||
|
This action cannot be undone. This will permanently mute this user and you will never receive message from
|
||||||
|
this user
|
||||||
|
</AlertDialog.Description>
|
||||||
|
<div className="flex justify-end gap-4">
|
||||||
|
<AlertDialog.Cancel asChild>
|
||||||
|
<button
|
||||||
|
autoFocus={false}
|
||||||
|
className="inline-flex h-9 items-center justify-center rounded px-4 font-medium leading-none text-zinc-200 outline-none hover:bg-zinc-900 focus:shadow-[0_0_0_2px]"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</AlertDialog.Cancel>
|
||||||
|
<AlertDialog.Action asChild>
|
||||||
|
<button
|
||||||
|
autoFocus={false}
|
||||||
|
onClick={() => muteUser()}
|
||||||
|
className="inline-flex h-9 items-center justify-center rounded bg-red-500 px-4 font-medium leading-none text-white outline-none hover:bg-red-600 focus:shadow-[0_0_0_2px] focus:shadow-red-700"
|
||||||
|
>
|
||||||
|
Yes, mute this user
|
||||||
|
</button>
|
||||||
|
</AlertDialog.Action>
|
||||||
|
</div>
|
||||||
|
</AlertDialog.Content>
|
||||||
|
</AlertDialog.Portal>
|
||||||
|
</AlertDialog.Root>
|
||||||
|
);
|
||||||
|
};
|
@ -55,7 +55,7 @@ export const ActiveAccount = memo(function ActiveAccount({ user }: { user: any }
|
|||||||
relays,
|
relays,
|
||||||
(event: any) => {
|
(event: any) => {
|
||||||
if (event.tags.length > 0) {
|
if (event.tags.length > 0) {
|
||||||
insertFollowsToStorage(event.tags);
|
//insertFollowsToStorage(event.tags);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
20000,
|
20000,
|
||||||
|
@ -7,6 +7,7 @@ import { RelayContext } from '@components/relaysProvider';
|
|||||||
|
|
||||||
import { channelReplyAtom } from '@stores/channel';
|
import { channelReplyAtom } from '@stores/channel';
|
||||||
|
|
||||||
|
import useLocalStorage from '@rehooks/local-storage';
|
||||||
import { useResetAtom } from 'jotai/utils';
|
import { useResetAtom } from 'jotai/utils';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import {
|
import {
|
||||||
@ -16,6 +17,7 @@ import {
|
|||||||
ReactPortal,
|
ReactPortal,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
@ -26,30 +28,44 @@ export default function Page() {
|
|||||||
const id: string | string[] = router.query.id || null;
|
const id: string | string[] = router.query.id || null;
|
||||||
|
|
||||||
const [messages, setMessages] = useState([]);
|
const [messages, setMessages] = useState([]);
|
||||||
|
const [activeAccount]: any = useLocalStorage('activeAccount', {});
|
||||||
const resetChannelReply = useResetAtom(channelReplyAtom);
|
const resetChannelReply = useResetAtom(channelReplyAtom);
|
||||||
|
|
||||||
|
const muted = useRef(new Set());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// reset channel reply
|
// reset channel reply
|
||||||
resetChannelReply();
|
resetChannelReply();
|
||||||
// subscribe event
|
// subscribe event
|
||||||
const unsubscribe = pool.subscribe(
|
const unsubscribe = pool.subscribe(
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
authors: [activeAccount.pubkey],
|
||||||
|
kinds: [44],
|
||||||
|
since: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'#e': [id],
|
'#e': [id],
|
||||||
kinds: [42],
|
kinds: [42, 43],
|
||||||
since: 0,
|
since: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
relays,
|
relays,
|
||||||
(event: any) => {
|
(event: any) => {
|
||||||
|
if (event.kind === 44) {
|
||||||
|
muted.current = muted.current.add(event.tags[0][1]);
|
||||||
|
} else if (event.kind === 42) {
|
||||||
|
if (!muted.current.has(event.pubkey)) {
|
||||||
setMessages((messages) => [event, ...messages]);
|
setMessages((messages) => [event, ...messages]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribe;
|
unsubscribe;
|
||||||
};
|
};
|
||||||
}, [id, pool, relays, resetChannelReply]);
|
}, [id, pool, relays, activeAccount.pubkey, resetChannelReply]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col justify-between">
|
<div className="flex h-full w-full flex-col justify-between">
|
||||||
|
Loading…
Reference in New Issue
Block a user