feat: loading indicator when expanding node

This commit is contained in:
EnixCoda 2018-09-15 16:15:12 +08:00
parent 5b1a7c6b89
commit 48e213a158
2 changed files with 55 additions and 5 deletions

View file

@ -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 (
<div className={cx(`node-item-row`, { focused })}>
<div className={'node-item'}>
<LoadingIndicator text={name} />
</div>
</div>
)
}
return (
<div className={cx(`node-item-row`, { focused })} title={path}>
<a href={node.url} onClick={this.onClick}>

View file

@ -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,
}