Merge branch 'develop'

This commit is contained in:
EnixCoda 2019-11-04 20:47:10 +08:00
commit 07450daf7b
No known key found for this signature in database
GPG key ID: 0C1A07377913A1DD
18 changed files with 3221 additions and 151 deletions

View file

@ -6,8 +6,8 @@
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 661.33331 200"
height="200"
width="661.33331"
height="90"
width="297.6"
xml:space="preserve"
id="svg2"
version="1.1"><metadata
@ -346,4 +346,4 @@
id="g296"><path
id="path298"
style="fill:#5f6368;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 0,0 c -0.057,0.784 -0.416,1.53 -1.078,2.24 -0.663,0.709 -1.649,1.065 -2.954,1.065 -0.952,0 -1.779,-0.299 -2.479,-0.897 -0.7,-0.597 -1.18,-1.4 -1.441,-2.408 z m -3.696,-8.96 c -2.073,0 -3.757,0.69 -5.054,2.072 -1.298,1.381 -1.946,3.126 -1.946,5.237 0,1.997 0.63,3.714 1.889,5.151 1.26,1.437 2.87,2.156 4.83,2.156 2.035,0 3.664,-0.663 4.886,-1.988 C 2.132,2.343 2.743,0.569 2.743,-1.651 L 2.716,-2.128 H -8.12 c 0.074,-1.382 0.536,-2.474 1.386,-3.275 0.848,-0.803 1.842,-1.204 2.981,-1.204 1.849,0 3.099,0.784 3.753,2.351 L 2.296,-5.208 C 1.848,-6.271 1.11,-7.163 0.084,-7.882 -0.943,-8.6 -2.203,-8.96 -3.696,-8.96" /></g></g></g></g></svg>
d="m 0,0 c -0.057,0.784 -0.416,1.53 -1.078,2.24 -0.663,0.709 -1.649,1.065 -2.954,1.065 -0.952,0 -1.779,-0.299 -2.479,-0.897 -0.7,-0.597 -1.18,-1.4 -1.441,-2.408 z m -3.696,-8.96 c -2.073,0 -3.757,0.69 -5.054,2.072 -1.298,1.381 -1.946,3.126 -1.946,5.237 0,1.997 0.63,3.714 1.889,5.151 1.26,1.437 2.87,2.156 4.83,2.156 2.035,0 3.664,-0.663 4.886,-1.988 C 2.132,2.343 2.743,0.569 2.743,-1.651 L 2.716,-2.128 H -8.12 c 0.074,-1.382 0.536,-2.474 1.386,-3.275 0.848,-0.803 1.842,-1.204 2.981,-1.204 1.849,0 3.099,0.784 3.753,2.351 L 2.296,-5.208 C 1.848,-6.271 1.11,-7.163 0.084,-7.882 -0.943,-8.6 -2.203,-8.96 -3.696,-8.96" /></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View file

