diff --git a/src/components/SideBar.tsx b/src/components/SideBar.tsx
index f2b82d5..8d23b6a 100644
--- a/src/components/SideBar.tsx
+++ b/src/components/SideBar.tsx
@@ -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)
diff --git a/src/components/SideBarBodyWrapper.tsx b/src/components/SideBarBodyWrapper.tsx
index e9a6a98..4698895 100644
--- a/src/components/SideBarBodyWrapper.tsx
+++ b/src/components/SideBarBodyWrapper.tsx
@@ -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 (
{
- setSize(defaultConfigs.sideBarWidth)
- apply(sizeVariableMountPoint, defaultConfigs.sideBarWidth)
+ setSize(defaultSideBarWidth)
+ apply(sizeVariableMountPoint, defaultSideBarWidth)
}}
onResizeStateChange={state => {
blockLeaveRef.current = state === 'resizing'
diff --git a/src/components/settings/SettingsBar.tsx b/src/components/settings/SettingsBar.tsx
index 4e60491..ded58b3 100644
--- a/src/components/settings/SettingsBar.tsx
+++ b/src/components/settings/SettingsBar.tsx
@@ -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('')
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 (
<>
Settings
diff --git a/src/platforms/GitHub/index.ts b/src/platforms/GitHub/index.ts
index e21855c..c9a8d15 100644
--- a/src/platforms/GitHub/index.ts
+++ b/src/platforms/GitHub/index.ts
@@ -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
+ }
},
}
diff --git a/src/platforms/platform.d.ts b/src/platforms/platform.d.ts
index e555d7a..8431249 100644
--- a/src/platforms/platform.d.ts
+++ b/src/platforms/platform.d.ts
@@ -26,6 +26,6 @@ type Platform = {
delegatePJAXProps?(options?: {
node?: TreeNode
}): void | (React.DOMAttributes & Record) // support data-* attributes
- loadWithPJAX?(url: string, element: HTMLElement): void
+ loadWithPJAX?(url: string, element: HTMLElement): boolean | void
usePlatformHooks?(): void
}
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 60570e5..ddf9ad4 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -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;
diff --git a/src/utils/config/helper.ts b/src/utils/config/helper.ts
index ea3c369..e541087 100644
--- a/src/utils/config/helper.ts
+++ b/src/utils/config/helper.ts
@@ -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) {
+ 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) {
export type VersionedConfig = Record & { configVersion: string }
+export const configRef: Partial = {}
+const updateConfigRef = async (config: Partial) => {
+ Object.assign(configRef, config)
+}
+
const prepareConfig = new Promise(async resolve => {
await migrateConfig()
resolve()
+ updateConfigRef(await get())
})
async function get(): Promise {
@@ -91,6 +103,7 @@ async function get(): Promise {
}
async function set(config: Config) {
+ updateConfigRef(config)
return await storageHelper.set({ [platformStorageKey]: config })
}
diff --git a/src/utils/hooks/usePJAX.ts b/src/utils/hooks/usePJAX.ts
index 396dcaf..ba06191 100644
--- a/src/utils/hooks/usePJAX.ts
+++ b/src/utils/hooks/usePJAX.ts
@@ -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) {