diff --git a/src/components/FileExplorer.js b/src/components/FileExplorer.js
index 10930e8..fb56863 100644
--- a/src/components/FileExplorer.js
+++ b/src/components/FileExplorer.js
@@ -6,6 +6,7 @@ import { FileExplorer as FileExplorerCore } from '../driver/core'
import SearchBar from './SearchBar'
import Node from './Node'
+import LoadingIndicator from './LoadingIndicator'
import cx from '../utils/cx'
@@ -45,44 +46,53 @@ export default class FileExplorer extends React.Component {
execAfterRender()
}
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.treeData !== this.props.treeData) {
+ const { init } = nextProps
+ init()
+ }
+ }
+
componentDidUpdate() {
const { execAfterRender } = this.props
execAfterRender()
}
+ renderFiles(visibleNodes, onNodeClick) {
+ const { nodes, depths, focusedNode, expandedNodes } = visibleNodes
+ if (nodes.length === 0) {
+ return (
+
+ )
+ }
+ return (
+
+ {nodes.map(node => (
+
+ ))}
+
+ )
+ }
+
render() {
- const {
- visibleNodes,
- freeze,
- handleKeyDown,
- handleSearchKeyChange,
- onNodeClick
- } = this.props
- const {
- nodes,
- depths,
- focusedNode,
- expandedNodes,
- } = visibleNodes || {}
+ const { stateText, visibleNodes, freeze, handleKeyDown, handleSearchKeyChange, onNodeClick } = this.props
return (
- {!visibleNodes || !nodes || nodes.length === 0 ? (
-
- ) : (
-
- {nodes.map(node => (
-
- ))}
-
- )}
+ {
+ !visibleNodes || stateText
+ ?
+ : this.renderFiles(visibleNodes, onNodeClick)
+ }
)
}
diff --git a/src/components/LoadingIndicator.js b/src/components/LoadingIndicator.js
new file mode 100644
index 0000000..dfecccd
--- /dev/null
+++ b/src/components/LoadingIndicator.js
@@ -0,0 +1,13 @@
+import React from 'react'
+import Icon from './Icon';
+
+export default function LoadingIndicator({ text }) {
+ return (
+
+ )
+}
diff --git a/src/components/SideBar.js b/src/components/SideBar.js
index b4158a9..43069b3 100644
--- a/src/components/SideBar.js
+++ b/src/components/SideBar.js
@@ -94,9 +94,8 @@ export default class Gitako extends React.PureComponent {
{metaData && }
{errorDueToAuth && this.renderAccessDeniedError()}
{metaData &&
- treeData && (
-
- )}
+
+ }
)
}
diff --git a/src/content.less b/src/content.less
index 99ab67b..5520364 100644
--- a/src/content.less
+++ b/src/content.less
@@ -215,6 +215,25 @@
padding: 4px 10px;
}
+ .loading-indicator-container {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .loading-indicator {
+ display: flex;
+ align-items: center;
+ }
+
+ .loading-indicator-icon {
+ width: 20px;
+ height: 20px;
+ animation: rotate 2s infinite linear;
+ }
+ }
+
.file-explorer {
width: 100%;
height: 100%;
@@ -373,3 +392,11 @@
}
}
}
+
+@keyframes rotate {
+ from {
+ transform: rotateZ(0);
+ } to {
+ transform: rotateZ(360deg);
+ }
+}
diff --git a/src/driver/core/FileExplorer.js b/src/driver/core/FileExplorer.js
index 12b5b8c..6db7b95 100644
--- a/src/driver/core/FileExplorer.js
+++ b/src/driver/core/FileExplorer.js
@@ -21,9 +21,15 @@ const tasksAfterRender = []
const visibleNodesGenerator = new VisibleNodesGenerator()
const init = dispatch => () => dispatch(async (state, { treeData, metaData, compressSingletonFolder }) => {
+ if (!treeData) {
+ dispatch(setStateText, 'Fetching Tree Data...')
+ return
+ }
+ dispatch(setStateText, 'Rendering File List...')
const { root } = treeParser.parse(treeData, metaData)
visibleNodesGenerator.setCompress(compressSingletonFolder)
await visibleNodesGenerator.plantTree(root)
+ dispatch(setStateText, null)
const currentPath = URLHelper.getCurrentPath(true)
if (currentPath.length) {
const nodeExpandedTo = visibleNodesGenerator.expandTo(currentPath.join('/'))
@@ -44,6 +50,10 @@ const execAfterRender = dispatch => () => {
tasksAfterRender.length = 0
}
+const setStateText = dispatch => text => dispatch({
+ stateText: text,
+})
+
const handleKeyDown = dispatch => ({ key }) => dispatch(({ visibleNodes: { nodes, focusedNode, expandedNodes, depths } }) => {
if (focusedNode) {
const focusedNodeIndex = nodes.indexOf(focusedNode)
@@ -174,6 +184,7 @@ const updateVisibleNodes = dispatch => () => {
export default {
init,
execAfterRender,
+ setStateText,
handleKeyDown,
handleSearchKeyChange,
setExpand,
diff --git a/src/driver/core/SideBar.js b/src/driver/core/SideBar.js
index df1ad1a..4bf3ae7 100644
--- a/src/driver/core/SideBar.js
+++ b/src/driver/core/SideBar.js
@@ -16,15 +16,9 @@ const init = dispatch => async () => {
dispatch(setMetaData, metaData)
const shouldShow = URLHelper.isInCodePage(metaData)
dispatch(setShouldShow, shouldShow)
- if (shouldShow) {
- DOMHelper.mountTopProgressBar()
- }
const treeData = await GitHubHelper.getTreeData({ ...metaData, accessToken })
dispatch({ logoContainerElement: DOMHelper.insertLogoMountPoint() })
dispatch({ treeData })
- if (shouldShow) {
- DOMHelper.unmountTopProgressBar()
- }
} catch (err) {
// TODO: detect request time exceeds limit
if (err.message === NOT_FOUND || err.message === BAD_CREDENTIALS) {