1
0
mirror of https://github.com/pavlobu/deskreen.git synced 2025-05-16 07:20:16 -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;
}
.class-allow-device-to-connect-alert > div > .bp3-button {
border-radius: 50px;
}
/* ALLOW CONNECTION ALERT BLINK ANIMATION START */
div.class-allow-device-to-connect-alert
> 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 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 select source to share from 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...": "Ждем когда пользователь выберет Весь экран или Окно приложения для отображения его здесь...",
"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 select source to share from 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...": "Чекаємо коли користувач вибере Весь екран або Вікно додатка для відображення його тут...",
"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 {
UNKNOWN_ERROR = 'An unknown error uccured.',
DENY_TO_CONNECT = 'You were not allowed to connect.',
DISCONNECTED = 'You were disconnected.',
NOT_ALLOWED = 'You were not allowed to connect.',
WEBRTC_ERROR = 'WebRTC error occurred.'
UNKNOWN_ERROR = 'An unknown error occurred',
DENY_TO_CONNECT = 'You were not allowed to connect',
DISCONNECTED = 'You were disconnected',
NOT_ALLOWED = 'You were not allowed to connect',
WEBRTC_ERROR = 'WebRTC error occurred'
}

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@ import {
Toaster,
Intent,
} from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import FullScreenEnter from '../../images/fullscreen_24px.svg';
import FullScreenExit from '../../images/fullscreen_exit-24px.svg';
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);
function PlayerControlPanel(props: PlayerControlPanelProps) {
const { t } = useTranslation();
const {
isPlaying,
onSwitchChangedCallback,
@ -92,9 +94,9 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
toaster?.show({
icon: 'clean',
intent: Intent.PRIMARY,
message: `Video is flipped horizontally`,
message: t('Video is flipped horizontally'),
});
}, [isVideoFlipped, toaster]);
}, [isVideoFlipped, toaster, t]);
return (
<>
@ -102,7 +104,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
<Row between="xs" middle="xs">
<Col xs={12} md={3}>
<Tooltip
content="Click to visit our website"
content={t('Click to visit our website')}
position={Position.BOTTOM}
>
<Button
@ -127,7 +129,9 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
</Button>
</Tooltip>
<Tooltip
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!"
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}
>
<Button
@ -150,7 +154,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
<div
style={{ transform: 'translateY(2px) translateX(-5px)' }}
>
<Text>Donate!</Text>
<Text>{t('Donate')}</Text>
</div>
</Col>
</Row>
@ -178,8 +182,8 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
icon: isPlaying ? 'pause' : 'play',
intent: Intent.PRIMARY,
message: isPlaying
? 'Video stream is paused.'
: 'Video stream is playing',
? t('Video stream is paused')
: t('Video stream is playing'),
});
}}
style={{
@ -197,7 +201,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
</Col>
<Col xs>
<Text className="bp3-text-large">
{isPlaying ? 'Pause' : 'Play'}
{isPlaying ? t('Pause') : t('Play')}
</Text>
</Col>
</Row>
@ -212,7 +216,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
<Popover
content={
<>
<H5>Video Settings:</H5>
<H5>{`${t('Video Settings')}:`}</H5>
<Divider />
<Row>
<Button
@ -222,7 +226,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
style={videoQualityButtonStyle}
onClick={toggleFlipVideo}
>
Flip
{t('Flip')}
</Button>
</Row>
<Divider />
@ -242,7 +246,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
toaster?.show({
icon: 'clean',
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}
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>
<Icon icon="cog" color="white" />
</Button>
@ -271,7 +275,7 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
}}
/>
<Tooltip
content="Enter Full Screen Mode"
content={t('Click to Enter Full Screen Mode')}
position={Position.BOTTOM}
>
<Button
@ -310,14 +314,14 @@ function PlayerControlPanel(props: PlayerControlPanelProps) {
toaster?.show({
icon: 'video',
intent: Intent.PRIMARY,
message: `Default video player has been turned ${
isDefaultPlayerTurnedOn ? 'OFF' : 'ON'
message: `${
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
label={`Default Video Player`}
label={t('Default Video Player')}
alignIndicator={Alignment.RIGHT}
checked={isDefaultPlayerTurnedOn}
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
className="row center-xs"
style={
@ -87,7 +96,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Type:
</div>
<span
className="bp3-popover-wrapper"
@ -116,7 +124,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device IP:
</div>
</div>
</span>
@ -125,19 +132,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Browser:
</div>
<div
className=""
>
Device OS:
</div>
</div>
<div
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>
@ -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
className="row center-xs"
style={
@ -268,7 +282,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Type:
</div>
<span
className="bp3-popover-wrapper"
@ -297,7 +310,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device IP:
</div>
</div>
</span>
@ -306,19 +318,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Browser:
</div>
<div
className=""
>
Device OS:
</div>
</div>
<div
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>
@ -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
className="row center-xs"
style={
@ -520,7 +539,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Type:
</div>
<span
className="bp3-popover-wrapper"
@ -549,7 +567,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device IP:
</div>
</div>
</span>
@ -558,19 +575,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Browser:
</div>
<div
className=""
>
Device OS:
</div>
</div>
<div
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>
@ -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
className="row center-xs"
style={
@ -754,7 +778,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Type:
</div>
<span
className="bp3-popover-wrapper"
@ -783,7 +806,6 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device IP:
</div>
</div>
</span>
@ -792,19 +814,17 @@ exports[`when getPromptContent is called should match exact snapshot on each ste
className=""
>
Device Browser:
</div>
<div
className=""
>
Device OS:
</div>
</div>
<div
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>

View File

@ -8,7 +8,7 @@ import {
} from '../../constants/styleConstants';
import MyDeviceInfoCard from '../../components/MyDeviceInfoCard';
import { TFunction } from 'i18next';
import { H3 } from '@blueprintjs/core';
import { H2, H3 } from '@blueprintjs/core';
import ConnectingIndicator from '../../components/ConnectingIndicator';
const Slide = require('react-reveal/Slide');
@ -23,7 +23,7 @@ interface ConnectionPropmptsProps {
isOpen: boolean;
}
function getPromptContent(step: number, t: TFunction) {
function getPromptContent(t: TFunction, step: number) {
switch (step) {
case 1:
return (
@ -34,7 +34,7 @@ function getPromptContent(step: number, t: TFunction) {
</H3>
);
case 2:
return <H3>Connected!</H3>;
return <H3>{t('Connected!')}</H3>;
case 3:
return (
<H3>
@ -44,7 +44,7 @@ function getPromptContent(step: number, t: TFunction) {
</H3>
);
default:
return <H3>Error occurred :(</H3>;
return <H3>{`${t('Error occurred')} :(`}</H3>;
}
}
@ -55,69 +55,69 @@ function ConnectionPropmpts(props: ConnectionPropmptsProps) {
connectionIconType,
isShownSpinnerIcon,
spinnerIconType,
isOpen
isOpen,
} = props;
const { t } = useTranslation();
const { isDarkTheme } = useContext(AppContext);
return (
<Slide
id="connection-prompts-slide"
bottom
when={isOpen}
duration={1000}
>
<div
style={{
position: 'absolute',
zIndex: 10,
top: 0,
left: 0,
width: '100%',
height: '100vh',
boxShadow: `0 0 0 5px ${isDarkTheme ? '#000' : '#A7B6C2'}`,
backgroundColor: isDarkTheme ? DARK_UI_BACKGROUND : LIGHT_UI_BACKGROUND,
}}
>
<Row
bottom="xs"
<Slide id="connection-prompts-slide" bottom when={isOpen} duration={1000}>
<div
style={{
height: '50vh',
position: 'absolute',
zIndex: 10,
top: 0,
left: 0,
width: '100%',
marginRight: '0px',
marginLeft: '0px',
height: '100vh',
boxShadow: `0 0 0 5px ${isDarkTheme ? '#000' : '#A7B6C2'}`,
backgroundColor: isDarkTheme
? DARK_UI_BACKGROUND
: LIGHT_UI_BACKGROUND,
}}
>
<Row center="xs" style={{ width: '100%', margin: '0 auto' }}>
<Col
xs={12}
style={{
marginBottom: '50px',
textAlign: 'center',
width: '100%',
}}
>
<div style={{ width: '100%' }}>
<Row center="xs" style={{ width: '100%', margin: '0 auto' }}>
<Col md={6} xl={4}>
<MyDeviceInfoCard deviceDetails={myDeviceDetails} />
</Col>
</Row>
<Row
bottom="xs"
style={{
height: '50vh',
width: '100%',
marginRight: '0px',
marginLeft: '0px',
}}
>
<Row center="xs" style={{ width: '100%', margin: '0 auto' }}>
<Col
xs={12}
style={{
marginBottom: '50px',
textAlign: 'center',
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' }}>
<Col md={6} xl={4}>
<MyDeviceInfoCard deviceDetails={myDeviceDetails} />
</Col>
</Row>
<div id="prompt-text" style={{ fontSize: '20px' }}>
{getPromptContent(promptStep, t)}
{getPromptContent(t, promptStep)}
</div>
</div>
</Col>
</div>
</Col>
</Row>
</Row>
</Row>
<ConnectingIndicator
currentStep={promptStep}
connectionIconType={connectionIconType}
isShownSelectingSharingIcon={isShownSpinnerIcon}
selectingSharingIconType={spinnerIconType}
/>
</div>
<ConnectingIndicator
currentStep={promptStep}
connectionIconType={connectionIconType}
isShownSelectingSharingIcon={isShownSpinnerIcon}
selectingSharingIconType={spinnerIconType}
/>
</div>
</Slide>
);
}

View File

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

View File

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

View File

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

View File

@ -2,6 +2,8 @@
import React from 'react';
import { Callout, Text, H4, Tooltip, Position } from '@blueprintjs/core';
import { Row, Col } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
import { TFunction } from 'i18next';
interface DeviceInfoCalloutProps {
deviceType: string | undefined;
@ -11,24 +13,24 @@ interface DeviceInfoCalloutProps {
deviceBrowser: string | undefined;
}
function getContentOfTooltip() {
function getContentOfTooltip(t: TFunction) {
return (
<>
<Text>
{`This should match with 'Device IP' displayed on the screen of device
that is trying to connect.`}
{t(
'This should match with Device IP displayed on the screen of device that is trying to connect'
)}
</Text>
<span style={{ fontWeight: 900 }}>
<Text>
{`If IPs don't match click 'Deny' or 'Disconnect' button immediately to
secure your computer!`}
</Text>
<Text>{t('If IP addresses dont match click Disconnect button')}</Text>
</span>
</>
);
}
export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) {
const { t } = useTranslation();
const {
deviceType,
deviceIP,
@ -40,15 +42,15 @@ export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) {
return (
<>
<H4 style={{ margin: '0 auto', textAlign: 'center' }}>
Partner Device Info:
{`${t('Partner Device Info')}:`}
</H4>
<Callout id="device-info-callout">
<Callout id="device-info-callout" style={{ borderRadius: '8px' }}>
<Row center="xs">
<Col xs={12}>
<Text>
Device Type: <span>{deviceType}</span>
{`${t('Device Type')}:`} <span>{deviceType}</span>
</Text>
<Tooltip content={getContentOfTooltip()} position={Position.TOP}>
<Tooltip content={getContentOfTooltip(t)} position={Position.TOP}>
<div
style={{
fontWeight: 900,
@ -59,19 +61,20 @@ export default function DeviceInfoCallout(props: DeviceInfoCalloutProps) {
}}
>
<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>
</div>
</Tooltip>
<Text>
Device Browser: <span>{deviceBrowser}</span>
{`${t('Device Browser')}:`} <span>{deviceBrowser}</span>
</Text>
<Text>
Device OS: <span>{deviceOS}</span>
{`${t('Device OS')}:`} <span>{deviceOS}</span>
</Text>
<div style={{ width: '200px', margin: '0 auto' }}>
<Text className="bp3-text-muted" ellipsize>
Session ID: <span>{sharingSessionID}</span>
{`${t('Session ID')}:`} <span>{sharingSessionID}</span>
</Text>
</div>
</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/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { ipcRenderer, remote, shell } from 'electron';
import React, { useContext, useCallback, useEffect, useState } from 'react';
import { ipcRenderer, shell } from 'electron';
import React, { useContext, useEffect, useState } from 'react';
import {
Button,
Overlay,
Classes,
H3,
@ -13,38 +12,28 @@ import {
Tabs,
Tab,
Icon,
HTMLSelect,
Text,
ControlGroup,
Checkbox,
} from '@blueprintjs/core';
import { useTranslation } from 'react-i18next';
import { Col, Row } from 'react-flexbox-grid';
import { createStyles, makeStyles } from '@material-ui/core/styles';
import i18n from 'i18next';
import SharingSessionService from '../../features/SharingSessionService';
import {
DARK_UI_BACKGROUND,
LIGHT_UI_BACKGROUND,
SettingsContext,
} from '../../containers/SettingsProvider';
import CloseOverlayButton from '../CloseOverlayButton';
import i18n_client, {
getLangFullNameToLangISOKeyMap,
getLangISOKeyToLangFullNameMap,
} from '../../configs/i18next.config.client';
import SettingRowLabelAndInput from './SettingRowLabelAndInput';
import isWithReactRevealAnimations from '../../utils/isWithReactRevealAnimations';
import config from '../../api/config';
import LanguageSelector from '../LanguageSelector';
import ToggleThemeBtnGroup from '../ToggleThemeBtnGroup';
const { port } = config;
const Fade = require('react-reveal/Fade');
const sharingSessionService = remote.getGlobal(
'sharingSessionService'
) as SharingSessionService;
interface SettingsOverlayProps {
isSettingsOpen: boolean;
handleClose: () => void;
@ -73,13 +62,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
const [latestVersion, setLatestVersion] = useState('');
const [currentVersion, setCurrentVersion] = useState('');
const {
isDarkTheme,
setIsDarkThemeHook,
setCurrentLanguageHook,
} = useContext(SettingsContext);
const [languagesList, setLanguagesList] = useState([] as string[]);
const { isDarkTheme } = useContext(SettingsContext);
useEffect(() => {
const getLatestVersion = async () => {
@ -98,96 +81,14 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
getCurrentVersion();
}, []);
useEffect(() => {
const tmp: string[] = [];
getLangFullNameToLangISOKeyMap().forEach((_, key) => {
tmp.push(key);
});
setLanguagesList(tmp);
setCurrentLanguageHook(i18n_client.language);
}, [setCurrentLanguageHook]);
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 = () => {
return (
<Checkbox
disabled
className={getClassesCallback().checkboxSettings}
label="Disabled"
label={t('Disabled')}
/>
);
};
@ -195,21 +96,21 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
const GeneralSettingsPanel: React.FC = () => (
<>
<Row middle="xs">
<H3 className="bp3-text-muted">General Settings</H3>
<H3 className="bp3-text-muted">{t('General Settings')}</H3>
</Row>
<SettingRowLabelAndInput
icon="style"
label="Colors"
input={getThemeChangingControlGroupInput()}
label={t('Color Theme')}
input={<ToggleThemeBtnGroup />}
/>
<SettingRowLabelAndInput
icon="translate"
label={t('Language')}
input={getLanguageChangingHTMLSelect()}
input={<LanguageSelector />}
/>
<SettingRowLabelAndInput
icon="automatic-updates"
label="Automatic Updates"
label={t('Automatic Updates')}
input={getAutomaticUpdatesCheckboxInput()}
/>
</>
@ -219,7 +120,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
<div>
<H3>
<Icon icon="shield" iconSize={20} />
Security
{t('Security Settings')}
</H3>
<H6 className={Classes.RUNNING_TEXT}>
{`HTML is great for declaring static documents, but it falters when we try
@ -231,12 +132,6 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
</div>
);
const BlockedIPsPanel: React.FC = () => (
<div>
<H3>Blocked IPs</H3>
</div>
);
const AboutPanel: React.FC = () => (
<Row center="xs" middle="xs" style={{ height: 'calc(100vh - 40%)' }}>
<div>
@ -248,14 +143,16 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
/>
</Col>
<Col xs={12}>
<H3>About Deskreen</H3>
</Col>
<Col xs={12}>
<Text>{`Version: ${currentVersion} (${currentVersion})`}</Text>
<H3>{t('About Deskreen')}</H3>
</Col>
<Col xs={12}>
<Text>
{`Copyright © ${new Date().getFullYear()} `}
{`${t('Version')}: ${currentVersion} (${currentVersion})`}
</Text>
</Col>
<Col xs={12}>
<Text>
{`${t('Copyright')} © ${new Date().getFullYear()} `}
<a
onClick={() => {
shell.openExternal('https://linkedin.com/in/pavlobu');
@ -268,16 +165,16 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
}
}
>
Pavlo (Paul) Buidenkov
Pavlo Buidenkov (Paul)
</a>
</Text>
</Col>
<Col xs={12}>
<Text>
{`Website: `}
{`${t('Website')}: `}
<a
onClick={() => {
shell.openExternal('https://www.deskreen.com');
shell.openExternal('https://deskreen.com');
}}
style={
isDarkTheme
@ -287,7 +184,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
}
}
>
https://www.deskreen.com
https://deskreen.com
</a>
</Text>
</Col>
@ -295,18 +192,6 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
</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 = () => {
return (
<Row middle="xs" className={getClassesCallback().tabNavigationRowButton}>
@ -314,7 +199,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
icon="shield"
className={getClassesCallback().iconInTablLeftButton}
/>
<Text className="bp3-text-large">Security</Text>
<Text className="bp3-text-large">{t('Security')}</Text>
</Row>
);
};
@ -326,7 +211,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
icon="wrench"
className={getClassesCallback().iconInTablLeftButton}
/>
<Text className="bp3-text-large">General</Text>
<Text className="bp3-text-large">{t('General')}</Text>
</Row>
);
};
@ -338,7 +223,7 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
icon="info-sign"
className={getClassesCallback().iconInTablLeftButton}
/>
<Text className="bp3-text-large">About</Text>
<Text className="bp3-text-large">{t('About')}</Text>
</Row>
);
};
@ -378,9 +263,14 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
e.preventDefault();
shell.openExternal('https://deskreen.com');
}}
style={{
width: 'calc(100% - 50px)',
}}
>
{/* 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>
) : (
<></>
@ -398,9 +288,6 @@ export default function SettingsOverlay(props: SettingsOverlayProps) {
<Tab id="ng" disabled title="" panel={<SecurityPanel />}>
{getTabNavSecurityButton()}
</Tab>
<Tab id="bb" disabled title="" panel={<BlockedIPsPanel />}>
{getTabNavBlockedIPsButton()}
</Tab>
<Tab id="cc" title="" panel={<AboutPanel />}>
{getTabNavAboutButton()}
</Tab>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { remote } from 'electron';
import { Text } from '@blueprintjs/core';
import { Row, Col } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
import SharingSourcePreviewCard from '../SharingSourcePreviewCard';
import SharingSessionService from '../../features/SharingSessionService';
import DeviceInfoCallout from '../DeviceInfoCallout';
@ -16,6 +17,7 @@ interface ConfirmStepProps {
}
export default function ConfirmStep(props: ConfirmStepProps) {
const { t } = useTranslation();
const { device } = props;
const [sharingSession, setSharingSession] = useState<
SharingSession | undefined
@ -34,7 +36,7 @@ export default function ConfirmStep(props: ConfirmStepProps) {
<Row style={{ marginBottom: '10px' }}>
<Col xs={12} style={{ textAlign: 'center' }}>
{/* 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>
</Row>
<Row middle="xs" center="xs">
@ -53,14 +55,6 @@ export default function ConfirmStep(props: ConfirmStepProps) {
/>
</Col>
</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>
);
}

View File

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

View File

@ -101,13 +101,15 @@ const ScanQRStep: React.FC = () => {
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>
</Text>
<Text className="bp3-text">{t('Scan the QR code')}</Text>
</div>
<div>
<Tooltip content="Click to make bigger" position={Position.LEFT}>
<Tooltip content={t('Click to make bigger')} position={Position.LEFT}>
<Button
id="magnify-qr-code-button"
className={classes.smallQRCode}
@ -131,12 +133,13 @@ const ScanQRStep: React.FC = () => {
</div>
<div style={{ marginBottom: '10px' }}>
<Text className="bp3-text-muted">
or type the following address manually in browser address bar on any
device:
{`${t(
'Or type the following address in browser address bar on any device'
)}:`}
</Text>
</div>
<Tooltip content="Click to copy" position={Position.LEFT}>
<Tooltip content={t('Click to copy')} position={Position.LEFT}>
<Button
intent="primary"
icon="duplicate"

View File

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

View File

@ -61,24 +61,6 @@ exports[`should match exact snapshot 1`] = `
<div
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
center="xs"
>
@ -168,9 +150,7 @@ exports[`should match exact snapshot 1`] = `
>
<div
className="bp3-running-text"
>
Entire Screen
</div>
/>
</Blueprint3.Text>
</span>
<Blueprint3.Icon
@ -233,9 +213,7 @@ exports[`should match exact snapshot 1`] = `
>
<div
className="bp3-running-text"
>
Application Window
</div>
/>
</Blueprint3.Text>
</span>
<Blueprint3.Icon
@ -267,12 +245,6 @@ exports[`should match exact snapshot 1`] = `
<Blueprint3.Icon
key="leftIcon"
/>
<span
className="bp3-button-text"
key="text"
>
OR
</span>
<Blueprint3.Icon
key="rightIcon"
/>

View File

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

View File

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

View File

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

View File

@ -90,9 +90,7 @@ exports[`should match exact snapshot 1`] = `
<Component>
<h5
className="bp3-heading"
>
Success!
</h5>
/>
</Component>
</div>
</Col>
@ -123,10 +121,7 @@ exports[`should match exact snapshot 1`] = `
>
<div
className=""
>
You should see now sharing session started on device you've connected
with.
</div>
/>
</Blueprint3.Text>
</div>
<div
@ -147,12 +142,7 @@ exports[`should match exact snapshot 1`] = `
>
<div
className=""
>
You can manage connected devices by clicking "Connected Devices"
button in top panel
</div>
/>
</Blueprint3.Text>
</div>
</div>
@ -207,12 +197,6 @@ exports[`should match exact snapshot 1`] = `
</svg>
</span>
</Blueprint3.Icon>
<span
className="bp3-button-text"
key="text"
>
Connect New Device
</span>
<Blueprint3.Icon
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 { createStyles, makeStyles } from '@material-ui/core/styles';
import { Col, Row } from 'react-flexbox-grid';
import { useTranslation } from 'react-i18next';
import SettingsOverlay from './SettingsOverlay/SettingsOverlay';
import ConnectedDevicesListDrawer from './ConnectedDevicesListDrawer';
import { SettingsContext } from '../containers/SettingsProvider';
@ -52,6 +53,7 @@ const useStylesWithTheme = (isDarkTheme: boolean) =>
);
export default function TopPanel(props: any) {
const { t } = useTranslation();
const { isDarkTheme } = useContext(SettingsContext);
const getClassesCallback = useCallback(() => {
@ -73,12 +75,14 @@ export default function TopPanel(props: any) {
setIsDrawerOpen(!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(() => {
return (
<Tooltip
content="If you like Deskreen, consider donating! Deskreen is free and opensource forever! You can help us to make Deskreen even better!"
position={Position.BOTTOM}
>
<Tooltip content={donateTooltipContent} position={Position.BOTTOM}>
<Button
style={{
marginRight: '10px',
@ -100,19 +104,19 @@ export default function TopPanel(props: any) {
</Col>
<Col xs>
<div style={{ transform: 'translateY(2px) translateX(-5px)' }}>
<Text>Donate!</Text>
<Text>{t('Donate')}</Text>
</div>
</Col>
</Row>
</Button>
</Tooltip>
);
}, []);
}, [donateTooltipContent, t]);
const renderConnectedDevicesListButton = useCallback(() => {
return (
<div className={getClassesCallback().topPanelControlButtonMargin}>
<Tooltip content="Connected Devices" position={Position.BOTTOM}>
<Tooltip content={t('Connected Devices')} position={Position.BOTTOM}>
<Button
id="top-panel-connected-devices-list-button"
intent="primary"
@ -128,12 +132,12 @@ export default function TopPanel(props: any) {
</Tooltip>
</div>
);
}, [getClassesCallback, handleToggleConnectedDevicesListDrawer]);
}, [getClassesCallback, handleToggleConnectedDevicesListDrawer, t]);
const renderHelpButton = useCallback(() => {
return (
<div className={getClassesCallback().topPanelControlButtonMargin}>
<Tooltip content="Tutorial" position={Position.BOTTOM}>
<Tooltip content={t('Tutorial')} position={Position.BOTTOM}>
<Button
id="top-panel-help-button"
intent="none"
@ -151,12 +155,12 @@ export default function TopPanel(props: any) {
</Tooltip>
</div>
);
}, [getClassesCallback]);
}, [getClassesCallback, t]);
const renderSettingsButton = useCallback(() => {
return (
<div className={getClassesCallback().topPanelControlButtonMargin}>
<Tooltip content="Settings" position={Position.BOTTOM}>
<Tooltip content={t('Settings')} position={Position.BOTTOM}>
<Button
id="top-panel-settings-button"
onClick={handleSettingsOpen}
@ -171,7 +175,7 @@ export default function TopPanel(props: any) {
</Tooltip>
</div>
);
}, [getClassesCallback, handleSettingsOpen]);
}, [getClassesCallback, handleSettingsOpen, t]);
const renderLogoWithAppName = useCallback(() => {
return (
@ -179,10 +183,7 @@ export default function TopPanel(props: any) {
id="logo-with-popover-visit-website"
className={getClassesCallback().logoWithAppName}
>
<Tooltip
content="Click to visit our website"
position={Position.BOTTOM}
>
<Tooltip content={deskreenButtonTooltip} position={Position.BOTTOM}>
<Button
minimal
onClick={() => {
@ -205,7 +206,7 @@ export default function TopPanel(props: any) {
</Tooltip>
</div>
);
}, [getClassesCallback]);
}, [deskreenButtonTooltip, getClassesCallback]);
return (
<>

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,10 @@ import settings from 'electron-settings';
import config from './app.lang.config';
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> => {
const res = new Map<string, string>();
// eslint-disable-next-line no-restricted-syntax
@ -32,6 +36,27 @@ export const getLangISOKeyToLangFullNameMap = (): Map<string, string> => {
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 i18nextOptions = {

View File

@ -6,10 +6,21 @@ import Stepper from '@material-ui/core/Stepper';
import Step from '@material-ui/core/Step';
import StepLabel from '@material-ui/core/StepLabel';
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 SuccessStep from '../components/StepsOfStepper/SuccessStep';
import IntermediateStep from '../components/StepsOfStepper/IntermediateStep';
import AllowConnectionForDeviceAlert from '../components/AllowConnectionForDeviceAlert';
@ -23,6 +34,9 @@ import SharingSessionService from '../features/SharingSessionService';
import ConnectedDevicesService from '../features/ConnectedDevicesService';
import SharingSessionStatusEnum from '../features/SharingSessionService/SharingSessionStatusEnum';
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);
@ -33,6 +47,8 @@ const connectedDevicesService = remote.getGlobal(
'connectedDevicesService'
) as ConnectedDevicesService;
const Fade = require('react-reveal/Fade');
const useStyles = makeStyles(() =>
createStyles({
stepContent: {
@ -51,21 +67,28 @@ const useStyles = makeStyles(() =>
})
);
function getSteps() {
return ['Connect', 'Select', 'Confirm'];
function getSteps(t: TFunction) {
return [t('Connect'), t('Select'), t('Confirm')];
}
// eslint-disable-next-line react/display-name
const DeskreenStepper = React.forwardRef((_props, ref) => {
const { t } = useTranslation();
const classes = useStyles();
const { isDarkTheme, currentLanguage } = useContext(SettingsContext);
const { isDarkTheme } = useContext(SettingsContext);
const { addToast } = useToasts();
const [isAlertOpen, setIsAlertOpen] = useState(false);
const [isUserAllowedConnection, setIsUserAllowedConnection] = useState(false);
const [isNoWiFiError, setisNoWiFiError] = useState(false);
const [isSelectLanguageDialogOpen, setIsSelectLanguageDialogOpen] = useState(
false
);
const [isDisplayHelloWord, setIsDisplayHelloWord] = useState(true);
const [helloWord, setHelloWord] = useState('Hello');
const [
pendingConnectionDevice,
@ -109,9 +132,29 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
}, []);
useEffect(() => {
sharingSessionService.setAppLanguage(currentLanguage);
sharingSessionService.setAppTheme(isDarkTheme);
}, [currentLanguage, isDarkTheme]);
const isFirstTimeStart = !settings.hasSync('isNotFirstTimeAppStart');
setIsSelectLanguageDialogOpen(isFirstTimeStart);
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 [isEntireScreenSelected, setIsEntireScreenSelected] = useState(false);
@ -119,7 +162,7 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
isApplicationWindowSelected,
setIsApplicationWindowSelected,
] = useState(false);
const steps = getSteps();
const steps = getSteps(t);
const handleNext = useCallback(() => {
if (activeStep === steps.length - 1) {
@ -238,7 +281,9 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
addToast(
<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>,
{
appearance: 'info',
@ -247,7 +292,7 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
isdarktheme: `${isDarkTheme}`,
}
);
}, [addToast, handleResetWithSharingSessionRestart, isDarkTheme]);
}, [addToast, handleResetWithSharingSessionRestart, isDarkTheme, t]);
const renderIntermediateOrSuccessStepContent = useCallback(() => {
return activeStep === steps.length ? (
@ -365,6 +410,54 @@ const DeskreenStepper = React.forwardRef((_props, ref) => {
</div>
</Grid>
</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 */
import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID,
TEST_SHARING_SESSION_ID,
TEST_USER,
@ -38,8 +36,6 @@ describe('createDesktopCapturerStream callback', () => {
TEST_ROOM_ID,
TEST_SHARING_SESSION_ID,
TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
{} as RoomIDService,
{} as ConnectedDevicesService,
{} as SharingSessionService,

View File

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

View File

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

View File

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

View File

@ -1,3 +1,4 @@
import settings from 'electron-settings';
import uuid from 'uuid';
import { process as processMessage } from '../../utils/message';
@ -42,13 +43,21 @@ export default async function handleRecieveEncryptedMessage(
if (message.type === 'GET_APP_THEME') {
peerConnection.sendEncryptedMessage({
type: 'APP_THEME',
payload: { value: peerConnection.appColorTheme },
payload: {
value: settings.hasSync('appIsDarkTheme')
? settings.getSync('appIsDarkTheme') === 'true'
: false,
},
});
}
if (message.type === 'GET_APP_LANGUAGE') {
peerConnection.sendEncryptedMessage({
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 {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID,
TEST_SHARING_SESSION_ID,
TEST_USER,
@ -38,8 +36,6 @@ describe('handleSelfDestroy callback', () => {
TEST_ROOM_ID,
TEST_SHARING_SESSION_ID,
TEST_USER,
TEST_APP_THEME,
TEST_APP_LANGUAGE,
({
unmarkRoomIDAsTaken: jest.fn(),
} as unknown) as RoomIDService,

View File

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

View File

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

View File

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

View File

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

View File

@ -6,8 +6,6 @@ import ConnectedDevicesService from '../ConnectedDevicesService';
import SharingSessionService from '../SharingSessionService';
import DesktopCapturerSourcesService from '../DesktopCapturerSourcesService';
import {
TEST_APP_LANGUAGE,
TEST_APP_THEME,
TEST_ROOM_ID,
TEST_SHARING_SESSION_ID,
TEST_USER,
@ -17,6 +15,8 @@ import handleSelfDestroy from './handleSelfDestroy';
import handleRecieveEncryptedMessage from './handleRecieveEncryptedMessage';
import handleCreatePeer from './handleCreatePeer';
import { prepare as prepareMessage } from '../../utils/message';
import getAppLanguage from '../../utils/getAppLanguage';
import getAppTheme from '../../utils/getAppTheme';
jest.useFakeTimers();
@ -60,8 +60,6 @@ describe('PeerConnection index.ts tests', () => {
TEST_ROOM_ID,
TEST_SHARING_SESSION_ID,
TEST_USER,
TEST_APP_THEME, // TODO getAppTheme
TEST_APP_LANGUAGE, // TODO getLanguage
{} as RoomIDService,
{} as ConnectedDevicesService,
{} as SharingSessionService,
@ -82,32 +80,6 @@ describe('PeerConnection index.ts tests', () => {
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', () => {
it('should call sendEncryptedMessage with proper payload', () => {
peerConnection.sendEncryptedMessage = jest.fn();
@ -116,7 +88,7 @@ describe('PeerConnection index.ts tests', () => {
expect(peerConnection.sendEncryptedMessage).toBeCalledWith({
type: 'APP_LANGUAGE',
payload: { value: peerConnection.appLanguage },
payload: { value: getAppLanguage() },
});
});
});
@ -129,7 +101,7 @@ describe('PeerConnection index.ts tests', () => {
expect(peerConnection.sendEncryptedMessage).toBeCalledWith({
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 setDisplaySizeFromLocalStream from './handleSetDisplaySizeFromLocalStream';
import DesktopCapturerSourceType from '../DesktopCapturerSourcesService/DesktopCapturerSourceType';
import getAppLanguage from '../../utils/getAppLanguage';
import getAppTheme from '../../utils/getAppTheme';
type DisplaySize = { width: number; height: number };
@ -41,15 +43,11 @@ export default class PeerConnection {
onDeviceConnectedCallback: (device: Device) => void;
displayID: string;
sourceDisplaySize: DisplaySize | undefined;
appLanguage: string;
appColorTheme: boolean;
constructor(
roomID: string,
sharingSessionID: string,
user: LocalPeerUser,
appColorTheme: boolean,
appLanguage: string,
roomIDService: RoomIDService,
connectedDevicesService: ConnectedDevicesService,
sharingSessionsService: SharingSessionService,
@ -71,8 +69,6 @@ export default class PeerConnection {
this.localStream = null;
this.displayID = '';
this.sourceDisplaySize = undefined;
this.appLanguage = appLanguage;
this.appColorTheme = appColorTheme;
this.desktopCapturerSourcesService = desktopCapturerSourcesService;
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() {
this.sendEncryptedMessage({
type: 'APP_LANGUAGE',
payload: { value: this.appLanguage },
payload: {
value: getAppLanguage(),
},
});
}
notifyClientWithNewColorTheme() {
this.sendEncryptedMessage({
type: 'APP_THEME',
payload: { value: this.appColorTheme },
payload: { value: getAppTheme() },
});
}

View File

@ -6,8 +6,6 @@ import SharingType from './SharingTypeEnum';
jest.useFakeTimers();
const testAppLang = 'ua';
const testAppTheme = true;
const testUser = {
username: '',
privateKey: '',
@ -19,24 +17,18 @@ describe('SharingSession unit tests', () => {
beforeEach(() => {
process.env.RUN_MODE = 'test-jest';
sharingSession = new SharingSession(
'1234',
testUser,
{
// @ts-ignore: fine here
createPeerConnectionHelperRenderer: () => {
return {
webContents: {
on: jest.fn(),
send: jest.fn(),
},
close: jest.fn(),
};
},
sharingSession = new SharingSession('1234', testUser, {
// @ts-ignore: fine here
createPeerConnectionHelperRenderer: () => {
return {
webContents: {
on: jest.fn(),
send: jest.fn(),
},
close: jest.fn(),
};
},
testAppLang,
testAppTheme
);
});
});
afterEach(() => {
@ -99,8 +91,6 @@ describe('SharingSession unit tests', () => {
roomID: sharingSession.roomID,
sharingSessionID: sharingSession.id,
user: testUser,
appTheme: testAppTheme,
appLanguage: testAppLang,
});
});
});
@ -258,25 +248,21 @@ describe('SharingSession unit tests', () => {
describe('when appLanguageChanged() is called', () => {
it('should call .webContents.send with proper event name', () => {
const testLang = 'ua';
sharingSession.appLanguageChanged(testLang);
sharingSession.appLanguageChanged();
expect(
sharingSession.peerConnectionHelperRenderer?.webContents.send
).toBeCalledWith('app-language-changed', testLang);
).toBeCalledWith('app-language-changed');
});
});
describe('when appThemeChanged() is called', () => {
it('should call .webContents.send with proper event name', () => {
const testTheme = true;
sharingSession.appThemeChanged(testTheme);
sharingSession.appThemeChanged();
expect(
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 PeerConnectionHelperRendererService from '../PeerConnectionHelperRendererService';
// type OnDeviceConnectedCallbackType = undefined | (device: Device) => void;
export default class SharingSession {
id: string;
deviceID: string;
@ -24,9 +22,7 @@ export default class SharingSession {
constructor(
_roomID: string,
user: LocalPeerUser,
peerConnectionHelperRendererService: PeerConnectionHelperRendererService,
appLanguage: string,
isDarkTheme: boolean
peerConnectionHelperRendererService: PeerConnectionHelperRendererService
) {
this.id = uuid.v4();
this.deviceID = '';
@ -51,8 +47,6 @@ export default class SharingSession {
roomID: this.roomID,
sharingSessionID: this.id,
user,
appTheme: isDarkTheme,
appLanguage,
}
);
});
@ -111,17 +105,13 @@ export default class SharingSession {
);
}
appLanguageChanged(newLang: string) {
this.peerConnectionHelperRenderer?.webContents.send(
'app-language-changed',
newLang
);
appLanguageChanged() {
this.peerConnectionHelperRenderer?.webContents.send('app-language-changed');
}
appThemeChanged(isDarkTheme: boolean) {
appThemeChanged() {
this.peerConnectionHelperRenderer?.webContents.send(
'app-color-theme-changed',
isDarkTheme
'app-color-theme-changed'
);
}

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', () => {
it('should call waitWhileUserIsNotCreated', async () => {
sharingSessionService.waitWhileUserIsNotCreated = jest

View File

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

View File

@ -1,8 +1,73 @@
{
"Language": "Language 🇬🇧 / 🇺🇸",
"Signaling server is running on port": "Signaling server is running on port ⚓",
"Hello": "Hello",
"Continue": "Continue",
"Language": "Language",
"ru": "Русский",
"en": "English",
"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": "Язык 🇷🇺",
"Signaling server is running on port": "Сигнальный сервер работает на порте ⚓",
"Hello": "Привет",
"Continue": "Продолжить",
"Language": "Язык",
"ru": "Русский",
"en": "English",
"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": "Мова 🇺🇦",
"Signaling server is running on port": "Сигнальный сервер працює на порту ⚓",
"Hello": "Привіт",
"Continue": "Продовжити",
"Language": "Мова",
"ru": "Русский",
"en": "English",
"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 notification = {
title: 'Deskreen Update is Available!',
body: `Your current version is ${this.appVersion} Click to download new ${this.latestVersion} updated version.`,
title: i18n.t('Deskreen Update is Available!'),
body: `${i18n.t('Your current version is')} ${
this.appVersion
} | ${i18n.t('Click to download new updated version')} ${
this.latestVersion
}`,
};
const notificationInstance = new Notification(notification);
notificationInstance.show();

2
app/package-lock.json generated
View File

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

View File

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

View File

@ -252,40 +252,6 @@ describe('peerConnectionHelperRendererWindowIndex tests', () => {
).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.sharingSessionID,
data.user,
data.appTheme, // TODO getAppTheme
data.appLanguage, // TODO getLanguage
roomIDService,
connectedDevicesService,
sharingSessionService,
@ -59,12 +57,12 @@ export function handleIpcRenderer() {
peerConnection.sendUserAllowedToConnect();
});
ipcRenderer.on('app-color-theme-changed', (_, newTheme: boolean) => {
peerConnection.setAppTheme(newTheme);
ipcRenderer.on('app-color-theme-changed', () => {
peerConnection.notifyClientWithNewColorTheme();
});
ipcRenderer.on('app-language-changed', (_, newLang: string) => {
peerConnection.setAppLanguage(newLang);
ipcRenderer.on('app-language-changed', () => {
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",
"productName": "Deskreen",
"version": "1.0.5",
"version": "1.0.6",
"description": "Deskreen turns any device into a secondary screen for your computer",
"scripts": {
"build": "yarn build-client && yarn build-main && yarn build-renderer",
@ -70,7 +70,7 @@
"build": {
"productName": "Deskreen",
"appId": "com.pavlobu.Deskreen",
"copyright": "Copyright © 2020-present Pavlo (Paul) Buidenkov",
"copyright": "Copyright © 2020-present Pavlo Buidenkov (Paul)",
"files": [
"dist/",
"node_modules/",
@ -141,7 +141,7 @@
"url": "https://github.com/pavlobu"
}
],
"license": "AGPL-3.0 License",
"license": "AGPL-3.0-or-later",
"bugs": {
"url": "https://github.com/pavlobu/deskreen/issues"
},
@ -308,9 +308,9 @@
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^20.0.0",
"terser-webpack-plugin": "^3.0.7",
"testcafe": "^1.9.2",
"testcafe-browser-provider-electron": "^0.0.15",
"testcafe-react-selectors": "^4.0.0",
"testcafe": "^1.10.1",
"testcafe-browser-provider-electron": "^0.0.16",
"testcafe-react-selectors": "^4.1.4",
"ts-jest": "^26.1.4",
"typescript": "^3.9.7",
"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 step3ConfirmButton = Selector('button').withText('Confirm');
const noINeedToShareOtherThingButton = Selector('button').withText(
'No, I need to share other thing'
'No, I need to choose other'
);
const step4ConnectNewDeviceButton = Selector('button').withText(
'Connect New Device'
@ -68,8 +68,8 @@ const yesDisconnectAllButton = Selector('button').withText(
);
const settingsButtonOfTopPanel = Selector('span').withAttribute('icon', 'cog');
const openedSettingsOverlay = Selector('#settings-overlay-inner');
const darkColorAppSettingButton = Selector('button').withText('Dark');
const lightColorAppSettingButton = Selector('button').withText('Light');
const darkColorAppSettingButton = '#dark-theme-toggle-btn';
const lightColorAppSettingButton = '#light-theme-toggle-btn';
const darkUIClassName = Selector('.bp3-dark');
async function getConnecteddeviceIPFromAllowToConnectDeviceAlert() {
@ -493,10 +493,10 @@ test(`when "Settings" Panel is opened,
await t.click(settingsButtonOfTopPanel());
// action and assertion 1
await t.click(darkColorAppSettingButton());
await t.click(darkColorAppSettingButton);
await t.expect(darkUIClassName().exists).ok();
// action and assertion 2
await t.click(lightColorAppSettingButton());
await t.click(lightColorAppSettingButton);
await t.expect(darkUIClassName().exists).notOk();
});

View File

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