refactor: voice data structure
This commit is contained in:
@@ -14,17 +14,24 @@ type Props = {
|
||||
|
||||
const RTCWidget = ({ id, context = "channel" }: Props) => {
|
||||
const { leave } = useVoice({ context, id });
|
||||
const { loginUser, joined } = useAppSelector(store => { return { loginUser: store.authData.user, joined: store.voice.joined }; });
|
||||
const { loginUser, voicingInfo, channelData, userData } = useAppSelector(store => {
|
||||
return {
|
||||
userData: store.users.byId,
|
||||
channelData: store.channels.byId,
|
||||
loginUser: store.authData.user,
|
||||
voicingInfo: store.voice.voicing
|
||||
};
|
||||
});
|
||||
if (!loginUser) return null;
|
||||
return (
|
||||
<div className='bg-gray-100 dark:bg-gray-900 flex flex-col p-2 rounded-3xl m-3 text-sm'>
|
||||
{joined &&
|
||||
{voicingInfo &&
|
||||
<div className="flex justify-between items-center border-b border-solid border-gray-100 dark:border-gray-800 pb-3 mb-2">
|
||||
<div className="flex items-center gap-1">
|
||||
<IconSignal />
|
||||
<div className="flex flex-col">
|
||||
<span className='text-green-800'>Voice Connected</span>
|
||||
<span className='text-gray-600 dark:text-gray-400 text-xs'>Channel / name</span>
|
||||
<span className='text-gray-600 dark:text-gray-400 text-xs'>{voicingInfo.context == "channel" ? "Channel" : "DM"} / {voicingInfo.context == "channel" ? channelData[voicingInfo.id].name : userData[voicingInfo.id].name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<IconHeadphone onClick={leave} role="button" className="fill-red-600" />
|
||||
|
||||
@@ -16,20 +16,20 @@ import { useAppSelector } from "../../../app/store";
|
||||
import { fromNowTime } from "../../../common/utils";
|
||||
|
||||
interface IProps {
|
||||
type?: "user" | "channel";
|
||||
type?: "dm" | "channel";
|
||||
id: number;
|
||||
mid: number;
|
||||
setDeleteChannelId: (param: number) => void;
|
||||
setInviteChannelId: (param: number) => void;
|
||||
}
|
||||
const Session: FC<IProps> = ({
|
||||
type = "user",
|
||||
type = "dm",
|
||||
id,
|
||||
mid,
|
||||
setDeleteChannelId,
|
||||
setInviteChannelId
|
||||
}) => {
|
||||
const navPath = type == "user" ? `/chat/dm/${id}` : `/chat/channel/${id}`;
|
||||
const navPath = type == "dm" ? `/chat/dm/${id}` : `/chat/channel/${id}`;
|
||||
// const { pathname } = useLocation();
|
||||
const isCurrentPath = useMatch(navPath);
|
||||
const navigate = useNavigate();
|
||||
@@ -46,7 +46,7 @@ const Session: FC<IProps> = ({
|
||||
return { size, type, name, url };
|
||||
});
|
||||
addStageFile(filesData);
|
||||
navigate(type == "user" ? `/chat/dm/${id}` : `/chat/channel/${id}`);
|
||||
navigate(type == "dm" ? `/chat/dm/${id}` : `/chat/channel/${id}`);
|
||||
}
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
@@ -62,24 +62,24 @@ const Session: FC<IProps> = ({
|
||||
mid: number;
|
||||
is_public: boolean;
|
||||
}>();
|
||||
const { messageData, userData, channelData, readIndex, loginUid, mids, muted, voiceInfo } = useAppSelector(
|
||||
const { messageData, userData, channelData, readIndex, loginUid, mids, muted, voiceList } = useAppSelector(
|
||||
(store) => {
|
||||
return {
|
||||
voiceInfo: store.voice.voicing,
|
||||
mids: type == "user" ? store.userMessage.byId[id] : store.channelMessage[id],
|
||||
voiceList: store.voice.list,
|
||||
mids: type == "dm" ? store.userMessage.byId[id] : store.channelMessage[id],
|
||||
loginUid: store.authData.user?.uid || 0,
|
||||
readIndex:
|
||||
type == "user" ? store.footprint.readUsers[id] : store.footprint.readChannels[id],
|
||||
type == "dm" ? store.footprint.readUsers[id] : store.footprint.readChannels[id],
|
||||
messageData: store.message,
|
||||
userData: store.users.byId,
|
||||
channelData: store.channels.byId,
|
||||
muted: type == "user" ? store.footprint.muteUsers[id] : store.footprint.muteChannels[id]
|
||||
muted: type == "dm" ? store.footprint.muteUsers[id] : store.footprint.muteChannels[id]
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const tmp = type == "user" ? userData[id] : channelData[id];
|
||||
const tmp = type == "dm" ? userData[id] : channelData[id];
|
||||
if (!tmp) return;
|
||||
if ("avatar" in tmp) {
|
||||
// user
|
||||
@@ -100,6 +100,7 @@ const Session: FC<IProps> = ({
|
||||
messageData,
|
||||
loginUid
|
||||
});
|
||||
const isVoicing = type == "channel" && voiceList.findIndex(item => item.id == id) > -1;
|
||||
return (
|
||||
<li className="session">
|
||||
<ContextMenu
|
||||
@@ -118,7 +119,7 @@ const Session: FC<IProps> = ({
|
||||
onContextMenu={handleContextMenuEvent}
|
||||
>
|
||||
<div className="flex shrink-0 relative">
|
||||
{type == "user" ? (
|
||||
{type == "dm" ? (
|
||||
<User avatarSize={40} compact interactive={false} uid={id} />
|
||||
) : (
|
||||
<Avatar
|
||||
@@ -130,7 +131,7 @@ const Session: FC<IProps> = ({
|
||||
src={icon}
|
||||
/>
|
||||
)}
|
||||
{type == "channel" && voiceInfo.id == id && <IconVoicing className="-top-0.5 -right-0.5 absolute w-[18px] h-[18px]" />}
|
||||
{isVoicing && <IconVoicing className="-top-0.5 -right-0.5 absolute w-[18px] h-[18px]" />}
|
||||
</div>
|
||||
<div className="w-full flex flex-col justify-between overflow-hidden">
|
||||
<div className="flex items-center justify-between ">
|
||||
|
||||
@@ -6,7 +6,7 @@ import DeleteChannelConfirmModal from "../../settingChannel/DeleteConfirmModal";
|
||||
import InviteModal from "../../../common/component/InviteModal";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
export interface ChatSession {
|
||||
type: "user" | "channel";
|
||||
type: "dm" | "channel";
|
||||
id: number;
|
||||
mid: number;
|
||||
unread: number;
|
||||
@@ -46,11 +46,11 @@ const SessionList: FC<Props> = ({ tempSession }) => {
|
||||
// console.log("adddd", id);
|
||||
const mids = userMessage[id];
|
||||
if (!mids || mids.length == 0) {
|
||||
return { unreads: 0, id, type: "user" };
|
||||
return { unreads: 0, id, type: "dm" };
|
||||
}
|
||||
// 先转换成数字,再排序
|
||||
const mid = [...mids].sort((a, b) => +a - +b).pop();
|
||||
return { type: "user", id, mid };
|
||||
return { type: "dm", id, mid };
|
||||
});
|
||||
const temps = [...(cSessions as ChatSession[]), ...(uSessions as ChatSession[])].sort((a, b) => {
|
||||
const { mid: aMid = 0 } = a;
|
||||
|
||||
@@ -44,7 +44,7 @@ function ChatPage() {
|
||||
mid: 0,
|
||||
unread: 0,
|
||||
id: +user_id,
|
||||
type: "user" as const
|
||||
type: "dm" as const
|
||||
}
|
||||
: undefined;
|
||||
// console.log("temp uid", tmpUid);
|
||||
|
||||
@@ -54,8 +54,8 @@ export default function ConfigAgora() {
|
||||
<div className="input">
|
||||
<Label htmlFor="project_id">Project ID</Label>
|
||||
<Input
|
||||
spellCheck={false}
|
||||
disabled={!enabled}
|
||||
// type={"number"}
|
||||
data-type="project_id"
|
||||
onChange={handleChange}
|
||||
value={project_id}
|
||||
@@ -66,6 +66,7 @@ export default function ConfigAgora() {
|
||||
<div className="input">
|
||||
<Label htmlFor="app_id">App ID</Label>
|
||||
<Input
|
||||
spellCheck={false}
|
||||
disabled={!enabled}
|
||||
data-type="app_id"
|
||||
onChange={handleChange}
|
||||
@@ -77,6 +78,7 @@ export default function ConfigAgora() {
|
||||
<div className="input">
|
||||
<Label htmlFor="app_certificate">APP Certificate</Label>
|
||||
<Input
|
||||
spellCheck={false}
|
||||
disabled={!enabled}
|
||||
data-type="app_certificate"
|
||||
onChange={handleChange}
|
||||
@@ -88,6 +90,7 @@ export default function ConfigAgora() {
|
||||
<div className="input">
|
||||
<Label htmlFor="rtm_key">RTM Key</Label>
|
||||
<Textarea
|
||||
spellCheck={false}
|
||||
disabled={!enabled}
|
||||
data-type="rtm_key"
|
||||
onChange={handleChange}
|
||||
@@ -99,6 +102,7 @@ export default function ConfigAgora() {
|
||||
<div className="input">
|
||||
<Label htmlFor="rtm_secret">RTM Secret</Label>
|
||||
<Textarea
|
||||
spellCheck={false}
|
||||
disabled={!enabled}
|
||||
data-type="rtm_secret"
|
||||
onChange={handleChange}
|
||||
|
||||
Reference in New Issue
Block a user