Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b964f14
feat: Add ability to choose resolution when streaming screen
Dadadah Apr 11, 2026
e73dea8
fix: Add styling for the video track to center it and limit height
Dadadah Apr 11, 2026
825b645
fix: Make screenshare not show up if paused
Dadadah Apr 11, 2026
cdc2a7b
feat: Remember stream settings choice, add settings ui for it
Dadadah Apr 11, 2026
fdfab5c
refactor: &
Dadadah Apr 11, 2026
a9fbd25
feat: Limit screen sharing options based on limits set in config
Dadadah Apr 12, 2026
3ff8dcf
fix: Squash desired quality if passed quality is not enabled
Dadadah Apr 12, 2026
a14ddb7
fix: Translate these strings
Dadadah Apr 12, 2026
bfe99fe
chore: Order imports in state
Dadadah Apr 12, 2026
8b6113d
refactor: Clean up some state code
Dadadah Apr 12, 2026
5e5374c
chore: Add documentation for these new functions
Dadadah Apr 12, 2026
ef6049a
fix: Add translation for modal name and import lingui correctly
Dadadah Apr 17, 2026
17d9784
refactor: Remove screensharequalities file and use the voice state
Dadadah Apr 18, 2026
81457c3
chore: sort imports
Dadadah Apr 18, 2026
9bc1328
fix: Use form2 for checkbox
Dadadah Apr 18, 2026
d9a748a
feat: Add new FloatingSelect in Form2 and use it in new modal
Dadadah Apr 18, 2026
f15e665
feat: Make the quality setting a button group
Dadadah Apr 18, 2026
6f61431
chore: order imports
Dadadah Apr 18, 2026
46e40be
fix: Add error view to new formbuttongroup
Dadadah Apr 18, 2026
79053e2
refactor: Replace `@` with a space in qualities
Dadadah Apr 18, 2026
fabad3f
fix: Don't show video settings if video is disabled
Dadadah Apr 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Server } from "stoat.js";
import { css } from "styled-system/css";

