Skip to content

Commit 149f955

Browse files
committed
fix(mediasoupChannelId): 修复通知
1 parent 4ecf264 commit 149f955

File tree

9 files changed

+296
-250
lines changed

9 files changed

+296
-250
lines changed

.dockerignore

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
data
22
docker
33
node_modules
4-
.secret
5-
.env
4+
packages/client-web/.env
5+
packages/client-web/node_modules
6+
packages/server/node_modules
7+
packages/server/dist
8+
packages/server/files
9+
packages/server/.secret
10+
packages/server/.env

compose-dev.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ services:
99
ports:
1010
- 3306:3306
1111
volumes:
12-
- ./temp/db-data:/var/lib/mysql
12+
- ./data/db:/var/lib/mysql
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import { useChannelStore, useCommonStore } from "@/stores";
2+
import { ActionIcon, Divider, Radio, Slider, Switch, Tooltip } from "@mantine/core";
3+
import {
4+
IconBroadcast,
5+
IconMicrophone,
6+
IconMicrophoneOff,
7+
IconPlugX,
8+
IconSettings,
9+
IconVolume,
10+
IconVolumeOff,
11+
} from "@tabler/icons-react";
12+
import { Observer } from "mobx-react-lite";
13+
import { useCallback } from "react";
14+
import {
15+
ContextMenu,
16+
ContextMenuContent,
17+
ContextMenuItem,
18+
ContextMenuLabel,
19+
ContextMenuSeparator,
20+
ContextMenuTrigger,
21+
} from "@/components/ui/context-menu";
22+
import { useNavigate } from "react-router-dom";
23+
24+
export const ChannelBottomPannel: React.FC<React.HTMLAttributes<HTMLDivElement>> = (props) => {
25+
const navigate = useNavigate();
26+
const commonStore = useCommonStore();
27+
const channelStore = useChannelStore();
28+
29+
const handleAudioControlPanel = useCallback(() => {
30+
switch (channelStore.connectionState) {
31+
case "new":
32+
return <span className="">语音未连接</span>;
33+
case "connecting":
34+
return <span className="">语音连接中</span>;
35+
case "connected":
36+
return (
37+
<>
38+
<IconBroadcast size="18px" />
39+
<span className="ml-1.5">语音已连接</span>
40+
</>
41+
);
42+
43+
default:
44+
return null;
45+
}
46+
// eslint-disable-next-line react-hooks/exhaustive-deps
47+
}, []);
48+
49+
return (
50+
<>
51+
{/* 底部控制面板 */}
52+
<div {...props}>
53+
{/* 用户信息 */}
54+
<Observer>
55+
{() => (
56+
<div className="select-none bg-background/30 p-3">
57+
{channelStore.joinedChannel ? (
58+
<>
59+
<div className="mb-2 flex items-center justify-between">
60+
<div>
61+
<div className="flex items-end text-sm font-bold">
62+
<Observer>{() => handleAudioControlPanel()}</Observer>
63+
</div>
64+
<div className="mt-0.5 text-xs text-foreground/40">{channelStore.joinedChannel.name}</div>
65+
</div>
66+
<div>
67+
<Tooltip label="退出语音" position="right" color="dark">
68+
<ActionIcon
69+
onClick={async () => {
70+
await channelStore.exitRoom();
71+
}}
72+
>
73+
<IconPlugX size="26px" color="red" />
74+
</ActionIcon>
75+
</Tooltip>
76+
</div>
77+
</div>
78+
<Divider className="my-3" />
79+
</>
80+
) : null}
81+
82+
<div className="flex items-center justify-between">
83+
<div className="w-32 cursor-pointer">
84+
<div className="overflow-hidden text-ellipsis text-sm text-foreground/80">
85+
{channelStore.userWithChannels?.nickname}
86+
</div>
87+
<div className="overflow-hidden text-ellipsis text-xs text-foreground/40">
88+
#{channelStore.userWithChannels?.nicknameNo}
89+
</div>
90+
</div>
91+
<div className="flex">
92+
<MicrophoneButton />
93+
<VolumeButton />
94+
{/* 用户设置 */}
95+
<Tooltip label="用户设置" color="dark">
96+
<ActionIcon
97+
onClick={() => {
98+
commonStore.settingModalOpen = true;
99+
navigate("setting/audio");
100+
}}
101+
>
102+
<IconSettings size={18} />
103+
</ActionIcon>
104+
</Tooltip>
105+
</div>
106+
</div>
107+
</div>
108+
)}
109+
</Observer>
110+
</div>
111+
</>
112+
);
113+
};
114+
115+
// 麦克风按钮
116+
const MicrophoneButton: React.FC = () => {
117+
const channelStore = useChannelStore();
118+
119+
console.log(channelStore);
120+
121+
return (
122+
<Observer>
123+
{() => (
124+
<ContextMenu dir="ltr">
125+
<ContextMenuTrigger>
126+
<Tooltip label={channelStore.audioGain.microphone ? "麦克风静音" : "取消静音"} color="dark">
127+
<ActionIcon
128+
onClick={() => {
129+
const current = channelStore.audioGain.microphone;
130+
const history = channelStore.audioGain.historyMicrophone || 100;
131+
channelStore.setAudioGainItem("microphone", current ? 0 : history);
132+
channelStore.setAudioGainItem("historyMicrophone", current);
133+
}}
134+
>
135+
{channelStore.audioGain.microphone ? <IconMicrophone size={18} /> : <IconMicrophoneOff size={18} />}
136+
</ActionIcon>
137+
</Tooltip>
138+
</ContextMenuTrigger>
139+
<ContextMenuContent className="w-80 select-none">
140+
<ContextMenuLabel>音频输入设置</ContextMenuLabel>
141+
<ContextMenuSeparator />
142+
<Radio.Group
143+
value={channelStore.audioDevice.inputDeviceId}
144+
onChange={(v) => {
145+
channelStore.setInputMediaDevice(v);
146+
}}
147+
>
148+
{channelStore.mediaDeviceInfos
149+
.filter((it) => it.kind === "audioinput")
150+
.map((it) => (
151+
<ContextMenuItem key={it.deviceId} title={it.label}>
152+
<Radio
153+
classNames={{ label: "!cursor-pointer truncate w-64" }}
154+
label={it.label}
155+
value={it.deviceId}
156+
/>
157+
</ContextMenuItem>
158+
))}
159+
</Radio.Group>
160+
<ContextMenuSeparator />
161+
162+
<Switch
163+
checked={channelStore.audioNoiseSuppression}
164+
onChange={() => channelStore.toggleNoiseSuppression()}
165+
labelPosition="left"
166+
radius="sm"
167+
className="p-2"
168+
label="AI降噪"
169+
onLabel="已开启"
170+
offLabel="已关闭"
171+
/>
172+
173+
<ContextMenuLabel className="text-xs">输入音量</ContextMenuLabel>
174+
<div className="p-2 pt-0">
175+
<Slider
176+
max={300}
177+
value={channelStore.audioGain.microphone}
178+
onChange={(v) => channelStore.setAudioGainItem("microphone", v)}
179+
/>
180+
</div>
181+
</ContextMenuContent>
182+
</ContextMenu>
183+
)}
184+
</Observer>
185+
);
186+
};
187+
188+
// 麦克风按钮
189+
const VolumeButton: React.FC = () => {
190+
const channelStore = useChannelStore();
191+
192+
return (
193+
<Observer>
194+
{() => (
195+
<ContextMenu dir="ltr">
196+
<ContextMenuTrigger>
197+
<Tooltip label={channelStore.audioGain.volume ? "音量静音" : "取消静音"} color="dark">
198+
<ActionIcon
199+
onClick={() => {
200+
const current = channelStore.audioGain.volume;
201+
const history = channelStore.audioGain.historyVolume || 100;
202+
channelStore.setAudioGainItem("volume", current ? 0 : history);
203+
channelStore.setAudioGainItem("historyVolume", current);
204+
}}
205+
>
206+
{channelStore.audioGain.volume ? <IconVolume size={18} /> : <IconVolumeOff size={18} />}
207+
</ActionIcon>
208+
</Tooltip>
209+
</ContextMenuTrigger>
210+
<ContextMenuContent className="w-80 select-none">
211+
<ContextMenuLabel>音频输出设置</ContextMenuLabel>
212+
<ContextMenuSeparator />
213+
<Radio.Group
214+
value={channelStore.audioDevice.outputDeviceId}
215+
onChange={(v) => {
216+
console.log(v);
217+
channelStore.setAudioDevice("outputDeviceId", v);
218+
// channelStore.setInputMediaDevice(v);
219+
}}
220+
>
221+
{channelStore.mediaDeviceInfos
222+
.filter((it) => it.kind === "audiooutput")
223+
.map((it) => (
224+
<ContextMenuItem key={it.deviceId} title={it.label}>
225+
<Radio
226+
classNames={{ label: "!cursor-pointer truncate w-64" }}
227+
label={it.label}
228+
value={it.deviceId}
229+
/>
230+
</ContextMenuItem>
231+
))}
232+
</Radio.Group>
233+
<ContextMenuSeparator />
234+
235+
<ContextMenuLabel className="text-xs">输出音量</ContextMenuLabel>
236+
<div className="p-2 pt-0">
237+
<Slider
238+
max={300}
239+
value={channelStore.audioGain.volume}
240+
onChange={(v) => channelStore.setAudioGainItem("volume", v)}
241+
/>
242+
</div>
243+
</ContextMenuContent>
244+
</ContextMenu>
245+
)}
246+
</Observer>
247+
);
248+
};

