1
0
mirror of https://github.com/pavlobu/deskreen.git synced 2025-05-16 23:40:15 -07:00

translations ru,ua done, ready for 1.0.6

This commit is contained in:
Pavlo Buidenkov 2021-02-09 14:09:39 +02:00
parent 7f0ca455cc
commit 1129b67c3a
73 changed files with 4449 additions and 1543 deletions

View File

@ -147,6 +147,10 @@ div.class-allow-device-to-connect-alert {
z-index: 9999; z-index: 9999;
} }
.class-allow-device-to-connect-alert > div > .bp3-button {
border-radius: 50px;
}
/* ALLOW CONNECTION ALERT BLINK ANIMATION START */ /* ALLOW CONNECTION ALERT BLINK ANIMATION START */
div.class-allow-device-to-connect-alert div.class-allow-device-to-connect-alert
> div.bp3-alert-body > div.bp3-alert-body

View File

@ -1,4 +1,39 @@
{ {
"Waiting for user to click ALLOW button on screen sharing device...": "Waiting for user to click ALLOW button on screen sharing device...", "Waiting for user to click ALLOW button on screen sharing device...": "Waiting for user to click ALLOW button on screen sharing device...",
"Waiting for user to select source to share from screen sharing device...": "Waiting for user to select source to share from screen sharing device..." "Waiting for user to select source to share from screen sharing device...": "Waiting for user to select source to share from screen sharing device...",
"My Device Info": "My Device Info",
"Device Type": "Device Type",
"Your Device IP should match with Device IP in alert popup appeared on your computer, where Deskreen is running": "Your Device IP should match with \"Device IP\" in alert popup appeared on your computer, where Deskreen is running.",
"Device IP": "Device IP",
"Device Browser": "Device Browser",
"Device OS": "Device OS",
"These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running": "These details should match with the ones that you see in alert popup on screen sharing device.",
"Deskreen Screen Viewer": "Deskreen Screen Viewer",
"Connected!": "Connected!",
"Error occurred": "Error occurred",
"Deskreen Error Dialog": "Deskreen Error Dialog",
"Something went wrong": "Something went wrong",
"You may close this browser window then try to connect again": "You may close this browser window then try to connect again",
"An unknown error occurred": "An unknown error occurred",
"You were not allowed to connect": "You were not allowed to connect",
"You were disconnected": "You were disconnected",
"WebRTC error occurred": "WebRTC error occurred",
"If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better": "If you like Deskreen, consider contributing financially. Deskreen is open-source. Your donations keep us motivated to make Deskreen even better.",
"Donate": "Donate",
"Video stream is paused": "Video stream is paused",
"Video stream is playing": "Video stream is playing",
"Pause": "Pause",
"Play": "Play",
"Video Settings": "Video Settings",
"Flip": "Flip",
"Video quality has been changed to": "Video quality has been changed to",
"Click to Open Video Settings": "Click to Open Video Settings",
"Click to Enter Full Screen Mode": "Click to Enter Full Screen Mode",
"Default video player has been turned OFF": "Default video player has been turned OFF",
"Default video player has been turned ON": "Default video player has been turned ON",
"ON": "ON",
"OFF": "OFF",
"Default Video Player": "Default Video Player",
"Click to visit our website": "Click to visit our website",
"Video is flipped horizontally": "Video is flipped horizontally"
} }

View File

@ -1,4 +1,39 @@
{ {
"Waiting for user to click ALLOW button on screen sharing device...": "Жду когда пользователь нажмет кнопку РАЗРЕШИТЬ доступ к экрану компьютера...", "Waiting for user to click ALLOW button on screen sharing device...": "Ждем когда пользователь нажмет кнопку РАЗРЕШИТЬ для доступа к экрану компьютера...",
"Waiting for user to select source to share from screen sharing device...": "Жду когда пользователь выберет весь экран или окно приложения для демонстрации..." "Waiting for user to select source to share from screen sharing device...": "Ждем когда пользователь выберет Весь экран или Окно приложения для отображения его здесь...",
"My Device Info": "Информация о моем устройстве",
"Device Type": "Тип устройства",
"Your Device IP should match with Device IP in alert popup appeared on your computer, where Deskreen is running": "IP-aдрес вашего устройства должен совпадать с «IP-адресом устройства» во всплывающем окне с предупреждением на компьютере, где работает Deskreen.",
"Device IP": "IP-aдрес устройства",
"Device Browser": "Веб-браузер устройства",
"Device OS": "ОС устройства",
"These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running": "Эти данные должны совпадать с теми, которые вы видите во всплывающем окне предупреждения на экране компьютера, на котором работает Deskreen.",
"Deskreen Screen Viewer": "Просмотрщик экрана Deskreen",
"Connected!": "Подключено!",
"Error occurred": "Произошла ошибка",
"Deskreen Error Dialog": "Диалог ошибки Deskreen",
"Something went wrong": "Произошло что-то не так",
"You may close this browser window then try to connect again": "Вы можете закрыть это окно браузера и попытаться подключиться снова",
"An unknown error occurred": "Произошла неизвестная ошибка",
"You were not allowed to connect": "Вам не разрешили подключиться",
"You were disconnected": "Вы были отключены",
"WebRTC error occurred": "Произошла ошибка WebRTC",
"If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better": "Если вам нравится Deskreen, подумайте о том, чтобы внести финансовый вклад. Deskreen - это оупенсорсный проэкт. Ваши пожертвования позволяют нам делать Deskreen еще лучше.",
"Donate": "Пожертвовать",
"Video stream is paused": "Видеопоток приостановлен",
"Video stream is playing": "Видеопоток воспроизводится",
"Pause": "Pause",
"Play": "Play",
"Video Settings": "Настройки видео",
"Flip": "Отзеркалить",
"Video quality has been changed to": "Качество видео изменено на",
"Click to Open Video Settings": "Нажмите, чтобы открыть настройки видео",
"Click to Enter Full Screen Mode": "Нажмите, чтобы перейти в полноэкранный режим",
"Default video player has been turned OFF": "Видеоплеер по умолчанию отключен",
"Default video player has been turned ON": "Видеопроигрыватель по умолчанию включен",
"ON": "ВКЛ",
"OFF": "ВЫКЛ",
"Default Video Player": "Видеоплеер по умолчанию",
"Click to visit our website": "Нажмите, чтобы посетить наш сайт",
"Video is flipped horizontally": "Видео отзеркалено"
} }

View File

@ -1,4 +1,39 @@
{ {
"Waiting for user to click ALLOW button on screen sharing device...": "Чекаэмо коли користувач натисне кнопку ДОЗВОЛИТИ доступ до екрану комп'ютера...", "Waiting for user to click ALLOW button on screen sharing device...": "Чекаємо коли користувач натисне кнопку ДОЗВОЛИТИ для доступу до екрану комп'ютера...",
"Waiting for user to select source to share from screen sharing device...": "Чекаю коли користувач вибере весь екран або вікно програми для демонстрації..." "Waiting for user to select source to share from screen sharing device...": "Чекаємо коли користувач вибере Весь екран або Вікно додатка для відображення його тут...",
"My Device Info": "Інформація про мій пристрій",
"Device Type": "Тип пристрою",
"Your Device IP should match with Device IP in alert popup appeared on your computer, where Deskreen is running": "IP-aдрес пристрою вашого пристрою має збігатися з «IP-адресою пристрою» у спливаючому вікні сповіщення, що з’явилося на комп’ютері, де працює Deskreen.",
"Device IP": "IP-aдрес пристрою",
"Device Browser": "Веб-браузер пристрою",
"Device OS": "ОС пристрою",
"These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running": "Ці деталі повинні збігатися з тими, які ви бачите у спливаючому вікні сповіщень на екрані комп’ютера, де запущений Deskreen.",
"Deskreen Screen Viewer": "Переглядач екрану Deskreen",
"Connected!": "Підключено!",
"Error occurred": "Виникла помилка",
"Deskreen Error Dialog": "Діалог помилки Deskreen",
"Something went wrong": "Щось не так сталося",
"You may close this browser window then try to connect again": "Ви можете закрити це вікно браузера та спробувати підключитися знову",
"An unknown error occurred": "Виникла невідома помилка",
"You were not allowed to connect": "Вам не дозволили підключитися",
"You were disconnected": "Ви були відключені",
"WebRTC error occurred": "Сталася помилка WebRTC",
"If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better": "Якщо вам подобається Deskreen, подумайте про те, щоб внести фінансовий внесок. Deskreen - це оупенсорсний проект. Ваші пожертвування дозволяють нам робити Deskreen ще краще.",
"Donate": "Пожертвувати",
"Video stream is paused": "Відеопотік призупинено",
"Video stream is playing": "Відеопотік продовжується",
"Pause": "Pause",
"Play": "Play",
"Video Settings": "Настройки видео",
"Flip": "Віддзеркалити",
"Video quality has been changed to": "Якість відео змінено на",
"Click to Open Video Settings": "Натисніть, щоб відкрити настройки відео",
"Click to Enter Full Screen Mode": "Натисніть для входу в повноекранноий режим",
"Default video player has been turned OFF": "Стандартний відеоплеєр браузера вимкнено",
"Default video player has been turned ON": "Стандартний відеоплеєр браузера включений",
"ON": "ВКЛ",
"OFF": "ВИМК",
"Default Video Player": "Стандартний відеоплеєр браузера",
"Click to visit our website": "Клацніть, щоб відвідати наш веб-сайт",
"Video is flipped horizontally": "Відео віддзеркалено"
} }

View File

@ -1,7 +1,7 @@
export enum ErrorMessage { export enum ErrorMessage {
UNKNOWN_ERROR = 'An unknown error uccured.', UNKNOWN_ERROR = 'An unknown error occurred',
DENY_TO_CONNECT = 'You were not allowed to connect.', DENY_TO_CONNECT = 'You were not allowed to connect',
DISCONNECTED = 'You were disconnected.', DISCONNECTED = 'You were disconnected',
NOT_ALLOWED = 'You were not allowed to connect.', NOT_ALLOWED = 'You were not allowed to connect',
WEBRTC_ERROR = 'WebRTC error occurred.' WEBRTC_ERROR = 'WebRTC error occurred'
} }

View File

@ -9,6 +9,7 @@ import {
Icon, Icon,
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { Col, Row } from 'react-flexbox-grid'; import { Col, Row } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
import './index.css'; import './index.css';
import { ErrorMessage } from './ErrorMessageEnum'; import { ErrorMessage } from './ErrorMessageEnum';
@ -18,6 +19,7 @@ interface ErrorDialogProps {
} }
function ErrorDialog(props: ErrorDialogProps) { function ErrorDialog(props: ErrorDialogProps) {
const { t } = useTranslation();
const { errorMessage, isOpen } = props; const { errorMessage, isOpen } = props;
return ( return (
@ -37,7 +39,7 @@ function ErrorDialog(props: ErrorDialogProps) {
> >
<Row center="xs" style={{ marginTop: '10px' }}> <Row center="xs" style={{ marginTop: '10px' }}>
<Col xs={12}> <Col xs={12}>
<H3 className={Classes.TEXT_MUTED}>Deskreen Error Dialog</H3> <H3 className={Classes.TEXT_MUTED}>{t('Deskreen Error Dialog')}</H3>
</Col> </Col>
</Row> </Row>
<Row middle="xs" center="xs" style={{ padding: '20px', width: '100%' }}> <Row middle="xs" center="xs" style={{ padding: '20px', width: '100%' }}>
@ -51,7 +53,7 @@ function ErrorDialog(props: ErrorDialogProps) {
className={Classes.TEXT_DISABLED} className={Classes.TEXT_DISABLED}
style={{ marginBottom: '0px' }} style={{ marginBottom: '0px' }}
> >
Something wrong happened :( {`${t('Something went wrong')} :(`}
</H1> </H1>
</Col> </Col>
</Row> </Row>
@ -59,9 +61,9 @@ function ErrorDialog(props: ErrorDialogProps) {
</Row> </Row>
<Divider /> <Divider />
<div className={Classes.DIALOG_BODY}> <div className={Classes.DIALOG_BODY}>
<H3 className={Classes.TEXT_MUTED}>{errorMessage}</H3> <H3 className={Classes.TEXT_MUTED}>{t(`${errorMessage}`)}</H3>
<Divider /> <Divider />
<H2>You may close this browser window then try to connect again.</H2> <H2>{`${t('You may close this browser window then try to connect again')}.`}</H2>
</div> </div>
</Dialog> </Dialog>
); );

View File

@ -1,5 +1,6 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { Callout, Card, H3, Text, Tooltip, Position } from '@blueprintjs/core'; import { Callout, Card, H3, Text, Tooltip, Position } from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import { AppContext } from '../../providers/AppContextProvider'; import { AppContext } from '../../providers/AppContextProvider';
import { import {
DARK_UI_BACKGROUND, DARK_UI_BACKGROUND,
@ -11,6 +12,7 @@ interface MyDeviceDetailsCardProps {
} }
function MyDeviceInfoCard(props: MyDeviceDetailsCardProps) { function MyDeviceInfoCard(props: MyDeviceDetailsCardProps) {
const { t } = useTranslation();
const { isDarkTheme } = useContext(AppContext); const { isDarkTheme } = useContext(AppContext);
const { deviceDetails } = props; const { deviceDetails } = props;
@ -24,11 +26,11 @@ function MyDeviceInfoCard(props: MyDeviceDetailsCardProps) {
marginBottom: '30px', marginBottom: '30px',
}} }}
> >
<H3>My Device Info:</H3> <H3>{`${t('My Device Info')}:`}</H3>
<Callout> <Callout>
<Text>Device Type: {myDeviceType}</Text> <Text>{`${t('Device Type')}: ${myDeviceType}`}</Text>
<Tooltip <Tooltip
content="This should match with 'Device IP' in alert popup appeared on your computer, where Deskreen is running." content={t('Your Device IP should match with Device IP in alert popup appeared on your computer, where Deskreen is running')}
position={Position.TOP} position={Position.TOP}
> >
<div <div
@ -40,15 +42,14 @@ function MyDeviceInfoCard(props: MyDeviceDetailsCardProps) {
borderRadius: '20px', borderRadius: '20px',
}} }}
> >
<Text>Device IP: {myIP}</Text> <Text>{`${t('Device IP')}: ${myIP}`}</Text>
</div> </div>
</Tooltip> </Tooltip>
<Text>Device Browser: {myBrowser}</Text> <Text>{`${t('Device Browser')}: ${myBrowser}`}</Text>
<Text>Device OS: {myOS}</Text> <Text>{`${t('Device OS')}: ${myOS}`}</Text>
</Callout> </Callout>
<Text className="bp3-text-muted"> <Text className="bp3-text-muted">
These details should match with the ones that you see in alert popup on {t('These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running')}
screen sharing device.
</Text> </Text>
</Card> </Card>
); );

View File

@ -127,7 +127,7 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Donate! Donate
</div> </div>
</div> </div>
</div> </div>

View File

@ -19,6 +19,7 @@ import {
Toaster, Toaster,
Intent, Intent,
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import FullScreenEnter from '../../images/fullscreen_24px.svg'; import FullScreenEnter from '../../images/fullscreen_24px.svg';
import FullScreenExit from '../../images/fullscreen_exit-24px.svg'; import FullScreenExit from '../../images/fullscreen_exit-24px.svg';
import RedHeartTwemojiPNG from '../../images/red_heart_2764_twemoji_120x120.png'; import RedHeartTwemojiPNG from '../../images/red_heart_2764_twemoji_120x120.png';
@ -50,6 +51,7 @@ interface PlayerControlPanelProps {
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
function PlayerControlPanel(props: PlayerControlPanelProps) { function PlayerControlPanel(props: PlayerControlPanelProps) {
const { t } = useTranslation();
const { const {
isPlaying, isPlaying,
onSwitchChangedCallback, onSwitchChangedCallback,
@ -92,9 +94,9 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
toaster?.show({ toaster?.show({
icon: 'clean', icon: 'clean',
intent: Intent.PRIMARY, intent: Intent.PRIMARY,
message: `Video is flipped horizontally`, message: t('Video is flipped horizontally'),
}); });
}, [isVideoFlipped, toaster]); }, [isVideoFlipped, toaster, t]);
return ( return (
<> <>
@ -102,7 +104,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
<Row between="xs" middle="xs"> <Row between="xs" middle="xs">
<Col xs={12} md={3}> <Col xs={12} md={3}>
<Tooltip <Tooltip
content="Click to visit our website" content={t('Click to visit our website')}
position={Position.BOTTOM} position={Position.BOTTOM}
> >
<Button <Button
@ -127,7 +129,9 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip <Tooltip
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!" content={t(
'If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better'
)}
position={Position.BOTTOM} position={Position.BOTTOM}
> >
<Button <Button
@ -150,7 +154,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
<div <div
style={{ transform: 'translateY(2px) translateX(-5px)' }} style={{ transform: 'translateY(2px) translateX(-5px)' }}
> >
<Text>Donate!</Text> <Text>{t('Donate')}</Text>
</div> </div>
</Col> </Col>
</Row> </Row>
@ -178,8 +182,8 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
icon: isPlaying ? 'pause' : 'play', icon: isPlaying ? 'pause' : 'play',
intent: Intent.PRIMARY, intent: Intent.PRIMARY,
message: isPlaying message: isPlaying
? 'Video stream is paused.' ? t('Video stream is paused')
: 'Video stream is playing', : t('Video stream is playing'),
}); });
}} }}
style={{ style={{
@ -197,7 +201,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
</Col> </Col>
<Col xs> <Col xs>
<Text className="bp3-text-large"> <Text className="bp3-text-large">
{isPlaying ? 'Pause' : 'Play'} {isPlaying ? t('Pause') : t('Play')}
</Text> </Text>
</Col> </Col>
</Row> </Row>
@ -212,7 +216,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
<Popover <Popover
content={ content={
<> <>
<H5>Video Settings:</H5> <H5>{`${t('Video Settings')}:`}</H5>
<Divider /> <Divider />
<Row> <Row>
<Button <Button
@ -222,7 +226,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
style={videoQualityButtonStyle} style={videoQualityButtonStyle}
onClick={toggleFlipVideo} onClick={toggleFlipVideo}
> >
Flip {t('Flip')}
</Button> </Button>
</Row> </Row>
<Divider /> <Divider />
@ -242,7 +246,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
toaster?.show({ toaster?.show({
icon: 'clean', icon: 'clean',
intent: Intent.PRIMARY, intent: Intent.PRIMARY,
message: `Video quality has been changed to ${q}`, message: `${t('Video quality has been changed to')} ${q}`,
}); });
}} }}
> >
@ -256,7 +260,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
position={Position.BOTTOM} position={Position.BOTTOM}
popoverClassName={Classes.POPOVER_CONTENT_SIZING} popoverClassName={Classes.POPOVER_CONTENT_SIZING}
> >
<Tooltip content="Video Quality" position={Position.BOTTOM}> <Tooltip content={t('Click to Open Video Settings')} position={Position.BOTTOM}>
<Button minimal> <Button minimal>
<Icon icon="cog" color="white" /> <Icon icon="cog" color="white" />
</Button> </Button>
@ -271,7 +275,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
}} }}
/> />
<Tooltip <Tooltip
content="Enter Full Screen Mode" content={t('Click to Enter Full Screen Mode')}
position={Position.BOTTOM} position={Position.BOTTOM}
> >
<Button <Button
@ -310,14 +314,14 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
toaster?.show({ toaster?.show({
icon: 'video', icon: 'video',
intent: Intent.PRIMARY, intent: Intent.PRIMARY,
message: `Default video player has been turned ${ message: `${
isDefaultPlayerTurnedOn ? 'OFF' : 'ON' isDefaultPlayerTurnedOn ? t('Default video player has been turned OFF') : t('Default video player has been turned ON')
}`, }`,
}); });
}} }}
innerLabel={isDefaultPlayerTurnedOn ? 'ON' : 'OFF'} innerLabel={isDefaultPlayerTurnedOn ? t('ON') : t('OFF')}
inline inline
label={`Default Video Player`} label={t('Default Video Player')}
alignIndicator={Alignment.RIGHT} alignIndicator={Alignment.RIGHT}
checked={isDefaultPlayerTurnedOn} checked={isDefaultPlayerTurnedOn}
disabled={!isFullScreenAPIAvailable} disabled={!isFullScreenAPIAvailable}

