From 2d79763f974f63dc8996c8e1a4f8ecc7e2d19056 Mon Sep 17 00:00:00 2001 From: Jeroen van Warmerdam Date: Sun, 9 Jun 2019 17:37:24 +0200 Subject: [PATCH 1/6] Add link to forked repo below the original. Closes #1129 --- source/content.ts | 1 + source/features/forked-to.tsx | 99 +++++++++++++++++++++++++++++++++++ source/libs/page-detect.ts | 2 + 3 files changed, 102 insertions(+) create mode 100644 source/features/forked-to.tsx diff --git a/source/content.ts b/source/content.ts index bdd22905c7a..4e0225c8c2f 100644 --- a/source/content.ts +++ b/source/content.ts @@ -105,6 +105,7 @@ import './features/release-download-count'; import './features/open-issue-to-latest-comment'; import './features/highest-rated-comment'; import './features/clean-issue-filters'; +import './features/forked-to'; import './features/scrollable-code-and-blockquote.css'; import './features/center-reactions-popup.css'; diff --git a/source/features/forked-to.tsx b/source/features/forked-to.tsx new file mode 100644 index 00000000000..2cc5ffc2999 --- /dev/null +++ b/source/features/forked-to.tsx @@ -0,0 +1,99 @@ +import React from 'dom-chef'; +import select from 'select-dom'; +import features from '../libs/features'; +import cache from '../libs/cache'; +import {getRepoURL} from '../libs/utils'; +import {isOwnRepo} from '../libs/page-detect'; + +const getCacheKey = (repo: string): string => `forked-to:${repo}`; + +async function showForks(): Promise { + const cached = await getValidatedCache(getSourceRepo()); + const pageHeader = select('.pagehead h1.public')!; + for (const fork of cached.filter(fork => fork !== getRepoURL())) { + pageHeader.append( + forked to  + {fork} + + ); + } +} + +function rememberCurrentFork(): void { + if (!isOwnRepo()) { + return; + } + + const forkedRepo = findForkedRepo(); + if (forkedRepo) { + addAndStoreCache(forkedRepo, getRepoURL()); + } +} + +function watchForkDialog(): void { + const forkDialog = select('details-dialog[src*="/fork"]')!; + select('include-fragment', forkDialog)!.addEventListener('load', () => { + const forks = select.all('.octicon-repo-forked', forkDialog).map(forkElement => { + return forkElement.parentNode!.textContent!.trim(); + }); + addAndStoreCache(getSourceRepo(), ...forks); + }); +} + +function findForkedRepo(): string | undefined { + const forkSourceElement = select('.fork-flag:not(.rgh-forked) a'); + if (forkSourceElement) { + return forkSourceElement.pathname.substring(1); + } + + return undefined; +} + +function getSourceRepo(): string { + return findForkedRepo() || getRepoURL(); +} + +async function validateFork(repo: string): Promise { + const response = await fetch(location.origin + '/' + repo, {method: 'HEAD'}); + return response.ok; +} + +async function getValidatedCache(repo: string): Promise { + const cached = await cache.get(getCacheKey(repo)) || []; + const validForks = cached.filter(validateFork).sort(undefined); + + if (cached.length !== validForks.length) { + await cache.set(getCacheKey(repo), validForks, 10); + } + + return validForks; +} + +async function addAndStoreCache(repo: string, ...forks: string[]): Promise { + const cached = await cache.get(getCacheKey(repo)) || []; + for (const fork of forks) { + if (!cached.includes(fork)) { + cached.push(fork); + } + } + + await cache.set(getCacheKey(repo), cached, 10); +} + +async function init(): Promise { + watchForkDialog(); + + rememberCurrentFork(); + + showForks(); +} + +features.add({ + id: 'forked-to', + description: 'Add link to forked repo below the source', + include: [ + features.isRepo + ], + load: features.onAjaxedPages, + init +}); diff --git a/source/libs/page-detect.ts b/source/libs/page-detect.ts index 208b49565b8..bb3f0061926 100644 --- a/source/libs/page-detect.ts +++ b/source/libs/page-detect.ts @@ -89,6 +89,8 @@ export const isRepoSettings = (): boolean => /^settings/.test(getRepoPath()!); export const isRepoTree = (): boolean => isRepoRoot() || /^tree\//.test(getRepoPath()!); +export const isOwnRepo = (): boolean => isRepo() && select.exists('.reponav-item[href$="/settings"]'); + export const isSingleCommit = (): boolean => /^commit\/[0-9a-f]{5,40}/.test(getRepoPath()!); export const isSingleFile = (): boolean => /^blob\//.test(getRepoPath()!); From 1c5a152812b658a74834b46fcb929d267284447e Mon Sep 17 00:00:00 2001 From: Jeroen van Warmerdam Date: Wed, 19 Jun 2019 22:48:33 +0200 Subject: [PATCH 2/6] isRepoWithAccess --- source/features/forked-to.tsx | 4 ++-- source/libs/page-detect.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/features/forked-to.tsx b/source/features/forked-to.tsx index 2cc5ffc2999..8a30f5f59f6 100644 --- a/source/features/forked-to.tsx +++ b/source/features/forked-to.tsx @@ -3,7 +3,7 @@ import select from 'select-dom'; import features from '../libs/features'; import cache from '../libs/cache'; import {getRepoURL} from '../libs/utils'; -import {isOwnRepo} from '../libs/page-detect'; +import {isRepoWithAccess} from '../libs/page-detect'; const getCacheKey = (repo: string): string => `forked-to:${repo}`; @@ -20,7 +20,7 @@ async function showForks(): Promise { } function rememberCurrentFork(): void { - if (!isOwnRepo()) { + if (!isRepoWithAccess()) { return; } diff --git a/source/libs/page-detect.ts b/source/libs/page-detect.ts index bb3f0061926..639e1477e17 100644 --- a/source/libs/page-detect.ts +++ b/source/libs/page-detect.ts @@ -89,7 +89,7 @@ export const isRepoSettings = (): boolean => /^settings/.test(getRepoPath()!); export const isRepoTree = (): boolean => isRepoRoot() || /^tree\//.test(getRepoPath()!); -export const isOwnRepo = (): boolean => isRepo() && select.exists('.reponav-item[href$="/settings"]'); +export const isRepoWithAccess = (): boolean => isRepo() && select.exists('.reponav-item[href$="/settings"]'); export const isSingleCommit = (): boolean => /^commit\/[0-9a-f]{5,40}/.test(getRepoPath()!); From df48aa6f24d742fc6e58c3dc015a5293dbbede44 Mon Sep 17 00:00:00 2001 From: Jeroen van Warmerdam Date: Wed, 19 Jun 2019 22:48:47 +0200 Subject: [PATCH 3/6] slice over substring --- source/features/forked-to.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/features/forked-to.tsx b/source/features/forked-to.tsx index 8a30f5f59f6..4b55c14f6ba 100644 --- a/source/features/forked-to.tsx +++ b/source/features/forked-to.tsx @@ -43,7 +43,7 @@ function watchForkDialog(): void { function findForkedRepo(): string | undefined { const forkSourceElement = select('.fork-flag:not(.rgh-forked) a'); if (forkSourceElement) { - return forkSourceElement.pathname.substring(1); + return forkSourceElement.pathname.slice(1); } return undefined; From 86fe42d9f1130a50dd14aed01a4bfc4048c26779 Mon Sep 17 00:00:00 2001 From: Jeroen van Warmerdam Date: Sat, 22 Jun 2019 10:36:47 +0200 Subject: [PATCH 4/6] Fix merge --- source/features/forked-to.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/features/forked-to.tsx b/source/features/forked-to.tsx index 4b55c14f6ba..fb2e876dd57 100644 --- a/source/features/forked-to.tsx +++ b/source/features/forked-to.tsx @@ -1,7 +1,7 @@ import React from 'dom-chef'; import select from 'select-dom'; +import cache from 'webext-storage-cache'; import features from '../libs/features'; -import cache from '../libs/cache'; import {getRepoURL} from '../libs/utils'; import {isRepoWithAccess} from '../libs/page-detect'; From 73b8f8dfa4a62e09f2e939d42545845f8b0e10d3 Mon Sep 17 00:00:00 2001 From: Jeroen van Warmerdam Date: Mon, 1 Jul 2019 21:51:10 +0200 Subject: [PATCH 5/6] Readme and screenshot --- readme.md | 1 + source/features/forked-to.tsx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index ac067798a37..9d235c74b2e 100644 --- a/readme.md +++ b/readme.md @@ -143,6 +143,7 @@ GitHub Enterprise is also supported. More info in the options. - [SVG files in a PR default to rich-diff view.](https://user-images.githubusercontent.com/5243867/57125552-c08a2b00-6d81-11e9-9b84-cdb535baa98e.png) - [Download count next to release assets.](https://user-images.githubusercontent.com/14323370/58944460-e1aeb480-874f-11e9-8052-2d4dc794ecab.png) - [The most useful comment in issues is highlighted.](https://user-images.githubusercontent.com/1402241/58757449-5b238880-853f-11e9-9526-e86c41a32f00.png) +- [Add link to forked repo below the source.](https://user-images.githubusercontent.com/55841/60462644-25f77c80-9c4a-11e9-8c69-582d00dd75dd.png) ### Declutter diff --git a/source/features/forked-to.tsx b/source/features/forked-to.tsx index fb2e876dd57..addf0316d74 100644 --- a/source/features/forked-to.tsx +++ b/source/features/forked-to.tsx @@ -89,8 +89,9 @@ async function init(): Promise { } features.add({ - id: 'forked-to', + id: __featureName__, description: 'Add link to forked repo below the source', + screenshot: 'https://user-images.githubusercontent.com/55841/60462644-25f77c80-9c4a-11e9-8c69-582d00dd75dd.png', include: [ features.isRepo ], From 468efe538fc5785a8ecd39c6973d9ad7bcdb6188 Mon Sep 17 00:00:00 2001 From: Jeroen van Warmerdam Date: Tue, 2 Jul 2019 22:16:50 +0200 Subject: [PATCH 6/6] meta --- readme.md | 2 +- source/features/forked-to.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index 9d235c74b2e..7b98625c454 100644 --- a/readme.md +++ b/readme.md @@ -143,7 +143,7 @@ GitHub Enterprise is also supported. More info in the options. - [SVG files in a PR default to rich-diff view.](https://user-images.githubusercontent.com/5243867/57125552-c08a2b00-6d81-11e9-9b84-cdb535baa98e.png) - [Download count next to release assets.](https://user-images.githubusercontent.com/14323370/58944460-e1aeb480-874f-11e9-8052-2d4dc794ecab.png) - [The most useful comment in issues is highlighted.](https://user-images.githubusercontent.com/1402241/58757449-5b238880-853f-11e9-9526-e86c41a32f00.png) -- [Add link to forked repo below the source.](https://user-images.githubusercontent.com/55841/60462644-25f77c80-9c4a-11e9-8c69-582d00dd75dd.png) +- [Your repo forks are shown under the repo title.](https://user-images.githubusercontent.com/55841/60543588-f5c9df80-9d16-11e9-8667-52ff16b2cb16.png) ### Declutter diff --git a/source/features/forked-to.tsx b/source/features/forked-to.tsx index addf0316d74..5990c5ca4b5 100644 --- a/source/features/forked-to.tsx +++ b/source/features/forked-to.tsx @@ -90,8 +90,8 @@ async function init(): Promise { features.add({ id: __featureName__, - description: 'Add link to forked repo below the source', - screenshot: 'https://user-images.githubusercontent.com/55841/60462644-25f77c80-9c4a-11e9-8c69-582d00dd75dd.png', + description: 'Your repo forks are shown under the repo title', + screenshot: 'https://user-images.githubusercontent.com/55841/60543588-f5c9df80-9d16-11e9-8667-52ff16b2cb16.png', include: [ features.isRepo ],