Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add folder size calculation and display #404

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions app/containers/HomePage/components/FileExplorer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ import {
redditShareUrl,
twitterShareUrl,
} from '../../../templates/socialMediaShareBtns';
import { baseName, pathInfo, pathUp, sanitizePath } from '../../../utils/files';
import { baseName, pathInfo, pathUp, sanitizePath, calculateFolderSize } from '../../../utils/files';
import {
DEVICE_TYPE,
FILE_EXPLORER_VIEW_TYPE,
Expand Down Expand Up @@ -202,6 +202,7 @@ class FileExplorer extends Component {
},
},
directoryGeneratedTime: Date.now(),
folderSizes: {}, // Add state for folder sizes
};

this.state = {
Expand Down Expand Up @@ -258,6 +259,7 @@ class FileExplorer extends Component {

if (nextDirectoryNodes !== prevDirectoryNodes) {
this._handleDirectoryGeneratedTime();
this.calculateFolderSizes(nextDirectoryNodes); // Calculate folder sizes when directory changes
}

if (nextShowDirectoriesFirst !== showDirectoriesFirst) {
Expand Down Expand Up @@ -1985,6 +1987,19 @@ class FileExplorer extends Component {
});
};

calculateFolderSizes = async (nodes) => {
const folderSizes = {};

for (const node of nodes) {
if (node.isFolder) {
const size = await calculateFolderSize(node.path);
folderSizes[node.path] = size;
}
}

this.setState({ folderSizes });
};

render() {
const {
classes: styles,
Expand All @@ -1999,7 +2014,7 @@ class FileExplorer extends Component {
isStatusBarEnabled,
fileTransferClipboard,
} = this.props;
const { toggleDialog, togglePasteConfirmDialog, directoryGeneratedTime } =
const { toggleDialog, togglePasteConfirmDialog, directoryGeneratedTime, folderSizes } =
this.state;
const { rename, newFolder } = toggleDialog;
const togglePasteDialog =
Expand Down Expand Up @@ -2181,6 +2196,7 @@ class FileExplorer extends Component {
this._handleFocussedFileExplorerDeviceType
}
onAcceleratorActivation={this._handleAcceleratorActivation}
folderSizes={folderSizes} // Pass folder sizes to FileExplorerBodyRender
/>
;
</Fragment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import classNames from 'classnames';
import { niceBytes, springTruncate } from '../../../utils/funcs';
import { FILE_EXPLORER_TABLE_TRUNCATE_MAX_CHARS } from '../../../constants';
import { styles } from '../styles/FileExplorerTableBodyListRender';
// eslint-disable-next-line import/no-relative-packages
import prettyFileIcons from '../../../vendors/pretty-file-icons';
import { imgsrc } from '../../../utils/imgsrc';
import { appDateFormat } from '../../../utils/date';
import { calculateFolderSize } from '../../../utils/files';

class FileExplorerTableBodyListRender extends PureComponent {
RenderFileIcon = () => {
Expand Down Expand Up @@ -56,6 +56,7 @@ class FileExplorerTableBodyListRender extends PureComponent {
onContextMenuClick,
onTableClick,
onTableDoubleClick,
folderSizes,
} = this.props;

const { RenderFileIcon, RenderFolderIcon } = this;
Expand All @@ -65,6 +66,8 @@ class FileExplorerTableBodyListRender extends PureComponent {
FILE_EXPLORER_TABLE_TRUNCATE_MAX_CHARS
);

const folderSize = item.isFolder ? folderSizes[item.path] : null;

return (
<TableRow
draggable
Expand Down Expand Up @@ -144,7 +147,7 @@ class FileExplorerTableBodyListRender extends PureComponent {
onTableDoubleClick(item, deviceType, event)
}
>
{item.isFolder ? `--` : `${niceBytes(item.size)}`}
{item.isFolder ? (folderSize ? niceBytes(folderSize) : '--') : `${niceBytes(item.size)}`}
</TableCell>
)}
{hideColList.indexOf('dateAdded') < 0 && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,54 @@ import { faMobile, faLaptop } from '@fortawesome/free-solid-svg-icons';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import { styles } from '../styles/FileExplorerTableFooterStatusBarRender';
import { getPluralText } from '../../../utils/funcs';
import { getPluralText, niceBytes } from '../../../utils/funcs';
import { DEVICE_TYPE } from '../../../enums';
import { DEVICES_LABEL } from '../../../constants';
import { calculateFolderSize } from '../../../utils/files';

class FileExplorerTableFooterStatusBarRender extends PureComponent {
getDirectoryListStats = () => {
const { directoryLists } = this.props;

let directories = 0;
let files = 0;
let totalSize = 0;

(directoryLists.nodes || []).map((a) => {
if (a.isFolder) {
directories += 1;
} else {
files += 1;
totalSize += a.size;
}

return a;
});

const total = directories + files;

return { total, directories, files };
return { total, directories, files, totalSize };
};

getSelectedDirectoryStats = () => {
getSelectedDirectoryStats = async () => {
const { directoryLists } = this.props;

const total = directoryLists.queue.selected.length;
const selected = directoryLists.queue.selected;
const total = selected.length;
let totalSize = 0;

for (const path of selected) {
const node = directoryLists.nodes.find((n) => n.path === path);
if (node) {
if (node.isFolder) {
totalSize += await calculateFolderSize(node.path);
} else {
totalSize += node.size;
}
}
}

return { total };
return { total, totalSize };
};

RenderDeviceName = () => {
Expand Down Expand Up @@ -69,8 +85,8 @@ class FileExplorerTableFooterStatusBarRender extends PureComponent {
render() {
const { classes: styles, fileTransferClipboard } = this.props;

const { directories, files, total } = this.getDirectoryListStats();
const { total: selectedTotal } = this.getSelectedDirectoryStats();
const { directories, files, total, totalSize } = this.getDirectoryListStats();
const { total: selectedTotal, totalSize: selectedTotalSize } = this.getSelectedDirectoryStats();
const fileTransferClipboardLength = fileTransferClipboard.queue.length;
const { RenderDeviceName } = this;

Expand All @@ -80,7 +96,7 @@ class FileExplorerTableFooterStatusBarRender extends PureComponent {
<RenderDeviceName />

{selectedTotal > 0 ? (
<Fragment>{`${selectedTotal} of ${total} selected`}</Fragment>
<Fragment>{`${selectedTotal} of ${total} selected, ${niceBytes(selectedTotalSize)}`}</Fragment>
) : (
<Fragment>{`${total} ${getPluralText(
'item',
Expand All @@ -89,7 +105,7 @@ class FileExplorerTableFooterStatusBarRender extends PureComponent {
'directory',
directories,
'directories'
)}, ${files} ${getPluralText('file', files)})`}</Fragment>
)}, ${files} ${getPluralText('file', files)}, ${niceBytes(totalSize)})`}</Fragment>
)}
{`, ${fileTransferClipboardLength} ${getPluralText(
'item',
Expand Down
42 changes: 42 additions & 0 deletions app/utils/files.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { join, parse } from 'path';
import { homedir as homedirOs } from 'os';
import { APP_BUNDLE_ID } from '../constants/meta';
import fs from 'fs';

const homeDir = homedirOs();

Expand Down Expand Up @@ -52,3 +53,44 @@ export const getExtension = (fileName, isFolder) => {
export const pathInfo = (filePath) => {
return parse(filePath);
};

export const calculateFolderSize = (folderPath) => {
return new Promise((resolve, reject) => {
let totalSize = 0;

fs.readdir(folderPath, (err, files) => {
if (err) {
return reject(err);
}

let pending = files.length;
if (!pending) {
return resolve(totalSize);
}

files.forEach((file) => {
const filePath = join(folderPath, file);

fs.stat(filePath, (err, stats) => {
if (err) {
return reject(err);
}

if (stats.isDirectory()) {
calculateFolderSize(filePath).then((size) => {
totalSize += size;
if (!--pending) {
resolve(totalSize);
}
}).catch(reject);
} else {
totalSize += stats.size;
if (!--pending) {
resolve(totalSize);
}
}
});
});
});
});
};