View File

@ -54,6 +54,15 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
} }
} }
> >
<div
className="row center-xs"
>
<h2
className="bp3-heading bp3-text-muted"
>
Deskreen Screen Viewer
</h2>
</div>
<div <div
className="row center-xs" className="row center-xs"
style={ style={
@ -87,7 +96,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Type: Device Type:
</div> </div>
<span <span
className="bp3-popover-wrapper" className="bp3-popover-wrapper"
@ -116,7 +124,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device IP: Device IP:
</div> </div>
</div> </div>
</span> </span>
@ -125,19 +132,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Browser: Device Browser:
</div> </div>
<div <div
className="" className=""
> >
Device OS: Device OS:
</div> </div>
</div> </div>
<div <div
className="bp3-text-muted" className="bp3-text-muted"
> >
These details should match with the ones that you see in alert popup on screen sharing device. These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running
</div> </div>
</div> </div>
</div> </div>
@ -235,6 +240,15 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
} }
} }
> >
<div
className="row center-xs"
>
<h2
className="bp3-heading bp3-text-muted"
>
Deskreen Screen Viewer
</h2>
</div>
<div <div
className="row center-xs" className="row center-xs"
style={ style={
@ -268,7 +282,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Type: Device Type:
</div> </div>
<span <span
className="bp3-popover-wrapper" className="bp3-popover-wrapper"
@ -297,7 +310,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device IP: Device IP:
</div> </div>
</div> </div>
</span> </span>
@ -306,19 +318,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Browser: Device Browser:
</div> </div>
<div <div
className="" className=""
> >
Device OS: Device OS:
</div> </div>
</div> </div>
<div <div
className="bp3-text-muted" className="bp3-text-muted"
> >
These details should match with the ones that you see in alert popup on screen sharing device. These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running
</div> </div>
</div> </div>
</div> </div>
@ -487,6 +497,15 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
} }
} }
> >
<div
className="row center-xs"
>
<h2
className="bp3-heading bp3-text-muted"
>
Deskreen Screen Viewer
</h2>
</div>
<div <div
className="row center-xs" className="row center-xs"
style={ style={
@ -520,7 +539,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Type: Device Type:
</div> </div>
<span <span
className="bp3-popover-wrapper" className="bp3-popover-wrapper"
@ -549,7 +567,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device IP: Device IP:
</div> </div>
</div> </div>
</span> </span>
@ -558,19 +575,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Browser: Device Browser:
</div> </div>
<div <div
className="" className=""
> >
Device OS: Device OS:
</div> </div>
</div> </div>
<div <div
className="bp3-text-muted" className="bp3-text-muted"
> >
These details should match with the ones that you see in alert popup on screen sharing device. These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running
</div> </div>
</div> </div>
</div> </div>
@ -721,6 +736,15 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
} }
} }
> >
<div
className="row center-xs"
>
<h2
className="bp3-heading bp3-text-muted"
>
Deskreen Screen Viewer
</h2>
</div>
<div <div
className="row center-xs" className="row center-xs"
style={ style={
@ -754,7 +778,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Type: Device Type:
</div> </div>
<span <span
className="bp3-popover-wrapper" className="bp3-popover-wrapper"
@ -783,7 +806,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device IP: Device IP:
</div> </div>
</div> </div>
</span> </span>
@ -792,19 +814,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className="" className=""
> >
Device Browser: Device Browser:
</div> </div>
<div <div
className="" className=""
> >
Device OS: Device OS:
</div> </div>
</div> </div>
<div <div
className="bp3-text-muted" className="bp3-text-muted"
> >
These details should match with the ones that you see in alert popup on screen sharing device. These details should match with the ones that you see in alert popup on computer screen, where Deskreen is running
</div> </div>
</div> </div>
</div> </div>

View File

@ -8,7 +8,7 @@ import {
} from '../../constants/styleConstants'; } from '../../constants/styleConstants';
import MyDeviceInfoCard from '../../components/MyDeviceInfoCard'; import MyDeviceInfoCard from '../../components/MyDeviceInfoCard';
import { TFunction } from 'i18next'; import { TFunction } from 'i18next';
import { H3 } from '@blueprintjs/core'; import { H2, H3 } from '@blueprintjs/core';
import ConnectingIndicator from '../../components/ConnectingIndicator'; import ConnectingIndicator from '../../components/ConnectingIndicator';
const Slide = require('react-reveal/Slide'); const Slide = require('react-reveal/Slide');
@ -23,7 +23,7 @@ interface ConnectionPropmptsProps {
isOpen: boolean; isOpen: boolean;
} }
function getPromptContent(step: number, t: TFunction) { function getPromptContent(t: TFunction, step: number) {
switch (step) { switch (step) {
case 1: case 1:
return ( return (
@ -34,7 +34,7 @@ function getPromptContent(step: number, t: TFunction) {
</H3> </H3>
); );
case 2: case 2:
return <H3>Connected!</H3>; return <H3>{t('Connected!')}</H3>;
case 3: case 3:
return ( return (
<H3> <H3>
@ -44,7 +44,7 @@ function getPromptContent(step: number, t: TFunction) {
</H3> </H3>
); );
default: default:
return <H3>Error occurred :(</H3>; return <H3>{`${t('Error occurred')} :(`}</H3>;
} }
} }
@ -55,19 +55,14 @@ function ConnectionPropmpts(props: ConnectionPropmptsProps) {
connectionIconType, connectionIconType,
isShownSpinnerIcon, isShownSpinnerIcon,
spinnerIconType, spinnerIconType,
isOpen isOpen,
} = props; } = props;
const { t } = useTranslation(); const { t } = useTranslation();
const { isDarkTheme } = useContext(AppContext); const { isDarkTheme } = useContext(AppContext);
return ( return (
<Slide <Slide id="connection-prompts-slide" bottom when={isOpen} duration={1000}>
id="connection-prompts-slide"
bottom
when={isOpen}
duration={1000}
>
<div <div
style={{ style={{
position: 'absolute', position: 'absolute',
@ -77,7 +72,9 @@ function ConnectionPropmpts(props: ConnectionPropmptsProps) {
width: '100%', width: '100%',
height: '100vh', height: '100vh',
boxShadow: `0 0 0 5px ${isDarkTheme ? '#000' : '#A7B6C2'}`, boxShadow: `0 0 0 5px ${isDarkTheme ? '#000' : '#A7B6C2'}`,
backgroundColor: isDarkTheme ? DARK_UI_BACKGROUND : LIGHT_UI_BACKGROUND, backgroundColor: isDarkTheme
? DARK_UI_BACKGROUND
: LIGHT_UI_BACKGROUND,
}} }}
> >
<Row <Row
@ -99,13 +96,16 @@ function ConnectionPropmpts(props: ConnectionPropmptsProps) {
}} }}
> >
<div style={{ width: '100%' }}> <div style={{ width: '100%' }}>
<Row center="xs">
<H2 className="bp3-text-muted">{t('Deskreen Screen Viewer')}</H2>
</Row>
<Row center="xs" style={{ width: '100%', margin: '0 auto' }}> <Row center="xs" style={{ width: '100%', margin: '0 auto' }}>
<Col md={6} xl={4}> <Col md={6} xl={4}>
<MyDeviceInfoCard deviceDetails={myDeviceDetails} /> <MyDeviceInfoCard deviceDetails={myDeviceDetails} />
</Col> </Col>
</Row> </Row>
<div id="prompt-text" style={{ fontSize: '20px' }}> <div id="prompt-text" style={{ fontSize: '20px' }}>
{getPromptContent(promptStep, t)} {getPromptContent(t, promptStep)}
</div> </div>
</div> </div>
</Col> </Col>

View File

@ -139,7 +139,7 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Donate! Donate
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Intent, Alert, H4 } from '@blueprintjs/core'; import { Intent, Alert, H4 } from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import DeviceInfoCallout from './DeviceInfoCallout'; import DeviceInfoCallout from './DeviceInfoCallout';
import isWithReactRevealAnimations from '../utils/isWithReactRevealAnimations'; import isWithReactRevealAnimations from '../utils/isWithReactRevealAnimations';
@ -13,13 +14,16 @@ interface AllowConnectionForDeviceAlertProps {
export default function AllowConnectionForDeviceAlert( export default function AllowConnectionForDeviceAlert(
props: AllowConnectionForDeviceAlertProps props: AllowConnectionForDeviceAlertProps
) { ) {
const { t } = useTranslation();
const { device, isOpen, onCancel, onConfirm } = props; const { device, isOpen, onCancel, onConfirm } = props;
const denyText = t('Deny');
const allowText = t('Allow');
return ( return (
<Alert <Alert
className="class-allow-device-to-connect-alert" className="class-allow-device-to-connect-alert"
cancelButtonText="Deny" cancelButtonText={denyText}
confirmButtonText="Allow" confirmButtonText={allowText}
icon="feed" icon="feed"
intent={Intent.DANGER} intent={Intent.DANGER}
isOpen={isOpen} isOpen={isOpen}
@ -30,7 +34,7 @@ export default function AllowConnectionForDeviceAlert(
// @ts-ignore // @ts-ignore
usePortal={false} usePortal={false}
> >
<H4>Device is trying to connect, do you allow?</H4> <H4>{t('Someone is trying to connect, do you allow?')}</H4>
<DeviceInfoCallout <DeviceInfoCallout
deviceType={device?.deviceType} deviceType={device?.deviceType}
deviceIP={device?.deviceIP} deviceIP={device?.deviceIP}

View File

@ -2,7 +2,7 @@
/* eslint-disable react/destructuring-assignment */ /* eslint-disable react/destructuring-assignment */
import { remote } from 'electron'; import { remote } from 'electron';
import React, { useEffect, useState, useCallback } from 'react'; import React, { useEffect, useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { import {
Button, Button,
Text, Text,
@ -68,6 +68,7 @@ const useStyles = makeStyles(() =>
export default function ConnectedDevicesListDrawer( export default function ConnectedDevicesListDrawer(
props: ConnectedDevicesListDrawerProps props: ConnectedDevicesListDrawerProps
) { ) {
const { t } = useTranslation();
const classes = useStyles(); const classes = useStyles();
const [isAlertDisconectAllOpen, setIsAlertDisconectAllOpen] = useState(false); const [isAlertDisconectAllOpen, setIsAlertDisconectAllOpen] = useState(false);
@ -142,6 +143,9 @@ export default function ConnectedDevicesListDrawer(
); );
}, [handleDisconnectAll, hideAllDevicesInDevicesDisplayed, props]); }, [handleDisconnectAll, hideAllDevicesInDevicesDisplayed, props]);
const disconnectAllCancelButtonText = t('No, Cancel');
const disconnectAllConfirmButtonText = t('Yes, Disconnect All');
return ( return (
<> <>
<Drawer <Drawer
@ -157,7 +161,7 @@ export default function ConnectedDevicesListDrawer(
<Col xs={11}> <Col xs={11}>
<Row middle="xs"> <Row middle="xs">
<div className={classes.topHeader}> <div className={classes.topHeader}>
<Text className="bp3-text-muted">Connected Devices</Text> <Text className="bp3-text-muted">{t('Connected Devices')}</Text>
</div> </div>
<Button <Button
intent="danger" intent="danger"
@ -167,7 +171,7 @@ export default function ConnectedDevicesListDrawer(
}} }}
icon="disable" icon="disable"
> >
Disconnect all devices {t('Disconnect all devices')}
</Button> </Button>
</Row> </Row>
</Col> </Col>
@ -222,7 +226,7 @@ export default function ConnectedDevicesListDrawer(
}} }}
icon="disable" icon="disable"
> >
Disconnect {t('Disconnect')}
</Button> </Button>
</Row> </Row>
</Card> </Card>
@ -241,8 +245,8 @@ export default function ConnectedDevicesListDrawer(
setIsAlertDisconectAllOpen(false); setIsAlertDisconectAllOpen(false);
}} }}
icon="warning-sign" icon="warning-sign"
cancelButtonText="No, Cancel" cancelButtonText={disconnectAllCancelButtonText}
confirmButtonText="Yes, Disconnect All" confirmButtonText={disconnectAllConfirmButtonText}
intent="danger" intent="danger"
canEscapeKeyCancel canEscapeKeyCancel
canOutsideClickCancel canOutsideClickCancel
@ -253,10 +257,14 @@ export default function ConnectedDevicesListDrawer(
transitionDuration={isWithReactRevealAnimations() ? 700 : 0} transitionDuration={isWithReactRevealAnimations() ? 700 : 0}
> >
<H4> <H4>
Are you sure you want to disconnect all connected viewing devices? {t(
'Are you sure you want to disconnect all connected viewing devices?'
)}
</H4> </H4>
<Text>This step can not be reverted.</Text> <Text>{`${t('This step can not be undone')}.`}</Text>
<Text>You will have to connect all devices manually again.</Text> <Text>
{`${t('You will have to connect all devices manually again')}.`}
</Text>
</Alert> </Alert>
</> </>
); );

View File

@ -2,6 +2,8 @@
import React from 'react'; import React from 'react';
import { Callout, Text, H4, Tooltip, Position } from '@blueprintjs/core'; import { Callout, Text, H4, Tooltip, Position } from '@blueprintjs/core';
import { Row, Col } from 'react-flexbox-grid'; import { Row, Col } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
import { TFunction } from 'i18next';
interface DeviceInfoCalloutProps { interface DeviceInfoCalloutProps {
deviceType: string | undefined; deviceType: string | undefined;
@ -11,24 +13,24 @@ interface DeviceInfoCalloutProps {
deviceBrowser: string | undefined; deviceBrowser: string | undefined;
} }
function getContentOfTooltip() { function getContentOfTooltip(t: TFunction) {
return ( return (
<> <>
<Text> <Text>
{`This should match with 'Device IP' displayed on the screen of device {t(
that is trying to connect.`} 'This should match with Device IP displayed on the screen of device that is trying to connect'
)}
</Text> </Text>
<span style={{ fontWeight: 900 }}> <span style={{ fontWeight: 900 }}>
<Text> <Text>{t('If IP addresses dont match click Disconnect button')}</Text>
{`If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!`}
</Text>
</span> </span>
</> </>
); );
} }
export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) { export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) {
const { t } = useTranslation();
const { const {
deviceType, deviceType,
deviceIP, deviceIP,
@ -40,15 +42,15 @@ export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) {
return ( return (
<> <>
<H4 style={{ margin: '0 auto', textAlign: 'center' }}> <H4 style={{ margin: '0 auto', textAlign: 'center' }}>
Partner Device Info: {`${t('Partner Device Info')}:`}
</H4> </H4>
<Callout id="device-info-callout"> <Callout id="device-info-callout" style={{ borderRadius: '8px' }}>
<Row center="xs"> <Row center="xs">
<Col xs={12}> <Col xs={12}>
<Text> <Text>
Device Type: <span>{deviceType}</span> {`${t('Device Type')}:`} <span>{deviceType}</span>
</Text> </Text>
<Tooltip content={getContentOfTooltip()} position={Position.TOP}> <Tooltip content={getContentOfTooltip(t)} position={Position.TOP}>
<div <div
style={{ style={{
fontWeight: 900, fontWeight: 900,
@ -59,19 +61,20 @@ export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) {
}} }}
> >
<Text className="bp3-text-large"> <Text className="bp3-text-large">
Device IP: <span className="device-ip-span">{deviceIP}</span> {`${t('Device IP')}:`}{' '}
<span className="device-ip-span">{deviceIP}</span>
</Text> </Text>
</div> </div>
</Tooltip> </Tooltip>
<Text> <Text>
Device Browser: <span>{deviceBrowser}</span> {`${t('Device Browser')}:`} <span>{deviceBrowser}</span>
</Text> </Text>
<Text> <Text>
Device OS: <span>{deviceOS}</span> {`${t('Device OS')}:`} <span>{deviceOS}</span>
</Text> </Text>
<div style={{ width: '200px', margin: '0 auto' }}> <div style={{ width: '200px', margin: '0 auto' }}>
<Text className="bp3-text-muted" ellipsize> <Text className="bp3-text-muted" ellipsize>
Session ID: <span>{sharingSessionID}</span> {`${t('Session ID')}:`} <span>{sharingSessionID}</span>
</Text> </Text>
</div> </div>
</Col> </Col>

View File

@ -0,0 +1,59 @@
import React, { useContext, useEffect, useState } from 'react';
import { remote } from 'electron';
import { HTMLSelect } from '@blueprintjs/core';
import i18n from 'i18next';
import SharingSessionService from '../../features/SharingSessionService';
import { SettingsContext } from '../../containers/SettingsProvider';
import i18n_client, {
getLangFullNameToLangISOKeyMap,
getLangISOKeyToLangFullNameMap,
} from '../../configs/i18next.config.client';
const sharingSessionService = remote.getGlobal(
'sharingSessionService'
) as SharingSessionService;
export default function LanguageSelector() {
const { setCurrentLanguageHook } = useContext(SettingsContext);
const [languagesList, setLanguagesList] = useState([] as string[]);
useEffect(() => {
const tmp: string[] = [];
getLangFullNameToLangISOKeyMap().forEach((_, key) => {
tmp.push(key);
});
setLanguagesList(tmp);
setCurrentLanguageHook(i18n_client.language);
}, [setCurrentLanguageHook]);
const onChangeLanguageHTMLSelectHandler = (
event: React.ChangeEvent<HTMLSelectElement>
) => {
if (
event.currentTarget &&
getLangFullNameToLangISOKeyMap().has(event.currentTarget.value)
) {
const newLang =
getLangFullNameToLangISOKeyMap().get(event.currentTarget.value) ||
'English';
i18n.changeLanguage(newLang);
// TODO: call sharing sessions service here to notify all connected clients about language change
sharingSessionService.sharingSessions.forEach((sharingSession) => {
sharingSession?.appLanguageChanged();
});
}
};
return (
<HTMLSelect
value={getLangISOKeyToLangFullNameMap().get(i18n.language)}
options={languagesList}
onChange={onChangeLanguageHTMLSelectHandler}
style={{
borderRadius: '50px',
width: '120px',
}}
/>
);
}

View File

@ -1,10 +1,9 @@
/* eslint-disable jsx-a11y/anchor-is-valid */ /* eslint-disable jsx-a11y/anchor-is-valid */
/* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/click-events-have-key-events */
import { ipcRenderer, remote, shell } from 'electron'; import { ipcRenderer, shell } from 'electron';
import React, { useContext, useCallback, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { import {
Button,
Overlay, Overlay,
Classes, Classes,
H3, H3,
@ -13,38 +12,28 @@ import {
Tabs, Tabs,
Tab, Tab,
Icon, Icon,
HTMLSelect,
Text, Text,
ControlGroup,
Checkbox, Checkbox,
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Col, Row } from 'react-flexbox-grid'; import { Col, Row } from 'react-flexbox-grid';
import { createStyles, makeStyles } from '@material-ui/core/styles'; import { createStyles, makeStyles } from '@material-ui/core/styles';
import i18n from 'i18next';
import SharingSessionService from '../../features/SharingSessionService';
import { import {
DARK_UI_BACKGROUND, DARK_UI_BACKGROUND,
LIGHT_UI_BACKGROUND, LIGHT_UI_BACKGROUND,
SettingsContext, SettingsContext,
} from '../../containers/SettingsProvider'; } from '../../containers/SettingsProvider';
import CloseOverlayButton from '../CloseOverlayButton'; import CloseOverlayButton from '../CloseOverlayButton';
import i18n_client, {
getLangFullNameToLangISOKeyMap,
getLangISOKeyToLangFullNameMap,
} from '../../configs/i18next.config.client';
import SettingRowLabelAndInput from './SettingRowLabelAndInput'; import SettingRowLabelAndInput from './SettingRowLabelAndInput';
import isWithReactRevealAnimations from '../../utils/isWithReactRevealAnimations'; import isWithReactRevealAnimations from '../../utils/isWithReactRevealAnimations';
import config from '../../api/config'; import config from '../../api/config';
import LanguageSelector from '../LanguageSelector';
import ToggleThemeBtnGroup from '../ToggleThemeBtnGroup';
const { port } = config; const { port } = config;
const Fade = require('react-reveal/Fade'); const Fade = require('react-reveal/Fade');
const sharingSessionService = remote.getGlobal(
'sharingSessionService'
) as SharingSessionService;
interface SettingsOverlayProps { interface SettingsOverlayProps {
isSettingsOpen: boolean; isSettingsOpen: boolean;
handleClose: () => void; handleClose: () => void;
@ -73,13 +62,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
const [latestVersion, setLatestVersion] = useState(''); const [latestVersion, setLatestVersion] = useState('');
const [currentVersion, setCurrentVersion] = useState(''); const [currentVersion, setCurrentVersion] = useState('');
const { const { isDarkTheme } = useContext(SettingsContext);
isDarkTheme,
setIsDarkThemeHook,
setCurrentLanguageHook,
} = useContext(SettingsContext);
const [languagesList, setLanguagesList] = useState([] as string[]);
useEffect(() => { useEffect(() => {
const getLatestVersion = async () => { const getLatestVersion = async () => {
@ -98,96 +81,14 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
getCurrentVersion(); getCurrentVersion();
}, []); }, []);
useEffect(() => {
const tmp: string[] = [];
getLangFullNameToLangISOKeyMap().forEach((_, key) => {
tmp.push(key);
});
setLanguagesList(tmp);
setCurrentLanguageHook(i18n_client.language);
}, [setCurrentLanguageHook]);
const getClassesCallback = useStylesWithTheme(isDarkTheme); const getClassesCallback = useStylesWithTheme(isDarkTheme);
const handleToggleDarkTheme = useCallback(() => {
if (!isDarkTheme) {
document.body.classList.toggle(Classes.DARK);
setIsDarkThemeHook(true);
}
// TODO: call sharing sessions service here to notify all connected clients about theme change
sharingSessionService.sharingSessions.forEach((sharingSession) => {
sharingSession?.appThemeChanged(true);
});
sharingSessionService.setAppTheme(true);
}, [isDarkTheme, setIsDarkThemeHook]);
const handleToggleLightTheme = useCallback(() => {
if (isDarkTheme) {
document.body.classList.toggle(Classes.DARK);
setIsDarkThemeHook(false);
}
// TODO: call sharing sessions service here to notify all connected clients about theme change
sharingSessionService.sharingSessions.forEach((sharingSession) => {
sharingSession?.appThemeChanged(false);
});
sharingSessionService.setAppTheme(false);
}, [isDarkTheme, setIsDarkThemeHook]);
const onChangeLangueageHTMLSelectHandler = (
event: React.ChangeEvent<HTMLSelectElement>
) => {
if (
event.currentTarget &&
getLangFullNameToLangISOKeyMap().has(event.currentTarget.value)
) {
const newLang =
getLangFullNameToLangISOKeyMap().get(event.currentTarget.value) ||
'English';
i18n.changeLanguage(newLang);
// TODO: call sharing sessions service here to notify all connected clients about language change
sharingSessionService.sharingSessions.forEach((sharingSession) => {
sharingSession?.appLanguageChanged(newLang);
});
sharingSessionService.setAppLanguage(newLang);
}
};
const getThemeChangingControlGroupInput = () => {
return (
<ControlGroup fill vertical={false}>
<Button
icon="flash"
text="Light"
onClick={handleToggleLightTheme}
active={!isDarkTheme}
/>
<Button
icon="moon"
text="Dark"
onClick={handleToggleDarkTheme}
active={isDarkTheme}
/>
</ControlGroup>
);
};
const getLanguageChangingHTMLSelect = () => {
return (
<HTMLSelect
disabled // TODO: remove when tranlations are ready
defaultValue={getLangISOKeyToLangFullNameMap().get(i18n.language)}
options={languagesList}
onChange={onChangeLangueageHTMLSelectHandler}
/>
);
};
const getAutomaticUpdatesCheckboxInput = () => { const getAutomaticUpdatesCheckboxInput = () => {
return ( return (
<Checkbox <Checkbox
disabled disabled
className={getClassesCallback().checkboxSettings} className={getClassesCallback().checkboxSettings}
label="Disabled" label={t('Disabled')}
/> />
); );
}; };
@ -195,21 +96,21 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
const GeneralSettingsPanel: React.FC = () => ( const GeneralSettingsPanel: React.FC = () => (
<> <>
<Row middle="xs"> <Row middle="xs">
<H3 className="bp3-text-muted">General Settings</H3> <H3 className="bp3-text-muted">{t('General Settings')}</H3>
</Row> </Row>
<SettingRowLabelAndInput <SettingRowLabelAndInput
icon="style" icon="style"
label="Colors" label={t('Color Theme')}
input={getThemeChangingControlGroupInput()} input={<ToggleThemeBtnGroup />}
/> />
<SettingRowLabelAndInput <SettingRowLabelAndInput
icon="translate" icon="translate"
label={t('Language')} label={t('Language')}
input={getLanguageChangingHTMLSelect()} input={<LanguageSelector />}
/> />
<SettingRowLabelAndInput <SettingRowLabelAndInput
icon="automatic-updates" icon="automatic-updates"
label="Automatic Updates" label={t('Automatic Updates')}
input={getAutomaticUpdatesCheckboxInput()} input={getAutomaticUpdatesCheckboxInput()}
/> />
</> </>
@ -219,7 +120,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
<div> <div>
<H3> <H3>
<Icon icon="shield" iconSize={20} /> <Icon icon="shield" iconSize={20} />
Security {t('Security Settings')}
</H3> </H3>
<H6 className={Classes.RUNNING_TEXT}> <H6 className={Classes.RUNNING_TEXT}>
{`HTML is great for declaring static documents, but it falters when we try {`HTML is great for declaring static documents, but it falters when we try
@ -231,12 +132,6 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
</div> </div>
); );
const BlockedIPsPanel: React.FC = () => (
<div>
<H3>Blocked IPs</H3>
</div>
);
const AboutPanel: React.FC = () => ( const AboutPanel: React.FC = () => (
<Row center="xs" middle="xs" style={{ height: 'calc(100vh - 40%)' }}> <Row center="xs" middle="xs" style={{ height: 'calc(100vh - 40%)' }}>
<div> <div>
@ -248,14 +143,16 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
/> />
</Col> </Col>
<Col xs={12}> <Col xs={12}>
<H3>About Deskreen</H3> <H3>{t('About Deskreen')}</H3>
</Col>
<Col xs={12}>
<Text>{`Version: ${currentVersion} (${currentVersion})`}</Text>
</Col> </Col>
<Col xs={12}> <Col xs={12}>
<Text> <Text>
{`Copyright © ${new Date().getFullYear()} `} {`${t('Version')}: ${currentVersion} (${currentVersion})`}
</Text>
</Col>
<Col xs={12}>
<Text>
{`${t('Copyright')} © ${new Date().getFullYear()} `}
<a <a
onClick={() => { onClick={() => {
shell.openExternal('https://linkedin.com/in/pavlobu'); shell.openExternal('https://linkedin.com/in/pavlobu');
@ -268,16 +165,16 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
} }
} }
> >
Pavlo (Paul) Buidenkov Pavlo Buidenkov (Paul)
</a> </a>
</Text> </Text>
</Col> </Col>
<Col xs={12}> <Col xs={12}>
<Text> <Text>
{`Website: `} {`${t('Website')}: `}
<a <a
onClick={() => { onClick={() => {
shell.openExternal('https://www.deskreen.com'); shell.openExternal('https://deskreen.com');
}} }}
style={ style={
isDarkTheme isDarkTheme
@ -287,7 +184,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
} }
} }
> >
https://www.deskreen.com https://deskreen.com
</a> </a>
</Text> </Text>
</Col> </Col>
@ -295,18 +192,6 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
</Row> </Row>
); );
const getTabNavBlockedIPsButton = () => {
return (
<Row middle="xs" className={getClassesCallback().tabNavigationRowButton}>
<Icon
icon="blocked-person"
className={getClassesCallback().iconInTablLeftButton}
/>
<Text className="bp3-text-large">Blacklisted IPs</Text>
</Row>
);
};
const getTabNavSecurityButton = () => { const getTabNavSecurityButton = () => {
return ( return (
<Row middle="xs" className={getClassesCallback().tabNavigationRowButton}> <Row middle="xs" className={getClassesCallback().tabNavigationRowButton}>
@ -314,7 +199,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
icon="shield" icon="shield"
className={getClassesCallback().iconInTablLeftButton} className={getClassesCallback().iconInTablLeftButton}
/> />
<Text className="bp3-text-large">Security</Text> <Text className="bp3-text-large">{t('Security')}</Text>
</Row> </Row>
); );
}; };
@ -326,7 +211,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
icon="wrench" icon="wrench"
className={getClassesCallback().iconInTablLeftButton} className={getClassesCallback().iconInTablLeftButton}
/> />
<Text className="bp3-text-large">General</Text> <Text className="bp3-text-large">{t('General')}</Text>
</Row> </Row>
); );
}; };
@ -338,7 +223,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
icon="info-sign" icon="info-sign"
className={getClassesCallback().iconInTablLeftButton} className={getClassesCallback().iconInTablLeftButton}
/> />
<Text className="bp3-text-large">About</Text> <Text className="bp3-text-large">{t('About')}</Text>
</Row> </Row>
); );
}; };
@ -378,9 +263,14 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
e.preventDefault(); e.preventDefault();
shell.openExternal('https://deskreen.com'); shell.openExternal('https://deskreen.com');
}} }}
style={{
width: 'calc(100% - 50px)',
}}
> >
{/* eslint-disable-next-line react/jsx-one-expression-per-line */} {/* eslint-disable-next-line react/jsx-one-expression-per-line */}
New version {latestVersion} is available! Click to download. {`${t(
'A new version of Deskreen is available! Click to download new version'
)} ${latestVersion}`}
</H4> </H4>
) : ( ) : (
<></> <></>
@ -398,9 +288,6 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
<Tab id="ng" disabled title="" panel={<SecurityPanel />}> <Tab id="ng" disabled title="" panel={<SecurityPanel />}>
{getTabNavSecurityButton()} {getTabNavSecurityButton()}
</Tab> </Tab>
<Tab id="bb" disabled title="" panel={<BlockedIPsPanel />}>
{getTabNavBlockedIPsButton()}
</Tab>
<Tab id="cc" title="" panel={<AboutPanel />}> <Tab id="cc" title="" panel={<AboutPanel />}>
{getTabNavAboutButton()} {getTabNavAboutButton()}
</Tab> </Tab>

View File

@ -1,6 +1,7 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import { Button, Icon, ControlGroup, Text } from '@blueprintjs/core'; import { Button, Icon, ControlGroup, Text } from '@blueprintjs/core';
import { createStyles, makeStyles } from '@material-ui/core/styles'; import { createStyles, makeStyles } from '@material-ui/core/styles';
import { useTranslation } from 'react-i18next';
import ChooseAppOrScreenOverlay from './StepsOfStepper/ChooseAppOrScreenOverlay/ChooseAppOrScreenOverlay'; import ChooseAppOrScreenOverlay from './StepsOfStepper/ChooseAppOrScreenOverlay/ChooseAppOrScreenOverlay';
interface ShareAppOrScreenControlGroupProps { interface ShareAppOrScreenControlGroupProps {
@ -53,6 +54,7 @@ const useStyles = makeStyles(() =>
export default function ShareAppOrScreenControlGroup( export default function ShareAppOrScreenControlGroup(
props: ShareAppOrScreenControlGroupProps props: ShareAppOrScreenControlGroupProps
) { ) {
const { t } = useTranslation();
const { handleNextEntireScreen, handleNextApplicationWindow } = props; const { handleNextEntireScreen, handleNextApplicationWindow } = props;
const classes = useStyles(); const classes = useStyles();
@ -103,7 +105,7 @@ export default function ShareAppOrScreenControlGroup(
iconSize={100} iconSize={100}
color="white" color="white"
/> />
<Text className="bp3-running-text">Entire Screen</Text> <Text className="bp3-running-text">{t('Entire Screen')}</Text>
</Button> </Button>
<Button <Button
className={classes.shareAppButton} className={classes.shareAppButton}
@ -116,14 +118,14 @@ export default function ShareAppOrScreenControlGroup(
iconSize={100} iconSize={100}
color="white" color="white"
/> />
<Text className="bp3-running-text">Application Window</Text> <Text className="bp3-running-text">{t('Application Window')}</Text>
</Button> </Button>
<Button <Button
active active
className={classes.orDecorationButton} className={classes.orDecorationButton}
style={{ zIndex: 999 }} style={{ zIndex: 999 }}
> >
OR {t('OR')}
</Button> </Button>
</ControlGroup> </ControlGroup>
<ChooseAppOrScreenOverlay <ChooseAppOrScreenOverlay

View File

@ -1,6 +1,8 @@
import React from 'react'; import React from 'react';
import { Row, Col } from 'react-flexbox-grid'; import { Row, Col } from 'react-flexbox-grid';
import { Icon, Text, Button, Popover, Tooltip } from '@blueprintjs/core'; import { Icon, Text, Button, Popover, Tooltip } from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import { TFunction } from 'i18next';
import DeviceInfoCallout from '../DeviceInfoCallout'; import DeviceInfoCallout from '../DeviceInfoCallout';
import isWithReactRevealAnimations from '../../utils/isWithReactRevealAnimations'; import isWithReactRevealAnimations from '../../utils/isWithReactRevealAnimations';
@ -10,9 +12,12 @@ interface DeviceConnectedInfoButtonProps {
} }
const getDeviceConnectedPopoverContent = ( const getDeviceConnectedPopoverContent = (
t: TFunction,
pendingConnectionDevice: Device, pendingConnectionDevice: Device,
handleDisconnect: () => void handleDisconnect: () => void
) => { ) => {
const disconnectButtonText = t('Disconnect');
return ( return (
<Row> <Row>
<div style={{ padding: '20px', borderRadius: '100px' }}> <div style={{ padding: '20px', borderRadius: '100px' }}>
@ -35,7 +40,7 @@ const getDeviceConnectedPopoverContent = (
}} }}
style={{ width: '100%', borderRadius: '5px' }} style={{ width: '100%', borderRadius: '5px' }}
> >
Disconnect {disconnectButtonText}
</Button> </Button>
</Col> </Col>
</Row> </Row>
@ -47,18 +52,20 @@ const getDeviceConnectedPopoverContent = (
export default function DeviceConnectedInfoButton( export default function DeviceConnectedInfoButton(
props: DeviceConnectedInfoButtonProps props: DeviceConnectedInfoButtonProps
) { ) {
const { t } = useTranslation();
const { device, onDisconnect } = props; const { device, onDisconnect } = props;
return ( return (
<> <>
<Popover <Popover
content={getDeviceConnectedPopoverContent(device, onDisconnect)} content={getDeviceConnectedPopoverContent(t, device, onDisconnect)}
position="bottom" position="bottom"
inheritDarkTheme={false} inheritDarkTheme={false}
transitionDuration={isWithReactRevealAnimations() ? 700 : 0} transitionDuration={isWithReactRevealAnimations() ? 700 : 0}
> >
<Tooltip <Tooltip
content={<Text>Click to manage</Text>} content={<Text>{t('Click to see more')}</Text>}
position="right" position="right"
hoverOpenDelay={400} hoverOpenDelay={400}
> >
@ -66,7 +73,7 @@ export default function DeviceConnectedInfoButton(
id="connected-device-info-stepper-button" id="connected-device-info-stepper-button"
intent="success" intent="success"
style={{ style={{
width: '120px', width: '150px',
height: '10px !important', height: '10px !important',
borderRadius: '100px', borderRadius: '100px',
position: 'relative', position: 'relative',
@ -78,7 +85,7 @@ export default function DeviceConnectedInfoButton(
<Icon icon="info-sign" /> <Icon icon="info-sign" />
</Col> </Col>
<Col xs> <Col xs>
<Text>Connected</Text> <Text>{t('Connected')}</Text>
</Col> </Col>
</Row> </Row>
</Button> </Button>

View File

@ -65,7 +65,7 @@ exports[`should match exact snapshot 1`] = `
} }
} }
> >
Disconnect
</Blueprint3.Button> </Blueprint3.Button>
</Col> </Col>
</Row> </Row>
@ -114,7 +114,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
Click to manage
</Blueprint3.Text> </Blueprint3.Text>
} }
hoverCloseDelay={0} hoverCloseDelay={0}
@ -135,7 +135,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
Click to manage
</Blueprint3.Text> </Blueprint3.Text>
} }
defaultIsOpen={false} defaultIsOpen={false}
@ -196,7 +196,7 @@ exports[`should match exact snapshot 1`] = `
"height": "10px !important", "height": "10px !important",
"margin": "0 auto", "margin": "0 auto",
"position": "relative", "position": "relative",
"width": "120px", "width": "150px",
} }
} }
tabIndex={0} tabIndex={0}
@ -213,7 +213,7 @@ exports[`should match exact snapshot 1`] = `
"height": "10px !important", "height": "10px !important",
"margin": "0 auto", "margin": "0 auto",
"position": "relative", "position": "relative",
"width": "120px", "width": "150px",
} }
} }
tabIndex={0} tabIndex={0}
@ -274,9 +274,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="" className=""
> />
Connected
</div>
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
</Col> </Col>

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import { Row, Col } from 'react-flexbox-grid'; import { Row, Col } from 'react-flexbox-grid';
import { Text } from '@blueprintjs/core';
import ShareEntireScreenOrAppWindowControlGroup from '../ShareAppOrScreenControlGroup'; import ShareEntireScreenOrAppWindowControlGroup from '../ShareAppOrScreenControlGroup';
interface ChooseAppOrScreeenStepProps { interface ChooseAppOrScreeenStepProps {
@ -18,9 +17,6 @@ const ChooseAppOrScreeenStep: React.FC<ChooseAppOrScreeenStepProps> = (
<Col xs={12}> <Col xs={12}>
<Row center="xs"> <Row center="xs">
<Col xs={6}> <Col xs={6}>
<div style={{ marginBottom: '10px' }}>
<Text>Choose Entire Screen or App window you want to share</Text>
</div>
<Row center="xs"> <Row center="xs">
<Col> <Col>
<ShareEntireScreenOrAppWindowControlGroup <ShareEntireScreenOrAppWindowControlGroup

View File

@ -3,6 +3,7 @@ import React, { useCallback, useEffect, useState } from 'react';
import { H3, Card, Dialog, Button } from '@blueprintjs/core'; import { H3, Card, Dialog, Button } from '@blueprintjs/core';
import { Row, Col } from 'react-flexbox-grid'; import { Row, Col } from 'react-flexbox-grid';
import { createStyles, makeStyles } from '@material-ui/core/styles'; import { createStyles, makeStyles } from '@material-ui/core/styles';
import { useTranslation } from 'react-i18next';
import CloseOverlayButton from '../../CloseOverlayButton'; import CloseOverlayButton from '../../CloseOverlayButton';
import PreviewGridList from './PreviewGridList'; import PreviewGridList from './PreviewGridList';
import DesktopCapturerSources from '../../../features/DesktopCapturerSourcesService'; import DesktopCapturerSources from '../../../features/DesktopCapturerSourcesService';
@ -50,6 +51,8 @@ interface ChooseAppOrScreenOverlayProps {
export default function ChooseAppOrScreenOverlay( export default function ChooseAppOrScreenOverlay(
props: ChooseAppOrScreenOverlayProps props: ChooseAppOrScreenOverlayProps
) { ) {
const { t } = useTranslation();
const { const {
handleClose, handleClose,
isChooseAppOrScreenOverlayOpen, isChooseAppOrScreenOverlayOpen,
@ -148,13 +151,13 @@ export default function ChooseAppOrScreenOverlay(
{isEntireScreenToShareChosen ? ( {isEntireScreenToShareChosen ? (
<div> <div>
<H3 style={{ marginBottom: '0px' }}> <H3 style={{ marginBottom: '0px' }}>
Select Entire Screen to Share {t('Select Entire Screen to Share')}
</H3> </H3>
</div> </div>
) : ( ) : (
<div> <div>
<H3 style={{ marginBottom: '0px' }}> <H3 style={{ marginBottom: '0px' }}>
Select App Window to Share {t('Select App Window to Share')}
</H3> </H3>
</div> </div>
)} )}
@ -168,7 +171,7 @@ export default function ChooseAppOrScreenOverlay(
borderRadius: '100px', borderRadius: '100px',
}} }}
> >
Refresh {t('Refresh')}
</Button> </Button>
</Col> </Col>

View File

@ -103,9 +103,7 @@ exports[`should match exact snapshot 1`] = `
<h3 <h3
class="bp3-heading" class="bp3-heading"
style="margin-bottom: 0px;" style="margin-bottom: 0px;"
> />
Select Entire Screen to Share
</h3>
</div> </div>
</div> </div>
<div <div
@ -135,11 +133,6 @@ exports[`should match exact snapshot 1`] = `
/> />
</svg> </svg>
</span> </span>
<span
class="bp3-button-text"
>
Refresh
</span>
</button> </button>
</div> </div>
<div <div
@ -250,9 +243,7 @@ exports[`should match exact snapshot 1`] = `
<h3 <h3
class="bp3-heading" class="bp3-heading"
style="margin-bottom: 0px;" style="margin-bottom: 0px;"
> />
Select Entire Screen to Share
</h3>
</div> </div>
</div> </div>
<div <div
@ -282,11 +273,6 @@ exports[`should match exact snapshot 1`] = `
/> />
</svg> </svg>
</span> </span>
<span
class="bp3-button-text"
>
Refresh
</span>
</button> </button>
</div> </div>
<div <div
@ -546,9 +532,7 @@ exports[`should match exact snapshot 1`] = `
"marginBottom": "0px", "marginBottom": "0px",
} }
} }
> />
Select Entire Screen to Share
</h3>
</Component> </Component>
</div> </div>
</div> </div>
@ -607,12 +591,6 @@ exports[`should match exact snapshot 1`] = `
</svg> </svg>
</span> </span>
</Blueprint3.Icon> </Blueprint3.Icon>
<span
className="bp3-button-text"
key="text"
>
Refresh
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />

View File

@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { remote } from 'electron'; import { remote } from 'electron';
import { Text } from '@blueprintjs/core'; import { Text } from '@blueprintjs/core';
import { Row, Col } from 'react-flexbox-grid'; import { Row, Col } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
import SharingSourcePreviewCard from '../SharingSourcePreviewCard'; import SharingSourcePreviewCard from '../SharingSourcePreviewCard';
import SharingSessionService from '../../features/SharingSessionService'; import SharingSessionService from '../../features/SharingSessionService';
import DeviceInfoCallout from '../DeviceInfoCallout'; import DeviceInfoCallout from '../DeviceInfoCallout';
@ -16,6 +17,7 @@ interface ConfirmStepProps {
} }
export default function ConfirmStep(props: ConfirmStepProps) { export default function ConfirmStep(props: ConfirmStepProps) {
const { t } = useTranslation();
const { device } = props; const { device } = props;
const [sharingSession, setSharingSession] = useState< const [sharingSession, setSharingSession] = useState<
SharingSession | undefined SharingSession | undefined
@ -34,7 +36,7 @@ export default function ConfirmStep(props: ConfirmStepProps) {
<Row style={{ marginBottom: '10px' }}> <Row style={{ marginBottom: '10px' }}>
<Col xs={12} style={{ textAlign: 'center' }}> <Col xs={12} style={{ textAlign: 'center' }}>
{/* eslint-disable-next-line react/no-unescaped-entities */} {/* eslint-disable-next-line react/no-unescaped-entities */}
<Text>Check if all is OK and click "Confirm"</Text> <Text>{t('Check if all is OK and click Confirm')}</Text>
</Col> </Col>
</Row> </Row>
<Row middle="xs" center="xs"> <Row middle="xs" center="xs">
@ -53,14 +55,6 @@ export default function ConfirmStep(props: ConfirmStepProps) {
/> />
</Col> </Col>
</Row> </Row>
<Row style={{ marginBottom: '10px' }}>
<Col xs={12} style={{ textAlign: 'center' }}>
<Text className="bp3-text-muted">
{/* eslint-disable-next-line react/no-unescaped-entities */}
Click "Back" if you need to change something
</Text>
</Col>
</Row>
</div> </div>
); );
} }

View File

@ -1,6 +1,8 @@
import React from 'react'; import React from 'react';
import { remote } from 'electron'; import { remote } from 'electron';
import { Button } from '@blueprintjs/core'; import { Button, Text } from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import { TFunction } from 'i18next';
import { Col, Row } from 'react-flexbox-grid'; import { Col, Row } from 'react-flexbox-grid';
import DEVICES from '../../constants/test-devices.json'; import DEVICES from '../../constants/test-devices.json';
import ScanQRStep from './ScanQRStep'; import ScanQRStep from './ScanQRStep';
@ -28,6 +30,7 @@ interface IntermediateStepProps {
} }
function getStepContent( function getStepContent(
t: TFunction,
stepIndex: number, stepIndex: number,
handleNextEntireScreen: () => void, handleNextEntireScreen: () => void,
handleNextApplicationWindow: () => void, handleNextApplicationWindow: () => void,
@ -38,10 +41,19 @@ function getStepContent(
return <ScanQRStep />; return <ScanQRStep />;
case 1: case 1:
return ( return (
<>
<Row center="xs">
<div style={{ marginBottom: '10px' }}>
<Text>
{t('Choose Entire Screen or App window you want to share')}
</Text>
</div>
</Row>
<ChooseAppOrScreeenStep <ChooseAppOrScreeenStep
handleNextEntireScreen={handleNextEntireScreen} handleNextEntireScreen={handleNextEntireScreen}
handleNextApplicationWindow={handleNextApplicationWindow} handleNextApplicationWindow={handleNextApplicationWindow}
/> />
</>
); );
case 2: case 2:
return <ConfirmStep device={pendingConnectionDevice} />; return <ConfirmStep device={pendingConnectionDevice} />;
@ -55,6 +67,8 @@ function isConfirmStep(activeStep: number, steps: string[]) {
} }
export default function IntermediateStep(props: IntermediateStepProps) { export default function IntermediateStep(props: IntermediateStepProps) {
const { t } = useTranslation();
const { const {
activeStep, activeStep,
steps, steps,
@ -83,6 +97,7 @@ export default function IntermediateStep(props: IntermediateStepProps) {
}} }}
> >
{getStepContent( {getStepContent(
t,
activeStep, activeStep,
handleNextEntireScreen, handleNextEntireScreen,
handleNextApplicationWindow, handleNextApplicationWindow,
@ -168,7 +183,9 @@ export default function IntermediateStep(props: IntermediateStepProps) {
: 'chevron-right' : 'chevron-right'
} }
> >
{isConfirmStep(activeStep, steps) ? 'Confirm' : 'Next'} {isConfirmStep(activeStep, steps)
? t('Confirm Button Text')
: 'Next'}
</Button> </Button>
</Col> </Col>
</Row> </Row>
@ -185,7 +202,7 @@ export default function IntermediateStep(props: IntermediateStepProps) {
}} }}
onClick={handleBack} onClick={handleBack}
icon="chevron-left" icon="chevron-left"
text="No, I need to share other thing" text={t('No, I need to choose other')}
/> />
</Row> </Row>
</Col> </Col>

View File

@ -101,13 +101,15 @@ const ScanQRStep: React.FC = () => {
borderRadius: '20px', borderRadius: '20px',
}} }}
> >
Make sure your computer and device are connected to same WiFi {t(
'Make sure your computer and screen viewing device are connected to same Wi-Fi'
)}
</span> </span>
</Text> </Text>
<Text className="bp3-text">{t('Scan the QR code')}</Text> <Text className="bp3-text">{t('Scan the QR code')}</Text>
</div> </div>
<div> <div>
<Tooltip content="Click to make bigger" position={Position.LEFT}> <Tooltip content={t('Click to make bigger')} position={Position.LEFT}>
<Button <Button
id="magnify-qr-code-button" id="magnify-qr-code-button"
className={classes.smallQRCode} className={classes.smallQRCode}
@ -131,12 +133,13 @@ const ScanQRStep: React.FC = () => {
</div> </div>
<div style={{ marginBottom: '10px' }}> <div style={{ marginBottom: '10px' }}>
<Text className="bp3-text-muted"> <Text className="bp3-text-muted">
or type the following address manually in browser address bar on any {`${t(
device: 'Or type the following address in browser address bar on any device'
)}:`}
</Text> </Text>
</div> </div>
<Tooltip content="Click to copy" position={Position.LEFT}> <Tooltip content={t('Click to copy')} position={Position.LEFT}>
<Button <Button
intent="primary" intent="primary"
icon="duplicate" icon="duplicate"

View File

@ -2,12 +2,15 @@
import React, { useCallback, useEffect } from 'react'; import React, { useCallback, useEffect } from 'react';
import { Button, H5, Icon, Text } from '@blueprintjs/core'; import { Button, H5, Icon, Text } from '@blueprintjs/core';
import { Row, Col } from 'react-flexbox-grid'; import { Row, Col } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
interface SuccessStepProps { interface SuccessStepProps {
handleReset: () => void; handleReset: () => void;
} }
const SuccessStep: React.FC<SuccessStepProps> = (props: SuccessStepProps) => { const SuccessStep: React.FC<SuccessStepProps> = (props: SuccessStepProps) => {
const { t } = useTranslation();
useEffect(() => { useEffect(() => {
document document
.querySelector('#top-panel-connected-devices-list-button') .querySelector('#top-panel-connected-devices-list-button')
@ -49,16 +52,13 @@ const SuccessStep: React.FC<SuccessStepProps> = (props: SuccessStepProps) => {
<Row center="xs"> <Row center="xs">
<Col xs={12}> <Col xs={12}>
<Icon icon="endorsed" iconSize={35} color="#0F9960" /> <Icon icon="endorsed" iconSize={35} color="#0F9960" />
<H5>Success!</H5> <H5>{t('Done!')}</H5>
</Col> </Col>
</Row> </Row>
<Row center="xs"> <Row center="xs">
<Col xs={10}> <Col xs={10}>
<div style={{ marginBottom: '10px' }}> <div style={{ marginBottom: '10px' }}>
<Text> <Text>{t('Now you can see your screen on other device')}</Text>
{`You should see now sharing session started on device you've connected
with.`}
</Text>
</div> </div>
<div <div
id="connected-devices-list-text-success" id="connected-devices-list-text-success"
@ -70,10 +70,9 @@ const SuccessStep: React.FC<SuccessStepProps> = (props: SuccessStepProps) => {
}} }}
> >
<Text className=""> <Text className="">
{` {t(
You can manage connected devices by clicking "Connected Devices" 'You can manage connected devices by clicking Connected Devices button in top panel'
button in top panel )}
`}
</Text> </Text>
</div> </div>
</Col> </Col>
@ -84,7 +83,7 @@ const SuccessStep: React.FC<SuccessStepProps> = (props: SuccessStepProps) => {
icon="repeat" icon="repeat"
style={{ borderRadius: '100px' }} style={{ borderRadius: '100px' }}
> >
Connect New Device {t('Connect New Device')}
</Button> </Button>
</Col> </Col>
); );

View File

@ -61,24 +61,6 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="col-xs-6" className="col-xs-6"
> >
<div
style={
Object {
"marginBottom": "10px",
}
}
>
<Blueprint3.Text
ellipsize={false}
tagName="div"
>
<div
className=""
>
Choose Entire Screen or App window you want to share
</div>
</Blueprint3.Text>
</div>
<Row <Row
center="xs" center="xs"
> >
@ -168,9 +150,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="bp3-running-text" className="bp3-running-text"
> />
Entire Screen
</div>
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
<Blueprint3.Icon <Blueprint3.Icon
@ -233,9 +213,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="bp3-running-text" className="bp3-running-text"
> />
Application Window
</div>
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
<Blueprint3.Icon <Blueprint3.Icon
@ -267,12 +245,6 @@ exports[`should match exact snapshot 1`] = `
<Blueprint3.Icon <Blueprint3.Icon
key="leftIcon" key="leftIcon"
/> />
<span
className="bp3-button-text"
key="text"
>
OR
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />

View File

@ -72,9 +72,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="" className=""
> />
Check if all is OK and click "Confirm"
</div>
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
</Col> </Col>
@ -111,15 +109,25 @@ exports[`should match exact snapshot 1`] = `
} }
} }
> >
Partner Device Info: :
</h4> </h4>
</Component> </Component>
<Blueprint3.Callout <Blueprint3.Callout
id="device-info-callout" id="device-info-callout"
style={
Object {
"borderRadius": "8px",
}
}
> >
<div <div
className="bp3-callout" className="bp3-callout"
id="device-info-callout" id="device-info-callout"
style={
Object {
"borderRadius": "8px",
}
}
> >
<Row <Row
center="xs" center="xs"
@ -140,7 +148,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Device Type: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -151,8 +160,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
This should match with 'Device IP' displayed on the screen of device
that is trying to connect.
</Blueprint3.Text> </Blueprint3.Text>
<span <span
style={ style={
@ -165,8 +173,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
</React.Fragment> </React.Fragment>
@ -188,8 +195,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
This should match with 'Device IP' displayed on the screen of device
that is trying to connect.
</Blueprint3.Text> </Blueprint3.Text>
<span <span
style={ style={
@ -202,8 +208,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
</React.Fragment> </React.Fragment>
@ -277,7 +282,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="bp3-text-large" className="bp3-text-large"
> >
Device IP: :
<span <span
className="device-ip-span" className="device-ip-span"
/> />
@ -314,7 +320,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Device Browser: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -325,7 +332,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Device OS: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -345,7 +353,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="bp3-text-overflow-ellipsis bp3-text-muted" className="bp3-text-overflow-ellipsis bp3-text-muted"
> >
Session ID: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -500,52 +509,6 @@ exports[`should match exact snapshot 1`] = `
</Col> </Col>
</div> </div>
</Row> </Row>
<Row
style={
Object {
"marginBottom": "10px",
}
}
>
<div
className="row"
style={
Object {
"marginBottom": "10px",
}
}
>
<Col
style={
Object {
"textAlign": "center",
}
}
xs={12}
>
<div
className="col-xs-12"
style={
Object {
"textAlign": "center",
}
}
>
<Blueprint3.Text
className="bp3-text-muted"
ellipsize={false}
tagName="div"
>
<div
className="bp3-text-muted"
>
Click "Back" if you need to change something
</div>
</Blueprint3.Text>
</div>
</Col>
</div>
</Row>
</div> </div>
</ConfirmStep> </ConfirmStep>
</Router> </Router>

View File

@ -91,9 +91,7 @@ exports[`should match exact snapshot on each step 1`] = `
"paddingRight": "8px", "paddingRight": "8px",
} }
} }
> />
Make sure your computer and device are connected to same WiFi
</span>
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
<Blueprint3.Text <Blueprint3.Text
@ -108,7 +106,7 @@ exports[`should match exact snapshot on each step 1`] = `
</div> </div>
<div> <div>
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Click to make bigger" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}
@ -120,7 +118,7 @@ exports[`should match exact snapshot on each step 1`] = `
boundary="scrollParent" boundary="scrollParent"
canEscapeKeyClose={false} canEscapeKeyClose={false}
captureDismiss={false} captureDismiss={false}
content="Click to make bigger" content=""
defaultIsOpen={false} defaultIsOpen={false}
disabled={false} disabled={false}
enforceFocus={false} enforceFocus={false}
@ -293,12 +291,12 @@ exports[`should match exact snapshot on each step 1`] = `
<div <div
className="bp3-text-muted" className="bp3-text-muted"
> >
or type the following address manually in browser address bar on any device: :
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Click to copy" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}
@ -310,7 +308,7 @@ exports[`should match exact snapshot on each step 1`] = `
boundary="scrollParent" boundary="scrollParent"
canEscapeKeyClose={false} canEscapeKeyClose={false}
captureDismiss={false} captureDismiss={false}
content="Click to copy" content=""
defaultIsOpen={false} defaultIsOpen={false}
disabled={false} disabled={false}
enforceFocus={false} enforceFocus={false}
@ -534,7 +532,7 @@ exports[`should match exact snapshot on each step 1`] = `
"marginTop": "10px", "marginTop": "10px",
} }
} }
text="No, I need to share other thing" text=""
> >
<button <button
className="bp3-button bp3-intent-danger" className="bp3-button bp3-intent-danger"
@ -575,12 +573,6 @@ exports[`should match exact snapshot on each step 1`] = `
</svg> </svg>
</span> </span>
</Blueprint3.Icon> </Blueprint3.Icon>
<span
className="bp3-button-text"
key="text"
>
No, I need to share other thing
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />
@ -661,6 +653,30 @@ exports[`should match exact snapshot on each step 2`] = `
} }
} }
> >
<Row
center="xs"
>
<div
className="row center-xs"
>
<div
style={
Object {
"marginBottom": "10px",
}
}
>
<Blueprint3.Text
ellipsize={false}
tagName="div"
>
<div
className=""
/>
</Blueprint3.Text>
</div>
</div>
</Row>
<ChooseAppOrScreeenStep <ChooseAppOrScreeenStep
handleNextApplicationWindow={[Function]} handleNextApplicationWindow={[Function]}
handleNextEntireScreen={[Function]} handleNextEntireScreen={[Function]}
@ -698,24 +714,6 @@ exports[`should match exact snapshot on each step 2`] = `
<div <div
className="col-xs-6" className="col-xs-6"
> >
<div
style={
Object {
"marginBottom": "10px",
}
}
>
<Blueprint3.Text
ellipsize={false}
tagName="div"
>
<div
className=""
>
Choose Entire Screen or App window you want to share
</div>
</Blueprint3.Text>
</div>
<Row <Row
center="xs" center="xs"
> >
@ -805,9 +803,7 @@ exports[`should match exact snapshot on each step 2`] = `
> >
<div <div
className="bp3-running-text" className="bp3-running-text"
> />
Entire Screen
</div>
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
<Blueprint3.Icon <Blueprint3.Icon
@ -870,9 +866,7 @@ exports[`should match exact snapshot on each step 2`] = `
> >
<div <div
className="bp3-running-text" className="bp3-running-text"
> />
Application Window
</div>
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
<Blueprint3.Icon <Blueprint3.Icon
@ -904,12 +898,6 @@ exports[`should match exact snapshot on each step 2`] = `
<Blueprint3.Icon <Blueprint3.Icon
key="leftIcon" key="leftIcon"
/> />
<span
className="bp3-button-text"
key="text"
>
OR
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />
@ -1071,7 +1059,7 @@ exports[`should match exact snapshot on each step 2`] = `
"marginTop": "10px", "marginTop": "10px",
} }
} }
text="No, I need to share other thing" text=""
> >
<button <button
className="bp3-button bp3-intent-danger" className="bp3-button bp3-intent-danger"
@ -1112,12 +1100,6 @@ exports[`should match exact snapshot on each step 2`] = `
</svg> </svg>
</span> </span>
</Blueprint3.Icon> </Blueprint3.Icon>
<span
className="bp3-button-text"
key="text"
>
No, I need to share other thing
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />
@ -1244,9 +1226,7 @@ exports[`should match exact snapshot on each step 3`] = `
> >
<div <div
className="" className=""
> />
Check if all is OK and click "Confirm"
</div>
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
</Col> </Col>
@ -1283,15 +1263,25 @@ exports[`should match exact snapshot on each step 3`] = `
} }
} }
> >
Partner Device Info: :
</h4> </h4>
</Component> </Component>
<Blueprint3.Callout <Blueprint3.Callout
id="device-info-callout" id="device-info-callout"
style={
Object {
"borderRadius": "8px",
}
}
> >
<div <div
className="bp3-callout" className="bp3-callout"
id="device-info-callout" id="device-info-callout"
style={
Object {
"borderRadius": "8px",
}
}
> >
<Row <Row
center="xs" center="xs"
@ -1312,7 +1302,8 @@ exports[`should match exact snapshot on each step 3`] = `
<div <div
className="" className=""
> >
Device Type: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -1323,8 +1314,7 @@ exports[`should match exact snapshot on each step 3`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
This should match with 'Device IP' displayed on the screen of device
that is trying to connect.
</Blueprint3.Text> </Blueprint3.Text>
<span <span
style={ style={
@ -1337,8 +1327,7 @@ exports[`should match exact snapshot on each step 3`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
</React.Fragment> </React.Fragment>
@ -1360,8 +1349,7 @@ exports[`should match exact snapshot on each step 3`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
This should match with 'Device IP' displayed on the screen of device
that is trying to connect.
</Blueprint3.Text> </Blueprint3.Text>
<span <span
style={ style={
@ -1374,8 +1362,7 @@ exports[`should match exact snapshot on each step 3`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
</React.Fragment> </React.Fragment>
@ -1449,7 +1436,8 @@ exports[`should match exact snapshot on each step 3`] = `
<div <div
className="bp3-text-large" className="bp3-text-large"
> >
Device IP: :
<span <span
className="device-ip-span" className="device-ip-span"
/> />
@ -1486,7 +1474,8 @@ exports[`should match exact snapshot on each step 3`] = `
<div <div
className="" className=""
> >
Device Browser: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -1497,7 +1486,8 @@ exports[`should match exact snapshot on each step 3`] = `
<div <div
className="" className=""
> >
Device OS: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -1517,7 +1507,8 @@ exports[`should match exact snapshot on each step 3`] = `
<div <div
className="bp3-text-overflow-ellipsis bp3-text-muted" className="bp3-text-overflow-ellipsis bp3-text-muted"
> >
Session ID: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -1672,52 +1663,6 @@ exports[`should match exact snapshot on each step 3`] = `
</Col> </Col>
</div> </div>
</Row> </Row>
<Row
style={
Object {
"marginBottom": "10px",
}
}
>
<div
className="row"
style={
Object {
"marginBottom": "10px",
}
}
>
<Col
style={
Object {
"textAlign": "center",
}
}
xs={12}
>
<div
className="col-xs-12"
style={
Object {
"textAlign": "center",
}
}
>
<Blueprint3.Text
className="bp3-text-muted"
ellipsize={false}
tagName="div"
>
<div
className="bp3-text-muted"
>
Click "Back" if you need to change something
</div>
</Blueprint3.Text>
</div>
</Col>
</div>
</Row>
</div> </div>
</ConfirmStep> </ConfirmStep>
<Row> <Row>
@ -1762,12 +1707,6 @@ exports[`should match exact snapshot on each step 3`] = `
<Blueprint3.Icon <Blueprint3.Icon
key="leftIcon" key="leftIcon"
/> />
<span
className="bp3-button-text"
key="text"
>
Confirm
</span>
<Blueprint3.Icon <Blueprint3.Icon
icon="small-tick" icon="small-tick"
key="rightIcon" key="rightIcon"
@ -1824,7 +1763,7 @@ exports[`should match exact snapshot on each step 3`] = `
"marginTop": "10px", "marginTop": "10px",
} }
} }
text="No, I need to share other thing" text=""
> >
<button <button
className="bp3-button bp3-intent-danger" className="bp3-button bp3-intent-danger"
@ -1865,12 +1804,6 @@ exports[`should match exact snapshot on each step 3`] = `
</svg> </svg>
</span> </span>
</Blueprint3.Icon> </Blueprint3.Icon>
<span
className="bp3-button-text"
key="text"
>
No, I need to share other thing
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />

View File

@ -23,9 +23,7 @@ exports[`<ScanQRStep /> when rendered should match exact snapshot 1`] = `
"paddingRight": "8px", "paddingRight": "8px",
} }
} }
> />
Make sure your computer and device are connected to same WiFi
</span>
</Blueprint3.Text> </Blueprint3.Text>
<Blueprint3.Text <Blueprint3.Text
className="bp3-text" className="bp3-text"
@ -35,7 +33,7 @@ exports[`<ScanQRStep /> when rendered should match exact snapshot 1`] = `
</div> </div>
<div> <div>
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Click to make bigger" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}
@ -78,11 +76,11 @@ exports[`<ScanQRStep /> when rendered should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
or type the following address manually in browser address bar on any device: :
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Click to copy" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}

