summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar André Oliveira <37463445+SpecialAro@users.noreply.github.com>2024-05-04 01:40:38 +0100
committerLibravatar GitHub <noreply@github.com>2024-05-04 01:40:38 +0100
commit87721c96194f80ecf774dc2ce71118b93ee6440c (patch)
treec352ffbdff967f523d9c8cc8ae18c7026e262d34
parentfix: screenshare not working properly (#1736) (diff)
downloadferdium-app-87721c96194f80ecf774dc2ce71118b93ee6440c.tar.gz
ferdium-app-87721c96194f80ecf774dc2ce71118b93ee6440c.tar.zst
ferdium-app-87721c96194f80ecf774dc2ce71118b93ee6440c.zip
Fix screenshare on wayland and style (#1739)
* fix: screenshare prompts twice * Add loading screen
-rw-r--r--src/components/MediaSource.tsx147
-rw-r--r--src/environment.ts2
-rw-r--r--src/i18n/locales/en-US.json2
3 files changed, 120 insertions, 31 deletions
diff --git a/src/components/MediaSource.tsx b/src/components/MediaSource.tsx
index 02e617800..34fbda227 100644
--- a/src/components/MediaSource.tsx
+++ b/src/components/MediaSource.tsx
@@ -1,37 +1,65 @@
1import { ipcRenderer } from 'electron'; 1import { ipcRenderer } from 'electron';
2import { useEffect, useState } from 'react'; 2import { type MouseEventHandler, useEffect, useState } from 'react';
3import {
4 type WrappedComponentProps,
5 defineMessages,
6 injectIntl,
7} from 'react-intl';
3import { SCREENSHARE_CANCELLED_BY_USER } from '../config'; 8import { SCREENSHARE_CANCELLED_BY_USER } from '../config';
9import { isWayland } from '../environment';
4import type Service from '../models/Service'; 10import type Service from '../models/Service';
11import FullscreenLoader from './ui/FullscreenLoader';
5 12
6export interface IProps { 13interface IProps extends WrappedComponentProps {
7 service: Service; 14 service: Service;
8} 15}
9 16
10export default function MediaSource(props: IProps) { 17const messages = defineMessages({
11 const { service } = props; 18 loading: {
19 id: 'service.screenshare.loading',
20 defaultMessage: 'Loading screens and windows',
21 },
22 cancel: {
23 id: 'service.screenshare.cancel',
24 defaultMessage: 'Cancel',
25 },
26});
27
28interface ICancelButtonProps extends WrappedComponentProps {
29 handleOnClick: MouseEventHandler<HTMLButtonElement> | undefined;
30}
31
32const CancelButton = injectIntl(
33 ({ handleOnClick, intl }: ICancelButtonProps) => (
34 <li className="desktop-capturer-selection__item">
35 <button
36 type="button" // Add explicit type attribute
37 className="desktop-capturer-selection__btn"
38 data-id={SCREENSHARE_CANCELLED_BY_USER}
39 title="Cancel"
40 onClick={handleOnClick}
41 >
42 <span className="desktop-capturer-selection__name desktop-capturer-selection__name--cancel">
43 {intl.formatMessage(messages.cancel)}
44 </span>
45 </button>
46 </li>
47 ),
48);
49
50function MediaSource(props: IProps) {
51 const { service, intl } = props;
12 const [sources, setSources] = useState<any>([]); 52 const [sources, setSources] = useState<any>([]);
13 const [show, setShow] = useState<boolean>(false); 53 const [show, setShow] = useState<boolean>(false);
14 const [trackerId, setTrackerId] = useState<string | null>(null); 54 const [trackerId, setTrackerId] = useState<string | null>(null);
55 const [loadingSources, setLoadingSources] = useState<boolean>(false);
15 56
16 ipcRenderer.on(`select-capture-device:${service.id}`, (_event, data) => { 57 ipcRenderer.on(`select-capture-device:${service.id}`, (_event, data) => {
58 if (loadingSources) return;
17 setShow(true); 59 setShow(true);
18 setTrackerId(data.trackerId); 60 setTrackerId(data.trackerId);
19 }); 61 });
20 62
21 useEffect(() => {
22 if (show) {
23 ipcRenderer
24 .invoke('get-desktop-capturer-sources')
25 .then(sources => setSources(sources));
26 } else {
27 setSources([]);
28 }
29 }, [show]);
30
31 if (sources.length === 0 || !show) {
32 return null;
33 }
34
35 const handleOnClick = (e: any) => { 63 const handleOnClick = (e: any) => {
36 const { id } = e.currentTarget.dataset; 64 const { id } = e.currentTarget.dataset;
37 window['ferdium'].actions.service.sendIPCMessage({ 65 window['ferdium'].actions.service.sendIPCMessage({
@@ -43,9 +71,76 @@ export default function MediaSource(props: IProps) {
43 }); 71 });
44 72
45 setShow(false); 73 setShow(false);
74 setSources([]);
46 setTrackerId(null); 75 setTrackerId(null);
47 }; 76 };
48 77
78 // biome-ignore lint/correctness/useExhaustiveDependencies: This effect should only run when `show` changes
79 useEffect(() => {
80 if (show) {
81 setLoadingSources(true);
82 ipcRenderer
83 .invoke('get-desktop-capturer-sources')
84 .then(sources => {
85 if (isWayland) {
86 // On Linux, we do not need to prompt the user again for the source
87 handleOnClick({
88 currentTarget: { dataset: { id: sources[0].id } },
89 });
90 return;
91 }
92
93 setSources(sources);
94 setLoadingSources(false);
95 })
96 // silence the error
97 .catch(() => {
98 setShow(false);
99 setSources([]);
100 setLoadingSources(false);
101 });
102 } else {
103 setSources([]);
104 setLoadingSources(false);
105 }
106 }, [show]);
107
108 if (!show) {
109 return null;
110 }
111
112 if (loadingSources) {
113 return (
114 <div className="desktop-capturer-selection">
115 <ul
116 className="desktop-capturer-selection__list"
117 style={{
118 display: 'flex',
119 flexDirection: 'column',
120 alignItems: 'center',
121 }}
122 >
123 <FullscreenLoader title={intl.formatMessage(messages.loading)}>
124 <div style={{ display: 'flex', justifyContent: 'center' }}>
125 <CancelButton handleOnClick={handleOnClick} />
126 </div>
127 </FullscreenLoader>
128 </ul>
129 </div>
130 );
131 }
132
133 if (sources.length === 0) {
134 return (
135 <div className="desktop-capturer-selection">
136 <ul className="desktop-capturer-selection__list">
137 <li>No available sources.</li>
138 <CancelButton handleOnClick={handleOnClick} />
139 </ul>
140 </div>
141 );
142 }
143
49 return ( 144 return (
50 <div className="desktop-capturer-selection"> 145 <div className="desktop-capturer-selection">
51 <ul className="desktop-capturer-selection__list"> 146 <ul className="desktop-capturer-selection__list">
@@ -67,20 +162,10 @@ export default function MediaSource(props: IProps) {
67 </button> 162 </button>
68 </li> 163 </li>
69 ))} 164 ))}
70 <li className="desktop-capturer-selection__item">
71 <button
72 type="button" // Add explicit type attribute
73 className="desktop-capturer-selection__btn"
74 data-id={SCREENSHARE_CANCELLED_BY_USER}
75 title="Cancel"
76 onClick={handleOnClick}
77 >
78 <span className="desktop-capturer-selection__name desktop-capturer-selection__name--cancel">
79 Cancel
80 </span>
81 </button>
82 </li>
83 </ul> 165 </ul>
166 <CancelButton handleOnClick={handleOnClick} />
84 </div> 167 </div>
85 ); 168 );
86} 169}
170
171export default injectIntl(MediaSource);
diff --git a/src/environment.ts b/src/environment.ts
index 87e2f4f66..4a0399876 100644
--- a/src/environment.ts
+++ b/src/environment.ts
@@ -7,6 +7,8 @@ export const isWindows = process.platform === 'win32';
7export const isLinux = process.platform === 'linux'; 7export const isLinux = process.platform === 'linux';
8export const isWinPortable = process.env.PORTABLE_EXECUTABLE_FILE != null; 8export const isWinPortable = process.env.PORTABLE_EXECUTABLE_FILE != null;
9 9
10export const isWayland = isLinux && process.env.XDG_SESSION_TYPE === 'wayland';
11
10export const electronVersion: string = process.versions.electron ?? ''; 12export const electronVersion: string = process.versions.electron ?? '';
11export const chromeVersion: string = process.versions.chrome ?? ''; 13export const chromeVersion: string = process.versions.chrome ?? '';
12export const nodeVersion: string = process.versions.node; 14export const nodeVersion: string = process.versions.node;
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index 1835854e1..3947b2e5f 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -164,6 +164,8 @@
164 "service.errorHandler.headline": "Oh no!", 164 "service.errorHandler.headline": "Oh no!",
165 "service.errorHandler.message": "Error", 165 "service.errorHandler.message": "Error",
166 "service.errorHandler.text": "{name} has failed to load.", 166 "service.errorHandler.text": "{name} has failed to load.",
167 "service.screenshare.cancel": "Cancel",
168 "service.screenshare.loading": "Loading screens and windows",
167 "service.webviewLoader.loading": "Loading {service}", 169 "service.webviewLoader.loading": "Loading {service}",
168 "services.getStarted": "Get started", 170 "services.getStarted": "Get started",
169 "services.login": "Please login to use Ferdium.", 171 "services.login": "Please login to use Ferdium.",