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 >
{ _ _ (
` 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 sign in to lbry.tv) `
) } { ' ' }
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
) ;
}