feat: add pjax mode setting

This commit is contained in:
EnixCoda 2022-06-25 12:41:04 +08:00
parent c8a6e38af1
commit d02c32bb4b
8 changed files with 105 additions and 59 deletions

View file

@ -108,12 +108,11 @@ export function SideBar() {
}
}, [intelligentToggle, sidebarToggleMode])
usePJAX()
useOnPJAXDone(updateSideBarVisibility)
platform.usePlatformHooks?.()
usePJAX()
// Hide sidebar when error due to auth but token is set #128
const hideSidebarOnInvalidToken: boolean =
intelligentToggle === null && Boolean(state === 'error-due-to-auth' && accessToken)

View file

@ -2,7 +2,7 @@ import { ResizeHandler } from 'components/ResizeHandler'
import { useConfigs } from 'containers/ConfigsContext'
import * as React from 'react'
import { useDebounce, useWindowSize } from 'react-use'
import { defaultConfigs } from 'utils/config/helper'
import { getDefaultConfigs } from 'utils/config/helper'
import { cx } from 'utils/cx'
import { setCSSVariable } from 'utils/DOMHelper'
import * as features from 'utils/features'
@ -103,6 +103,9 @@ export function SideBarBodyWrapper({
)
const dummySize: [number, number] = React.useMemo(() => [size, size], [size])
const defaultSideBarWidth = React.useMemo(() => getDefaultConfigs().sideBarWidth, []);
return (
<div
ref={bodyWrapperRef}
@ -115,8 +118,8 @@ export function SideBarBodyWrapper({
<ResizeHandler
onResize={onResize}
onResetSize={() => {
setSize(defaultConfigs.sideBarWidth)
apply(sizeVariableMountPoint, defaultConfigs.sideBarWidth)
setSize(defaultSideBarWidth)
apply(sizeVariableMountPoint, defaultSideBarWidth)
}}
onResizeStateChange={state => {
blockLeaveRef.current = state === 'resizing'

View file

@ -1,9 +1,11 @@
import { Link } from '@primer/components'
import { Icon } from 'components/Icon'
import { useConfigs } from 'containers/ConfigsContext'
import { VERSION } from 'env'
import { platform } from 'platforms'
import { GitHub } from 'platforms/GitHub'
import * as React from 'react'
import { useUpdateEffect } from 'react-use'
import { useStateIO } from 'utils/hooks/useStateIO'
import { SimpleField, SimpleToggleField } from '../SimpleToggleField'
import { AccessTokenSettings } from './AccessTokenSettings'
@ -19,6 +21,7 @@ export const wikiLinks = {
copyFileButton: `${WIKI_HOME_LINK}/Copy-file-and-snippet`,
copySnippet: `${WIKI_HOME_LINK}/Copy-file-and-snippet`,
createAccessToken: `${WIKI_HOME_LINK}/Access-token-for-Gitako`,
pjaxMode: `${WIKI_HOME_LINK}/Pjax-Mode`,
}
type Props = {
@ -30,7 +33,9 @@ function SettingsBarContent() {
const useReloadHint = useStateIO<React.ReactNode>('')
const { value: reloadHint } = useReloadHint
const moreFields: SimpleField<'copyFileButton' | 'copySnippetButton'|'codeFolding'>[] =
const moreFields: SimpleField<
'copyFileButton' | 'copySnippetButton' | 'codeFolding' | 'pjaxMode'
>[] =
platform === GitHub
? [
{
@ -39,6 +44,16 @@ function SettingsBarContent() {
wikiLink: wikiLinks.codeFolding,
tooltip: `Read more in Gitako's Wiki`,
},
{
key: 'pjaxMode',
label: 'Native PJAX mode',
wikiLink: wikiLinks.pjaxMode,
tooltip: 'Please keep it enabled unless Gitako crashes after redirecting',
overwrite: {
value: pjaxMode => pjaxMode === 'native',
onChange: checked => (checked ? 'native' : 'pjax-api'),
},
},
{
key: 'copyFileButton',
label: 'Copy file button',
@ -54,6 +69,10 @@ function SettingsBarContent() {
]
: []
useUpdateEffect(() => {
window.location.reload()
}, [useConfigs().value.pjaxMode])
return (
<>
<h2 className={'gitako-settings-bar-title'}>Settings</h2>

View file

@ -1,6 +1,7 @@
import { useConfigs } from 'containers/ConfigsContext'
import { GITHUB_OAUTH } from 'env'
import { Base64 } from 'js-base64'
import { configRef } from 'utils/config/helper'
import { run } from 'utils/general'
import { resolveGitModules } from 'utils/gitSubmodule'
import { sortFoldersToFront } from 'utils/treeParser'
@ -169,7 +170,10 @@ export const GitHub: Platform = {
return await getRepositoryTreeData(metaData, path, recursive, accessToken)
},
shouldShow() {
return Boolean(DOMHelper.isInCodePage() || (URLHelper.isInPullPage() && !DOMHelper.isNativePRFileTreeShown()))
return Boolean(
DOMHelper.isInCodePage() ||
(URLHelper.isInPullPage() && !DOMHelper.isNativePRFileTreeShown()),
)
},
shouldExpandAll() {
return Boolean(URLHelper.isInPullPage())
@ -205,8 +209,8 @@ export const GitHub: Platform = {
useGitHubCodeFold(codeFolding)
useEnterpriseStatBarStyleFix()
},
delegatePJAXProps(options) {
if (!options?.node || options.node.type === 'blob')
delegatePJAXProps: options => {
if (configRef.pjaxMode === 'native' && (!options?.node || options.node.type === 'blob'))
return {
'data-pjax': pjaxContainerSelector,
onClick() {
@ -214,8 +218,11 @@ export const GitHub: Platform = {
},
}
},
loadWithPJAX(url, element) {
element.click()
loadWithPJAX: (url, element) => {
if (configRef.pjaxMode === 'native') {
element.click()
return true
}
},
}

View file

@ -26,6 +26,6 @@ type Platform = {
delegatePJAXProps?(options?: {
node?: TreeNode
}): void | (React.DOMAttributes<HTMLElement> & Record<string, any>) // support data-* attributes
loadWithPJAX?(url: string, element: HTMLElement): void
loadWithPJAX?(url: string, element: HTMLElement): boolean | void
usePlatformHooks?(): void
}

View file

@ -883,6 +883,40 @@ $minimal-z-index: max(
overflow: auto;
position: relative;
.select-wrapper {
position: relative;
select {
width: 100%;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
// make it look like text inputs
height: 36px;
padding: 0 6px;
border-radius: 6px;
border: 1px solid var(--gitako-border-default);
background: var(--gitako-canvas-default);
color: var(--gitako-fg-default);
box-shadow: var(--gitako-primer-shadow-inset);
}
.chevron {
position: absolute;
right: 6px;
top: 8px;
width: 10px;
height: 20px;
&::before {
width: 10px;
height: 20px;
background-color: var(--gitako-fg-subtle);
@include pseudo-primer-icon('chevron-down');
}
}
}
.shadow-shelter {
position: absolute;
width: 100%;
@ -914,39 +948,6 @@ $minimal-z-index: max(
cursor: not-allowed;
}
}
.select-wrapper {
position: relative;
select {
width: 100%;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
// make it look like text inputs
height: 36px;
padding: 0 6px;
border-radius: 6px;
border: 1px solid var(--gitako-border-default);
background: var(--gitako-canvas-default);
color: var(--gitako-fg-default);
box-shadow: var(--gitako-primer-shadow-inset);
}
.chevron {
position: absolute;
right: 6px;
top: 8px;
width: 10px;
height: 20px;
&::before {
width: 10px;
height: 20px;
background-color: var(--gitako-fg-subtle);
@include pseudo-primer-icon('chevron-down');
}
}
}
&.field-checkbox {
padding-left: 20px;
vertical-align: middle;

View file

@ -1,4 +1,5 @@
import { SearchMode } from 'components/searchModes'
import { platformName } from 'platforms'
import { storageHelper } from 'utils/storageHelper'
import { migrateConfig } from './migrations'
@ -21,6 +22,7 @@ export type Config = {
compactFileTree: boolean
restoreExpandedFolders: boolean
showDiffInText: boolean
pjaxMode: 'native' | 'pjax-api'
}
enum configKeys {
@ -42,18 +44,20 @@ enum configKeys {
compactFileTree = 'compactFileTree',
restoreExpandedFolders = 'restoreExpandedFolders',
showDiffInText = 'showDiffInText',
pjaxMode = 'pjaxMode',
}
// do NOT use platform name
// NOT use platform name to distinguish GHE from github.com
const platformStorageKey = `platform_` + window.location.host.toLowerCase()
const isInGitHub = platformStorageKey === 'platform_github.com'
export const defaultConfigs: Config = {
export const getDefaultConfigs: () => Config = () => ({
sideBarWidth: 260,
shortcut: undefined,
accessToken: '',
compressSingletonFolder: true,
copyFileButton: platformStorageKey !== 'platform_github.com', // false when on github.com,
copySnippetButton: platformStorageKey !== 'platform_github.com', // false when on github.com
copyFileButton: !isInGitHub, // disable on github.com
copySnippetButton: !isInGitHub, // disable on github.com
intelligentToggle: null,
icons: 'rich',
toggleButtonVerticalDistance: 124, // align with GitHub's navbar items
@ -66,11 +70,13 @@ export const defaultConfigs: Config = {
compactFileTree: false,
restoreExpandedFolders: true,
showDiffInText: false,
}
pjaxMode: platformName === 'GitHub' ? 'native' : 'pjax-api', // use native on GitHub
})
const configKeyArray = Object.values(configKeys)
function applyDefaultConfigs(configs: Partial<Config>) {
const defaultConfigs = getDefaultConfigs()
return configKeyArray.reduce((applied, key) => {
Object.assign(applied, { [key]: key in configs ? configs[key] : defaultConfigs[key] })
return applied
@ -79,9 +85,15 @@ function applyDefaultConfigs(configs: Partial<Config>) {
export type VersionedConfig<SiteConfig> = Record<string, SiteConfig> & { configVersion: string }
export const configRef: Partial<Config> = {}
const updateConfigRef = async (config: Partial<Config>) => {
Object.assign(configRef, config)
}
const prepareConfig = new Promise<void>(async resolve => {
await migrateConfig()
resolve()
updateConfigRef(await get())
})
async function get(): Promise<Config> {
@ -91,6 +103,7 @@ async function get(): Promise<Config> {
}
async function set(config: Config) {
updateConfigRef(config)
return await storageHelper.set({ [platformStorageKey]: config })
}

View file

@ -1,4 +1,5 @@
import { Config, Pjax } from 'pjax-api'
import { useConfigs } from 'containers/ConfigsContext'
import { Config } from 'pjax-api'
import { platform } from 'platforms'
import * as React from 'react'
import { useEvent } from 'react-use'
@ -28,14 +29,18 @@ const config: Config = {
}
export function usePJAX() {
const { pjaxMode } = useConfigs().value
// make history travel work
React.useEffect(() => {
new Pjax({
...config,
filter() {
return false
},
})
if (pjaxMode === 'pjax-api') {
const { Pjax } = require('pjax-api')
new Pjax({
...config,
filter() {
return false
},
})
}
}, [])
// bindings for legacy support
@ -44,8 +49,7 @@ export function usePJAX() {
}
export const loadWithPJAX = (url: string, element: HTMLElement) => {
if (platform.loadWithPJAX) platform.loadWithPJAX(url, element)
else Pjax.assign(url, config)
platform.loadWithPJAX?.(url, element) || require('pjax-api').Pjax.assign(url, config)
}
export function useOnPJAXDone(callback: () => void) {