add muted popover

This commit is contained in:
Ren Amamiya
2023-04-25 18:19:55 +07:00
parent 5ea338a685
commit 9d635d472e
6 changed files with 138 additions and 12 deletions

View File

@@ -0,0 +1,52 @@
import { UserMuted } from '@components/user/muted';
import { Popover, Transition } from '@headlessui/react';
import { MicMute } from 'iconoir-react';
import { Fragment } from 'react';
export const ChannelBlackList = ({ blacklist }: { blacklist: any }) => {
return (
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button
className={`group inline-flex h-8 w-8 items-center justify-center rounded-md ${
open ? 'bg-zinc-800 hover:bg-zinc-700' : 'bg-zinc-900 hover:bg-zinc-800'
}`}
>
<MicMute width={16} height={16} className="text-zinc-400 group-hover:text-zinc-200" />
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute right-0 z-10 mt-1 w-screen max-w-xs transform px-4 sm:px-0">
<div className="flex flex-col gap-2 overflow-hidden rounded-lg border border-zinc-800 bg-zinc-900 shadow-popover">
<div className="h-min w-full shrink-0 border-b border-zinc-800 p-3">
<div className="flex flex-col gap-0.5">
<h3 className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text font-semibold leading-none text-transparent">
Your muted list
</h3>
<p className="text-xs leading-tight text-zinc-400">
Currently, unmute only affect locally, when you move to new client, muted list will loaded again
</p>
</div>
</div>
<div className="px-3 pb-3 pt-1">
{blacklist.map((item: any) => (
<UserMuted key={item.id} data={item} />
))}
</div>
</div>
</Popover.Panel>
</Transition>
</>
)}
</Popover>
);
};

View File

