diff --git a/src/app.js b/src/app.js
index a2181e5..c271980 100644
--- a/src/app.js
+++ b/src/app.js
@@ -10,7 +10,17 @@ export default function App() {
if (gitProvider.showLanding()) {
return ;
} else {
- return ;
+ return (
+
+
+ {/* */}
+
+ );
}
}
diff --git a/src/git-providers/differ.js b/src/git-providers/differ.js
index c46765d..9f04a44 100644
--- a/src/git-providers/differ.js
+++ b/src/git-providers/differ.js
@@ -105,5 +105,11 @@ export function getChanges(lines) {
i++;
}
+ if (currentChange) {
+ currentChange.end = i - 1;
+ changes.push(currentChange);
+ currentChange = null;
+ }
+
return changes;
}
diff --git a/src/icons/chrome.svg b/src/icons/chrome.svg
new file mode 100644
index 0000000..c36112c
--- /dev/null
+++ b/src/icons/chrome.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/icons/cli.svg b/src/icons/cli.svg
new file mode 100644
index 0000000..c06ba82
--- /dev/null
+++ b/src/icons/cli.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/icons/firefox.svg b/src/icons/firefox.svg
new file mode 100644
index 0000000..c52dd46
--- /dev/null
+++ b/src/icons/firefox.svg
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/icons/vscode.svg b/src/icons/vscode.svg
new file mode 100644
index 0000000..b1b42d8
--- /dev/null
+++ b/src/icons/vscode.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/landing.css b/src/landing.css
new file mode 100644
index 0000000..b8121b9
--- /dev/null
+++ b/src/landing.css
@@ -0,0 +1,137 @@
+.extensions {
+ display: flex;
+ justify-content: center;
+ padding-bottom: 10px;
+}
+
+.extensions > * {
+ padding: 4px 10px;
+}
+
+.landing a {
+ color: inherit;
+}
+
+.landing {
+ color: #222;
+ background: #fafafa;
+}
+
+.landing > * {
+ background: linear-gradient(rgba(255, 255, 255), rgba(220, 220, 220));
+}
+
+.landing header {
+ display: flex;
+ padding: 100px 0px;
+}
+.landing h1 {
+ margin-top: 10px;
+}
+
+.landing header a {
+ color: rgb(1, 22, 39);
+}
+
+.landing header a.button {
+ background: rgb(1, 22, 39);
+ color: #fafafa;
+ padding: 9px 16px;
+ margin: 10px auto 15px;
+ width: 80px;
+ text-align: center;
+ border-radius: 4px;
+ text-decoration: none;
+ display: block;
+}
+
+.landing header video {
+ margin-right: 115px;
+}
+
+@media (max-width: 1130px) {
+ .landing header video {
+ margin-right: 0px;
+ margin-bottom: 20px;
+ max-width: 80%;
+ height: auto !important;
+ min-width: 350px;
+ }
+ .landing header {
+ flex-direction: column;
+ padding: 40px 0px 20px;
+ }
+ .landing header .summary {
+ width: 560px;
+ max-width: 80%;
+ }
+}
+
+.landing .testimonies {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ display: grid;
+ width: 800px;
+ margin: 10px auto;
+ grid-template-columns: 400px 400px;
+ grid-template-rows: 180px 150px;
+ grid-column-gap: 14px;
+ grid-row-gap: 14px;
+}
+
+@media (max-width: 900px) {
+ .landing .testimonies {
+ grid-template-columns: 400px;
+ grid-template-rows: 180px 180px 150px 150px;
+ width: 400px;
+ }
+}
+@media (max-width: 420px) {
+ .landing .testimonies {
+ grid-template-columns: auto;
+ grid-template-rows: auto;
+ width: 90%;
+ }
+}
+
+.landing .testimonies > * {
+ border: 1px solid #e1e8ed;
+ display: inline-block;
+ text-decoration: none;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ border-radius: 5px;
+}
+
+.landing blockquote {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ margin: 0;
+ padding: 19px;
+ box-sizing: border-box;
+}
+
+.landing blockquote p {
+ flex: 1;
+ margin: 0 0 12px 0;
+}
+
+.landing blockquote img {
+ height: 36px;
+ width: 36px;
+ border-radius: 50%;
+}
+
+.landing .support > div {
+ width: 800px;
+}
+
+@media (max-width: 900px) {
+ .landing .support > div {
+ width: 600px;
+ }
+}
+@media (max-width: 600px) {
+ .landing .support > div {
+ width: 350px;
+ }
+}
diff --git a/src/landing.js b/src/landing.js
index 7f6325d..7e7fc77 100644
--- a/src/landing.js
+++ b/src/landing.js
@@ -1,55 +1,205 @@
import React from "react";
import demo from "./demo.gif";
+import { ReactComponent as ChromeLogo } from "./icons/chrome.svg";
+import { ReactComponent as FirefoxLogo } from "./icons/firefox.svg";
+import { ReactComponent as CliLogo } from "./icons/cli.svg";
+import { ReactComponent as VsCodeLogo } from "./icons/vscode.svg";
+import "./landing.css";
export default function Landing() {
const url = `${window.location.protocol}//${
window.location.host
}/babel/babel/blob/master/packages/babel-core/test/browserify.js`;
return (
-
-
-
Git History
-
-
- Quickly browse the history of any GitHub file (GitLab and Bitbucket{" "}
-
- coming soon
-
- ):
+
+
+
+
+
+
+
Git History
+ Quickly browse the history of files in any git repo:
- Replace github.com with{" "}
- github.githistory.xyz in any file url
+ Go to a file in GitHub (or{" "}
+ GitLab , or Bitbucket )
- There's no step two
+
+ Replace github.com with github.githistory.xyz
+
+ There's no step three
-
Try it
+
+ Try it
+
+
Also available as extensions:
+
+
-
- You can also add an Open in Git History button to
- GitHub with the{" "}
-
- Chrome
- {" "}
- and{" "}
-
- Firefox
- {" "}
- extensions.
-
- CLI
- For local git repos use the{" "}
- CLI .
- · · ·
+
+
+
+
+ );
+}
+
+function Testimonies() {
+ return (
+
+ What people are saying...
+
+
+ Git History caught our eye with a beautiful way to tour the history of
+ a file in a GitHub repo. ... there’s nothing to download and install:
+ point Git History to a repository file URL to start traveling through
+ time. Great Scott!
+
+
+ Ahh you know when you need to browse your Git history but it takes a
+ while to find what you are looking for? Git History lets you browse
+ the history in no-time. Useful.
+
+
+ I love little apps like this that copy the URL structure of another
+ app, so you can replace just the TLD and it does something useful.
+
+
+ There's something really satisfying about browsing file history with
+ this timeline UI. It's super nice.
+
+
+
+ );
+}
+
+function Testimony({ link, avatar, name, children }) {
+ return (
+
+
+ {children}
+
+
+
+ {name}
+
+
+
+
+ );
+}
+
+function ResponsivePicture({ link, src, alt, append = "" }) {
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+function Backers() {
+ return (
+
+ Support Git History
+
Sponsors
Support this project by becoming a sponsor. Your logo will show up
@@ -58,26 +208,37 @@ export default function Landing() {
Become a sponsor
-
-
-
+
Backers
- Thank you to all our backers! 🙏.{" "}
+ Thank you to all our backers!{" "}
+
+ 🙏
+
+ .{" "}
Become a backer to help us ship more features!
-
-
-
+
+
Contributors
+
This project exists thanks to all the people who contribute.
+
+
-
+
);
}
diff --git a/src/scroller.js b/src/scroller.js
index 217d1f1..37a0653 100644
--- a/src/scroller.js
+++ b/src/scroller.js
@@ -2,7 +2,7 @@ import React from "react";
import useChildren from "./use-virtual-children";
import "./scroller.css";
import useSpring from "./use-spring";
-import { nextIndex, prevIndex, closestIndex, getScrollTop } from "./utils";
+import { nextIndex, prevIndex, getScrollTop } from "./utils";
const initialState = {
snap: false,
@@ -23,6 +23,8 @@ export default function Scroller({
const reducer = (prevState, action) => {
switch (action.type) {
+ case "unsnap":
+ return !prevState.snap ? prevState : { ...prevState, snap: false };
case "change-area":
if (snapAreas.length === 0) {
return prevState;
@@ -129,6 +131,12 @@ export default function Scroller({
// });
// }, [snapAreas]);
+ React.useEffect(() => {
+ dispatch({
+ type: "unsnap"
+ });
+ }, [snapAreas]);
+
React.useLayoutEffect(() => {
if (snap) {
ref.current.scrollTop = top;
diff --git a/src/use-virtual-children.js b/src/use-virtual-children.js
index 5fc565c..8a08ae1 100644
--- a/src/use-virtual-children.js
+++ b/src/use-virtual-children.js
@@ -10,7 +10,7 @@ export default function useChildren({
}) {
const children = [];
- const extraRender = 1500;
+ const extraRender = 1000;
const topT = top - extraRender;
const bottomT = top + height + extraRender;