Improve option handling and GitLab styling
* Refactor storage support * Options except urls are per-site * Fix GitLab styling bug
This commit is contained in:
parent
f8161c02c7
commit
63e111e438
|
@ -50,8 +50,9 @@ By default, Octotree only works on `github.com` and `gitlab.com`. To support ent
|
||||||
|
|
||||||
### v2.0.0
|
### v2.0.0
|
||||||
* Support GitLab
|
* Support GitLab
|
||||||
* Modify Octotree options
|
* Support lazy-load individual folder (GitHub only)
|
||||||
* Support lazy-load individual folder (GitHub)
|
* Simplify Octotree options
|
||||||
|
* Support selecting different options for each host
|
||||||
|
|
||||||
### v1.7.2
|
### v1.7.2
|
||||||
* Fix bug long branches are not loaded correctly due to GitHub DOM change
|
* Fix bug long branches are not loaded correctly due to GitHub DOM change
|
||||||
|
|
92
gulpfile.js
92
gulpfile.js
|
@ -1,29 +1,31 @@
|
||||||
var gulp = require('gulp')
|
'use strict'
|
||||||
, path = require('path')
|
|
||||||
, merge = require('event-stream').merge
|
const gulp = require('gulp')
|
||||||
, map = require('map-stream')
|
const path = require('path')
|
||||||
, spawn = require('child_process').spawn
|
const merge = require('event-stream').merge
|
||||||
, $ = require('gulp-load-plugins')()
|
const map = require('map-stream')
|
||||||
|
const spawn = require('child_process').spawn
|
||||||
|
const $ = require('gulp-load-plugins')()
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
gulp.task('clean', function () {
|
gulp.task('clean', () => {
|
||||||
return pipe('./tmp', [$.clean()])
|
return pipe('./tmp', [$.clean()])
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('build', function (cb) {
|
gulp.task('build', (cb) => {
|
||||||
$.runSequence('clean', 'styles', 'chrome', 'opera', 'safari', 'firefox', cb)
|
$.runSequence('clean', 'styles', 'chrome', 'opera', 'safari', 'firefox', cb)
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('default', ['build'], function () {
|
gulp.task('default', ['build'], () => {
|
||||||
gulp.watch(['./libs/**/*', './src/**/*'], ['default'])
|
gulp.watch(['./libs/**/*', './src/**/*'], ['default'])
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('dist', ['build'], function (cb) {
|
gulp.task('dist', ['build'], (cb) => {
|
||||||
$.runSequence('firefox:xpi', 'chrome:zip', 'chrome:crx', 'opera:nex', cb)
|
$.runSequence('firefox:xpi', 'chrome:zip', 'chrome:crx', 'opera:nex', cb)
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('test', ['build'], function (cb) {
|
gulp.task('test', ['build'], (cb) => {
|
||||||
var ps = spawn(
|
const ps = spawn(
|
||||||
'./node_modules/.bin/mocha',
|
'./node_modules/.bin/mocha',
|
||||||
['--harmony', '--reporter', 'spec', '--bail', '--recursive', '--timeout', '-1']
|
['--harmony', '--reporter', 'spec', '--bail', '--recursive', '--timeout', '-1']
|
||||||
)
|
)
|
||||||
|
@ -32,62 +34,62 @@ gulp.task('test', ['build'], function (cb) {
|
||||||
ps.on('close', cb)
|
ps.on('close', cb)
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('styles', function () {
|
gulp.task('styles', () => {
|
||||||
return pipe('./src/styles/octotree.less',
|
return pipe('./src/styles/octotree.less',
|
||||||
[$.less(), $.autoprefixer({cascade: true})],
|
[$.less(), $.autoprefixer({cascade: true})],
|
||||||
'./tmp')
|
'./tmp')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Chrome
|
// Chrome
|
||||||
gulp.task('chrome:template', function () {
|
gulp.task('chrome:template', () => {
|
||||||
return buildTemplate({CHROME: true})
|
return buildTemplate({CHROME: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('chrome:js', ['chrome:template'], function () {
|
gulp.task('chrome:js', ['chrome:template'], () => {
|
||||||
return buildJs(['./src/config/chrome/storage.js'], {CHROME: true})
|
return buildJs(['./src/config/chrome/overrides.js'], {CHROME: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('chrome', ['chrome:js'], function () {
|
gulp.task('chrome', ['chrome:js'], () => {
|
||||||
return merge(
|
return merge(
|
||||||
pipe('./icons/**/*', './tmp/chrome/icons'),
|
pipe('./icons/**/*', './tmp/chrome/icons'),
|
||||||
pipe(['./libs/**/*', './tmp/octotree.*', './src/config/chrome/**/*', '!./src/config/chrome/storage.js'], './tmp/chrome/')
|
pipe(['./libs/**/*', './tmp/octotree.*', './src/config/chrome/**/*', '!./src/config/chrome/storage.js'], './tmp/chrome/')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('chrome:zip', function () {
|
gulp.task('chrome:zip', () => {
|
||||||
return pipe('./tmp/chrome/**/*', [$.zip('chrome.zip')], './dist')
|
return pipe('./tmp/chrome/**/*', [$.zip('chrome.zip')], './dist')
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('chrome:_crx', function (cb) {
|
gulp.task('chrome:_crx', (cb) => {
|
||||||
$.run('"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"' +
|
$.run('"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"' +
|
||||||
' --pack-extension=' + path.join(__dirname, './tmp/chrome') +
|
' --pack-extension=' + path.join(__dirname, './tmp/chrome') +
|
||||||
' --pack-extension-key=' + path.join(process.env.HOME, '.ssh/chrome.pem')
|
' --pack-extension-key=' + path.join(process.env.HOME, '.ssh/chrome.pem')
|
||||||
).exec(cb)
|
).exec(cb)
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('chrome:crx', ['chrome:_crx'], function () {
|
gulp.task('chrome:crx', ['chrome:_crx'], () => {
|
||||||
return pipe('./tmp/chrome.crx', './dist')
|
return pipe('./tmp/chrome.crx', './dist')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Opera
|
// Opera
|
||||||
gulp.task('opera', ['chrome'], function () {
|
gulp.task('opera', ['chrome'], () => {
|
||||||
return pipe('./tmp/chrome/**/*', './tmp/opera')
|
return pipe('./tmp/chrome/**/*', './tmp/opera')
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('opera:nex', function () {
|
gulp.task('opera:nex', () => {
|
||||||
return pipe('./dist/chrome.crx', [$.rename('opera.nex')], './dist')
|
return pipe('./dist/chrome.crx', [$.rename('opera.nex')], './dist')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Safari
|
// Safari
|
||||||
gulp.task('safari:template', function () {
|
gulp.task('safari:template', () => {
|
||||||
return buildTemplate({SAFARI: true})
|
return buildTemplate({SAFARI: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('safari:js', ['safari:template'], function () {
|
gulp.task('safari:js', ['safari:template'], () => {
|
||||||
return buildJs(['./src/config/safari/storage.js'], {SAFARI: true})
|
return buildJs([], {SAFARI: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('safari', ['safari:js'], function () {
|
gulp.task('safari', ['safari:js'], () => {
|
||||||
return merge(
|
return merge(
|
||||||
pipe('./icons/**/*', './tmp/safari/octotree.safariextension/icons'),
|
pipe('./icons/**/*', './tmp/safari/octotree.safariextension/icons'),
|
||||||
pipe(['./libs/**/*', './tmp/octotree.js', './tmp/octotree.css',
|
pipe(['./libs/**/*', './tmp/octotree.js', './tmp/octotree.css',
|
||||||
|
@ -96,15 +98,15 @@ gulp.task('safari', ['safari:js'], function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Firefox
|
// Firefox
|
||||||
gulp.task('firefox:template', function () {
|
gulp.task('firefox:template', () => {
|
||||||
return buildTemplate({FIREFOX: true})
|
return buildTemplate({FIREFOX: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('firefox:js', ['firefox:template'], function () {
|
gulp.task('firefox:js', ['firefox:template'], () => {
|
||||||
return buildJs(['./src/config/firefox/storage.js'], {FIREFOX: true})
|
return buildJs([], {FIREFOX: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('firefox', ['firefox:js'], function () {
|
gulp.task('firefox', ['firefox:js'], () => {
|
||||||
return merge(
|
return merge(
|
||||||
pipe('./icons/**/*', './tmp/firefox/data/icons'),
|
pipe('./icons/**/*', './tmp/firefox/data/icons'),
|
||||||
pipe(['./libs/**/*', './tmp/octotree.js', './tmp/octotree.css'], './tmp/firefox/data'),
|
pipe(['./libs/**/*', './tmp/octotree.js', './tmp/octotree.css'], './tmp/firefox/data'),
|
||||||
|
@ -113,7 +115,7 @@ gulp.task('firefox', ['firefox:js'], function () {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
gulp.task('firefox:xpi', function (cb) {
|
gulp.task('firefox:xpi', (cb) => {
|
||||||
$.run('cd ./tmp/firefox && cfx xpi --output-file=../../dist/firefox.xpi').exec(cb)
|
$.run('cd ./tmp/firefox && cfx xpi --output-file=../../dist/firefox.xpi').exec(cb)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -123,10 +125,12 @@ function pipe(src, transforms, dest) {
|
||||||
dest = transforms
|
dest = transforms
|
||||||
transforms = null
|
transforms = null
|
||||||
}
|
}
|
||||||
var stream = gulp.src(src)
|
|
||||||
|
let stream = gulp.src(src)
|
||||||
transforms && transforms.forEach(function (transform) {
|
transforms && transforms.forEach(function (transform) {
|
||||||
stream = stream.pipe(transform)
|
stream = stream.pipe(transform)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (dest) stream = stream.pipe(gulp.dest(dest))
|
if (dest) stream = stream.pipe(gulp.dest(dest))
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
|
@ -135,20 +139,22 @@ function html2js(template) {
|
||||||
return map(escape)
|
return map(escape)
|
||||||
|
|
||||||
function escape(file, cb) {
|
function escape(file, cb) {
|
||||||
var path = $.util.replaceExtension(file.path, '.js')
|
const path = $.util.replaceExtension(file.path, '.js')
|
||||||
, content = file.contents.toString()
|
const content = file.contents.toString()
|
||||||
, escaped = content.replace(/\\/g, "\\\\")
|
const escaped = content
|
||||||
.replace(/'/g, "\\'")
|
.replace(/\\/g, "\\\\")
|
||||||
.replace(/\r?\n/g, "\\n' +\n '")
|
.replace(/'/g, "\\'")
|
||||||
, body = template.replace('$$', escaped)
|
.replace(/\r?\n/g, "\\n' +\n '")
|
||||||
|
const body = template.replace('$$', escaped)
|
||||||
|
|
||||||
file.path = path
|
file.path = path
|
||||||
file.contents = new Buffer(body)
|
file.contents = new Buffer(body)
|
||||||
cb(null, file)
|
cb(null, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildJs(additions, ctx) {
|
function buildJs(overrides, ctx) {
|
||||||
var src = additions.concat([
|
const src = [
|
||||||
'./tmp/template.js',
|
'./tmp/template.js',
|
||||||
'./src/constants.js',
|
'./src/constants.js',
|
||||||
'./src/adapters/adapter.js',
|
'./src/adapters/adapter.js',
|
||||||
|
@ -161,8 +167,10 @@ function buildJs(additions, ctx) {
|
||||||
'./src/util.location.js',
|
'./src/util.location.js',
|
||||||
'./src/util.module.js',
|
'./src/util.module.js',
|
||||||
'./src/util.async.js',
|
'./src/util.async.js',
|
||||||
'./src/octotree.js',
|
'./src/util.storage.js'
|
||||||
])
|
].concat(overrides)
|
||||||
|
.concat('./src/octotree.js')
|
||||||
|
|
||||||
return pipe(src, [
|
return pipe(src, [
|
||||||
$.babel({presets: ['es2015']}),
|
$.babel({presets: ['es2015']}),
|
||||||
$.concat('octotree.js'),
|
$.concat('octotree.js'),
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
"crx": "^0.4.4",
|
"crx": "^0.4.4",
|
||||||
"event-stream": "*",
|
"event-stream": "*",
|
||||||
"firefox-profile": "~0.3.6",
|
"firefox-profile": "~0.3.6",
|
||||||
"gulp": "^3.8.6",
|
"gulp": "^3.9.0",
|
||||||
"gulp-autoprefixer": "0.0.8",
|
"gulp-autoprefixer": "0.0.8",
|
||||||
"gulp-babel": "^6.1.0",
|
"gulp-babel": "^6.1.0",
|
||||||
"gulp-clean": "^0.3.1",
|
"gulp-clean": "^0.3.1",
|
||||||
|
|
|
@ -191,13 +191,31 @@ class Adapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the CSS class to be added to the Octotree sidebar.
|
* Inits behaviors after the sidebar is added to the DOM.
|
||||||
* @api public
|
* @api public
|
||||||
*/
|
*/
|
||||||
|
init($sidebar) {
|
||||||
|
$sidebar
|
||||||
|
.resizable({ handles: 'e', minWidth: this.getMinWidth() })
|
||||||
|
.addClass(this.getCssClass())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the CSS class to be added to the Octotree sidebar.
|
||||||
|
* @api protected
|
||||||
|
*/
|
||||||
getCssClass() {
|
getCssClass() {
|
||||||
throw new Error('Not implemented')
|
throw new Error('Not implemented')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum width acceptable for the sidebar.
|
||||||
|
* @api protected
|
||||||
|
*/
|
||||||
|
getMinWidth() {
|
||||||
|
return 200
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the adapter is capable of loading the entire tree in
|
* Returns whether the adapter is capable of loading the entire tree in
|
||||||
* a single request. This is usually determined by the underlying the API.
|
* a single request. This is usually determined by the underlying the API.
|
||||||
|
@ -247,7 +265,6 @@ class Adapter {
|
||||||
window.location.href = path
|
window.location.href = path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects a submodule.
|
* Selects a submodule.
|
||||||
* @api public
|
* @api public
|
||||||
|
|
|
@ -14,6 +14,7 @@ const GH_PJAX_SEL = '#js-repo-pjax-container'
|
||||||
const GH_CONTAINERS = '.container'
|
const GH_CONTAINERS = '.container'
|
||||||
|
|
||||||
class GitHub extends Adapter {
|
class GitHub extends Adapter {
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
getCssClass() {
|
getCssClass() {
|
||||||
return 'octotree_github_sidebar'
|
return 'octotree_github_sidebar'
|
||||||
|
|
|
@ -9,6 +9,7 @@ const GL_SHIFTED = 'h1.title'
|
||||||
const GL_PROJECT_ID = '#project_id'
|
const GL_PROJECT_ID = '#project_id'
|
||||||
|
|
||||||
class GitLab extends Adapter {
|
class GitLab extends Adapter {
|
||||||
|
|
||||||
constructor(store) {
|
constructor(store) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
|
@ -21,6 +22,11 @@ class GitLab extends Adapter {
|
||||||
store.set(STORE.TOKEN, token, true)
|
store.set(STORE.TOKEN, token, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @override
|
||||||
|
init($sidebar) {
|
||||||
|
super.init($sidebar)
|
||||||
|
|
||||||
// Triggers layout when the GL sidebar is toggled
|
// Triggers layout when the GL sidebar is toggled
|
||||||
$('.toggle-nav-collapse').click(() => {
|
$('.toggle-nav-collapse').click(() => {
|
||||||
|
@ -28,6 +34,22 @@ class GitLab extends Adapter {
|
||||||
$(document).trigger(EVENT.LAYOUT_CHANGE)
|
$(document).trigger(EVENT.LAYOUT_CHANGE)
|
||||||
}, 10)
|
}, 10)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// GitLab disables our submit buttons, re-enable them
|
||||||
|
$('.octotree_view_body button[type="submit"]').click((event) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
$(event.target).prop('disabled', false).removeClass('disabled')
|
||||||
|
}, 100)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Reuses GitLab styles for inputs
|
||||||
|
$('.octotree_view_body input[type="text"], .octotree_view_body textarea')
|
||||||
|
.addClass('form-control')
|
||||||
|
|
||||||
|
// GitLab removes DOM, add back
|
||||||
|
$(document).on(EVENT.LOC_CHANGE, () => {
|
||||||
|
$sidebar.appendTo('body')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
|
@ -35,6 +57,11 @@ class GitLab extends Adapter {
|
||||||
return 'octotree_gitlab_sidebar'
|
return 'octotree_gitlab_sidebar'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @override
|
||||||
|
getMinWidth() {
|
||||||
|
return 230 // just enough to hide the GitLab sidebar
|
||||||
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
getCreateTokenUrl() {
|
getCreateTokenUrl() {
|
||||||
return `${location.protocol}//${location.host}/profile/account`
|
return `${location.protocol}//${location.host}/profile/account`
|
||||||
|
@ -42,16 +69,16 @@ class GitLab extends Adapter {
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
updateLayout(sidebarVisible, sidebarWidth) {
|
updateLayout(sidebarVisible, sidebarWidth) {
|
||||||
const useNewDesign = $('.navbar-gitlab.header-collapsed, .navbar-gitlab.header-expanded').length > 0
|
const isNewDesign = $('.navbar-gitlab.header-collapsed, .navbar-gitlab.header-expanded').length > 0
|
||||||
const glSidebarExpanded = $('.page-with-sidebar').hasClass('page-sidebar-expanded')
|
const glSidebarExpanded = $('.page-with-sidebar').hasClass('page-sidebar-expanded')
|
||||||
let glSidebarWidth = glSidebarExpanded ? 230 : 62
|
|
||||||
|
|
||||||
if (useNewDesign) {
|
if (isNewDesign) {
|
||||||
|
const glSidebarWidth = glSidebarExpanded ? 230 : 62
|
||||||
$(GL_SHIFTED).css('margin-left', sidebarVisible ? '' : 36)
|
$(GL_SHIFTED).css('margin-left', sidebarVisible ? '' : 36)
|
||||||
$('.octotree_toggle').css('right', sidebarVisible ? '' : -(glSidebarWidth + 50))
|
$('.octotree_toggle').css('right', sidebarVisible ? '' : -(glSidebarWidth + 50))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
glSidebarWidth = glSidebarExpanded ? 230 : 52
|
const glSidebarWidth = glSidebarExpanded ? 230 : 52
|
||||||
$(GL_HEADER).css('z-index', 3)
|
$(GL_HEADER).css('z-index', 3)
|
||||||
$(GL_SIDEBAR).css('z-index', 1)
|
$(GL_SIDEBAR).css('z-index', 1)
|
||||||
$(GL_SHIFTED).css('margin-left', sidebarVisible ? '' : 56)
|
$(GL_SHIFTED).css('margin-left', sidebarVisible ? '' : 56)
|
||||||
|
@ -61,7 +88,7 @@ class GitLab extends Adapter {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$(GL_HEADER).css({'z-index': 3, 'padding-left': sidebarVisible ? sidebarWidth : ''})
|
$(GL_HEADER).css({'z-index': 3, 'margin-left': sidebarVisible ? sidebarWidth : ''})
|
||||||
$('.page-with-sidebar').css('padding-left', sidebarVisible ? sidebarWidth : '')
|
$('.page-with-sidebar').css('padding-left', sidebarVisible ? sidebarWidth : '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,25 +165,6 @@ class GitLab extends Adapter {
|
||||||
}, cb)
|
}, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
|
||||||
setSideBar(sidebar) {
|
|
||||||
this.sidebar = sidebar
|
|
||||||
// GL disables our submit buttons, re-enable them
|
|
||||||
const btns = $('.octotree_view_body button[type="submit"]')
|
|
||||||
|
|
||||||
btns.click((event) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
$(event.target).prop('disabled', false).removeClass('disabled')
|
|
||||||
}, 30)
|
|
||||||
})
|
|
||||||
// Make inputs consistent with GL style
|
|
||||||
$('.octotree_view_body input[type="text"], .octotree_view_body textarea').addClass('form-control')
|
|
||||||
|
|
||||||
$(document).on(EVENT.LOC_CHANGE, () => {
|
|
||||||
this.sidebar.appendTo('body')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
_getTree(path, opts, cb) {
|
_getTree(path, opts, cb) {
|
||||||
this._get(`/tree?path=${path}&ref_name=${opts.encodedBranch}`, opts, cb)
|
this._get(`/tree?path=${path}&ref_name=${opts.encodedBranch}`, opts, cb)
|
||||||
|
|
|
@ -3,18 +3,6 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-sidebar-expanded {
|
|
||||||
.octotree_gitlab_sidebar {
|
|
||||||
left: 249px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-sidebar-collapsed {
|
|
||||||
.octotree_gitlab_sidebar {
|
|
||||||
left: 79px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.octotree_gitlab_sidebar {
|
.octotree_gitlab_sidebar {
|
||||||
a.octotree_toggle {
|
a.octotree_toggle {
|
||||||
right: 5px;
|
right: 5px;
|
||||||
|
@ -29,24 +17,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html:not(.octotree) {
|
|
||||||
.page-sidebar-expanded {
|
|
||||||
.octotree_gitlab_sidebar {
|
|
||||||
a.octotree_toggle {
|
|
||||||
right: -294px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-sidebar-collapsed {
|
|
||||||
.octotree_gitlab_sidebar {
|
|
||||||
a.octotree_toggle {
|
|
||||||
right: -110px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.octotree_gitlab_sidebar {
|
.octotree_gitlab_sidebar {
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
padding-top: 58px;
|
padding-top: 58px;
|
|
@ -0,0 +1,21 @@
|
||||||
|
(() => {
|
||||||
|
const oldSet = Storage.prototype.set
|
||||||
|
Storage.prototype.set = function (key, val, cb) {
|
||||||
|
this._cache = this._cache || {}
|
||||||
|
this._cache[key] = val
|
||||||
|
|
||||||
|
const shared = ~key.indexOf('.shared')
|
||||||
|
if (shared) chrome.storage.local.set({[key]: val}, cb || Function())
|
||||||
|
else oldSet.call(this, key, val, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldGet = Storage.prototype.get
|
||||||
|
Storage.prototype.get = function (key, cb) {
|
||||||
|
this._cache = this._cache || {}
|
||||||
|
if (!cb) return this._cache[key]
|
||||||
|
|
||||||
|
const shared = ~key.indexOf('.shared')
|
||||||
|
if (shared) chrome.storage.local.get(key, (item) => cb(item[key]))
|
||||||
|
else oldGet.call(this, key, cb)
|
||||||
|
}
|
||||||
|
})()
|
|
@ -1,48 +0,0 @@
|
||||||
function Storage() {
|
|
||||||
var cache = this.cache = {}
|
|
||||||
chrome.storage.onChanged.addListener(function(changes) {
|
|
||||||
for (var key in changes) cache[key] = changes[key].newValue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Storage.prototype.set = function(key, val, local, cb) {
|
|
||||||
if (typeof local === 'function') {
|
|
||||||
cb = local
|
|
||||||
local = false
|
|
||||||
}
|
|
||||||
|
|
||||||
cb = cb || Function()
|
|
||||||
this.cache[key] = val
|
|
||||||
|
|
||||||
if (local) {
|
|
||||||
localStorage.setItem(key, JSON.stringify(val))
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var item = {}
|
|
||||||
item[key] = val
|
|
||||||
chrome.storage.local.set(item, cb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Storage.prototype.get = function(key, local, cb) {
|
|
||||||
if (typeof local === 'function') {
|
|
||||||
cb = local
|
|
||||||
local = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cb) return this.cache[key]
|
|
||||||
|
|
||||||
if (local) cb(parse(localStorage.getItem(key)))
|
|
||||||
else chrome.storage.local.get(key, function(item) {
|
|
||||||
cb(item[key])
|
|
||||||
})
|
|
||||||
|
|
||||||
function parse(val) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(val)
|
|
||||||
} catch (e) {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
function Storage() {}
|
|
||||||
|
|
||||||
Storage.prototype.set = function(key, val, local, cb) {
|
|
||||||
if (typeof local === 'function') cb = local
|
|
||||||
|
|
||||||
localStorage.setItem(key, JSON.stringify(val))
|
|
||||||
if (cb) cb()
|
|
||||||
}
|
|
||||||
|
|
||||||
Storage.prototype.get = function(key, local, cb) {
|
|
||||||
if (typeof local === 'function') cb = local
|
|
||||||
|
|
||||||
var val = parse(localStorage.getItem(key))
|
|
||||||
if (cb) cb(val)
|
|
||||||
else return val
|
|
||||||
|
|
||||||
function parse(val) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(val)
|
|
||||||
} catch (e) {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
function Storage() {}
|
|
||||||
|
|
||||||
Storage.prototype.set = function(key, val, local, cb) {
|
|
||||||
if (typeof local === 'function') cb = local
|
|
||||||
|
|
||||||
localStorage.setItem(key, JSON.stringify(val))
|
|
||||||
if (cb) cb()
|
|
||||||
}
|
|
||||||
|
|
||||||
Storage.prototype.get = function(key, local, cb) {
|
|
||||||
if (typeof local === 'function') cb = local
|
|
||||||
|
|
||||||
var val = parse(localStorage.getItem(key))
|
|
||||||
if (cb) cb(val)
|
|
||||||
else return val
|
|
||||||
|
|
||||||
function parse(val) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(val)
|
|
||||||
} catch (e) {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,11 +6,11 @@ const STORE = {
|
||||||
NONCODE : 'octotree.noncode_shown',
|
NONCODE : 'octotree.noncode_shown',
|
||||||
HOTKEYS : 'octotree.hotkeys',
|
HOTKEYS : 'octotree.hotkeys',
|
||||||
LOADALL : 'octotree.loadall',
|
LOADALL : 'octotree.loadall',
|
||||||
GHEURLS : 'octotree.gheurls',
|
|
||||||
GLEURLS : 'octotree.gleurls',
|
|
||||||
WIDTH : 'octotree.sidebar_width',
|
|
||||||
POPUP : 'octotree.popup_shown',
|
POPUP : 'octotree.popup_shown',
|
||||||
SHOWN : 'octotree.sidebar_shown'
|
WIDTH : 'octotree.sidebar_width',
|
||||||
|
SHOWN : 'octotree.sidebar_shown',
|
||||||
|
GHEURLS : 'octotree.gheurls.shared',
|
||||||
|
GLEURLS : 'octotree.gleurls.shared'
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULTS = {
|
const DEFAULTS = {
|
||||||
|
@ -26,7 +26,7 @@ const DEFAULTS = {
|
||||||
// @endif
|
// @endif
|
||||||
GHEURLS : '',
|
GHEURLS : '',
|
||||||
GLEURLS : '',
|
GLEURLS : '',
|
||||||
WIDTH : 250,
|
WIDTH : 232,
|
||||||
POPUP : false,
|
POPUP : false,
|
||||||
SHOWN : false
|
SHOWN : false
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,8 @@ $(document).ready(() => {
|
||||||
|
|
||||||
function setDefault(key, cb) {
|
function setDefault(key, cb) {
|
||||||
const storeKey = STORE[key]
|
const storeKey = STORE[key]
|
||||||
const local = storeKey === STORE.TOKEN
|
store.get(storeKey, (val) => {
|
||||||
|
store.set(storeKey, val == null ? DEFAULTS[key] : val, cb)
|
||||||
store.get(storeKey, local, (val) => {
|
|
||||||
store.set(storeKey, val == null ? DEFAULTS[key] : val, local, cb)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,13 +34,11 @@ $(document).ready(() => {
|
||||||
let hasError = false
|
let hasError = false
|
||||||
|
|
||||||
$sidebar
|
$sidebar
|
||||||
.width(parseFloat(store.get(STORE.WIDTH)))
|
.width(parseInt(store.get(STORE.WIDTH)))
|
||||||
.resizable({ handles: 'e', minWidth: 230 }) // to hide GL sidebar
|
|
||||||
.resize(layoutChanged)
|
.resize(layoutChanged)
|
||||||
.addClass(adapter.getCssClass())
|
|
||||||
.appendTo($('body'))
|
.appendTo($('body'))
|
||||||
|
|
||||||
adapter.setSideBar($sidebar)
|
adapter.init($sidebar)
|
||||||
layoutChanged()
|
layoutChanged()
|
||||||
|
|
||||||
$(window).resize((event) => { // handle zoom
|
$(window).resize((event) => { // handle zoom
|
||||||
|
@ -170,7 +166,7 @@ $(document).ready(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function layoutChanged() {
|
function layoutChanged() {
|
||||||
const width = $sidebar.width()
|
const width = $sidebar.outerWidth()
|
||||||
adapter.updateLayout(isSidebarVisible(), width)
|
adapter.updateLayout(isSidebarVisible(), width)
|
||||||
store.set(STORE.WIDTH, width)
|
store.set(STORE.WIDTH, width)
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,7 @@ a.octotree_toggle {
|
||||||
|
|
||||||
&.octotree_loading {
|
&.octotree_loading {
|
||||||
& > span:after {
|
& > span:after {
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader {
|
.loader {
|
||||||
|
@ -221,9 +221,7 @@ a.octotree_toggle {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: none;
|
display: none;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
top: 40px;
|
z-index: 999999999;
|
||||||
left: 5px;
|
|
||||||
z-index: 93;
|
|
||||||
width: 260px;
|
width: 260px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
|
@ -1,3 +1,3 @@
|
||||||
@import "common";
|
@import "base";
|
||||||
@import "github";
|
@import "../adapters/github";
|
||||||
@import "gitlab";
|
@import "../adapters/gitlab";
|
||||||
|
|
|
@ -32,6 +32,26 @@
|
||||||
<input type="text" data-store="TOKEN" data-perhost="true">
|
<input type="text" data-store="TOKEN" data-perhost="true">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<label>Hotkeys</label>
|
||||||
|
<a href="https://github.com/madrobby/keymaster#defining-shortcuts" target="_blank" tabIndex="-1">supported keys</a>
|
||||||
|
</div>
|
||||||
|
<input type="text" data-store="HOTKEYS">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label><input type="checkbox" data-store="REMEMBER"> Remember sidebar visibility</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label><input type="checkbox" data-store="NONCODE"> Show in non-code pages</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="octotree_github_only">
|
||||||
|
<label><input type="checkbox" data-store="LOADALL"> Load entire tree at once</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- @ifdef CHROME -->
|
<!-- @ifdef CHROME -->
|
||||||
<div class="octotree_github_only">
|
<div class="octotree_github_only">
|
||||||
<div>
|
<div>
|
||||||
|
@ -40,6 +60,7 @@
|
||||||
<textarea data-store="GHEURLS" placeholder="https://github.mysite1.com/ https://github.mysite2.com/">
|
<textarea data-store="GHEURLS" placeholder="https://github.mysite1.com/ https://github.mysite2.com/">
|
||||||
</textarea>
|
</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="octotree_gitlab_only">
|
<div class="octotree_gitlab_only">
|
||||||
<div>
|
<div>
|
||||||
<label>GitLab Enterprise URLs</label>
|
<label>GitLab Enterprise URLs</label>
|
||||||
|
@ -49,24 +70,6 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- @endif -->
|
<!-- @endif -->
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label><input type="checkbox" data-store="REMEMBER"> Remember sidebar visibility</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label><input type="checkbox" data-store="NONCODE"> Show in non-code pages</label>
|
|
||||||
</div>
|
|
||||||
<div class="octotree_github_only">
|
|
||||||
<label><input type="checkbox" data-store="LOADALL"> Load entire tree at once</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<label>Hotkeys</label>
|
|
||||||
<a href="https://github.com/madrobby/keymaster#defining-shortcuts" target="_blank" tabIndex="-1">supported keys</a>
|
|
||||||
</div>
|
|
||||||
<input type="text" data-store="HOTKEYS">
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<button type="submit" class="btn">Save</button>
|
<button type="submit" class="btn">Save</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
class Storage {
|
||||||
|
set(key, val, cb) {
|
||||||
|
localStorage.setItem(key, JSON.stringify(val))
|
||||||
|
if (cb) cb()
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key, cb) {
|
||||||
|
var val = parse(localStorage.getItem(key))
|
||||||
|
if (cb) cb(val)
|
||||||
|
else return val
|
||||||
|
|
||||||
|
function parse(val) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(val)
|
||||||
|
} catch (e) {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,13 +5,27 @@ class HelpPopup {
|
||||||
}
|
}
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
const $view = this.$view
|
|
||||||
const store = this.store
|
const store = this.store
|
||||||
const popupShown = store.get(STORE.POPUP)
|
const popupShown = store.get(STORE.POPUP)
|
||||||
|
const sidebarVisible = $('html').hasClass(PREFIX)
|
||||||
|
|
||||||
if (popupShown) return
|
if (popupShown || sidebarVisible) {
|
||||||
|
store.set(STORE.POPUP, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
$view.css('display', 'block').appendTo($('body'))
|
const $view = this.$view
|
||||||
|
const $toggler = $('.octotree_toggle')
|
||||||
|
const offset = $toggler.offset()
|
||||||
|
const height = $toggler.outerHeight()
|
||||||
|
|
||||||
|
$view
|
||||||
|
.css({
|
||||||
|
display: 'block',
|
||||||
|
top: offset.top + height + 2,
|
||||||
|
left: offset.left
|
||||||
|
})
|
||||||
|
$view.appendTo($('body'))
|
||||||
|
|
||||||
$(document).one(EVENT.TOGGLE, hide)
|
$(document).one(EVENT.TOGGLE, hide)
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class OptionsView {
|
||||||
|
|
||||||
_load() {
|
_load() {
|
||||||
this._eachOption(
|
this._eachOption(
|
||||||
($elm, key, local, value, cb) => {
|
($elm, key, value, cb) => {
|
||||||
if ($elm.is(':checkbox')) $elm.prop('checked', value)
|
if ($elm.is(':checkbox')) $elm.prop('checked', value)
|
||||||
else $elm.val(value)
|
else $elm.val(value)
|
||||||
cb()
|
cb()
|
||||||
|
@ -70,11 +70,11 @@ class OptionsView {
|
||||||
_saveOptions() {
|
_saveOptions() {
|
||||||
const changes = {}
|
const changes = {}
|
||||||
this._eachOption(
|
this._eachOption(
|
||||||
($elm, key, local, value, cb) => {
|
($elm, key, value, cb) => {
|
||||||
const newValue = $elm.is(':checkbox') ? $elm.is(':checked') : $elm.val()
|
const newValue = $elm.is(':checkbox') ? $elm.is(':checked') : $elm.val()
|
||||||
if (value === newValue) return cb()
|
if (value === newValue) return cb()
|
||||||
changes[key] = [value, newValue]
|
changes[key] = [value, newValue]
|
||||||
this.store.set(key, newValue, local, cb)
|
this.store.set(key, newValue, cb)
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this._toggle(false)
|
this._toggle(false)
|
||||||
|
@ -90,10 +90,9 @@ class OptionsView {
|
||||||
(elm, cb) => {
|
(elm, cb) => {
|
||||||
const $elm = $(elm)
|
const $elm = $(elm)
|
||||||
const key = STORE[$elm.data('store')]
|
const key = STORE[$elm.data('store')]
|
||||||
const local = !!$elm.data('perhost')
|
|
||||||
|
|
||||||
this.store.get(key, local, (value) => {
|
this.store.get(key, (value) => {
|
||||||
processFn($elm, key, local, value, () => cb())
|
processFn($elm, key, value, () => cb())
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
completeFn
|
completeFn
|
||||||
|
|
Loading…
Reference in New Issue