@@ -125,8 +125,8 @@ export const UpdateChannelModal = ({ id }: { id: string }) => {
</button>
</div>
<Dialog.Description className="leading-tight text-zinc-400">
Channels are freedom square, everyone can speech freely, no one can stop you or deceive what to
speech
New metadata will be published on all relays, and will be immediately available to all users, so
please carefully.
</Dialog.Description>
</div>
</div>

View File

@@ -0,0 +1,65 @@
import { DEFAULT_AVATAR } from '@stores/constants';
import { useProfileMetadata } from '@utils/hooks/useProfileMetadata';
import { shortenKey } from '@utils/shortenKey';
import { useState } from 'react';
export const UserMuted = ({ data }: { data: any }) => {
const profile = useProfileMetadata(data.content);
const [status, setStatus] = useState(data.status);
const unmute = async () => {
const { updateItemInBlacklist } = await import('@utils/storage');
const res = await updateItemInBlacklist(data.content, 0);
if (res) {
setStatus(0);
}
};
const mute = async () => {
const { updateItemInBlacklist } = await import('@utils/storage');
const res = await updateItemInBlacklist(data.content, 1);
if (res) {
setStatus(1);
}
};
return (
<div className="flex items-center justify-between">
<div className="flex items-center gap-1.5">
<div className="relative h-9 w-9 shrink rounded-md">
<img
src={profile?.picture || DEFAULT_AVATAR}
alt={data.content}
className="h-9 w-9 rounded-md object-cover"
loading="lazy"
/>
</div>
<div className="flex w-full flex-1 flex-col items-start gap-0.5 text-start">
<span className="truncate text-sm font-medium leading-none text-zinc-200">
{profile?.display_name || profile?.name}
</span>
<span className="text-xs leading-none text-zinc-400">{shortenKey(data.content)}</span>
</div>
</div>
<div>
{status === 1 ? (
<button
onClick={() => unmute()}
className="inline-flex h-6 w-min items-center justify-center rounded px-1.5 text-xs font-medium leading-none text-zinc-400 hover:bg-zinc-800 hover:text-fuchsia-500"
>
Unmute
</button>
) : (
<button
onClick={() => mute()}
className="inline-flex h-6 w-min items-center justify-center rounded px-1.5 text-xs font-medium leading-none text-zinc-400 hover:bg-zinc-800 hover:text-fuchsia-500"
>
Mute
</button>
)}
</div>
</div>
);
};

View File

@@ -1,4 +1,5 @@
import { AccountContext } from '@components/accountProvider';
import { ChannelBlackList } from '@components/channels/channelBlackList';
import { ChannelProfile } from '@components/channels/channelProfile';
import { UpdateChannelModal } from '@components/channels/updateChannelModal';
import { FormChannel } from '@components/form/channel';
@@ -12,7 +13,6 @@ import { dateToUnix, hoursAgo } from '@utils/getDate';
import { usePageContext } from '@utils/hooks/usePageContext';
import { arrayObjToPureArr } from '@utils/transform';
import { EyeClose } from 'iconoir-react';
import { useSetAtom } from 'jotai';
import { useResetAtom } from 'jotai/utils';
import { Suspense, lazy, useContext, useRef } from 'react';
@@ -21,12 +21,14 @@ import useSWRSubscription from 'swr/subscription';
const ChannelMessages = lazy(() => import('@components/channels/messages'));
let mutedList: any = [];
let hidedList: any = [];
let activeMutedList: any = [];
let activeHidedList: any = [];
if (typeof window !== 'undefined') {
const { getBlacklist, getActiveAccount } = await import('@utils/storage');
const { getBlacklist, getActiveBlacklist, getActiveAccount } = await import('@utils/storage');
const activeAccount = await getActiveAccount();
hidedList = await getBlacklist(activeAccount.id, 43);
activeHidedList = await getActiveBlacklist(activeAccount.id, 43);
activeMutedList = await getActiveBlacklist(activeAccount.id, 44);
mutedList = await getBlacklist(activeAccount.id, 44);
}
@@ -45,8 +47,8 @@ export function Page() {
const resetChannelReply = useResetAtom(channelReplyAtom);
const now = useRef(new Date());
const hided = arrayObjToPureArr(hidedList);
const muted = arrayObjToPureArr(mutedList);
const hided = arrayObjToPureArr(activeHidedList);
const muted = arrayObjToPureArr(activeMutedList);
useSWRSubscription(id, () => {
// reset channel reply
@@ -87,9 +89,7 @@ export function Page() {
<ChannelProfile id={id} pubkey={channelPubkey} />
</div>
<div className="flex items-center gap-2">
<div className="inline-flex h-8 w-8 items-center justify-center rounded-md bg-zinc-900">
<EyeClose width={16} height={16} className="text-zinc-400" />
</div>
<ChannelBlackList blacklist={mutedList} />
{activeAccount.pubkey === channelPubkey && <UpdateChannelModal id={id} />}
</div>
</div>

View File

@@ -174,7 +174,15 @@ export async function updateLastLogin(value: number) {
// get blacklist by kind and account id
export async function getBlacklist(account_id: number, kind: number) {
const db = await connect();
return await db.select(`SELECT content FROM blacklist WHERE account_id = "${account_id}" AND kind = "${kind}";`);
return await db.select(`SELECT * FROM blacklist WHERE account_id = "${account_id}" AND kind = "${kind}";`);
}
// get active blacklist by kind and account id
export async function getActiveBlacklist(account_id: number, kind: number) {
const db = await connect();
return await db.select(
`SELECT content FROM blacklist WHERE account_id = "${account_id}" AND kind = "${kind}" AND status = 1;`
);
}
// add to blacklist

View File

@@ -25,6 +25,7 @@ module.exports = {
inset 0 0 0 0.3px hsl(0deg 0% 100% / 30%),
0 0 0 0.5px hsl(0deg 0% 100% / 40%);
`,
popover: `0px 0px 7px rgba(0,0,0,0.52)`,
inner: `
0 2px 2px rgb(4 4 7 / 45%),
0 8px 24px rgb(4 4 7 / 60%)