add lazy load option

This commit is contained in:
An Le Phu Nguyen 2015-10-04 00:36:02 +07:00
parent ac169ee16a
commit 576048baa8
10 changed files with 127 additions and 44 deletions

View File

@ -161,17 +161,19 @@ GitHub.prototype.getRepoFromPath = function(showInNonCodePage, currentRepo, toke
/**
* Retrieves the code tree of a repository.
* @param {Object} repo - the repo whose code tree is to be retrieved.
* @param {String} token - the access token.
* @param {Object} opts: { repo: repository, node(optional): selected node (null for resursively loading), token (optional): user access token, apiUrl (optional): base API URL }
* @param {Function} cb(err: error, tree: array (of arrays) of items)
*/
GitHub.prototype.getCodeTree = function(repo, token, cb) {
var self = this
, folders = { '': [] }
GitHub.prototype.getCodeTree = function(opts, cb) {
var self = this
, folders = { '': [] }
, repo = opts.repo
, token = opts.token
, encodedBranch = encodeURIComponent(decodeURIComponent(repo.branch))
, $dummyDiv = $('<div/>')
, $dummyDiv = $('<div/>')
getTree(encodedBranch + '?recursive=true', function(err, tree) {
var treePath = (opts.node && (opts.node.sha || encodedBranch)) || (encodedBranch + '?recursive=1')
getTree(treePath, function(err, tree) {
if (err) return cb(err)
fetchSubmodules(function(err, submodules) {
@ -192,6 +194,10 @@ GitHub.prototype.getCodeTree = function(repo, token, cb) {
// we're done
if (item === undefined) return cb(null, folders[''])
// includes parent path
if (opts.node && opts.node.path)
item.path = opts.node.path + '/' + item.path
path = item.path
type = item.type
index = path.lastIndexOf('/')
@ -201,10 +207,16 @@ GitHub.prototype.getCodeTree = function(repo, token, cb) {
item.text = name
item.icon = type // use `type` as class name for tree node
folders[path.substring(0, index)].push(item)
if (opts.node) {
// no hierarchy in lazy loading
folders[''].push(item)
}
else
folders[path.substring(0, index)].push(item)
if (type === 'tree') {
folders[item.path] = item.children = []
if (opts.node) item.children = true
else folders[item.path] = item.children = []
item.a_attr = { href: '#' }
}
else if (type === 'blob') {

View File

@ -1,6 +1,6 @@
{
"name": "Octotree",
"version": "1.7.2",
"version": "2.0.0",
"manifest_version": 2,
"author": "Buu Nguyen",
"description": "Display GitHub code in tree format",

View File

@ -2,17 +2,18 @@ const
PREFIX = 'octotree'
, STORE = {
TOKEN : 'octotree.github_access_token',
COLLAPSE : 'octotree.collapse',
TABSIZE : 'octotree.tabsize',
REMEMBER : 'octotree.remember',
LAZYLOAD : 'octotree.lazyload',
HOTKEYS : 'octotree.hotkeys',
GHEURLS : 'octotree.gheurls',
WIDTH : 'octotree.sidebar_width',
POPUP : 'octotree.popup_shown',
SHOWN : 'octotree.sidebar_shown',
NONCODE : 'octotree.noncode_shown',
TOKEN : 'octotree.github_access_token',
COLLAPSE : 'octotree.collapse',
TABSIZE : 'octotree.tabsize',
REMEMBER : 'octotree.remember',
LAZYLOAD : 'octotree.lazyload',
RECURSIVE : 'octotree.recursive',
HOTKEYS : 'octotree.hotkeys',
GHEURLS : 'octotree.gheurls',
WIDTH : 'octotree.sidebar_width',
POPUP : 'octotree.popup_shown',
SHOWN : 'octotree.sidebar_shown',
NONCODE : 'octotree.noncode_shown',
}
, DEFAULTS = {
@ -21,6 +22,7 @@ const
TABSIZE : '',
REMEMBER : false,
LAZYLOAD : false,
RECURSIVE: true,
// @ifdef SAFARI
HOTKEYS : '⌘+b, ⌃+b',
// @endif
@ -43,4 +45,5 @@ const
OPTS_CHANGE : 'octotree:change',
VIEW_READY : 'octotree:ready',
VIEW_CLOSE : 'octotree:close',
FETCH_ERROR : 'octotree:error'
}

View File

@ -11,7 +11,7 @@
"icon": "data/icons/icon48.png",
"icon64": "data/icons/icon64.png",
"license": "MIT",
"version": "1.7.2",
"version": "2.0.0",
"permissions": {
"cross-domain-content": ["https://api.github.com", "https://github.com"]
}

View File

@ -50,6 +50,9 @@ $(document).ready(function() {
showView(hasError ? errorView.$view : treeView.$view)
})
.on(EVENT.OPTS_CHANGE, optionsChanged)
.on(EVENT.FETCH_ERROR, function(event, err) {
errorView.show(err)
})
})
$document
@ -81,6 +84,9 @@ $(document).ready(function() {
key.unbind(value[0])
key(value[1], toggleSidebar)
break
case STORE.RECURSIVE:
reload = true
break
}
})
if (reload) tryLoadRepo(true)
@ -108,12 +114,9 @@ $(document).ready(function() {
if (repoChanged || reload === true) {
$document.trigger(EVENT.REQ_START)
currRepo = repo
treeView.showHeader(repo)
adapter.getCodeTree(repo, token, function(err, tree) {
if (err) errorView.show(err)
else treeView.show(repo, tree)
})
treeView.show(repo, token)
}
else treeView.syncSelection()
}

View File

@ -202,6 +202,11 @@
label {
font-weight: normal !important;
}
label.disabled {
color: gray;
}
input[type=text], textarea {
width: 100%;
}

View File

@ -13,9 +13,9 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleShortVersionString</key>
<string>1.7.2</string>
<string>2.0.0</string>
<key>CFBundleVersion</key>
<string>1.7.2</string>
<string>2.0.0</string>
<key>Chrome</key>
<dict/>
<key>Content</key>

View File

@ -53,7 +53,10 @@
<label><input type="checkbox" data-store="LAZYLOAD"> Only load tree when sidebar is open</label>
</div>
<div>
<label><input type="checkbox" data-store="COLLAPSE"> Collapse folders with single sub-folder</label>
<label><input type="checkbox" data-store="RECURSIVE"> Load repository recursively</label>
</div>
<div>
<label><input type="checkbox" data-store="COLLAPSE" data-trigger-disable="RECURSIVE"> Collapse folders with single sub-folder</label>
</div>
<div>
<div>

View File

@ -6,6 +6,23 @@ function OptionsView($dom, store) {
this.$view = $view
$(document).ready(function() {
function triggerChange(checkbox) {
var store = $(checkbox).data('store')
, checkboxs = $view.find('[data-trigger-disable=' + store + ']')
checkboxs.prop('disabled', !checkbox.checked).closest('label').toggleClass('disabled', !checkbox.checked)
}
eachOption(
function($elm) {
// triggers to disable all checkboxs having data-trigger-disable
$elm.change(function(event) {
triggerChange(event.target)
})
}
)
})
// hide options view when sidebar is hidden
$(document).on(EVENT.TOGGLE, function(event, visible) {
if (!visible) toggle(false)
@ -23,7 +40,8 @@ function OptionsView($dom, store) {
else {
eachOption(
function($elm, key, local, value, cb) {
if ($elm.is(':checkbox')) $elm.prop('checked', value)
// Original jQuery prop function doesn't trigger change event
if ($elm.is(':checkbox')) $elm.prop('checked', value).trigger("change")
else $elm.val(value)
cb()
},
@ -91,4 +109,4 @@ function OptionsView($dom, store) {
completeFn
)
}
}
}

View File

@ -74,15 +74,30 @@ TreeView.prototype.showHeader = function(repo) {
})
}
TreeView.prototype.show = function(repo, treeData) {
TreeView.prototype.show = function(repo, token) {
var self = this
, treeContainer = self.$view.find('.octotree_view_body')
, tree = treeContainer.jstree(true)
, collapseTree = self.store.get(STORE.COLLAPSE)
, recursiveLoad = self.store.get(STORE.RECURSIVE)
treeData = sort(treeData)
if (collapseTree) treeData = collapse(treeData)
tree.settings.core.data = treeData
function fetchData(node, success) {
var selectedNode = node.original
if (node.id === '#') selectedNode = {path: ''}
self.adapter.getCodeTree({ repo: repo, token: token, node: recursiveLoad ? null : selectedNode}, function(err, treeData) {
if (err) $(self).trigger(EVENT.FETCH_ERROR, [err])
else success(treeData)
})
}
tree.settings.core.data = function (node, cb) {
fetchData(node, function(treeData) {
treeData = sort(treeData)
if (collapseTree && recursiveLoad)
treeData = collapse(treeData)
cb(treeData)
})
}
treeContainer.one('refresh.jstree', function() {
self.syncSelection()
@ -97,7 +112,7 @@ TreeView.prototype.show = function(repo, treeData) {
return a.type === 'blob' ? 1 : -1
})
folder.forEach(function(item) {
if (item.type === 'tree') sort(item.children)
if (item.type === 'tree' && item.children !== true && item.children.length > 0) sort(item.children)
})
return folder
}
@ -119,17 +134,41 @@ TreeView.prototype.show = function(repo, treeData) {
TreeView.prototype.syncSelection = function() {
var tree = this.$view.find('.octotree_view_body').jstree(true)
, path = location.pathname
, path = decodeURIComponent(location.pathname)
, recursiveLoad = this.store.get(STORE.RECURSIVE)
if (!tree) return
tree.deselect_all()
// e.g. converts /buunguyen/octotree/type/branch/path to path
var match = path.match(/(?:[^\/]+\/){4}(.*)/)
, nodeId
if (match) {
nodeId = PREFIX + decodeURIComponent(match[1])
tree.select_node(nodeId)
tree.open_node(nodeId)
if (!match) return
currentPath = match[1]
// e.g. converts ["lib/controllers"] to ["lib", "lib/controllers"]
function createPaths(fullPath) {
var paths = fullPath.split("/")
, arrResult = [paths[0]]
paths.reduce(function(lastPath, curPath) {
var path = (lastPath + "/" + curPath)
arrResult.push(path)
return path
})
return arrResult
}
function openPathAtIndex (paths, index) {
nodeId = PREFIX + paths[index]
if (tree.get_node(nodeId)) {
tree.deselect_all()
tree.select_node(nodeId)
tree.open_node(nodeId, function(node){
if (index < paths.length - 1) openPathAtIndex(paths, index + 1)
})
}
}
var paths = recursiveLoad ? [currentPath] : createPaths(currentPath)
openPathAtIndex(paths, 0)
}