diff --git a/src/js/components/tree.jsx b/src/js/components/tree.jsx index eb1d102..c297e11 100644 --- a/src/js/components/tree.jsx +++ b/src/js/components/tree.jsx @@ -1,6 +1,6 @@ import React from 'react' import Branch from './branch.jsx' -import { isElementVisible } from '../lib' +import { createFileTree, isElementVisible } from '../lib' const MIN_RESIZE_WIDTH = 55 const MAX_RESIZE_WIDTH = 700 @@ -17,6 +17,7 @@ class Tree extends React.Component { this.onMouseMove = this.onMouseMove.bind(this) this.onMouseUp = this.onMouseUp.bind(this) this.toggleDocumentFullWidth = this.toggleDocumentFullWidth.bind(this) + this.filterFiles = this.filterFiles.bind(this) this.isResizing = false this.resizeDelta = 0 @@ -27,8 +28,10 @@ class Tree extends React.Component { this.setInitialWidth() this.state = { + root: this.props.root, show: true, - visibleElement: null + visibleElement: null, + filter: null } } @@ -127,9 +130,16 @@ class Tree extends React.Component { document.querySelector('body').classList.toggle('__better_github_pr_wide') } + filterFiles (event) { + const filter = event.target.value || null + this.setState({ + root: createFileTree(filter).tree, + filter + }) + } + render () { - const { root } = this.props - const { show, visibleElement } = this.state + const { root, filter, show, visibleElement } = this.state if (!show) { return null @@ -137,6 +147,7 @@ class Tree extends React.Component { return (
+
diff --git a/src/js/index.jsx b/src/js/index.jsx index 4ab2e3e..7a62397 100644 --- a/src/js/index.jsx +++ b/src/js/index.jsx @@ -16,6 +16,7 @@ const observe = () => { } const renderTree = () => { + const isFilteredToCommit = Boolean(document.querySelector('.js-commits-filtered')) const fileCount = parseInt((document.getElementById('files_tab_counter') || { innerText: 0 }).innerText, 10) const rootElement = createRootElement() const enabled = Boolean(rootElement && fileCount > 0) @@ -26,6 +27,11 @@ const renderTree = () => { const { tree, count } = createFileTree() render(, rootElement) + + if (isFilteredToCommit) { + return + } + if (fileCount !== count) { setTimeout(renderTree.bind(this, rootElement), 100) } diff --git a/src/js/lib.js b/src/js/lib.js index 28b6a18..ba077fd 100644 --- a/src/js/lib.js +++ b/src/js/lib.js @@ -44,6 +44,10 @@ const isDeletedForFileIndex = (fileIndex) => { return hiddenDiffReason && (hiddenDiffReason.innerText.includes('file was deleted')) } +const filterItem = (item, filter) => { + return filter === EMPTY_FILTER || (item && (item.toLowerCase().indexOf(filter) > -1)) +} + export const folderConcat = (node) => { const isFileOrEmpty = (node.list === undefined || node.list.length === 0 || (node.href !== null && node.href !== undefined)) if (isFileOrEmpty) { @@ -67,7 +71,7 @@ export const folderConcat = (node) => { return node } -export const createFileTree = () => { +export const createFileTree = (filter = EMPTY_FILTER) => { const fileInfo = [...document.querySelectorAll('.file-info > a')] const files = fileInfo.map(({ title, href }) => { title = title.split(' → ')[0] @@ -81,26 +85,28 @@ export const createFileTree = () => { files.forEach(({ parts, href }, fileIndex) => { let location = tree - parts.forEach((part, index) => { - let node = location.list.find(node => node.nodeLabel === part) - if (!node) { - const hasComments = (hasCommentsForFileIndex(fileIndex) > 0) - const isDeleted = isDeletedForFileIndex(fileIndex) - const diffElement = document.getElementById(`diff-${fileIndex}`) - tree.diffElements.push(diffElement) - node = { - nodeLabel: part, - list: [], - href: (index === parts.length - 1) ? href : null, - hasComments, - isDeleted, - diffElement + if (filterItem(parts[parts.length - 1], filter)) { + parts.forEach((part, index) => { + let node = location.list.find(node => node.nodeLabel === part) + if (!node) { + const hasComments = (hasCommentsForFileIndex(fileIndex) > 0) + const isDeleted = isDeletedForFileIndex(fileIndex) + const diffElement = document.getElementById(`diff-${fileIndex}`) + tree.diffElements.push(diffElement) + node = { + nodeLabel: part, + list: [], + href: (index === parts.length - 1) ? href : null, + hasComments, + isDeleted, + diffElement + } + location.list.push(node) } - location.list.push(node) - } - location.list = location.list.sort(sorter) - location = node - }) + location.list = location.list.sort(sorter) + location = node + }) + } }) return { tree: folderConcat(tree), @@ -125,3 +131,5 @@ export const isElementVisible = (el) => { return (vertInView && horInView) } + +const EMPTY_FILTER = '' diff --git a/src/js/style.css b/src/js/style.css index 3c8a6e4..36b2569 100644 --- a/src/js/style.css +++ b/src/js/style.css @@ -28,7 +28,7 @@ display: block; position: relative; margin-top: 20px; - padding: 30px 10px 0; + padding: 40px 10px 0; width: 330px; height: calc(100vh - 61px); background-color: #fafbfc; @@ -51,7 +51,7 @@ background: none; border: none; position: absolute; - top: 1px; + top: 5px; right: 10px; padding: 5px 2px; } @@ -61,7 +61,7 @@ height: 16px; background-size: cover; position: absolute; - top: 6px; + top: 11px; right: 40px; cursor: pointer; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMyIDMyIiBoZWlnaHQ9IjMycHgiIGlkPSLQodC70L7QuV8xIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJGdWxsc2NyZWVuIj48cGF0aCBkPSJNMzIsMWMwLTAuNTU4LTAuNDQyLTEtMS0xbC04Ljk4NSwwYy0wLjU2OCwwLTAuOTkxLDAuNDQ4LTAuOTkyLDEuMDE2QzIxLjAyMywxLjU4MywyMS40NDcsMiwyMi4wMTUsMkwzMCwyICAgbC0wLjAxNiw4LjAyM2MwLDAuNTY4LDAuNDMyLDEsMSwxYzAuNTY4LTAuMDAxLDEtMC40MzIsMS0xTDMyLDEuMDE1YzAtMC4wMDMtMC4wMDEtMC4wMDUtMC4wMDEtMC4wMDdDMzEuOTk5LDEuMDA1LDMyLDEuMDAzLDMyLDF6ICAgIiBmaWxsPSIjMTIxMzEzIi8+PHBhdGggZD0iTTEwLjAxNiwwSDEuMDMxQzEuMDI4LDAsMS4wMjYsMC4wMDEsMS4wMjMsMC4wMDFDMS4wMjEsMC4wMDEsMS4wMTgsMCwxLjAxNiwwYy0wLjU1OCwwLTEsMC40NDItMSwxICAgTDAsMTAuMDA4QzAsMTAuNTc2LDAuNDQ4LDExLDEuMDE2LDExQzEuNTgzLDExLDIsMTAuNTc2LDIsMTAuMDA4TDIuMDE2LDJoOGMwLjU2OCwwLDEtMC40MzIsMS0xQzExLjAxNSwwLjQzMiwxMC41ODMsMCwxMC4wMTYsMHoiIGZpbGw9IiMxMjEzMTMiLz48cGF0aCBkPSJNOS45ODUsMzBIMnYtOGMwLTAuNTY4LTAuNDMyLTEtMS0xYy0wLjU2OCwwLTEsMC40MzItMSwxdjguOTg1YzAsMC4wMDMsMC4wMDEsMC4wMDUsMC4wMDEsMC4wMDcgICBDMC4wMDEsMzAuOTk1LDAsMzAuOTk3LDAsMzFjMCwwLjU1OCwwLjQ0MiwxLDEsMWg4Ljk4NWMwLjU2OCwwLDAuOTkxLTAuNDQ4LDAuOTkyLTEuMDE2QzEwLjk3NywzMC40MTcsMTAuNTUzLDMwLDkuOTg1LDMweiIgZmlsbD0iIzEyMTMxMyIvPjxwYXRoIGQ9Ik0zMC45ODQsMjEuMDIzYy0wLjU2OCwwLTAuOTg1LDAuNDI0LTAuOTg0LDAuOTkyVjMwbC04LDBjLTAuNTY4LDAtMSwwLjQzMi0xLDFjMCwwLjU2OCwwLjQzMiwxLDEsMSAgIGw4Ljk4NSwwYzAuMDAzLDAsMC4wMDUtMC4wMDEsMC4wMDctMC4wMDFDMzAuOTk1LDMxLjk5OCwzMC45OTcsMzIsMzEsMzJjMC41NTgsMCwxLTAuNDQyLDEtMXYtOC45ODUgICBDMzIsMjEuNDQ3LDMxLjU1MiwyMS4wMjMsMzAuOTg0LDIxLjAyM3oiIGZpbGw9IiMxMjEzMTMiLz48L2c+PGcvPjxnLz48Zy8+PGcvPjxnLz48Zy8+PC9zdmc+'); @@ -69,6 +69,13 @@ border: none; } +.__better_github_pr_file_filter { + position: absolute; + top: 5px; + padding: 2px 5px; + width: calc(100% - 100px); +} + .__better_github_pr_noselect { -webkit-touch-callout: none; /* iOS Safari */ -webkit-user-select: none; /* Safari */