From 4eca87e7b6bd5db4422934227d59fca30b68d038 Mon Sep 17 00:00:00 2001 From: Tal Bereznitskey Date: Fri, 11 May 2018 16:38:45 +0300 Subject: [PATCH] Add Scroll Spy to highlight current visible file --- src/js/components/branch.jsx | 7 ++++--- src/js/components/file.jsx | 7 +++++-- src/js/components/tree.jsx | 35 ++++++++++++++++++++++++++++++++--- src/js/lib.js | 31 +++++++++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/src/js/components/branch.jsx b/src/js/components/branch.jsx index 62b7c67..085ec57 100644 --- a/src/js/components/branch.jsx +++ b/src/js/components/branch.jsx @@ -2,16 +2,17 @@ import React from 'react' import TreeView from 'react-treeview' import File from './file' -const Branch = ({ nodeLabel, list, href, hasComments }) => { +const Branch = ({ nodeLabel, list, href, hasComments, diffElement, visibleElement }) => { if (href) { - return + const isVisible = (diffElement === visibleElement) + return } return ( {list.map(node => ( - + ))} diff --git a/src/js/components/file.jsx b/src/js/components/file.jsx index 02cbdde..55e24a2 100644 --- a/src/js/components/file.jsx +++ b/src/js/components/file.jsx @@ -1,10 +1,13 @@ import React from 'react' import fileIcons from 'file-icons-js' -const File = ({ name, href, hasComments }) => { +const highlightColor = '#ebebeb' +const transparentColor = 'transparent' + +const File = ({ name, href, hasComments, isVisible }) => { const className = fileIcons.getClassWithColor(name) return ( -
+
{name} {hasComments ? ' 💬' : ''}
diff --git a/src/js/components/tree.jsx b/src/js/components/tree.jsx index 44b1ad7..6525c08 100644 --- a/src/js/components/tree.jsx +++ b/src/js/components/tree.jsx @@ -1,14 +1,43 @@ import React from 'react' import Branch from './branch.jsx' +import { isElementVisible } from '../lib' class Tree extends React.Component { constructor (props) { super(props) this.onClose = this.onClose.bind(this) + this.onScroll = this.onScroll.bind(this) this.state = { - show: true + show: true, + visibleElement: null + } + } + + componentDidMount () { + window.addEventListener('DOMContentLoaded', this.onScroll, false) + window.addEventListener('load', this.onScroll, false) + window.addEventListener('scroll', this.onScroll, false) + window.addEventListener('resize', this.onScroll, 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) + } + + onScroll () { + const { visibleElement } = this.state + const { root } = this.props + const { diffElements = [] } = root + const nextVisibleElement = diffElements.find(isElementVisible) + if (nextVisibleElement !== visibleElement) { + this.setState({ + visibleElement: nextVisibleElement + }) } } @@ -20,7 +49,7 @@ class Tree extends React.Component { render () { const { root } = this.props - const { show } = this.state + const { show, visibleElement } = this.state if (!show) { return null @@ -31,7 +60,7 @@ class Tree extends React.Component { {root.list.map(node => ( - + ))}
diff --git a/src/js/lib.js b/src/js/lib.js index 58178d1..82a6380 100644 --- a/src/js/lib.js +++ b/src/js/lib.js @@ -42,7 +42,8 @@ export const createFileTree = () => { }) const tree = { nodeLabel: '/', - list: [] + list: [], + diffElements: [] } files.forEach(({ parts, href }, fileIndex) => { @@ -51,7 +52,15 @@ export const createFileTree = () => { let node = location.list.find(node => node.nodeLabel === part) if (!node) { const hasComments = (hasCommentsForFileIndex(fileIndex) > 0) - node = { nodeLabel: part, list: [], href: (index === parts.length - 1) ? href : null, hasComments } + const diffElement = document.getElementById(`diff-${fileIndex}`) + tree.diffElements.push(diffElement) + node = { + nodeLabel: part, + list: [], + href: (index === parts.length - 1) ? href : null, + hasComments, + diffElement + } location.list.push(node) } location.list = location.list.sort(sorter) @@ -63,3 +72,21 @@ export const createFileTree = () => { count: fileInfo.length } } + +export const isElementVisible = (el) => { + if (!el) { + return false + } + + const GITHUB_HEADER_HEIGHT = 60 + + const rect = el.getBoundingClientRect() + + const windowHeight = (window.innerHeight || document.documentElement.clientHeight) + const windowWidth = (window.innerWidth || document.documentElement.clientWidth) + + const vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= GITHUB_HEADER_HEIGHT) + const horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0) + + return (vertInView && horInView) +}