// @flow import * as SETTINGS from 'constants/settings'; import * as PAGES from 'constants/pages'; import * as React from 'react'; import { FormField, FormFieldPrice, Form } from 'component/common/form'; import Button from 'component/button'; import Page from 'component/page'; import FileSelector from 'component/common/file-selector'; type Price = { currency: string, amount: number, }; type SetDaemonSettingArg = boolean | string | number | Price; type DarkModeTimes = { from: { hour: string, min: string, formattedTime: string }, to: { hour: string, min: string, formattedTime: string }, }; type OptionTimes = { fromTo: string, time: string, }; type DaemonSettings = { download_dir: string, share_usage_data: boolean, max_key_fee?: Price, max_connections_per_download?: number, save_files: boolean, save_blobs: boolean, }; type Props = { setDaemonSetting: (string, ?SetDaemonSettingArg) => void, setClientSetting: (string, SetDaemonSettingArg) => void, clearCache: () => Promise, getThemes: () => void, daemonSettings: DaemonSettings, showNsfw: boolean, instantPurchaseEnabled: boolean, instantPurchaseMax: Price, currentLanguage: string, languages: {}, currentTheme: string, themes: Array, automaticDarkModeEnabled: boolean, autoplay: boolean, autoDownload: boolean, changeLanguage: string => void, encryptWallet: () => void, decryptWallet: () => void, updateWalletStatus: () => void, walletEncrypted: boolean, osNotificationsEnabled: boolean, supportOption: boolean, userBlockedChannelsCount?: number, hideBalance: boolean, floatingPlayer: boolean, clearPlayingUri: () => void, darkModeTimes: DarkModeTimes, setDarkTime: (string, {}) => void, }; type State = { clearingCache: boolean, }; class SettingsPage extends React.PureComponent { constructor(props: Props) { super(props); this.state = { clearingCache: false, }; (this: any).onKeyFeeChange = this.onKeyFeeChange.bind(this); (this: any).onMaxConnectionsChange = this.onMaxConnectionsChange.bind(this); (this: any).onKeyFeeDisableChange = this.onKeyFeeDisableChange.bind(this); (this: any).onInstantPurchaseMaxChange = this.onInstantPurchaseMaxChange.bind(this); (this: any).onThemeChange = this.onThemeChange.bind(this); (this: any).onAutomaticDarkModeChange = this.onAutomaticDarkModeChange.bind(this); (this: any).onLanguageChange = this.onLanguageChange.bind(this); (this: any).clearCache = this.clearCache.bind(this); (this: any).onChangeTime = this.onChangeTime.bind(this); } componentDidMount() { this.props.getThemes(); this.props.updateWalletStatus(); } onKeyFeeChange(newValue: Price) { this.setDaemonSetting('max_key_fee', newValue); } onMaxConnectionsChange(event: SyntheticInputEvent<*>) { const { value } = event.target; this.setDaemonSetting('max_connections_per_download', value); } onKeyFeeDisableChange(isDisabled: boolean) { if (isDisabled) this.setDaemonSetting('max_key_fee'); } onThemeChange(event: SyntheticInputEvent<*>) { const { value } = event.target; if (value === 'dark') { this.onAutomaticDarkModeChange(false); } this.props.setClientSetting(SETTINGS.THEME, value); } onLanguageChange(event: SyntheticInputEvent<*>) { const { value } = event.target; this.props.changeLanguage(value); } onAutomaticDarkModeChange(value: boolean) { this.props.setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, value); } onInstantPurchaseEnabledChange(enabled: boolean) { this.props.setClientSetting(SETTINGS.INSTANT_PURCHASE_ENABLED, enabled); } onInstantPurchaseMaxChange(newValue: Price) { this.props.setClientSetting(SETTINGS.INSTANT_PURCHASE_MAX, newValue); } onChangeEncryptWallet() { const { decryptWallet, walletEncrypted, encryptWallet } = this.props; if (walletEncrypted) { decryptWallet(); } else { encryptWallet(); } } onChangeTime(event: SyntheticInputEvent<*>, options: OptionTimes) { const { value } = event.target; this.props.setDarkTime(value, options); } to12Hour(time: string) { const now = new Date(0, 0, 0, Number(time)); const hour = now.toLocaleTimeString('en-US', { hour12: true, hour: '2-digit' }); return hour; } setDaemonSetting(name: string, value: ?SetDaemonSettingArg): void { this.props.setDaemonSetting(name, value); } clearCache() { this.setState({ clearingCache: true, }); const success = () => { this.setState({ clearingCache: false }); window.location.href = 'index.html'; }; const clear = () => this.props.clearCache().then(success); setTimeout(clear, 1000, { once: true }); } render() { const { daemonSettings, showNsfw, instantPurchaseEnabled, instantPurchaseMax, currentTheme, currentLanguage, languages, themes, automaticDarkModeEnabled, autoplay, walletEncrypted, osNotificationsEnabled, autoDownload, setDaemonSetting, setClientSetting, supportOption, hideBalance, userBlockedChannelsCount, floatingPlayer, clearPlayingUri, darkModeTimes, } = this.props; const noDaemonSettings = !daemonSettings || Object.keys(daemonSettings).length === 0; const defaultMaxKeyFee = { currency: 'USD', amount: 50 }; const disableMaxKeyFee = !(daemonSettings && daemonSettings.max_key_fee); const connectionOptions = [1, 2, 4, 6, 10, 20]; const startHours = ['18', '19', '20', '21']; const endHours = ['5', '6', '7', '8']; return ( {noDaemonSettings && !IS_WEB ? (
{__('Failed to load settings.')}
) : (
{!IS_WEB && (

{__('Download Directory')}

{ setDaemonSetting('download_dir', newDirectory); }} />

{__('LBRY downloads will be saved here.')}

)} {!IS_WEB && (

{__('Network and Data Settings')}

setDaemonSetting('save_files', !daemonSettings.save_files)} checked={daemonSettings.save_files} label={__('Save all viewed content to your downloads directory')} helper={__( 'Paid content and some file types are saved by default. Changing this setting will not affect previously downloaded content.' )} />
setDaemonSetting('save_blobs', !daemonSettings.save_blobs)} checked={daemonSettings.save_blobs} label={__('Save hosting data to help the LBRY network')} helper={ {__("If disabled, LBRY will be very sad and you won't be helping improve the network.")}{' '}
)}

