diff --git a/app/javascript/components/media_deck.tsx b/app/javascript/components/media_deck.tsx index 6ef82d7d0..5ca517921 100644 --- a/app/javascript/components/media_deck.tsx +++ b/app/javascript/components/media_deck.tsx @@ -3,49 +3,31 @@ import ScreenShare from "components/media_deck/screen_share"; import AddScreenShare from "components/media_deck/add_screen_share"; import CameraShare from "components/media_deck/camera_share"; import AddWebcamSource from "components/media_deck/add_webcam_source"; +import { observer } from "mobx-preact"; +import ScreenSourceStore from "components/media_deck/secreen_source"; +import WebcamSourceStore from "components/media_deck/webcam_source"; -type State = { - isScreenVisible: boolean; - webcamShared: boolean; - screenShared: boolean; -}; - -export default class MediaDeck extends Component { - constructor() { - super(); - this.setState({ - isScreenVisible: true, - webcamShared: false, - screenShared: false, - }) - } - +const MediaDeck = observer(class MediaDeck extends Component { render(): VNode { return (
this.setState({isScreenVisible: !this.state.isScreenVisible})} + screenSourceStore={ScreenSourceStore} /> - -
+ +
this.setState({ screenShared: true })} - stopSharing={() => this.setState(({ screenShared: false }))} - toggleVisibility={() => this.setState({ isScreenVisible: !this.state.isScreenVisible})} + screenSourceStore={ScreenSourceStore} /> this.setState({ webcamShared: true })} - stopSharing={() => this.setState({webcamShared: false})} + webcamSourceStore={WebcamSourceStore} />
); } -} +}); + +export default MediaDeck; diff --git a/app/javascript/components/media_deck/add_screen_share.tsx b/app/javascript/components/media_deck/add_screen_share.tsx index 99a47ef78..e29e7fad3 100644 --- a/app/javascript/components/media_deck/add_screen_share.tsx +++ b/app/javascript/components/media_deck/add_screen_share.tsx @@ -1,41 +1,43 @@ import { Component, h, VNode } from "preact"; +import { ScreenSourceStore } from "components/media_deck/secreen_source"; type Props = { - isScreenVisible: boolean; screenSourceAttached: boolean; - addScreenCaptureSource(): void; stopSharing(): void; - toggleVisibility(): void; + screenSourceStore: ScreenSourceStore; }; +import { observer } from "mobx-preact"; -export default class AddScreenShare extends Component { +const AddScreenShare = observer(class AddScreenShare extends Component { render(): VNode { return (
{this.renderVisibilityControls()} { - !this.props.screenSourceAttached ? - : + : }
); } renderVisibilityControls(): VNode { - if (!this.props.screenSourceAttached) { + if (!this.props.screenSourceStore.screenCaptureSource) { return ; } return ( ); } -} \ No newline at end of file +}); + +export default AddScreenShare; \ No newline at end of file diff --git a/app/javascript/components/media_deck/add_webcam_source.tsx b/app/javascript/components/media_deck/add_webcam_source.tsx index 3495f4648..1b98d31aa 100644 --- a/app/javascript/components/media_deck/add_webcam_source.tsx +++ b/app/javascript/components/media_deck/add_webcam_source.tsx @@ -1,22 +1,28 @@ import { Component, h, VNode } from "preact"; +import { WebcamSourceStore } from "components/media_deck/webcam_source"; +import { observer } from "mobx-preact"; type Props = { webcamSourceAttached: boolean; addWebcamCaptureSource(): void; stopSharing(): void; + webcamSourceStore: WebcamSourceStore } -export default class AddWebcamSource extends Component { + +const AddWebcamSource = observer(class AddWebcamSource extends Component { render(): VNode { return (
{ - !this.props.webcamSourceAttached ? - : - + }
); } -} +}); + +export default AddWebcamSource; diff --git a/app/javascript/components/media_deck/camera_share.tsx b/app/javascript/components/media_deck/camera_share.tsx index cef57e136..1b500fe88 100644 --- a/app/javascript/components/media_deck/camera_share.tsx +++ b/app/javascript/components/media_deck/camera_share.tsx @@ -1,38 +1,20 @@ import { Component, h, VNode } from "preact"; -import EventBus from "event_bus"; -import { RemoveCaptureSourceEvent } from "helpers/broadcast/capture_source_manager"; import { WebcamCaptureSource } from "helpers/broadcast/capture_sources/webcam"; +import { WebcamSourceStore } from "components/media_deck/webcam_source"; +import { observer } from "mobx-preact"; -type Props = { webcamShared: boolean }; -type State = { deviceId: string; streamStarted: boolean; webcamCaptureSource: WebcamCaptureSource; } +type Props = { webcamShared: boolean; webcamSourceStore: WebcamSourceStore; }; -export default class CameraShare extends Component { - private videoTag: HTMLVideoElement; - private webcamDevices: MediaDeviceInfo[]; - - constructor(props: Props) { - super(props); - - this.setState({ - deviceId: null, - streamStarted: false, - webcamCaptureSource: null, - }); - } +const CameraShare = observer(class CameraShare extends Component { render(): VNode { return (
-
{ - this.props.webcamShared && !this.state.streamStarted ? + this.props.webcamSourceStore.webcamDialogueVisible && !this.props.webcamSourceStore.webcamCaptureSource ? : null @@ -41,26 +23,9 @@ export default class CameraShare extends Component { ); } - async componentDidMount(): Promise { - const devices = await navigator.mediaDevices.enumerateDevices(); - this.webcamDevices = devices.filter((d: MediaDeviceInfo) => d.kind === "videoinput"); - } - - async componentDidUpdate(prevProps: Props): Promise { - if (prevProps.webcamShared === this.props.webcamShared) - return; - - if (!this.props.webcamShared) { - EventBus.dispatch(RemoveCaptureSourceEvent, this.state.webcamCaptureSource); - this.state.webcamCaptureSource.stop(); - this.videoTag.srcObject = null; - this.setState({ webcamCaptureSource: null }); - } - } - private renderWebcamDevices(): VNode[] { const devicesMarkup = []; - this.webcamDevices.forEach((device: MediaDeviceInfo) => { + this.props.webcamSourceStore.webcamDevices.forEach((device: MediaDeviceInfo) => { devicesMarkup.push(this.deviceMarkup(device)); }); return devicesMarkup; @@ -71,24 +36,12 @@ export default class CameraShare extends Component { ); } +}); - private async startWebcamStream(deviceId: string): Promise { - const webcamCaptureSource = await WebcamCaptureSource.connect( - this.state.deviceId, - this.videoTag - ); - - this.setState({ - deviceId: deviceId, - streamStarted: true, - webcamCaptureSource, - }); - - } -} \ No newline at end of file +export default CameraShare; diff --git a/app/javascript/components/media_deck/screen_share.tsx b/app/javascript/components/media_deck/screen_share.tsx index ba8476ab7..d4c15964a 100644 --- a/app/javascript/components/media_deck/screen_share.tsx +++ b/app/javascript/components/media_deck/screen_share.tsx @@ -1,26 +1,18 @@ import { Component, h, VNode } from "preact"; -import { ScreenCaptureSource } from "helpers/broadcast/capture_sources/screen"; import { NewCaptureSourceEvent, RemoveCaptureSourceEvent, } from "helpers/broadcast/capture_source_manager"; import hiddenIcon from "images/visible-false.svg"; import EventBus from "event_bus"; +import { observer } from "mobx-preact"; +import { ScreenSourceStore } from "components/media_deck/secreen_source"; -type State = { screenCaptureSource: ScreenCaptureSource; }; -type Props = { screenShared: boolean; isVisible: boolean; toggleVisibility(): void; }; +type Props = { screenSourceStore: ScreenSourceStore }; -export default class ScreenShare extends Component { +const ScreenShare = observer(class ScreenShare extends Component { private videoTag: HTMLVideoElement; - constructor(props: Props) { - super(props); - - this.state = { - screenCaptureSource: null, - }; - } - render(): VNode { return (
{ this.toggleVisibility(); }} > - {this.props.isVisible ? null : ( + {this.props.screenSourceStore.isScreenVisible ? null : (
hidden icon
)}
-
); } - async componentDidUpdate(prevProps: Props): Promise { - if (prevProps.screenShared === this.props.screenShared) - return; - - if (this.props.screenShared) { - const screenCaptureSource = await ScreenCaptureSource.connect( - this.videoTag - ); - - this.setState({ - screenCaptureSource, - }); - this.props.toggleVisibility() - } else { - EventBus.dispatch(RemoveCaptureSourceEvent, this.state.screenCaptureSource); - this.state.screenCaptureSource.stop(); - this.videoTag.srcObject = null; - this.setState({ screenCaptureSource: null }); - } - } - renderVisibilityControls(): VNode { - if (!this.state.screenCaptureSource) { + if (!this.props.screenSourceStore.screenCaptureSource) { return ; } return ( ); } private toggleVisibility() { - if (this.state.screenCaptureSource) { - if (this.props.isVisible) { + if (this.props.screenSourceStore.screenCaptureSource) { + if (this.props.screenSourceStore.isScreenVisible) { EventBus.dispatch( RemoveCaptureSourceEvent, - this.state.screenCaptureSource + this.props.screenSourceStore.screenCaptureSource ); - this.props.toggleVisibility(); + this.props.screenSourceStore.toggleVisibility(); } else { EventBus.dispatch( NewCaptureSourceEvent, - this.state.screenCaptureSource + this.props.screenSourceStore.screenCaptureSource ); } - this.props.toggleVisibility(); + this.props.screenSourceStore.toggleVisibility(); } } -} +}); + +export default ScreenShare; diff --git a/app/javascript/components/media_deck/secreen_source.tsx b/app/javascript/components/media_deck/secreen_source.tsx new file mode 100644 index 000000000..75dcd8945 --- /dev/null +++ b/app/javascript/components/media_deck/secreen_source.tsx @@ -0,0 +1,50 @@ +import { h, VNode } from "preact"; +import { makeAutoObservable } from "mobx"; +import EventBus from "event_bus"; +import { ScreenCaptureSource } from "helpers/broadcast/capture_sources/screen"; +import { + RemoveCaptureSourceEvent, +} from "helpers/broadcast/capture_source_manager"; + +export class ScreenSourceStore { + isScreenVisible = true; + screenCaptureSource = null; + videoTag = null; + + constructor() { + makeAutoObservable(this); + } + + renderVideo(): VNode { + return ( +
+
+ ); + } + + *connectScreenShareSource() { + this.screenCaptureSource = yield ScreenCaptureSource.connect( + this.videoTag + ); + this.isScreenVisible = true; + } + + disconnectScreenShareSource(): void { + EventBus.dispatch(RemoveCaptureSourceEvent, this.screenCaptureSource); + this.screenCaptureSource.stop(); + this.videoTag.srcObject = null; + this.screenCaptureSource = null; + } + + toggleVisibility(): void { + this.isScreenVisible = !this.isScreenVisible; + } +} + +export default new ScreenSourceStore(); \ No newline at end of file diff --git a/app/javascript/components/media_deck/webcam_source.tsx b/app/javascript/components/media_deck/webcam_source.tsx new file mode 100644 index 000000000..cb99c54f8 --- /dev/null +++ b/app/javascript/components/media_deck/webcam_source.tsx @@ -0,0 +1,57 @@ +import { h, VNode } from "preact"; +import { autorun, makeAutoObservable } from "mobx"; +import { WebcamCaptureSource } from "helpers/broadcast/capture_sources/webcam"; +import EventBus from "event_bus"; +import { RemoveCaptureSourceEvent } from "helpers/broadcast/capture_source_manager"; + +export class WebcamSourceStore { + webcamDialogueVisible = false; + webcamCaptureSource = null; + webcamDevices = []; + videoTag = null; + deviceId = ""; + + constructor() { + makeAutoObservable(this); + autorun(() => this.enumerateWebcamDevices()) + } + + renderVideo(): VNode { + return ( +