mirror of
https://github.com/pavlobu/deskreen.git
synced 2025-05-28 05:10:09 -07:00
Merge pull request #12 from pavlobu/client-ui
Client and Host UI improvements
This commit is contained in:
commit
6230424192
@ -12,12 +12,15 @@
|
||||
"@types/react": "^16.9.0",
|
||||
"@types/react-dom": "^16.9.0",
|
||||
"@types/ua-parser-js": "^0.7.33",
|
||||
"i18next": "^19.8.4",
|
||||
"i18next-http-backend": "^1.0.21",
|
||||
"jest-sonar-reporter": "^2.0.0",
|
||||
"node-forge": "^0.9.1",
|
||||
"pixelmatch": "^5.2.1",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-flexbox-grid": "^2.1.2",
|
||||
"react-i18next": "^11.7.4",
|
||||
"react-player": "^2.6.2",
|
||||
"react-reveal": "^1.2.2",
|
||||
"react-scripts": "3.4.3",
|
||||
|
4
app/client/public/locales/en/translation.json
Normal file
4
app/client/public/locales/en/translation.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"Waiting for user to click ALLOW button on screen sharing device...": "Waiting for user to click ALLOW button on screen sharing device...",
|
||||
"Wating for user to select source to share from screen sharing device...": "Wating for user to select source to share from screen sharing device..."
|
||||
}
|
4
app/client/public/locales/ru/translation.json
Normal file
4
app/client/public/locales/ru/translation.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"Waiting for user to click ALLOW button on screen sharing device...": "Жду когда пользователь нажмет кнопку РАЗРЕШИТЬ доступ к экрану компьютера...",
|
||||
"Wating for user to select source to share from screen sharing device...": "Жду когда пользователь выберет весь экран или окно приложения для демонстрации..."
|
||||
}
|
4
app/client/public/locales/ua/translation.json
Normal file
4
app/client/public/locales/ua/translation.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"Waiting for user to click ALLOW button on screen sharing device...": "Чекаэмо коли користувач натисне кнопку ДОЗВОЛИТИ доступ до екрану комп'ютера...",
|
||||
"Wating for user to select source to share from screen sharing device...": "Чекаю коли користувач вибере весь екран або вікно програми для демонстрації..."
|
||||
}
|
@ -1,12 +1,20 @@
|
||||
import React, { useEffect, useState, useRef, useContext } from 'react';
|
||||
import { H3, Button } from '@blueprintjs/core';
|
||||
import React, {
|
||||
useEffect,
|
||||
useState,
|
||||
useRef,
|
||||
useContext,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import i18n from './config/i18n';
|
||||
import { H3, Position, Toaster } from '@blueprintjs/core';
|
||||
import { Grid, Row, Col } from 'react-flexbox-grid';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import ReactPlayer from 'react-player';
|
||||
import screenfull from 'screenfull';
|
||||
import Crypto from './utils/crypto';
|
||||
import './App.css';
|
||||
import LocalTestPeer from './features/PeerConnection';
|
||||
import PeerConnection from './features/PeerConnection';
|
||||
import VideoAutoQualityOptimizer from './features/VideoAutoQualityOptimizer';
|
||||
import ConnectingIndicator from './components/ConnectingIndicator';
|
||||
import MyDeviceInfoCard from './components/MyDeviceInfoCard';
|
||||
@ -15,24 +23,34 @@ import {
|
||||
LIGHT_UI_BACKGROUND,
|
||||
} from './constants/styleConstants';
|
||||
import { AppContext } from './providers/AppContextProvider';
|
||||
import ToggleDarkModeSwitch from './components/ToggleDarkModeSwitch';
|
||||
import PlayerControlPanel from './components/PlayerControlPanel';
|
||||
import { VideoQuality } from './features/PeerConnection/VideoQualityEnum';
|
||||
import { REACT_PLAYER_WRAPPER_ID } from './constants/appConstants';
|
||||
import { TFunction } from 'i18next';
|
||||
import ErrorDialog from './components/ErrorDialog';
|
||||
import { ErrorMessage } from './components/ErrorDialog/ErrorMessageEnum';
|
||||
|
||||
const Fade = require('react-reveal/Fade');
|
||||
const Slide = require('react-reveal/Slide');
|
||||
|
||||
function getPromptContent(step: number) {
|
||||
function getPromptContent(step: number, t: TFunction) {
|
||||
switch (step) {
|
||||
case 1:
|
||||
return (
|
||||
<H3>Waiting for user to click "Allow" on screen sharing device...</H3>
|
||||
<H3>
|
||||
{t(
|
||||
'Waiting for user to click ALLOW button on screen sharing device...'
|
||||
)}
|
||||
</H3>
|
||||
);
|
||||
case 2:
|
||||
return <H3>Connected!</H3>;
|
||||
case 3:
|
||||
return (
|
||||
<H3>
|
||||
Wating for user to select source to share from screen sharing
|
||||
device...
|
||||
{t(
|
||||
'Wating for user to select source to share from screen sharing device...'
|
||||
)}
|
||||
</H3>
|
||||
);
|
||||
default:
|
||||
@ -41,10 +59,23 @@ function getPromptContent(step: number) {
|
||||
}
|
||||
|
||||
function App() {
|
||||
const { t } = useTranslation();
|
||||
const { isDarkTheme, setIsDarkThemeHook } = useContext(AppContext);
|
||||
const [isErrorDialogOpen, setIsErrorDialogOpen] = useState(false);
|
||||
|
||||
const [toaster, setToaster] = useState<undefined | Toaster>();
|
||||
|
||||
const refHandlers = {
|
||||
toaster: (ref: Toaster) => {
|
||||
setToaster(ref);
|
||||
},
|
||||
};
|
||||
|
||||
const player = useRef(null);
|
||||
const [promptStep, setPromptStep] = useState(1);
|
||||
const [dialogErrorMessage, setDialogErrorMessage] = useState<ErrorMessage>(
|
||||
ErrorMessage.UNKNOWN_ERROR
|
||||
);
|
||||
const [connectionIconType, setConnectionIconType] = useState<
|
||||
'feed' | 'feed-subscribed'
|
||||
>('feed');
|
||||
@ -56,43 +87,73 @@ function App() {
|
||||
});
|
||||
|
||||
const [playing, setPlaying] = useState(true);
|
||||
const [isFullScreenOn, setIsFullScreenOn] = useState(false);
|
||||
const [url, setUrl] = useState();
|
||||
const [screenSharingSourceType, setScreenSharingSourceType] = useState<
|
||||
'screen' | 'window'
|
||||
>('screen');
|
||||
const [isWithControls, setIsWithControls] = useState(!screenfull.isEnabled);
|
||||
const [isShownTextPrompt, setIsShownTextPrompt] = useState(false);
|
||||
const [isShownSpinnerIcon, setIsShownSpinnerIcon] = useState(false);
|
||||
const [spinnerIconType, setSpinnerIconType] = useState<
|
||||
'desktop' | 'application'
|
||||
>('desktop');
|
||||
const [videoQuality, setVideoQuality] = useState<VideoQuality>(
|
||||
VideoQuality.Q_AUTO
|
||||
);
|
||||
const [peer, setPeer] = useState<undefined | PeerConnection>();
|
||||
|
||||
const changeLanguage = (lng: string) => {
|
||||
i18n.changeLanguage(lng);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!peer) return;
|
||||
if (!peer.isStreamStarted) return;
|
||||
peer.setVideoQuality(videoQuality);
|
||||
}, [videoQuality, peer]);
|
||||
|
||||
useEffect(() => {
|
||||
document.body.style.backgroundColor = isDarkTheme
|
||||
? DARK_UI_BACKGROUND
|
||||
: LIGHT_UI_BACKGROUND;
|
||||
}, [isDarkTheme]);
|
||||
|
||||
const peer = new LocalTestPeer(
|
||||
setUrl,
|
||||
new Crypto(),
|
||||
new VideoAutoQualityOptimizer(),
|
||||
setMyDeviceDetails,
|
||||
() => {
|
||||
setConnectionIconType('feed-subscribed');
|
||||
useEffect(() => {
|
||||
if (!peer) {
|
||||
const _peer = new PeerConnection(
|
||||
setUrl,
|
||||
new Crypto(),
|
||||
new VideoAutoQualityOptimizer(),
|
||||
isDarkTheme,
|
||||
setMyDeviceDetails,
|
||||
() => {
|
||||
setConnectionIconType('feed-subscribed');
|
||||
|
||||
setIsShownTextPrompt(false);
|
||||
setIsShownTextPrompt(true);
|
||||
setPromptStep(2);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsShownTextPrompt(false);
|
||||
setIsShownTextPrompt(true);
|
||||
setPromptStep(3);
|
||||
}, 2000);
|
||||
}
|
||||
);
|
||||
setPromptStep(2);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsShownTextPrompt(true);
|
||||
}, 100);
|
||||
}, []);
|
||||
setTimeout(() => {
|
||||
setIsShownTextPrompt(false);
|
||||
setIsShownTextPrompt(true);
|
||||
setPromptStep(3);
|
||||
}, 2000);
|
||||
},
|
||||
setScreenSharingSourceType,
|
||||
setIsDarkThemeHook,
|
||||
changeLanguage,
|
||||
setDialogErrorMessage,
|
||||
setIsErrorDialogOpen
|
||||
);
|
||||
|
||||
setPeer(_peer);
|
||||
|
||||
setTimeout(() => {
|
||||
setIsShownTextPrompt(true);
|
||||
}, 100);
|
||||
}
|
||||
}, [setIsDarkThemeHook, isDarkTheme, peer]);
|
||||
|
||||
useEffect(() => {
|
||||
// infinite use effect
|
||||
@ -102,22 +163,11 @@ function App() {
|
||||
spinnerIconType === 'desktop' ? 'application' : 'desktop'
|
||||
);
|
||||
}, 1500);
|
||||
}, [isShownSpinnerIcon]);
|
||||
}, [isShownSpinnerIcon, spinnerIconType]);
|
||||
|
||||
const handleClickFullscreen = () => {
|
||||
// @ts-ignore Property 'request' does not exist on type '{ isEnabled: false; }'.
|
||||
screenfull.request(findDOMNode(player.current));
|
||||
};
|
||||
|
||||
const handlePlayPause = () => {
|
||||
const handlePlayPause = useCallback(() => {
|
||||
setPlaying(!playing);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.body.style.backgroundColor = isDarkTheme
|
||||
? DARK_UI_BACKGROUND
|
||||
: LIGHT_UI_BACKGROUND;
|
||||
}, [isDarkTheme]);
|
||||
}, [playing]);
|
||||
|
||||
useEffect(() => {
|
||||
if (url !== undefined) {
|
||||
@ -157,7 +207,6 @@ function App() {
|
||||
: LIGHT_UI_BACKGROUND,
|
||||
}}
|
||||
>
|
||||
<ToggleDarkModeSwitch />
|
||||
<Row
|
||||
bottom="xs"
|
||||
style={{
|
||||
@ -189,7 +238,7 @@ function App() {
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<div id="prompt-text" style={{ fontSize: '20px' }}>
|
||||
{getPromptContent(promptStep)}
|
||||
{getPromptContent(promptStep, t)}
|
||||
</div>
|
||||
</Fade>
|
||||
</div>
|
||||
@ -221,22 +270,22 @@ function App() {
|
||||
height: '100vh',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
onClick={() => setIsWithControls(true)}
|
||||
onTouchStart={() => setIsWithControls(true)}
|
||||
>
|
||||
Help! I'm having troubles to zoom in on my device
|
||||
</Button>
|
||||
<Button onClick={handlePlayPause} onTouchStart={handlePlayPause}>
|
||||
PLAY!
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleClickFullscreen}
|
||||
onTouchStart={handleClickFullscreen}
|
||||
>
|
||||
ENTER FULL SCREEN
|
||||
</Button>
|
||||
<ToggleDarkModeSwitch />
|
||||
<PlayerControlPanel
|
||||
onSwitchChangedCallback={(isEnabled) => setIsWithControls(isEnabled)}
|
||||
isDefaultPlayerTurnedOn={isWithControls}
|
||||
handleClickFullscreen={() => {
|
||||
if (!screenfull.isEnabled) return;
|
||||
// @ts-ignore Property 'request' does not exist on type '{ isEnabled: false; }'.
|
||||
screenfull.request(findDOMNode(player.current));
|
||||
setIsFullScreenOn(!isFullScreenOn);
|
||||
}}
|
||||
handleClickPlayPause={handlePlayPause}
|
||||
isPlaying={playing}
|
||||
setVideoQuality={setVideoQuality}
|
||||
selectedVideoQuality={videoQuality}
|
||||
screenSharingSourceType={screenSharingSourceType}
|
||||
toaster={toaster}
|
||||
/>
|
||||
<div
|
||||
id="video-container"
|
||||
style={{
|
||||
@ -245,6 +294,7 @@ function App() {
|
||||
}}
|
||||
>
|
||||
<div
|
||||
id="player-wrapper-id"
|
||||
className="player-wrapper"
|
||||
style={{
|
||||
position: 'relative',
|
||||
@ -253,19 +303,12 @@ function App() {
|
||||
>
|
||||
<ReactPlayer
|
||||
ref={player}
|
||||
id="video-local-test-peer-sees"
|
||||
id={REACT_PLAYER_WRAPPER_ID}
|
||||
playing={playing}
|
||||
playsinline={true}
|
||||
controls={isWithControls}
|
||||
muted={true}
|
||||
// url={mergedStream}
|
||||
url={(url as unknown) as MediaStream}
|
||||
// width={url.getVideoTracks()[0].getSettings().width}
|
||||
// height={url.getVideoTracks()[0].getSettings().height}
|
||||
// onPlay={setProperCanvasWidth}
|
||||
// wrapper="div"
|
||||
// width={window.screen.width}
|
||||
// height={window.screen.height}
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{
|
||||
@ -278,6 +321,11 @@ function App() {
|
||||
<canvas id="comparison-canvas" style={{ display: 'none' }}></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<Toaster ref={refHandlers.toaster} position={Position.TOP_LEFT} />
|
||||
<ErrorDialog
|
||||
errorMessage={dialogErrorMessage}
|
||||
isOpen={isErrorDialogOpen}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
export enum ErrorMessage {
|
||||
UNKNOWN_ERROR = 'An unknonw error uccured.',
|
||||
DENY_TO_CONNECT = 'You were not allowed to connect.',
|
||||
DICONNECTED = 'You were disconnected.',
|
||||
NOT_ALLOWED = 'You were not allowed to connect.',
|
||||
}
|
3
app/client/src/components/ErrorDialog/index.css
Normal file
3
app/client/src/components/ErrorDialog/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
.error-dialog-backdrop {
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
70
app/client/src/components/ErrorDialog/index.tsx
Normal file
70
app/client/src/components/ErrorDialog/index.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Classes,
|
||||
Dialog,
|
||||
Divider,
|
||||
H1,
|
||||
H2,
|
||||
H3,
|
||||
Icon,
|
||||
} from '@blueprintjs/core';
|
||||
import { Col, Row } from 'react-flexbox-grid';
|
||||
import './index.css';
|
||||
import { ErrorMessage } from './ErrorMessageEnum';
|
||||
|
||||
interface ErrorDialogProps {
|
||||
isOpen: boolean;
|
||||
errorMessage: ErrorMessage;
|
||||
}
|
||||
|
||||
function ErrorDialog(props: ErrorDialogProps) {
|
||||
const { errorMessage, isOpen } = props;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
className="error-dialog"
|
||||
autoFocus
|
||||
canEscapeKeyClose
|
||||
canOutsideClickClose
|
||||
enforceFocus
|
||||
isOpen={isOpen}
|
||||
usePortal
|
||||
style={{
|
||||
width: '90%',
|
||||
maxWidth: '1200px',
|
||||
}}
|
||||
backdropClassName="error-dialog-backdrop"
|
||||
>
|
||||
<Row center="xs" style={{ marginTop: '10px' }}>
|
||||
<Col xs={12}>
|
||||
<H3 className={Classes.TEXT_MUTED}>Descreen Error Dialog</H3>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row middle="xs" center="xs" style={{ padding: '20px', width: '100%' }}>
|
||||
<Col xs={12} md={10} lg={6}>
|
||||
<Row middle="xs" center="xs">
|
||||
<Col xs={1}>
|
||||
<Icon icon="error" iconSize={52} color="#8A9BA8" />
|
||||
</Col>
|
||||
<Col xs={11}>
|
||||
<H1
|
||||
className={Classes.TEXT_DISABLED}
|
||||
style={{ marginBottom: '0px' }}
|
||||
>
|
||||
Something wrong happened :(
|
||||
</H1>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider />
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<H3 className={Classes.TEXT_MUTED}>{errorMessage}</H3>
|
||||
<Divider />
|
||||
<H2>You may close this browser window then try to connect again.</H2>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default ErrorDialog;
|
@ -1,9 +1,10 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { Callout, Card, H3, Text, Tooltip, Position } from '@blueprintjs/core';
|
||||
import { AppContext } from '../../providers/AppContextProvider';
|
||||
|
||||
const LIGHT_UI_BACKGROUND = 'rgba(240, 248, 250, 1)';
|
||||
const DARK_UI_BACKGROUND = '#293742';
|
||||
import {
|
||||
DARK_UI_BACKGROUND,
|
||||
LIGHT_UI_BACKGROUND,
|
||||
} from '../../constants/styleConstants';
|
||||
|
||||
interface MyDeviceDetailsCardProps {
|
||||
deviceDetails: DeviceDetails;
|
||||
@ -27,10 +28,18 @@ function MyDeviceInfoCard(props: MyDeviceDetailsCardProps) {
|
||||
<Callout>
|
||||
<Text>Device Type: {myDeviceType}</Text>
|
||||
<Tooltip
|
||||
content="This should match with 'Device IP' in alert displayed on your computer, where Deskreen is running."
|
||||
content="This should match with 'Device IP' in alert popup appeared on your computer, where Deskreen is running."
|
||||
position={Position.TOP}
|
||||
>
|
||||
<div style={{ fontWeight: 900, backgroundColor: '#00f99273' }}>
|
||||
<div
|
||||
style={{
|
||||
fontWeight: 900,
|
||||
backgroundColor: '#00f99273',
|
||||
paddingLeft: '10px',
|
||||
paddingRight: '10px',
|
||||
borderRadius: '20px',
|
||||
}}
|
||||
>
|
||||
<Text>Device IP: {myIP}</Text>
|
||||
</div>
|
||||
</Tooltip>
|
||||
@ -38,8 +47,8 @@ function MyDeviceInfoCard(props: MyDeviceDetailsCardProps) {
|
||||
<Text>Device OS: {myOS}</Text>
|
||||
</Callout>
|
||||
<Text className="bp3-text-muted">
|
||||
These details should match with the ones that you see in alert on
|
||||
sharing device.
|
||||
These details should match with the ones that you see in alert popup on
|
||||
screen sharing device.
|
||||
</Text>
|
||||
</Card>
|
||||
);
|
||||
|
326
app/client/src/components/PlayerControlPanel/index.tsx
Normal file
326
app/client/src/components/PlayerControlPanel/index.tsx
Normal file
@ -0,0 +1,326 @@
|
||||
import React, {
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import {
|
||||
Alignment,
|
||||
Button,
|
||||
Card,
|
||||
H5,
|
||||
Switch,
|
||||
Divider,
|
||||
Text,
|
||||
Icon,
|
||||
Tooltip,
|
||||
Position,
|
||||
Popover,
|
||||
Classes,
|
||||
Toaster,
|
||||
Intent,
|
||||
} from '@blueprintjs/core';
|
||||
import FullScreenEnter from '../../images/fullscreen_24px.svg';
|
||||
import FullScreenExit from '../../images/fullscreen_exit-24px.svg';
|
||||
import DeskreenIconPNG from '../../images/deskreen_logo_128x128.png';
|
||||
import RedHeartTwemojiPNG from '../../images/red_heart_2764_twemoji_120x120.png';
|
||||
import { Col, Row } from 'react-flexbox-grid';
|
||||
import screenfull from 'screenfull';
|
||||
import { VideoQuality } from '../../features/PeerConnection/VideoQualityEnum';
|
||||
import { REACT_PLAYER_WRAPPER_ID } from '../../constants/appConstants';
|
||||
|
||||
const videoQualityButtonStyle: React.CSSProperties = {
|
||||
width: '100%',
|
||||
textAlign: 'center',
|
||||
};
|
||||
|
||||
interface PlayerControlPanelProps {
|
||||
onSwitchChangedCallback: (isEnabled: boolean) => void;
|
||||
isPlaying: boolean;
|
||||
isDefaultPlayerTurnedOn: boolean;
|
||||
handleClickFullscreen: () => void;
|
||||
handleClickPlayPause: () => void;
|
||||
setVideoQuality: (q: VideoQuality) => void;
|
||||
selectedVideoQuality: VideoQuality;
|
||||
screenSharingSourceType: 'screen' | 'window';
|
||||
toaster: undefined | Toaster;
|
||||
}
|
||||
|
||||
function PlayerControlPanel(props: PlayerControlPanelProps) {
|
||||
|
||||
const {
|
||||
isPlaying,
|
||||
onSwitchChangedCallback,
|
||||
isDefaultPlayerTurnedOn,
|
||||
handleClickPlayPause,
|
||||
handleClickFullscreen,
|
||||
selectedVideoQuality,
|
||||
setVideoQuality,
|
||||
screenSharingSourceType,
|
||||
toaster,
|
||||
} = props;
|
||||
|
||||
const isFullScreenAPIAvailable = useMemo(() => screenfull.isEnabled, []);
|
||||
|
||||
const [isFullScreenOn, setIsFullScreenOn] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!screenfull.isEnabled) return;
|
||||
// @ts-ignore
|
||||
screenfull.on('change', () => {
|
||||
// @ts-ignore
|
||||
setIsFullScreenOn(screenfull.isFullscreen);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleClickFullscreenWhenDefaultPlayerIsOn = useCallback(() => {
|
||||
const player = document.querySelector(
|
||||
`#${REACT_PLAYER_WRAPPER_ID} > video`
|
||||
);
|
||||
if (!player) return;
|
||||
// @ts-ignore
|
||||
if (player.requestFullScreen) {
|
||||
// @ts-ignore
|
||||
player.requestFullScreen();
|
||||
// @ts-ignore
|
||||
} else if (player.webkitRequestFullScreen) {
|
||||
// @ts-ignore
|
||||
player.webkitRequestFullScreen();
|
||||
// @ts-ignore
|
||||
} else if (player.mozRequestFullScreen) {
|
||||
// @ts-ignore
|
||||
player.mozRequestFullScreen();
|
||||
// @ts-ignore
|
||||
} else if (player.msRequestFullscreen) {
|
||||
// @ts-ignore
|
||||
player.msRequestFullscreen();
|
||||
// @ts-ignore
|
||||
} else if (player.webkitEnterFullscreen) {
|
||||
// @ts-ignore
|
||||
player.webkitEnterFullscreen(); //for iphone this code worked
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card elevation={4}>
|
||||
<Row between="xs" middle="xs">
|
||||
<Col xs={12} md={3}>
|
||||
<Tooltip
|
||||
content="Click to visit our website"
|
||||
position={Position.BOTTOM}
|
||||
>
|
||||
<Button minimal>
|
||||
<Row middle="xs" style={{ opacity: '0.75' }}>
|
||||
<Col xs={4}>
|
||||
<img src={DeskreenIconPNG} width={42} height={42} alt="logo" />
|
||||
</Col>
|
||||
<Col xs={8}>
|
||||
<H5 style={{ marginBottom: '0px' }}>Deskreen</H5>
|
||||
</Col>
|
||||
</Row>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!"
|
||||
position={Position.BOTTOM}
|
||||
>
|
||||
<Button>
|
||||
<Row start="xs">
|
||||
<Col xs>
|
||||
<img
|
||||
src={RedHeartTwemojiPNG}
|
||||
width={16}
|
||||
height={16}
|
||||
style={{ transform: 'translateY(2px)' }}
|
||||
alt="heart"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs>
|
||||
<div
|
||||
style={{ transform: 'translateY(2px) translateX(-5px)' }}
|
||||
>
|
||||
<Text>Donate!</Text>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Col>
|
||||
<Col xs={12} md={6}>
|
||||
<Row center="xs" style={{ height: '42px' }}>
|
||||
<Row
|
||||
center="xs"
|
||||
middle="xs"
|
||||
style={{
|
||||
borderRadius: '20px',
|
||||
backgroundColor: '#137CBD',
|
||||
width: '190px',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<Row style={{ width: '100%' }} middle="xs" center="xs">
|
||||
<Button
|
||||
minimal
|
||||
onClick={() => {
|
||||
handleClickPlayPause();
|
||||
toaster?.show({
|
||||
icon: isPlaying ? 'pause' : 'play',
|
||||
intent: Intent.PRIMARY,
|
||||
message: isPlaying
|
||||
? 'Video stream is paused.'
|
||||
: 'Video stream is playing',
|
||||
});
|
||||
}}
|
||||
style={{
|
||||
width: '85px',
|
||||
minWidth: '70px',
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
<Row>
|
||||
<Col xs>
|
||||
<Icon
|
||||
icon={isPlaying ? 'pause' : 'play'}
|
||||
color="white"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs>
|
||||
<Text className="bp3-text-large">
|
||||
{isPlaying ? 'Pause' : 'Play'}
|
||||
</Text>
|
||||
</Col>
|
||||
</Row>
|
||||
</Button>
|
||||
<Divider
|
||||
style={{
|
||||
height: '20px',
|
||||
borderRight: '1px solid #ffffffa8',
|
||||
borderBottom: '1px solid #ffffffa8',
|
||||
}}
|
||||
/>
|
||||
{screenSharingSourceType === 'window' ? (
|
||||
<Tooltip
|
||||
content="You can't change video quality when sharing a window. You can change quality only when shering entire screen."
|
||||
position={Position.BOTTOM}
|
||||
>
|
||||
<Button minimal disabled>
|
||||
<Icon icon="cog" color="#A7B6C2" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Popover
|
||||
content={
|
||||
<>
|
||||
<H5>Video Quality:</H5>
|
||||
<Divider />
|
||||
{Object.values(VideoQuality).map(
|
||||
(q: VideoQuality) => {
|
||||
return (
|
||||
<Row>
|
||||
<Button
|
||||
minimal
|
||||
active={selectedVideoQuality === q}
|
||||
style={videoQualityButtonStyle}
|
||||
onClick={() => {
|
||||
setVideoQuality(q);
|
||||
toaster?.show({
|
||||
icon: 'clean',
|
||||
intent: Intent.PRIMARY,
|
||||
message: `Video quality has been changed to ${q}`,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{q}
|
||||
</Button>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</>
|
||||
}
|
||||
position={Position.BOTTOM}
|
||||
popoverClassName={Classes.POPOVER_CONTENT_SIZING}
|
||||
>
|
||||
<Tooltip
|
||||
content="Video Quality"
|
||||
position={Position.BOTTOM}
|
||||
>
|
||||
<Button minimal>
|
||||
<Icon icon="cog" color="white" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
)}
|
||||
<Divider
|
||||
style={{
|
||||
height: '20px',
|
||||
borderRight: '1px solid #ffffffa8',
|
||||
borderBottom: '1px solid #ffffffa8',
|
||||
}}
|
||||
/>
|
||||
<Tooltip
|
||||
content="Enter Full Screen Mode"
|
||||
position={Position.BOTTOM}
|
||||
>
|
||||
<Button
|
||||
minimal
|
||||
onClick={() => {
|
||||
if (isDefaultPlayerTurnedOn) {
|
||||
handleClickFullscreenWhenDefaultPlayerIsOn();
|
||||
} else {
|
||||
handleClickFullscreen();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={isFullScreenOn ? FullScreenExit : FullScreenEnter}
|
||||
width={16}
|
||||
height={16}
|
||||
style={{
|
||||
transform: 'scale(1.5) translateY(1px)',
|
||||
filter:
|
||||
'invert(100%) sepia(100%) saturate(0%) hue-rotate(127deg) brightness(107%) contrast(102%)',
|
||||
}}
|
||||
alt="fullscreen-toggle"
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Row>
|
||||
</Row>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={12} md={3}>
|
||||
<Row end="xs">
|
||||
<Col xs={12}>
|
||||
<Switch
|
||||
onChange={() => {
|
||||
onSwitchChangedCallback(!isDefaultPlayerTurnedOn);
|
||||
toaster?.show({
|
||||
icon: 'video',
|
||||
intent: Intent.PRIMARY,
|
||||
message: `Default video player has been turned ${
|
||||
isDefaultPlayerTurnedOn ? 'OFF' : 'ON'
|
||||
}`,
|
||||
});
|
||||
}}
|
||||
innerLabel={isDefaultPlayerTurnedOn ? 'ON' : 'OFF'}
|
||||
inline
|
||||
label={`Default Video Player`}
|
||||
alignIndicator={Alignment.RIGHT}
|
||||
checked={isDefaultPlayerTurnedOn}
|
||||
disabled={!isFullScreenAPIAvailable}
|
||||
style={{
|
||||
marginBottom: '0px',
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default PlayerControlPanel;
|
@ -1,12 +1,10 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { Icon, Text, Switch, Classes, Alignment } from '@blueprintjs/core';
|
||||
import { Row, Col } from 'react-flexbox-grid';
|
||||
import { Switch, Classes, Alignment } from '@blueprintjs/core';
|
||||
import { AppContext } from '../../providers/AppContextProvider';
|
||||
|
||||
function ToggleDarkModeSwitch() {
|
||||
const { isDarkTheme, setIsDarkThemeHook } = useContext(AppContext)
|
||||
|
||||
|
||||
return (
|
||||
<Switch
|
||||
onChange={() => {
|
||||
|
43
app/client/src/config/i18n.ts
Normal file
43
app/client/src/config/i18n.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import Backend from 'i18next-http-backend';
|
||||
|
||||
// don't want to use this?
|
||||
// have a look at the Quick start guide
|
||||
// for passing in lng and translations on init
|
||||
|
||||
i18n
|
||||
// load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
|
||||
// learn more: https://github.com/i18next/i18next-http-backend
|
||||
.use(Backend)
|
||||
// pass the i18n instance to react-i18next.
|
||||
.use(initReactI18next)
|
||||
// init i18next
|
||||
// for all options read: https://www.i18next.com/overview/configuration-options
|
||||
.init({
|
||||
// fallbackLng: 'ua',
|
||||
lng: 'en',
|
||||
saveMissing: true,
|
||||
saveMissingTo: 'all',
|
||||
fallbackLng: 'en', // TODO: to generate missing keys use false as value here, will be useful when custom nodejs server is created to store missing values
|
||||
debug: true, // change to true to see debug message logs in browser console
|
||||
whitelist: ['en', 'ru', 'ua'],
|
||||
|
||||
backend: {
|
||||
// path where resources get loaded from
|
||||
loadPath: '/locales/{{lng}}/{{ns}}.json',
|
||||
// TODO: in future implement custom nodejs server that accepts missing translations POST requests and updates .missing.json files accordingly. Here is how to do so: https://www.robinwieruch.de/react-internationalization . it can be simple nodejs server that can be started when 'yarn dev' is running, need to ckagne package.json file then
|
||||
// path to post missing resources
|
||||
addPath: '/locales/{{lng}}/{{ns}}.json',
|
||||
// jsonIndent to use when storing json files
|
||||
jsonIndent: 2,
|
||||
},
|
||||
|
||||
keySeparator: false, // we do not use keys in form messages.welcome
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // react already safes from xss
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
8
app/client/src/constants/appConstants.ts
Normal file
8
app/client/src/constants/appConstants.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const REACT_PLAYER_WRAPPER_ID = 'react-player-wrapper-id';
|
||||
export const VIDEO_QUALITY_TO_DECIMAL = {
|
||||
'25%': 0.25, // Q_25_PERCENT
|
||||
'40%': 0.40, // Q_40_PERCENT
|
||||
'60%': 0.60, // Q_60_PERCENT
|
||||
'80%': 0.80, // Q_80_PERCENT
|
||||
'100%': 1, // Q_100_PERCENT
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
export enum VideoQuality {
|
||||
Q_AUTO = 'Auto',
|
||||
Q_25_PERCENT = '25%',
|
||||
Q_40_PERCENT = '40%',
|
||||
Q_60_PERCENT = '60%',
|
||||
Q_80_PERCENT = '80%',
|
||||
Q_100_PERCENT = '100%',
|
||||
}
|
@ -10,7 +10,16 @@ import {
|
||||
import setSdpMediaBitrate from './setSdpMediaBitrate';
|
||||
import Crypto from '../../utils/crypto';
|
||||
import VideoAutoQualityOptimizer from '../VideoAutoQualityOptimizer';
|
||||
import { getBrowserFromUAParser, getDeviceTypeFromUAParser, getOSFromUAParser } from '../../utils/userAgentParserHelpers';
|
||||
import {
|
||||
getBrowserFromUAParser,
|
||||
getDeviceTypeFromUAParser,
|
||||
getOSFromUAParser,
|
||||
} from '../../utils/userAgentParserHelpers';
|
||||
import { VideoQuality } from './VideoQualityEnum';
|
||||
import prepareDataMessageToChangeQuality from './prepareDataMessageToChangeQuality';
|
||||
import { VIDEO_QUALITY_TO_DECIMAL } from './../../constants/appConstants';
|
||||
import prepareDataMessageToGetSharingSourceType from './prepareDataMessageToGetSharingSourceType';
|
||||
import { ErrorMessage } from '../../components/ErrorDialog/ErrorMessageEnum';
|
||||
|
||||
interface LocalPeerUser {
|
||||
username: string;
|
||||
@ -37,7 +46,7 @@ interface ReceiveEncryptedMessagePayload {
|
||||
keys: { sessionKey: string; signingKey: string }[];
|
||||
}
|
||||
|
||||
export default class LocalTestPeer {
|
||||
export default class PeerConnection {
|
||||
roomId: string;
|
||||
|
||||
socket: any;
|
||||
@ -48,7 +57,7 @@ export default class LocalTestPeer {
|
||||
|
||||
partner: PartnerPeerUser = nullUser;
|
||||
|
||||
peer: any;
|
||||
peer: null | SimplePeer.Instance = null;
|
||||
|
||||
myIP = '';
|
||||
|
||||
@ -72,24 +81,49 @@ export default class LocalTestPeer {
|
||||
|
||||
largeMismatchFramesCount: number;
|
||||
|
||||
isRequestedHalfQuality: boolean;
|
||||
screenSharingSourceType: string | undefined = undefined;
|
||||
|
||||
videoQuality = VideoQuality.Q_AUTO;
|
||||
|
||||
videoAutoQualityOptimizer: VideoAutoQualityOptimizer;
|
||||
|
||||
isDarkTheme: boolean;
|
||||
|
||||
isStreamStarted: boolean = false;
|
||||
|
||||
setMyDeviceDetails: (details: DeviceDetails) => void;
|
||||
|
||||
hostAllowedToConnectCallback: () => void;
|
||||
|
||||
setScreenSharingSourceTypeCallback: (s: 'screen' | 'window') => void;
|
||||
|
||||
setIsDarkThemeCallback: (val: boolean) => void;
|
||||
|
||||
setAppLanguageCallback: (newLang: string) => void;
|
||||
|
||||
setDialogErrorMessageCallback: (message: ErrorMessage) => void;
|
||||
|
||||
setIsErrorDialogOpen: (val: boolean) => void;
|
||||
|
||||
errorDialogMessage = ErrorMessage.UNKNOWN_ERROR;
|
||||
|
||||
constructor(
|
||||
setUrlCallback: any,
|
||||
crypto: Crypto,
|
||||
videoAutoQualityOptimizer: VideoAutoQualityOptimizer,
|
||||
isDarkTheme: boolean,
|
||||
setMyDeviceDetailsCallback: (details: DeviceDetails) => void,
|
||||
hostAllowedToConnectCallback: () => void
|
||||
hostAllowedToConnectCallback: () => void,
|
||||
setScreenSharingSourceTypeCallback: (s: 'screen' | 'window') => void,
|
||||
setIsDarkThemeCallback: (val: boolean) => void,
|
||||
setAppLanguageCallback: (newLang: string) => void,
|
||||
setDialogErrorMessageCallback: (message: ErrorMessage) => void,
|
||||
setIsErrorDialogOpen: (val: boolean) => void
|
||||
) {
|
||||
this.setUrlCallback = setUrlCallback;
|
||||
this.crypto = crypto;
|
||||
this.videoAutoQualityOptimizer = videoAutoQualityOptimizer;
|
||||
this.isDarkTheme = isDarkTheme;
|
||||
this.setMyDeviceDetails = setMyDeviceDetailsCallback;
|
||||
this.hostAllowedToConnectCallback = hostAllowedToConnectCallback;
|
||||
this.roomId = encodeURI(window.location.pathname.replace('/', ''));
|
||||
@ -97,15 +131,51 @@ export default class LocalTestPeer {
|
||||
this.uaParser = new UAParser();
|
||||
this.createUserAndInitSocket();
|
||||
this.createPeer();
|
||||
this.setScreenSharingSourceTypeCallback = setScreenSharingSourceTypeCallback;
|
||||
this.setIsDarkThemeCallback = setIsDarkThemeCallback;
|
||||
this.setAppLanguageCallback = setAppLanguageCallback;
|
||||
this.setDialogErrorMessageCallback = setDialogErrorMessageCallback;
|
||||
this.setIsErrorDialogOpen = setIsErrorDialogOpen;
|
||||
|
||||
this.video = null;
|
||||
this.canvas = null;
|
||||
this.largeMismatchFramesCount = 0;
|
||||
this.isRequestedHalfQuality = false;
|
||||
|
||||
if (!this.roomId || this.roomId === '') {
|
||||
setDialogErrorMessageCallback(ErrorMessage.UNKNOWN_ERROR);
|
||||
setIsErrorDialogOpen(true);
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
if (!this.socket.connected) {
|
||||
if (this.errorDialogMessage === ErrorMessage.UNKNOWN_ERROR) {
|
||||
this.setDialogErrorMessageCallback(ErrorMessage.DENY_TO_CONNECT);
|
||||
this.setIsErrorDialogOpen(true);
|
||||
this.errorDialogMessage = ErrorMessage.DENY_TO_CONNECT;
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
log(...toLog: any[]) {
|
||||
console.log('LocalTestPeer - ', ...toLog);
|
||||
setVideoQuality(videoQuality: VideoQuality) {
|
||||
this.videoQuality = videoQuality;
|
||||
this.videoQualityChangedCallback();
|
||||
}
|
||||
|
||||
setErrorDialogMessage(message: ErrorMessage) {
|
||||
this.errorDialogMessage = message;
|
||||
}
|
||||
|
||||
videoQualityChangedCallback() {
|
||||
if (this.videoQuality !== VideoQuality.Q_AUTO) {
|
||||
this.peer?.send(
|
||||
prepareDataMessageToChangeQuality(
|
||||
VIDEO_QUALITY_TO_DECIMAL[this.videoQuality]
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.peer?.send(prepareDataMessageToChangeQuality(1));
|
||||
}
|
||||
}
|
||||
|
||||
createPeer() {
|
||||
@ -127,23 +197,26 @@ export default class LocalTestPeer {
|
||||
});
|
||||
|
||||
peer.on('stream', (stream) => {
|
||||
setTimeout(() => {
|
||||
(document.querySelector(
|
||||
'#video-local-test-peer-sees'
|
||||
) as any).srcObject = stream;
|
||||
}, 1000);
|
||||
|
||||
this.videoAutoQualityOptimizer.setGoodQualityCallback(() => {
|
||||
this.peer.send('set good quality');
|
||||
if (this.videoQuality === VideoQuality.Q_AUTO) {
|
||||
this.peer?.send(prepareDataMessageToChangeQuality(1));
|
||||
}
|
||||
});
|
||||
|
||||
this.videoAutoQualityOptimizer.setHalfQualityCallbak(() => {
|
||||
this.peer.send('set half quality');
|
||||
if (this.videoQuality === VideoQuality.Q_AUTO) {
|
||||
this.peer?.send(prepareDataMessageToChangeQuality(0.5));
|
||||
}
|
||||
});
|
||||
|
||||
this.videoAutoQualityOptimizer.startOptimizationLoop();
|
||||
|
||||
this.setUrlCallback(stream);
|
||||
setTimeout(() => {
|
||||
this.peer?.send(prepareDataMessageToGetSharingSourceType());
|
||||
}, 1000);
|
||||
|
||||
this.isStreamStarted = true;
|
||||
});
|
||||
|
||||
peer.on('signal', (data) => {
|
||||
@ -156,6 +229,20 @@ export default class LocalTestPeer {
|
||||
});
|
||||
});
|
||||
|
||||
peer.on('data', (data) => {
|
||||
const dataJSON = JSON.parse(data);
|
||||
|
||||
if (dataJSON.type === 'screen_sharing_source_type') {
|
||||
this.screenSharingSourceType = dataJSON.payload.value;
|
||||
if (
|
||||
this.screenSharingSourceType === 'screen' ||
|
||||
this.screenSharingSourceType === 'window'
|
||||
) {
|
||||
this.setScreenSharingSourceTypeCallback(this.screenSharingSourceType);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.peer = peer;
|
||||
}
|
||||
|
||||
@ -193,7 +280,6 @@ export default class LocalTestPeer {
|
||||
if (!this.user) return;
|
||||
if (!this.partner) return;
|
||||
const msg = (await prepareMessage(payload, this.user, this.partner)) as any;
|
||||
this.log('encrypted message', msg);
|
||||
this.socket.emit('ENCRYPTED_MESSAGE', msg.toSend);
|
||||
}
|
||||
|
||||
@ -204,18 +290,34 @@ export default class LocalTestPeer {
|
||||
this.user.privateKey
|
||||
)) as any;
|
||||
if (message.type === 'CALL_USER') {
|
||||
this.log('ACCEPTING CALL USER', message);
|
||||
this.peer.signal(message.payload.signalData);
|
||||
this.peer?.signal(message.payload.signalData);
|
||||
}
|
||||
if (message.type === 'DENY_TO_CONNECT') {
|
||||
this.log('OH NO, deny to connect...');
|
||||
if (this.errorDialogMessage === ErrorMessage.UNKNOWN_ERROR) {
|
||||
this.setDialogErrorMessageCallback(ErrorMessage.DENY_TO_CONNECT);
|
||||
this.setIsErrorDialogOpen(true);
|
||||
this.errorDialogMessage = ErrorMessage.DENY_TO_CONNECT;
|
||||
}
|
||||
}
|
||||
if (message.type === 'DISCONNECT_BY_HOST_MACHINE_USER') {
|
||||
this.log('DAMN, you were disconnected by host machine user!');
|
||||
if (this.errorDialogMessage === ErrorMessage.UNKNOWN_ERROR) {
|
||||
this.setDialogErrorMessageCallback(ErrorMessage.DICONNECTED);
|
||||
this.setIsErrorDialogOpen(true);
|
||||
this.errorDialogMessage = ErrorMessage.DICONNECTED;
|
||||
}
|
||||
}
|
||||
if (message.type === 'ALLOWED_TO_CONNECT') {
|
||||
this.hostAllowedToConnectCallback();
|
||||
}
|
||||
if (message.type === 'APP_THEME') {
|
||||
if (this.isDarkTheme !== message.payload.value) {
|
||||
this.setIsDarkThemeCallback(message.payload.value);
|
||||
this.isDarkTheme = message.payload.value;
|
||||
}
|
||||
}
|
||||
if (message.type === 'APP_LANGUAGE') {
|
||||
this.setAppLanguageCallback(message.payload.value);
|
||||
}
|
||||
}
|
||||
|
||||
createUserAndInitSocket() {
|
||||
@ -228,36 +330,33 @@ export default class LocalTestPeer {
|
||||
|
||||
this.socket.on('disconnect', () => {
|
||||
// this.props.toggleSocketConnected(false);
|
||||
if (this.errorDialogMessage === ErrorMessage.UNKNOWN_ERROR) {
|
||||
this.setDialogErrorMessageCallback(ErrorMessage.DICONNECTED);
|
||||
this.setIsErrorDialogOpen(true);
|
||||
this.errorDialogMessage = ErrorMessage.DICONNECTED;
|
||||
}
|
||||
});
|
||||
|
||||
this.socket.on('connect', () => {
|
||||
this.socket.emit('GET_MY_IP', (ip: string) => {
|
||||
// TODO: use set ip callback here, that will change the UI of react component
|
||||
// @ts-ignore
|
||||
// document.querySelector('#my-ip')?.innerHTML = ip;
|
||||
this.myIP = ip;
|
||||
this.uaParser.setUA(window.navigator.userAgent);
|
||||
// const osFromUAParser = this.uaParser.getResult().os;
|
||||
// const deviceTypeFromUAParser = this.uaParser.getResult().device;
|
||||
// const browserFromUAParser = this.uaParser.getResult().browser;
|
||||
|
||||
// this.myOS = `${osFromUAParser.name ? osFromUAParser.name : ''} ${
|
||||
// osFromUAParser.version ? osFromUAParser.version : ''
|
||||
// }`;
|
||||
// this.myDeviceType = deviceTypeFromUAParser.type
|
||||
// ? deviceTypeFromUAParser.type.toString()
|
||||
// : 'computer';
|
||||
this.myOS = getOSFromUAParser(this.uaParser);
|
||||
this.myDeviceType = getDeviceTypeFromUAParser(this.uaParser);
|
||||
// this.myBrowser = `${browserFromUAParser.name ? browserFromUAParser.name : ''} ${
|
||||
// browserFromUAParser.version ? browserFromUAParser.version : ''
|
||||
// }`;
|
||||
this.myBrowser = getBrowserFromUAParser(this.uaParser);
|
||||
|
||||
this.initApp(createdUser, ip);
|
||||
});
|
||||
});
|
||||
|
||||
this.socket.on('NOT_ALLOWED', () => {
|
||||
if (this.errorDialogMessage === ErrorMessage.UNKNOWN_ERROR) {
|
||||
this.setDialogErrorMessageCallback(ErrorMessage.NOT_ALLOWED);
|
||||
this.setIsErrorDialogOpen(true);
|
||||
this.errorDialogMessage = ErrorMessage.NOT_ALLOWED;
|
||||
}
|
||||
});
|
||||
|
||||
this.socket.on('USER_ENTER', (payload: { users: PartnerPeerUser[] }) => {
|
||||
const filteredPartner = payload.users.filter((v) => {
|
||||
return createdUser.publicKey !== v.publicKey;
|
||||
@ -288,6 +387,9 @@ export default class LocalTestPeer {
|
||||
},
|
||||
});
|
||||
|
||||
this.sendEncryptedMessage({ type: 'GET_APP_THEME', payload: {} });
|
||||
this.sendEncryptedMessage({ type: 'GET_APP_LANGUAGE', payload: {} });
|
||||
|
||||
setTimeout(() => {
|
||||
this.setMyDeviceDetails({
|
||||
myIP: this.myIP,
|
||||
@ -313,6 +415,11 @@ export default class LocalTestPeer {
|
||||
// TODO: call ROOM LOCKED callback to change react component contain ROOM LOCKED message
|
||||
// @ts-ignore
|
||||
// document.querySelector('#my-ip')?.innerHTML = 'ROOM LOCKED';
|
||||
if (this.errorDialogMessage === ErrorMessage.UNKNOWN_ERROR) {
|
||||
this.setDialogErrorMessageCallback(ErrorMessage.DENY_TO_CONNECT);
|
||||
this.setIsErrorDialogOpen(true);
|
||||
this.errorDialogMessage = ErrorMessage.UNKNOWN_ERROR;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('beforeunload', (_) => {
|
||||
|
@ -0,0 +1,10 @@
|
||||
export default (q: number) => {
|
||||
return `
|
||||
{
|
||||
"type": "set_video_quality",
|
||||
"payload": {
|
||||
"value": ${q}
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
export default () => {
|
||||
return `
|
||||
{
|
||||
"type": "get_sharing_source_type",
|
||||
"payload": {
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
import pixelmatch from 'pixelmatch';
|
||||
import { REACT_PLAYER_WRAPPER_ID } from '../../constants/appConstants';
|
||||
|
||||
export default class VideoAutoQualityOptimizer {
|
||||
video: any;
|
||||
@ -15,8 +16,6 @@ export default class VideoAutoQualityOptimizer {
|
||||
|
||||
halfQualityCallbak = () => {};
|
||||
|
||||
constructor() {}
|
||||
|
||||
setGoodQualityCallback(callback: () => void) {
|
||||
this.goodQualityCallback = callback;
|
||||
}
|
||||
@ -66,13 +65,11 @@ export default class VideoAutoQualityOptimizer {
|
||||
} else if (mismatchInPercent < 0.1 && this.isRequestedHalfQuality) {
|
||||
this.largeMismatchFramesCount = 0;
|
||||
this.isRequestedHalfQuality = false;
|
||||
// this.peer.send('set good quality');
|
||||
this.goodQualityCallback();
|
||||
} else if (mismatchInPercent >= 0.1 && !this.isRequestedHalfQuality) {
|
||||
if (this.largeMismatchFramesCount < 3) {
|
||||
this.largeMismatchFramesCount += 1;
|
||||
} else {
|
||||
// this.peer.send('set half quality');
|
||||
this.halfQualityCallbak();
|
||||
this.isRequestedHalfQuality = true;
|
||||
}
|
||||
@ -85,7 +82,7 @@ export default class VideoAutoQualityOptimizer {
|
||||
imageData = null;
|
||||
} else {
|
||||
this.video = document.querySelector(
|
||||
'#video-local-test-peer-sees > video'
|
||||
`#${REACT_PLAYER_WRAPPER_ID} > video`
|
||||
);
|
||||
this.canvas = document.getElementById('comparison-canvas');
|
||||
}
|
||||
|
BIN
app/client/src/images/deskreen_logo_128x128.png
Executable file
BIN
app/client/src/images/deskreen_logo_128x128.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
1
app/client/src/images/fullscreen_24px.svg
Normal file
1
app/client/src/images/fullscreen_24px.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>
|
After Width: | Height: | Size: 216 B |
1
app/client/src/images/fullscreen_exit-24px.svg
Normal file
1
app/client/src/images/fullscreen_exit-24px.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></svg>
|
After Width: | Height: | Size: 215 B |
BIN
app/client/src/images/red_heart_2764_twemoji_120x120.png
Normal file
BIN
app/client/src/images/red_heart_2764_twemoji_120x120.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import React, { Suspense } from 'react';
|
||||
import './config/i18n';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
@ -8,7 +9,9 @@ import { AppContextProvider } from './providers/AppContextProvider';
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<AppContextProvider>
|
||||
<App />
|
||||
<Suspense fallback="loading">
|
||||
<App />
|
||||
</Suspense>
|
||||
</AppContextProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
|
@ -1,7 +1,10 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
// export const LIGHT_UI_BACKGROUND = 'rgba(240, 248, 250, 1)';
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
DARK_UI_BACKGROUND,
|
||||
LIGHT_UI_BACKGROUND,
|
||||
} from '../../constants/styleConstants';
|
||||
|
||||
interface AppContextInterface {
|
||||
isDarkTheme: boolean;
|
||||
@ -19,34 +22,27 @@ export const AppContext = React.createContext<AppContextInterface>(
|
||||
|
||||
export const AppContextProvider: React.FC = ({ children }) => {
|
||||
const [isDarkTheme, setIsDarkTheme] = useState(false);
|
||||
|
||||
const getThemeFromHost = () => {
|
||||
// const gotIsDarkThemeFromSettings = settings.hasSync('appIsDarkTheme')
|
||||
// ? settings.getSync('appIsDarkTheme') === 'true'
|
||||
// : false;
|
||||
|
||||
// if (gotIsDarkThemeFromSettings) {
|
||||
// document.body.classList.toggle(Classes.DARK);
|
||||
// document.body.style.backgroundColor = LIGHT_UI_BACKGROUND;
|
||||
// }
|
||||
|
||||
// setIsDarkTheme(gotIsDarkThemeFromSettings);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getThemeFromHost();
|
||||
}, []);
|
||||
const [appLanguage, setAppLanguage] = useState('en');
|
||||
|
||||
const setIsDarkThemeHook = (val: boolean) => {
|
||||
// settings.setSync('appIsDarkTheme', `${val}`);
|
||||
setIsDarkTheme(val);
|
||||
document.body.classList.toggle(Classes.DARK);
|
||||
|
||||
document.body.style.backgroundColor = val
|
||||
? DARK_UI_BACKGROUND
|
||||
: LIGHT_UI_BACKGROUND;
|
||||
setIsDarkTheme(val);
|
||||
};
|
||||
|
||||
const value = { isDarkTheme, setIsDarkThemeHook };
|
||||
const setAppLanguageHook = (newLang: string) => {
|
||||
setAppLanguage(newLang);
|
||||
};
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={value}>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
const value = {
|
||||
isDarkTheme,
|
||||
setIsDarkThemeHook,
|
||||
appLanguage,
|
||||
setAppLanguageHook,
|
||||
};
|
||||
|
||||
return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
|
||||
};
|
||||
|
@ -1122,7 +1122,7 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.5.5":
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5":
|
||||
version "7.12.5"
|
||||
resolved "https://packages.deskreen.com/@babel%2fruntime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
|
||||
integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==
|
||||
@ -5535,6 +5535,13 @@ html-minifier-terser@^5.0.1:
|
||||
relateurl "^0.2.7"
|
||||
terser "^4.6.3"
|
||||
|
||||
html-parse-stringify2@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://packages.deskreen.com/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz#dc5670b7292ca158b7bc916c9a6735ac8872834a"
|
||||
integrity sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=
|
||||
dependencies:
|
||||
void-elements "^2.0.1"
|
||||
|
||||
html-webpack-plugin@4.0.0-beta.11:
|
||||
version "4.0.0-beta.11"
|
||||
resolved "https://packages.deskreen.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz#3059a69144b5aecef97708196ca32f9e68677715"
|
||||
@ -5634,6 +5641,20 @@ https-browserify@^1.0.0:
|
||||
resolved "https://packages.deskreen.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
|
||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
||||
|
||||
i18next-http-backend@^1.0.21:
|
||||
version "1.0.21"
|
||||
resolved "https://packages.deskreen.com/i18next-http-backend/-/i18next-http-backend-1.0.21.tgz#cee901b3527dad5165fa91de973b6aa6404c1c37"
|
||||
integrity sha512-UDeHoV2B+31Gr++0KFAVjM5l+SEwePpF6sfDyaDq5ennM9QNJ78PBEMPStwkreEm4h5C8sT7M1JdNQrLcU1Wdg==
|
||||
dependencies:
|
||||
node-fetch "2.6.1"
|
||||
|
||||
i18next@^19.8.4:
|
||||
version "19.8.4"
|
||||
resolved "https://packages.deskreen.com/i18next/-/i18next-19.8.4.tgz#447718f2a26319b8debdbcc6fbc1a9761be7316b"
|
||||
integrity sha512-FfVPNWv+felJObeZ6DSXZkj9QM1Ivvh7NcFCgA8XPtJWHz0iXVa9BUy+QY8EPrCLE+vWgDfV/sc96BgXVo6HAA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.0"
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://packages.deskreen.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
@ -7418,6 +7439,11 @@ no-case@^3.0.3:
|
||||
lower-case "^2.0.1"
|
||||
tslib "^1.10.0"
|
||||
|
||||
node-fetch@2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://packages.deskreen.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
node-forge@0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://packages.deskreen.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
|
||||
@ -9116,6 +9142,14 @@ react-flexbox-grid@^2.1.2:
|
||||
flexboxgrid2 "^7.2.0"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
react-i18next@^11.7.4:
|
||||
version "11.7.4"
|
||||
resolved "https://packages.deskreen.com/react-i18next/-/react-i18next-11.7.4.tgz#6c0142e15652d8dd80cd7d857e36efe2e9d4d09a"
|
||||
integrity sha512-Aq0+QVW7NMYuAtk0Stcwp4jWeNTd1p5XefAfBPcjs/4c/2duG3v3G3zdtn8fC8L4EyA/coKLwdULHI+lYTbF8w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
html-parse-stringify2 "2.0.1"
|
||||
|
||||
react-is@^16.12.0, react-is@^16.8.1, react-is@^16.8.4:
|
||||
version "16.13.1"
|
||||
resolved "https://packages.deskreen.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
@ -10967,6 +11001,11 @@ vm-browserify@^1.0.1:
|
||||
resolved "https://packages.deskreen.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
|
||||
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
|
||||
|
||||
void-elements@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://packages.deskreen.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
||||
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
|
||||
|
||||
w3c-hr-time@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://packages.deskreen.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
|
||||
|
@ -49,7 +49,15 @@ export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) {
|
||||
Device Type: <span>{deviceType}</span>
|
||||
</Text>
|
||||
<Tooltip content={getContentOfTooltip()} position={Position.TOP}>
|
||||
<div style={{ fontWeight: 900, backgroundColor: '#00f99273' }}>
|
||||
<div
|
||||
style={{
|
||||
fontWeight: 900,
|
||||
backgroundColor: '#00f99273',
|
||||
paddingLeft: '10px',
|
||||
paddingRight: '10px',
|
||||
borderRadius: '20px',
|
||||
}}
|
||||
>
|
||||
<Text className="bp3-text-large">
|
||||
Device IP: <span className="device-ip-span">{deviceIP}</span>
|
||||
</Text>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { remote } from 'electron';
|
||||
import React, { useContext, useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
Button,
|
||||
@ -17,13 +18,14 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Row } from 'react-flexbox-grid';
|
||||
import { createStyles, makeStyles } from '@material-ui/core/styles';
|
||||
import i18n from 'i18next';
|
||||
import SharingSessionsService from '../../features/SharingSessionsService';
|
||||
import {
|
||||
DARK_UI_BACKGROUND,
|
||||
LIGHT_UI_BACKGROUND,
|
||||
SettingsContext,
|
||||
} from '../../containers/SettingsProvider';
|
||||
import CloseOverlayButton from '../CloseOverlayButton';
|
||||
import {
|
||||
import i18n_client, {
|
||||
getLangFullNameToLangISOKeyMap,
|
||||
getLangISOKeyToLangFullNameMap,
|
||||
} from '../../configs/i18next.config.client';
|
||||
@ -32,6 +34,10 @@ import SettingRowLabelAndInput from './SettingRowLabelAndInput';
|
||||
|
||||
const Fade = require('react-reveal/Fade');
|
||||
|
||||
const sharingSessionsService = remote.getGlobal(
|
||||
'sharingSessionService'
|
||||
) as SharingSessionsService;
|
||||
|
||||
interface SettingsOverlayProps {
|
||||
isSettingsOpen: boolean;
|
||||
handleClose: () => void;
|
||||
@ -57,7 +63,11 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
|
||||
|
||||
const { handleClose, isSettingsOpen } = props;
|
||||
|
||||
const { isDarkTheme, setIsDarkThemeHook } = useContext(SettingsContext);
|
||||
const {
|
||||
isDarkTheme,
|
||||
setIsDarkThemeHook,
|
||||
setCurrentLanguageHook,
|
||||
} = useContext(SettingsContext);
|
||||
|
||||
const [languagesList, setLanguagesList] = useState([] as string[]);
|
||||
|
||||
@ -67,7 +77,8 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
|
||||
tmp.push(key);
|
||||
});
|
||||
setLanguagesList(tmp);
|
||||
}, []);
|
||||
setCurrentLanguageHook(i18n_client.language);
|
||||
}, [setCurrentLanguageHook]);
|
||||
|
||||
const getClassesCallback = useStylesWithTheme(isDarkTheme);
|
||||
|
||||
@ -76,6 +87,11 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
|
||||
document.body.classList.toggle(Classes.DARK);
|
||||
setIsDarkThemeHook(true);
|
||||
}
|
||||
// TODO: call sharing sessions service here to notify all connected clients about theme change
|
||||
sharingSessionsService.sharingSessions.forEach((sharingSession) => {
|
||||
sharingSession?.appThemeChanged(true);
|
||||
});
|
||||
sharingSessionsService.setAppTheme(true);
|
||||
}, [isDarkTheme, setIsDarkThemeHook]);
|
||||
|
||||
const handleToggleLightTheme = useCallback(() => {
|
||||
@ -83,6 +99,11 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
|
||||
document.body.classList.toggle(Classes.DARK);
|
||||
setIsDarkThemeHook(false);
|
||||
}
|
||||
// TODO: call sharing sessions service here to notify all connected clients about theme change
|
||||
sharingSessionsService.sharingSessions.forEach((sharingSession) => {
|
||||
sharingSession?.appThemeChanged(false);
|
||||
});
|
||||
sharingSessionsService.setAppTheme(false);
|
||||
}, [isDarkTheme, setIsDarkThemeHook]);
|
||||
|
||||
const onChangeLangueageHTMLSelectHandler = (
|
||||
@ -92,10 +113,15 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
|
||||
event.currentTarget &&
|
||||
getLangFullNameToLangISOKeyMap().has(event.currentTarget.value)
|
||||
) {
|
||||
i18n.changeLanguage(
|
||||
const newLang =
|
||||
getLangFullNameToLangISOKeyMap().get(event.currentTarget.value) ||
|
||||
'English'
|
||||
);
|
||||
'English';
|
||||
i18n.changeLanguage(newLang);
|
||||
// TODO: call sharing sessions service here to notify all connected clients about language change
|
||||
sharingSessionsService.sharingSessions.forEach((sharingSession) => {
|
||||
sharingSession?.appLanguageChanged(newLang);
|
||||
});
|
||||
sharingSessionsService.setAppLanguage(newLang);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -67,15 +67,15 @@ exports[`should match exact snapshot 1`] = `
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
class="makeStyles-overlayInnerRoot-8 bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
|
||||
class="makeStyles-overlayInnerRoot-21 bp3-overlay-content bp3-overlay-appear-active"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="react-reveal makeStyles-overlayInsideFade-9 bp3-card"
|
||||
class="react-reveal makeStyles-overlayInsideFade-22 bp3-card"
|
||||
id="settings-overlay-inner"
|
||||
>
|
||||
<button
|
||||
class="bp3-button makeStyles-closeButton-13 makeStyles-absoluteCloseButton-10"
|
||||
class="bp3-button makeStyles-closeButton-13 makeStyles-absoluteCloseButton-23"
|
||||
id="close-overlay-button"
|
||||
type="button"
|
||||
>
|
||||
@ -112,7 +112,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
<div
|
||||
class="bp3-tab-indicator-wrapper"
|
||||
style="height: 0px; transform: translateX(0px) translateY(0px); width: 0px; transition: none;"
|
||||
style="height: 0px; transform: translateX(0px) translateY(0px); width: 0px;"
|
||||
>
|
||||
<div
|
||||
class="bp3-tab-indicator"
|
||||
@ -131,10 +131,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
|
||||
<div
|
||||
class="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
class="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-wrench makeStyles-iconInTablLeftButton-12"
|
||||
class="bp3-icon bp3-icon-wrench makeStyles-iconInTablLeftButton-25"
|
||||
icon="wrench"
|
||||
>
|
||||
<svg
|
||||
@ -172,10 +172,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
|
||||
<div
|
||||
class="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
class="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-shield makeStyles-iconInTablLeftButton-12"
|
||||
class="bp3-icon bp3-icon-shield makeStyles-iconInTablLeftButton-25"
|
||||
icon="shield"
|
||||
>
|
||||
<svg
|
||||
@ -212,10 +212,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
|
||||
<div
|
||||
class="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
class="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-blocked-person makeStyles-iconInTablLeftButton-12"
|
||||
class="bp3-icon bp3-icon-blocked-person makeStyles-iconInTablLeftButton-25"
|
||||
icon="blocked-person"
|
||||
>
|
||||
<svg
|
||||
@ -267,13 +267,13 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="col-xs-6"
|
||||
>
|
||||
<div
|
||||
class="makeStyles-oneSettingRow-20 row middle-xs"
|
||||
class="makeStyles-oneSettingRow-26 row middle-xs"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-style makeStyles-settingRowIcon-21"
|
||||
class="bp3-icon bp3-icon-style makeStyles-settingRowIcon-27"
|
||||
icon="style"
|
||||
>
|
||||
<svg
|
||||
@ -381,13 +381,13 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="col-xs-6"
|
||||
>
|
||||
<div
|
||||
class="makeStyles-oneSettingRow-22 row middle-xs"
|
||||
class="makeStyles-oneSettingRow-28 row middle-xs"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-translate makeStyles-settingRowIcon-23"
|
||||
class="bp3-icon bp3-icon-translate makeStyles-settingRowIcon-29"
|
||||
icon="translate"
|
||||
>
|
||||
<svg
|
||||
@ -473,13 +473,13 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="col-xs-6"
|
||||
>
|
||||
<div
|
||||
class="makeStyles-oneSettingRow-24 row middle-xs"
|
||||
class="makeStyles-oneSettingRow-30 row middle-xs"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-automatic-updates makeStyles-settingRowIcon-25"
|
||||
class="bp3-icon bp3-icon-automatic-updates makeStyles-settingRowIcon-31"
|
||||
icon="automatic-updates"
|
||||
>
|
||||
<svg
|
||||
@ -516,7 +516,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="row"
|
||||
>
|
||||
<label
|
||||
class="bp3-control bp3-checkbox makeStyles-checkboxSettings-7"
|
||||
class="bp3-control bp3-checkbox makeStyles-checkboxSettings-20"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
@ -552,15 +552,15 @@ exports[`should match exact snapshot 1`] = `
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
class="makeStyles-overlayInnerRoot-8 bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
|
||||
class="makeStyles-overlayInnerRoot-21 bp3-overlay-content bp3-overlay-appear-active"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="react-reveal makeStyles-overlayInsideFade-9 bp3-card"
|
||||
class="react-reveal makeStyles-overlayInsideFade-22 bp3-card"
|
||||
id="settings-overlay-inner"
|
||||
>
|
||||
<button
|
||||
class="bp3-button makeStyles-closeButton-13 makeStyles-absoluteCloseButton-10"
|
||||
class="bp3-button makeStyles-closeButton-13 makeStyles-absoluteCloseButton-23"
|
||||
id="close-overlay-button"
|
||||
type="button"
|
||||
>
|
||||
@ -597,7 +597,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
<div
|
||||
class="bp3-tab-indicator-wrapper"
|
||||
style="height: 0px; transform: translateX(0px) translateY(0px); width: 0px; transition: none;"
|
||||
style="height: 0px; transform: translateX(0px) translateY(0px); width: 0px;"
|
||||
>
|
||||
<div
|
||||
class="bp3-tab-indicator"
|
||||
@ -616,10 +616,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
|
||||
<div
|
||||
class="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
class="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-wrench makeStyles-iconInTablLeftButton-12"
|
||||
class="bp3-icon bp3-icon-wrench makeStyles-iconInTablLeftButton-25"
|
||||
icon="wrench"
|
||||
>
|
||||
<svg
|
||||
@ -657,10 +657,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
|
||||
<div
|
||||
class="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
class="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-shield makeStyles-iconInTablLeftButton-12"
|
||||
class="bp3-icon bp3-icon-shield makeStyles-iconInTablLeftButton-25"
|
||||
icon="shield"
|
||||
>
|
||||
<svg
|
||||
@ -697,10 +697,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
|
||||
<div
|
||||
class="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
class="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-blocked-person makeStyles-iconInTablLeftButton-12"
|
||||
class="bp3-icon bp3-icon-blocked-person makeStyles-iconInTablLeftButton-25"
|
||||
icon="blocked-person"
|
||||
>
|
||||
<svg
|
||||
@ -752,13 +752,13 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="col-xs-6"
|
||||
>
|
||||
<div
|
||||
class="makeStyles-oneSettingRow-20 row middle-xs"
|
||||
class="makeStyles-oneSettingRow-26 row middle-xs"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-style makeStyles-settingRowIcon-21"
|
||||
class="bp3-icon bp3-icon-style makeStyles-settingRowIcon-27"
|
||||
icon="style"
|
||||
>
|
||||
<svg
|
||||
@ -866,13 +866,13 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="col-xs-6"
|
||||
>
|
||||
<div
|
||||
class="makeStyles-oneSettingRow-22 row middle-xs"
|
||||
class="makeStyles-oneSettingRow-28 row middle-xs"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-translate makeStyles-settingRowIcon-23"
|
||||
class="bp3-icon bp3-icon-translate makeStyles-settingRowIcon-29"
|
||||
icon="translate"
|
||||
>
|
||||
<svg
|
||||
@ -958,13 +958,13 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="col-xs-6"
|
||||
>
|
||||
<div
|
||||
class="makeStyles-oneSettingRow-24 row middle-xs"
|
||||
class="makeStyles-oneSettingRow-30 row middle-xs"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="bp3-icon bp3-icon-automatic-updates makeStyles-settingRowIcon-25"
|
||||
class="bp3-icon bp3-icon-automatic-updates makeStyles-settingRowIcon-31"
|
||||
icon="automatic-updates"
|
||||
>
|
||||
<svg
|
||||
@ -1001,7 +1001,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
class="row"
|
||||
>
|
||||
<label
|
||||
class="bp3-control bp3-checkbox makeStyles-checkboxSettings-7"
|
||||
class="bp3-control bp3-checkbox makeStyles-checkboxSettings-20"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
@ -1035,7 +1035,6 @@ exports[`should match exact snapshot 1`] = `
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
<CSSTransition
|
||||
appear={true}
|
||||
classNames="bp3-overlay"
|
||||
in={true}
|
||||
key=".$__backdrop"
|
||||
@ -1043,7 +1042,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
timeout={0}
|
||||
>
|
||||
<Transition
|
||||
appear={true}
|
||||
appear={false}
|
||||
enter={true}
|
||||
exit={true}
|
||||
in={true}
|
||||
@ -1065,7 +1064,6 @@ exports[`should match exact snapshot 1`] = `
|
||||
</Transition>
|
||||
</CSSTransition>
|
||||
<CSSTransition
|
||||
appear={true}
|
||||
classNames="bp3-overlay"
|
||||
in={true}
|
||||
key=".$.0"
|
||||
@ -1073,7 +1071,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
timeout={0}
|
||||
>
|
||||
<Transition
|
||||
appear={true}
|
||||
appear={false}
|
||||
enter={true}
|
||||
exit={true}
|
||||
in={true}
|
||||
@ -1088,7 +1086,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
unmountOnExit={false}
|
||||
>
|
||||
<div
|
||||
className="makeStyles-overlayInnerRoot-8 bp3-overlay-content"
|
||||
className="makeStyles-overlayInnerRoot-21 bp3-overlay-content"
|
||||
tabIndex={0}
|
||||
>
|
||||
<Fade
|
||||
@ -1125,7 +1123,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
refProp="ref"
|
||||
>
|
||||
<div
|
||||
className="react-reveal makeStyles-overlayInsideFade-9 bp3-card"
|
||||
className="react-reveal makeStyles-overlayInsideFade-22 bp3-card"
|
||||
id="settings-overlay-inner"
|
||||
style={
|
||||
Object {
|
||||
@ -1134,17 +1132,17 @@ exports[`should match exact snapshot 1`] = `
|
||||
}
|
||||
>
|
||||
<CloseOverlayButton
|
||||
className="makeStyles-absoluteCloseButton-10"
|
||||
className="makeStyles-absoluteCloseButton-23"
|
||||
isDefaultStyles={true}
|
||||
onClick={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="makeStyles-closeButton-13 makeStyles-absoluteCloseButton-10"
|
||||
className="makeStyles-closeButton-13 makeStyles-absoluteCloseButton-23"
|
||||
id="close-overlay-button"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<button
|
||||
className="bp3-button makeStyles-closeButton-13 makeStyles-absoluteCloseButton-10"
|
||||
className="bp3-button makeStyles-closeButton-13 makeStyles-absoluteCloseButton-23"
|
||||
id="close-overlay-button"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
@ -1213,7 +1211,6 @@ exports[`should match exact snapshot 1`] = `
|
||||
Object {
|
||||
"height": 0,
|
||||
"transform": "translateX(0px) translateY(0px)",
|
||||
"transition": "none",
|
||||
"width": 0,
|
||||
}
|
||||
}
|
||||
@ -1245,18 +1242,18 @@ exports[`should match exact snapshot 1`] = `
|
||||
tabIndex={0}
|
||||
>
|
||||
<Row
|
||||
className="makeStyles-tabNavigationRowButton-11"
|
||||
className="makeStyles-tabNavigationRowButton-24"
|
||||
middle="xs"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
className="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-iconInTablLeftButton-12"
|
||||
className="makeStyles-iconInTablLeftButton-25"
|
||||
icon="wrench"
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-wrench makeStyles-iconInTablLeftButton-12"
|
||||
className="bp3-icon bp3-icon-wrench makeStyles-iconInTablLeftButton-25"
|
||||
icon="wrench"
|
||||
>
|
||||
<svg
|
||||
@ -1312,18 +1309,18 @@ exports[`should match exact snapshot 1`] = `
|
||||
tabIndex={0}
|
||||
>
|
||||
<Row
|
||||
className="makeStyles-tabNavigationRowButton-11"
|
||||
className="makeStyles-tabNavigationRowButton-24"
|
||||
middle="xs"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
className="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-iconInTablLeftButton-12"
|
||||
className="makeStyles-iconInTablLeftButton-25"
|
||||
icon="shield"
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-shield makeStyles-iconInTablLeftButton-12"
|
||||
className="bp3-icon bp3-icon-shield makeStyles-iconInTablLeftButton-25"
|
||||
icon="shield"
|
||||
>
|
||||
<svg
|
||||
@ -1377,18 +1374,18 @@ exports[`should match exact snapshot 1`] = `
|
||||
role="tab"
|
||||
>
|
||||
<Row
|
||||
className="makeStyles-tabNavigationRowButton-11"
|
||||
className="makeStyles-tabNavigationRowButton-24"
|
||||
middle="xs"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-tabNavigationRowButton-11 row middle-xs"
|
||||
className="makeStyles-tabNavigationRowButton-24 row middle-xs"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-iconInTablLeftButton-12"
|
||||
className="makeStyles-iconInTablLeftButton-25"
|
||||
icon="blocked-person"
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-blocked-person makeStyles-iconInTablLeftButton-12"
|
||||
className="bp3-icon bp3-icon-blocked-person makeStyles-iconInTablLeftButton-25"
|
||||
icon="blocked-person"
|
||||
>
|
||||
<svg
|
||||
@ -1492,23 +1489,23 @@ exports[`should match exact snapshot 1`] = `
|
||||
className="col-xs-6"
|
||||
>
|
||||
<Row
|
||||
className="makeStyles-oneSettingRow-20"
|
||||
className="makeStyles-oneSettingRow-26"
|
||||
middle="xs"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-oneSettingRow-20 row middle-xs"
|
||||
className="makeStyles-oneSettingRow-26 row middle-xs"
|
||||
>
|
||||
<Col>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-settingRowIcon-21"
|
||||
className="makeStyles-settingRowIcon-27"
|
||||
icon="style"
|
||||
iconSize={25}
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-style makeStyles-settingRowIcon-21"
|
||||
className="bp3-icon bp3-icon-style makeStyles-settingRowIcon-27"
|
||||
icon="style"
|
||||
>
|
||||
<svg
|
||||
@ -1701,23 +1698,23 @@ exports[`should match exact snapshot 1`] = `
|
||||
className="col-xs-6"
|
||||
>
|
||||
<Row
|
||||
className="makeStyles-oneSettingRow-22"
|
||||
className="makeStyles-oneSettingRow-28"
|
||||
middle="xs"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-oneSettingRow-22 row middle-xs"
|
||||
className="makeStyles-oneSettingRow-28 row middle-xs"
|
||||
>
|
||||
<Col>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-settingRowIcon-23"
|
||||
className="makeStyles-settingRowIcon-29"
|
||||
icon="translate"
|
||||
iconSize={25}
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-translate makeStyles-settingRowIcon-23"
|
||||
className="bp3-icon bp3-icon-translate makeStyles-settingRowIcon-29"
|
||||
icon="translate"
|
||||
>
|
||||
<svg
|
||||
@ -1840,7 +1837,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
input={
|
||||
<Blueprint3.Checkbox
|
||||
checked={true}
|
||||
className="makeStyles-checkboxSettings-7"
|
||||
className="makeStyles-checkboxSettings-20"
|
||||
label="Enabled"
|
||||
/>
|
||||
}
|
||||
@ -1860,23 +1857,23 @@ exports[`should match exact snapshot 1`] = `
|
||||
className="col-xs-6"
|
||||
>
|
||||
<Row
|
||||
className="makeStyles-oneSettingRow-24"
|
||||
className="makeStyles-oneSettingRow-30"
|
||||
middle="xs"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-oneSettingRow-24 row middle-xs"
|
||||
className="makeStyles-oneSettingRow-30 row middle-xs"
|
||||
>
|
||||
<Col>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-settingRowIcon-25"
|
||||
className="makeStyles-settingRowIcon-31"
|
||||
icon="automatic-updates"
|
||||
iconSize={25}
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-automatic-updates makeStyles-settingRowIcon-25"
|
||||
className="bp3-icon bp3-icon-automatic-updates makeStyles-settingRowIcon-31"
|
||||
icon="automatic-updates"
|
||||
>
|
||||
<svg
|
||||
@ -1927,12 +1924,12 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
<Blueprint3.Checkbox
|
||||
checked={true}
|
||||
className="makeStyles-checkboxSettings-7"
|
||||
className="makeStyles-checkboxSettings-20"
|
||||
label="Enabled"
|
||||
>
|
||||
<Control
|
||||
checked={true}
|
||||
className="makeStyles-checkboxSettings-7"
|
||||
className="makeStyles-checkboxSettings-20"
|
||||
inputRef={[Function]}
|
||||
label="Enabled"
|
||||
onChange={[Function]}
|
||||
@ -1940,7 +1937,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
typeClassName="bp3-checkbox"
|
||||
>
|
||||
<label
|
||||
className="bp3-control bp3-checkbox makeStyles-checkboxSettings-7"
|
||||
className="bp3-control bp3-checkbox makeStyles-checkboxSettings-20"
|
||||
>
|
||||
<input
|
||||
checked={true}
|
||||
|
@ -43,9 +43,8 @@ const useStyles = makeStyles(() =>
|
||||
width: '40px',
|
||||
borderRadius: '100px !important',
|
||||
position: 'relative',
|
||||
top: '72px',
|
||||
top: '70px',
|
||||
left: '-190px !important',
|
||||
zIndex: 9999,
|
||||
cursor: 'default',
|
||||
},
|
||||
})
|
||||
@ -119,7 +118,11 @@ export default function ShareEntireScreenOrAppWindowControlGroup(
|
||||
/>
|
||||
<Text className="bp3-running-text">Application Window</Text>
|
||||
</Button>
|
||||
<Button active className={classes.orDecorationButton}>
|
||||
<Button
|
||||
active
|
||||
className={classes.orDecorationButton}
|
||||
style={{ zIndex: 999 }}
|
||||
>
|
||||
OR
|
||||
</Button>
|
||||
</ControlGroup>
|
||||
|
@ -1,13 +1,20 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import { clipboard, remote } from 'electron';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { Button, Text, Tooltip, Position, H2, Dialog } from '@blueprintjs/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Button,
|
||||
Text,
|
||||
Tooltip,
|
||||
Position,
|
||||
Dialog,
|
||||
Classes,
|
||||
} from '@blueprintjs/core';
|
||||
import QRCode from 'qrcode.react';
|
||||
import { makeStyles, createStyles } from '@material-ui/core';
|
||||
import { Row, Col } from 'react-flexbox-grid';
|
||||
import { SettingsContext } from '../../containers/SettingsProvider';
|
||||
import isProduction from '../../utils/isProduction';
|
||||
import CloseOverlayButton from '../CloseOverlayButton';
|
||||
import SharingSessionService from '../../features/SharingSessionsService';
|
||||
|
||||
const sharingSessionService = remote.getGlobal(
|
||||
@ -38,17 +45,21 @@ const useStyles = makeStyles(() =>
|
||||
dialogQRWrapper: {
|
||||
backgroundColor: 'white',
|
||||
padding: '20px',
|
||||
// width: '95%',
|
||||
// hieght: '95%',
|
||||
borderRadius: '10px',
|
||||
},
|
||||
bigQRCodeDialogRoot: {
|
||||
'&:hover': {
|
||||
cursor: 'zoom-out',
|
||||
},
|
||||
paddingBottom: '0px',
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const ScanQRStep: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const classes = useStyles();
|
||||
const { isDarkTheme } = useContext(SettingsContext);
|
||||
|
||||
@ -73,10 +84,20 @@ const ScanQRStep: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<Text className="bp3-text">Scan the QR code</Text>
|
||||
<Text className="bp3-text-muted">
|
||||
( make sure your computer and device are connected on same WiFi )
|
||||
<Text>
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: '#00f99273',
|
||||
fontWeight: 900,
|
||||
paddingRight: '8px',
|
||||
paddingLeft: '8px',
|
||||
borderRadius: '20px',
|
||||
}}
|
||||
>
|
||||
make sure your computer and device are connected to same WiFi
|
||||
</span>
|
||||
</Text>
|
||||
<Text className="bp3-text">{t('Scan the QR code')}</Text>
|
||||
</div>
|
||||
<div>
|
||||
<Tooltip content="Click to make bigger" position={Position.LEFT}>
|
||||
@ -133,50 +154,32 @@ const ScanQRStep: React.FC = () => {
|
||||
canEscapeKeyClose
|
||||
canOutsideClickClose
|
||||
transitionDuration={isProduction() ? 700 : 0}
|
||||
style={{ position: 'relative', top: '-30px' }}
|
||||
style={{ position: 'relative', top: '0px' }}
|
||||
>
|
||||
<Button
|
||||
<Row
|
||||
id="qr-code-dialog-inner"
|
||||
className={Classes.DIALOG_BODY}
|
||||
center="xs"
|
||||
middle="xs"
|
||||
onClick={() => setIsQRCodeMagnified(false)}
|
||||
style={{ paddingTop: '20px', paddingBottom: '13px' }}
|
||||
>
|
||||
<Row between="xs" middle="xs">
|
||||
<Col xs={10}>
|
||||
<H2 style={{ margin: '0px', padding: '0px', marginLeft: '35px' }}>
|
||||
Scan QR Code
|
||||
</H2>
|
||||
</Col>
|
||||
<Col xs={2}>
|
||||
<CloseOverlayButton
|
||||
onClick={() => setIsQRCodeMagnified(false)}
|
||||
style={{
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
position: 'relative',
|
||||
borderRadius: '100px',
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row center="xs">
|
||||
<div className={classes.dialogQRWrapper}>
|
||||
<QRCode
|
||||
value={`http://${LOCAL_LAN_IP}:${CLIENT_VIEWER_PORT}/${roomID}`}
|
||||
level="H"
|
||||
renderAs="svg"
|
||||
imageSettings={{
|
||||
// TODO: change image to app icon
|
||||
src:
|
||||
'https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Electron_Software_Framework_Logo.svg/256px-Electron_Software_Framework_Logo.svg.png',
|
||||
width: 25,
|
||||
height: 25,
|
||||
}}
|
||||
width="390px"
|
||||
height="390px"
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
</Button>
|
||||
<Col xs={11} className={classes.dialogQRWrapper}>
|
||||
<QRCode
|
||||
value={`http://${LOCAL_LAN_IP}:${CLIENT_VIEWER_PORT}/${roomID}`}
|
||||
level="H"
|
||||
renderAs="svg"
|
||||
imageSettings={{
|
||||
// TODO: change image to app icon
|
||||
src:
|
||||
'https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Electron_Software_Framework_Logo.svg/256px-Electron_Software_Framework_Logo.svg.png',
|
||||
width: 25,
|
||||
height: 25,
|
||||
}}
|
||||
width="390px"
|
||||
height="390px"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
|
@ -237,11 +237,21 @@ exports[`should match exact snapshot 1`] = `
|
||||
<Blueprint3.Button
|
||||
active={true}
|
||||
className="makeStyles-orDecorationButton-6"
|
||||
style={
|
||||
Object {
|
||||
"zIndex": 999,
|
||||
}
|
||||
}
|
||||
>
|
||||
<button
|
||||
className="bp3-button bp3-active makeStyles-orDecorationButton-6"
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"zIndex": 999,
|
||||
}
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
|
@ -236,7 +236,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#00f99273",
|
||||
"borderRadius": "20px",
|
||||
"fontWeight": 900,
|
||||
"paddingLeft": "10px",
|
||||
"paddingRight": "10px",
|
||||
}
|
||||
}
|
||||
tabIndex={0}
|
||||
|
@ -74,23 +74,31 @@ exports[`should match exact snapshot on each step 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<Blueprint3.Text>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#00f99273",
|
||||
"borderRadius": "20px",
|
||||
"fontWeight": 900,
|
||||
"paddingLeft": "8px",
|
||||
"paddingRight": "8px",
|
||||
}
|
||||
}
|
||||
>
|
||||
make sure your computer and device are connected to same WiFi
|
||||
</span>
|
||||
</div>
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text"
|
||||
>
|
||||
<div
|
||||
className="bp3-text"
|
||||
>
|
||||
Scan the QR code
|
||||
</div>
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text-muted"
|
||||
>
|
||||
<div
|
||||
className="bp3-text-muted"
|
||||
>
|
||||
( make sure your computer and device are connected on same WiFi )
|
||||
</div>
|
||||
/>
|
||||
</Blueprint3.Text>
|
||||
</div>
|
||||
<div>
|
||||
@ -423,7 +431,7 @@ exports[`should match exact snapshot on each step 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"position": "relative",
|
||||
"top": "-30px",
|
||||
"top": "0px",
|
||||
}
|
||||
}
|
||||
transitionDuration={0}
|
||||
@ -443,7 +451,7 @@ exports[`should match exact snapshot on each step 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"position": "relative",
|
||||
"top": "-30px",
|
||||
"top": "0px",
|
||||
}
|
||||
}
|
||||
transitionDuration={0}
|
||||
@ -840,11 +848,21 @@ exports[`should match exact snapshot on each step 2`] = `
|
||||
<Blueprint3.Button
|
||||
active={true}
|
||||
className="makeStyles-orDecorationButton-9"
|
||||
style={
|
||||
Object {
|
||||
"zIndex": 999,
|
||||
}
|
||||
}
|
||||
>
|
||||
<button
|
||||
className="bp3-button bp3-active makeStyles-orDecorationButton-9"
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"zIndex": 999,
|
||||
}
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
@ -1352,7 +1370,10 @@ exports[`should match exact snapshot on each step 3`] = `
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#00f99273",
|
||||
"borderRadius": "20px",
|
||||
"fontWeight": 900,
|
||||
"paddingLeft": "10px",
|
||||
"paddingRight": "10px",
|
||||
}
|
||||
}
|
||||
tabIndex={0}
|
||||
|
@ -9,16 +9,24 @@ exports[`<ScanQRStep /> when rendered should match exact snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<Blueprint3.Text>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#00f99273",
|
||||
"borderRadius": "20px",
|
||||
"fontWeight": 900,
|
||||
"paddingLeft": "8px",
|
||||
"paddingRight": "8px",
|
||||
}
|
||||
}
|
||||
>
|
||||
make sure your computer and device are connected to same WiFi
|
||||
</span>
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text"
|
||||
>
|
||||
Scan the QR code
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text-muted"
|
||||
>
|
||||
( make sure your computer and device are connected on same WiFi )
|
||||
</Blueprint3.Text>
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Blueprint3.Tooltip
|
||||
@ -95,83 +103,42 @@ exports[`<ScanQRStep /> when rendered should match exact snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"position": "relative",
|
||||
"top": "-30px",
|
||||
"top": "0px",
|
||||
}
|
||||
}
|
||||
transitionDuration={0}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
<Row
|
||||
center="xs"
|
||||
className="bp3-dialog-body"
|
||||
id="qr-code-dialog-inner"
|
||||
middle="xs"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"paddingBottom": "13px",
|
||||
"paddingTop": "20px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Row
|
||||
between="xs"
|
||||
middle="xs"
|
||||
<Col
|
||||
className="makeStyles-dialogQRWrapper-2"
|
||||
xs={11}
|
||||
>
|
||||
<Col
|
||||
xs={10}
|
||||
>
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"margin": "0px",
|
||||
"marginLeft": "35px",
|
||||
"padding": "0px",
|
||||
}
|
||||
<QRCode
|
||||
bgColor="#FFFFFF"
|
||||
fgColor="#000000"
|
||||
height="390px"
|
||||
imageSettings={
|
||||
Object {
|
||||
"height": 25,
|
||||
"src": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Electron_Software_Framework_Logo.svg/256px-Electron_Software_Framework_Logo.svg.png",
|
||||
"width": 25,
|
||||
}
|
||||
>
|
||||
Scan QR Code
|
||||
</Component>
|
||||
</Col>
|
||||
<Col
|
||||
xs={2}
|
||||
>
|
||||
<CloseOverlayButton
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"borderRadius": "100px",
|
||||
"height": "40px",
|
||||
"position": "relative",
|
||||
"width": "40px",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row
|
||||
center="xs"
|
||||
>
|
||||
<div
|
||||
className="makeStyles-dialogQRWrapper-2"
|
||||
>
|
||||
<QRCode
|
||||
bgColor="#FFFFFF"
|
||||
fgColor="#000000"
|
||||
height="390px"
|
||||
imageSettings={
|
||||
Object {
|
||||
"height": 25,
|
||||
"src": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Electron_Software_Framework_Logo.svg/256px-Electron_Software_Framework_Logo.svg.png",
|
||||
"width": 25,
|
||||
}
|
||||
}
|
||||
includeMargin={false}
|
||||
level="H"
|
||||
renderAs="svg"
|
||||
size={128}
|
||||
value="http://255.255.255.255:3000/"
|
||||
width="390px"
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
</Blueprint3.Button>
|
||||
}
|
||||
includeMargin={false}
|
||||
level="H"
|
||||
renderAs="svg"
|
||||
size={128}
|
||||
value="http://255.255.255.255:3000/"
|
||||
width="390px"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Blueprint3.Dialog>
|
||||
</Fragment>
|
||||
`;
|
||||
|
@ -2,12 +2,16 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
import React, { useCallback, useContext } from 'react';
|
||||
import { Button, Icon, Position, Tooltip } from '@blueprintjs/core';
|
||||
import { Button, Text, Icon, Position, Tooltip } from '@blueprintjs/core';
|
||||
import { createStyles, makeStyles } from '@material-ui/core/styles';
|
||||
import { Col, Row } from 'react-flexbox-grid';
|
||||
import SettingsOverlay from './SettingsOverlay/SettingsOverlay';
|
||||
import ConnectedDevicesListDrawer from './ConnectedDevicesListDrawer';
|
||||
import { SettingsContext } from '../containers/SettingsProvider';
|
||||
import isProduction from '../utils/isProduction';
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore fine import here
|
||||
import RedHeartTwemojiPNG from '../images/red_heart_2764_twemoji_120x120.png';
|
||||
|
||||
const Zoom = require('react-reveal/Zoom');
|
||||
const Fade = require('react-reveal/Fade');
|
||||
@ -72,13 +76,41 @@ export default function TopPanel(props: any) {
|
||||
setIsDrawerOpen(!isDrawersOpen);
|
||||
}, [isDrawersOpen]);
|
||||
|
||||
const renderDonateButton = useCallback(() => {
|
||||
return (
|
||||
<Tooltip
|
||||
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!"
|
||||
position={Position.BOTTOM}
|
||||
>
|
||||
<Button style={{ transform: 'translateY(2px)', marginRight: '10px' }}>
|
||||
<Row start="xs">
|
||||
<Col xs>
|
||||
<img
|
||||
src={RedHeartTwemojiPNG}
|
||||
width={16}
|
||||
height={16}
|
||||
style={{ transform: 'translateY(2px)' }}
|
||||
alt="heart"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs>
|
||||
<div style={{ transform: 'translateY(2px) translateX(-5px)' }}>
|
||||
<Text>Donate!</Text>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
}, []);
|
||||
|
||||
const renderConnectedDevicesListButton = useCallback(() => {
|
||||
return (
|
||||
<div className={getClassesCallback().topPanelControlButtonMargin}>
|
||||
<Tooltip content="Connected Devices" position={Position.BOTTOM}>
|
||||
<Button
|
||||
id="top-panel-connected-devices-list-button"
|
||||
intent="none"
|
||||
intent="primary"
|
||||
className={getClassesCallback().topPanelControlButton}
|
||||
onClick={handleToggleConnectedDevicesListDrawer}
|
||||
>
|
||||
@ -96,7 +128,7 @@ export default function TopPanel(props: any) {
|
||||
const renderHelpButton = useCallback(() => {
|
||||
return (
|
||||
<div className={getClassesCallback().topPanelControlButtonMargin}>
|
||||
<Tooltip content="Help" position={Position.BOTTOM}>
|
||||
<Tooltip content="Tutorial" position={Position.BOTTOM}>
|
||||
<Button
|
||||
id="top-panel-help-button"
|
||||
intent="none"
|
||||
@ -104,7 +136,7 @@ export default function TopPanel(props: any) {
|
||||
>
|
||||
<Icon
|
||||
className={getClassesCallback().topPanelIconOfControlButton}
|
||||
icon="help"
|
||||
icon="learning"
|
||||
iconSize={22}
|
||||
/>
|
||||
</Button>
|
||||
@ -140,12 +172,17 @@ export default function TopPanel(props: any) {
|
||||
id="logo-with-popover-visit-website"
|
||||
className={getClassesCallback().logoWithAppName}
|
||||
>
|
||||
<h4
|
||||
id="deskreen-top-app-name-header"
|
||||
className={getClassesCallback().appNameHeader}
|
||||
<Tooltip
|
||||
content="Click to visit our website"
|
||||
position={Position.BOTTOM}
|
||||
>
|
||||
Deskreen
|
||||
</h4>
|
||||
<h4
|
||||
id="deskreen-top-app-name-header"
|
||||
className={getClassesCallback().appNameHeader}
|
||||
>
|
||||
Deskreen
|
||||
</h4>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Zoom>
|
||||
);
|
||||
@ -154,7 +191,14 @@ export default function TopPanel(props: any) {
|
||||
return (
|
||||
<>
|
||||
<div className={getClassesCallback().topPanelRoot}>
|
||||
{renderLogoWithAppName()}
|
||||
<Row
|
||||
middle="xs"
|
||||
center="xs"
|
||||
style={{ width: '100%', transform: 'translateX(-50px)' }}
|
||||
>
|
||||
<Col>{renderDonateButton()}</Col>
|
||||
<Col>{renderLogoWithAppName()}</Col>
|
||||
</Row>
|
||||
<div className={getClassesCallback().topPanelControlButtonsRoot}>
|
||||
<Fade right duration={isProduction() ? 2000 : 0}>
|
||||
{renderConnectedDevicesListButton()}
|
||||
|
@ -151,7 +151,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
style="font-weight: 900; background-color: rgba(0, 249, 146, 0.451);"
|
||||
style="font-weight: 900; background-color: rgba(0, 249, 146, 0.451); padding-left: 10px; padding-right: 10px; border-radius: 20px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
@ -301,7 +301,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
style="font-weight: 900; background-color: rgba(0, 249, 146, 0.451);"
|
||||
style="font-weight: 900; background-color: rgba(0, 249, 146, 0.451); padding-left: 10px; padding-right: 10px; border-radius: 20px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
@ -628,7 +628,10 @@ exports[`should match exact snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#00f99273",
|
||||
"borderRadius": "20px",
|
||||
"fontWeight": 900,
|
||||
"paddingLeft": "10px",
|
||||
"paddingRight": "10px",
|
||||
}
|
||||
}
|
||||
tabIndex={0}
|
||||
|
@ -175,11 +175,21 @@ exports[`should match exact snapshot 1`] = `
|
||||
<Blueprint3.Button
|
||||
active={true}
|
||||
className="makeStyles-orDecorationButton-6"
|
||||
style={
|
||||
Object {
|
||||
"zIndex": 999,
|
||||
}
|
||||
}
|
||||
>
|
||||
<button
|
||||
className="bp3-button bp3-active makeStyles-orDecorationButton-6"
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"zIndex": 999,
|
||||
}
|
||||
}
|
||||
type="button"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
|
@ -5,22 +5,96 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
|
||||
<div
|
||||
className="makeStyles-topPanelRoot-1"
|
||||
>
|
||||
<Zoom
|
||||
duration={0}
|
||||
top={true}
|
||||
<Row
|
||||
center="xs"
|
||||
middle="xs"
|
||||
style={
|
||||
Object {
|
||||
"transform": "translateX(-50px)",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="makeStyles-logoWithAppName-9"
|
||||
id="logo-with-popover-visit-website"
|
||||
>
|
||||
<h4
|
||||
className="makeStyles-appNameHeader-17"
|
||||
id="deskreen-top-app-name-header"
|
||||
<Col>
|
||||
<Blueprint3.Tooltip
|
||||
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!"
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
position="bottom"
|
||||
transitionDuration={100}
|
||||
>
|
||||
Deskreen
|
||||
</h4>
|
||||
</div>
|
||||
</Zoom>
|
||||
<Blueprint3.Button
|
||||
style={
|
||||
Object {
|
||||
"marginRight": "10px",
|
||||
"transform": "translateY(2px)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Row
|
||||
start="xs"
|
||||
>
|
||||
<Col
|
||||
xs={true}
|
||||
>
|
||||
<img
|
||||
alt="heart"
|
||||
height={16}
|
||||
src="test-file-stub"
|
||||
style={
|
||||
Object {
|
||||
"transform": "translateY(2px)",
|
||||
}
|
||||
}
|
||||
width={16}
|
||||
/>
|
||||
</Col>
|
||||
<Col
|
||||
xs={true}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"transform": "translateY(2px) translateX(-5px)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Blueprint3.Text>
|
||||
Donate!
|
||||
</Blueprint3.Text>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Blueprint3.Button>
|
||||
</Blueprint3.Tooltip>
|
||||
</Col>
|
||||
<Col>
|
||||
<Zoom
|
||||
duration={0}
|
||||
top={true}
|
||||
>
|
||||
<div
|
||||
className="makeStyles-logoWithAppName-9"
|
||||
id="logo-with-popover-visit-website"
|
||||
>
|
||||
<Blueprint3.Tooltip
|
||||
content="Click to visit our website"
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
position="bottom"
|
||||
transitionDuration={100}
|
||||
>
|
||||
<h4
|
||||
className="makeStyles-appNameHeader-17"
|
||||
id="deskreen-top-app-name-header"
|
||||
>
|
||||
Deskreen
|
||||
</h4>
|
||||
</Blueprint3.Tooltip>
|
||||
</div>
|
||||
</Zoom>
|
||||
</Col>
|
||||
</Row>
|
||||
<div
|
||||
className="makeStyles-topPanelControlButtonsRoot-25"
|
||||
>
|
||||
@ -41,7 +115,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
|
||||
<Blueprint3.Button
|
||||
className="makeStyles-topPanelControlButton-40"
|
||||
id="top-panel-connected-devices-list-button"
|
||||
intent="none"
|
||||
intent="primary"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
@ -56,7 +130,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
|
||||
className="makeStyles-topPanelControlButtonMargin-55"
|
||||
>
|
||||
<Blueprint3.Tooltip
|
||||
content="Help"
|
||||
content="Tutorial"
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
position="bottom"
|
||||
@ -69,7 +143,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-topPanelIconOfControlButton-70"
|
||||
icon="help"
|
||||
icon="learning"
|
||||
iconSize={22}
|
||||
/>
|
||||
</Blueprint3.Button>
|
||||
|
@ -8,6 +8,7 @@ import settings from 'electron-settings';
|
||||
import config from './app.lang.config';
|
||||
import isProduction from '../utils/isProduction';
|
||||
|
||||
// TODO: move this outside this file!
|
||||
export const getLangFullNameToLangISOKeyMap = (): Map<string, string> => {
|
||||
const res = new Map<string, string>();
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
@ -19,6 +20,7 @@ export const getLangFullNameToLangISOKeyMap = (): Map<string, string> => {
|
||||
return res;
|
||||
};
|
||||
|
||||
// TODO: move this outside this file!
|
||||
export const getLangISOKeyToLangFullNameMap = (): Map<string, string> => {
|
||||
const res = new Map<string, string>();
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
@ -23,6 +23,8 @@ jest.mock('electron', () => {
|
||||
return {
|
||||
createWaitingForConnectionSharingSession: () =>
|
||||
new Promise(() => {}),
|
||||
setAppLanguage: () => {},
|
||||
setAppTheme: () => {},
|
||||
};
|
||||
}
|
||||
return {};
|
||||
|
@ -9,12 +9,16 @@ export const DARK_UI_BACKGROUND = '#293742';
|
||||
|
||||
interface SettingsContextInterface {
|
||||
isDarkTheme: boolean;
|
||||
currentLanguage: string;
|
||||
setIsDarkThemeHook: (val: boolean) => void;
|
||||
setCurrentLanguageHook: (newLang: string) => void;
|
||||
}
|
||||
|
||||
const defaultSettingsContextValue = {
|
||||
isDarkTheme: false,
|
||||
setIsDarkThemeHook: () => {},
|
||||
setCurrentLanguageHook: () => {},
|
||||
currentLanguage: 'en',
|
||||
};
|
||||
|
||||
export const SettingsContext = React.createContext<SettingsContextInterface>(
|
||||
@ -23,6 +27,7 @@ export const SettingsContext = React.createContext<SettingsContextInterface>(
|
||||
|
||||
export const SettingsProvider: React.FC = ({ children }) => {
|
||||
const [isDarkTheme, setIsDarkTheme] = useState(false);
|
||||
const [currentLanguage, setCurrentLanguage] = useState('en');
|
||||
|
||||
const loadDarkThemeFromSettings = () => {
|
||||
const gotIsDarkThemeFromSettings = settings.hasSync('appIsDarkTheme')
|
||||
@ -46,7 +51,16 @@ export const SettingsProvider: React.FC = ({ children }) => {
|
||||
setIsDarkTheme(val);
|
||||
};
|
||||
|
||||
const value = { isDarkTheme, setIsDarkThemeHook };
|
||||
const setCurrentLanguageHook = (newLang: string) => {
|
||||
setCurrentLanguage(newLang);
|
||||
};
|
||||
|
||||
const value = {
|
||||
isDarkTheme,
|
||||
setIsDarkThemeHook,
|
||||
currentLanguage,
|
||||
setCurrentLanguageHook,
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsContext.Provider value={value}>
|
||||
|
@ -17,6 +17,8 @@ jest.mock('electron', () => {
|
||||
return {
|
||||
createWaitingForConnectionSharingSession: () =>
|
||||
new Promise(() => {}),
|
||||
setAppLanguage: () => {},
|
||||
setAppTheme: () => {},
|
||||
};
|
||||
}
|
||||
if (globalName === 'connectedDevicesService') {
|
||||
|
@ -66,7 +66,7 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
|
||||
|
||||
const [isInterShow, setIsInterShow] = useState(false);
|
||||
|
||||
const { isDarkTheme } = useContext(SettingsContext);
|
||||
const { isDarkTheme, currentLanguage } = useContext(SettingsContext);
|
||||
|
||||
const { addToast } = useToasts();
|
||||
|
||||
@ -104,8 +104,17 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
|
||||
},
|
||||
isProduction() ? 500 : 0
|
||||
);
|
||||
|
||||
// sharingSessionService.setAppLanguage(currentLanguage);
|
||||
// sharingSessionService.setAppTheme(isDarkTheme ? 'dark' : 'light');
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
sharingSessionService.setAppLanguage(currentLanguage);
|
||||
sharingSessionService.setAppTheme(isDarkTheme);
|
||||
}, [currentLanguage, isDarkTheme]);
|
||||
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
const [isEntireScreenSelected, setIsEntireScreenSelected] = useState(false);
|
||||
const [
|
||||
@ -153,7 +162,40 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
|
||||
setActiveStep(0);
|
||||
setPendingConnectionDevice(null);
|
||||
setIsUserAllowedConnection(false);
|
||||
|
||||
// const sharingSession =
|
||||
// sharingSessionService.waitingForConnectionSharingSession;
|
||||
// sharingSession?.disconnectByHostMachineUser();
|
||||
// sharingSession?.destory();
|
||||
// sharingSessionService.sharingSessions.delete(sharingSession?.id as string);
|
||||
// sharingSessionService.waitingForConnectionSharingSession = null;
|
||||
|
||||
sharingSessionService
|
||||
.createWaitingForConnectionSharingSession()
|
||||
// eslint-disable-next-line promise/always-return
|
||||
.then((waitingForConnectionSharingSession) => {
|
||||
waitingForConnectionSharingSession.setOnDeviceConnectedCallback(
|
||||
(device: Device) => {
|
||||
connectedDevicesService.setPendingConnectionDevice(device);
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch((e) => log.error(e));
|
||||
}, []);
|
||||
|
||||
const handleResetWithSharingSessionRestart = useCallback(() => {
|
||||
makeSmoothIntermediateStepTransition();
|
||||
setActiveStep(0);
|
||||
setPendingConnectionDevice(null);
|
||||
setIsUserAllowedConnection(false);
|
||||
|
||||
const sharingSession =
|
||||
sharingSessionService.waitingForConnectionSharingSession;
|
||||
sharingSession?.disconnectByHostMachineUser();
|
||||
sharingSession?.destory();
|
||||
sharingSessionService.sharingSessions.delete(sharingSession?.id as string);
|
||||
sharingSessionService.waitingForConnectionSharingSession = null;
|
||||
|
||||
sharingSessionService
|
||||
.createWaitingForConnectionSharingSession()
|
||||
// eslint-disable-next-line promise/always-return
|
||||
@ -169,7 +211,7 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
handleReset() {
|
||||
handleReset();
|
||||
handleResetWithSharingSessionRestart();
|
||||
},
|
||||
}));
|
||||
|
||||
@ -215,7 +257,7 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
|
||||
}, [handleNext]);
|
||||
|
||||
const handleUserClickedDeviceDisconnectButton = useCallback(async () => {
|
||||
handleReset();
|
||||
handleResetWithSharingSessionRestart();
|
||||
|
||||
addToast(
|
||||
<Text>
|
||||
@ -224,20 +266,11 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
|
||||
{
|
||||
appearance: 'info',
|
||||
autoDismiss: true,
|
||||
// @ts-ignore: works fine here, ignore
|
||||
// @ts-ignore: works fine here
|
||||
isdarktheme: `${isDarkTheme}`,
|
||||
}
|
||||
);
|
||||
|
||||
if (sharingSessionService.waitingForConnectionSharingSession !== null) {
|
||||
const sharingSession =
|
||||
sharingSessionService.waitingForConnectionSharingSession;
|
||||
sharingSession.disconnectByHostMachineUser();
|
||||
sharingSession.destory();
|
||||
sharingSession.setStatus(SharingSessionStatusEnum.NOT_CONNECTED);
|
||||
sharingSessionService.sharingSessions.delete(sharingSession.id);
|
||||
}
|
||||
}, [addToast, handleReset, isDarkTheme]);
|
||||
}, [addToast, handleResetWithSharingSessionRestart, isDarkTheme]);
|
||||
|
||||
const renderIntermediateOrSuccessStepContent = useCallback(() => {
|
||||
return activeStep === steps.length ? (
|
||||
|
@ -57,63 +57,339 @@ exports[`should match exact snapshot 1`] = `
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="makeStyles-topPanelRoot-1"
|
||||
className="makeStyles-topPanelRoot-117"
|
||||
>
|
||||
<Zoom
|
||||
duration={0}
|
||||
top={true}
|
||||
<Row
|
||||
center="xs"
|
||||
middle="xs"
|
||||
style={
|
||||
Object {
|
||||
"transform": "translateX(-50px)",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<RevealBase
|
||||
fraction={0.2}
|
||||
inEffect={
|
||||
<div
|
||||
className="row center-xs middle-xs"
|
||||
style={
|
||||
Object {
|
||||
"count": 1,
|
||||
"delay": 0,
|
||||
"duration": 0,
|
||||
"forever": undefined,
|
||||
"make": [Function],
|
||||
"reverse": undefined,
|
||||
"style": Object {
|
||||
"animationFillMode": "both",
|
||||
},
|
||||
"transform": "translateX(-50px)",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
outEffect={
|
||||
Object {
|
||||
"count": 1,
|
||||
"delay": 0,
|
||||
"duration": 0,
|
||||
"forever": undefined,
|
||||
"make": [Function],
|
||||
"reverse": undefined,
|
||||
"style": Object {
|
||||
"animationFillMode": "both",
|
||||
},
|
||||
}
|
||||
}
|
||||
refProp="ref"
|
||||
top={true}
|
||||
>
|
||||
<div
|
||||
className="react-reveal makeStyles-logoWithAppName-9"
|
||||
id="logo-with-popover-visit-website"
|
||||
style={
|
||||
Object {
|
||||
"opacity": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<h4
|
||||
className="makeStyles-appNameHeader-17"
|
||||
id="deskreen-top-app-name-header"
|
||||
<Col>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
Deskreen
|
||||
</h4>
|
||||
</div>
|
||||
</RevealBase>
|
||||
</Zoom>
|
||||
<Blueprint3.Tooltip
|
||||
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!"
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
position="bottom"
|
||||
transitionDuration={100}
|
||||
>
|
||||
<Blueprint3.Popover
|
||||
autoFocus={false}
|
||||
boundary="scrollParent"
|
||||
canEscapeKeyClose={false}
|
||||
captureDismiss={false}
|
||||
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!"
|
||||
defaultIsOpen={false}
|
||||
disabled={false}
|
||||
enforceFocus={false}
|
||||
fill={false}
|
||||
hasBackdrop={false}
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
inheritDarkTheme={true}
|
||||
interactionKind="hover-target"
|
||||
lazy={true}
|
||||
minimal={false}
|
||||
modifiers={Object {}}
|
||||
openOnTargetFocus={true}
|
||||
popoverClassName="bp3-tooltip"
|
||||
position="bottom"
|
||||
targetTagName="span"
|
||||
transitionDuration={100}
|
||||
usePortal={true}
|
||||
wrapperTagName="span"
|
||||
>
|
||||
<Manager>
|
||||
<span
|
||||
className="bp3-popover-wrapper"
|
||||
>
|
||||
<Reference
|
||||
innerRef={[Function]}
|
||||
>
|
||||
<InnerReference
|
||||
innerRef={[Function]}
|
||||
setReferenceNode={[Function]}
|
||||
>
|
||||
<Blueprint3.ResizeSensor
|
||||
onResize={[Function]}
|
||||
>
|
||||
<span
|
||||
className="bp3-popover-target"
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className=""
|
||||
key=".0"
|
||||
style={
|
||||
Object {
|
||||
"marginRight": "10px",
|
||||
"transform": "translateY(2px)",
|
||||
}
|
||||
}
|
||||
tabIndex={0}
|
||||
>
|
||||
<button
|
||||
className="bp3-button"
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"marginRight": "10px",
|
||||
"transform": "translateY(2px)",
|
||||
}
|
||||
}
|
||||
tabIndex={0}
|
||||
type="button"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
key="leftIcon"
|
||||
/>
|
||||
<span
|
||||
className="bp3-button-text"
|
||||
key="text"
|
||||
>
|
||||
<Row
|
||||
start="xs"
|
||||
>
|
||||
<div
|
||||
className="row start-xs"
|
||||
>
|
||||
<Col
|
||||
xs={true}
|
||||
>
|
||||
<div
|
||||
className="col-xs"
|
||||
>
|
||||
<img
|
||||
alt="heart"
|
||||
height={16}
|
||||
src="test-file-stub"
|
||||
style={
|
||||
Object {
|
||||
"transform": "translateY(2px)",
|
||||
}
|
||||
}
|
||||
width={16}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col
|
||||
xs={true}
|
||||
>
|
||||
<div
|
||||
className="col-xs"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"transform": "translateY(2px) translateX(-5px)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Blueprint3.Text>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
Donate!
|
||||
</div>
|
||||
</Blueprint3.Text>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</div>
|
||||
</Row>
|
||||
</span>
|
||||
<Blueprint3.Icon
|
||||
key="rightIcon"
|
||||
/>
|
||||
</button>
|
||||
</Blueprint3.Button>
|
||||
</span>
|
||||
</Blueprint3.ResizeSensor>
|
||||
</InnerReference>
|
||||
</Reference>
|
||||
<Blueprint3.Overlay
|
||||
autoFocus={false}
|
||||
backdropClassName="bp3-popover-backdrop"
|
||||
backdropProps={Object {}}
|
||||
canEscapeKeyClose={false}
|
||||
canOutsideClickClose={false}
|
||||
enforceFocus={false}
|
||||
hasBackdrop={false}
|
||||
isOpen={false}
|
||||
lazy={true}
|
||||
onClose={[Function]}
|
||||
transitionDuration={100}
|
||||
transitionName="bp3-popover"
|
||||
usePortal={true}
|
||||
/>
|
||||
</span>
|
||||
</Manager>
|
||||
</Blueprint3.Popover>
|
||||
</Blueprint3.Tooltip>
|
||||
</div>
|
||||
</Col>
|
||||
<Col>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<Zoom
|
||||
duration={0}
|
||||
top={true}
|
||||
>
|
||||
<RevealBase
|
||||
fraction={0.2}
|
||||
inEffect={
|
||||
Object {
|
||||
"count": 1,
|
||||
"delay": 0,
|
||||
"duration": 0,
|
||||
"forever": undefined,
|
||||
"make": [Function],
|
||||
"reverse": undefined,
|
||||
"style": Object {
|
||||
"animationFillMode": "both",
|
||||
},
|
||||
}
|
||||
}
|
||||
outEffect={
|
||||
Object {
|
||||
"count": 1,
|
||||
"delay": 0,
|
||||
"duration": 0,
|
||||
"forever": undefined,
|
||||
"make": [Function],
|
||||
"reverse": undefined,
|
||||
"style": Object {
|
||||
"animationFillMode": "both",
|
||||
},
|
||||
}
|
||||
}
|
||||
refProp="ref"
|
||||
top={true}
|
||||
>
|
||||
<div
|
||||
className="react-reveal makeStyles-logoWithAppName-125"
|
||||
id="logo-with-popover-visit-website"
|
||||
style={
|
||||
Object {
|
||||
"opacity": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Blueprint3.Tooltip
|
||||
content="Click to visit our website"
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
position="bottom"
|
||||
transitionDuration={100}
|
||||
>
|
||||
<Blueprint3.Popover
|
||||
autoFocus={false}
|
||||
boundary="scrollParent"
|
||||
canEscapeKeyClose={false}
|
||||
captureDismiss={false}
|
||||
content="Click to visit our website"
|
||||
defaultIsOpen={false}
|
||||
disabled={false}
|
||||
enforceFocus={false}
|
||||
fill={false}
|
||||
hasBackdrop={false}
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
inheritDarkTheme={true}
|
||||
interactionKind="hover-target"
|
||||
lazy={true}
|
||||
minimal={false}
|
||||
modifiers={Object {}}
|
||||
openOnTargetFocus={true}
|
||||
popoverClassName="bp3-tooltip"
|
||||
position="bottom"
|
||||
targetTagName="span"
|
||||
transitionDuration={100}
|
||||
usePortal={true}
|
||||
wrapperTagName="span"
|
||||
>
|
||||
<Manager>
|
||||
<span
|
||||
className="bp3-popover-wrapper"
|
||||
>
|
||||
<Reference
|
||||
innerRef={[Function]}
|
||||
>
|
||||
<InnerReference
|
||||
innerRef={[Function]}
|
||||
setReferenceNode={[Function]}
|
||||
>
|
||||
<Blueprint3.ResizeSensor
|
||||
onResize={[Function]}
|
||||
>
|
||||
<span
|
||||
className="bp3-popover-target"
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<h4
|
||||
className="makeStyles-appNameHeader-133"
|
||||
id="deskreen-top-app-name-header"
|
||||
key=".0"
|
||||
tabIndex={0}
|
||||
>
|
||||
Deskreen
|
||||
</h4>
|
||||
</span>
|
||||
</Blueprint3.ResizeSensor>
|
||||
</InnerReference>
|
||||
</Reference>
|
||||
<Blueprint3.Overlay
|
||||
autoFocus={false}
|
||||
backdropClassName="bp3-popover-backdrop"
|
||||
backdropProps={Object {}}
|
||||
canEscapeKeyClose={false}
|
||||
canOutsideClickClose={false}
|
||||
enforceFocus={false}
|
||||
hasBackdrop={false}
|
||||
isOpen={false}
|
||||
lazy={true}
|
||||
onClose={[Function]}
|
||||
transitionDuration={100}
|
||||
transitionName="bp3-popover"
|
||||
usePortal={true}
|
||||
/>
|
||||
</span>
|
||||
</Manager>
|
||||
</Blueprint3.Popover>
|
||||
</Blueprint3.Tooltip>
|
||||
</div>
|
||||
</RevealBase>
|
||||
</Zoom>
|
||||
</div>
|
||||
</Col>
|
||||
</div>
|
||||
</Row>
|
||||
<div
|
||||
className="makeStyles-topPanelControlButtonsRoot-25"
|
||||
className="makeStyles-topPanelControlButtonsRoot-141"
|
||||
>
|
||||
<Fade
|
||||
duration={0}
|
||||
@ -152,7 +428,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
right={true}
|
||||
>
|
||||
<div
|
||||
className="react-reveal makeStyles-topPanelControlButtonMargin-34"
|
||||
className="react-reveal makeStyles-topPanelControlButtonMargin-150"
|
||||
style={
|
||||
Object {
|
||||
"opacity": undefined,
|
||||
@ -214,15 +490,15 @@ exports[`should match exact snapshot 1`] = `
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="makeStyles-topPanelControlButton-40"
|
||||
className="makeStyles-topPanelControlButton-156"
|
||||
id="top-panel-connected-devices-list-button"
|
||||
intent="none"
|
||||
intent="primary"
|
||||
key=".0"
|
||||
onClick={[Function]}
|
||||
tabIndex={0}
|
||||
>
|
||||
<button
|
||||
className="bp3-button makeStyles-topPanelControlButton-40"
|
||||
className="bp3-button bp3-intent-primary makeStyles-topPanelControlButton-156"
|
||||
id="top-panel-connected-devices-list-button"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
@ -238,12 +514,12 @@ exports[`should match exact snapshot 1`] = `
|
||||
key="text"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-topPanelIconOfControlButton-49"
|
||||
className="makeStyles-topPanelIconOfControlButton-165"
|
||||
icon="th-list"
|
||||
iconSize={20}
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-th-list makeStyles-topPanelIconOfControlButton-49"
|
||||
className="bp3-icon bp3-icon-th-list makeStyles-topPanelIconOfControlButton-165"
|
||||
icon="th-list"
|
||||
>
|
||||
<svg
|
||||
@ -327,7 +603,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
right={true}
|
||||
>
|
||||
<div
|
||||
className="react-reveal makeStyles-topPanelControlButtonMargin-55"
|
||||
className="react-reveal makeStyles-topPanelControlButtonMargin-171"
|
||||
style={
|
||||
Object {
|
||||
"opacity": undefined,
|
||||
@ -335,7 +611,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
}
|
||||
>
|
||||
<Blueprint3.Tooltip
|
||||
content="Help"
|
||||
content="Tutorial"
|
||||
hoverCloseDelay={0}
|
||||
hoverOpenDelay={100}
|
||||
position="bottom"
|
||||
@ -346,7 +622,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
boundary="scrollParent"
|
||||
canEscapeKeyClose={false}
|
||||
captureDismiss={false}
|
||||
content="Help"
|
||||
content="Tutorial"
|
||||
defaultIsOpen={false}
|
||||
disabled={false}
|
||||
enforceFocus={false}
|
||||
@ -389,14 +665,14 @@ exports[`should match exact snapshot 1`] = `
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="makeStyles-topPanelControlButton-61"
|
||||
className="makeStyles-topPanelControlButton-177"
|
||||
id="top-panel-help-button"
|
||||
intent="none"
|
||||
key=".0"
|
||||
tabIndex={0}
|
||||
>
|
||||
<button
|
||||
className="bp3-button makeStyles-topPanelControlButton-61"
|
||||
className="bp3-button makeStyles-topPanelControlButton-177"
|
||||
id="top-panel-help-button"
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
@ -411,28 +687,33 @@ exports[`should match exact snapshot 1`] = `
|
||||
key="text"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-topPanelIconOfControlButton-70"
|
||||
icon="help"
|
||||
className="makeStyles-topPanelIconOfControlButton-186"
|
||||
icon="learning"
|
||||
iconSize={22}
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-help makeStyles-topPanelIconOfControlButton-70"
|
||||
icon="help"
|
||||
className="bp3-icon bp3-icon-learning makeStyles-topPanelIconOfControlButton-186"
|
||||
icon="learning"
|
||||
>
|
||||
<svg
|
||||
data-icon="help"
|
||||
data-icon="learning"
|
||||
height={22}
|
||||
viewBox="0 0 20 20"
|
||||
width={22}
|
||||
>
|
||||
<desc>
|
||||
help
|
||||
learning
|
||||
</desc>
|
||||
<path
|
||||
d="M10 0C4.48 0 0 4.48 0 10s4.48 10 10 10 10-4.48 10-10S15.52 0 10 0zM7.41 4.62c.65-.54 1.51-.82 2.56-.82.54 0 1.03.08 1.48.25.44.17.83.39 1.14.68.32.29.56.63.74 1.02.17.39.26.82.26 1.27s-.08.87-.24 1.23c-.16.37-.4.73-.71 1.11l-1.21 1.58c-.14.17-.28.33-.32.48-.05.15-.11.35-.11.6v.97H9v-2s.06-.58.24-.81l1.21-1.64c.25-.3.41-.56.51-.77s.14-.44.14-.67c0-.35-.11-.63-.32-.85s-.5-.33-.88-.33c-.37 0-.67.11-.89.33-.22.23-.37.54-.46.94-.03.12-.11.17-.23.16l-1.95-.29c-.12-.01-.16-.08-.14-.22.13-.93.52-1.67 1.18-2.22zM9 14h2.02L11 16H9v-2z"
|
||||
d="M10.551 1.127a1.256 1.256 0 00-1.102 0L.456 5.89c-.608.309-.608.913 0 1.222l8.993 4.762c.334.17.767.17 1.102 0l8.992-4.762c.61-.309.61-.913 0-1.222l-8.992-4.762z"
|
||||
fillRule="evenodd"
|
||||
key="0"
|
||||
/>
|
||||
<path
|
||||
d="M18 6.5l.016 4.514c.002.548.447.99.994.99a.99.99 0 00.99-.99V6.5h-2zM3.366 10.033l6.401 3.358a.5.5 0 00.465 0l6.406-3.358a.25.25 0 01.366.221v5.109a.25.25 0 01-.139.224l-6.64 3.302a.5.5 0 01-.446 0l-6.64-3.302A.25.25 0 013 15.363v-5.108a.25.25 0 01.366-.222z"
|
||||
fillRule="evenodd"
|
||||
key="1"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</Blueprint3.Icon>
|
||||
@ -500,7 +781,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
right={true}
|
||||
>
|
||||
<div
|
||||
className="react-reveal makeStyles-topPanelControlButtonMargin-76"
|
||||
className="react-reveal makeStyles-topPanelControlButtonMargin-192"
|
||||
style={
|
||||
Object {
|
||||
"opacity": undefined,
|
||||
@ -562,14 +843,14 @@ exports[`should match exact snapshot 1`] = `
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="makeStyles-topPanelControlButton-82"
|
||||
className="makeStyles-topPanelControlButton-198"
|
||||
id="top-panel-settings-button"
|
||||
key=".0"
|
||||
onClick={[Function]}
|
||||
tabIndex={0}
|
||||
>
|
||||
<button
|
||||
className="bp3-button makeStyles-topPanelControlButton-82"
|
||||
className="bp3-button makeStyles-topPanelControlButton-198"
|
||||
id="top-panel-settings-button"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
@ -585,12 +866,12 @@ exports[`should match exact snapshot 1`] = `
|
||||
key="text"
|
||||
>
|
||||
<Blueprint3.Icon
|
||||
className="makeStyles-topPanelIconOfControlButton-91"
|
||||
className="makeStyles-topPanelIconOfControlButton-207"
|
||||
icon="cog"
|
||||
iconSize={22}
|
||||
>
|
||||
<span
|
||||
className="bp3-icon bp3-icon-cog makeStyles-topPanelIconOfControlButton-91"
|
||||
className="bp3-icon bp3-icon-cog makeStyles-topPanelIconOfControlButton-207"
|
||||
icon="cog"
|
||||
>
|
||||
<svg
|
||||
@ -1773,23 +2054,31 @@ exports[`should match exact snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<Blueprint3.Text>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#00f99273",
|
||||
"borderRadius": "20px",
|
||||
"fontWeight": 900,
|
||||
"paddingLeft": "8px",
|
||||
"paddingRight": "8px",
|
||||
}
|
||||
}
|
||||
>
|
||||
make sure your computer and device are connected to same WiFi
|
||||
</span>
|
||||
</div>
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text"
|
||||
>
|
||||
<div
|
||||
className="bp3-text"
|
||||
>
|
||||
Scan the QR code
|
||||
</div>
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text-muted"
|
||||
>
|
||||
<div
|
||||
className="bp3-text-muted"
|
||||
>
|
||||
( make sure your computer and device are connected on same WiFi )
|
||||
</div>
|
||||
/>
|
||||
</Blueprint3.Text>
|
||||
</div>
|
||||
<div>
|
||||
@ -2122,7 +2411,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"position": "relative",
|
||||
"top": "-30px",
|
||||
"top": "0px",
|
||||
}
|
||||
}
|
||||
transitionDuration={0}
|
||||
@ -2142,7 +2431,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"position": "relative",
|
||||
"top": "-30px",
|
||||
"top": "0px",
|
||||
}
|
||||
}
|
||||
transitionDuration={0}
|
||||
|
@ -1059,23 +1059,31 @@ exports[`should match exact snapshot 1`] = `
|
||||
}
|
||||
}
|
||||
>
|
||||
<Blueprint3.Text>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#00f99273",
|
||||
"borderRadius": "20px",
|
||||
"fontWeight": 900,
|
||||
"paddingLeft": "8px",
|
||||
"paddingRight": "8px",
|
||||
}
|
||||
}
|
||||
>
|
||||
make sure your computer and device are connected to same WiFi
|
||||
</span>
|
||||
</div>
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text"
|
||||
>
|
||||
<div
|
||||
className="bp3-text"
|
||||
>
|
||||
Scan the QR code
|
||||
</div>
|
||||
</Blueprint3.Text>
|
||||
<Blueprint3.Text
|
||||
className="bp3-text-muted"
|
||||
>
|
||||
<div
|
||||
className="bp3-text-muted"
|
||||
>
|
||||
( make sure your computer and device are connected on same WiFi )
|
||||
</div>
|
||||
/>
|
||||
</Blueprint3.Text>
|
||||
</div>
|
||||
<div>
|
||||
@ -1408,7 +1416,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"position": "relative",
|
||||
"top": "-30px",
|
||||
"top": "0px",
|
||||
}
|
||||
}
|
||||
transitionDuration={0}
|
||||
@ -1428,7 +1436,7 @@ exports[`should match exact snapshot 1`] = `
|
||||
style={
|
||||
Object {
|
||||
"position": "relative",
|
||||
"top": "-30px",
|
||||
"top": "0px",
|
||||
}
|
||||
}
|
||||
transitionDuration={0}
|
||||
|
@ -2,8 +2,8 @@ export default async (
|
||||
sourceID: string,
|
||||
width: number | null | undefined = undefined,
|
||||
height: number | null | undefined = undefined,
|
||||
minSizeDivisor = 1,
|
||||
maxSizeDivisor = 1,
|
||||
minSizeMultiplier = 1,
|
||||
maxSizeMultiplier = 1,
|
||||
minFrameRate = 15,
|
||||
maxFrameRate = 60
|
||||
) => {
|
||||
@ -17,10 +17,10 @@ export default async (
|
||||
chromeMediaSource: 'desktop',
|
||||
chromeMediaSourceId: sourceID,
|
||||
|
||||
minWidth: width / minSizeDivisor,
|
||||
maxWidth: width / maxSizeDivisor,
|
||||
minHeight: height / minSizeDivisor,
|
||||
maxHeight: height / maxSizeDivisor,
|
||||
minWidth: width * minSizeMultiplier,
|
||||
maxWidth: width * maxSizeMultiplier,
|
||||
minHeight: height * minSizeMultiplier,
|
||||
maxHeight: height * maxSizeMultiplier,
|
||||
|
||||
minFrameRate,
|
||||
maxFrameRate,
|
||||
|
@ -18,6 +18,7 @@ import Logger from '../../utils/logger';
|
||||
import DesktopCapturerSources from '../DesktopCapturerSourcesService';
|
||||
import setSdpMediaBitrate from './setSdpMediaBitrate';
|
||||
import getDesktopSourceStreamBySourceID from './getDesktopSourceStreamBySourceID';
|
||||
import prepareDataMessageToSendScreenSourceType from './prepareDataMessageToSendScreenSourceType';
|
||||
|
||||
const log = new Logger(__filename);
|
||||
|
||||
@ -69,11 +70,15 @@ export default class PeerConnection {
|
||||
prevStreamHeight: number;
|
||||
displayID: string;
|
||||
sourceDisplaySize: DisplaySize | undefined;
|
||||
appLanguage: string;
|
||||
appColorTheme: boolean;
|
||||
|
||||
constructor(
|
||||
roomID: string,
|
||||
sharingSessionID: string,
|
||||
user: LocalPeerUser,
|
||||
appColorTheme: boolean,
|
||||
appLanguage: string,
|
||||
roomIDService: RoomIDService,
|
||||
connectedDevicesService: ConnectedDevicesService,
|
||||
sharingSessionsService: SharingSessionsService
|
||||
@ -96,11 +101,37 @@ export default class PeerConnection {
|
||||
this.prevStreamHeight = -1;
|
||||
this.displayID = '';
|
||||
this.sourceDisplaySize = undefined;
|
||||
this.appLanguage = appLanguage;
|
||||
this.appColorTheme = appColorTheme;
|
||||
this.onDeviceConnectedCallback = () => {};
|
||||
|
||||
this.initSocketWhenUserCreatedCallback();
|
||||
}
|
||||
|
||||
setAppLanguage(lang: string) {
|
||||
this.appLanguage = lang;
|
||||
this.notifyClientWithNewLanguage();
|
||||
}
|
||||
|
||||
setAppTheme(theme: boolean) {
|
||||
this.appColorTheme = theme;
|
||||
this.notifyClientWithNewColorTheme();
|
||||
}
|
||||
|
||||
notifyClientWithNewLanguage() {
|
||||
this.sendEncryptedMessage({
|
||||
type: 'APP_LANGUAGE',
|
||||
payload: { value: this.appLanguage },
|
||||
});
|
||||
}
|
||||
|
||||
notifyClientWithNewColorTheme() {
|
||||
this.sendEncryptedMessage({
|
||||
type: 'APP_THEME',
|
||||
payload: { value: this.appColorTheme },
|
||||
});
|
||||
}
|
||||
|
||||
setDesktopCapturerSourceID(id: string) {
|
||||
this.desktopCapturerSourceID = id;
|
||||
if (process.env.RUN_MODE === 'test') return;
|
||||
@ -137,9 +168,14 @@ export default class PeerConnection {
|
||||
this.sendEncryptedMessage({
|
||||
type: 'DENY_TO_CONNECT',
|
||||
payload: {},
|
||||
});
|
||||
|
||||
this.disconnectPartner();
|
||||
})
|
||||
// eslint-disable-next-line promise/always-return
|
||||
.then(() => {
|
||||
this.disconnectPartner();
|
||||
})
|
||||
.catch((e) => {
|
||||
log.error(e);
|
||||
});
|
||||
}
|
||||
|
||||
sendUserAllowedToConnect() {
|
||||
@ -153,10 +189,15 @@ export default class PeerConnection {
|
||||
this.sendEncryptedMessage({
|
||||
type: 'DISCONNECT_BY_HOST_MACHINE_USER',
|
||||
payload: {},
|
||||
});
|
||||
|
||||
this.disconnectPartner();
|
||||
this.selfDestrory();
|
||||
})
|
||||
// eslint-disable-next-line promise/always-return
|
||||
.then(() => {
|
||||
this.disconnectPartner();
|
||||
this.selfDestrory();
|
||||
})
|
||||
.catch((e) => {
|
||||
log.error(e);
|
||||
});
|
||||
}
|
||||
|
||||
disconnectPartner() {
|
||||
@ -284,13 +325,10 @@ export default class PeerConnection {
|
||||
async receiveEncryptedMessage(payload: ReceiveEncryptedMessagePayload) {
|
||||
if (!this.user) return;
|
||||
const message = await processMessage(payload, this.user.privateKey);
|
||||
log.info(message);
|
||||
if (message.type === 'CALL_ACCEPTED') {
|
||||
this.peer.signal(message.payload.signalData);
|
||||
}
|
||||
if (message.type === 'DEVICE_DETAILS') {
|
||||
log.info(message);
|
||||
log.info(message.payload.browser);
|
||||
this.socket.emit(
|
||||
'GET_IP_BY_SOCKET_ID',
|
||||
message.payload.socketID,
|
||||
@ -310,6 +348,18 @@ export default class PeerConnection {
|
||||
}
|
||||
);
|
||||
}
|
||||
if (message.type === 'GET_APP_THEME') {
|
||||
this.sendEncryptedMessage({
|
||||
type: 'APP_THEME',
|
||||
payload: { value: this.appColorTheme },
|
||||
});
|
||||
}
|
||||
if (message.type === 'GET_APP_LANGUAGE') {
|
||||
this.sendEncryptedMessage({
|
||||
type: 'APP_LANGUAGE',
|
||||
payload: { value: this.appLanguage },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
callPeer() {
|
||||
@ -358,18 +408,21 @@ export default class PeerConnection {
|
||||
this.peer = peer;
|
||||
|
||||
this.peer.on('data', async (data) => {
|
||||
if (`${data}` === 'set half quality') {
|
||||
// TODO: later on change to more sophisticated quality change for app window
|
||||
const dataJSON = JSON.parse(data);
|
||||
|
||||
if (dataJSON.type === 'set_video_quality') {
|
||||
const maxVideoQualityMultiplier = dataJSON.payload.value;
|
||||
const minVideoQualityMultiplier =
|
||||
maxVideoQualityMultiplier === 1 ? 0.5 : maxVideoQualityMultiplier;
|
||||
|
||||
if (!this.desktopCapturerSourceID.includes('screen')) return;
|
||||
|
||||
const newStream = await getDesktopSourceStreamBySourceID(
|
||||
this.desktopCapturerSourceID,
|
||||
this.sourceDisplaySize?.width,
|
||||
this.sourceDisplaySize?.height,
|
||||
2,
|
||||
2,
|
||||
15,
|
||||
30
|
||||
minVideoQualityMultiplier,
|
||||
maxVideoQualityMultiplier
|
||||
);
|
||||
const newVideoTrack = newStream.getVideoTracks()[0];
|
||||
const oldTrack = this.localStream?.getVideoTracks()[0];
|
||||
@ -378,23 +431,14 @@ export default class PeerConnection {
|
||||
peer.replaceTrack(oldTrack, newVideoTrack, this.localStream);
|
||||
oldTrack.stop();
|
||||
}
|
||||
} else if (`${data}` === 'set good quality') {
|
||||
// TODO: later on change to more sophisticated quality change for app window
|
||||
if (!this.desktopCapturerSourceID.includes('screen')) return;
|
||||
}
|
||||
|
||||
const newStream = await getDesktopSourceStreamBySourceID(
|
||||
this.desktopCapturerSourceID,
|
||||
this.sourceDisplaySize?.width,
|
||||
this.sourceDisplaySize?.height,
|
||||
2,
|
||||
1
|
||||
);
|
||||
const newVideoTrack = newStream.getVideoTracks()[0];
|
||||
const oldTrack = this.localStream?.getVideoTracks()[0];
|
||||
if (oldTrack && this.localStream) {
|
||||
peer.replaceTrack(oldTrack, newVideoTrack, this.localStream);
|
||||
oldTrack.stop();
|
||||
}
|
||||
if (dataJSON.type === 'get_sharing_source_type') {
|
||||
const sourceType = this.desktopCapturerSourceID.includes('screen')
|
||||
? 'screen'
|
||||
: 'window';
|
||||
|
||||
this.peer.send(prepareDataMessageToSendScreenSourceType(sourceType));
|
||||
}
|
||||
});
|
||||
return peer;
|
||||
@ -419,7 +463,7 @@ export default class PeerConnection {
|
||||
sourceID,
|
||||
this.sourceDisplaySize?.width,
|
||||
this.sourceDisplaySize?.height,
|
||||
2,
|
||||
0.5,
|
||||
1
|
||||
).then((stream) => {
|
||||
this.localStream = stream;
|
||||
|
@ -0,0 +1,10 @@
|
||||
export default (s: string) => {
|
||||
return `
|
||||
{
|
||||
"type": "screen_sharing_source_type",
|
||||
"payload": {
|
||||
"value": "${s}"
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
@ -26,7 +26,9 @@ describe('SharingSession unit tests', () => {
|
||||
},
|
||||
};
|
||||
},
|
||||
}
|
||||
},
|
||||
'',
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -24,7 +24,9 @@ export default class SharingSession {
|
||||
constructor(
|
||||
_roomID: string,
|
||||
user: LocalPeerUser,
|
||||
peerConnectionHelperRendererService: PeerConnectionHelperRendererService
|
||||
peerConnectionHelperRendererService: PeerConnectionHelperRendererService,
|
||||
appLanguage: string,
|
||||
isDarkTheme: boolean
|
||||
) {
|
||||
this.id = uuid.v4();
|
||||
this.deviceID = '';
|
||||
@ -49,6 +51,8 @@ export default class SharingSession {
|
||||
roomID: this.roomID,
|
||||
sharingSessionID: this.id,
|
||||
user,
|
||||
appTheme: isDarkTheme,
|
||||
appLanguage,
|
||||
}
|
||||
);
|
||||
});
|
||||
@ -107,6 +111,20 @@ export default class SharingSession {
|
||||
);
|
||||
}
|
||||
|
||||
appLanguageChanged(newLang: string) {
|
||||
this.peerConnectionHelperRenderer?.webContents.send(
|
||||
'app-language-changed',
|
||||
newLang
|
||||
);
|
||||
}
|
||||
|
||||
appThemeChanged(isDarkTheme: boolean) {
|
||||
this.peerConnectionHelperRenderer?.webContents.send(
|
||||
'app-color-theme-changed',
|
||||
isDarkTheme
|
||||
);
|
||||
}
|
||||
|
||||
addStatusChangeListener(callback: SharingSessionStatusChangeListener): void {
|
||||
this.statusChangeListeners.push(callback);
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ export default class SharingSessionService {
|
||||
connectedDevicesService: ConnectedDevicesService;
|
||||
rendererWebrtcHelpersService: RendererWebrtcHelpersService;
|
||||
isCreatingNewSharingSession: boolean;
|
||||
appLanguage = 'en';
|
||||
isDarkTheme = false;
|
||||
|
||||
constructor(
|
||||
_roomIDService: RoomIDService,
|
||||
@ -38,6 +40,14 @@ export default class SharingSessionService {
|
||||
}, 1000 * 60 * 60); // every hour
|
||||
}
|
||||
|
||||
setAppLanguage(newLang: string): void {
|
||||
this.appLanguage = newLang;
|
||||
}
|
||||
|
||||
setAppTheme(isDarkTheme: boolean): void {
|
||||
this.isDarkTheme = isDarkTheme;
|
||||
}
|
||||
|
||||
createUser(): Promise<undefined> {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve) => {
|
||||
@ -75,10 +85,13 @@ export default class SharingSessionService {
|
||||
|
||||
createNewSharingSession(_roomID: string): SharingSession {
|
||||
const roomID = _roomID || this.roomIDService.getSimpleAvailableRoomID();
|
||||
this.roomIDService.markRoomIDAsTaken(roomID);
|
||||
const sharingSession = new SharingSession(
|
||||
roomID,
|
||||
this.user as LocalPeerUser,
|
||||
this.rendererWebrtcHelpersService
|
||||
this.rendererWebrtcHelpersService,
|
||||
this.appLanguage,
|
||||
this.isDarkTheme
|
||||
);
|
||||
this.sharingSessions.set(sharingSession.id, sharingSession);
|
||||
return sharingSession;
|
||||
@ -87,7 +100,6 @@ export default class SharingSessionService {
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
changeSharingSessionStatusToSharing(sharingSession: SharingSession) {
|
||||
sharingSession.status = SharingSessionStatusEnum.SHARING;
|
||||
this.roomIDService.markRoomIDAsTaken(sharingSession.roomID);
|
||||
}
|
||||
|
||||
pollForInactiveSessions(): void {
|
||||
|
BIN
app/images/red_heart_2764_twemoji_120x120.png
Normal file
BIN
app/images/red_heart_2764_twemoji_120x120.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
@ -3,5 +3,6 @@
|
||||
"Signaling server is running on port": "Signaling server is running on port ⚓",
|
||||
"ru": "Русский",
|
||||
"en": "English",
|
||||
"ua": "Українська"
|
||||
"ua": "Українська",
|
||||
"Scan the QR code": "Scan the QR code"
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"ru": "ru",
|
||||
"en": "en"
|
||||
}
|
@ -3,5 +3,6 @@
|
||||
"Signaling server is running on port": "Сигнальный сервер работает на порте ⚓",
|
||||
"ru": "Русский",
|
||||
"en": "English",
|
||||
"ua": "Українська"
|
||||
"ua": "Українська",
|
||||
"Scan the QR code": "Отсканируйте QR код"
|
||||
}
|
||||
|
@ -3,5 +3,6 @@
|
||||
"Signaling server is running on port": "Сигнальный сервер працює на порту ⚓",
|
||||
"ru": "Русский",
|
||||
"en": "English",
|
||||
"ua": "Українська"
|
||||
"ua": "Українська",
|
||||
"Scan the QR code": "Відскануйте QR код"
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ ipcRenderer.on('create-peer-connection-with-data', (_, data) => {
|
||||
data.roomID,
|
||||
data.sharingSessionID,
|
||||
data.user,
|
||||
data.appTheme, // TODO getAppTheme
|
||||
data.appLanguage, // TODO getLanguage
|
||||
roomIDService,
|
||||
connectedDevicesService,
|
||||
sharingSessionsService
|
||||
@ -48,3 +50,11 @@ ipcRenderer.on('deny-connection-for-partner', () => {
|
||||
ipcRenderer.on('send-user-allowed-to-connect', () => {
|
||||
peerConnection.sendUserAllowedToConnect();
|
||||
});
|
||||
|
||||
ipcRenderer.on('app-color-theme-changed', (_, newTheme: boolean) => {
|
||||
peerConnection.setAppTheme(newTheme);
|
||||
});
|
||||
|
||||
ipcRenderer.on('app-language-changed', (_, newLang: string) => {
|
||||
peerConnection.setAppLanguage(newLang);
|
||||
});
|
||||
|
@ -33,4 +33,8 @@ export default class RoomIDService {
|
||||
public unmarkRoomIDAsTaken(id: string) {
|
||||
this.takenRoomIDs.delete(id);
|
||||
}
|
||||
|
||||
public isRoomIDTaken(id: string) {
|
||||
return this.takenRoomIDs.has(id);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import { getIO } from '.';
|
||||
import socketsIPService from './socketsIPService';
|
||||
import getStore from './store';
|
||||
|
||||
const LOCALHOST_SOCKET_IP = '::1';
|
||||
|
||||
interface User {
|
||||
socketId: string;
|
||||
publicKey: string;
|
||||
@ -152,7 +154,8 @@ export default class Socket implements SocketOPTS {
|
||||
{
|
||||
socketId: socket.id,
|
||||
publicKey: payload.publicKey,
|
||||
isOwner: (room.users || []).length === 0,
|
||||
isOwner:
|
||||
LOCALHOST_SOCKET_IP === socket.request.connection.remoteAddress,
|
||||
ip: payload.ip ? payload.ip : '',
|
||||
},
|
||||
],
|
||||
|
@ -22,6 +22,7 @@ import getStore from './store';
|
||||
import Logger from '../utils/logger';
|
||||
import isProduction from '../utils/isProduction';
|
||||
import SocketsIPService from './socketsIPService';
|
||||
import getDeskreenGlobal from '../mainProcessHelpers/getDeskreenGlobal';
|
||||
|
||||
const log = new Logger('app/server/index.ts');
|
||||
|
||||
@ -90,25 +91,34 @@ io.sockets.on('connection', (socket) => {
|
||||
io.on('connection', async (socket) => {
|
||||
const { roomId } = socket.handshake.query;
|
||||
|
||||
const roomIdHash = getRoomIdHash(roomId);
|
||||
setTimeout(async () => {
|
||||
if (!getDeskreenGlobal().roomIDService.isRoomIDTaken(roomId)) {
|
||||
socket.emit('NOT_ALLOWED');
|
||||
setTimeout(() => {
|
||||
socket.disconnect();
|
||||
}, 1000);
|
||||
} else {
|
||||
const roomIdHash = getRoomIdHash(roomId);
|
||||
|
||||
let room = await store.get('rooms', roomIdHash);
|
||||
room = JSON.parse(room || '{}');
|
||||
let room = await store.get('rooms', roomIdHash);
|
||||
room = JSON.parse(room || '{}');
|
||||
|
||||
// eslint-disable-next-line no-new
|
||||
new DarkwireSocket({
|
||||
roomIdOriginal: roomId,
|
||||
roomId: roomIdHash,
|
||||
socket,
|
||||
room,
|
||||
});
|
||||
// eslint-disable-next-line no-new
|
||||
new DarkwireSocket({
|
||||
roomIdOriginal: roomId,
|
||||
roomId: roomIdHash,
|
||||
socket,
|
||||
room,
|
||||
});
|
||||
}
|
||||
}, 1000); // timeout 1 second for throttling malitios connections
|
||||
});
|
||||
|
||||
const init = async (PORT: number) => {
|
||||
pollForInactiveRooms();
|
||||
|
||||
return server.listen(PORT, () => {
|
||||
log.info(`Signaling server is online at port ${PORT}`);
|
||||
log.info(`Deskreen signaling server is online at port ${PORT}`);
|
||||
});
|
||||
};
|
||||
|
||||
|
14
app/utils/ProcessedMessage.d.ts
vendored
14
app/utils/ProcessedMessage.d.ts
vendored
@ -17,6 +17,18 @@ type DeviceDetailsMessageWithPayload = {
|
||||
};
|
||||
};
|
||||
|
||||
type GetAppThemeMessageWithPayload = {
|
||||
type: 'GET_APP_THEME';
|
||||
payload: Record<string, unknown>;
|
||||
};
|
||||
|
||||
type GetAppLanguageMessageWithPayload = {
|
||||
type: 'GET_APP_LANGUAGE';
|
||||
payload: Record<string, unknown>;
|
||||
};
|
||||
|
||||
type ProcessedMessage =
|
||||
| CallAcceptedMessageWithPayload
|
||||
| DeviceDetailsMessageWithPayload;
|
||||
| DeviceDetailsMessageWithPayload
|
||||
| GetAppThemeMessageWithPayload
|
||||
| GetAppLanguageMessageWithPayload;
|
||||
|
@ -108,8 +108,8 @@ async function openLargeQRCodeDialog(t) {
|
||||
await t.click(magnifyQRCodeButton());
|
||||
}
|
||||
|
||||
async function clickCrossButtonToCloseDialog(t) {
|
||||
await t.click(crossCloseDialogButton());
|
||||
async function clickOnLargeQRCodeDialog(t) {
|
||||
await t.click(largeQRCodeDialog());
|
||||
}
|
||||
|
||||
async function openConnectedDeviceInfoPopover(t) {
|
||||
@ -239,7 +239,7 @@ test(`when large QR overflow is opened,
|
||||
|
||||
it should close large QR code overflow`, async (t) => {
|
||||
await openLargeQRCodeDialog(t);
|
||||
await clickCrossButtonToCloseDialog(t);
|
||||
await clickOnLargeQRCodeDialog(t);
|
||||
|
||||
const largeQrCodeDialogExists = largeQRCodeDialog().exists;
|
||||
await t.expect(largeQrCodeDialogExists).notOk();
|
||||
|
Loading…
x
Reference in New Issue
Block a user