import { useClient, useClientLifecycle } from "@revolt/client";
import { CONFIGURATION } from "@revolt/common";
import { useUser } from "@revolt/markdown/users";
import { useModals } from "@revolt/modal";
import { ColouredText, Column, Text, iconSize } from "@revolt/ui";
Expand Down Expand Up @@ -205,7 +206,11 @@ const Config: SettingsConfiguration<{ server: Server }> = {
{
id: "voice",
icon: <MdMic {...iconSize(20)} />,
title: <Trans>Voice</Trans>,
title: CONFIGURATION.ENABLE_VIDEO ? (
<Trans>Voice & Video</Trans>
) : (
<Trans>Voice</Trans>
),
},
{
id: "appearance",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Trans } from "@lingui-solid/solid/macro";

import { useVoice } from "@revolt/rtc";
import { useState } from "@revolt/state";
import { ScreenShareQualityName } from "@revolt/state/stores/Voice";
import {
CategoryButton,
CategorySelectOption,
Checkbox,
Column,
Text,
} from "@revolt/ui";
import { Symbol } from "@revolt/ui/components/utils/Symbol";

export function ScreenShareOptions() {
const { voice } = useState();
const voiceContext = useVoice();

const qualities = voiceContext.getEnabledScreenShareQualities();

return (
<Column>
<Text class="title">
<Trans>Screen Share Settings</Trans>
</Text>
<CategoryButton.Group>
<CategoryButton.Select
icon={<Symbol>screen_share</Symbol>}
title={<Trans>Select screen share quality</Trans>}
options={
Object.fromEntries(
Object.keys(qualities).map((name) => [
name,
{
title: qualities[name as ScreenShareQualityName]!.fullName,
},
]),
) as { [key in ScreenShareQualityName]: CategorySelectOption }
}
value={voice.screenShareQuality}
onUpdate={(ns) => (voice.screenShareQuality = ns)}
/>
<CategoryButton
icon="blank"
action={<Checkbox checked={voice.screenShareQualityAsk} />}
onClick={() =>
(voice.screenShareQualityAsk = !voice.screenShareQualityAsk)
}
>
<Trans>Always Ask for Screen Share Quality</Trans>
</CategoryButton>
</CategoryButton.Group>
</Column>
);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Show } from "solid-js";

import { CONFIGURATION } from "@revolt/common";
import { Column } from "@revolt/ui";

import { ScreenShareOptions } from "./ScreenShareOptions";
import { VoiceInputOptions } from "./VoiceInputOptions";
import { VoiceProcessingOptions } from "./VoiceProcessingOptions";

/**
* Configure voice options
*/
Expand All @@ -11,6 +14,9 @@ export function VoiceSettings() {
<Column gap="lg">
<VoiceInputOptions />
<VoiceProcessingOptions />
<Show when={CONFIGURATION.ENABLE_VIDEO}>
<ScreenShareOptions />
</Show>
</Column>
);
}
4 changes: 3 additions & 1 deletion packages/client/components/modal/modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { PolicyChangeModal } from "./modals/PolicyChange";
import { RenameSessionModal } from "./modals/RenameSession";
import { ReportContentModal } from "./modals/ReportContent";
import { ResetBotTokenModal } from "./modals/ResetBotToken";
import { ScreenShareSettingsModal } from "./modals/ScreenShareSettings";
import { ServerIdentityModal } from "./modals/ServerIdentity";
import { ServerInfoModal } from "./modals/ServerInfo";
import { SettingsModal } from "./modals/Settings";
Expand Down Expand Up @@ -183,7 +184,8 @@ export function RenderModal(props: ActiveModal & { onClose: () => void }) {
return <ResetBotTokenModal {...modalProps} />;
case "edit_category":
return <EditCategoryModal {...modalProps} />;

case "screen_share_settings":
return <ScreenShareSettingsModal {...modalProps} />;
default:
console.error(
"Failed to create modal for",
Expand Down
84 changes: 84 additions & 0 deletions packages/client/components/modal/modals/ScreenShareSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Trans, useLingui } from "@lingui-solid/solid/macro";
import { createFormControl, createFormGroup } from "solid-forms";

import { useState } from "@revolt/state";
import { ScreenShareQualityName } from "@revolt/state/stores/Voice";
import { Column, Dialog, DialogProps, Form2 } from "@revolt/ui";
import { VideoTrack } from "solid-livekit-components";

import { Modals } from "../types";

export function ScreenShareSettingsModal(
props: DialogProps & Modals & { type: "screen_share_settings" },
) {
const { voice } = useState();
const { t } = useLingui();

const group = createFormGroup({
qualityName: createFormControl<ScreenShareQualityName>(
voice.screenShareQuality || "low",
{ required: true },
),
dontAsk: createFormControl(false),
});

async function onSubmit() {
if (group.controls.dontAsk.value) {
voice.screenShareQuality = group.controls.qualityName.value;
voice.screenShareQualityAsk = false;
}

props.callback(group.controls.qualityName.value);
props.onClose();
}

const submit = Form2.useSubmitHandler(group, onSubmit);

return (
<Dialog
minWidth={420}
show={props.show}
onClose={() => {
props.onCancel();
props.onClose();
}}
title={t`Screen Share Settings`}
actions={[
{ text: <Trans>Cancel</Trans> },
{
text: <Trans>Go</Trans>,
onClick: () => {
onSubmit();
return false;
},
},
]}
>
<VideoTrack
trackRef={props.trackReference}
style={{
padding: "var(--gap-md)",
"border-radius": "var(--borderRadius-lg)",
"max-height": "400px",
"justify-self": "center",
}}
/>
<form onSubmit={submit}>
<Column>
<Form2.ButtonGroup
control={group.controls.qualityName}
buttonDefinitions={props.qualities.map((quality) => {
return {
children: quality.fullName,
value: quality.name,
};
})}
/>
<Form2.Checkbox control={group.controls.dontAsk}>
<Trans>Don't ask me again</Trans>
</Form2.Checkbox>
</Column>
</form>
</Dialog>
);
}
9 changes: 9 additions & 0 deletions packages/client/components/modal/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TrackReference } from "solid-livekit-components";
import {
API,
Bot,
Expand All @@ -22,6 +23,7 @@ import { ProtocolV1 } from "stoat.js/lib/events/v1";

import type { SettingsConfigurations } from "@revolt/app";
import { CategoryData } from "@revolt/app/menus/CategoryContextMenu";
import { ScreenShareQualityName } from "@revolt/state/stores/Voice";

export type Modals =
| {
Expand Down Expand Up @@ -314,4 +316,11 @@ export type Modals =
type: "edit_category";
server: Server;
category: CategoryData;
}
| {
type: "screen_share_settings";
trackReference: TrackReference;
qualities: { name: string; fullName: string }[];
callback: (qualityName: ScreenShareQualityName) => void;
onCancel: () => void;
};
Loading
Loading