From 032859fccb57eefad876a283c25cd0df3cd0215f Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Sun, 24 Feb 2019 01:27:03 -0300 Subject: [PATCH] Make virtual children --- package.json | 1 + src/history.js | 6 ++- src/slide.js | 103 ++++++++++++++++++++++++++++++++------ src/todo.md | 2 + src/useVirtualChildren.js | 43 ++++++++++++++++ yarn.lock | 70 +++++++++++++++++++++++++- 6 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 src/todo.md create mode 100644 src/useVirtualChildren.js diff --git a/package.json b/package.json index 75b6726..9bd84c7 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "netlify-auth-providers": "^1.0.0-alpha5", "prismjs": "^1.15.0", "react": "^16.8.1", + "react-custom-scrollbars": "^4.2.1", "react-dom": "^16.8.1", "react-scripts": "2.1.3", "react-swipeable": "^4.3.2", diff --git a/src/history.js b/src/history.js index 20c521d..cf2eda9 100644 --- a/src/history.js +++ b/src/history.js @@ -135,7 +135,11 @@ function Slides({ commits, slideLines, loadMore }) { currentIndex={current} selectCommit={index => setClampedTarget(index)} /> - + diff --git a/src/slide.js b/src/slide.js index 7cd698e..2be2988 100644 --- a/src/slide.js +++ b/src/slide.js @@ -1,6 +1,8 @@ import React from "react"; import animation from "./animation"; import theme from "./nightOwl"; +import useChildren from "./useVirtualChildren"; +import { Scrollbars } from "react-custom-scrollbars"; const themeStylesByType = Object.create(null); theme.styles.forEach(({ types, style }) => { @@ -27,32 +29,101 @@ function Line({ line, style }) { ); } -export default function Slide({ time, lines }) { - const styles = animation((time + 1) / 2, lines); +function getLineHeight(line, i, { styles }) { + return styles[i].height != null ? styles[i].height : 15; +} + +function getLine(line, i, { styles }) { + return ; +} + +function Lines({ height, top, lines, styles }) { + const children = useChildren({ + height, + top, + items: lines, + getRow: getLine, + getRowHeight: getLineHeight, + data: { styles } + }); + return children; +} + +function useHeight(ref) { + let [height, setHeight] = React.useState(null); + + function handleResize() { + setHeight(ref.current.offsetHeight); + } + + React.useEffect(() => { + handleResize(); + window.addEventListener("resize", handleResize); + return () => { + window.removeEventListener("resize", handleResize); + }; + }, [ref.current]); + + return height; +} + +function Slide({ lines, styles }) { + const [top, setTop] = React.useState(0); + + let ref = React.useRef(null); + let height = useHeight(ref); return ( -
-      
-        {lines.map((line, i) => (
-          
-        ))}
-      
-    
+ setTop(e.target.scrollTop)} + renderThumbVertical={({ style, ...props }) => ( +
+ )} + > + + + + + +
); } + +export default function SlideWrapper({ time, lines }) { + const styles = animation((time + 1) / 2, lines); + return ; +} diff --git a/src/todo.md b/src/todo.md new file mode 100644 index 0000000..8431d6a --- /dev/null +++ b/src/todo.md @@ -0,0 +1,2 @@ +- move diffing to web worker +- make diffing incremental diff --git a/src/useVirtualChildren.js b/src/useVirtualChildren.js new file mode 100644 index 0000000..e133ba4 --- /dev/null +++ b/src/useVirtualChildren.js @@ -0,0 +1,43 @@ +import React from "react"; + +export default function useChildren({ + items, + getRow, + getRowHeight, + height, + top, + data +}) { + const children = []; + + const extraRender = 200; + + const topT = top - extraRender; + const bottomT = top + height + extraRender; + let h = 0; + + let topPlaceHolderH = 0; + let bottomPlaceholderH = 0; + + // This is the bottleneck + items.forEach((item, i) => { + const itemH = getRowHeight(item, i, data); + const nextH = h + itemH; + const isOverTop = nextH < topT; + const isUnderBottom = h > bottomT; + + if (isOverTop) { + topPlaceHolderH += itemH; + } else if (isUnderBottom) { + bottomPlaceholderH += itemH; + } else { + children.push(getRow(item, i, data)); + } + + h = nextH; + }); + + children.unshift(
); + children.push(
); + return children; +} diff --git a/yarn.lock b/yarn.lock index a81aebc..324203d 100755 --- a/yarn.lock +++ b/yarn.lock @@ -1141,6 +1141,11 @@ acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.5.tgz#81730c0815f3f3b34d8efa95cb7430965f4d887a" integrity sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg== +add-px-to-style@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/add-px-to-style/-/add-px-to-style-1.0.0.tgz#d0c135441fa8014a8137904531096f67f28f263a" + integrity sha1-0ME1RB+oAUqBN5BFMQlvZ/KPJjo= + address@1.0.3, address@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" @@ -3090,6 +3095,15 @@ dom-converter@~0.2: dependencies: utila "~0.4" +dom-css@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/dom-css/-/dom-css-2.1.0.tgz#fdbc2d5a015d0a3e1872e11472bbd0e7b9e6a202" + integrity sha1-/bwtWgFdCj4YcuEUcrvQ57nmogI= + dependencies: + add-px-to-style "1.0.0" + prefix-style "2.0.1" + to-camel-case "1.0.0" + dom-serializer@0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -6026,7 +6040,7 @@ loglevel@^1.4.1: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -7783,6 +7797,11 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2, postcss@^7.0.5, postcss@^7.0.7: source-map "^0.6.1" supports-color "^5.5.0" +prefix-style@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/prefix-style/-/prefix-style-2.0.1.tgz#66bba9a870cfda308a5dc20e85e9120932c95a06" + integrity sha1-ZrupqHDP2jCKXcIOhekSCTLJWgY= + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -7871,6 +7890,15 @@ prompts@^0.1.9: kleur "^2.0.1" sisteransi "^0.1.1" +prop-types@^15.5.10: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + prop-types@^15.5.8, prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" @@ -7986,6 +8014,13 @@ raf@3.4.0: dependencies: performance-now "^2.1.0" +raf@^3.1.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" + integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== + dependencies: + performance-now "^2.1.0" + randomatic@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" @@ -8046,6 +8081,15 @@ react-app-polyfill@^0.2.0: raf "3.4.0" whatwg-fetch "3.0.0" +react-custom-scrollbars@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db" + integrity sha1-gw/ZUCkn6X6KeMIIaBOJmyqLZts= + dependencies: + dom-css "^2.0.0" + prop-types "^15.5.10" + raf "^3.1.0" + react-dev-utils@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-7.0.1.tgz#c53e759a22668ee2c0d146c24ce4bdec2b41e3c8" @@ -8091,6 +8135,11 @@ react-error-overlay@^5.1.2: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.2.tgz#888957b884d4b25b083a82ad550f7aad96585394" integrity sha512-7kEBKwU9R8fKnZJBRa5RSIfay4KJwnYvKB6gODGicUmDSAhQJ7Tdnll5S0RLtYrzRfMVXlqYw61rzrSpP4ThLQ== +react-is@^16.8.1: + version "16.8.3" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.3.tgz#4ad8b029c2a718fc0cfc746c8d4e1b7221e5387d" + integrity sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA== + react-scripts@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-2.1.3.tgz#6e49be279f4039fb9f330d2b3529b933b8e90945" @@ -9490,6 +9539,13 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= +to-camel-case@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46" + integrity sha1-GlYFSy+daWKYzmamCJcyK29CPkY= + dependencies: + to-space-case "^1.0.0" + to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -9500,6 +9556,11 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= +to-no-case@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/to-no-case/-/to-no-case-1.0.2.tgz#c722907164ef6b178132c8e69930212d1b4aa16a" + integrity sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo= + to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" @@ -9525,6 +9586,13 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +to-space-case@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-space-case/-/to-space-case-1.0.0.tgz#b052daafb1b2b29dc770cea0163e5ec0ebc9fc17" + integrity sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc= + dependencies: + to-no-case "^1.0.0" + topo@2.x.x: version "2.0.2" resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182"