mirror of
https://github.com/stoatchat/for-legacy-web.git
synced 2026-03-10 10:35:27 +00:00
Remove voice
This commit is contained in:
@@ -26,7 +26,6 @@ import { PageHeader } from "../../components/ui/Header";
|
||||
import { useClient } from "../../controllers/client/ClientController";
|
||||
import ChannelHeader from "./ChannelHeader";
|
||||
import { MessageArea } from "./messaging/MessageArea";
|
||||
import VoiceHeader from "./voice/VoiceHeader";
|
||||
|
||||
const ChannelMain = styled.div.attrs({ "data-component": "channel" })`
|
||||
flex-grow: 1;
|
||||
@@ -126,9 +125,6 @@ export const Channel = observer(
|
||||
}
|
||||
|
||||
const channel = client.channels.get(id)!;
|
||||
if (channel.channel_type === "VoiceChannel") {
|
||||
return <VoiceChannel channel={channel} />;
|
||||
}
|
||||
|
||||
return <TextChannel channel={channel} />;
|
||||
},
|
||||
@@ -191,7 +187,6 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
|
||||
<ChannelMain>
|
||||
<ErrorBoundary section="renderer">
|
||||
<ChannelContent>
|
||||
<VoiceHeader id={channel._id} />
|
||||
<NewMessages channel={channel} last_id={lastId} />
|
||||
<MessageArea channel={channel} last_id={lastId} />
|
||||
<TypingIndicator channel={channel} />
|
||||
@@ -208,15 +203,6 @@ const TextChannel = observer(({ channel }: { channel: ChannelI }) => {
|
||||
);
|
||||
});
|
||||
|
||||
function VoiceChannel({ channel }: { channel: ChannelI }) {
|
||||
return (
|
||||
<>
|
||||
<ChannelHeader channel={channel} />
|
||||
<VoiceHeader id={channel._id} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ChannelPlaceholder() {
|
||||
return (
|
||||
<PlaceholderBase>
|
||||
|
||||
@@ -16,7 +16,6 @@ import { IconButton } from "@revoltchat/ui";
|
||||
import { chainedDefer, defer } from "../../../lib/defer";
|
||||
import { internalEmit } from "../../../lib/eventEmitter";
|
||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||
import { voiceState, VoiceStatus } from "../../../lib/vortex/VoiceState";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
import { SIDEBAR_MEMBERS } from "../../../mobx/stores/Layout";
|
||||
@@ -132,7 +131,6 @@ export default function HeaderActions({ channel }: ChannelHeaderProps) {
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
<VoiceActions channel={channel} />
|
||||
{(channel.channel_type === "Group" ||
|
||||
channel.channel_type === "TextChannel") && (
|
||||
<IconButton onClick={openMembers}>
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
import {
|
||||
BarChartAlt2,
|
||||
Microphone,
|
||||
MicrophoneOff,
|
||||
PhoneOff,
|
||||
VolumeFull,
|
||||
VolumeMute,
|
||||
} from "@styled-icons/boxicons-solid";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import styled from "styled-components/macro";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
import { useMemo } from "preact/hooks";
|
||||
|
||||
import { Button } from "@revoltchat/ui";
|
||||
|
||||
import { voiceState, VoiceStatus } from "../../../lib/vortex/VoiceState";
|
||||
|
||||
import Tooltip from "../../../components/common/Tooltip";
|
||||
import UserIcon from "../../../components/common/user/UserIcon";
|
||||
import { useClient } from "../../../controllers/client/ClientController";
|
||||
import { modalController } from "../../../controllers/modals/ModalController";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
}
|
||||
|
||||
const VoiceBase = styled.div`
|
||||
margin-top: 48px;
|
||||
padding: 20px;
|
||||
background: var(--secondary-background);
|
||||
flex-grow: 1;
|
||||
|
||||
.status {
|
||||
flex: 1 0;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
user-select: none;
|
||||
gap: 6px;
|
||||
|
||||
color: var(--success);
|
||||
border-radius: var(--border-radius);
|
||||
background: var(--primary-background);
|
||||
|
||||
svg {
|
||||
cursor: help;
|
||||
}
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.participants {
|
||||
margin: 40px 20px;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
gap: 16px;
|
||||
|
||||
div:hover img {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.disconnected {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default observer(({ id }: Props) => {
|
||||
if (voiceState.roomId !== id) return null;
|
||||
|
||||
const client = useClient();
|
||||
const self = client.users.get(client.user!._id);
|
||||
|
||||
const keys = Array.from(voiceState.participants.keys());
|
||||
const users = useMemo(() => {
|
||||
return keys.map((key) => client.users.get(key));
|
||||
// eslint-disable-next-line
|
||||
}, [keys]);
|
||||
|
||||
return (
|
||||
<VoiceBase>
|
||||
<div className="participants">
|
||||
{users && users.length !== 0
|
||||
? users.map((user, index) => {
|
||||
const user_id = keys![index];
|
||||
return (
|
||||
<div key={user_id}>
|
||||
<UserIcon
|
||||
size={80}
|
||||
target={user}
|
||||
status={false}
|
||||
voice={
|
||||
client.user?._id === user_id &&
|
||||
voiceState.isDeaf()
|
||||
? "deaf"
|
||||
: voiceState.participants!.get(
|
||||
user_id,
|
||||
)?.audio
|
||||
? undefined
|
||||
: "muted"
|
||||
}
|
||||
onClick={() =>
|
||||
modalController.push({
|
||||
type: "user_profile",
|
||||
user_id,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
: self !== undefined && (
|
||||
<div key={self._id} className="disconnected">
|
||||
<UserIcon
|
||||
size={80}
|
||||
target={self}
|
||||
status={false}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="status">
|
||||
<BarChartAlt2 size={16} />
|
||||
{voiceState.status === VoiceStatus.CONNECTED && (
|
||||
<Text id="app.main.channel.voice.connected" />
|
||||
)}
|
||||
</div>
|
||||
<div className="actions">
|
||||
<Tooltip content={"Leave call"} placement={"top"}>
|
||||
<Button palette="error" onClick={voiceState.disconnect}>
|
||||
<PhoneOff width={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{voiceState.isProducing("audio") ? (
|
||||
<Tooltip content={"Mute microphone"} placement={"top"}>
|
||||
<Button
|
||||
onClick={() => voiceState.stopProducing("audio")}>
|
||||
<Microphone width={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Tooltip content={"Unmute microphone"} placement={"top"}>
|
||||
<Button
|
||||
onClick={() => voiceState.startProducing("audio")}>
|
||||
<MicrophoneOff width={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{voiceState.isDeaf() ? (
|
||||
<Tooltip content={"Undeafen"} placement={"top"}>
|
||||
<Button onClick={() => voiceState.stopDeafen()}>
|
||||
<VolumeMute width={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Tooltip content={"Deafen"} placement={"top"}>
|
||||
<Button onClick={() => voiceState.startDeafen()}>
|
||||
<VolumeFull width={20} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</VoiceBase>
|
||||
);
|
||||
});
|
||||
@@ -12,7 +12,6 @@ import { Text } from "preact-i18n";
|
||||
import { IconButton } from "@revoltchat/ui";
|
||||
|
||||
import { stopPropagation } from "../../lib/stopPropagation";
|
||||
import { voiceState } from "../../lib/vortex/VoiceState";
|
||||
|
||||
import UserIcon from "../../components/common/user/UserIcon";
|
||||
import UserStatus from "../../components/common/user/UserStatus";
|
||||
@@ -32,20 +31,6 @@ export const Friend = observer(({ user }: Props) => {
|
||||
subtext = <UserStatus user={user} />;
|
||||
actions.push(
|
||||
<>
|
||||
<IconButton
|
||||
shape="circle"
|
||||
className={classNames(styles.button, styles.success)}
|
||||
onClick={(ev) =>
|
||||
stopPropagation(
|
||||
ev,
|
||||
user
|
||||
.openDM()
|
||||
.then(voiceState.connect)
|
||||
.then((x) => history.push(`/channel/${x._id}`)),
|
||||
)
|
||||
}>
|
||||
<PhoneCall size={20} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
shape="circle"
|
||||
className={styles.button}
|
||||
|
||||
@@ -48,7 +48,6 @@ import { APP_VERSION } from "../../version";
|
||||
import { GenericSettings } from "./GenericSettings";
|
||||
import { Account } from "./panes/Account";
|
||||
import { Appearance } from "./panes/Appearance";
|
||||
import { Audio } from "./panes/Audio";
|
||||
import { ExperimentsPage } from "./panes/Experiments";
|
||||
import { Feedback } from "./panes/Feedback";
|
||||
import { Languages } from "./panes/Languages";
|
||||
@@ -155,14 +154,6 @@ export default observer(() => {
|
||||
icon: <CheckShield size={20} />,
|
||||
title: <Text id="app.settings.pages.sessions.title" />,
|
||||
},
|
||||
{
|
||||
category: (
|
||||
<Text id="app.settings.categories.client_settings" />
|
||||
),
|
||||
id: "audio",
|
||||
icon: <Speaker size={20} />,
|
||||
title: <Text id="app.settings.pages.audio.title" />,
|
||||
},
|
||||
{
|
||||
id: "appearance",
|
||||
icon: <Palette size={20} />,
|
||||
@@ -229,9 +220,6 @@ export default observer(() => {
|
||||
<Route path="/settings/plugins">
|
||||
<PluginsPage />
|
||||
</Route>
|
||||
<Route path="/settings/audio">
|
||||
<Audio />
|
||||
</Route>
|
||||
<Route path="/settings/notifications">
|
||||
<Notifications />
|
||||
</Route>
|
||||
|
||||
@@ -1,272 +0,0 @@
|
||||
import styles from "./Panes.module.scss";
|
||||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import { Button, Category, ComboBox, Tip } from "@revoltchat/ui";
|
||||
|
||||
import { stopPropagation } from "../../../lib/stopPropagation";
|
||||
import { voiceState } from "../../../lib/vortex/VoiceState";
|
||||
|
||||
import { I18nError } from "../../../context/Locale";
|
||||
|
||||
import opusSVG from "../assets/opus_logo.svg";
|
||||
|
||||
{
|
||||
/*import OpusSVG from "../assets/opus_logo.svg";*/
|
||||
}
|
||||
|
||||
const constraints = { audio: true };
|
||||
|
||||
// TODO: do not rewrite this code until voice is rewritten!
|
||||
|
||||
export function Audio() {
|
||||
const [mediaStream, setMediaStream] = useState<MediaStream | undefined>(
|
||||
undefined,
|
||||
);
|
||||
const [mediaDevices, setMediaDevices] = useState<
|
||||
MediaDeviceInfo[] | undefined
|
||||
>(undefined);
|
||||
const [permission, setPermission] = useState<PermissionState | undefined>(
|
||||
undefined,
|
||||
);
|
||||
const [error, setError] = useState<DOMException | undefined>(undefined);
|
||||
|
||||
const askOrGetPermission = async () => {
|
||||
try {
|
||||
const result = await navigator.mediaDevices.getUserMedia(
|
||||
constraints,
|
||||
);
|
||||
|
||||
setMediaStream(result);
|
||||
} catch (err) {
|
||||
// The user has blocked the permission
|
||||
setError(err as DOMException);
|
||||
}
|
||||
|
||||
try {
|
||||
const { state } = await navigator.permissions.query({
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore: very few browsers accept this `PermissionName`, but it has been drafted in https://www.w3.org/TR/permissions/#powerful-features-registry
|
||||
name: "microphone",
|
||||
});
|
||||
|
||||
setPermission(state);
|
||||
} catch (err) {
|
||||
// the browser might not support `query` functionnality or `PermissionName`
|
||||
// nothing to do
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (mediaStream) {
|
||||
// close microphone access on unmount
|
||||
mediaStream.getTracks().forEach((track) => {
|
||||
track.stop();
|
||||
});
|
||||
}
|
||||
};
|
||||
}, [mediaStream]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mediaStream) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.mediaDevices.enumerateDevices().then(
|
||||
(devices) => {
|
||||
setMediaDevices(devices);
|
||||
},
|
||||
(err) => {
|
||||
setError(err as DOMException);
|
||||
},
|
||||
);
|
||||
}, [mediaStream]);
|
||||
|
||||
const handleAskForPermission = (
|
||||
ev: JSX.TargetedMouseEvent<HTMLElement>,
|
||||
) => {
|
||||
stopPropagation(ev);
|
||||
setError(undefined);
|
||||
askOrGetPermission();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.audio}>
|
||||
<Tip palette="warning">
|
||||
<span>
|
||||
We are currently{" "}
|
||||
<a
|
||||
style={{ color: "inherit", fontWeight: "600" }}
|
||||
href="https://github.com/revoltchat/frontend/issues/14"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
rebuilding the client
|
||||
</a>{" "}
|
||||
and{" "}
|
||||
<a
|
||||
style={{ color: "inherit", fontWeight: "600" }}
|
||||
href="https://trello.com/c/Ay6KdiOV/1-voice-overhaul-and-video-calling"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
the voice server
|
||||
</a>{" "}
|
||||
from scratch.
|
||||
<br />
|
||||
<br />
|
||||
The old voice should work in most cases, but it may
|
||||
inexplicably not connect in some scenarios and / or
|
||||
exhibit weird behaviour.
|
||||
</span>
|
||||
</Tip>
|
||||
|
||||
{!permission && (
|
||||
<Tip palette="error">
|
||||
<Text id="app.settings.pages.audio.tip_grant_permission" />
|
||||
</Tip>
|
||||
)}
|
||||
|
||||
{error && permission === "prompt" && (
|
||||
<Tip palette="error">
|
||||
<Text id="app.settings.pages.audio.tip_retry" />
|
||||
<a onClick={handleAskForPermission}>
|
||||
<Text id="app.settings.pages.audio.button_retry" />
|
||||
</a>
|
||||
.
|
||||
</Tip>
|
||||
)}
|
||||
|
||||
<div className={styles.audioRow}>
|
||||
<div className={styles.select}>
|
||||
<h3>
|
||||
<Text id="app.settings.pages.audio.input_device" />
|
||||
</h3>
|
||||
<div className={styles.audioBox}>
|
||||
<ComboBox
|
||||
value={
|
||||
window.localStorage.getItem(
|
||||
"audioInputDevice",
|
||||
) ?? 0
|
||||
}
|
||||
onChange={(e) =>
|
||||
changeAudioDevice(
|
||||
e.currentTarget.value,
|
||||
"input",
|
||||
)
|
||||
}>
|
||||
{mediaDevices
|
||||
?.filter(
|
||||
(device) =>
|
||||
device.kind === "audioinput",
|
||||
)
|
||||
.map((device) => {
|
||||
return (
|
||||
<option
|
||||
value={device.deviceId}
|
||||
key={device.deviceId}>
|
||||
{device.label || (
|
||||
<Text id="app.settings.pages.audio.device_label_NA" />
|
||||
)}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</ComboBox>
|
||||
{/*TOFIX: add logic to sound notches*/}
|
||||
{/*<div className={styles.notches}>
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>*/}
|
||||
{!permission && (
|
||||
<Button
|
||||
compact
|
||||
onClick={(e: any) =>
|
||||
handleAskForPermission(e)
|
||||
}
|
||||
palette="error">
|
||||
<Text id="app.settings.pages.audio.button_grant" />
|
||||
</Button>
|
||||
)}
|
||||
{error && error.name === "NotAllowedError" && (
|
||||
<Category>
|
||||
<I18nError error="AudioPermissionBlock" />
|
||||
</Category>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.select}>
|
||||
<h3>
|
||||
<Text id="app.settings.pages.audio.output_device" />
|
||||
</h3>
|
||||
{/* TOFIX: create audio output combobox*/}
|
||||
<ComboBox
|
||||
value={
|
||||
window.localStorage.getItem(
|
||||
"audioOutputDevice",
|
||||
) ?? 0
|
||||
}
|
||||
onChange={(e) =>
|
||||
changeAudioDevice(
|
||||
e.currentTarget.value,
|
||||
"output",
|
||||
)
|
||||
}>
|
||||
{mediaDevices
|
||||
?.filter(
|
||||
(device) => device.kind === "audiooutput",
|
||||
)
|
||||
.map((device) => {
|
||||
return (
|
||||
<option
|
||||
value={device.deviceId}
|
||||
key={device.deviceId}>
|
||||
{device.label || (
|
||||
<Text id="app.settings.pages.audio.device_label_NA" />
|
||||
)}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</ComboBox>
|
||||
{/*<div className={styles.notches}>
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div className={styles.opus}>
|
||||
<img height="20" src={opusSVG} draggable={false} />
|
||||
Audio codec powered by Opus
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function changeAudioDevice(deviceId: string, deviceType: string) {
|
||||
if (deviceType === "input") {
|
||||
window.localStorage.setItem("audioInputDevice", deviceId);
|
||||
if (voiceState.isProducing("audio")) {
|
||||
voiceState.stopProducing("audio");
|
||||
voiceState.startProducing("audio");
|
||||
}
|
||||
} else if (deviceType === "output") {
|
||||
window.localStorage.setItem("audioOutputDevice", deviceId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user