diff --git a/static/app-strings.json b/static/app-strings.json index 5fa9cd9e9..dd7cfc530 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -2280,5 +2280,10 @@ "Shuffle is off.": "Shuffle is off.", "Loop is on.": "Loop is on.", "Loop is off.": "Loop is off.", + "View History Hosting lets you choose how much storage to use helping content you've consumed.": "View History Hosting lets you choose how much storage to use helping content you've consumed.", + "Clean Now": "Clean Now", + "Enable Automatic Hosting": "Enable Automatic Hosting", + "Download and serve arbitrary data on the network.": "Download and serve arbitrary data on the network.", + "View History Hosting": "View History Hosting", "--end--": "--end--" } diff --git a/ui/component/settingDataHosting/index.js b/ui/component/settingDataHosting/index.js new file mode 100644 index 000000000..1bbdf3971 --- /dev/null +++ b/ui/component/settingDataHosting/index.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { doSetDaemonSetting, doGetDaemonStatus, doCleanBlobs } from 'redux/actions/settings'; +import { selectDaemonStatus, selectDaemonSettings } from 'redux/selectors/settings'; +import SettingWalletServer from './view'; + +const select = (state) => ({ + daemonSettings: selectDaemonSettings(state), + daemonStatus: selectDaemonStatus(state), +}); + +const perform = (dispatch) => ({ + getDaemonStatus: () => dispatch(doGetDaemonStatus()), + setDaemonSetting: (key, value) => dispatch(doSetDaemonSetting(key, value)), + cleanBlobs: () => dispatch(doCleanBlobs()), +}); + +export default connect(select, perform)(SettingWalletServer); diff --git a/ui/component/settingDataHosting/view.jsx b/ui/component/settingDataHosting/view.jsx new file mode 100644 index 000000000..035a32ef4 --- /dev/null +++ b/ui/component/settingDataHosting/view.jsx @@ -0,0 +1,195 @@ +// @flow + +import React from 'react'; +import { FormField } from 'component/common/form'; +import Button from 'component/button'; +import * as DAEMON_SETTINGS from 'constants/daemon_settings'; +import { formatBytes } from 'util/format-bytes'; +const BYTES_PER_MB = 1048576; +const ENABLE_AUTOMATIC_HOSTING = false; + +type Price = { + currency: string, + amount: number, +}; + +type DaemonStatus = { + disk_space: { + content_blobs_storage_used_mb: string, + published_blobs_storage_used_mb: string, + running: true, + seed_blobs_storage_used_mb: string, + total_used_mb: string, + }, +}; + +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, + daemonStatus: DaemonStatus, + // --- perform --- + setDaemonSetting: (string, ?SetDaemonSettingArg) => void, + cleanBlobs: () => void, +}; + +function SettingWalletServer(props: Props) { + const { daemonSettings, daemonStatus, setDaemonSetting, cleanBlobs } = props; + + const { disk_space } = daemonStatus; + const contentSpaceUsed = Number(disk_space.content_blobs_storage_used_mb); + const networkSpaceUsed = Number(disk_space.seed_blobs_storage_used_mb); + const blobLimitSetting = daemonSettings[DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB]; + const networkLimitSetting = daemonSettings[DAEMON_SETTINGS.NETWORK_STORAGE_LIMIT_MB]; + const [contentBlobSpaceLimitGB, setContentBlobSpaceLimit] = React.useState( + blobLimitSetting ? blobLimitSetting / 1024 : 0 + ); + const [networkBlobSpaceLimitGB, setNetworkBlobSpaceLimit] = React.useState( + networkLimitSetting ? networkLimitSetting / 1024 : 0 + ); + const [limitSpace, setLimitSpace] = React.useState(Boolean(blobLimitSetting)); + + function updateContentBlobLimitField(gb) { + if (gb === 0) { + setContentBlobSpaceLimit(0); + } else if (!gb || !isNaN(gb)) { + setContentBlobSpaceLimit(gb); + } + } + + function updateNetworkBlobLimitField(gb) { + if (gb === 0) { + setNetworkBlobSpaceLimit(0); + } else if (!gb || !isNaN(gb)) { + setNetworkBlobSpaceLimit(gb); + } + } + + function handleLimitSpace(value) { + setLimitSpace(value); + if (!value) { + setDaemonSetting(DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB, String(0)); + } else { + const spaceLimitMB = contentBlobSpaceLimitGB * 1024; + setDaemonSetting(DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB, String(spaceLimitMB)); + } + } + + function handleSetContentBlobSpaceLimit() { + const spaceLimitMB = contentBlobSpaceLimitGB * 1024; + if (!isNaN(spaceLimitMB) && blobLimitSetting !== spaceLimitMB * 1024) { + setDaemonSetting(DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB, String(spaceLimitMB)); + } + } + + function handleSetNetworkBlobSpaceLimit() { + const spaceLimitMB = networkBlobSpaceLimitGB * 1024; + if (!isNaN(spaceLimitMB) && blobLimitSetting !== spaceLimitMB * 1024) { + setDaemonSetting(DAEMON_SETTINGS.NETWORK_STORAGE_LIMIT_MB, String(spaceLimitMB)); + } + } + + return ( + <> + + setDaemonSetting('save_blobs', !daemonSettings.save_blobs)} + checked={daemonSettings.save_blobs} + label={__('Enable Data Hosting')} + /> + + {daemonSettings.save_blobs && ( + +
{__('View History Hosting')}
+
+ {`View History Hosting using ${formatBytes(contentSpaceUsed * BYTES_PER_MB)} of ${ + daemonSettings[DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB] + ? formatBytes(daemonSettings[DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB] * BYTES_PER_MB) + : 'Unlimited' + }`} +
+
+ )} + {daemonSettings.save_blobs && ( + + handleLimitSpace(!limitSpace)} + checked={limitSpace} + label={__('Limit Hosting of Content History')} + /> + + )} + + {daemonSettings.save_blobs && limitSpace && ( + updateContentBlobLimitField(e.target.value)} + value={contentBlobSpaceLimitGB} + inputButton={ +