packages/client-web/src/components/business/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from "./setting-modal";
88
export * from "./join-channel-modal";
99
export * from "./channel-users";
1010
export * from "./chat-pannel";
11+
export * from "./channel-bottom-pannel";
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { StoreStorage } from "@/lib/store-storage";
22
import { CommonStore } from "@/stores/CommonStore";
33
import React from "react";
4-
import { io } from "socket.io-client";
4+
import { ManagerOptions, SocketOptions, io } from "socket.io-client";
55
export * from "./apollo";
66

7-
export const socketClient = io({
8-
host: import.meta.env.DEV ? "http://localhost:3000" : undefined,
7+
const SOCKET_URL = import.meta.env.DEV ? "http://localhost:3000" : undefined;
8+
9+
const SOCKET_OPTIONS: Partial<ManagerOptions & SocketOptions> = {
910
autoConnect: false,
1011
auth(cb) {
1112
const token = StoreStorage.load(CommonStore, "sessionToken", "");
@@ -14,6 +15,11 @@ export const socketClient = io({
1415
token,
1516
});
1617
},
17-
});
18+
};
19+
20+
export const socketClient = (() => {
21+
if (SOCKET_URL) return io(SOCKET_URL, SOCKET_OPTIONS);
22+
return io(SOCKET_OPTIONS);
23+
})();
1824

1925
export const SocketClientContext = React.createContext(socketClient);

0 commit comments

Comments
 (0)