From 7f2e976286cd19f97432a41fb0960b20936e5de7 Mon Sep 17 00:00:00 2001 From: Tristan Yang Date: Fri, 19 May 2023 15:35:34 +0800 Subject: [PATCH] feat: add call entry into profile --- public/locales/en/member.json | 1 + public/locales/zh/member.json | 1 + src/components/Profile/index.tsx | 42 +++++++++++++++++++++++--------- src/hooks/useUserOperation.ts | 30 ++++++++++++++++++++--- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/public/locales/en/member.json b/public/locales/en/member.json index db330018..7d221c48 100644 --- a/public/locales/en/member.json +++ b/public/locales/en/member.json @@ -19,6 +19,7 @@ "user": "User", "copy_email": "Copy Email", "send_msg": "Send Message", + "call": "Call", "remove": "Remove from Server", "remove_from_contact": "Remove From Contact", "remove_account": "Remove Account", diff --git a/public/locales/zh/member.json b/public/locales/zh/member.json index e99aa9cc..da4877b5 100644 --- a/public/locales/zh/member.json +++ b/public/locales/zh/member.json @@ -18,6 +18,7 @@ "user": "普通用户", "copy_email": "复制邮箱", "send_msg": "发消息", + "call": "呼叫", "remove": "从服务器删除", "remove_from_contact": "从联系人中移除", "remove_account": "注销账号", diff --git a/src/components/Profile/index.tsx b/src/components/Profile/index.tsx index 2f34ad26..155d34f4 100644 --- a/src/components/Profile/index.tsx +++ b/src/components/Profile/index.tsx @@ -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 = ({ 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 = ({ 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 = ({ 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 (
= ({ uid, type = "embed", cid }) => { {t("send_msg")} + {agoraEnabled && type == "embed" && ( +
  • + + {t("call")} +
  • + )} + {agoraEnabled && type == "card" && ( +
  • + {t("call")} +
  • + )} {canCopyEmail && (
  • {t("copy_email")} @@ -94,7 +112,7 @@ const Profile: FC = ({ uid, type = "embed", cid }) => { >
  • - {ct("more")} + {ct("more")}
  • diff --git a/src/hooks/useUserOperation.ts b/src/hooks/useUserOperation.ts index 38d0bed9..7d5dd34a 100644 --- a/src/hooks/useUserOperation.ts +++ b/src/hooks/useUserOperation.ts @@ -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(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;