build: upgrade UI dependencies

This commit is contained in:
EnixCoda 2022-05-12 23:21:33 +08:00
parent 7fadb5fd57
commit 771a10ea57
17 changed files with 361 additions and 1008 deletions

View file

@ -12,7 +12,7 @@
"dev-safari": "TARGET=safari yarn run dev",
"debug-firefox": "web-ext run --source-dir=dist --firefox-profile=firefox-profile --profile-create-if-missing --keep-profile-changes --start-url github.com/EnixCoda/Gitako",
"analyse-bundle": "ANALYSE= NODE_ENV=production webpack",
"postinstall": "rm -rf node_modules/@types/react-native && node scripts/fix-pjax-api",
"postinstall": "node scripts/fix-pjax-api",
"build": "VERSION=v$(node scripts/get-version.js) NODE_ENV=production webpack",
"roll": "make release",
"test": "yarn run test:parallel && yarn run test:non-parallel",
@ -20,9 +20,9 @@
"test:non-parallel": "NODE_ENV=test jest --config __tests__/jest.non-parallel.config.js"
},
"dependencies": {
"@primer/components": "^22.0.2",
"@primer/css": "^15.2.0",
"@primer/octicons-react": "^10.0.0",
"@primer/css": "^20.0.0",
"@primer/octicons-react": "^17.1.0",
"@primer/react": "^35.2.1",
"@sentry/browser": "^6.3.6",
"@types/history": "^5.0.0",
"@types/ini": "^1.3.31",
@ -31,17 +31,16 @@
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.3",
"@types/react-window": "^1.8.5",
"@types/styled-components": "^5.1.3",
"@types/styled-system__css": "^5.0.14",
"@types/styled-components": "^5.1.25",
"ini": "^3.0.0",
"js-base64": "^3.7.2",
"nprogress": "^0.2.0",
"pjax-api": "^3.33.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-use": "^15.3.0",
"react-use": "^17.3.2",
"react-window": "^1.8.7",
"styled-components": "^5.2.0",
"styled-components": "^5.3.5",
"webext-domain-permission-toggle": "^1.0.0",
"webext-dynamic-content-scripts": "^6.0.3",
"webextension-polyfill": "^0.5.0"
@ -91,7 +90,7 @@
"arrowParens": "avoid"
},
"resolutions": {
"react": "^17",
"@types/styled-components": "^5.0.0"
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.3"
}
}

View file

@ -1,4 +1,4 @@
import { Label, Text } from '@primer/components'
import { Label, Text } from '@primer/react'
import { LoadingIndicator } from 'components/LoadingIndicator'
import { Node } from 'components/Node'
import { SearchBar } from 'components/SearchBar'
@ -189,9 +189,8 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
<div className={'status'}>
<Label
title="This repository is large. Gitako has switched to Lazy Mode to improve performance. Folders will be loaded when it gets expanded."
bg="yellow.5"
color="gray.6"
className={'lazy-mode'}
variant="attention"
>
Lazy Mode is ON
</Label>
@ -285,7 +284,7 @@ function ListView({ width, height, metaData, expandTo, renderNodeContext }: List
listRef.current.scrollToItem(index, 'auto')
}
}
}, [focusedNode, nodes])
}, [focusedNode?.path, nodes])
// For some reason, removing the deps array above results in bug:
// If scroll fast and far, then clicking on items would result in redirect
// Not know the reason :(

View file

