mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
feat: add pjax mode setting
This commit is contained in:
parent
c8a6e38af1
commit
d02c32bb4b
8 changed files with 105 additions and 59 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
2
src/platforms/platform.d.ts
vendored
2
src/platforms/platform.d.ts
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue