refactor(driver): split core and link

This commit is contained in:
EnixCoda 2018-06-17 20:40:51 +08:00
parent 1fea1072a7
commit ac3505f859
3 changed files with 102 additions and 81 deletions

View file

@ -1,13 +1,12 @@
import React from 'react'
export default function(core) {
return function(ComponentClass) {
return class Driven extends React.PureComponent {
export default function connect(core) {
return function linkComponent(ComponentClass) {
return class AwesomeApp extends React.PureComponent {
static displayName = `Driven${ComponentClass.name}`
state = {}
dispatch = this.setState.bind(this)
boundCore = core(this.dispatch)
boundCore = core(this)
render() {
return (

View file

@ -1,101 +1,103 @@
import link from './link'
import DOMHelper, { REPO_TYPE_PRIVATE } from '../utils/DOMHelper'
import GitHubHelper, { NOT_FOUND, BAD_CREDENTIALS } from '../utils/GitHubHelper'
import storageHelper from '../utils/storageHelper'
import URLHelper from '../utils/URLHelper'
import keyHelper from '../utils/keyHelper'
export default function(dispatch) {
const init = async () => {
try {
DOMHelper.decorateGitHubPageContent()
const metaData = URLHelper.parse()
setMetaData(metaData)
const [accessToken, shortcut] = await Promise.all([
storageHelper.getAccessToken(),
storageHelper.getShortcut(),
])
dispatch({ hasAccessToken: Boolean(accessToken), toggleShowSideBarShortcut: shortcut })
const metaDataFromAPI = await GitHubHelper.getRepoMeta({ ...metaData, accessToken })
const branchName = metaData.branchName || metaDataFromAPI['default_branch']
Object.assign(metaData, { branchName, api: metaDataFromAPI })
setMetaData(metaData)
const shouldShow = URLHelper.isInCodePage(metaData)
setShouldShow(shouldShow)
if (shouldShow) {
DOMHelper.mountTopProgressBar()
}
const treeData = await GitHubHelper.getTreeData({ ...metaData, accessToken })
dispatch({ logoContainerElement: DOMHelper.insertLogo() })
dispatch({ treeData })
if (shouldShow) {
DOMHelper.unmountTopProgressBar()
}
} catch (err) {
// TODO: detect request time exceeds limit
if (err.message === NOT_FOUND || err.message === BAD_CREDENTIALS) {
const repoPageType = await DOMHelper.getRepoPageType()
const errorDueToAuth = repoPageType === REPO_TYPE_PRIVATE || err.message === BAD_CREDENTIALS
dispatch({
showSettings: repoPageType !== null,
errorDueToAuth,
})
setShouldShow(errorDueToAuth)
} else {
console.error(err)
setShouldShow(false)
}
const init = dispatch => async () => {
try {
DOMHelper.decorateGitHubPageContent()
const metaData = URLHelper.parse()
dispatch(setMetaData, metaData)
const [accessToken, shortcut] = await Promise.all([
storageHelper.getAccessToken(),
storageHelper.getShortcut(),
])
dispatch({ hasAccessToken: Boolean(accessToken), toggleShowSideBarShortcut: shortcut })
const metaDataFromAPI = await GitHubHelper.getRepoMeta({ ...metaData, accessToken })
const branchName = metaData.branchName || metaDataFromAPI['default_branch']
Object.assign(metaData, { branchName, api: metaDataFromAPI })
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.insertLogo() })
dispatch({ treeData })
if (shouldShow) {
DOMHelper.unmountTopProgressBar()
}
} catch (err) {
// TODO: detect request time exceeds limit
if (err.message === NOT_FOUND || err.message === BAD_CREDENTIALS) {
const repoPageType = await DOMHelper.getRepoPageType()
const errorDueToAuth = repoPageType === REPO_TYPE_PRIVATE || err.message === BAD_CREDENTIALS
dispatch({
showSettings: repoPageType !== null,
errorDueToAuth,
})
dispatch(setShouldShow, errorDueToAuth)
} else {
console.error(err)
dispatch(setShouldShow, false)
}
}
}
const onPJAXEnd = () => {
dispatch(({ metaData }) => {
DOMHelper.mountTopProgressBar()
const mergedMetaData = { ...metaData, ...URLHelper.parse() }
setShouldShow(URLHelper.isInCodePage(mergedMetaData))
setMetaData(mergedMetaData)
DOMHelper.decorateGitHubPageContent()
DOMHelper.focusSearchInput()
})
}
const onPJAXEnd = dispatch => () => {
dispatch(({ metaData }) => {
DOMHelper.unmountTopProgressBar()
DOMHelper.decorateGitHubPageContent()
DOMHelper.focusSearchInput()
const mergedMetaData = { ...metaData, ...URLHelper.parse() }
dispatch(setShouldShow, URLHelper.isInCodePage(mergedMetaData))
dispatch(setMetaData, mergedMetaData)
})
}
const setShouldShow = shouldShow => {
dispatch({ shouldShow })
DOMHelper.setBodyIndent(shouldShow)
}
const toggleShowSideBar = () => dispatch(({ shouldShow }) => setShouldShow(!shouldShow))
const toggleShowSettings = () => dispatch(({ showSettings }) => ({ showSettings: !showSettings }))
const onHasAccessTokenChange = hasAccessToken => dispatch({ hasAccessToken })
const onKeyDown = e => {
dispatch(({ toggleShowSideBarShortcut }) => {
if (toggleShowSideBarShortcut) {
const keys = keyHelper.parseEvent(e)
if (keys === toggleShowSideBarShortcut) {
toggleShowSideBar()
}
const onKeyDown = dispatch => e => {
dispatch(({ toggleShowSideBarShortcut }) => {
if (toggleShowSideBarShortcut) {
const keys = keyHelper.parseEvent(e)
if (keys === toggleShowSideBarShortcut) {
dispatch(toggleShowSideBar)
}
})
}
}
})
}
const onShortcutChange = shortcut => dispatch({ toggleShowSideBarShortcut: shortcut })
const toggleShowSideBar = dispatch => () => dispatch(({ shouldShow }) => dispatch(setShouldShow, !shouldShow))
const onResize = size => dispatch({ size })
const setShouldShow = dispatch => shouldShow => {
dispatch({ shouldShow })
DOMHelper.setBodyIndent(shouldShow)
}
const setMetaData = metaData => dispatch({ metaData })
const onResize = dispatch => size => dispatch({ size })
return {
const toggleShowSettings = dispatch => () => dispatch(({ showSettings }) => ({ showSettings: !showSettings }))
const onHasAccessTokenChange = dispatch => hasAccessToken => dispatch({ hasAccessToken })
const onShortcutChange = dispatch => shortcut => dispatch({ toggleShowSideBarShortcut: shortcut })
const setMetaData = dispatch => metaData => dispatch({ metaData })
export default function(instance) {
return link(instance.setState.bind(instance), {
init,
onPJAXEnd,
onKeyDown,
setShouldShow,
toggleShowSideBar,
toggleShowSettings,
onHasAccessTokenChange,
onKeyDown,
onShortcutChange,
onResize,
setMetaData,
}
})
}

20
src/driver/link.js Normal file
View file

@ -0,0 +1,20 @@
export default function link(setState, sources) {
const wrappedMethods = {/* sources[key] -> wrappedMethods.method */}
const map = new Map(/* sources.creator -> wrappedMethods.method */)
function dispatch(...args) {
if (Object.values(sources).includes(args[0])) {
map.get(args[0])(...args.slice(1))
} else {
setState(...args)
}
}
Object.entries(sources).forEach(([key, createMethod]) => {
const method = createMethod(dispatch)
wrappedMethods[key] = method
map.set(createMethod, method)
})
return wrappedMethods
}