@ -19,7 +19,6 @@ import {
HourglassIcon as Hourglass,
IconProps,
MarkdownIcon as Markdown,
OctofaceIcon as Octoface,
PinIcon as Pin,
ReplyIcon as Reply,
SearchIcon as Search,
@ -42,7 +41,6 @@ const iconToComponentMap = {
Hourglass,
Submodule,
Grabber,
Octoface,
ChevronDown,
X,
Gear,
@ -66,7 +64,6 @@ const typeToIconComponentMap: {
hourglass: 'Hourglass',
submodule: 'Submodule',
grabber: 'Grabber',
octoface: 'Octoface',
comment: 'Comment',
x: 'X',
pin: 'Pin',

View file

@ -1,8 +1,8 @@
import { BranchName, Breadcrumb, Flex, Text } from '@primer/components'
import { GitBranchIcon } from '@primer/octicons-react'
import { Box, BranchName, Breadcrumbs, Text } from '@primer/react'
import { platform } from 'platforms'
import * as React from 'react'
import { createAnchorClickHandler } from "utils/createAnchorClickHandler"
import { createAnchorClickHandler } from 'utils/createAnchorClickHandler'
type Props = {
metaData: MetaData
@ -13,20 +13,20 @@ export function MetaBar({ metaData }: Props) {
const { repoUrl, userUrl, branchUrl } = platform.resolveUrlFromMetaData(metaData)
return (
<>
<Breadcrumb className={'user-and-repo'}>
<Breadcrumb.Item className={'user-name'} href={userUrl}>
<Breadcrumbs className={'user-and-repo'}>
<Breadcrumbs.Item className={'user-name'} href={userUrl}>
{userName}
</Breadcrumb.Item>
<Breadcrumb.Item
</Breadcrumbs.Item>
<Breadcrumbs.Item
className={'repo-name'}
href={repoUrl}
onClick={createAnchorClickHandler(repoUrl)}
{...platform.delegatePJAXProps?.()}
>
<Text fontWeight="bolder">{repoName}</Text>
</Breadcrumb.Item>
</Breadcrumb>
<Flex paddingTop={1} flexWrap="nowrap" alignItems="flex-start">
</Breadcrumbs.Item>
</Breadcrumbs>
<Box display="flex" paddingTop={1} flexWrap="nowrap" alignItems="flex-start">
<div className={'octicon-wrapper'}>
<GitBranchIcon size="small" />
</div>
@ -39,7 +39,7 @@ export function MetaBar({ metaData }: Props) {
>
{branchName || '...'}
</BranchName>
</Flex>
</Box>
</>
)
}

View file

@ -1,5 +1,5 @@
import { TextInput, TextInputProps } from '@primer/components'
import { SearchIcon } from '@primer/octicons-react'
import { TextInput, TextInputProps } from '@primer/react'
import { useConfigs } from 'containers/ConfigsContext'
import * as React from 'react'
import { cx } from 'utils/cx'
@ -24,8 +24,7 @@ export function SearchBar({ onSearch, onFocus, value }: Props) {
return (
<div className={'search-input-wrapper'}>
<TextInput
backgroundColor="white"
icon={SearchIcon as any}
icon={SearchIcon}
onFocus={e => {
onFocus(e)
e.target.select()

View file

@ -95,7 +95,7 @@ export function SideBarBodyWrapper({
}, [sizeVariableMountPoint])
const onMouseLeave = React.useCallback(
e => {
<E extends HTMLElement>(e: React.MouseEvent<E>) => {
if (blockLeaveRef.current) return
onLeave?.(e)
},

View file

@ -6,10 +6,13 @@ type Size = {
height: number
}
type Props = {
type?: string | React.ComponentType
children(size: Partial<Size>): React.ReactNode
} & React.HTMLAttributes<HTMLElement>
type Props = Override<
React.HTMLAttributes<HTMLElement>,
{
type?: string | React.ComponentType
children(size: Partial<Size>): React.ReactNode
}
>
export function SizeObserver({ type = 'div', children, ...rest }: Props) {
const ref = React.useRef<any>()

View file

@ -4,7 +4,6 @@ import * as React from 'react'
import { useDebounce, useWindowSize } from 'react-use'
import { cx } from 'utils/cx'
import { useResizeHandler } from 'utils/hooks/useResizeHandler'
import { Icon } from './Icon'
type Props = {
error?: string | null
@ -67,11 +66,7 @@ export function ToggleShowButton({ error, className, onClick, onHover }: Props)
onPointerDown={onPointerDown}
title={'Gitako (draggable)'}
>
{config.value.toggleButtonContent === 'octoface' ? (
<Icon className={'octoface-icon'} type={'octoface'} />
) : (
<img className={'tentacle'} draggable={false} src={iconURL} />
)}
<img className={'tentacle'} draggable={false} src={iconURL} />
</button>
{error && <span className={'error-message'}>{error}</span>}
</div>

View file

@ -1,4 +1,4 @@
import { Button, Text, TextInput } from '@primer/components'
import { Button, Text, TextInput } from '@primer/react'
import { wikiLinks } from 'components/settings/SettingsBar'
import { useConfigs } from 'containers/ConfigsContext'
import { platform } from 'platforms'
@ -109,7 +109,7 @@ export function AccessTokenSettings(props: React.PropsWithChildren<Props>) {
)}
<div className={'access-token-input-control'}>
<TextInput
marginRight={1}
sx={{ marginRight: 1 }}
className={'access-token-input'}
value={accessToken}
placeholder="Or input here manually"

View file

@ -1,4 +1,4 @@
import { Link } from '@primer/components'
import { Link } from '@primer/react'
import { Icon } from 'components/Icon'
import { VERSION } from 'env'
import * as React from 'react'
@ -14,7 +14,6 @@ export function Footer(props: Props) {
<div className={'gitako-footer'}>
<Link
className={'version'}
fontSize={14}
href={wikiLinks.changeLog}
target={'_blank'}
title={'Check out new features!'}

View file

@ -1,9 +1,7 @@
import { Button, TextInput } from '@primer/components'
import { Option, SelectInput } from 'components/SelectInput'
import { Button, TextInput } from '@primer/react'
import { SimpleToggleField } from 'components/SimpleToggleField'
import { useConfigs } from 'containers/ConfigsContext'
import * as React from 'react'
import { Config } from 'utils/config/helper'
import { friendlyFormatShortcut } from 'utils/general'
import { useStateIO } from 'utils/hooks/useStateIO'
import * as keyHelper from 'utils/keyHelper'
@ -12,19 +10,6 @@ import { SettingsSection } from './SettingsSection'
type Props = {}
const toggleButtonContentOptions: Option<Config['toggleButtonContent']>[] = [
{
key: 'logo',
value: 'logo',
label: `Gitako Logo`,
},
{
key: 'octoface',
value: 'octoface',
label: `The Classic Octoface`,
},
]
export function SidebarSettings(props: React.PropsWithChildren<Props>) {
const configContext = useConfigs()
const useToggleShowSideBarShortcut = useStateIO(configContext.value.shortcut)
@ -41,7 +26,7 @@ export function SidebarSettings(props: React.PropsWithChildren<Props>) {
<div className={'toggle-shortcut-input-control'}>
<TextInput
id="toggle-sidebar-shortcut"
marginRight={1}
sx={{ marginRight: 1 }}
className={'toggle-shortcut-input'}
onFocus={() => focused.onChange(true)}
onBlur={() => focused.onChange(false)}
@ -78,18 +63,6 @@ export function SidebarSettings(props: React.PropsWithChildren<Props>) {
)}
</div>
</Field>
<Field id="toggle-button-content" title="Icon of the toggle button">
<SelectInput
id="toggle-button-content"
options={toggleButtonContentOptions}
onChange={v => {
configContext.onChange({
toggleButtonContent: v,
})
}}
value={configContext.value.toggleButtonContent}
/>
</Field>
<SimpleToggleField
field={{
key: 'intelligentToggle',

View file

@ -1,7 +1,7 @@
import { raiseError } from 'analytics'
import * as React from 'react'
export class ErrorBoundary extends React.PureComponent {
export class ErrorBoundary extends React.PureComponent<React.PropsWithChildren<{}>> {
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
raiseError(error, errorInfo)
}

View file

@ -1,237 +1,5 @@
import { theme } from '@primer/components'
import { ThemeProvider } from '@primer/react'
import * as React from 'react'
import { ThemeProvider } from 'styled-components'
const { lighten, rgba, desaturate } = require('polished')
// Refactored from https://github.com/primer/components/blob/main/src/theme-preval.js
export function generateDarkTheme() {
const primitives = {
black: '#f0f6fc',
white: '#010409',
gray: [
'#0d1117',
'#161b22',
'#21262d',
'#30363d',
'#484f58',
'#6e7681',
'#8b949e',
'#b1bac4',
'#c9d1d9',
'#f0f6fc',
],
blue: [
'#051d4d',
'#0c2d6b',
'#0d419d',
'#1158c7',
'#1f6feb',
'#388bfd',
'#58a6ff',
'#79c0ff',
'#a5d6ff',
'#cae8ff',
],
green: [
'#04260f',
'#033a16',
'#0f5323',
'#196c2e',
'#238636',
'#2ea043',
'#3fb950',
'#56d364',
'#7ee787',
'#aff5b4',
],
yellow: [
'#341a00',
'#4b2900',
'#693e00',
'#845306',
'#9e6a03',
'#bb8009',
'#d29922',
'#e3b341',
'#f2cc60',
'#f8e3a1',
],
orange: [
'#3d1300',
'#5a1e02',
'#762d0a',
'#9b4215',
'#bd561d',
'#db6d28',
'#f0883e',
'#ffa657',
'#ffc680',
'#ffdfb6',
],
red: [
'#490202',
'#67060c',
'#8e1519',
'#b62324',
'#da3633',
'#f85149',
'#ff7b72',
'#ffa198',
'#ffc1ba',
'#ffdcd7',
],
purple: [
'#271052',
'#3c1e70',
'#553098',
'#6e40c9',
'#8957e5',
'#a371f7',
'#bc8cff',
'#d2a8ff',
'#e2c5ff',
'#eddeff',
],
pink: [
'#42062a',
'#5e103e',
'#7d2457',
'#9e3670',
'#bf4b8a',
'#db61a2',
'#f778ba',
'#ff9bce',
'#ffbedd',
'#ffdaec',
],
}
const { black, white, pink, gray, blue, green, orange, purple, red, yellow } = primitives
// General
// any :(
const colors: any = {
black,
white,
gray,
blue,
green,
orange,
purple,
red,
yellow,
pink,
}
colors.bodytext = gray[9]
colors.blackfade15 = rgba(black, 0.15)
colors.blackfade30 = rgba(black, 0.3)
colors.blackfade50 = rgba(black, 0.5)
colors.blackfade70 = rgba(black, 0.7)
colors.blackfade85 = rgba(black, 0.85)
colors.whitefade15 = rgba(white, 0.15)
colors.whitefade30 = rgba(white, 0.3)
colors.whitefade50 = rgba(white, 0.5)
colors.whitefade70 = rgba(white, 0.7)
colors.whitefade85 = rgba(white, 0.85)
colors.state = {
error: red[5],
failure: red[5],
pending: yellow[7],
queued: yellow[7],
success: green[5],
unknown: gray[4],
}
colors.border = {
blackFade: colors.blackfade15,
blue: blue[5],
blueLight: blue[2],
grayLight: lighten(0.03, gray[2]),
gray: gray[2],
grayDark: gray[3],
grayDarker: gray[7],
green: green[4],
greenLight: desaturate(0.4, green[3]),
purple: purple[5],
red: red[5],
redLight: desaturate(0.6, red[3]),
white,
whiteFade: colors.whitefade15,
yellow: desaturate(0.6, yellow[3]),
}
colors.text = {
white,
gray: gray[6],
grayLight: gray[5],
grayDark: gray[8],
red: red[6],
}
colors.bg = {
gray: gray[1],
grayLight: gray[3],
grayDark: gray[9],
disabled: gray[2],
}
colors.accent = orange[5]
colors.labels = {
gray: gray[2],
grayText: gray[9],
grayDark: gray[5],
grayDarkText: gray[9],
blue: blue[5],
blueText: blue[5],
orange: orange[5],
orangeText: orange[6],
green: green[5],
greenText: green[6],
red: red[6],
redText: red[6],
yellow: yellow[6],
yellowText: yellow[9],
pink: pink[4],
pinkText: pink[6],
purple: purple[4],
}
// Components
const buttons = {
default: {
color: {
default: colors.text.grayDark,
disabled: gray[4],
},
border: {
default: rgba(black, 0.12),
active: colors.border.grayDark,
disabled: colors.border.grayLight,
},
bg: {
default: colors.bg.grayLight,
hover: colors.gray[3],
active: colors.bg.gray,
disabled: colors.bg.grayLight,
},
shadow: {
default: `0 0 transparent, 0 0 transparent`,
hover: `0 0 transparent, 0 0 transparent`,
active: `0 0 transparent 0 0 transparent`,
focus: `0 0 transparent 0 0 transparent`,
},
},
}
const theme = {
colors,
buttons,
}
return theme
}
const getIsPreferDarkTheme = () => {
const colorMode = document.documentElement.dataset.colorMode
@ -242,27 +10,19 @@ const getIsPreferDarkTheme = () => {
}
// No need to watch the property as it does not change in repo pages
function usePreferDarkTheme() {
const [is, setIs] = React.useState(getIsPreferDarkTheme)
const [prefer, setPrefer] = React.useState(getIsPreferDarkTheme)
React.useEffect(() => {
const update = () => {
console.log(`updating color scheme`)
setIs(getIsPreferDarkTheme())
}
const match = window.matchMedia('(prefers-color-scheme: dark)')
const update = () => setPrefer(match.matches) // `.matches` will update on media change
match.addEventListener('change', update)
return () => match.removeEventListener('change', update)
}, [])
return is
}
function useThemeConfig() {
const preferDarkTheme = usePreferDarkTheme()
return React.useMemo(() => {
return preferDarkTheme ? generateDarkTheme() : theme
}, [preferDarkTheme])
return prefer
}
export function Theme({ children }: React.PropsWithChildren<{}>) {
const theme = useThemeConfig()
return <ThemeProvider theme={theme}>{children}</ThemeProvider>
const preferDarkTheme = usePreferDarkTheme()
return (
<ThemeProvider colorMode={preferDarkTheme ? 'night' : 'day'} dayScheme="" {...{ children }} />
)
}

View file

@ -91,8 +91,8 @@ $minimal-z-index: max(
display: block;
cursor: pointer;
user-select: none;
-webkit-mask-image: url('~@primer/octicons/build/svg/' + $icon-name + '.svg?inline');
mask-image: url('~@primer/octicons/build/svg/' + $icon-name + '.svg?inline');
-webkit-mask-image: url('~@primer/octicons-react/build/svg/' + $icon-name + '.svg?inline');
mask-image: url('~@primer/octicons-react/build/svg/' + $icon-name + '.svg?inline');
-webkit-mask-size: contain;
mask-size: contain;
-webkit-mask-position: center;
@ -129,10 +129,10 @@ $minimal-z-index: max(
align-items: center;
&::before {
width: 10px;
width: 16px;
height: 20px;
transition: 0.25s ease;
@include pseudo-primer-icon('chevron-down');
@include pseudo-primer-icon('chevron-down-16');
}
@include interactive-background-on-before(
@ -195,7 +195,7 @@ $minimal-z-index: max(
width: 100%;
height: 100%;
display: block;
background-image: url('~@primer/octicons-react/build/svg/clippy-16.svg?inline');
background-image: url('~@primer/octicons-react/build/svg/copy-16.svg?inline');
background-position: center;
background-repeat: no-repeat;
&.success {
@ -330,26 +330,6 @@ $minimal-z-index: max(
cursor: not-allowed;
}
.octoface-icon {
@include flex-center();
width: 32px;
height: 32px;
padding: 4px;
border-radius: 6px;
@include interactive-frame;
color: var(--gitako-fg-default);
&:active {
color: var(--gitako-fg-subtle);
}
transition: all ease 0.3s;
font-size: 16px;
transform: translateX(8px);
&:active,
&:hover {
transform: translateX(12px);
}
}
.tentacle {
width: 40px;
height: 40px;
@ -489,7 +469,6 @@ $minimal-z-index: max(
padding: 6px 10px;
flex-shrink: 0;
position: relative; // prevent overlap by outline of other elements
border-bottom: 1px solid var(--gitako-border-default);
.user-and-repo {
display: inline; // would be override by CSS rule of section from @primer/css
@ -563,6 +542,7 @@ $minimal-z-index: max(
.loading-indicator-container {
width: 100%;
height: 100%;
border-top: 1px solid var(--gitako-border-default);
@include flex-center();
.loading-indicator {
@ -592,7 +572,14 @@ $minimal-z-index: max(
flex-direction: column;
flex-wrap: nowrap;
&.freeze {
filter: blur(1.5px) opacity(0.6) grayscale(0.9);
filter: blur(1.5px) opacity(0.6) grayscale(0.9) brightness(0.8);
transition: filter 0.25s ease;
&:hover {
filter: blur(1.5px) opacity(0.6) grayscale(0.9) brightness(0.9);
}
&:active {
filter: blur(1.5px) opacity(0.6) grayscale(0.9) brightness(0.7);
}
cursor: pointer;
> * {
@ -608,9 +595,9 @@ $minimal-z-index: max(
.search-input {
width: 100%;
box-shadow: none; // stay low
border: none; // reset borders on other sides
border-bottom: 1px solid var(--gitako-border-default);
border: none;
border-radius: 0;
border-top: 1px solid var(--gitako-border-default);
color: var(--gitako-fg-default);
background: var(--gitako-bg-default);
padding-right: 40px; // save space for actions
@ -649,6 +636,7 @@ $minimal-z-index: max(
.status {
padding: 4px;
background: var(--gitako-bg-subtle);
.lazy-mode {
cursor: help;
@ -659,6 +647,7 @@ $minimal-z-index: max(
position: relative;
flex: 1;
overflow: hidden;
border-top: 1px solid var(--gitako-border-default);
// Put this inside files will help files to get proper size derived from parents, regardless of its content size
.magic-size-container {
@ -954,14 +943,14 @@ $minimal-z-index: max(
position: absolute;
right: 6px;
top: 8px;
width: 10px;
width: 16px;
height: 20px;
&::before {
width: 10px;
width: 16px;
height: 20px;
background-color: var(--gitako-fg-subtle);
@include pseudo-primer-icon('chevron-down');
@include pseudo-primer-icon('chevron-down-16');
}
}
}

View file

@ -12,7 +12,6 @@ export type Config = {
intelligentToggle: boolean | null // `null` stands for intelligent, boolean for sidebar open state
icons: 'rich' | 'dim' | 'native'
toggleButtonVerticalDistance: number
toggleButtonContent: 'logo' | 'octoface'
recursiveToggleFolder: 'shift' | 'alt'
searchMode: SearchMode
sidebarToggleMode: 'persistent' | 'float'
@ -33,7 +32,6 @@ enum configKeys {
intelligentToggle = 'intelligentToggle',
icons = 'icons',
toggleButtonVerticalDistance = 'toggleButtonVerticalDistance',
toggleButtonContent = 'toggleButtonContent',
recursiveToggleFolder = 'recursiveToggleFolder',
searchMode = 'searchMode',
sidebarToggleMode = 'sidebarToggleMode',
@ -57,7 +55,6 @@ export const defaultConfigs: Config = {
intelligentToggle: null,
icons: 'rich',
toggleButtonVerticalDistance: 124, // align with GitHub's navbar items
toggleButtonContent: 'logo',
recursiveToggleFolder: 'shift',
searchMode: 'fuzzy',
sidebarToggleMode: 'float',

943
yarn.lock

File diff suppressed because it is too large Load diff