{__('Max Purchase Price')}

{ this.onKeyFeeDisableChange(true); }} /> { this.onKeyFeeDisableChange(false); this.onKeyFeeChange(defaultMaxKeyFee); }} label={__('Choose limit')} /> {!disableMaxKeyFee && ( )}

{__('This will prevent you from purchasing any content over a certain cost, as a safety measure.')}

{__('Purchase Confirmations')}

{ this.onInstantPurchaseEnabledChange(false); }} /> { this.onInstantPurchaseEnabledChange(true); }} /> {instantPurchaseEnabled && ( )}

{__("When this option is chosen, LBRY won't ask you to confirm downloads below your chosen price.")}

{__('Content Settings')}

{ setClientSetting(SETTINGS.FLOATING_PLAYER, !floatingPlayer); clearPlayingUri(); }} checked={floatingPlayer} label={__('Floating video player')} helper={__('Keep content playing in the corner when navigating to a different page.')} /> setClientSetting(SETTINGS.AUTOPLAY, !autoplay)} checked={autoplay} label={__('Autoplay media files')} helper={__( 'Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.' )} /> setClientSetting(SETTINGS.SHOW_NSFW, !showNsfw)} checked={showNsfw} label={__('Show mature content')} helper={__( 'Mature content may include nudity, intense sexuality, profanity, or other adult content. By displaying mature content, you are affirming you are of legal age to view mature content in your country or jurisdiction. ' )} />

{__('Blocked Channels')}

{__('You have')} {userBlockedChannelsCount} {__('blocked')}{' '} {userBlockedChannelsCount === 1 && __('channel')} {userBlockedChannelsCount !== 1 && __('channels')}.{' '}

{!IS_WEB && (

{__('Notifications')}

setClientSetting(SETTINGS.OS_NOTIFICATIONS_ENABLED, !osNotificationsEnabled)} checked={osNotificationsEnabled} label={__('Show Desktop Notifications')} helper={__('Get notified when a publish is confirmed, or when new content is available to watch.')} />
)}

{__('Share Diagnostic Data')}

setDaemonSetting('share_usage_data', !daemonSettings.share_usage_data)} checked={daemonSettings.share_usage_data} label={ {__('Help make LBRY better by contributing analytics and diagnostic data about my usage.')}{' '}

{__('Appearance')}

{themes.map(theme => ( ))} this.onAutomaticDarkModeChange(!automaticDarkModeEnabled)} checked={automaticDarkModeEnabled} label={__('Automatic dark mode')} /> {automaticDarkModeEnabled && ( this.onChangeTime(value, { fromTo: 'from', time: 'hour' })} value={darkModeTimes.from.hour} label={__('From')} > {startHours.map(time => ( ))} this.onChangeTime(value, { fromTo: 'to', time: 'hour' })} value={darkModeTimes.to.hour} > {endHours.map(time => ( ))} )}
{!IS_WEB && (

{__('Wallet Security')}

this.onChangeEncryptWallet()} checked={walletEncrypted} label={__('Encrypt my wallet with a custom password')} helper={ {__('Secure your local wallet data with a custom password.')}{' '} {__('Lost passwords cannot be recovered.')}
)} {!IS_WEB && (

{__('Experimental Settings')}

setClientSetting(SETTINGS.SUPPORT_OPTION, !supportOption)} checked={supportOption} label={__('Enable claim support')} helper={ {__('This will add a Support button along side tipping. Similar to tips, supports help ')}
)}

{__('Application Cache')}

{__( 'This will clear the application cache. Your wallet will not be affected. Currently, followed tags and blocked channels will be cleared.' )}

)}
); } } export default SettingsPage;