Skip to content

Commit

Permalink
change call volume
Browse files Browse the repository at this point in the history
  • Loading branch information
SupertigerDev committed Oct 14, 2024
1 parent 3c26125 commit 0b19e88
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 5 deletions.
7 changes: 5 additions & 2 deletions src/chat-api/store/useVoiceUsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type VoiceUser = RawVoice & {
videoStream?: MediaStream;
vad?: VADInstance;
voiceActivity: boolean;
audio?: HTMLAudioElement
};

// voiceUsers[channelId][userId] = VoiceUser
Expand Down Expand Up @@ -185,7 +186,7 @@ const getVoiceUsers = (channelId: string): VoiceUser[] => {
};

const getVoiceUser = (channelId: string, userId: string) => {
return voiceUsers[channelId][userId];
return voiceUsers[channelId]?.[userId];
};

export async function createPeer(voiceUser: VoiceUser | RawVoice) {
Expand Down Expand Up @@ -315,9 +316,10 @@ const onStream = (voiceUser: VoiceUser | RawVoice, stream: MediaStream) => {
stream.onremovetrack = null;
};

let mic: HTMLAudioElement | undefined = undefined;
if (streamType === "audioStream") {
setVAD(stream, voiceUser);
const mic = new Audio();
mic = new Audio();
const deviceId = getStorageString(StorageKeys.outputDeviceId, undefined);
if (deviceId) {
mic.setSinkId(JSON.parse(deviceId));
Expand All @@ -327,6 +329,7 @@ const onStream = (voiceUser: VoiceUser | RawVoice, stream: MediaStream) => {
}
setVoiceUsers(voiceUser.channelId, voiceUser.userId, {
[streamType]: stream,
audio: mic,
});
};

Expand Down
19 changes: 19 additions & 0 deletions src/components/main-pane-header/MainPaneHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
hasBit,
} from "@/chat-api/Bitwise";
import { WebcamModal } from "./WebcamModal";
import MemberContextMenu from "../member-context-menu/MemberContextMenu";

export default function MainPaneHeader() {
const {
Expand Down Expand Up @@ -444,6 +445,11 @@ function VoiceParticipantItem(props: {
onClick: () => void;
}) {
const { voiceUsers } = useStore();
const params = useParams<{ serverId?: string; channelId?: string }>();
const [contextPosition, setContextPosition] = createSignal<null | {
x: number;
y: number;
}>(null);

const isMuted = () => {
return !voiceUsers.micEnabled(
Expand All @@ -467,16 +473,29 @@ function VoiceParticipantItem(props: {
event.preventDefault();
}
};
const onContextMenu = (event: MouseEvent) => {
event.preventDefault();
setContextPosition({ x: event.clientX, y: event.clientY });
};

return (
<CustomLink
onContextMenu={onContextMenu}
onClick={onClick}
href={RouterEndpoints.PROFILE(user().id)}
class={classNames(
styles.voiceParticipantItem,
conditionalClass(props.selected, styles.selected)
)}
>
<MemberContextMenu
position={contextPosition()}
serverId={params.serverId}
userId={user().id}
onClose={() => {
setContextPosition(null);
}}
/>
<Avatar
user={user()}
size={props.size === "small" ? 40 : 60}
Expand Down
60 changes: 59 additions & 1 deletion src/components/member-context-menu/MemberContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { copyToClipboard } from "@/common/clipboard";
import ContextMenu, {
ContextMenuProps,
} from "@/components/ui/context-menu/ContextMenu";
import { createEffect, createSignal, For, Show } from "solid-js";
import { createEffect, createSignal, For, on, Show } from "solid-js";
import useStore from "@/chat-api/store/useStore";
import LegacyModal from "@/components/ui/legacy-modal/LegacyModal";
import { ServerRole } from "@/chat-api/store/useServerRoles";
Expand All @@ -29,6 +29,7 @@ import { Trans } from "@mbarzda/solid-i18next";
import Input from "../ui/input/Input";
import { Notice } from "../ui/Notice/Notice";
import Text from "../ui/Text";
import Avatar from "../ui/Avatar";
type Props = Omit<ContextMenuProps, "items"> & {
serverId?: string;
userId: string;
Expand Down Expand Up @@ -153,6 +154,7 @@ export default function MemberContextMenu(props: Props) {
return (
<>
<ContextMenu
header={<Header userId={props.userId} />}
{...props}
items={[
{
Expand All @@ -178,6 +180,62 @@ export default function MemberContextMenu(props: Props) {
);
}

function Header(props: { userId: string }) {
const [voiceVolume, setVoiceVolume] = createSignal(1);
const store = useStore();
const user = () => store.users.get(props.userId);

const voiceUser = () =>
store.voiceUsers.getVoiceUser(
store.voiceUsers.currentVoiceChannelId()!,
props.userId
);
const audio = () => voiceUser()?.audio;

createEffect(
on(audio, () => {
const audio = voiceUser()?.audio;
if (!audio) return;
console.log(audio.volume);
setVoiceVolume(audio.volume);
})
);

const isMe = () => user()?.id === store.account.user()?.id;

const onVolumeChange = (e: any) => {
setVoiceVolume(Number(e.currentTarget?.value!));
const audio = voiceUser()?.audio;
if (!audio) return;
audio.volume = Number(e.currentTarget?.value!);
};

return (
<Show when={user()}>
<div class={styles.header}>
<div class={styles.headerDetails}>
<Avatar user={user()} size={24} />
<div class={styles.username}>{user()!.username}</div>
</div>
</div>

<Show when={audio() && !isMe()}>
<div class={styles.voiceVolume}>
<div class={styles.label}>Call Volume</div>
<input
type="range"
min={0}
max={1}
step={0.01}
value={voiceVolume()}
onInput={onVolumeChange}
/>
</div>
</Show>
</Show>
);
}

function KickModal(props: { member: ServerMember; close: () => void }) {
const [requestSent, setRequestSent] = createSignal(false);
const onKickClick = async () => {
Expand Down
35 changes: 35 additions & 0 deletions src/components/member-context-menu/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,38 @@
margin-top: 10px;
}
}

.header {
display: flex;
flex-direction: column;
}
.headerDetails {
position: relative;
display: flex;
align-items: center;
gap: 6px;
height: 34px;
margin-left: 6px;
font-size: 14px;

.username {
position: absolute;
overflow: hidden;
text-overflow: ellipsis;
font-weight: bold;
white-space: nowrap;
left: 30px;
right: 0;
}
}

.voiceVolume {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 4px;
.label {
font-size: 14px;
margin-left: 4px;
}
}
2 changes: 1 addition & 1 deletion src/components/message-pane/message-item/MessageItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ const FileEmbed = (props: {
};
}) => {
const { createPortal } = useCustomPortal();
const isImage = () => props.file?.mime.startsWith("image/");
const isImage = () => props.file?.mime?.startsWith("image/");

const previewClick = () => {
createPortal((close) => (
Expand Down
4 changes: 3 additions & 1 deletion src/components/ui/context-menu/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ export interface ContextMenuProps {
x: number;
y: number;
} | null;
header?: JSXElement;
}

export default function ContextMenu(props: ContextMenuProps) {
let [contextMenuEl, setContextMenuEl] = createSignal<HTMLDivElement | null>(
const [contextMenuEl, setContextMenuEl] = createSignal<HTMLDivElement | null>(
null
);
const [pos, setPos] = createSignal({ top: "0", left: "0" });
Expand Down Expand Up @@ -174,6 +175,7 @@ export default function ContextMenu(props: ContextMenuProps) {
style={isMobileWidth() ? {} : pos()}
>
<div class={styles.contextMenuInner}>
{props.header}
<For each={items}>
{(item, i) => (
<Show when={item.show !== false}>
Expand Down

0 comments on commit 0b19e88

Please sign in to comment.