summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/gitbook-core/src/actions/TYPES.js20
-rw-r--r--packages/gitbook-core/src/actions/history.js (renamed from packages/gitbook-core/src/actions/navigation.js)33
-rw-r--r--packages/gitbook-core/src/components/PJAXWrapper.js4
-rw-r--r--packages/gitbook-core/src/lib/createContext.js4
-rw-r--r--packages/gitbook-core/src/lib/renderWithContext.js6
-rw-r--r--packages/gitbook-core/src/reducers/history.js (renamed from packages/gitbook-core/src/reducers/navigation.js)28
-rw-r--r--packages/gitbook-core/src/reducers/index.js2
-rw-r--r--packages/gitbook-core/src/shapes/History.js11
-rw-r--r--packages/gitbook-core/src/shapes/Location.js12
-rw-r--r--packages/gitbook-core/src/shapes/index.js2
-rw-r--r--packages/gitbook-plugin-search/src/index.js4
-rw-r--r--packages/gitbook-plugin-theme-default/less/LoadingBar.less30
-rw-r--r--packages/gitbook-plugin-theme-default/less/main.less1
-rw-r--r--packages/gitbook-plugin-theme-default/less/variables.less4
-rw-r--r--packages/gitbook-plugin-theme-default/src/components/LoadingBar.js124
-rw-r--r--packages/gitbook-plugin-theme-default/src/components/Theme.js9
16 files changed, 239 insertions, 55 deletions
diff --git a/packages/gitbook-core/src/actions/TYPES.js b/packages/gitbook-core/src/actions/TYPES.js
index f49b4bb..9876057 100644
--- a/packages/gitbook-core/src/actions/TYPES.js
+++ b/packages/gitbook-core/src/actions/TYPES.js
@@ -1,16 +1,16 @@
module.exports = {
// Components
- REGISTER_COMPONENT: 'components/register',
- UNREGISTER_COMPONENT: 'components/unregister',
+ REGISTER_COMPONENT: 'components/register',
+ UNREGISTER_COMPONENT: 'components/unregister',
// Navigation
- NAVIGATION_ACTIVATE: 'navigation/activate',
- NAVIGATION_DEACTIVATE: 'navigation/deactivate',
- NAVIGATION_LISTEN: 'navigation/listen',
- NAVIGATION_UPDATE: 'navigation/update',
- PAGE_FETCH_START: 'navigation/fetch:start',
- PAGE_FETCH_END: 'navigation/fetch:end',
- PAGE_FETCH_ERROR: 'navigation/fetch:error',
+ HISTORY_ACTIVATE: 'history/activate',
+ HISTORY_DEACTIVATE: 'history/deactivate',
+ HISTORY_LISTEN: 'history/listen',
+ HISTORY_UPDATE: 'history/update',
+ PAGE_FETCH_START: 'history/fetch:start',
+ PAGE_FETCH_END: 'history/fetch:end',
+ PAGE_FETCH_ERROR: 'history/fetch:error',
// i18n
- I18N_REGISTER_LOCALE: 'i18n/register:locale'
+ I18N_REGISTER_LOCALE: 'i18n/register:locale'
};
diff --git a/packages/gitbook-core/src/actions/navigation.js b/packages/gitbook-core/src/actions/history.js
index 26bfa59..a7cf228 100644
--- a/packages/gitbook-core/src/actions/navigation.js
+++ b/packages/gitbook-core/src/actions/history.js
@@ -10,16 +10,16 @@ const SUPPORTED = (
);
/**
- * Initialize the navigation
+ * Initialize the history
*/
function activate() {
return (dispatch, getState) => {
dispatch({
- type: ACTION_TYPES.NAVIGATION_ACTIVATE,
+ type: ACTION_TYPES.HISTORY_ACTIVATE,
listener: (location) => {
location = Location.fromNative(location);
- const prevLocation = getState().navigation.location;
+ const prevLocation = getState().history.location;
// Fetch page if required
if (!prevLocation || location.pathname !== prevLocation.pathname) {
@@ -31,7 +31,7 @@ function activate() {
// Update the location
dispatch({
- type: ACTION_TYPES.NAVIGATION_UPDATE,
+ type: ACTION_TYPES.HISTORY_UPDATE,
location
});
}
@@ -48,13 +48,13 @@ function activate() {
*/
function emit(to) {
return (dispatch, getState) => {
- const { listeners, history } = getState().navigation;
+ const { listeners, client } = getState().history;
- if (!history) {
+ if (!client) {
return;
}
- const location = Location.fromNative(history.location);
+ const location = Location.fromNative(client.location);
to = to || listeners;
@@ -65,24 +65,24 @@ function emit(to) {
}
/**
- * Cleanup the navigation
+ * Cleanup the history
*/
function deactivate() {
- return { type: ACTION_TYPES.NAVIGATION_DEACTIVATE };
+ return { type: ACTION_TYPES.HISTORY_DEACTIVATE };
}
/**
- * Push a new url into the navigation
+ * Push a new url into the history
* @param {String|Location} location
* @return {Action} action
*/
function push(location) {
return (dispatch, getState) => {
- const { history } = getState().navigation;
+ const { client } = getState().history;
location = Location.fromNative(location);
if (SUPPORTED) {
- history.push(location.toNative());
+ client.push(location.toNative());
} else {
redirect(location.toString());
}
@@ -90,17 +90,17 @@ function push(location) {
}
/**
- * Replace current state in navigation
+ * Replace current state in history
* @param {String|Location} location
* @return {Action} action
*/
function replace(location) {
return (dispatch, getState) => {
- const { history } = getState().navigation;
+ const { client } = getState().history;
location = Location.fromNative(location);
if (SUPPORTED) {
- history.replace(location.toNative());
+ client.replace(location.toNative());
} else {
redirect(location.toString());
}
@@ -125,7 +125,7 @@ function redirect(uri) {
*/
function listen(listener) {
return (dispatch, getState) => {
- dispatch({ type: ACTION_TYPES.NAVIGATION_LISTEN, listener });
+ dispatch({ type: ACTION_TYPES.HISTORY_LISTEN, listener });
// Trigger for existing listeners
dispatch(emit([ listener ]));
@@ -163,7 +163,6 @@ function fetchPage(pathname) {
.catch(
error => {
// dispatch(redirect(pathname));
- console.error(error);
dispatch({ type: ACTION_TYPES.PAGE_FETCH_ERROR, error });
}
);
diff --git a/packages/gitbook-core/src/components/PJAXWrapper.js b/packages/gitbook-core/src/components/PJAXWrapper.js
index d2eb456..6ed0697 100644
--- a/packages/gitbook-core/src/components/PJAXWrapper.js
+++ b/packages/gitbook-core/src/components/PJAXWrapper.js
@@ -1,6 +1,6 @@
const React = require('react');
const ReactRedux = require('react-redux');
-const Navigation = require('../actions/navigation');
+const History = require('../actions/history');
/**
* Check if an element is inside a link
@@ -83,7 +83,7 @@ const PJAXWrapper = React.createClass({
}
event.preventDefault();
- dispatch(Navigation.push(href));
+ dispatch(History.push(href));
},
componentDidMount() {
diff --git a/packages/gitbook-core/src/lib/createContext.js b/packages/gitbook-core/src/lib/createContext.js
index 87593e3..ba0c7e1 100644
--- a/packages/gitbook-core/src/lib/createContext.js
+++ b/packages/gitbook-core/src/lib/createContext.js
@@ -9,7 +9,7 @@ const composeReducer = require('./composeReducer');
const Components = require('../actions/components');
const I18n = require('../actions/i18n');
-const Navigation = require('../actions/navigation');
+const History = require('../actions/history');
const isBrowser = (typeof window !== 'undefined');
@@ -21,7 +21,7 @@ const isBrowser = (typeof window !== 'undefined');
const corePlugin = new Plugin({
reduce: coreReducers,
actions: {
- Components, I18n, Navigation
+ Components, I18n, History
}
});
diff --git a/packages/gitbook-core/src/lib/renderWithContext.js b/packages/gitbook-core/src/lib/renderWithContext.js
index f9a093c..c84c221 100644
--- a/packages/gitbook-core/src/lib/renderWithContext.js
+++ b/packages/gitbook-core/src/lib/renderWithContext.js
@@ -4,7 +4,7 @@ const { InjectedComponent } = require('../components/InjectedComponent');
const PJAXWrapper = require('../components/PJAXWrapper');
const I18nProvider = require('../components/I18nProvider');
const ContextProvider = require('../components/ContextProvider');
-const Navigation = require('../actions/navigation');
+const History = require('../actions/history');
const contextShape = require('../shapes/context');
const GitBookApplication = React.createClass({
@@ -15,12 +15,12 @@ const GitBookApplication = React.createClass({
componentDidMount() {
const { context } = this.props;
- context.dispatch(Navigation.activate());
+ context.dispatch(History.activate());
},
componentWillUnmount() {
const { context } = this.props;
- context.dispatch(Navigation.deactivate());
+ context.dispatch(History.deactivate());
},
render() {
diff --git a/packages/gitbook-core/src/reducers/navigation.js b/packages/gitbook-core/src/reducers/history.js
index 11774de..d78b158 100644
--- a/packages/gitbook-core/src/reducers/navigation.js
+++ b/packages/gitbook-core/src/reducers/history.js
@@ -4,7 +4,7 @@ const ACTION_TYPES = require('../actions/TYPES');
const isServerSide = (typeof window === 'undefined');
-const NavigationState = Record({
+const HistoryState = Record({
// Current location
location: null,
// Are we loading a new page
@@ -15,12 +15,12 @@ const NavigationState = Record({
listeners: List(),
// Function to call to stop listening
unlisten: null,
- // History instance
- history: null
+ // HistoryJS instance
+ client: null
});
-function reduceNavigation(state, action) {
- state = state || NavigationState();
+function reduceHistory(state, action) {
+ state = state || HistoryState();
switch (action.type) {
case ACTION_TYPES.PAGE_FETCH_START:
@@ -39,33 +39,33 @@ function reduceNavigation(state, action) {
error: action.error
});
- case ACTION_TYPES.NAVIGATION_ACTIVATE:
- const history = isServerSide ? createMemoryHistory() : createBrowserHistory();
- const unlisten = history.listen(action.listener);
+ case ACTION_TYPES.HISTORY_ACTIVATE:
+ const client = isServerSide ? createMemoryHistory() : createBrowserHistory();
+ const unlisten = client.listen(action.listener);
// We can't use .merge since it convert history to an immutable
const newState = state
- .set('history', history)
+ .set('client', client)
.set('unlisten', unlisten);
return newState;
- case ACTION_TYPES.NAVIGATION_DEACTIVATE:
+ case ACTION_TYPES.HISTORY_DEACTIVATE:
if (state.unlisten) {
state.unlisten();
}
return state.merge({
- history: null,
+ client: null,
unlisten: null
});
- case ACTION_TYPES.NAVIGATION_UPDATE:
+ case ACTION_TYPES.HISTORY_UPDATE:
return state.merge({
location: action.location
});
- case ACTION_TYPES.NAVIGATION_LISTEN:
+ case ACTION_TYPES.HISTORY_LISTEN:
return state.merge({
listeners: state.listeners.push(action.listener)
});
@@ -76,4 +76,4 @@ function reduceNavigation(state, action) {
}
}
-module.exports = reduceNavigation;
+module.exports = reduceHistory;
diff --git a/packages/gitbook-core/src/reducers/index.js b/packages/gitbook-core/src/reducers/index.js
index 335a1cf..fc80b4a 100644
--- a/packages/gitbook-core/src/reducers/index.js
+++ b/packages/gitbook-core/src/reducers/index.js
@@ -3,7 +3,7 @@ const createReducer = require('../lib/createReducer');
module.exports = composeReducer(
createReducer('components', require('./components')),
- createReducer('navigation', require('./navigation')),
+ createReducer('history', require('./history')),
createReducer('i18n', require('./i18n')),
// GitBook JSON
createReducer('config', require('./config')),
diff --git a/packages/gitbook-core/src/shapes/History.js b/packages/gitbook-core/src/shapes/History.js
new file mode 100644
index 0000000..1b59ea0
--- /dev/null
+++ b/packages/gitbook-core/src/shapes/History.js
@@ -0,0 +1,11 @@
+const React = require('react');
+const locationShape = require('./Location');
+const {
+ bool,
+ shape
+} = React.PropTypes;
+
+module.exports = shape({
+ loading: bool,
+ location: locationShape
+});
diff --git a/packages/gitbook-core/src/shapes/Location.js b/packages/gitbook-core/src/shapes/Location.js
new file mode 100644
index 0000000..13e0a34
--- /dev/null
+++ b/packages/gitbook-core/src/shapes/Location.js
@@ -0,0 +1,12 @@
+const React = require('react');
+const { map } = require('react-immutable-proptypes');
+const {
+ string,
+ shape
+} = React.PropTypes;
+
+module.exports = shape({
+ pathname: string,
+ hash: string,
+ query: map
+});
diff --git a/packages/gitbook-core/src/shapes/index.js b/packages/gitbook-core/src/shapes/index.js
index 2faddbc..8b28842 100644
--- a/packages/gitbook-core/src/shapes/index.js
+++ b/packages/gitbook-core/src/shapes/index.js
@@ -8,6 +8,8 @@ module.exports = {
Context: require('./Context'),
Page: require('./Page'),
File: require('./File'),
+ History: require('./History'),
+ Location: require('./Location'),
Readme: require('./Readme'),
Summary: require('./Summary'),
SummaryPart: require('./SummaryPart'),
diff --git a/packages/gitbook-plugin-search/src/index.js b/packages/gitbook-plugin-search/src/index.js
index bc6c406..298c088 100644
--- a/packages/gitbook-plugin-search/src/index.js
+++ b/packages/gitbook-plugin-search/src/index.js
@@ -18,9 +18,9 @@ const onLocationChange = (location, dispatch) => {
};
module.exports = GitBook.createPlugin({
- activate: (dispatch, getState, { Navigation, Components }) => {
+ activate: (dispatch, getState, { History, Components }) => {
// Register the navigation handler
- dispatch(Navigation.listen(onLocationChange));
+ dispatch(History.listen(onLocationChange));
// Register components
dispatch(Components.registerComponent(SearchInput, { role: 'search:input' }));
diff --git a/packages/gitbook-plugin-theme-default/less/LoadingBar.less b/packages/gitbook-plugin-theme-default/less/LoadingBar.less
new file mode 100644
index 0000000..1fca2ea
--- /dev/null
+++ b/packages/gitbook-plugin-theme-default/less/LoadingBar.less
@@ -0,0 +1,30 @@
+.LoadingBar {
+ pointer-events: none;
+ transition: 400ms linear all;
+
+ .LoadingBar-Bar {
+ background: @color-primary;
+ height: 2px;
+
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 10000;
+ display: none;
+ width: 100%;
+ border-radius: 0 1px 1px 0;
+ transition: width 350ms;
+ }
+
+ .LoadingBar-Shadow {
+ content: '';
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 70px;
+ height: 2px;
+ border-radius: 50%;
+ opacity: .45;
+ box-shadow: @color-primary 1px 0 6px 1px;
+ }
+}
diff --git a/packages/gitbook-plugin-theme-default/less/main.less b/packages/gitbook-plugin-theme-default/less/main.less
index 6b50858..960477d 100644
--- a/packages/gitbook-plugin-theme-default/less/main.less
+++ b/packages/gitbook-plugin-theme-default/less/main.less
@@ -14,6 +14,7 @@
@import "Search.less";
@import "Body.less";
@import "Dropdown.less";
+@import "LoadingBar.less";
* {
.box-sizing(border-box);
diff --git a/packages/gitbook-plugin-theme-default/less/variables.less b/packages/gitbook-plugin-theme-default/less/variables.less
index c8dc452..62f4f52 100644
--- a/packages/gitbook-plugin-theme-default/less/variables.less
+++ b/packages/gitbook-plugin-theme-default/less/variables.less
@@ -1,3 +1,5 @@
+// Colors
+@color-primary: hsl(207, 100%, 50%); // rgb(44, 106, 254);
// Fonts
@font-family-serif: Georgia, serif;
@font-family-sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
@@ -16,7 +18,7 @@
@summary-article-padding-v: 10px;
@summary-article-padding-h: 15px;
@summary-article-color: hsl(207, 15%, 25%);
-@summary-article-hover-color: hsl(207, 100%, 50%);
+@summary-article-hover-color: @color-primary;
@summary-article-active-color: @summary-article-color;
@summary-article-active-background: #f5f5f5;
// Page
diff --git a/packages/gitbook-plugin-theme-default/src/components/LoadingBar.js b/packages/gitbook-plugin-theme-default/src/components/LoadingBar.js
new file mode 100644
index 0000000..11e1ddb
--- /dev/null
+++ b/packages/gitbook-plugin-theme-default/src/components/LoadingBar.js
@@ -0,0 +1,124 @@
+const GitBook = require('gitbook-core');
+const { React } = GitBook;
+
+/**
+ * Displays a progress bar (YouTube-like) at the top of container
+ * Based on https://github.com/lonelyclick/react-loading-bar/blob/master/src/Loading.jsx
+ */
+const LoadingBar = React.createClass({
+ propTypes: {
+ show: React.PropTypes.bool
+ },
+
+ getDefaultProps() {
+ return {
+ show: false
+ };
+ },
+
+ getInitialState() {
+ return {
+ size: 0,
+ disappearDelayHide: false, // when dispappear, first transition then display none
+ percent: 0,
+ appearDelayWidth: 0 // when appear, first display block then transition width
+ };
+ },
+
+ componentWillReceiveProps(nextProps) {
+ const { show } = nextProps;
+
+ if (show) {
+ this.show();
+ } else {
+ this.hide();
+ }
+ },
+
+ shouldComponentUpdate(nextProps, nextState) {
+ return true; // !shallowEqual(nextState, this.state)
+ },
+
+ show() {
+ let { size, percent } = this.state;
+
+ const appearDelayWidth = size === 0;
+ percent = calculatePercent(percent);
+
+ this.setState({
+ size: ++size,
+ appearDelayWidth,
+ percent
+ });
+
+ if (appearDelayWidth) {
+ setTimeout(() => {
+ this.setState({
+ appearDelayWidth: false
+ });
+ });
+ }
+ },
+
+ hide() {
+ let { size } = this.state;
+
+ if (--size < 0) {
+ this.setState({ size: 0 });
+ return;
+ }
+
+ this.setState({
+ size: 0,
+ disappearDelayHide: true,
+ percent: 1
+ });
+
+ setTimeout(() => {
+ this.setState({
+ disappearDelayHide: false,
+ percent: 0
+ });
+ }, 500);
+ },
+
+ getBarStyle() {
+ const { disappearDelayHide, appearDelayWidth, percent } = this.state;
+
+ return {
+ width: appearDelayWidth ? 0 : percent * 100 + '%',
+ display: disappearDelayHide || percent > 0 ? 'block' : 'none'
+ };
+ },
+
+ getShadowStyle() {
+ const { percent, disappearDelayHide } = this.state;
+
+ return {
+ display: disappearDelayHide || percent > 0 ? 'block' : 'none'
+ };
+ },
+
+ render() {
+ return (
+ <div className="LoadingBar">
+ <div className="LoadingBar-Bar" style={this.getBarStyle()}>
+ <div className="LoadingBar-Shadow"
+ style={this.getShadowStyle()}>
+ </div>
+ </div>
+ </div>
+ );
+ }
+});
+
+function calculatePercent(percent) {
+ percent = percent || 0;
+
+ // How much of remaining bar we advance
+ const progress = 0.1 + Math.random() * 0.3;
+
+ return percent + progress * (1 - percent);
+}
+
+module.exports = LoadingBar;
diff --git a/packages/gitbook-plugin-theme-default/src/components/Theme.js b/packages/gitbook-plugin-theme-default/src/components/Theme.js
index bf00502..741b3cc 100644
--- a/packages/gitbook-plugin-theme-default/src/components/Theme.js
+++ b/packages/gitbook-plugin-theme-default/src/components/Theme.js
@@ -3,6 +3,7 @@ const { React } = GitBook;
const Sidebar = require('./Sidebar');
const Body = require('./Body');
+const LoadingBar = require('./LoadingBar');
const Theme = React.createClass({
propTypes: {
@@ -10,16 +11,18 @@ const Theme = React.createClass({
page: GitBook.Shapes.Page,
summary: GitBook.Shapes.Summary,
readme: GitBook.Shapes.Readme,
+ history: GitBook.Shapes.History,
sidebar: React.PropTypes.object,
// Other props
children: React.PropTypes.node
},
render() {
- const { page, summary, children, sidebar, readme } = this.props;
+ const { page, summary, children, sidebar, readme, history } = this.props;
return (
<GitBook.FlexLayout column className="GitBook book">
+ <LoadingBar show={history.loading} />
<GitBook.Head
title={page.title}
titleTemplate="%s - GitBook" />
@@ -43,6 +46,6 @@ const Theme = React.createClass({
}
});
-module.exports = GitBook.connect(Theme, ({page, summary, sidebar, readme}) => {
- return { page, summary, sidebar, readme };
+module.exports = GitBook.connect(Theme, ({page, summary, sidebar, readme, history}) => {
+ return { page, summary, sidebar, readme, history };
});