2021-08-05 10:41:45 +02:00
// @flow
import { ALERT } from 'constants/icons' ;
2021-08-08 10:13:35 +02:00
import { SETTINGS _GRP } from 'constants/settings' ;
2021-08-05 10:41:45 +02:00
import React from 'react' ;
import Button from 'component/button' ;
import Card from 'component/common/card' ;
2021-08-06 10:25:37 +02:00
import { FormField } from 'component/common/form' ;
2021-08-07 15:35:11 +02:00
import FileSelector from 'component/common/file-selector' ;
import I18nMessage from 'component/i18nMessage' ;
2021-08-05 10:41:45 +02:00
import SettingAutoLaunch from 'component/settingAutoLaunch' ;
import SettingClosingBehavior from 'component/settingClosingBehavior' ;
2021-08-07 15:12:07 +02:00
import SettingCommentsServer from 'component/settingCommentsServer' ;
2021-10-22 04:41:45 +02:00
import SettingShareUrl from 'component/settingShareUrl' ;
2021-08-05 10:41:45 +02:00
import SettingsRow from 'component/settingsRow' ;
2021-08-07 15:12:07 +02:00
import SettingWalletServer from 'component/settingWalletServer' ;
2021-08-07 15:35:11 +02:00
import Spinner from 'component/spinner' ;
2021-08-08 04:26:40 +02:00
import { getPasswordFromCookie } from 'util/saved-passwords' ;
2021-10-28 01:21:16 +02:00
import * as DAEMON _SETTINGS from 'constants/daemon_settings' ;
import { formatBytes } from 'util/format-bytes' ;
2021-08-05 10:41:45 +02:00
// @if TARGET='app'
const IS _MAC = process . platform === 'darwin' ;
// @endif
2021-10-28 01:21:16 +02:00
const BYTES _PER _MB = 1048576 ;
2021-08-05 10:41:45 +02:00
2021-08-06 10:25:37 +02:00
type Price = {
currency : string ,
amount : number ,
} ;
type SetDaemonSettingArg = boolean | string | number | Price ;
type DaemonSettings = {
download _dir : string ,
share _usage _data : boolean ,
max _key _fee ? : Price ,
max _connections _per _download ? : number ,
save _files : boolean ,
save _blobs : boolean ,
ffmpeg _path : string ,
} ;
2021-10-28 01:21:16 +02:00
type DaemonStatus = {
disk _space : {
running : boolean ,
space _used : string ,
} ,
} ;
2021-08-05 10:41:45 +02:00
type Props = {
2021-08-07 15:35:11 +02:00
// --- select ---
2021-08-06 10:25:37 +02:00
daemonSettings : DaemonSettings ,
2021-08-07 15:35:11 +02:00
ffmpegStatus : { available : boolean , which : string } ,
findingFFmpeg : boolean ,
2021-08-08 04:26:40 +02:00
walletEncrypted : boolean ,
isAuthenticated : boolean ,
2021-08-08 05:13:04 +02:00
allowAnalytics : boolean ,
2021-08-07 15:35:11 +02:00
// --- perform ---
2021-08-06 10:25:37 +02:00
setDaemonSetting : ( string , ? SetDaemonSettingArg ) => void ,
2021-08-07 15:35:11 +02:00
clearDaemonSetting : ( string ) => void ,
2021-08-05 10:41:45 +02:00
clearCache : ( ) => Promise < any > ,
2021-08-07 15:35:11 +02:00
findFFmpeg : ( ) => void ,
2021-08-08 04:26:40 +02:00
encryptWallet : ( ) => void ,
decryptWallet : ( ) => void ,
updateWalletStatus : ( ) => void ,
confirmForgetPassword : ( { } ) => void ,
2021-08-08 05:13:04 +02:00
toggle3PAnalytics : ( boolean ) => void ,
2021-10-28 01:21:16 +02:00
daemonStatus : DaemonStatus ,
2021-08-05 10:41:45 +02:00
} ;
export default function SettingSystem ( props : Props ) {
2021-08-07 15:35:11 +02:00
const {
daemonSettings ,
ffmpegStatus ,
findingFFmpeg ,
2021-08-08 04:26:40 +02:00
walletEncrypted ,
isAuthenticated ,
2021-08-08 05:13:04 +02:00
allowAnalytics ,
2021-08-07 15:35:11 +02:00
setDaemonSetting ,
clearDaemonSetting ,
clearCache ,
findFFmpeg ,
2021-08-08 04:26:40 +02:00
encryptWallet ,
decryptWallet ,
updateWalletStatus ,
confirmForgetPassword ,
2021-08-08 05:13:04 +02:00
toggle3PAnalytics ,
2021-10-28 01:21:16 +02:00
daemonStatus ,
2021-08-07 15:35:11 +02:00
} = props ;
2021-08-08 04:26:40 +02:00
2021-08-05 10:41:45 +02:00
const [ clearingCache , setClearingCache ] = React . useState ( false ) ;
2021-08-08 04:26:40 +02:00
const [ storedPassword , setStoredPassword ] = React . useState ( false ) ;
2021-10-28 01:21:16 +02:00
const { disk _space } = daemonStatus ;
const spaceUsed = Number ( disk _space . space _used ) ;
const blobLimitSetting = daemonSettings [ DAEMON _SETTINGS . BLOB _STORAGE _LIMIT _MB ] ;
const [ blobSpaceLimitGB , setBlobSpaceLimit ] = React . useState ( blobLimitSetting ? blobLimitSetting / 1024 : 0 ) ;
// const debouncedBlobSpaceLimitGB = useDebounce(blobSpaceLimitGB || 0, 500);
const [ limitSpace , setLimitSpace ] = React . useState ( Boolean ( blobLimitSetting ) ) ;
console . log ( 'spaceUsed' , spaceUsed , 'blobLimit' , blobLimitSetting ) ;
2021-08-07 15:35:11 +02:00
// @if TARGET='app'
const { available : ffmpegAvailable , which : ffmpegPath } = ffmpegStatus ;
// @endif
2021-08-08 04:26:40 +02:00
function onChangeEncryptWallet ( ) {
if ( walletEncrypted ) {
decryptWallet ( ) ;
} else {
encryptWallet ( ) ;
}
}
function onConfirmForgetPassword ( ) {
confirmForgetPassword ( { callback : ( ) => setStoredPassword ( false ) } ) ;
}
2021-10-28 01:21:16 +02:00
function updateBlobLimitField ( gb ) {
if ( gb === 0 ) {
setBlobSpaceLimit ( 0 ) ;
} else if ( ! gb || ! isNaN ( gb ) ) {
setBlobSpaceLimit ( gb ) ;
}
}
function handleLimitSpace ( value ) {
setLimitSpace ( value ) ;
if ( ! value ) {
setDaemonSetting ( DAEMON _SETTINGS . BLOB _STORAGE _LIMIT _MB , String ( 0 ) ) ;
} else {
const spaceLimitMB = blobSpaceLimitGB * 1024 ;
setDaemonSetting ( DAEMON _SETTINGS . BLOB _STORAGE _LIMIT _MB , String ( spaceLimitMB ) ) ;
}
}
function handleSetBlobSpaceLimit ( ) {
const spaceLimitMB = blobSpaceLimitGB * 1024 ;
if ( ! isNaN ( spaceLimitMB ) && blobLimitSetting !== spaceLimitMB * 1024 ) {
setDaemonSetting ( DAEMON _SETTINGS . BLOB _STORAGE _LIMIT _MB , String ( spaceLimitMB ) ) ;
}
}
2021-08-08 04:26:40 +02:00
// Update ffmpeg variables
2021-08-07 15:35:11 +02:00
React . useEffect ( ( ) => {
// @if TARGET='app'
const { available } = ffmpegStatus ;
const { ffmpeg _path : ffmpegPath } = daemonSettings ;
if ( ! available ) {
if ( ffmpegPath ) {
clearDaemonSetting ( 'ffmpeg_path' ) ;
}
findFFmpeg ( ) ;
}
// @endif
} , [ ] ) ; // eslint-disable-line react-hooks/exhaustive-deps
2021-08-08 04:26:40 +02:00
// Update storedPassword state
React . useEffect ( ( ) => {
if ( isAuthenticated || ! IS _WEB ) {
updateWalletStatus ( ) ;
getPasswordFromCookie ( ) . then ( ( p ) => {
if ( typeof p === 'string' ) {
setStoredPassword ( true ) ;
}
} ) ;
}
} , [ ] ) ; // eslint-disable-line react-hooks/exhaustive-deps
2021-08-05 10:41:45 +02:00
return (
2021-08-09 04:22:16 +02:00
< >
< div className = "card__title-section" >
< h2 className = "card__title" > { _ _ ( 'System' ) } < / h2 >
< / div >
< Card
id = { SETTINGS _GRP . SYSTEM }
isBodyList
body = {
< >
{ /* @if TARGET='app' */ }
< SettingsRow title = { _ _ ( 'Download directory' ) } subtitle = { _ _ ( 'LBRY downloads will be saved here.' ) } >
< FileSelector
type = "openDirectory"
currentPath = { daemonSettings . download _dir }
onFileChosen = { ( newDirectory : WebFile ) => {
setDaemonSetting ( 'download_dir' , newDirectory . path ) ;
} }
/ >
< / SettingsRow >
{ /* @endif */ }
2021-08-08 05:13:04 +02:00
2021-08-09 04:22:16 +02:00
{ /* @if TARGET='app' */ }
2021-08-06 10:25:37 +02:00
< SettingsRow
2021-08-09 04:22:16 +02:00
title = { _ _ ( 'Save all viewed content to your downloads directory' ) }
2021-08-06 10:25:37 +02:00
subtitle = { _ _ (
2021-08-09 04:22:16 +02:00
'Paid content and some file types are saved by default. Changing this setting will not affect previously downloaded content.'
2021-08-06 10:25:37 +02:00
) }
>
2021-08-09 04:22:16 +02:00
< FormField
type = "checkbox"
name = "save_files"
onChange = { ( ) => setDaemonSetting ( 'save_files' , ! daemonSettings . save _files ) }
checked = { daemonSettings . save _files }
/ >
< / SettingsRow >
< SettingsRow
2021-10-28 01:21:16 +02:00
title = { _ _ ( 'Data Hosting' ) }
multirow
2021-08-09 04:22:16 +02:00
subtitle = {
< React.Fragment >
{ _ _ ( "If disabled, LBRY will be very sad and you won't be helping improve the network." ) } { ' ' }
2021-10-28 01:21:16 +02:00
{ _ _ ( 'If you set a limit, playing videos may exceed your limit until cleanup runs every 30 minutes.' ) } { ' ' }
2021-08-09 04:22:16 +02:00
< Button button = "link" label = { _ _ ( 'Learn more' ) } href = "https://lbry.com/faq/host-content" / > .
2021-10-28 01:21:16 +02:00
< p className = { 'help' } >
{ ` Using ${ formatBytes ( spaceUsed * BYTES _PER _MB ) } of ${
daemonSettings [ DAEMON _SETTINGS . BLOB _STORAGE _LIMIT _MB ]
? formatBytes ( daemonSettings [ DAEMON _SETTINGS . BLOB _STORAGE _LIMIT _MB ] * BYTES _PER _MB )
: 'Unlimited'
} ` }
< / p >
2021-08-09 04:22:16 +02:00
< / React.Fragment >
}
>
2021-10-28 01:21:16 +02:00
< fieldset - section >
< FormField
type = "checkbox"
name = "save_blobs"
onChange = { ( ) => setDaemonSetting ( 'save_blobs' , ! daemonSettings . save _blobs ) }
checked = { daemonSettings . save _blobs }
label = { _ _ ( 'Enable Data Hosting' ) }
/ >
< / f i e l d s e t - s e c t i o n >
< fieldset - section >
< FormField
type = "checkbox"
name = "limit_space_used"
onChange = { ( ) => handleLimitSpace ( ! limitSpace ) }
checked = { limitSpace }
label = { _ _ ( 'Limit Space Used' ) }
/ >
< / f i e l d s e t - s e c t i o n >
{ limitSpace && (
< FormField
2021-10-28 01:28:28 +02:00
name = "blob_limit_gb"
2021-10-28 01:21:16 +02:00
type = "text"
2021-10-28 01:28:28 +02:00
label = { _ _ ( ` Limit (GB) ` ) }
2021-10-28 01:21:16 +02:00
helper = { _ _ (
'Data over the limit will be deleted within 30 minutes. This will make the Yrbl cry a little bit.'
) }
disabled = { ! daemonSettings . save _blobs }
onChange = { ( e ) => updateBlobLimitField ( e . target . value ) }
value = { blobSpaceLimitGB }
inputButton = {
< Button
disabled = { isNaN ( blobSpaceLimitGB ) }
button = "primary"
label = { _ _ ( 'Apply' ) }
onClick = { handleSetBlobSpaceLimit }
/ >
}
/ >
) }
2021-08-05 10:41:45 +02:00
< / SettingsRow >
2021-08-09 04:22:16 +02:00
{ /* @endif */ }
2021-08-05 10:41:45 +02:00
2021-08-09 04:22:16 +02:00
{ /* @if TARGET='app' */ }
< SettingsRow
title = { _ _ ( 'Share usage and diagnostic data' ) }
subtitle = {
< React.Fragment >
{ _ _ (
2021-11-28 21:05:10 +01:00
` This is information like error logging, performance tracking, and usage statistics. It includes your IP address and basic system details, but no other identifying information (unless you connect to a cloud service) `
2021-08-09 04:22:16 +02:00
) } { ' ' }
2021-10-11 03:43:29 +02:00
< Button button = "link" label = { _ _ ( 'Learn more' ) } href = "https://lbry.com/privacypolicy" / >
2021-08-09 04:22:16 +02:00
< / React.Fragment >
}
2021-08-22 09:58:56 +02:00
multirow
2021-08-09 04:22:16 +02:00
>
< FormField
type = "checkbox"
name = "share_internal"
onChange = { ( ) => setDaemonSetting ( 'share_usage_data' , ! daemonSettings . share _usage _data ) }
checked = { daemonSettings . share _usage _data }
label = { < React.Fragment > { _ _ ( 'Allow the app to share data to LBRY.inc' ) } < / React.Fragment > }
helper = {
isAuthenticated
? _ _ ( 'Internal sharing is required while signed in.' )
: _ _ ( 'Internal sharing is required to participate in rewards programs.' )
}
disabled = { isAuthenticated && daemonSettings . share _usage _data }
/ >
< FormField
type = "checkbox"
name = "share_third_party"
onChange = { ( e ) => toggle3PAnalytics ( e . target . checked ) }
checked = { allowAnalytics }
label = { _ _ ( 'Allow the app to access third party analytics platforms' ) }
helper = { _ _ ( 'We use detailed analytics to improve all aspects of the LBRY experience.' ) }
/ >
< / SettingsRow >
{ /* @endif */ }
2021-08-05 10:41:45 +02:00
2021-08-09 04:22:16 +02:00
{ /* @if TARGET='app' */ }
{ /* Auto launch in a hidden state doesn't work on mac https://github.com/Teamwork/node-auto-launch/issues/81 */ }
{ ! IS _MAC && (
< SettingsRow
title = { _ _ ( 'Start minimized' ) }
subtitle = { _ _ (
'Improve view speed and help the LBRY network by allowing the app to cuddle up in your system tray.'
) }
>
< SettingAutoLaunch noLabels / >
< / SettingsRow >
) }
{ /* @endif */ }
2021-08-07 15:35:11 +02:00
2021-08-09 04:22:16 +02:00
{ /* @if TARGET='app' */ }
< SettingsRow title = { _ _ ( 'Leave app running in notification area when the window is closed' ) } >
< SettingClosingBehavior noLabels / >
< / SettingsRow >
{ /* @endif */ }
{ /* @if TARGET='app' */ }
< SettingsRow
title = {
< span >
{ _ _ ( 'Automatic transcoding' ) }
{ findingFFmpeg && < Spinner type = "small" / > }
< / span >
}
>
< FileSelector
type = "openDirectory"
placeholder = { _ _ ( 'A Folder containing FFmpeg' ) }
currentPath = { ffmpegPath || daemonSettings . ffmpeg _path }
onFileChosen = { ( newDirectory : WebFile ) => {
// $FlowFixMe
setDaemonSetting ( 'ffmpeg_path' , newDirectory . path ) ;
findFFmpeg ( ) ;
} }
disabled = { Boolean ( ffmpegPath ) }
/ >
< p className = "help" >
{ ffmpegAvailable ? (
2021-08-08 04:26:40 +02:00
< I18nMessage
tokens = { {
learn _more : (
2021-08-09 04:22:16 +02:00
< Button
button = "link"
label = { _ _ ( 'Learn more' ) }
href = "https://lbry.com/faq/video-publishing-guide#automatic"
/ >
2021-08-08 04:26:40 +02:00
) ,
} }
>
2021-08-09 04:22:16 +02:00
FFmpeg is correctly configured . % learn _more %
2021-08-08 04:26:40 +02:00
< / I18nMessage >
2021-08-09 04:22:16 +02:00
) : (
< I18nMessage
tokens = { {
check _again : (
< Button
button = "link"
label = { _ _ ( 'Check again' ) }
onClick = { ( ) => findFFmpeg ( ) }
disabled = { findingFFmpeg }
/ >
) ,
learn _more : (
< Button
button = "link"
label = { _ _ ( 'Learn more' ) }
href = "https://lbry.com/faq/video-publishing-guide#automatic"
/ >
) ,
} }
>
FFmpeg could not be found . Navigate to it or Install , Then % check _again % or quit and restart the
app . % learn _more %
< / I18nMessage >
) }
< / p >
< / SettingsRow >
{ /* @endif */ }
2021-08-08 04:26:40 +02:00
2021-08-09 04:22:16 +02:00
{ /* @if TARGET='app' */ }
2021-08-22 09:58:56 +02:00
< SettingsRow
title = { _ _ ( 'Encrypt my wallet with a custom password' ) }
subtitle = {
< React.Fragment >
< I18nMessage
tokens = { {
learn _more : (
< Button button = "link" label = { _ _ ( 'Learn more' ) } href = "https://lbry.com/faq/account-sync" / >
) ,
} }
>
Wallet encryption is currently unavailable until it ' s supported for synced accounts . It will be
added back soon . % learn _more % .
< / I18nMessage >
{ / * { _ _ ( ' S e c u r e y o u r l o c a l w a l l e t d a t a w i t h a c u s t o m p a s s w o r d . ' ) } { ' ' }
< strong > { _ _ ( 'Lost passwords cannot be recovered.' ) } < / strong >
< Button button = "link" label = { _ _ ( 'Learn more' ) } href = "https://lbry.com/faq/wallet-encryption" / > . * / }
< / React.Fragment >
}
>
2021-08-08 04:26:40 +02:00
< FormField
2021-08-09 04:22:16 +02:00
disabled
2021-08-08 04:26:40 +02:00
type = "checkbox"
2021-08-09 04:22:16 +02:00
name = "encrypt_wallet"
onChange = { ( ) => onChangeEncryptWallet ( ) }
checked = { walletEncrypted }
2021-08-08 04:26:40 +02:00
/ >
2021-08-22 09:58:56 +02:00
< / SettingsRow >
2021-08-08 04:26:40 +02:00
2021-08-22 09:58:56 +02:00
{ walletEncrypted && storedPassword && (
< SettingsRow
title = { _ _ ( 'Save wallet password' ) }
subtitle = { _ _ ( 'Automatically unlock your wallet on startup' ) }
>
2021-08-09 04:22:16 +02:00
< FormField
type = "checkbox"
name = "save_password"
onChange = { onConfirmForgetPassword }
checked = { storedPassword }
/ >
2021-08-22 09:58:56 +02:00
< / SettingsRow >
) }
2021-08-09 04:22:16 +02:00
{ /* @endif */ }
{ /* @if TARGET='app' */ }
2021-08-22 09:58:56 +02:00
< SettingsRow
title = { _ _ ( 'Max connections' ) }
subtitle = { _ _ (
'For users with good bandwidth, try a higher value to improve streaming and download speeds. Low bandwidth users may benefit from a lower setting. Default is 4.'
) }
>
2021-08-09 04:22:16 +02:00
{ /* Disabling below until we get downloads to work with shared subscriptions code */ }
{ / *
2021-08-07 15:12:07 +02:00
< FormField
type = "checkbox"
name = "auto_download"
onChange = { ( ) => setClientSetting ( SETTINGS . AUTO _DOWNLOAD , ! autoDownload ) }
checked = { autoDownload }
label = { _ _ ( 'Automatically download new content from my subscriptions' ) }
helper = { _ _ (
"The latest file from each of your subscriptions will be downloaded for quick access as soon as it's published."
) }
/ >
* / }
2021-08-09 04:22:16 +02:00
< fieldset - section >
< FormField
name = "max_connections"
type = "select"
min = { 1 }
max = { 100 }
2021-10-28 01:21:16 +02:00
onChange = { ( e ) => setDaemonSetting ( DAEMON _SETTINGS . MAX _CONNECTIONS _PER _DOWNLOAD , e . target . value ) }
value = { daemonSettings [ DAEMON _SETTINGS . MAX _CONNECTIONS _PER _DOWNLOAD ] }
2021-08-09 04:22:16 +02:00
>
{ [ 1 , 2 , 4 , 6 , 10 , 20 ] . map ( ( connectionOption ) => (
< option key = { connectionOption } value = { connectionOption } >
{ connectionOption }
< / option >
) ) }
< / FormField >
< / f i e l d s e t - s e c t i o n >
2021-08-22 09:58:56 +02:00
< / SettingsRow >
2021-08-07 15:12:07 +02:00
2021-08-22 09:58:56 +02:00
< SettingsRow title = { _ _ ( 'Wallet server' ) } multirow >
2021-08-09 04:22:16 +02:00
< SettingWalletServer / >
2021-08-22 09:58:56 +02:00
< / SettingsRow >
< SettingsRow title = { _ _ ( 'Comments server' ) } multirow >
2021-08-09 04:22:16 +02:00
< SettingCommentsServer / >
< / SettingsRow >
2021-10-22 04:41:45 +02:00
< SettingsRow title = { _ _ ( 'Share url' ) } multirow >
< SettingShareUrl / >
< / SettingsRow >
2021-08-09 04:22:16 +02:00
{ /* @endif */ }
2021-08-07 15:12:07 +02:00
2021-08-09 04:22:16 +02:00
< SettingsRow
title = { _ _ ( 'Clear application cache' ) }
subtitle = { _ _ ( 'This might fix issues that you are having. Your wallet will not be affected.' ) }
>
< Button
button = "secondary"
icon = { ALERT }
label = { clearingCache ? _ _ ( 'Clearing' ) : _ _ ( 'Clear Cache' ) }
onClick = { ( ) => {
setClearingCache ( true ) ;
clearCache ( ) ;
} }
disabled = { clearingCache }
/ >
< / SettingsRow >
< / >
}
/ >
< / >
2021-08-05 10:41:45 +02:00
) ;
}