View File

@ -90,9 +90,7 @@ exports[`should match exact snapshot 1`] = `
<Component> <Component>
<h5 <h5
className="bp3-heading" className="bp3-heading"
> />
Success!
</h5>
</Component> </Component>
</div> </div>
</Col> </Col>
@ -123,10 +121,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="" className=""
> />
You should see now sharing session started on device you've connected
with.
</div>
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
<div <div
@ -147,12 +142,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="" className=""
> />
You can manage connected devices by clicking "Connected Devices"
button in top panel
</div>
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
</div> </div>
@ -207,12 +197,6 @@ exports[`should match exact snapshot 1`] = `
</svg> </svg>
</span> </span>
</Blueprint3.Icon> </Blueprint3.Icon>
<span
className="bp3-button-text"
key="text"
>
Connect New Device
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />

View File

@ -0,0 +1,57 @@
import { remote } from 'electron';
import React, { useContext, useCallback } from 'react';
import { Button, Classes, ControlGroup } from '@blueprintjs/core';
import SharingSessionService from '../../features/SharingSessionService';
import { SettingsContext } from '../../containers/SettingsProvider';
const sharingSessionService = remote.getGlobal(
'sharingSessionService'
) as SharingSessionService;
export default function ToggleThemeBtnGroup() {
const { isDarkTheme, setIsDarkThemeHook } = useContext(SettingsContext);
const handleToggleDarkTheme = useCallback(() => {
if (!isDarkTheme) {
document.body.classList.toggle(Classes.DARK);
setIsDarkThemeHook(true);
}
// TODO: call sharing sessions service here to notify all connected clients about theme change
sharingSessionService.sharingSessions.forEach((sharingSession) => {
sharingSession?.appThemeChanged();
});
}, [isDarkTheme, setIsDarkThemeHook]);
const handleToggleLightTheme = useCallback(() => {
if (isDarkTheme) {
document.body.classList.toggle(Classes.DARK);
setIsDarkThemeHook(false);
}
// TODO: call sharing sessions service here to notify all connected clients about theme change
sharingSessionService.sharingSessions.forEach((sharingSession) => {
sharingSession?.appThemeChanged();
});
}, [isDarkTheme, setIsDarkThemeHook]);
return (
<ControlGroup fill vertical={false} style={{ width: '120px' }}>
<Button
id="light-theme-toggle-btn"
icon="flash"
onClick={handleToggleLightTheme}
active={!isDarkTheme}
style={{ borderTopLeftRadius: '50px', borderBottomLeftRadius: '50px' }}
/>
<Button
id="dark-theme-toggle-btn"
icon="moon"
onClick={handleToggleDarkTheme}
active={isDarkTheme}
style={{
borderTopRightRadius: '50px',
borderBottomRightRadius: '50px',
}}
/>
</ControlGroup>
);
}

