// @flow import { ALERT } from 'constants/icons'; import { SETTINGS_GRP } from 'constants/settings'; import React from 'react'; import Button from 'component/button'; import Card from 'component/common/card'; import { FormField } from 'component/common/form'; import FileSelector from 'component/common/file-selector'; import I18nMessage from 'component/i18nMessage'; import SettingAutoLaunch from 'component/settingAutoLaunch'; import SettingClosingBehavior from 'component/settingClosingBehavior'; import SettingCommentsServer from 'component/settingCommentsServer'; import SettingShareUrl from 'component/settingShareUrl'; import SettingsRow from 'component/settingsRow'; import SettingWalletServer from 'component/settingWalletServer'; import Spinner from 'component/spinner'; import { getPasswordFromCookie } from 'util/saved-passwords'; import * as DAEMON_SETTINGS from 'constants/daemon_settings'; import SettingEnablePrereleases from 'component/settingEnablePrereleases'; import SettingDisableAutoUpdates from 'component/settingDisableAutoUpdates'; const IS_MAC = process.platform === 'darwin'; 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, }; type Props = { // --- select --- daemonSettings: DaemonSettings, ffmpegStatus: { available: boolean, which: string }, findingFFmpeg: boolean, walletEncrypted: boolean, isAuthenticated: boolean, allowAnalytics: boolean, // --- perform --- setDaemonSetting: (string, ?SetDaemonSettingArg) => void, clearDaemonSetting: (string) => void, clearCache: () => Promise<any>, findFFmpeg: () => void, encryptWallet: () => void, decryptWallet: () => void, updateWalletStatus: () => void, confirmForgetPassword: ({}) => void, toggle3PAnalytics: (boolean) => void, }; export default function SettingSystem(props: Props) { const { daemonSettings, ffmpegStatus, findingFFmpeg, walletEncrypted, isAuthenticated, allowAnalytics, setDaemonSetting, clearDaemonSetting, clearCache, findFFmpeg, encryptWallet, decryptWallet, updateWalletStatus, confirmForgetPassword, toggle3PAnalytics, } = props; const [clearingCache, setClearingCache] = React.useState(false); const [storedPassword, setStoredPassword] = React.useState(false); const { available: ffmpegAvailable, which: ffmpegPath } = ffmpegStatus; function onChangeEncryptWallet() { if (walletEncrypted) { decryptWallet(); } else { encryptWallet(); } } function onConfirmForgetPassword() { confirmForgetPassword({ callback: () => setStoredPassword(false) }); } // Update ffmpeg variables React.useEffect(() => { const { available } = ffmpegStatus; const { ffmpeg_path: ffmpegPath } = daemonSettings; if (!available) { if (ffmpegPath) { clearDaemonSetting('ffmpeg_path'); } findFFmpeg(); } }, []); // eslint-disable-line react-hooks/exhaustive-deps // Update storedPassword state React.useEffect(() => { updateWalletStatus(); getPasswordFromCookie().then((p) => { if (typeof p === 'string') { setStoredPassword(true); } }); }, []); // eslint-disable-line react-hooks/exhaustive-deps return ( <> <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 */} <SettingsRow title={__('Save all viewed content to your downloads directory')} subtitle={__( 'Paid content and some file types are saved by default. Changing this setting will not affect previously downloaded content.' )} > <FormField type="checkbox" name="save_files" onChange={() => setDaemonSetting('save_files', !daemonSettings.save_files)} checked={daemonSettings.save_files} /> </SettingsRow> <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 connect to a cloud service)` )}{' '} <Button button="link" label={__('Learn more')} href="https://lbry.com/privacypolicy" /> </React.Fragment> } multirow > <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> {/* 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> )} <SettingsRow title={__('Leave app running in notification area when the window is closed')}> <SettingClosingBehavior noLabels /> </SettingsRow> <SettingsRow title={__('Enable Upgrade to Test Builds')} subtitle={__('Prereleases may break things and we may not be able to fix them for you.')} > <SettingEnablePrereleases /> </SettingsRow> <SettingsRow title={__('Disable automatic updates')} subtitle={__( "Preven't new updates to be downloaded automatically in the background (we will keep notifying you if there is an update)" )} > <SettingDisableAutoUpdates /> </SettingsRow> <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 ? ( <I18nMessage tokens={{ learn_more: ( <Button button="link" label={__('Learn more')} href="https://lbry.com/faq/video-publishing-guide#automatic" /> ), }} > FFmpeg is correctly configured. %learn_more% </I18nMessage> ) : ( <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> <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> {/* {__('Secure your local wallet data with a custom password.')}{' '} <strong>{__('Lost passwords cannot be recovered.')} </strong> <Button button="link" label={__('Learn more')} href="https://lbry.com/faq/wallet-encryption" />. */} </React.Fragment> } > <FormField disabled type="checkbox" name="encrypt_wallet" onChange={() => onChangeEncryptWallet()} checked={walletEncrypted} /> </SettingsRow> {walletEncrypted && storedPassword && ( <SettingsRow title={__('Save wallet password')} subtitle={__('Automatically unlock your wallet on startup')} > <FormField type="checkbox" name="save_password" onChange={onConfirmForgetPassword} checked={storedPassword} /> </SettingsRow> )} <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.' )} > {/* Disabling below until we get downloads to work with shared subscriptions code */} {/* <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." )} /> */} <fieldset-section> <FormField name="max_connections" type="select" min={1} max={100} onChange={(e) => setDaemonSetting(DAEMON_SETTINGS.MAX_CONNECTIONS_PER_DOWNLOAD, e.target.value)} value={daemonSettings[DAEMON_SETTINGS.MAX_CONNECTIONS_PER_DOWNLOAD]} > {[1, 2, 4, 6, 10, 20].map((connectionOption) => ( <option key={connectionOption} value={connectionOption}> {connectionOption} </option> ))} </FormField> </fieldset-section> </SettingsRow> <SettingsRow title={__('Wallet server')} subtitle={ <I18nMessage tokens={{ learn_more: ( <Button button="link" href="http://lbry.com/faq/wallet-servers" label={__('Learn More')} /> ), }} > Wallet servers are used to relay data to and from the LBRY blockchain. They also determine what content shows in trending or is blocked. %learn_more% </I18nMessage> } multirow > <SettingWalletServer /> </SettingsRow> <SettingsRow title={__('Comments server')} multirow> <SettingCommentsServer /> </SettingsRow> <SettingsRow title={__('Share url')} multirow> <SettingShareUrl /> </SettingsRow> <SettingsRow title={__('Clear application cache')} subtitle={__('This might fix issues that you are having. Your wallet will not be affected.')} > <Button button="primary" icon={ALERT} label={clearingCache ? __('Clearing') : __('Clear Cache')} onClick={() => { setClearingCache(true); clearCache(); }} disabled={clearingCache} /> </SettingsRow> </> } /> </> ); }