Remove voice

This commit is contained in:
Anonymous
2024-08-28 10:32:00 +08:00
parent 423fbb6546
commit 2974dda142
15 changed files with 8 additions and 1419 deletions

View File

@@ -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>

View File

@@ -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}>

View File

@@ -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>
);
});

View File

@@ -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}

View File

@@ -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>

View File

@@ -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);
}
}