View File

@ -6,6 +6,7 @@ import React, { useCallback, useContext } from 'react';
import { Button, Text, Icon, Position, Tooltip } from '@blueprintjs/core'; import { Button, Text, Icon, Position, Tooltip } from '@blueprintjs/core';
import { createStyles, makeStyles } from '@material-ui/core/styles'; import { createStyles, makeStyles } from '@material-ui/core/styles';
import { Col, Row } from 'react-flexbox-grid'; import { Col, Row } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
import SettingsOverlay from './SettingsOverlay/SettingsOverlay'; import SettingsOverlay from './SettingsOverlay/SettingsOverlay';
import ConnectedDevicesListDrawer from './ConnectedDevicesListDrawer'; import ConnectedDevicesListDrawer from './ConnectedDevicesListDrawer';
import { SettingsContext } from '../containers/SettingsProvider'; import { SettingsContext } from '../containers/SettingsProvider';
@ -52,6 +53,7 @@ const useStylesWithTheme = (isDarkTheme: boolean) =>
); );
export default function TopPanel(props: any) { export default function TopPanel(props: any) {
const { t } = useTranslation();
const { isDarkTheme } = useContext(SettingsContext); const { isDarkTheme } = useContext(SettingsContext);
const getClassesCallback = useCallback(() => { const getClassesCallback = useCallback(() => {
@ -73,12 +75,14 @@ export default function TopPanel(props: any) {
setIsDrawerOpen(!isDrawersOpen); setIsDrawerOpen(!isDrawersOpen);
}, [isDrawersOpen]); }, [isDrawersOpen]);
const donateTooltipContent = t(
'If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better'
);
const deskreenButtonTooltip = t('Click to visit our website');
const renderDonateButton = useCallback(() => { const renderDonateButton = useCallback(() => {
return ( return (
<Tooltip <Tooltip content={donateTooltipContent} position={Position.BOTTOM}>
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 <Button
style={{ style={{
marginRight: '10px', marginRight: '10px',
@ -100,19 +104,19 @@ export default function TopPanel(props: any) {
</Col> </Col>
<Col xs> <Col xs>
<div style={{ transform: 'translateY(2px) translateX(-5px)' }}> <div style={{ transform: 'translateY(2px) translateX(-5px)' }}>
<Text>Donate!</Text> <Text>{t('Donate')}</Text>
</div> </div>
</Col> </Col>
</Row> </Row>
</Button> </Button>
</Tooltip> </Tooltip>
); );
}, []); }, [donateTooltipContent, t]);
const renderConnectedDevicesListButton = useCallback(() => { const renderConnectedDevicesListButton = useCallback(() => {
return ( return (
<div className={getClassesCallback().topPanelControlButtonMargin}> <div className={getClassesCallback().topPanelControlButtonMargin}>
<Tooltip content="Connected Devices" position={Position.BOTTOM}> <Tooltip content={t('Connected Devices')} position={Position.BOTTOM}>
<Button <Button
id="top-panel-connected-devices-list-button" id="top-panel-connected-devices-list-button"
intent="primary" intent="primary"
@ -128,12 +132,12 @@ export default function TopPanel(props: any) {
</Tooltip> </Tooltip>
</div> </div>
); );
}, [getClassesCallback, handleToggleConnectedDevicesListDrawer]); }, [getClassesCallback, handleToggleConnectedDevicesListDrawer, t]);
const renderHelpButton = useCallback(() => { const renderHelpButton = useCallback(() => {
return ( return (
<div className={getClassesCallback().topPanelControlButtonMargin}> <div className={getClassesCallback().topPanelControlButtonMargin}>
<Tooltip content="Tutorial" position={Position.BOTTOM}> <Tooltip content={t('Tutorial')} position={Position.BOTTOM}>
<Button <Button
id="top-panel-help-button" id="top-panel-help-button"
intent="none" intent="none"
@ -151,12 +155,12 @@ export default function TopPanel(props: any) {
</Tooltip> </Tooltip>
</div> </div>
); );
}, [getClassesCallback]); }, [getClassesCallback, t]);
const renderSettingsButton = useCallback(() => { const renderSettingsButton = useCallback(() => {
return ( return (
<div className={getClassesCallback().topPanelControlButtonMargin}> <div className={getClassesCallback().topPanelControlButtonMargin}>
<Tooltip content="Settings" position={Position.BOTTOM}> <Tooltip content={t('Settings')} position={Position.BOTTOM}>
<Button <Button
id="top-panel-settings-button" id="top-panel-settings-button"
onClick={handleSettingsOpen} onClick={handleSettingsOpen}
@ -171,7 +175,7 @@ export default function TopPanel(props: any) {
</Tooltip> </Tooltip>
</div> </div>
); );
}, [getClassesCallback, handleSettingsOpen]); }, [getClassesCallback, handleSettingsOpen, t]);
const renderLogoWithAppName = useCallback(() => { const renderLogoWithAppName = useCallback(() => {
return ( return (
@ -179,10 +183,7 @@ export default function TopPanel(props: any) {
id="logo-with-popover-visit-website" id="logo-with-popover-visit-website"
className={getClassesCallback().logoWithAppName} className={getClassesCallback().logoWithAppName}
> >
<Tooltip <Tooltip content={deskreenButtonTooltip} position={Position.BOTTOM}>
content="Click to visit our website"
position={Position.BOTTOM}
>
<Button <Button
minimal minimal
onClick={() => { onClick={() => {
@ -205,7 +206,7 @@ export default function TopPanel(props: any) {
</Tooltip> </Tooltip>
</div> </div>
); );
}, [getClassesCallback]); }, [deskreenButtonTooltip, getClassesCallback]);
return ( return (
<> <>

View File

@ -33,9 +33,9 @@ exports[`should match exact snapshot 1`] = `
<Blueprint3.Alert <Blueprint3.Alert
canEscapeKeyCancel={false} canEscapeKeyCancel={false}
canOutsideClickCancel={false} canOutsideClickCancel={false}
cancelButtonText="Deny" cancelButtonText=""
className="class-allow-device-to-connect-alert" className="class-allow-device-to-connect-alert"
confirmButtonText="Allow" confirmButtonText=""
icon="feed" icon="feed"
intent="danger" intent="danger"
isOpen={true} isOpen={true}
@ -181,9 +181,7 @@ exports[`should match exact snapshot 1`] = `
<Component> <Component>
<h4 <h4
className="bp3-heading" className="bp3-heading"
> />
Device is trying to connect, do you allow?
</h4>
</Component> </Component>
<DeviceInfoCallout> <DeviceInfoCallout>
<Component <Component
@ -203,15 +201,25 @@ exports[`should match exact snapshot 1`] = `
} }
} }
> >
Partner Device Info: :
</h4> </h4>
</Component> </Component>
<Blueprint3.Callout <Blueprint3.Callout
id="device-info-callout" id="device-info-callout"
style={
Object {
"borderRadius": "8px",
}
}
> >
<div <div
className="bp3-callout" className="bp3-callout"
id="device-info-callout" id="device-info-callout"
style={
Object {
"borderRadius": "8px",
}
}
> >
<Row <Row
center="xs" center="xs"
@ -232,7 +240,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Device Type: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -243,8 +252,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
This should match with 'Device IP' displayed on the screen of device
that is trying to connect.
</Blueprint3.Text> </Blueprint3.Text>
<span <span
style={ style={
@ -257,8 +265,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
</React.Fragment> </React.Fragment>
@ -280,8 +287,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
This should match with 'Device IP' displayed on the screen of device
that is trying to connect.
</Blueprint3.Text> </Blueprint3.Text>
<span <span
style={ style={
@ -294,8 +300,7 @@ exports[`should match exact snapshot 1`] = `
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> >
If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
</React.Fragment> </React.Fragment>
@ -369,7 +374,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="bp3-text-large" className="bp3-text-large"
> >
Device IP: :
<span <span
className="device-ip-span" className="device-ip-span"
/> />
@ -406,7 +412,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Device Browser: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -417,7 +424,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="" className=""
> >
Device OS: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -437,7 +445,8 @@ exports[`should match exact snapshot 1`] = `
<div <div
className="bp3-text-overflow-ellipsis bp3-text-muted" className="bp3-text-overflow-ellipsis bp3-text-muted"
> >
Session ID: :
<span /> <span />
</div> </div>
</Blueprint3.Text> </Blueprint3.Text>
@ -457,7 +466,7 @@ exports[`should match exact snapshot 1`] = `
<Blueprint3.Button <Blueprint3.Button
intent="danger" intent="danger"
onClick={[Function]} onClick={[Function]}
text="Allow" text=""
> >
<button <button
className="bp3-button bp3-intent-danger" className="bp3-button bp3-intent-danger"
@ -470,38 +479,6 @@ exports[`should match exact snapshot 1`] = `
<Blueprint3.Icon <Blueprint3.Icon
key="leftIcon" key="leftIcon"
/> />
<span
className="bp3-button-text"
key="text"
>
Allow
</span>
<Blueprint3.Icon
key="rightIcon"
/>
</button>
</Blueprint3.Button>
<Blueprint3.Button
onClick={[Function]}
text="Deny"
>
<button
className="bp3-button"
onBlur={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
onKeyUp={[Function]}
type="button"
>
<Blueprint3.Icon
key="leftIcon"
/>
<span
className="bp3-button-text"
key="text"
>
Deny
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />

View File

@ -93,9 +93,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
class="bp3-text-muted" class="bp3-text-muted"
> />
Connected Devices
</div>
</div> </div>
<button <button
class="bp3-button bp3-disabled bp3-intent-danger" class="bp3-button bp3-disabled bp3-intent-danger"
@ -122,11 +120,6 @@ exports[`should match exact snapshot 1`] = `
/> />
</svg> </svg>
</span> </span>
<span
class="bp3-button-text"
>
Disconnect all devices
</span>
</button> </button>
</div> </div>
</div> </div>
@ -212,9 +205,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
class="bp3-text-muted" class="bp3-text-muted"
> />
Connected Devices
</div>
</div> </div>
<button <button
class="bp3-button bp3-disabled bp3-intent-danger" class="bp3-button bp3-disabled bp3-intent-danger"
@ -241,11 +232,6 @@ exports[`should match exact snapshot 1`] = `
/> />
</svg> </svg>
</span> </span>
<span
class="bp3-button-text"
>
Disconnect all devices
</span>
</button> </button>
</div> </div>
</div> </div>
@ -406,9 +392,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="bp3-text-muted" className="bp3-text-muted"
> />
Connected Devices
</div>
</Blueprint3.Text> </Blueprint3.Text>
</div> </div>
<Blueprint3.Button <Blueprint3.Button
@ -451,12 +435,6 @@ exports[`should match exact snapshot 1`] = `
</svg> </svg>
</span> </span>
</Blueprint3.Icon> </Blueprint3.Icon>
<span
className="bp3-button-text"
key="text"
>
Disconnect all devices
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />
@ -608,8 +586,8 @@ exports[`should match exact snapshot 1`] = `
<Blueprint3.Alert <Blueprint3.Alert
canEscapeKeyCancel={true} canEscapeKeyCancel={true}
canOutsideClickCancel={true} canOutsideClickCancel={true}
cancelButtonText="No, Cancel" cancelButtonText=""
confirmButtonText="Yes, Disconnect All" confirmButtonText=""
icon="warning-sign" icon="warning-sign"
intent="danger" intent="danger"
isOpen={false} isOpen={false}

View File

@ -103,9 +103,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="bp3-running-text" className="bp3-running-text"
> />
Entire Screen
</div>
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
<Blueprint3.Icon <Blueprint3.Icon
@ -168,9 +166,7 @@ exports[`should match exact snapshot 1`] = `
> >
<div <div
className="bp3-running-text" className="bp3-running-text"
> />
Application Window
</div>
</Blueprint3.Text> </Blueprint3.Text>
</span> </span>
<Blueprint3.Icon <Blueprint3.Icon
@ -202,12 +198,6 @@ exports[`should match exact snapshot 1`] = `
<Blueprint3.Icon <Blueprint3.Icon
key="leftIcon" key="leftIcon"
/> />
<span
className="bp3-button-text"
key="text"
>
OR
</span>
<Blueprint3.Icon <Blueprint3.Icon
key="rightIcon" key="rightIcon"
/> />

View File

@ -17,7 +17,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
> >
<Col> <Col>
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}
@ -64,9 +64,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
<Blueprint3.Text <Blueprint3.Text
ellipsize={false} ellipsize={false}
tagName="div" tagName="div"
> />
Donate!
</Blueprint3.Text>
</div> </div>
</Col> </Col>
</Row> </Row>
@ -79,7 +77,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
id="logo-with-popover-visit-website" id="logo-with-popover-visit-website"
> >
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Click to visit our website" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}
@ -118,7 +116,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
className="makeStyles-topPanelControlButtonMargin-34" className="makeStyles-topPanelControlButtonMargin-34"
> >
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Connected Devices" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}
@ -143,7 +141,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
className="makeStyles-topPanelControlButtonMargin-55" className="makeStyles-topPanelControlButtonMargin-55"
> >
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Tutorial" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}
@ -168,7 +166,7 @@ exports[`<TopPanel /> should match exact snapshot 1`] = `
className="makeStyles-topPanelControlButtonMargin-76" className="makeStyles-topPanelControlButtonMargin-76"
> >
<Blueprint3.Tooltip <Blueprint3.Tooltip
content="Settings" content=""
hoverCloseDelay={0} hoverCloseDelay={0}
hoverOpenDelay={100} hoverOpenDelay={100}
minimal={false} minimal={false}

View File

@ -10,6 +10,10 @@ import settings from 'electron-settings';
import config from './app.lang.config'; import config from './app.lang.config';
import isProduction from '../utils/isProduction'; import isProduction from '../utils/isProduction';
import translationEN from '../locales/en/translation.json';
import translationUA from '../locales/ua/translation.json';
import translationRU from '../locales/ru/translation.json';
export const getLangFullNameToLangISOKeyMap = (): Map<string, string> => { export const getLangFullNameToLangISOKeyMap = (): Map<string, string> => {
const res = new Map<string, string>(); const res = new Map<string, string>();
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
@ -32,6 +36,27 @@ export const getLangISOKeyToLangFullNameMap = (): Map<string, string> => {
return res; return res;
}; };
function shuffleArray(array: any[]) {
// eslint-disable-next-line no-plusplus
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
export const getShuffledArrayOfHello = (): string[] => {
const res: string[] = [];
res.push(translationUA.Hello);
res.push(translationRU.Hello);
shuffleArray(res);
res.unshift(translationEN.Hello);
return res;
};
const appPath = remote.getGlobal('appPath'); const appPath = remote.getGlobal('appPath');
const i18nextOptions = { const i18nextOptions = {

View File

@ -6,10 +6,21 @@ import Stepper from '@material-ui/core/Stepper';
import Step from '@material-ui/core/Step'; import Step from '@material-ui/core/Step';
import StepLabel from '@material-ui/core/StepLabel'; import StepLabel from '@material-ui/core/StepLabel';
import { Row, Col, Grid } from 'react-flexbox-grid'; import { Row, Col, Grid } from 'react-flexbox-grid';
import { Dialog, H3, H4, H5, Icon, Spinner, Text } from '@blueprintjs/core'; import settings from 'electron-settings';
import {
Button,
Dialog,
H1,
H3,
H4,
H5,
Icon,
Spinner,
Text,
} from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import { TFunction } from 'i18next';
import { useToasts } from 'react-toast-notifications'; import { useToasts } from 'react-toast-notifications';
import SuccessStep from '../components/StepsOfStepper/SuccessStep'; import SuccessStep from '../components/StepsOfStepper/SuccessStep';
import IntermediateStep from '../components/StepsOfStepper/IntermediateStep'; import IntermediateStep from '../components/StepsOfStepper/IntermediateStep';
import AllowConnectionForDeviceAlert from '../components/AllowConnectionForDeviceAlert'; import AllowConnectionForDeviceAlert from '../components/AllowConnectionForDeviceAlert';
@ -23,6 +34,9 @@ import SharingSessionService from '../features/SharingSessionService';
import ConnectedDevicesService from '../features/ConnectedDevicesService'; import ConnectedDevicesService from '../features/ConnectedDevicesService';
import SharingSessionStatusEnum from '../features/SharingSessionService/SharingSessionStatusEnum'; import SharingSessionStatusEnum from '../features/SharingSessionService/SharingSessionStatusEnum';
import Logger from '../utils/LoggerWithFilePrefix'; import Logger from '../utils/LoggerWithFilePrefix';
import LanguageSelector from '../components/LanguageSelector';
import { getShuffledArrayOfHello } from '../configs/i18next.config.client';
import ToggleThemeBtnGroup from '../components/ToggleThemeBtnGroup';
const log = new Logger(__filename); const log = new Logger(__filename);
@ -33,6 +47,8 @@ const connectedDevicesService = remote.getGlobal(
'connectedDevicesService' 'connectedDevicesService'
) as ConnectedDevicesService; ) as ConnectedDevicesService;
const Fade = require('react-reveal/Fade');
const useStyles = makeStyles(() => const useStyles = makeStyles(() =>
createStyles({ createStyles({
stepContent: { stepContent: {
@ -51,21 +67,28 @@ const useStyles = makeStyles(() =>
}) })
); );
function getSteps() { function getSteps(t: TFunction) {
return ['Connect', 'Select', 'Confirm']; return [t('Connect'), t('Select'), t('Confirm')];
} }
// eslint-disable-next-line react/display-name // eslint-disable-next-line react/display-name
const DeskreenStepper = React.forwardRef((_props, ref) => { const DeskreenStepper = React.forwardRef((_props, ref) => {
const { t } = useTranslation();
const classes = useStyles(); const classes = useStyles();
const { isDarkTheme, currentLanguage } = useContext(SettingsContext); const { isDarkTheme } = useContext(SettingsContext);
const { addToast } = useToasts(); const { addToast } = useToasts();
const [isAlertOpen, setIsAlertOpen] = useState(false); const [isAlertOpen, setIsAlertOpen] = useState(false);
const [isUserAllowedConnection, setIsUserAllowedConnection] = useState(false); const [isUserAllowedConnection, setIsUserAllowedConnection] = useState(false);
const [isNoWiFiError, setisNoWiFiError] = useState(false); const [isNoWiFiError, setisNoWiFiError] = useState(false);
const [isSelectLanguageDialogOpen, setIsSelectLanguageDialogOpen] = useState(
false
);
const [isDisplayHelloWord, setIsDisplayHelloWord] = useState(true);
const [helloWord, setHelloWord] = useState('Hello');
const [ const [
pendingConnectionDevice, pendingConnectionDevice,
@ -109,9 +132,29 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
}, []); }, []);
useEffect(() => { useEffect(() => {
sharingSessionService.setAppLanguage(currentLanguage); const isFirstTimeStart = !settings.hasSync('isNotFirstTimeAppStart');
sharingSessionService.setAppTheme(isDarkTheme); setIsSelectLanguageDialogOpen(isFirstTimeStart);
}, [currentLanguage, isDarkTheme]);
if (!isFirstTimeStart) return () => {};
const helloWords = getShuffledArrayOfHello();
let pos = 0;
const helloInterval = setInterval(() => {
setIsDisplayHelloWord(false);
if (pos + 1 === helloWords.length) {
pos = 0;
} else {
pos += 1;
}
setHelloWord(helloWords[pos]);
setIsDisplayHelloWord(true);
}, 4000);
return () => {
clearInterval(helloInterval);
};
}, []);
const [activeStep, setActiveStep] = useState(0); const [activeStep, setActiveStep] = useState(0);
const [isEntireScreenSelected, setIsEntireScreenSelected] = useState(false); const [isEntireScreenSelected, setIsEntireScreenSelected] = useState(false);
@ -119,7 +162,7 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
isApplicationWindowSelected, isApplicationWindowSelected,
setIsApplicationWindowSelected, setIsApplicationWindowSelected,
] = useState(false); ] = useState(false);
const steps = getSteps(); const steps = getSteps(t);
const handleNext = useCallback(() => { const handleNext = useCallback(() => {
if (activeStep === steps.length - 1) { if (activeStep === steps.length - 1) {
@ -238,7 +281,9 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
addToast( addToast(
<Text> <Text>
Device is successfully disconnected by you. You can connect new device {t(
'Device is successfully disconnected by you You can connect a new device'
)}
</Text>, </Text>,
{ {
appearance: 'info', appearance: 'info',
@ -247,7 +292,7 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
isdarktheme: `${isDarkTheme}`, isdarktheme: `${isDarkTheme}`,
} }
); );
}, [addToast, handleResetWithSharingSessionRestart, isDarkTheme]); }, [addToast, handleResetWithSharingSessionRestart, isDarkTheme, t]);
const renderIntermediateOrSuccessStepContent = useCallback(() => { const renderIntermediateOrSuccessStepContent = useCallback(() => {
return activeStep === steps.length ? ( return activeStep === steps.length ? (
@ -365,6 +410,54 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
</div> </div>
</Grid> </Grid>
</Dialog> </Dialog>
<Dialog isOpen={isSelectLanguageDialogOpen} autoFocus usePortal>
<Grid>
<div style={{ padding: '10px' }}>
<Row center="xs" style={{ marginTop: '10px' }}>
<Fade collapse opposite when={isDisplayHelloWord} duration={700}>
<H1>{helloWord}</H1>
</Fade>
</Row>
<Row>
<Col xs>
<Row center="xs" style={{ marginTop: '20px' }}>
<Icon icon="translate" iconSize={50} color="#8A9BA8" />
</Row>
<Row center="xs" style={{ marginTop: '20px' }}>
<H5>{t('Language')}</H5>
</Row>
<Row center="xs" style={{ marginTop: '10px' }}>
<LanguageSelector />
</Row>
</Col>
<Col xs>
<Row center="xs" style={{ marginTop: '20px' }}>
<Icon icon="style" iconSize={50} color="#8A9BA8" />
</Row>
<Row center="xs" style={{ marginTop: '20px' }}>
<H5>{t('Color Theme')}</H5>
</Row>
<Row center="xs" style={{ marginTop: '10px' }}>
<ToggleThemeBtnGroup />
</Row>
</Col>
</Row>
<Row center="xs" style={{ marginTop: '20px' }}>
<Button
minimal
rightIcon="chevron-right"
onClick={() => {
setIsSelectLanguageDialogOpen(false);
settings.setSync('isNotFirstTimeAppStart', true);
}}
style={{ borderRadius: '50px' }}
>
{t('Continue')}
</Button>
</Row>
</div>
</Grid>
</Dialog>
</> </>
); );
}); });

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -38,8 +36,6 @@ describe('createDesktopCapturerStream callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,

View File

@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -58,8 +56,6 @@ describe('handleCreatePeer callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,

View File

@ -3,8 +3,6 @@ import handlePeerOnData from './handlePeerOnData';
import getDesktopSourceStreamBySourceID from './getDesktopSourceStreamBySourceID'; import getDesktopSourceStreamBySourceID from './getDesktopSourceStreamBySourceID';
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -50,8 +48,6 @@ describe('handlePeerOnData callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,

View File

@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import uuid from 'uuid'; import uuid from 'uuid';
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -17,6 +15,8 @@ import handleRecieveEncryptedMessage, {
handleDeviceIPMessage, handleDeviceIPMessage,
} from './handleRecieveEncryptedMessage'; } from './handleRecieveEncryptedMessage';
import DesktopCapturerSourcesService from '../DesktopCapturerSourcesService'; import DesktopCapturerSourcesService from '../DesktopCapturerSourcesService';
import getAppTheme from '../../utils/getAppTheme';
import getAppLanguage from '../../utils/getAppLanguage';
jest.useFakeTimers(); jest.useFakeTimers();
@ -51,8 +51,6 @@ describe('handleRecieveEncryptedMessage.ts', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,
@ -123,7 +121,7 @@ describe('handleRecieveEncryptedMessage.ts', () => {
peerConnection.sendEncryptedMessage = jest.fn(); peerConnection.sendEncryptedMessage = jest.fn();
const TEST_GET_APP_THEME_PAYLOAD = { const TEST_GET_APP_THEME_PAYLOAD = {
type: 'APP_THEME', type: 'APP_THEME',
payload: { value: peerConnection.appColorTheme }, payload: { value: getAppTheme() },
}; };
// @ts-ignore // @ts-ignore
processMessage.mockImplementation(() => { processMessage.mockImplementation(() => {
@ -149,7 +147,7 @@ describe('handleRecieveEncryptedMessage.ts', () => {
peerConnection.sendEncryptedMessage = jest.fn(); peerConnection.sendEncryptedMessage = jest.fn();
const TEST_GET_APP_LANGUAGE_PAYLOAD = { const TEST_GET_APP_LANGUAGE_PAYLOAD = {
type: 'APP_LANGUAGE', type: 'APP_LANGUAGE',
payload: { value: peerConnection.appLanguage }, payload: { value: getAppLanguage() },
}; };
// @ts-ignore // @ts-ignore
processMessage.mockImplementation(() => { processMessage.mockImplementation(() => {

View File

@ -1,3 +1,4 @@
import settings from 'electron-settings';
import uuid from 'uuid'; import uuid from 'uuid';
import { process as processMessage } from '../../utils/message'; import { process as processMessage } from '../../utils/message';
@ -42,13 +43,21 @@ export default async function handleRecieveEncryptedMessage(
if (message.type === 'GET_APP_THEME') { if (message.type === 'GET_APP_THEME') {
peerConnection.sendEncryptedMessage({ peerConnection.sendEncryptedMessage({
type: 'APP_THEME', type: 'APP_THEME',
payload: { value: peerConnection.appColorTheme }, payload: {
value: settings.hasSync('appIsDarkTheme')
? settings.getSync('appIsDarkTheme') === 'true'
: false,
},
}); });
} }
if (message.type === 'GET_APP_LANGUAGE') { if (message.type === 'GET_APP_LANGUAGE') {
peerConnection.sendEncryptedMessage({ peerConnection.sendEncryptedMessage({
type: 'APP_LANGUAGE', type: 'APP_LANGUAGE',
payload: { value: peerConnection.appLanguage }, payload: {
value: settings.hasSync('appLanguage')
? settings.getSync('appLanguage')
: 'en',
},
}); });
} }
} }

View File

@ -1,7 +1,5 @@
import handleSelfDestroy from './handleSelfDestroy'; import handleSelfDestroy from './handleSelfDestroy';
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -38,8 +36,6 @@ describe('handleSelfDestroy callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
({ ({
unmarkRoomIDAsTaken: jest.fn(), unmarkRoomIDAsTaken: jest.fn(),
} as unknown) as RoomIDService, } as unknown) as RoomIDService,

View File

@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -30,8 +28,6 @@ describe('setDisplaySizeFromLocalStream callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,

View File

@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -51,8 +49,6 @@ describe('handleSocket callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,

View File

@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -55,8 +53,6 @@ describe('handleSocketUserEnter callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,

View File

@ -1,8 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -27,8 +25,6 @@ describe('handleSocketUserExit callback', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,

View File

@ -6,8 +6,6 @@ import ConnectedDevicesService from '../ConnectedDevicesService';
import SharingSessionService from '../SharingSessionService'; import SharingSessionService from '../SharingSessionService';
import DesktopCapturerSourcesService from '../DesktopCapturerSourcesService'; import DesktopCapturerSourcesService from '../DesktopCapturerSourcesService';
import { import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
@ -17,6 +15,8 @@ import handleSelfDestroy from './handleSelfDestroy';
import handleRecieveEncryptedMessage from './handleRecieveEncryptedMessage'; import handleRecieveEncryptedMessage from './handleRecieveEncryptedMessage';
import handleCreatePeer from './handleCreatePeer'; import handleCreatePeer from './handleCreatePeer';
import { prepare as prepareMessage } from '../../utils/message'; import { prepare as prepareMessage } from '../../utils/message';
import getAppLanguage from '../../utils/getAppLanguage';
import getAppTheme from '../../utils/getAppTheme';
jest.useFakeTimers(); jest.useFakeTimers();
@ -60,8 +60,6 @@ describe('PeerConnection index.ts tests', () => {
TEST_ROOM_ID, TEST_ROOM_ID,
TEST_SHARING_SESSION_ID, TEST_SHARING_SESSION_ID,
TEST_USER, TEST_USER,
TEST_APP_THEME, // TODO getAppTheme
TEST_APP_LANGUAGE, // TODO getLanguage
{} as RoomIDService, {} as RoomIDService,
{} as ConnectedDevicesService, {} as ConnectedDevicesService,
{} as SharingSessionService, {} as SharingSessionService,
@ -82,32 +80,6 @@ describe('PeerConnection index.ts tests', () => {
expect(peerConnection.sharingSessionService).toBeDefined(); expect(peerConnection.sharingSessionService).toBeDefined();
}); });
describe('when setAppLanguage was called', () => {
it('should set peerConnection app language and call notifyClientWithNewLanguage', () => {
const TEST_APP_LANG = 'ua';
const mockNotify = jest.fn();
peerConnection.notifyClientWithNewLanguage = mockNotify;
peerConnection.setAppLanguage(TEST_APP_LANG);
expect(mockNotify).toBeCalled();
expect(peerConnection.appLanguage).toBe(TEST_APP_LANG);
});
});
describe('when setAppTheme was called', () => {
it('should set peerConnection theme and call notifyClientWithNewColorTheme', () => {
const APP_THEME = true;
const mockNotify = jest.fn();
peerConnection.notifyClientWithNewColorTheme = mockNotify;
peerConnection.setAppTheme(APP_THEME);
expect(mockNotify).toBeCalled();
expect(peerConnection.appColorTheme).toBe(APP_THEME);
});
});
describe('when notifyClientWithNewLanguage was called', () => { describe('when notifyClientWithNewLanguage was called', () => {
it('should call sendEncryptedMessage with proper payload', () => { it('should call sendEncryptedMessage with proper payload', () => {
peerConnection.sendEncryptedMessage = jest.fn(); peerConnection.sendEncryptedMessage = jest.fn();
@ -116,7 +88,7 @@ describe('PeerConnection index.ts tests', () => {
expect(peerConnection.sendEncryptedMessage).toBeCalledWith({ expect(peerConnection.sendEncryptedMessage).toBeCalledWith({
type: 'APP_LANGUAGE', type: 'APP_LANGUAGE',
payload: { value: peerConnection.appLanguage }, payload: { value: getAppLanguage() },
}); });
}); });
}); });
@ -129,7 +101,7 @@ describe('PeerConnection index.ts tests', () => {
expect(peerConnection.sendEncryptedMessage).toBeCalledWith({ expect(peerConnection.sendEncryptedMessage).toBeCalledWith({
type: 'APP_THEME', type: 'APP_THEME',
payload: { value: peerConnection.appColorTheme }, payload: { value: getAppTheme() },
}); });
}); });
}); });

View File

@ -17,6 +17,8 @@ import NullUser from './NullUser';
import NullSimplePeer from './NullSimplePeer'; import NullSimplePeer from './NullSimplePeer';
import setDisplaySizeFromLocalStream from './handleSetDisplaySizeFromLocalStream'; import setDisplaySizeFromLocalStream from './handleSetDisplaySizeFromLocalStream';
import DesktopCapturerSourceType from '../DesktopCapturerSourcesService/DesktopCapturerSourceType'; import DesktopCapturerSourceType from '../DesktopCapturerSourcesService/DesktopCapturerSourceType';
import getAppLanguage from '../../utils/getAppLanguage';
import getAppTheme from '../../utils/getAppTheme';
type DisplaySize = { width: number; height: number }; type DisplaySize = { width: number; height: number };
@ -41,15 +43,11 @@ export default class PeerConnection {
onDeviceConnectedCallback: (device: Device) => void; onDeviceConnectedCallback: (device: Device) => void;
displayID: string; displayID: string;
sourceDisplaySize: DisplaySize | undefined; sourceDisplaySize: DisplaySize | undefined;
appLanguage: string;
appColorTheme: boolean;
constructor( constructor(
roomID: string, roomID: string,
sharingSessionID: string, sharingSessionID: string,
user: LocalPeerUser, user: LocalPeerUser,
appColorTheme: boolean,
appLanguage: string,
roomIDService: RoomIDService, roomIDService: RoomIDService,
connectedDevicesService: ConnectedDevicesService, connectedDevicesService: ConnectedDevicesService,
sharingSessionsService: SharingSessionService, sharingSessionsService: SharingSessionService,
@ -71,8 +69,6 @@ export default class PeerConnection {
this.localStream = null; this.localStream = null;
this.displayID = ''; this.displayID = '';
this.sourceDisplaySize = undefined; this.sourceDisplaySize = undefined;
this.appLanguage = appLanguage;
this.appColorTheme = appColorTheme;
this.desktopCapturerSourcesService = desktopCapturerSourcesService; this.desktopCapturerSourcesService = desktopCapturerSourcesService;
this.onDeviceConnectedCallback = () => {}; this.onDeviceConnectedCallback = () => {};
@ -83,27 +79,19 @@ export default class PeerConnection {
}); });
} }
setAppLanguage(lang: string) {
this.appLanguage = lang;
this.notifyClientWithNewLanguage();
}
setAppTheme(theme: boolean) {
this.appColorTheme = theme;
this.notifyClientWithNewColorTheme();
}
notifyClientWithNewLanguage() { notifyClientWithNewLanguage() {
this.sendEncryptedMessage({ this.sendEncryptedMessage({
type: 'APP_LANGUAGE', type: 'APP_LANGUAGE',
payload: { value: this.appLanguage }, payload: {
value: getAppLanguage(),
},
}); });
} }
notifyClientWithNewColorTheme() { notifyClientWithNewColorTheme() {
this.sendEncryptedMessage({ this.sendEncryptedMessage({
type: 'APP_THEME', type: 'APP_THEME',
payload: { value: this.appColorTheme }, payload: { value: getAppTheme() },
}); });
} }

View File

@ -6,8 +6,6 @@ import SharingType from './SharingTypeEnum';
jest.useFakeTimers(); jest.useFakeTimers();
const testAppLang = 'ua';
const testAppTheme = true;
const testUser = { const testUser = {
username: '', username: '',
privateKey: '', privateKey: '',
@ -19,10 +17,7 @@ describe('SharingSession unit tests', () => {
beforeEach(() => { beforeEach(() => {
process.env.RUN_MODE = 'test-jest'; process.env.RUN_MODE = 'test-jest';
sharingSession = new SharingSession( sharingSession = new SharingSession('1234', testUser, {
'1234',
testUser,
{
// @ts-ignore: fine here // @ts-ignore: fine here
createPeerConnectionHelperRenderer: () => { createPeerConnectionHelperRenderer: () => {
return { return {
@ -33,10 +28,7 @@ describe('SharingSession unit tests', () => {
close: jest.fn(), close: jest.fn(),
}; };
}, },
}, });
testAppLang,
testAppTheme
);
}); });
afterEach(() => { afterEach(() => {
@ -99,8 +91,6 @@ describe('SharingSession unit tests', () => {
roomID: sharingSession.roomID, roomID: sharingSession.roomID,
sharingSessionID: sharingSession.id, sharingSessionID: sharingSession.id,
user: testUser, user: testUser,
appTheme: testAppTheme,
appLanguage: testAppLang,
}); });
}); });
}); });
@ -258,25 +248,21 @@ describe('SharingSession unit tests', () => {
describe('when appLanguageChanged() is called', () => { describe('when appLanguageChanged() is called', () => {
it('should call .webContents.send with proper event name', () => { it('should call .webContents.send with proper event name', () => {
const testLang = 'ua'; sharingSession.appLanguageChanged();
sharingSession.appLanguageChanged(testLang);
expect( expect(
sharingSession.peerConnectionHelperRenderer?.webContents.send sharingSession.peerConnectionHelperRenderer?.webContents.send
).toBeCalledWith('app-language-changed', testLang); ).toBeCalledWith('app-language-changed');
}); });
}); });
describe('when appThemeChanged() is called', () => { describe('when appThemeChanged() is called', () => {
it('should call .webContents.send with proper event name', () => { it('should call .webContents.send with proper event name', () => {
const testTheme = true; sharingSession.appThemeChanged();
sharingSession.appThemeChanged(testTheme);
expect( expect(
sharingSession.peerConnectionHelperRenderer?.webContents.send sharingSession.peerConnectionHelperRenderer?.webContents.send
).toBeCalledWith('app-color-theme-changed', testTheme); ).toBeCalledWith('app-color-theme-changed');
}); });
}); });
}); });

View File

@ -5,8 +5,6 @@ import SharingSessionStatusEnum from './SharingSessionStatusEnum';
import SharingTypeEnum from './SharingTypeEnum'; import SharingTypeEnum from './SharingTypeEnum';
import PeerConnectionHelperRendererService from '../PeerConnectionHelperRendererService'; import PeerConnectionHelperRendererService from '../PeerConnectionHelperRendererService';
// type OnDeviceConnectedCallbackType = undefined | (device: Device) => void;
export default class SharingSession { export default class SharingSession {
id: string; id: string;
deviceID: string; deviceID: string;
@ -24,9 +22,7 @@ export default class SharingSession {
constructor( constructor(
_roomID: string, _roomID: string,
user: LocalPeerUser, user: LocalPeerUser,
peerConnectionHelperRendererService: PeerConnectionHelperRendererService, peerConnectionHelperRendererService: PeerConnectionHelperRendererService
appLanguage: string,
isDarkTheme: boolean
) { ) {
this.id = uuid.v4(); this.id = uuid.v4();
this.deviceID = ''; this.deviceID = '';
@ -51,8 +47,6 @@ export default class SharingSession {
roomID: this.roomID, roomID: this.roomID,
sharingSessionID: this.id, sharingSessionID: this.id,
user, user,
appTheme: isDarkTheme,
appLanguage,
} }
); );
}); });
@ -111,17 +105,13 @@ export default class SharingSession {
); );
} }
appLanguageChanged(newLang: string) { appLanguageChanged() {
this.peerConnectionHelperRenderer?.webContents.send( this.peerConnectionHelperRenderer?.webContents.send('app-language-changed');
'app-language-changed',
newLang
);
} }
appThemeChanged(isDarkTheme: boolean) { appThemeChanged() {
this.peerConnectionHelperRenderer?.webContents.send( this.peerConnectionHelperRenderer?.webContents.send(
'app-color-theme-changed', 'app-color-theme-changed'
isDarkTheme
); );
} }

View File

@ -104,26 +104,6 @@ describe('SharingSessionService unit tests', () => {
}); });
}); });
describe('when setAppLanguage is called', () => {
it('should set app language accordingly', () => {
const testLang = 'be';
sharingSessionService.setAppLanguage(testLang);
expect(sharingSessionService.appLanguage).toBe(testLang);
});
});
describe('when setAppTheme is called', () => {
it('should set app language accordingly', () => {
const testTheme = true;
sharingSessionService.setAppTheme(testTheme);
expect(sharingSessionService.isDarkTheme).toBe(testTheme);
});
});
describe('when createWaitingForConnectionSharingSession is called', () => { describe('when createWaitingForConnectionSharingSession is called', () => {
it('should call waitWhileUserIsNotCreated', async () => { it('should call waitWhileUserIsNotCreated', async () => {
sharingSessionService.waitWhileUserIsNotCreated = jest sharingSessionService.waitWhileUserIsNotCreated = jest

View File

@ -17,8 +17,6 @@ export default class SharingSessionService {
connectedDevicesService: ConnectedDevicesService; connectedDevicesService: ConnectedDevicesService;
rendererWebrtcHelpersService: RendererWebrtcHelpersService; rendererWebrtcHelpersService: RendererWebrtcHelpersService;
isCreatingNewSharingSession: boolean; isCreatingNewSharingSession: boolean;
appLanguage = 'en';
isDarkTheme = false;
constructor( constructor(
_roomIDService: RoomIDService, _roomIDService: RoomIDService,
@ -40,14 +38,6 @@ export default class SharingSessionService {
}, 1000 * 60 * 60); // every hour }, 1000 * 60 * 60); // every hour
} }
setAppLanguage(newLang: string): void {
this.appLanguage = newLang;
}
setAppTheme(isDarkTheme: boolean): void {
this.isDarkTheme = isDarkTheme;
}
createUser(): Promise<undefined> { createUser(): Promise<undefined> {
// eslint-disable-next-line no-async-promise-executor // eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
@ -90,9 +80,7 @@ export default class SharingSessionService {
const sharingSession = new SharingSession( const sharingSession = new SharingSession(
roomID, roomID,
this.user as LocalPeerUser, this.user as LocalPeerUser,
this.rendererWebrtcHelpersService, this.rendererWebrtcHelpersService
this.appLanguage,
this.isDarkTheme
); );
this.sharingSessions.set(sharingSession.id, sharingSession); this.sharingSessions.set(sharingSession.id, sharingSession);
return sharingSession; return sharingSession;

View File

@ -1,8 +1,73 @@
{ {
"Language": "Language 🇬🇧 / 🇺🇸", "Hello": "Hello",
"Signaling server is running on port": "Signaling server is running on port ⚓", "Continue": "Continue",
"Language": "Language",
"ru": "Русский", "ru": "Русский",
"en": "English", "en": "English",
"ua": "Українська", "ua": "Українська",
"Scan the QR code": "Scan the QR code" "Donate": "Donate",
"If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better": "If you like Deskreen, consider contributing financially. Deskreen is open-source. Your donations keep us motivated to make Deskreen even better.",
"Click to visit our website": "Click to visit our website",
"Connected Devices": "Connected Devices",
"Tutorial": "Tutorial",
"Settings": "Settings",
"Connect": "Connect",
"Select": "Select",
"Confirm": "Confirm",
"Scan the QR code": "Scan the QR code",
"Make sure your computer and screen viewing device are connected to same Wi-Fi": "Make sure your computer and screen viewing device are connected to same Wi-Fi",
"Or type the following address in browser address bar on any device": "Or type the following address in browser address bar on any device",
"Someone is trying to connect, do you allow?": "Someone is trying to connect, do you allow?",
"Click to make bigger": "Click to make bigger",
"Click to copy": "Click to copy",
"Partner Device Info": "Partner Device Info",
"Device Type": "Device Type",
"Device IP": "Device IP",
"Device Browser": "Device Browser",
"Device OS": "Device OS",
"Session ID": "Session ID",
"Allow": "Allow",
"Deny": "Deny",
"Device is successfully disconnected by you You can connect a new device": "Device is successfully disconnected by you. You can connect a new device.",
"Deskreen Update is Available!": "Deskreen Update is Available!",
"Your current version is": "Your current version is",
"Click to download new updated version": "Click to download new updated version",
"Connected": "Connected",
"Click to see more": "Click to see more",
"This should match with Device IP displayed on the screen of device that is trying to connect": "This should match with Device IP displayed on the screen of device that is trying to connect.",
"If IP addresses dont match click Disconnect button": "If IP addresses don't match click Disconnect button to prevent unauthorized access to your computer screen.",
"Disconnect": "Disconnect",
"Choose Entire Screen or App window you want to share": "Choose Entire Screen or App window you want to share",
"OR": "OR",
"Entire Screen": "Entire Screen",
"Application Window": "Application Window",
"Check if all is OK and click Confirm": "Check if all is OK and click Confirm",
"Confirm Button Text": "Confirm",
"No, I need to choose other": "No, I need to share other thing",
"Done!": "Done!",
"Now you can see your screen on other device": "Now you can see your screen on other device.",
"You can manage connected devices by clicking Connected Devices button in top panel": "You can manage connected devices by clicking Connected Devices button in top panel.",
"Connect New Device": "Connect New Device",
"Select Entire Screen to Share": "Select Entire Screen to Share",
"Select App Window to Share": "Select App Window to Share",
"Refresh": "Refresh",
"Disconnect all devices": "Disconnect all devices",
"Are you sure you want to disconnect all connected viewing devices?": "Are you sure you want to disconnect all connected viewing devices?",
"This step can not be undone": "This step can not be reverted",
"You will have to connect all devices manually again": "You will have to connect all devices manually again",
"No, Cancel": "No, Cancel",
"Yes, Disconnect All": "Yes, Disconnect All",
"A new version of Deskreen is available! Click to download new version": "A new version of Deskreen is available! Click to download new version",
"Security": "Security",
"General": "General",
"About": "About",
"Website": "Website",
"About Deskreen": "About Deskreen",
"Security Settings": "Security Settings",
"Color Theme": "Color Theme",
"Automatic Updates": "Automatic Updates",
"General Settings": "General Settings",
"Disabled": "Disabled",
"Version": "Version",
"Copyright": "Copyright"
} }

View File

@ -0,0 +1,9 @@
{
"Confirm": "Confirm",
"No, Cancel": "No, Cancel",
"Yes, Disconnect All": "Yes, Disconnect All",
"Disconnect all devices": "Disconnect all devices",
"Are you sure you want to disconnect all connected viewing devices?": "Are you sure you want to disconnect all connected viewing devices?",
"This step can not be reverted": "This step can not be reverted",
"You will have to connect all devices manually again": "You will have to connect all devices manually again"
}

View File

@ -1,8 +1,73 @@
{ {
"Language": "Язык 🇷🇺", "Hello": "Привет",
"Signaling server is running on port": "Сигнальный сервер работает на порте ⚓", "Continue": "Продолжить",
"Language": "Язык",
"ru": "Русский", "ru": "Русский",
"en": "English", "en": "English",
"ua": "Українська", "ua": "Українська",
"Scan the QR code": "Отсканируйте QR код" "Donate": "Пожертвовать",
"If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better": "Если вам нравится Deskreen, подумайте о том, чтобы внести финансовый вклад. Deskreen - это оупенсорсный проэкт. Ваши пожертвования позволяют нам делать Deskreen еще лучше.",
"Click to visit our website": "Нажмите, чтобы посетить наш сайт",
"Connected Devices": "Подключенные устройства",
"Tutorial": "Инструкция по использованию",
"Settings": "Настройки",
"Connect": "Подключите",
"Select": "Выберите",
"Confirm": "Подтвердите",
"Scan the QR code": "Отсканируйте QR код",
"Make sure your computer and screen viewing device are connected to same Wi-Fi": "Убедитесь, что ваш компьютер и устройство просмотра экрана подключены к одному и тому же Wi-Fi",
"Or type the following address in browser address bar on any device": "Или введите следующий адрес вручную в адресной строке браузера на любом устройстве",
"Someone is trying to connect, do you allow?": "Кто-то пытается подключиться, вы разрешаете?",
"Click to make bigger": "Нажмите, чтобы увеличить",
"Click to copy": "Нажмите, чтобы скопировать",
"Partner Device Info": "Информация об устройстве партнера",
"Device Type": "Тип устройства",
"Device IP": "IP-aдрес устройства",
"Device Browser": "Веб-браузер устройства",
"Device OS": "ОС устройства",
"Session ID": "ID сессии",
"Allow": "Разрешить",
"Deny": "Отказать",
"Device is successfully disconnected by you You can connect a new device": "Устройство успешно отключено вами. Вы можете подключить новое устройство.",
"Deskreen Update is Available!": "Вышло обновление Deskreen!",
"Your current version is": "Ваша текущая версия",
"Click to download new updated version": "Нажмите, чтобы загрузить новую обновленную версию",
"Connected": "Подключено",
"Click to see more": "Нажмите, чтобы увидеть больше",
"This should match with Device IP displayed on the screen of device that is trying to connect": "Это должно совпадать с IP-адресом устройства, отображаемым на экране устройства, которое пытается подключиться.",
"If IP addresses dont match click Disconnect button": "Если IP-адреса не совпадают, нажмите кнопку «Отключить», чтобы предотвратить несанкционированный доступ к экрану вашего компьютера.",
"Disconnect": "Отсоединить",
"Choose Entire Screen or App window you want to share": "Выберите Весь экран или Окно приложения, которым хотите поделиться",
"OR": "ИЛИ",
"Entire Screen": "Весь экран",
"Application Window": "Окно приложения",
"Check if all is OK and click Confirm": "Убедитесь, что все в порядке, и нажмите Подтвердить",
"Confirm Button Text": "Подтвердить",
"No, I need to choose other": "Нет, мне нужно выбрать другое",
"Done!": "Сделано!",
"Now you can see your screen on other device": "Теперь вы можете видеть свой экран на другом устройстве.",
"You can manage connected devices by clicking Connected Devices button in top panel": "Вы можете управлять подключенными устройствами, нажав кнопку «Подключенные устройства» на верхней панели.",
"Connect New Device": "Подключить новое устройство",
"Select Entire Screen to Share": "Выберите экран которым хотите поделиться",
"Select App Window to Share": "Выберите окно приложения которым хотите поделиться",
"Refresh": "Обновить",
"Disconnect all devices": "Отсоединить все устройства",
"Are you sure you want to disconnect all connected viewing devices?": "Вы уверены, что хотите отключить все подключенные устройства просмотра?",
"This step can not be undone": "Этот шаг невозможно будет отменить",
"You will have to connect all devices manually again": "После этого вам придется снова подключить каждое устройство",
"No, Cancel": "Нет, отменить",
"Yes, Disconnect All": "Да, отсоединить все устройства",
"A new version of Deskreen is available! Click to download new version": "Доступна новая версия Deskreen! Нажмите, чтобы загрузить новую версию",
"Security": "Безопасность",
"General": "Общие",
"About": "О нас",
"Website": "Веб-сайт",
"About Deskreen": "Про Deskreen",
"Security Settings": "Настройки безопасности",
"Color Theme": "Цветовая схема",
"Automatic Updates": "Авто-обновления",
"General Settings": "Общие настройки",
"Disabled": "Отключено",
"Version": "Версия",
"Copyright": "Авторские права"
} }

View File

@ -1,8 +1,73 @@
{ {
"Language": "Мова 🇺🇦", "Hello": "Привіт",
"Signaling server is running on port": "Сигнальный сервер працює на порту ⚓", "Continue": "Продовжити",
"Language": "Мова",
"ru": "Русский", "ru": "Русский",
"en": "English", "en": "English",
"ua": "Українська", "ua": "Українська",
"Scan the QR code": "Відскануйте QR код" "Donate": "Пожертвувати",
"If you like Deskreen consider contributing financially Deskreen is open-source Your donations keep us motivated to make Deskreen even better": "Якщо вам подобається Deskreen, подумайте про те, щоб внести фінансовий внесок. Deskreen - це оупенсорсний проект. Ваші пожертвування дозволяють нам робити Deskreen ще краще.",
"Click to visit our website": "Натисніть, щоб відвідати наш сайт",
"Connected Devices": "Підключені пристрої",
"Tutorial": "Інструкція по використанню",
"Settings": "Налаштування",
"Connect": "Підключіть",
"Select": "Виберіть",
"Confirm": "Підтвердіть",
"Scan the QR code": "Відскануйте QR код",
"Make sure your computer and screen viewing device are connected to same Wi-Fi": "Переконайтеся, що ваш комп'ютер і пристрій перегляду екрану підключені до одного й того ж Wi-Fi",
"Or type the following address in browser address bar on any device": "Або введіть наступну адресу в адресному рядку браузера на будь-якому пристрої",
"Someone is trying to connect, do you allow?": "Хтось намагається підключитися, ви дозволяєте?",
"Click to make bigger": "Натисніть, щоб збільшити",
"Click to copy": "Натисніть, щоб скопіювати",
"Partner Device Info": "Інформація про пристрій партнера",
"Device Type": "Тип пристрою",
"Device IP": "IP-aдрес пристрою",
"Device Browser": "Веб-браузер пристрою",
"Device OS": "ОС пристрою",
"Session ID": "ID сесії",
"Allow": "Дозволити",
"Deny": "Відмовити",
"Device is successfully disconnected by you You can connect a new device": "Пристрій успішно відключено вами. Ви можете підключити новий пристрій.",
"Deskreen Update is Available!": "Вийшло оновлення Deskreen!",
"Your current version is": "Ваша поточна версія",
"Click to download new updated version": "Натисніть, щоб завантажити нову оновлену версію",
"Connected": "З'єднано",
"Click to see more": "Натисніть, щоб побачити більше",
"This should match with Device IP displayed on the screen of device that is trying to connect": "Це повинно збігатися з IP-адресою пристрою на екрані пристрою, який намагається підключитися.",
"If IP addresses dont match click Disconnect button": "Якщо IP-адреси не збігаються, натисніть кнопку «Відключити», щоб запобігти несанкціонованому доступу до екрану вашого комп'ютера.",
"Disconnect": "Від'єднати",
"Choose Entire Screen or App window you want to share": "Виберіть Весь екран або Вікно додатка, яким хочете поділитися",
"OR": "ЧИ",
"Entire Screen": "Весь екран",
"Application Window": "Вікно додатка",
"Check if all is OK and click Confirm": "Переконайтеся, що все гаразд, і натисніть Підтвердити",
"Confirm Button Text": "Підтвердити",
"No, I need to choose other": "Ні, мені потрібно вибрати інше",
"Done!": "Зроблено!",
"Now you can see your screen on other device": "Тепер ви можете бачити свій екран на іншому пристрою.",
"You can manage connected devices by clicking Connected Devices button in top panel": "Ви можете управляти підключеними пристроями, натиснувши кнопку «Підключені пристрої» на верхній панелі.",
"Connect New Device": "Підключити новий пристрій",
"Select Entire Screen to Share": "Виберіть екран яким хочете поділитися",
"Select App Window to Share": "Виберіть вікно додатка яким хочете поділитися",
"Refresh": "Відновити",
"Disconnect all devices": "Від'єднати всі пристрої",
"Are you sure you want to disconnect all connected viewing devices?": "Ви впевнені, що хочете відключити всі підключені пристрої перегляду?",
"This step can not be undone": "Цей крок неможливо буде скасувати",
"You will have to connect all devices manually again": "Після цього вам доведеться знову підключити кожен пристрій",
"No, Cancel": "Ні, скасувати",
"Yes, Disconnect All": "Так, від'єднати всі пристрої",
"A new version of Deskreen is available! Click to download new version": "Доступна нова версія Deskreen! Натисніть, щоб завантажити нову версію",
"Security": "Безпека",
"General": "Загальні",
"About": "Про нас",
"Website": "Веб сайт",
"About Deskreen": "Про Deskreen",
"Security Settings": "Налаштування безпеки",
"Color Theme": "Схема кольорів",
"Automatic Updates": "Авто-оновлення",
"General Settings": "Загальні налаштування",
"Disabled": "Відключено",
"Version": "Версія",
"Copyright": "Авторські права"
} }

View File

@ -62,8 +62,12 @@ export default class DeskreenApp {
const showNotification = () => { const showNotification = () => {
const notification = { const notification = {
title: 'Deskreen Update is Available!', title: i18n.t('Deskreen Update is Available!'),
body: `Your current version is ${this.appVersion} Click to download new ${this.latestVersion} updated version.`, body: `${i18n.t('Your current version is')} ${
this.appVersion
} | ${i18n.t('Click to download new updated version')} ${
this.latestVersion
}`,
}; };
const notificationInstance = new Notification(notification); const notificationInstance = new Notification(notification);
notificationInstance.show(); notificationInstance.show();

2
app/package-lock.json generated
View File

@ -1,5 +1,5 @@
{ {
"name": "Deskreen", "name": "Deskreen",
"version": "1.0.5", "version": "1.0.6",
"lockfileVersion": 1 "lockfileVersion": 1
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "deskreen", "name": "deskreen",
"productName": "Deskreen", "productName": "Deskreen",
"version": "1.0.5", "version": "1.0.6",
"description": "Deskreen turns any device into a secondary screen for your computer", "description": "Deskreen turns any device into a secondary screen for your computer",
"main": "./main.prod.js", "main": "./main.prod.js",
"author": { "author": {

View File

@ -252,40 +252,6 @@ describe('peerConnectionHelperRendererWindowIndex tests', () => {
).toHaveBeenCalled(); ).toHaveBeenCalled();
}); });
}); });
describe('when ipcRenderer.on("app-color-theme-changed" callback occurred', () => {
it('should call peerConnection.setAppTheme(newTheme)', () => {
const peerConnectionInstance = mockAndGetPeerConnectionInstance();
const setAppThemeCallback =
// @ts-ignore
ipcRenderer.on.mock.calls[6][1];
const testTheme = true;
setAppThemeCallback(undefined, testTheme);
expect(peerConnectionInstance.setAppTheme).toHaveBeenCalledWith(
testTheme
);
});
});
describe('when ipcRenderer.on("app-language-changed" callback occurred', () => {
it('should call peerConnection.testAppLang(newLang)', () => {
const peerConnectionInstance = mockAndGetPeerConnectionInstance();
const setAppLangCallback =
// @ts-ignore
ipcRenderer.on.mock.calls[7][1];
const testAppLang = 'eu';
setAppLangCallback(undefined, testAppLang);
expect(peerConnectionInstance.setAppLanguage).toHaveBeenCalledWith(
testAppLang
);
});
});
}); });
}); });
}); });

View File

@ -26,8 +26,6 @@ export function handleIpcRenderer() {
data.roomID, data.roomID,
data.sharingSessionID, data.sharingSessionID,
data.user, data.user,
data.appTheme, // TODO getAppTheme
data.appLanguage, // TODO getLanguage
roomIDService, roomIDService,
connectedDevicesService, connectedDevicesService,
sharingSessionService, sharingSessionService,
@ -59,12 +57,12 @@ export function handleIpcRenderer() {
peerConnection.sendUserAllowedToConnect(); peerConnection.sendUserAllowedToConnect();
}); });
ipcRenderer.on('app-color-theme-changed', (_, newTheme: boolean) => { ipcRenderer.on('app-color-theme-changed', () => {
peerConnection.setAppTheme(newTheme); peerConnection.notifyClientWithNewColorTheme();
}); });
ipcRenderer.on('app-language-changed', (_, newLang: string) => { ipcRenderer.on('app-language-changed', () => {
peerConnection.setAppLanguage(newLang); peerConnection.notifyClientWithNewLanguage();
}); });
}); });
} }

View File

@ -0,0 +1,7 @@
import settings from 'electron-settings';
export default function getAppLanguage(): string {
return settings.hasSync('appLanguage')
? (settings.getSync('appLanguage') as string)
: 'en';
}

7
app/utils/getAppTheme.ts Normal file
View File

@ -0,0 +1,7 @@
import settings from 'electron-settings';
export default function getAppTheme(): boolean {
return settings.hasSync('appIsDarkTheme')
? settings.getSync('appIsDarkTheme') === 'true'
: false;
}

View File

@ -1,7 +1,7 @@
{ {
"name": "deskreen", "name": "deskreen",
"productName": "Deskreen", "productName": "Deskreen",
"version": "1.0.5", "version": "1.0.6",
"description": "Deskreen turns any device into a secondary screen for your computer", "description": "Deskreen turns any device into a secondary screen for your computer",
"scripts": { "scripts": {
"build": "yarn build-client && yarn build-main && yarn build-renderer", "build": "yarn build-client && yarn build-main && yarn build-renderer",
@ -70,7 +70,7 @@
"build": { "build": {
"productName": "Deskreen", "productName": "Deskreen",
"appId": "com.pavlobu.Deskreen", "appId": "com.pavlobu.Deskreen",
"copyright": "Copyright © 2020-present Pavlo (Paul) Buidenkov", "copyright": "Copyright © 2020-present Pavlo Buidenkov (Paul)",
"files": [ "files": [
"dist/", "dist/",
"node_modules/", "node_modules/",
@ -141,7 +141,7 @@
"url": "https://github.com/pavlobu" "url": "https://github.com/pavlobu"
} }
], ],
"license": "AGPL-3.0 License", "license": "AGPL-3.0-or-later",
"bugs": { "bugs": {
"url": "https://github.com/pavlobu/deskreen/issues" "url": "https://github.com/pavlobu/deskreen/issues"
}, },
@ -308,9 +308,9 @@
"stylelint-config-prettier": "^8.0.2", "stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^20.0.0", "stylelint-config-standard": "^20.0.0",
"terser-webpack-plugin": "^3.0.7", "terser-webpack-plugin": "^3.0.7",
"testcafe": "^1.9.2", "testcafe": "^1.10.1",
"testcafe-browser-provider-electron": "^0.0.15", "testcafe-browser-provider-electron": "^0.0.16",
"testcafe-react-selectors": "^4.0.0", "testcafe-react-selectors": "^4.1.4",
"ts-jest": "^26.1.4", "ts-jest": "^26.1.4",
"typescript": "^3.9.7", "typescript": "^3.9.7",
"typings-for-css-modules-loader": "^1.7.0", "typings-for-css-modules-loader": "^1.7.0",

View File

@ -50,7 +50,7 @@ const headerWithTextSelectAppWindow = Selector('h3').withText(
const previewShareButton = Selector('.preview-share-thumb-container'); const previewShareButton = Selector('.preview-share-thumb-container');
const step3ConfirmButton = Selector('button').withText('Confirm'); const step3ConfirmButton = Selector('button').withText('Confirm');
const noINeedToShareOtherThingButton = Selector('button').withText( const noINeedToShareOtherThingButton = Selector('button').withText(
'No, I need to share other thing' 'No, I need to choose other'
); );
const step4ConnectNewDeviceButton = Selector('button').withText( const step4ConnectNewDeviceButton = Selector('button').withText(
'Connect New Device' 'Connect New Device'
@ -68,8 +68,8 @@ const yesDisconnectAllButton = Selector('button').withText(
); );
const settingsButtonOfTopPanel = Selector('span').withAttribute('icon', 'cog'); const settingsButtonOfTopPanel = Selector('span').withAttribute('icon', 'cog');
const openedSettingsOverlay = Selector('#settings-overlay-inner'); const openedSettingsOverlay = Selector('#settings-overlay-inner');
const darkColorAppSettingButton = Selector('button').withText('Dark'); const darkColorAppSettingButton = '#dark-theme-toggle-btn';
const lightColorAppSettingButton = Selector('button').withText('Light'); const lightColorAppSettingButton = '#light-theme-toggle-btn';
const darkUIClassName = Selector('.bp3-dark'); const darkUIClassName = Selector('.bp3-dark');
async function getConnecteddeviceIPFromAllowToConnectDeviceAlert() { async function getConnecteddeviceIPFromAllowToConnectDeviceAlert() {
@ -493,10 +493,10 @@ test(`when "Settings" Panel is opened,
await t.click(settingsButtonOfTopPanel()); await t.click(settingsButtonOfTopPanel());
// action and assertion 1 // action and assertion 1
await t.click(darkColorAppSettingButton()); await t.click(darkColorAppSettingButton);
await t.expect(darkUIClassName().exists).ok(); await t.expect(darkUIClassName().exists).ok();
// action and assertion 2 // action and assertion 2
await t.click(lightColorAppSettingButton()); await t.click(lightColorAppSettingButton);
await t.expect(darkUIClassName().exists).notOk(); await t.expect(darkUIClassName().exists).notOk();
}); });

View File

@ -13699,10 +13699,10 @@ test-exclude@^6.0.0:
glob "^7.1.4" glob "^7.1.4"
minimatch "^3.0.4" minimatch "^3.0.4"
testcafe-browser-provider-electron@^0.0.15: testcafe-browser-provider-electron@^0.0.16:
version "0.0.15" version "0.0.16"
resolved "https://registry.npmjs.org/testcafe-browser-provider-electron/-/testcafe-browser-provider-electron-0.0.15.tgz#4c0d084222349501cf2eb400ccac50029cb454ae" resolved "https://registry.npmjs.org/testcafe-browser-provider-electron/-/testcafe-browser-provider-electron-0.0.16.tgz#cb4255b775bdec226ec76699f408a4aba20a8146"
integrity sha512-nmsYcaf0HXv+8yDQxHR9b8kWkPwRPDVV5cwrZUCR2bh43pCozkcmgvWCFn9uD2twFo/oead61oBh9eMMxdTdZA== integrity sha512-3qBIXdlV2gN0I3pLYbEdVlhe6rgfGdihaB6hc/339ZYVtpXE/AOt4CW+EubBJLG6gkwJI+39rv8azzQ6NebgKg==
dependencies: dependencies:
babel-runtime "^6.25.0" babel-runtime "^6.25.0"
chrome-remote-interface "^0.27.0" chrome-remote-interface "^0.27.0"
@ -13788,7 +13788,7 @@ testcafe-legacy-api@4.0.0:
pinkie "^2.0.1" pinkie "^2.0.1"
strip-bom "^2.0.0" strip-bom "^2.0.0"
testcafe-react-selectors@^4.0.0: testcafe-react-selectors@^4.1.4:
version "4.1.4" version "4.1.4"
resolved "https://registry.npmjs.org/testcafe-react-selectors/-/testcafe-react-selectors-4.1.4.tgz#9aebba4eb102c410596e40957dccc81ea8ff59bf" resolved "https://registry.npmjs.org/testcafe-react-selectors/-/testcafe-react-selectors-4.1.4.tgz#9aebba4eb102c410596e40957dccc81ea8ff59bf"
integrity sha512-+YkgZcQiFrdkqGJEE5q/YrANF2QPn6bG9Q1wG11rp0yZA405lG51CB9WXdSJkB2ACcEoIuWIqX2V839hPJ51og== integrity sha512-+YkgZcQiFrdkqGJEE5q/YrANF2QPn6bG9Q1wG11rp0yZA405lG51CB9WXdSJkB2ACcEoIuWIqX2V839hPJ51og==
@ -13818,7 +13818,7 @@ testcafe-reporter-xunit@^2.1.0:
resolved "https://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz#e6d66c572ce15af266706af0fd610b2a841dd443" resolved "https://registry.npmjs.org/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz#e6d66c572ce15af266706af0fd610b2a841dd443"
integrity sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM= integrity sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM=
testcafe@^1.9.2: testcafe@^1.10.1:
version "1.10.1" version "1.10.1"
resolved "https://registry.npmjs.org/testcafe/-/testcafe-1.10.1.tgz#0dc33954eabbdfb6ea018b789eb21b5557b35582" resolved "https://registry.npmjs.org/testcafe/-/testcafe-1.10.1.tgz#0dc33954eabbdfb6ea018b789eb21b5557b35582"
integrity sha512-c1ErVj+QvQR7fqJs/XVa4S7Ctl5Hf5bxnkTaFVl4Qt2QlliL3EAXtL3WjCOx65Pd8BatxTWUCXJ5NVwAvq7jWg== integrity sha512-c1ErVj+QvQR7fqJs/XVa4S7Ctl5Hf5bxnkTaFVl4Qt2QlliL3EAXtL3WjCOx65Pd8BatxTWUCXJ5NVwAvq7jWg==