From 48e213a1588a53028843f47c8db57e529b007b18 Mon Sep 17 00:00:00 2001 From: EnixCoda Date: Sat, 15 Sep 2018 16:15:12 +0800 Subject: [PATCH] feat: loading indicator when expanding node --- src/components/Node.js | 14 +++++++++- src/driver/core/FileExplorer.js | 46 ++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/components/Node.js b/src/components/Node.js index fe2aeae..26e8e08 100644 --- a/src/components/Node.js +++ b/src/components/Node.js @@ -4,6 +4,7 @@ import Icon from './Icon' import cx from '../utils/cx' import DOMHelper from '../utils/DOMHelper' +import LoadingIndicator from './LoadingIndicator'; function getIconType(node) { switch (node.type) { @@ -26,7 +27,18 @@ export default class Node extends React.PureComponent { render() { const { node, depth, expanded, focused } = this.props - const { name, path } = node + const { name, path, virtual } = node + if (virtual) { + // this is not a real node + // for now, all virtual nodes are indicators for pending state + return ( +
+
+ +
+
+ ) + } return (
diff --git a/src/driver/core/FileExplorer.js b/src/driver/core/FileExplorer.js index 928757f..67762f4 100644 --- a/src/driver/core/FileExplorer.js +++ b/src/driver/core/FileExplorer.js @@ -143,16 +143,38 @@ const handleSearchKeyChange = dispatch => async event => { dispatch(updateVisibleNodes) } +const delayExpandThreshold = 400 +function shouldDelayExpand(node) { + return visibleNodesGenerator.visibleNodes.expandedNodes.has(node) + && node.contents.length > delayExpandThreshold +} + const setExpand = dispatch => (node, expand) => { visibleNodesGenerator.setExpand(node, expand) - dispatch(focusNode, node) - tasksAfterRender.push(DOMHelper.focusSearchInput) + const applyChanges = () => { + dispatch(focusNode, node) + tasksAfterRender.push(DOMHelper.focusSearchInput) + } + if (shouldDelayExpand(node)) { + dispatch(mountExpandingIndicator, node) + tasksAfterRender.push(() => setTimeout(applyChanges, 0)) + } else { + applyChanges() + } } const toggleNodeExpansion = dispatch => (node, skipScrollToNode) => { visibleNodesGenerator.toggleExpand(node) - dispatch(focusNode, node, skipScrollToNode) - tasksAfterRender.push(DOMHelper.focusFileExplorer) + const applyChanges = () => { + dispatch(focusNode, node, skipScrollToNode) + tasksAfterRender.push(DOMHelper.focusFileExplorer) + } + if (shouldDelayExpand(node)) { + dispatch(mountExpandingIndicator, node) + tasksAfterRender.push(() => setTimeout(applyChanges, 0)) + } else { + applyChanges() + } } const focusNode = dispatch => (node, skipScroll) => dispatch(({ visibleNodes: { nodes } }) => { @@ -177,6 +199,21 @@ const onNodeClick = dispatch => (node) => { } } +const mountExpandingIndicator = dispatch => node => dispatch(({ visibleNodes }) => { + const dummyVisibleNodes = { + ...visibleNodes, + nodes: visibleNodes.nodes.slice(), + } + dummyVisibleNodes.nodes.splice( + dummyVisibleNodes.nodes.indexOf(node) + 1, + 0, + { virtual: true, name: 'Loading' }, + ) + return { + visibleNodes: dummyVisibleNodes + } +}) + const updateVisibleNodes = dispatch => () => { const { visibleNodes } = visibleNodesGenerator dispatch({ visibleNodes }) @@ -193,4 +230,5 @@ export default { focusNode, onNodeClick, updateVisibleNodes, + mountExpandingIndicator, }