feat: add call entry into profile

This commit is contained in:
Tristan Yang
2023-05-19 15:35:34 +08:00
parent 50387e726a
commit 7f2e976286
4 changed files with 58 additions and 16 deletions
+30 -12
View File
@@ -1,13 +1,16 @@
import { FC, memo } from "react";
import { NavLink } from "react-router-dom";
import Tippy from "@tippyjs/react";
import { useGetAgoraStatusQuery } from "@/app/services/server";
import { useAppSelector } from "@/app/store";
import IconCall from "@/assets/icons/call.svg";
import IconMessage from "@/assets/icons/message.svg";
import IconMore from "@/assets/icons/more.svg";
import Avatar from "../Avatar";
import useUserOperation from "@/hooks/useUserOperation";
import { useAppSelector } from "@/app/store";
import { useTranslation } from "react-i18next";
import Tippy from "@tippyjs/react";
import clsx from "clsx";
import { FC, memo } from "react";
import { useTranslation } from "react-i18next";
import { NavLink } from "react-router-dom";
import Avatar from "../Avatar";
interface Props {
uid: number;
@@ -16,11 +19,13 @@ interface Props {
}
const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
const { data: agoraEnabled } = useGetAgoraStatusQuery();
const { t } = useTranslation("member");
const { t: ct } = useTranslation();
const {
canCopyEmail,
copyEmail,
startCall,
removeFromChannel,
canRemoveFromChannel,
canRemove,
@@ -32,7 +37,6 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
data: store.users.byId[uid]
};
});
if (!data) return null;
// console.log("profile", data);
const {
@@ -41,11 +45,14 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
avatar
// introduction = "This guy has nothing to introduce",
} = data;
const isCard = type == 'card';
const isCard = type == "card";
const canRemoveFromServer = !isCard && canRemove;
const hasMore = email || canRemoveFromChannel || canRemoveFromServer;
const iconClass = `cursor-pointer flex flex-col items-center gap-1 rounded-lg w-32 text-primary-400 bg-gray-50 dark:bg-gray-800 text-sm pt-3.5 pb-3`;
const containerClass = clsx(`flex-center flex-col gap-1 z-[99] mt-20 select-none`, isCard ? "p-4 w-[280px] bg-white dark:bg-gray-800 drop-shadow rounded-md" : "md:w-[432px]");
const iconClass = `cursor-pointer flex flex-col items-center gap-1 rounded-lg w-32 text-primary-400 bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 text-sm pt-3.5 pb-3`;
const containerClass = clsx(
`flex-center flex-col gap-1 z-[99] mt-20 select-none`,
isCard ? "p-4 w-[280px] bg-white dark:bg-gray-800 drop-shadow rounded-md" : "md:w-[432px]"
);
return (
<div className={containerClass}>
<Avatar
@@ -65,15 +72,26 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
<span>{t("send_msg")}</span>
</li>
</NavLink>
{agoraEnabled && type == "embed" && (
<li role="button" onClick={startCall} className={`${iconClass} icon chat`}>
<IconCall className="fill-primary-400" />
<span>{t("call")}</span>
</li>
)}
<Tippy
disabled={!hasMore}
interactive
popperOptions={{ strategy: "fixed" }}
placement="bottom-start"
placement="right"
trigger="click"
hideOnClick={true}
content={
<ul className="context-menu">
{agoraEnabled && type == "card" && (
<li className="item" onClick={startCall}>
{t("call")}
</li>
)}
{canCopyEmail && (
<li className="item" onClick={copyEmail.bind(undefined, email)}>
{t("copy_email")}
@@ -94,7 +112,7 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
>
<li className={`${iconClass} icon ${hasMore ? "" : "text-gray-500"}`}>
<IconMore className={hasMore ? "fill-primary-500" : ""} />
<span >{ct("more")}</span>
<span>{ct("more")}</span>
</li>
</Tippy>
</ul>
+26 -4
View File
@@ -3,18 +3,23 @@ import toast from "react-hot-toast";
// import { ContentTypes } from "@/app/config";
import { useNavigate, useMatch } from "react-router-dom";
import { hideAll } from "tippy.js";
import { useTranslation } from "react-i18next";
import { useRemoveMembersMutation } from "@/app/services/channel";
import { useLazyDeleteUserQuery, useUpdateContactStatusMutation } from "@/app/services/user";
// import useConfig from "./useConfig";
import useCopy from "./useCopy";
import { useAppSelector } from "@/app/store";
import { useTranslation } from "react-i18next";
// import { AgoraConfig } from "@/types/server";
import { useVoice } from "@/components/Voice";
import { updateCallInfo } from "@/app/slices/voice";
import { updateDMVisibleAside } from "@/app/slices/footprint";
import { useDispatch } from "react-redux";
interface IProps {
uid?: number;
cid?: number;
}
const useUserOperation = ({ uid, cid }: IProps) => {
const { joinVoice, joined, joining = false, joinedAtThisContext } = useVoice({ id: uid ?? 0, context: "dm" });
const dispatch = useDispatch();
const { t: ct } = useTranslation();
const [passedUid, setPassedUid] = useState<number | undefined>(undefined);
const isUserDetailPath = useMatch(`/users/${uid}`);
@@ -68,7 +73,23 @@ const useUserOperation = ({ uid, cid }: IProps) => {
copy(finalEmail || "");
hideAll();
};
const startCall = () => {
if (joining || joined) {
alert("You have joined another channel, please leave first!");
return;
}
joinVoice();
const data = {
id: uid ?? 0,
aside: "voice" as const
};
dispatch(updateDMVisibleAside(data));
// 实时显示calling box
if (!joinedAtThisContext) {
dispatch(updateCallInfo({ from: loginUser?.uid ?? 0, to: uid, calling: false }));
}
navigateTo(`/chat/dm/${uid}`);
};
const startChat = () => {
navigateTo(`/chat/dm/${uid}`);
};
@@ -114,6 +135,7 @@ const useUserOperation = ({ uid, cid }: IProps) => {
canRemoveFromChannel,
canCopyEmail: !!user?.email,
copyEmail,
startCall
};
};
export default useUserOperation;