finish view data hosting
This commit is contained in:
parent
e9502410de
commit
04a6c735ac
12 changed files with 190 additions and 111 deletions
|
@ -17,8 +17,12 @@ import startSandbox from './startSandbox';
|
||||||
import installDevtools from './installDevtools';
|
import installDevtools from './installDevtools';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { diskSpaceLinux } from '../ui/util/diskspace';
|
||||||
|
|
||||||
const { download } = require('electron-dl');
|
const { download } = require('electron-dl');
|
||||||
const remote = require('@electron/remote/main');
|
const remote = require('@electron/remote/main');
|
||||||
|
const os = require('os');
|
||||||
|
|
||||||
remote.initialize();
|
remote.initialize();
|
||||||
const filePath = path.join(process.resourcesPath, 'static', 'upgradeDisabled');
|
const filePath = path.join(process.resourcesPath, 'static', 'upgradeDisabled');
|
||||||
let upgradeDisabled;
|
let upgradeDisabled;
|
||||||
|
@ -292,6 +296,22 @@ app.on('before-quit', () => {
|
||||||
appState.isQuitting = true;
|
appState.isQuitting = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on('get-disk-space', async (event) => {
|
||||||
|
try {
|
||||||
|
const { data_dir } = await Lbry.settings_get();
|
||||||
|
if (os.platform() === 'linux') {
|
||||||
|
const stdout = await diskSpaceLinux(data_dir);
|
||||||
|
const dfResult = stdout.split('\n')[1].split(/\s+/);
|
||||||
|
const total_and_available = { total: dfResult[1], free: dfResult[3]};
|
||||||
|
rendererWindow.webContents.send('send-disk-space', { diskSpace: total_and_available });
|
||||||
|
}
|
||||||
|
// const space = await nodeDiskInfo.getDiskInfo();
|
||||||
|
} catch (e) {
|
||||||
|
rendererWindow.webContents.send('send-disk-space', { error: e.message || e });
|
||||||
|
console.log('Failed to start LbryFirst', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.on('download-upgrade', async (event, params) => {
|
ipcMain.on('download-upgrade', async (event, params) => {
|
||||||
const { url, options } = params;
|
const { url, options } = params;
|
||||||
const dir = fs.mkdtempSync(app.getPath('temp') + path.sep);
|
const dir = fs.mkdtempSync(app.getPath('temp') + path.sep);
|
||||||
|
|
5
flow-typed/Settings.js
vendored
5
flow-typed/Settings.js
vendored
|
@ -6,3 +6,8 @@ declare type CommentServerDetails = {
|
||||||
declare type WalletServerDetails = {
|
declare type WalletServerDetails = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
declare type DiskSpace = {
|
||||||
|
total: string,
|
||||||
|
free: string,
|
||||||
|
};
|
||||||
|
|
|
@ -2287,5 +2287,9 @@
|
||||||
"View History Hosting": "View History Hosting",
|
"View History Hosting": "View History Hosting",
|
||||||
"Disable automatic updates": "Disable automatic updates",
|
"Disable automatic updates": "Disable automatic updates",
|
||||||
"Preven't new updates to be downloaded automatically in the background (we will keep notifying you if there is an update)": "Preven't new updates to be downloaded automatically in the background (we will keep notifying you if there is an update)",
|
"Preven't new updates to be downloaded automatically in the background (we will keep notifying you if there is an update)": "Preven't new updates to be downloaded automatically in the background (we will keep notifying you if there is an update)",
|
||||||
|
"Unlimited View Hosting": "Unlimited View Hosting",
|
||||||
|
"Choose View Hosting Limit": "Choose View Hosting Limit",
|
||||||
|
"View Hosting Limit (GB)": "View Hosting Limit (GB)",
|
||||||
|
"%free% of %total% available": "%free% of %total% available",
|
||||||
"--end--": "--end--"
|
"--end--": "--end--"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,12 @@ import { connect } from 'react-redux';
|
||||||
import { doSetDaemonSetting, doGetDaemonStatus, doCleanBlobs } from 'redux/actions/settings';
|
import { doSetDaemonSetting, doGetDaemonStatus, doCleanBlobs } from 'redux/actions/settings';
|
||||||
import { selectDaemonStatus, selectDaemonSettings } from 'redux/selectors/settings';
|
import { selectDaemonStatus, selectDaemonSettings } from 'redux/selectors/settings';
|
||||||
import SettingWalletServer from './view';
|
import SettingWalletServer from './view';
|
||||||
|
import { selectDiskSpace } from 'redux/selectors/app';
|
||||||
|
|
||||||
const select = (state) => ({
|
const select = (state) => ({
|
||||||
daemonSettings: selectDaemonSettings(state),
|
daemonSettings: selectDaemonSettings(state),
|
||||||
daemonStatus: selectDaemonStatus(state),
|
daemonStatus: selectDaemonStatus(state),
|
||||||
|
diskSpace: selectDiskSpace(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { FormField } from 'component/common/form';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import * as DAEMON_SETTINGS from 'constants/daemon_settings';
|
import * as DAEMON_SETTINGS from 'constants/daemon_settings';
|
||||||
import { formatBytes } from 'util/format-bytes';
|
import { formatBytes } from 'util/format-bytes';
|
||||||
|
import { isTrulyANumber } from 'util/number';
|
||||||
|
import I18nMessage from 'component/i18nMessage';
|
||||||
const BYTES_PER_MB = 1048576;
|
const BYTES_PER_MB = 1048576;
|
||||||
const ENABLE_AUTOMATIC_HOSTING = false;
|
const ENABLE_AUTOMATIC_HOSTING = false;
|
||||||
|
|
||||||
|
@ -41,155 +43,168 @@ type Props = {
|
||||||
daemonStatus: DaemonStatus,
|
daemonStatus: DaemonStatus,
|
||||||
// --- perform ---
|
// --- perform ---
|
||||||
setDaemonSetting: (string, ?SetDaemonSettingArg) => void,
|
setDaemonSetting: (string, ?SetDaemonSettingArg) => void,
|
||||||
cleanBlobs: () => void,
|
cleanBlobs: () => string,
|
||||||
|
diskSpace?: DiskSpace,
|
||||||
|
getDaemonStatus: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
function SettingWalletServer(props: Props) {
|
function SettingDataHosting(props: Props) {
|
||||||
const { daemonSettings, daemonStatus, setDaemonSetting, cleanBlobs } = props;
|
const { daemonSettings, daemonStatus, setDaemonSetting, cleanBlobs, diskSpace, getDaemonStatus } = props;
|
||||||
|
|
||||||
const { disk_space } = daemonStatus;
|
const { disk_space: blobSpace } = daemonStatus;
|
||||||
const contentSpaceUsed = Number(disk_space.content_blobs_storage_used_mb);
|
const contentSpaceUsed = Number(blobSpace.content_blobs_storage_used_mb);
|
||||||
const networkSpaceUsed = Number(disk_space.seed_blobs_storage_used_mb);
|
const blobLimitSetting = daemonSettings[DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB] || '0';
|
||||||
const blobLimitSetting = daemonSettings[DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB];
|
|
||||||
const networkLimitSetting = daemonSettings[DAEMON_SETTINGS.NETWORK_STORAGE_LIMIT_MB];
|
|
||||||
const [contentBlobSpaceLimitGB, setContentBlobSpaceLimit] = React.useState(
|
const [contentBlobSpaceLimitGB, setContentBlobSpaceLimit] = React.useState(
|
||||||
blobLimitSetting ? blobLimitSetting / 1024 : 0
|
blobLimitSetting ? String(blobLimitSetting / 1024) : '10'
|
||||||
);
|
);
|
||||||
|
const [applying, setApplying] = React.useState(false);
|
||||||
|
|
||||||
|
const networkSpaceUsed = Number(blobSpace.seed_blobs_storage_used_mb);
|
||||||
|
const networkLimitSetting = daemonSettings[DAEMON_SETTINGS.NETWORK_STORAGE_LIMIT_MB] || '0';
|
||||||
const [networkBlobSpaceLimitGB, setNetworkBlobSpaceLimit] = React.useState(
|
const [networkBlobSpaceLimitGB, setNetworkBlobSpaceLimit] = React.useState(
|
||||||
networkLimitSetting ? networkLimitSetting / 1024 : 0
|
networkLimitSetting ? String(networkLimitSetting / 1024) : '0'
|
||||||
);
|
);
|
||||||
const [limitSpace, setLimitSpace] = React.useState(Boolean(blobLimitSetting));
|
|
||||||
|
|
||||||
function updateContentBlobLimitField(gb) {
|
const [unlimited, setUnlimited] = React.useState(blobLimitSetting === '0');
|
||||||
if (gb === 0) {
|
|
||||||
setContentBlobSpaceLimit(0);
|
React.useEffect(() => {
|
||||||
} else if (!gb || !isNaN(gb)) {
|
getDaemonStatus();
|
||||||
setContentBlobSpaceLimit(gb);
|
}, []);
|
||||||
}
|
|
||||||
|
function convertGbToMb(gb) {
|
||||||
|
return Number(gb) * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateNetworkBlobLimitField(gb) {
|
function handleContentLimitChange(gb) {
|
||||||
if (gb === 0) {
|
if (gb === '') {
|
||||||
setNetworkBlobSpaceLimit(0);
|
setContentBlobSpaceLimit('');
|
||||||
} else if (!gb || !isNaN(gb)) {
|
} else if (gb === '0') {
|
||||||
setNetworkBlobSpaceLimit(gb);
|
setContentBlobSpaceLimit('0.01'); // setting 0 means unlimited.
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleLimitSpace(value) {
|
|
||||||
setLimitSpace(value);
|
|
||||||
if (!value) {
|
|
||||||
setDaemonSetting(DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB, String(0));
|
|
||||||
} else {
|
} else {
|
||||||
const spaceLimitMB = contentBlobSpaceLimitGB * 1024;
|
if (isTrulyANumber(Number(gb))) {
|
||||||
setDaemonSetting(DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB, String(spaceLimitMB));
|
setContentBlobSpaceLimit(gb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSetContentBlobSpaceLimit() {
|
function handleNetworkLimitChange(gb) {
|
||||||
const spaceLimitMB = contentBlobSpaceLimitGB * 1024;
|
if (gb === '') {
|
||||||
if (!isNaN(spaceLimitMB) && blobLimitSetting !== spaceLimitMB * 1024) {
|
setNetworkBlobSpaceLimit('');
|
||||||
setDaemonSetting(DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB, String(spaceLimitMB));
|
} else {
|
||||||
|
const numberGb = Number(gb);
|
||||||
|
if (isTrulyANumber(numberGb)) {
|
||||||
|
setNetworkBlobSpaceLimit(gb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSetNetworkBlobSpaceLimit() {
|
async function handleApply() {
|
||||||
const spaceLimitMB = networkBlobSpaceLimitGB * 1024;
|
setApplying(true);
|
||||||
if (!isNaN(spaceLimitMB) && blobLimitSetting !== spaceLimitMB * 1024) {
|
if (unlimited) {
|
||||||
setDaemonSetting(DAEMON_SETTINGS.NETWORK_STORAGE_LIMIT_MB, String(spaceLimitMB));
|
await setDaemonSetting(DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB, '0');
|
||||||
|
} else {
|
||||||
|
await setDaemonSetting(
|
||||||
|
DAEMON_SETTINGS.BLOB_STORAGE_LIMIT_MB,
|
||||||
|
String(contentBlobSpaceLimitGB === '0.01' ? '1' : convertGbToMb(contentBlobSpaceLimitGB))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
await setDaemonSetting(
|
||||||
|
DAEMON_SETTINGS.NETWORK_STORAGE_LIMIT_MB,
|
||||||
|
String(convertGbToMb(Number(networkBlobSpaceLimitGB)))
|
||||||
|
);
|
||||||
|
await cleanBlobs();
|
||||||
|
getDaemonStatus();
|
||||||
|
setApplying(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validHostingAmount(amountString) {
|
||||||
|
const numberAmount = Number(amountString);
|
||||||
|
return amountString.length && ((numberAmount && String(numberAmount)) || numberAmount === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<fieldset-section>
|
<div className={'fieldset-section'}>
|
||||||
<FormField
|
<FormField
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="save_blobs"
|
name="save_blobs"
|
||||||
onChange={() => setDaemonSetting('save_blobs', !daemonSettings.save_blobs)}
|
onChange={() => setDaemonSetting('save_blobs', !daemonSettings.save_blobs)}
|
||||||
checked={daemonSettings.save_blobs}
|
checked={daemonSettings.save_blobs}
|
||||||
label={__('Enable Data Hosting')}
|
label={__('Enable Data Hosting')}
|
||||||
/>
|
helper={
|
||||||
</fieldset-section>
|
diskSpace && (
|
||||||
{daemonSettings.save_blobs && (
|
<I18nMessage
|
||||||
<fieldset-section>
|
tokens={{
|
||||||
<div className={'settings__row-section-title'}>{__('View History Hosting')}</div>
|
free: formatBytes(Number(diskSpace.free) * 1024, 0),
|
||||||
<div className={'help'}>
|
total: formatBytes(Number(diskSpace.total) * 1024, 0),
|
||||||
{`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)
|
%free% of %total% available
|
||||||
: 'Unlimited'
|
</I18nMessage>
|
||||||
}`}
|
)
|
||||||
</div>
|
|
||||||
</fieldset-section>
|
|
||||||
)}
|
|
||||||
{daemonSettings.save_blobs && (
|
|
||||||
<fieldset-section>
|
|
||||||
<FormField
|
|
||||||
type="checkbox"
|
|
||||||
name="limit_space_used"
|
|
||||||
onChange={() => handleLimitSpace(!limitSpace)}
|
|
||||||
checked={limitSpace}
|
|
||||||
label={__('Limit Hosting of Content History')}
|
|
||||||
/>
|
|
||||||
</fieldset-section>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{daemonSettings.save_blobs && limitSpace && (
|
|
||||||
<FormField
|
|
||||||
name="content_blob_limit_gb"
|
|
||||||
type="text"
|
|
||||||
label={__(`Limit (GB)`)}
|
|
||||||
disabled={!daemonSettings.save_blobs}
|
|
||||||
onChange={(e) => updateContentBlobLimitField(e.target.value)}
|
|
||||||
value={contentBlobSpaceLimitGB}
|
|
||||||
inputButton={
|
|
||||||
<Button
|
|
||||||
disabled={isNaN(contentBlobSpaceLimitGB)}
|
|
||||||
button="primary"
|
|
||||||
label={__('Apply')}
|
|
||||||
onClick={handleSetContentBlobSpaceLimit}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
{daemonSettings.save_blobs && (
|
||||||
|
<div className={'fieldset-section'}>
|
||||||
|
<FormField
|
||||||
|
type="radio"
|
||||||
|
name="no_hosting_limit"
|
||||||
|
checked={unlimited}
|
||||||
|
label={__('Unlimited View Hosting')}
|
||||||
|
onChange={() => setUnlimited(true)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
type="radio"
|
||||||
|
name="set_hosting_limit"
|
||||||
|
checked={!unlimited}
|
||||||
|
onChange={() => setUnlimited(false)}
|
||||||
|
label={__('Choose View Hosting Limit')}
|
||||||
|
/>
|
||||||
|
{!unlimited && (
|
||||||
|
<FormField
|
||||||
|
name="content_blob_limit_gb"
|
||||||
|
type="number"
|
||||||
|
min={0}
|
||||||
|
onWheel={(e) => e.preventDefault()}
|
||||||
|
label={__(`View Hosting Limit (GB)`)}
|
||||||
|
onChange={(e) => handleContentLimitChange(e.target.value)}
|
||||||
|
value={Number(contentBlobSpaceLimitGB) <= Number('0.01') ? '0' : contentBlobSpaceLimitGB}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className={'help'}>{`Currently using ${formatBytes(contentSpaceUsed * BYTES_PER_MB)}`}</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
<fieldset-section>
|
|
||||||
<Button type="button" button="inverse" onClick={cleanBlobs} label={__('Clean Now')} />
|
|
||||||
</fieldset-section>
|
|
||||||
{/* Automatic Hosting Section */}
|
|
||||||
{daemonSettings.save_blobs && ENABLE_AUTOMATIC_HOSTING && (
|
{daemonSettings.save_blobs && ENABLE_AUTOMATIC_HOSTING && (
|
||||||
<fieldset-section>
|
<fieldset-section>
|
||||||
<div className={'settings__row-section-title'}>{__('Automatic Hosting - Experimental')}</div>
|
|
||||||
<p className={'help'}>
|
|
||||||
{`Automatic Hosting using ${formatBytes(networkSpaceUsed * BYTES_PER_MB)} of ${formatBytes(
|
|
||||||
daemonSettings[DAEMON_SETTINGS.NETWORK_STORAGE_LIMIT_MB] * BYTES_PER_MB
|
|
||||||
)}`}
|
|
||||||
</p>
|
|
||||||
</fieldset-section>
|
|
||||||
)}
|
|
||||||
{daemonSettings.save_blobs && ENABLE_AUTOMATIC_HOSTING && (
|
|
||||||
<>
|
|
||||||
<FormField
|
<FormField
|
||||||
name="network_blob_limit_gb"
|
name="network_blob_limit_gb"
|
||||||
type="text"
|
type="number"
|
||||||
label={__(`Allow (GB)`)}
|
label={__(`Automatic Hosting (GB)`)}
|
||||||
disabled={!daemonSettings.save_blobs}
|
onChange={(e) => handleNetworkLimitChange(e.target.value)}
|
||||||
onChange={(e) => updateNetworkBlobLimitField(e.target.value)}
|
|
||||||
value={networkBlobSpaceLimitGB}
|
value={networkBlobSpaceLimitGB}
|
||||||
inputButton={
|
|
||||||
<Button
|
|
||||||
disabled={isNaN(networkBlobSpaceLimitGB)}
|
|
||||||
button="primary"
|
|
||||||
label={__('Apply')}
|
|
||||||
onClick={handleSetNetworkBlobSpaceLimit}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<div className="form-field__help">{__('Download and serve arbitrary data on the network.')}</div>
|
<div className={'help'}>{`Auto-hosting ${formatBytes(networkSpaceUsed * BYTES_PER_MB)}`}</div>
|
||||||
</>
|
</fieldset-section>
|
||||||
)}
|
)}
|
||||||
|
<div className={'card__actions'}>
|
||||||
|
<Button
|
||||||
|
disabled={
|
||||||
|
(unlimited && blobLimitSetting === '0') ||
|
||||||
|
(!unlimited &&
|
||||||
|
(blobLimitSetting === convertGbToMb(contentBlobSpaceLimitGB) || // &&
|
||||||
|
// networkLimitSetting === convertGbToMb(networkBlobSpaceLimitGB)
|
||||||
|
!validHostingAmount(String(contentBlobSpaceLimitGB)))) ||
|
||||||
|
applying
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
|
button="primary"
|
||||||
|
onClick={handleApply}
|
||||||
|
label={__('Apply')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SettingWalletServer;
|
export default SettingDataHosting;
|
||||||
|
|
|
@ -32,6 +32,7 @@ export const TOGGLE_YOUTUBE_SYNC_INTEREST = 'TOGGLE_YOUTUBE_SYNC_INTEREST';
|
||||||
export const TOGGLE_SPLASH_ANIMATION = 'TOGGLE_SPLASH_ANIMATION';
|
export const TOGGLE_SPLASH_ANIMATION = 'TOGGLE_SPLASH_ANIMATION';
|
||||||
export const SET_ACTIVE_CHANNEL = 'SET_ACTIVE_CHANNEL';
|
export const SET_ACTIVE_CHANNEL = 'SET_ACTIVE_CHANNEL';
|
||||||
export const SET_INCOGNITO = 'SET_INCOGNITO';
|
export const SET_INCOGNITO = 'SET_INCOGNITO';
|
||||||
|
export const DISK_SPACE = 'DISK_SPACE';
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
|
export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
|
||||||
|
|
12
ui/index.jsx
12
ui/index.jsx
|
@ -91,6 +91,18 @@ rewards.setCallback('claimRewardSuccess', (reward) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcRenderer.on('send-disk-space', (event, result) => {
|
||||||
|
if (result.error) {
|
||||||
|
console.log(`disk space error: ${result.error}`);
|
||||||
|
} else {
|
||||||
|
app.store.dispatch({
|
||||||
|
type: ACTIONS.DISK_SPACE,
|
||||||
|
data: result.diskSpace,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcRenderer.send('get-disk-space');
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
ipcRenderer.on('open-uri-requested', (event, url, newSession) => {
|
ipcRenderer.on('open-uri-requested', (event, url, newSession) => {
|
||||||
function handleError() {
|
function handleError() {
|
||||||
|
|
|
@ -132,7 +132,10 @@ export function doSetDaemonSetting(key, value, doNotDispatch = false) {
|
||||||
|
|
||||||
export function doCleanBlobs() {
|
export function doCleanBlobs() {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
Lbry.blob_clean().then(dispatch(doFetchDaemonSettings()));
|
Lbry.blob_clean().then(() => {
|
||||||
|
dispatch(doFetchDaemonSettings());
|
||||||
|
return 'done';
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ export type AppState = {
|
||||||
interestedInYoutubeSync: boolean,
|
interestedInYoutubeSync: boolean,
|
||||||
activeChannel: ?string,
|
activeChannel: ?string,
|
||||||
incognito: boolean,
|
incognito: boolean,
|
||||||
|
diskSpace: ?DiskSpace,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultState: AppState = {
|
const defaultState: AppState = {
|
||||||
|
@ -83,6 +84,7 @@ const defaultState: AppState = {
|
||||||
interestedInYoutubeSync: false,
|
interestedInYoutubeSync: false,
|
||||||
activeChannel: undefined,
|
activeChannel: undefined,
|
||||||
incognito: false,
|
incognito: false,
|
||||||
|
diskSpace: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
// @@router comes from react-router
|
// @@router comes from react-router
|
||||||
|
@ -317,6 +319,13 @@ reducers[ACTIONS.SET_INCOGNITO] = (state, action) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reducers[ACTIONS.DISK_SPACE] = (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
diskSpace: action.data,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
reducers[ACTIONS.SYNC_STATE_POPULATE] = (state, action) => {
|
reducers[ACTIONS.SYNC_STATE_POPULATE] = (state, action) => {
|
||||||
const { welcomeVersion, allowAnalytics } = action.data;
|
const { welcomeVersion, allowAnalytics } = action.data;
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -139,3 +139,5 @@ export const selectActiveChannelStakedLevel = createSelector(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIncognito = createSelector(selectState, (state) => state.incognito);
|
export const selectIncognito = createSelector(selectState, (state) => state.incognito);
|
||||||
|
|
||||||
|
export const selectDiskSpace = createSelector(selectState, (state) => state.diskSpace);
|
||||||
|
|
|
@ -15,6 +15,7 @@ export const diskSpaceLinux = (path) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// to implement
|
||||||
// export diskSpaceWindows = (path) => {
|
// export diskSpaceWindows = (path) => {
|
||||||
// new Promise((resolve, reject) => {
|
// new Promise((resolve, reject) => {
|
||||||
//
|
//
|
||||||
|
|
|
@ -3,3 +3,8 @@
|
||||||
export function formatNumberWithCommas(num: number, numberOfDigits?: number): string {
|
export function formatNumberWithCommas(num: number, numberOfDigits?: number): string {
|
||||||
return num.toLocaleString('en', { minimumFractionDigits: numberOfDigits !== undefined ? numberOfDigits : 8 });
|
return num.toLocaleString('en', { minimumFractionDigits: numberOfDigits !== undefined ? numberOfDigits : 8 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isTrulyANumber(num: number) {
|
||||||
|
// typeof NaN = 'number' but NaN !== NaN
|
||||||
|
return typeof num === 'number' && num === num; // eslint-disable-line
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue