/* Copyright 2024 New Vector Ltd. Copyright 2021 Šimon Brandner SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ import React from "react"; import classNames from "classnames"; import { _t, _td, TranslationKey } from "../../../languageHandler"; import BaseDialog from "..//dialogs/BaseDialog"; import DialogButtons from "./DialogButtons"; import AccessibleButton from "./AccessibleButton"; import TabbedView, { Tab, TabLocation } from "../../structures/TabbedView"; import PlatformPeg from "../../../PlatformPeg"; import { NonEmptyArray } from "../../../@types/common"; export function getDesktopCapturerSources(): Promise> { const options: GetSourcesOptions = { thumbnailSize: { height: 176, width: 312, }, types: ["screen", "window"], }; const plaf = PlatformPeg.get(); return plaf ? plaf?.getDesktopCapturerSources(options) : Promise.resolve([]); } export enum Tabs { Screens = "screen", Windows = "window", } export interface ExistingSourceIProps { source: DesktopCapturerSource; onSelect(source: DesktopCapturerSource): void; selected: boolean; } export class ExistingSource extends React.Component { private onClick = (): void => { this.props.onSelect(this.props.source); }; public render(): React.ReactNode { const thumbnailClasses = classNames({ mx_desktopCapturerSourcePicker_source_thumbnail: true, mx_desktopCapturerSourcePicker_source_thumbnail_selected: this.props.selected, }); return ( {this.props.source.name} {this.props.source.name} ); } } export interface PickerIState { selectedTab: Tabs; sources: Array; selectedSource?: DesktopCapturerSource; } export interface PickerIProps { onFinished(source?: DesktopCapturerSource): void; } export default class DesktopCapturerSourcePicker extends React.Component { public interval?: number; public constructor(props: PickerIProps) { super(props); this.state = { selectedTab: Tabs.Screens, sources: [], }; } public async componentDidMount(): Promise { // window.setInterval() first waits and then executes, therefore // we call getDesktopCapturerSources() here without any delay. // Otherwise the dialog would be left empty for some time. this.setState({ sources: await getDesktopCapturerSources(), }); // We update the sources every 500ms to get newer thumbnails this.interval = window.setInterval(async (): Promise => { this.setState({ sources: await getDesktopCapturerSources(), }); }, 500); } public componentWillUnmount(): void { clearInterval(this.interval); } private onSelect = (source: DesktopCapturerSource): void => { this.setState({ selectedSource: source }); }; private onShare = (): void => { this.props.onFinished(this.state.selectedSource); }; private onTabChange = (tab: Tabs): void => { this.setState({ selectedSource: undefined, selectedTab: tab }); }; private onCloseClick = (): void => { this.props.onFinished(); }; private getTab(type: Tabs, label: TranslationKey): Tab { const sources = this.state.sources .filter((source) => source.id.startsWith(type)) .map((source) => { return ( ); }); return new Tab(type, label, null,
{sources}
); } public render(): React.ReactNode { const tabs: NonEmptyArray> = [ this.getTab(Tabs.Screens, _td("voip|screenshare_monitor")), this.getTab(Tabs.Windows, _td("voip|screenshare_window")), ]; return ( ); } }