Skip to content

Commit

Permalink
Merge pull request #22 from berzniz/concat_folders
Browse files Browse the repository at this point in the history
  • Loading branch information
berzniz authored Oct 4, 2018
2 parents b06bc9a + bd29d22 commit cd83357
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 14 deletions.
88 changes: 82 additions & 6 deletions src/js/components/tree.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@ import React from 'react'
import Branch from './branch.jsx'
import { isElementVisible } from '../lib'

const MIN_RESIZE_WIDTH = 55
const MAX_RESIZE_WIDTH = 700

const widthLocalStorageKey = '__better_github_pr_tree_width'

class Tree extends React.Component {
constructor (props) {
super(props)

this.onClose = this.onClose.bind(this)
this.onScroll = this.onScroll.bind(this)
this.onResizerMouseDown = this.onResizerMouseDown.bind(this)
this.onMouseMove = this.onMouseMove.bind(this)
this.onMouseUp = this.onMouseUp.bind(this)
this.toggleDocumentFullWidth = this.toggleDocumentFullWidth.bind(this)

this.isResizing = false
this.resizeDelta = 0

this.treeContainer = document.querySelector('.__better_github_pr')
this.reviewContainers = document.querySelectorAll('.enable_better_github_pr .diff-view, .enable_better_github_pr .commit.full-commit.prh-commit')

this.setInitialWidth()

this.state = {
show: true,
Expand All @@ -20,13 +37,44 @@ class Tree extends React.Component {
window.addEventListener('load', this.onScroll, false)
window.addEventListener('scroll', this.onScroll, false)
window.addEventListener('resize', this.onScroll, false)

this.resizer.addEventListener('mousedown', this.onResizerMouseDown, false)
document.addEventListener('mousemove', this.onMouseMove, false)
document.addEventListener('mouseup', this.onMouseUp, false)
}

componentWillUnmount () {
window.removeEventListener('DOMContentLoaded', this.onScroll, false)
window.removeEventListener('load', this.onScroll, false)
window.removeEventListener('scroll', this.onScroll, false)
window.removeEventListener('resize', this.onScroll, false)

this.resizer.removeEventListener('mousedown', this.onResizerMouseDown, false)
document.removeEventListener('mousemove', this.onMouseMove, false)
document.removeEventListener('mouseup', this.onMouseUp, false)
}

onResizerMouseDown () {
this.isResizing = true
this.treeContainer.classList.add('__better_github_pr_noselect')
this.prevWidth = this.treeContainer.offsetWidth
this.startResizeX = this.resizer.getBoundingClientRect().x
}

onMouseMove (e) {
if (!this.isResizing) return

this.resizeDelta = e.clientX - this.startResizeX
let newWidth = this.prevWidth + this.resizeDelta
setTimeout(() => this.setWidth(newWidth), 0)
}

onMouseUp () {
if (!this.isResizing) return

this.isResizing = false
this.treeContainer.classList.remove('__better_github_pr_noselect')
window.localStorage.setItem(widthLocalStorageKey, this.treeContainer.offsetWidth)
}

onScroll () {
Expand All @@ -45,6 +93,30 @@ class Tree extends React.Component {
const show = false
this.setState({ show })
document.body.classList.toggle('enable_better_github_pr', show)
this.setWidth(0, false)
}

setInitialWidth () {
const savedWitdh = window.localStorage.getItem(widthLocalStorageKey)
if (savedWitdh) {
this.setWidth(parseInt(savedWitdh, 10))
}
}

setWidth (width, withConstraints = true) {
if (withConstraints) {
if (width <= MIN_RESIZE_WIDTH) width = MIN_RESIZE_WIDTH
if (width >= MAX_RESIZE_WIDTH) width = MAX_RESIZE_WIDTH
}

this.treeContainer.style.width = `${width}px`
this.reviewContainers.forEach((element) => {
element.style['margin-left'] = `${width + 10}px`
})
}

toggleDocumentFullWidth () {
document.querySelector('body').classList.toggle('__better_github_pr_wide')
}

render () {
Expand All @@ -56,13 +128,17 @@ class Tree extends React.Component {
}

return (
<div>
<div >
<button onClick={this.toggleDocumentFullWidth} className='__better_github_pr_full_width' title='Toggle maximum width of github content' />
<button onClick={this.onClose} className='close_button'></button>
{root.list.map(node => (
<span key={node.nodeLabel}>
<Branch {...node} visibleElement={visibleElement} />
</span>
))}
<div>
<div className='_better_github_pr_resizer' ref={node => { this.resizer = node }} />
{root.list.map(node => (
<span key={node.nodeLabel}>
<Branch {...node} visibleElement={visibleElement} />
</span>
))}
</div>
</div>
)
}
Expand Down
24 changes: 23 additions & 1 deletion src/js/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,28 @@ const hasCommentsForFileIndex = (fileIndex) => {
return diffTable.querySelectorAll('.inline-comments').length
}

export const folderConcat = (node) => {
const isFileOrEmpty = (node.list === undefined || node.list.length === 0 || (node.href !== null && node.href !== undefined))
if (isFileOrEmpty) {
return node
}

const hasSingleChild = (node.list.length === 1)
if (hasSingleChild) {
const collapsed = folderConcat(node.list[0])
const isLastCollapsedIsFolder = node.nodeLabel !== '/' && (collapsed.href === null || collapsed.href === undefined)
if (isLastCollapsedIsFolder) {
node.nodeLabel = node.nodeLabel + '/' + collapsed.nodeLabel
node.hasComments = collapsed.hasComments || node.hasComments
node.list = collapsed.list
}
return node
}

node.list.map(x => folderConcat(x))
return node
}

export const createFileTree = () => {
const fileInfo = [...document.querySelectorAll('.file-info > a')]
const files = fileInfo.map(({ title, href }) => {
Expand Down Expand Up @@ -68,7 +90,7 @@ export const createFileTree = () => {
})
})
return {
tree,
tree: folderConcat(tree),
count: fileInfo.length
}
}
Expand Down
76 changes: 69 additions & 7 deletions src/js/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,29 @@
display: none;
}

._better_github_pr_resizer {
position: absolute;
width: 5px;
height: 100%;
background: lightgray;
right: 0;
top: 0;
cursor: col-resize;
opacity: .4;
transition: opacity .2s ease;
z-index: 1;
}

._better_github_pr_resizer:hover {
opacity: 1;
}

.enable_better_github_pr .__better_github_pr {
display: block;
position: relative;
margin-top: 20px;
padding: 10px;
width: 240px;
overflow: auto;
padding: 30px 10px 0;
width: 330px;
height: calc(100vh - 61px);
background-color: #fafbfc;
border: 1px solid #e1e4e8;
Expand All @@ -22,23 +38,65 @@
}

.__better_github_pr > div {
display: inline-block;
overflow: auto;
height: 100%;
padding-bottom: 10px;
}

.__better_github_pr > div > div {
width: fit-content;
}

.__better_github_pr .close_button {
background: none;
border: none;
position: absolute;
top: 0;
right: 0;
top: 1px;
right: 10px;
padding: 5px 2px;
}

.__better_github_pr_full_width {
width: 16px;
height: 16px;
background-size: cover;
position: absolute;
top: 6px;
right: 40px;
cursor: pointer;
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMyIDMyIiBoZWlnaHQ9IjMycHgiIGlkPSLQodC70L7QuV8xIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJGdWxsc2NyZWVuIj48cGF0aCBkPSJNMzIsMWMwLTAuNTU4LTAuNDQyLTEtMS0xbC04Ljk4NSwwYy0wLjU2OCwwLTAuOTkxLDAuNDQ4LTAuOTkyLDEuMDE2QzIxLjAyMywxLjU4MywyMS40NDcsMiwyMi4wMTUsMkwzMCwyICAgbC0wLjAxNiw4LjAyM2MwLDAuNTY4LDAuNDMyLDEsMSwxYzAuNTY4LTAuMDAxLDEtMC40MzIsMS0xTDMyLDEuMDE1YzAtMC4wMDMtMC4wMDEtMC4wMDUtMC4wMDEtMC4wMDdDMzEuOTk5LDEuMDA1LDMyLDEuMDAzLDMyLDF6ICAgIiBmaWxsPSIjMTIxMzEzIi8+PHBhdGggZD0iTTEwLjAxNiwwSDEuMDMxQzEuMDI4LDAsMS4wMjYsMC4wMDEsMS4wMjMsMC4wMDFDMS4wMjEsMC4wMDEsMS4wMTgsMCwxLjAxNiwwYy0wLjU1OCwwLTEsMC40NDItMSwxICAgTDAsMTAuMDA4QzAsMTAuNTc2LDAuNDQ4LDExLDEuMDE2LDExQzEuNTgzLDExLDIsMTAuNTc2LDIsMTAuMDA4TDIuMDE2LDJoOGMwLjU2OCwwLDEtMC40MzIsMS0xQzExLjAxNSwwLjQzMiwxMC41ODMsMCwxMC4wMTYsMHoiIGZpbGw9IiMxMjEzMTMiLz48cGF0aCBkPSJNOS45ODUsMzBIMnYtOGMwLTAuNTY4LTAuNDMyLTEtMS0xYy0wLjU2OCwwLTEsMC40MzItMSwxdjguOTg1YzAsMC4wMDMsMC4wMDEsMC4wMDUsMC4wMDEsMC4wMDcgICBDMC4wMDEsMzAuOTk1LDAsMzAuOTk3LDAsMzFjMCwwLjU1OCwwLjQ0MiwxLDEsMWg4Ljk4NWMwLjU2OCwwLDAuOTkxLTAuNDQ4LDAuOTkyLTEuMDE2QzEwLjk3NywzMC40MTcsMTAuNTUzLDMwLDkuOTg1LDMweiIgZmlsbD0iIzEyMTMxMyIvPjxwYXRoIGQ9Ik0zMC45ODQsMjEuMDIzYy0wLjU2OCwwLTAuOTg1LDAuNDI0LTAuOTg0LDAuOTkyVjMwbC04LDBjLTAuNTY4LDAtMSwwLjQzMi0xLDFjMCwwLjU2OCwwLjQzMiwxLDEsMSAgIGw4Ljk4NSwwYzAuMDAzLDAsMC4wMDUtMC4wMDEsMC4wMDctMC4wMDFDMzAuOTk1LDMxLjk5OCwzMC45OTcsMzIsMzEsMzJjMC41NTgsMCwxLTAuNDQyLDEtMXYtOC45ODUgICBDMzIsMjEuNDQ3LDMxLjU1MiwyMS4wMjMsMzAuOTg0LDIxLjAyM3oiIGZpbGw9IiMxMjEzMTMiLz48L2c+PGcvPjxnLz48Zy8+PGcvPjxnLz48Zy8+PC9zdmc+');
background-color: transparent;
border: none;
}

.__better_github_pr_noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome and Opera */
}

.__better_github_pr_wide .container {
min-width: 980px;
width: 96% !important;
}

.__better_github_pr_wide .repository-content .discussion-timeline {
width: calc(100% - 220px) !important;
}

.__better_github_pr_wide .repository-content .discussion-timeline .timeline-new-comment {
max-width: 100% !important;
}

/* GitHub page changes */

.enable_better_github_pr .diff-view,
.enable_better_github_pr .commit.full-commit.prh-commit {
margin-left: 250px;
margin-left: 340px;
}

.enable_better_github_pr .diff-view .file-header {
Expand All @@ -51,6 +109,10 @@
max-width: 708px;
}

.enable_better_github_pr .container {
transition: width .2s ease;
}

/* react-treeview */

.tree-view_item {
Expand Down

0 comments on commit cd83357

Please sign in to comment.