import { ipcRenderer } from 'electron'; import { type MouseEventHandler, useEffect, useState } from 'react'; import { type WrappedComponentProps, defineMessages, injectIntl, } from 'react-intl'; import { SCREENSHARE_CANCELLED_BY_USER } from '../config'; import { isWayland } from '../environment'; import type Service from '../models/Service'; import FullscreenLoader from './ui/FullscreenLoader'; interface IProps extends WrappedComponentProps { service: Service; } const messages = defineMessages({ loading: { id: 'service.screenshare.loading', defaultMessage: 'Loading screens and windows', }, cancel: { id: 'service.screenshare.cancel', defaultMessage: 'Cancel', }, }); interface ICancelButtonProps extends WrappedComponentProps { handleOnClick: MouseEventHandler | undefined; } const CancelButton = injectIntl( ({ handleOnClick, intl }: ICancelButtonProps) => (
  • ), ); function MediaSource(props: IProps) { const { service, intl } = props; const [sources, setSources] = useState([]); const [show, setShow] = useState(false); const [trackerId, setTrackerId] = useState(null); const [loadingSources, setLoadingSources] = useState(false); ipcRenderer.on(`select-capture-device:${service.id}`, (_event, data) => { if (loadingSources) return; setShow(true); setTrackerId(data.trackerId); }); const handleOnClick = (e: any) => { const { id } = e.currentTarget.dataset; window['ferdium'].actions.service.sendIPCMessage({ serviceId: service.id, channel: `selected-media-source:${trackerId}`, args: { mediaSourceId: id, }, }); setShow(false); setSources([]); setTrackerId(null); }; // biome-ignore lint/correctness/useExhaustiveDependencies: This effect should only run when `show` changes useEffect(() => { if (show) { setLoadingSources(true); ipcRenderer .invoke('get-desktop-capturer-sources') .then(sources => { if (isWayland) { // On Linux, we do not need to prompt the user again for the source handleOnClick({ currentTarget: { dataset: { id: sources[0].id } }, }); return; } setSources(sources); setLoadingSources(false); }) // silence the error .catch(() => { setShow(false); setSources([]); setLoadingSources(false); }); } else { setSources([]); setLoadingSources(false); } }, [show]); if (!show) { return null; } if (loadingSources) { return (
    ); } if (sources.length === 0) { return (
    • No available sources.
    ); } return (
      {sources.map(({ id, name, thumbnail }) => (
    • ))}
    ); } export default injectIntl(MediaSource);