@@ -20,7 +20,7 @@ import {
20
20
useState
21
21
} from "@vencord/types/webpack/common" ;
22
22
import type { Dispatch , SetStateAction } from "react" ;
23
- import { patchAudioWithDevice } from "renderer/patches/screenShareAudio " ;
23
+ import { patchDisplayMedia } from "renderer/patches/screenSharePatch " ;
24
24
import { addPatch } from "renderer/patches/shared" ;
25
25
import { isLinux , isWindows } from "renderer/utils" ;
26
26
@@ -42,6 +42,7 @@ interface StreamSettings {
42
42
43
43
export interface StreamPick extends StreamSettings {
44
44
id : string ;
45
+ cameraId ?: string ;
45
46
}
46
47
47
48
interface Source {
@@ -50,6 +51,11 @@ interface Source {
50
51
url : string ;
51
52
}
52
53
54
+ interface Camera {
55
+ id : string ;
56
+ name : string ;
57
+ }
58
+
53
59
let currentSettings : StreamSettings | null = null ;
54
60
55
61
addPatch ( {
@@ -96,6 +102,7 @@ if (isLinux) {
96
102
97
103
export function openScreenSharePicker ( screens : Source [ ] , skipPicker : boolean ) {
98
104
let didSubmit = false ;
105
+
99
106
return new Promise < StreamPick > ( ( resolve , reject ) => {
100
107
const key = openModal (
101
108
props => (
@@ -105,6 +112,12 @@ export function openScreenSharePicker(screens: Source[], skipPicker: boolean) {
105
112
submit = { async v => {
106
113
didSubmit = true ;
107
114
115
+ patchDisplayMedia ( {
116
+ audioId : v . audioDevice ,
117
+ venmic : ! ! v . audioSource && v . audioSource !== "None" ,
118
+ videoId : v . cameraId
119
+ } ) ;
120
+
108
121
if ( ! v . audioDevice && v . audioSource && v . audioSource !== "None" ) {
109
122
if ( v . audioSource === "Entire System" ) {
110
123
await VesktopNative . virtmic . startSystem ( ) ;
@@ -113,8 +126,6 @@ export function openScreenSharePicker(screens: Source[], skipPicker: boolean) {
113
126
}
114
127
}
115
128
116
- if ( v . audioDevice ) patchAudioWithDevice ( v . audioDevice ) ;
117
-
118
129
resolve ( v ) ;
119
130
} }
120
131
close = { ( ) => {
@@ -134,12 +145,26 @@ export function openScreenSharePicker(screens: Source[], skipPicker: boolean) {
134
145
} ) ;
135
146
}
136
147
137
- function ScreenPicker ( { screens, chooseScreen } : { screens : Source [ ] ; chooseScreen : ( id : string ) => void } ) {
148
+ function ScreenPicker ( {
149
+ screens,
150
+ chooseScreen,
151
+ isDisabled = false
152
+ } : {
153
+ screens : Source [ ] ;
154
+ chooseScreen : ( id : string ) => void ;
155
+ isDisabled ?: boolean ;
156
+ } ) {
138
157
return (
139
158
< div className = "vcd-screen-picker-grid" >
140
159
{ screens . map ( ( { id, name, url } ) => (
141
160
< label key = { id } >
142
- < input type = "radio" name = "screen" value = { id } onChange = { ( ) => chooseScreen ( id ) } />
161
+ < input
162
+ type = "radio"
163
+ name = "screen"
164
+ value = { id }
165
+ onChange = { ( ) => chooseScreen ( id ) }
166
+ disabled = { isDisabled }
167
+ />
143
168
144
169
< img src = { url } alt = "" />
145
170
< Text variant = "text-sm/normal" > { name } </ Text >
@@ -149,6 +174,37 @@ function ScreenPicker({ screens, chooseScreen }: { screens: Source[]; chooseScre
149
174
) ;
150
175
}
151
176
177
+ function CameraPicker ( {
178
+ camera,
179
+ chooseCamera
180
+ } : {
181
+ camera : string | undefined ;
182
+ chooseCamera : ( id : string | undefined ) => void ;
183
+ } ) {
184
+ const [ cameras ] = useAwaiter (
185
+ ( ) =>
186
+ navigator . mediaDevices
187
+ . enumerateDevices ( )
188
+ . then ( res =>
189
+ res
190
+ . filter ( d => d . kind === "videoinput" )
191
+ . map ( d => ( { id : d . deviceId , name : d . label } ) satisfies Camera )
192
+ ) ,
193
+ { fallbackValue : [ ] }
194
+ ) ;
195
+
196
+ return (
197
+ < Select
198
+ clearable = { true }
199
+ options = { cameras . map ( s => ( { label : s . name , value : s . id } ) ) }
200
+ isSelected = { s => s === camera }
201
+ select = { s => chooseCamera ( s ) }
202
+ clear = { ( ) => chooseCamera ( undefined ) }
203
+ serialize = { String }
204
+ />
205
+ ) ;
206
+ }
207
+
152
208
function StreamSettings ( {
153
209
source,
154
210
settings,
@@ -171,6 +227,7 @@ function StreamSettings({
171
227
return (
172
228
< div >
173
229
< Forms . FormTitle > What you're streaming</ Forms . FormTitle >
230
+
174
231
< Card className = "vcd-screen-picker-card vcd-screen-picker-preview" >
175
232
< img src = { thumb } alt = "" />
176
233
< Text variant = "text-sm/normal" > { source . name } </ Text >
@@ -257,7 +314,7 @@ function AudioSourceAnyDevice({
257
314
audioDevice ?: string ;
258
315
setAudioDevice ( s : string | undefined ) : void ;
259
316
} ) {
260
- const [ sources , _ , loading ] = useAwaiter (
317
+ const [ sources ] = useAwaiter (
261
318
( ) =>
262
319
navigator . mediaDevices
263
320
. enumerateDevices ( )
@@ -341,11 +398,8 @@ function ModalComponent({
341
398
skipPicker : boolean ;
342
399
} ) {
343
400
const [ selected , setSelected ] = useState < string | undefined > ( skipPicker ? screens [ 0 ] . id : void 0 ) ;
344
- const [ settings , setSettings ] = useState < StreamSettings > ( {
345
- resolution : "1080" ,
346
- fps : "60" ,
347
- audio : true
348
- } ) ;
401
+ const [ camera , setCamera ] = useState < string | undefined > ( undefined ) ;
402
+ const [ settings , setSettings ] = useState < StreamSettings > ( { resolution : "1080" , fps : "60" , audio : true } ) ;
349
403
350
404
return (
351
405
< Modals . ModalRoot { ...modalProps } >
@@ -356,7 +410,10 @@ function ModalComponent({
356
410
357
411
< Modals . ModalContent className = "vcd-screen-picker-modal" >
358
412
{ ! selected ? (
359
- < ScreenPicker screens = { screens } chooseScreen = { setSelected } />
413
+ < >
414
+ < ScreenPicker screens = { screens } chooseScreen = { setSelected } isDisabled = { ! ! camera } />
415
+ < CameraPicker camera = { camera } chooseCamera = { setCamera } />
416
+ </ >
360
417
) : (
361
418
< StreamSettings
362
419
source = { screens . find ( s => s . id === selected ) ! }
@@ -369,7 +426,7 @@ function ModalComponent({
369
426
370
427
< Modals . ModalFooter className = "vcd-screen-picker-footer" >
371
428
< Button
372
- disabled = { ! selected }
429
+ disabled = { ! selected && ! camera }
373
430
onClick = { ( ) => {
374
431
currentSettings = settings ;
375
432
@@ -393,6 +450,7 @@ function ModalComponent({
393
450
394
451
submit ( {
395
452
id : selected ! ,
453
+ cameraId : camera ,
396
454
...settings
397
455
} ) ;
398
456
0 commit comments