@ -1,6 +1,6 @@
# Gitako
Yet another Chrome extension for GitHub. Inspired by [Octotree](https://github.com/buunguyen/octotree) & [GayHub](https://github.com/jawil/GayHub), thanks to them! Gitako is aimed at providing the best performance, better UX, more consistent UI and more essential features.
Yet another extension for GitHub, available on both Chrome and Firefox. Inspired by [Octotree](https://github.com/buunguyen/octotree) & [GayHub](https://github.com/jawil/GayHub), thanks to them! Gitako is aimed at providing the best performance, better UX, more consistent UI and more essential features.
### Features
@ -20,11 +20,11 @@ Yet another Chrome extension for GitHub. Inspired by [Octotree](https://github.c
### Install
<div style="max-width: 300px">
[![Install for Chrome](./ChromeWebStoreBadge.svg)](https://chrome.google.com/webstore/detail/gitako-github-file-tree/giljefjcheohhamkjphiebfjnlphnokk)
[![Please install from Chrome Web Store](./ChromeWebStoreBadge.svg)](https://chrome.google.com/webstore/detail/gitako-github-file-tree/giljefjcheohhamkjphiebfjnlphnokk)
[Or install for Firefox](https://addons.mozilla.org/en-US/firefox/addon/gitako-github-file-tree/)
</div>
> Gitako for Firefox is still in beta
### Issues

View file

@ -1,6 +1,6 @@
{
"name": "gitako",
"version": "0.5.14",
"version": "0.5.15",
"description": "The missing part of GitHub.",
"repository": "https://github.com/EnixCoda/Gitako",
"author": "EnixCoda",
@ -8,6 +8,7 @@
"private": true,
"scripts": {
"start": "webpack --watch",
"debug-firefox": "web-ext run -s dist",
"postversion": "node scripts/version.js && npm run roll",
"build": "NODE_ENV=production webpack",
"analyse-bundle": "ANALYSE= NODE_ENV=production webpack",
@ -17,6 +18,7 @@
"@primer/octicons": "^9.1.1",
"@primer/octicons-react": "^9.2.0",
"@sentry/browser": "^5.5.0",
"@types/firefox-webext-browser": "^70.0.1",
"@types/react-window": "^1.8.1",
"ini": "^1.3.5",
"js-base64": "^2.5.1",
@ -24,7 +26,8 @@
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-window": "^1.8.5",
"safe-touch": "^0.2.2"
"safe-touch": "^0.2.2",
"webextension-polyfill": "^0.5.0"
},
"devDependencies": {
"@babel/cli": "^7.2.3",
@ -35,7 +38,6 @@
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
"@sentry/cli": "^1.47.1",
"@types/chrome": "^0.0.87",
"@types/ini": "^1.3.30",
"@types/js-base64": "^2.3.1",
"@types/node": "^11.10.4",
@ -56,6 +58,7 @@
"typescript": "^3.6.3",
"uglifyjs-webpack-plugin": "^2.1.2",
"url-loader": "^1.1.2",
"web-ext": "^3.2.0",
"webpack": "^4.29.6",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.1.2"

View file

@ -7,9 +7,9 @@ VERSION=v$(node scripts/get-version.js)
echo "Got version $VERSION"
# sentry
yarn sentry-cli releases new "$VERSION"
git push # make sure sentry can retrieve current commit on remote
yarn sentry-cli releases set-commits $VERSION --commit "EnixCoda/Gitako@$GIT_SHA"
yarn sentry-cli releases new "$VERSION"
yarn sentry-cli releases set-commits "$VERSION" --auto
yarn sentry-cli releases files "$VERSION" upload-sourcemaps dist --no-rewrite
yarn sentry-cli releases finalize "$VERSION"

View file

@ -6,11 +6,15 @@ import { version } from '../package.json'
const PUBLIC_KEY = 'd22ec5c9cc874539a51c78388c12e3b0'
const PROJECT_ID = '1406497'
Sentry.init({
const sentryOptions: Sentry.BrowserOptions = {
dsn: `https://${PUBLIC_KEY}@sentry.io/${PROJECT_ID}`,
release: `v${version}`,
environment: IN_PRODUCTION_MODE ? 'production' : 'development',
})
// Not safe to activate all integrations in non-Chrome environments where Gitako may not run in top context
// https://docs.sentry.io/platforms/javascript/#sdk-integrations
integrations: ints => ints.filter(({ name }) => name !== 'TryCatch'),
}
Sentry.init(sentryOptions)
export function raiseError(error: Error, extra?: any) {
return reportError(error, extra)

View file

@ -1,6 +1,6 @@
import * as React from 'react'
import SideBar from 'components/SideBar'
import { raiseError } from 'analytics'
import SideBar from 'components/SideBar'
import * as React from 'react'
export default class Gitako extends React.PureComponent {
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {

View file

@ -8,6 +8,7 @@ import Octicon, {
FileZip,
Gear,
Grabber,
Icon as OcticonIcon,
Markdown,
Octoface,
Reply,
@ -17,37 +18,78 @@ import Octicon, {
import * as React from 'react'
import cx from 'utils/cx'
function getSVGIconComponent(type: string) {
function getSVGIconComponent(
type: string,
): {
IconComponent: OcticonIcon
name: string
} {
switch (type) {
case 'submodule':
return Submodule
return {
IconComponent: Submodule,
name: 'Submodule',
}
case 'grabber':
return Grabber
return {
IconComponent: Grabber,
name: 'Grabber',
}
case 'octoface':
return Octoface
return {
IconComponent: Octoface,
name: 'Octoface',
}
case 'chevron-down':
return ChevronDown
return {
IconComponent: ChevronDown,
name: 'ChevronDown',
}
case 'x':
return X
return {
IconComponent: X,
name: 'X',
}
case 'gear':
return Gear
return {
IconComponent: Gear,
name: 'Gear',
}
case 'folder':
return TriangleRight
return {
IconComponent: TriangleRight,
name: 'TriangleRight',
}
case 'go-to':
return Reply
return {
IconComponent: Reply,
name: 'Reply',
}
case '.pdf':
return FilePdf
return {
IconComponent: FilePdf,
name: 'FilePdf',
}
case '.zip':
case '.rar':
case '.7z':
return FileZip
return {
IconComponent: FileZip,
name: 'FileZip',
}
case '.md':
return Markdown
return {
IconComponent: Markdown,
name: 'Markdown',
}
case '.png':
case '.jpg':
case '.gif':
case '.bmp':
return FileMedia
return {
IconComponent: FileMedia,
name: 'FileMedia',
}
case '.js':
case '.jsx':
case '.ts':
@ -58,14 +100,20 @@ function getSVGIconComponent(type: string) {
case '.less':
case '.scss':
case '.sass':
return FileCode
return {
IconComponent: FileCode,
name: 'FileCode',
}
// TODO: adapt to more file types
// case '': return FileBinary
// case '': return FileSubmodule
// case '': return FileSymlinkDirectory
// case '': return FileSymlinkFile
default:
return File
return {
IconComponent: File,
name: 'File',
}
}
}
@ -76,12 +124,13 @@ type Props = {
}
const Icon: React.SFC<Props> = function Icon({ type, className = undefined, ...otherProps }) {
const icon = getSVGIconComponent(type)
const { name, IconComponent } = getSVGIconComponent(type)
const mergedClassName = cx('octicon', name)
return (
<div className={cx('octicon-wrapper', className)} {...otherProps}>
{React.createElement(Octicon, {
icon,
className: cx('octicon', icon.name),
icon: IconComponent,
className: mergedClassName,
})}
</div>
)

View file

@ -1,4 +1,5 @@
import Icon from 'components/Icon'
import { oauth } from 'env'
import * as React from 'react'
import configHelper, { Config, configKeys } from 'utils/configHelper'
import { friendlyFormatShortcut, JSONRequest, parseURLSearch } from 'utils/general'
@ -14,11 +15,6 @@ const wikiLinks = {
createAccessToken: `${WIKI_HOME_LINK}/How-to-create-access-token-for-Gitako%3F`,
}
const oauth = {
clientId: process.env.GITHUB_OAUTH_CLIENT_ID,
clientSecret: process.env.GITHUB_OAUTH_CLIENT_SECRET,
}
const ACCESS_TOKEN_REGEXP = /^[0-9a-f]{40}$/
type Props = {

View file

@ -19,7 +19,7 @@ export default function SizeObserver({ type = 'div', children, ...rest }: Props)
height: undefined,
})
React.useEffect(() => {
React.useLayoutEffect(() => {
if (features.resize) {
const observer = new window.ResizeObserver(entries => {
const entry = entries[0]

View file

@ -283,10 +283,15 @@
display: flex;
align-items: center;
.octicon {
&-icon {
width: 20px;
height: 20px;
animation: rotate 2s infinite linear;
.octicon {
width: 20px;
height: 20px;
animation: rotate 2s infinite linear;
}
}
}
}

View file

@ -1 +1,11 @@
export const IN_PRODUCTION_MODE = process.env.NODE_ENV === 'production'
type KnownPlatform = 'chrome' | 'firefox'
type Platform = KnownPlatform | Exclude<string, keyof KnownPlatform>
export const PLATFORM: Platform = process.env.PLATFORM || 'unknown'
export const oauth = {
clientId: process.env.GITHUB_OAUTH_CLIENT_ID,
clientSecret: process.env.GITHUB_OAUTH_CLIENT_SECRET,
}

1
src/firefox-shim.js Normal file
View file

@ -0,0 +1 @@
window.requestAnimationFrame = window.requestAnimationFrame.bind(window)

View file

@ -1,25 +1,18 @@
{
"manifest_version": 2,
"name": "Gitako - Github file tree",
"version": "0.5.14",
"version": "0.5.15",
"description": "The missing part of GitHub.",
"author": "EnixCoda",
"icons": {
"128": "icons/Gitako-128x128.png"
},
"homepage_url": "https://github.com/EnixCoda/Gitako",
"permissions": [
"storage",
"*://github.com/*"
],
"permissions": ["storage", "*://*.github.com/*", "*://*.sentry.io/*"],
"content_scripts": [
{
"matches": [
"https://github.com/*"
],
"js": [
"content.js"
]
"matches": ["https://github.com/*"],
"js": ["firefox-shim.js", "browser-polyfill.js", "content.js"]
}
]
}
}

View file

@ -302,9 +302,9 @@ const clippy = createClippy()
let currentCodeSnippetElement: Element
function attachCopySnippet() {
const readmeSelector = '.repository-content #readme'
const readmeSelector = '.repository-content div#readme'
return $(readmeSelector, () => {
const readmeArticleSelector = '.repository-content #readme article'
const readmeArticleSelector = '.repository-content div#readme article'
$(
readmeArticleSelector,
readmeElement =>
@ -327,7 +327,7 @@ function attachCopySnippet() {
}
}),
() => {
const plainReadmeSelector = '.repository-content #readme .plain'
const plainReadmeSelector = '.repository-content div#readme .plain'
$(plainReadmeSelector, undefined, () =>
raiseError(
new Error('cannot find mount point for copy snippet button while readme exists'),

View file

@ -43,14 +43,18 @@ function isInCodePage(metaData: MetaData = {}) {
const { type, branchName } = mergedRepo
return Boolean(
isInRepoPage() &&
(!type || type === TYPES.TREE || type === TYPES.BLOB) &&
type !== TYPES.COMMIT &&
(branchName || (!type && !branchName))
(!type || type === TYPES.TREE || type === TYPES.BLOB) &&
type !== TYPES.COMMIT &&
(branchName || (!type && !branchName)),
)
}
function isCommitPath(path: string[]) {
return /^[a-z0-9]{40}$/.test(path[0])
return isCompleteCommitSHA(path[0])
}
function isCompleteCommitSHA(sha?: string) {
return typeof sha === 'string' && /^[abcdef0-9]{40}$/i.test(sha)
}
function getCurrentPath(branchName = '') {
@ -61,13 +65,19 @@ function getCurrentPath(branchName = '') {
path.shift()
} else {
// path = branch/name/path/to/item or HEAD/path/to/item
// HEAD is not a valid branch name. Coming up with HEAD, means currently detached.
// HEAD is not a valid branch name. Getting HEAD means being detached.
if (path[0] === 'HEAD') path.shift()
else {
const slicedBranchName = branchName.split('/')
while (slicedBranchName.length) {
if (slicedBranchName[0] === path[0]) {
slicedBranchName.shift()
const splitBranchName = branchName.split('/')
while (splitBranchName.length) {
if (
splitBranchName[0] === path[0] ||
// Keep consuming as their heads are same
(splitBranchName.length === 1 && splitBranchName[0].startsWith(path[0]))
// This happens when visiting URLs like /blob/{commitSHA}/path/to/file
// and {commitSHA} is shorter than we got from DOM
) {
splitBranchName.shift()
path.shift()
} else {
raiseError(new Error(`branch name and path prefix not match`))

View file

@ -1,11 +1,11 @@
const localStorage = chrome.storage.local
const localStorage = browser.storage.local
function get(mapping: string[] | null): Promise<any> {
return new Promise(resolve => localStorage.get(mapping, resolve))
return localStorage.get(mapping || undefined)
}
function set(value: any): Promise<void> {
return new Promise(resolve => localStorage.set(value, resolve))
return localStorage.set(value)
}
export default {

View file

@ -18,6 +18,14 @@ const plugins = [
from: './src/assets/icons/*',
to: 'icons/[name].[ext]',
},
{
from: 'node_modules/webextension-polyfill/dist/browser-polyfill.js',
to: 'browser-polyfill.js',
},
{
from: './src/firefox-shim.js',
to: 'firefox-shim.js',
},
]),
new ForkTsCheckerWebpackPlugin(),
new Dotenv(),

3155
yarn.lock

File diff suppressed because it is too large Load diff