mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
refactor: raise Gitako out of document body
This commit is contained in:
parent
8f0e4a9ccb
commit
98a67381db
6 changed files with 46 additions and 96 deletions
|
|
@ -127,8 +127,11 @@ export function SideBar() {
|
|||
collapsed: !shouldShow,
|
||||
})}
|
||||
baseSize={baseSize}
|
||||
// TODO: move sidebarToggleMode inside
|
||||
onLeave={sidebarToggleMode === 'float' ? () => setShowSideBar(false) : undefined}
|
||||
sizeVariableMountPoint={sidebarToggleMode === 'persistent' ? document.body : undefined}
|
||||
sizeVariableMountPoint={
|
||||
sidebarToggleMode === 'persistent' ? DOMHelper.gitakoDescriptionTarget : undefined
|
||||
}
|
||||
>
|
||||
<div className={'gitako-side-bar-body'}>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { cx } from 'utils/cx'
|
|||
import { setCSSVariable } from 'utils/DOMHelper'
|
||||
import * as features from 'utils/features'
|
||||
import { detectBrowser } from 'utils/general'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import { ResizeState } from 'utils/hooks/useResizeHandler'
|
||||
import { useConditionalHook } from '../utils/hooks/useConditionalHook'
|
||||
|
||||
|
|
@ -53,7 +54,6 @@ export function SideBarBodyWrapper({
|
|||
const safeSize = getSafeSize(size, width)
|
||||
if (safeSize !== size) setSize(safeSize)
|
||||
}, [width, size])
|
||||
const bodyWrapperRef = React.useRef<HTMLDivElement | null>(null)
|
||||
useDebounce(() => configContext.onChange({ sideBarWidth: size }), 100, [size])
|
||||
|
||||
const applySizeToCSSVariables = React.useCallback(function apply(
|
||||
|
|
@ -66,13 +66,6 @@ export function SideBarBodyWrapper({
|
|||
sizeVariableMountPoint ? `${size}px` : undefined,
|
||||
sizeVariableMountPoint,
|
||||
)
|
||||
|
||||
if (bodyWrapperRef.current)
|
||||
setCSSVariable(
|
||||
'--gitako-width',
|
||||
sizeVariableMountPoint ? undefined : `${size}px`,
|
||||
bodyWrapperRef.current,
|
||||
)
|
||||
},
|
||||
[])
|
||||
|
||||
|
|
@ -95,9 +88,15 @@ export function SideBarBodyWrapper({
|
|||
}
|
||||
}, [width, sizeVariableMountPoint, applySizeToCSSVariables])
|
||||
|
||||
const applyLatestSizeToCSSVariables = React.useCallback(
|
||||
() => applySizeToCSSVariables(sizeVariableMountPoint, size),
|
||||
[sizeVariableMountPoint, size],
|
||||
)
|
||||
React.useEffect(() => {
|
||||
applySizeToCSSVariables(sizeVariableMountPoint, size)
|
||||
}, [sizeVariableMountPoint, size, applySizeToCSSVariables])
|
||||
applyLatestSizeToCSSVariables()
|
||||
}, [applyLatestSizeToCSSVariables])
|
||||
|
||||
useOnPJAXDone(applyLatestSizeToCSSVariables)
|
||||
|
||||
const onMouseLeave = React.useCallback(
|
||||
<E extends HTMLElement>(e: React.MouseEvent<E>) => {
|
||||
|
|
@ -112,11 +111,10 @@ export function SideBarBodyWrapper({
|
|||
blockLeaveRef.current = state === 'resizing'
|
||||
}, [])
|
||||
|
||||
const defaultSideBarWidth = React.useMemo(() => getDefaultConfigs().sideBarWidth, []);
|
||||
const defaultSideBarWidth = React.useMemo(() => getDefaultConfigs().sideBarWidth, [])
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={bodyWrapperRef}
|
||||
className={cx('gitako-side-bar-body-wrapper', className)}
|
||||
style={{ height: heightForSafari }}
|
||||
onMouseLeave={onMouseLeave}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Gitako } from 'components/Gitako'
|
||||
import * as React from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { insertSideBarMountPoint, persistGitakoElements } from 'utils/DOMHelper'
|
||||
import { insertSideBarMountPoint } from 'utils/DOMHelper'
|
||||
import './content.scss'
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
|
|
@ -12,7 +12,6 @@ if (document.readyState === 'loading') {
|
|||
|
||||
async function init() {
|
||||
await injectStyles(browser.runtime.getURL('content.css'))
|
||||
persistGitakoElements()
|
||||
createRoot(insertSideBarMountPoint()).render(<Gitako />)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ $minimal-z-index: max(
|
|||
mask-position: center;
|
||||
}
|
||||
|
||||
.#{$name}-ready {
|
||||
[data-#{$name}-ready='true'] {
|
||||
// github
|
||||
// code folding start
|
||||
.blob-wrapper table .blob-num {
|
||||
|
|
@ -232,16 +232,18 @@ $minimal-z-index: max(
|
|||
}
|
||||
}
|
||||
|
||||
.with-gitako-spacing {
|
||||
@media screen {
|
||||
margin-left: var(--gitako-width);
|
||||
}
|
||||
html[data-with-gitako-spacing='true'] {
|
||||
body {
|
||||
@media screen {
|
||||
margin-left: var(--gitako-width);
|
||||
}
|
||||
|
||||
// gitee
|
||||
&.git-project {
|
||||
width: auto; // shrink width
|
||||
.site-content {
|
||||
min-width: 1040px;
|
||||
// gitee
|
||||
&.git-project {
|
||||
width: auto; // shrink width
|
||||
.site-content {
|
||||
min-width: 1040px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -425,6 +427,7 @@ $minimal-z-index: max(
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--color-bg-subtle);
|
||||
font-size: 14px;
|
||||
|
||||
.octicon-wrapper {
|
||||
display: inline-block;
|
||||
|
|
@ -638,6 +641,7 @@ $minimal-z-index: max(
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&:not(:hover) {
|
||||
|
|
|
|||
|
|
@ -3,33 +3,24 @@
|
|||
*/
|
||||
|
||||
export const rootElementID = 'gitako-root'
|
||||
|
||||
export function setGitakoBodyClass(className: string, enable: boolean) {
|
||||
const classList = document.body.classList
|
||||
if (enable) classList.add(className)
|
||||
else classList.remove(className)
|
||||
}
|
||||
export const gitakoDescriptionTarget = document.documentElement
|
||||
|
||||
/**
|
||||
* when gitako is ready, make page's header narrower
|
||||
* or cancel it
|
||||
*/
|
||||
export function markGitakoReadyState(ready: boolean) {
|
||||
const readyClassName = 'gitako-ready'
|
||||
return setGitakoBodyClass(readyClassName, ready)
|
||||
const readyAttributeName = 'data-gitako-ready'
|
||||
return gitakoDescriptionTarget.setAttribute(readyAttributeName, `${ready}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* if should show gitako, then move body right to make space for showing gitako
|
||||
* otherwise, hide the space
|
||||
*/
|
||||
export const bodySpacingClassName = 'with-gitako-spacing'
|
||||
export const spacingAttributeName = 'data-with-gitako-spacing'
|
||||
export function setBodyIndent(shouldShowGitako: boolean) {
|
||||
if (shouldShowGitako) {
|
||||
document.body.classList.add(bodySpacingClassName)
|
||||
} else {
|
||||
document.body.classList.remove(bodySpacingClassName)
|
||||
}
|
||||
gitakoDescriptionTarget.setAttribute(spacingAttributeName, `${shouldShowGitako}`)
|
||||
}
|
||||
|
||||
export function $(selector: string): HTMLElement | null
|
||||
|
|
@ -56,20 +47,20 @@ export function $(selector: string, existCallback?: any, otherwise?: any) {
|
|||
/**
|
||||
* DOM Structure after calling the `insert*MountPoint` functions
|
||||
*
|
||||
* <html>
|
||||
* <body>
|
||||
* <div id={rootElementID}>
|
||||
* <div id={sidebarMountPointID}>
|
||||
* </div>
|
||||
* <div id={logoMountPointID}>
|
||||
* </div>
|
||||
* </div>
|
||||
* </body>
|
||||
* </html>
|
||||
* <html>
|
||||
* <body>
|
||||
* </body>
|
||||
* <div id={rootElementID}>
|
||||
* <div id={sidebarMountPointID}>
|
||||
* </div>
|
||||
* <div id={logoMountPointID}>
|
||||
* </div>
|
||||
* </div>
|
||||
* </html>
|
||||
*/
|
||||
|
||||
const mountPointContainer = document.documentElement
|
||||
export function insertMountPoint() {
|
||||
const mountPointContainer = document.body // TODO: when replace this, refactor root of `$`
|
||||
return $(formatID(rootElementID), undefined, () => {
|
||||
const element = document.createElement('div')
|
||||
element.setAttribute('id', rootElementID)
|
||||
|
|
@ -186,46 +177,3 @@ export function formatClass(className: string) {
|
|||
export function parseIntFromElement(e: HTMLElement): number {
|
||||
return parseInt((e.innerText || '').replace(/[^0-9]/g, ''))
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike the good-old-PJAX-time, now GitHub replaces whole body element after redirecting using turbo.
|
||||
* If move Gitako mount point from `body` to `html`, Gitako style would break because it inherits style from GitHub body.
|
||||
* The temporary solution is recovery Gitako elements once the body is removed.
|
||||
*/
|
||||
export function persistGitakoElements(mountPointElement = insertMountPoint()) {
|
||||
mountPointElement.setAttribute('data-turbo-permanent', '')
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
for (const { addedNodes, removedNodes } of mutations) {
|
||||
const [addedBody, removedBody] = [addedNodes, removedNodes].map(findBodyElement)
|
||||
if (addedBody && removedBody) {
|
||||
// hard-coded list due to limited time
|
||||
// TODO: refactor in a better practice
|
||||
|
||||
// migrate gitako attributes, e.g. class
|
||||
const propertiesNeedToMigrate = ['--gitako-width']
|
||||
for (const property of propertiesNeedToMigrate) {
|
||||
const oldValue = removedBody.style.getPropertyValue(property)
|
||||
if (oldValue) addedBody.style.setProperty(property, oldValue)
|
||||
}
|
||||
const cssClassesNeedToMigrate = [bodySpacingClassName]
|
||||
for (const cssClass of cssClassesNeedToMigrate) {
|
||||
if (removedBody.classList.contains(cssClass)) addedBody.classList.add(cssClass)
|
||||
}
|
||||
|
||||
// move gitako elements
|
||||
if (!addedBody.contains(mountPointElement)) addedBody.appendChild(mountPointElement)
|
||||
if (removedBody.contains(mountPointElement)) removedBody.removeChild(mountPointElement)
|
||||
}
|
||||
}
|
||||
|
||||
function findBodyElement(addedNodes: NodeList) {
|
||||
return Array.from(addedNodes).find(addedNode => addedNode instanceof HTMLBodyElement) as
|
||||
| HTMLBodyElement
|
||||
| undefined
|
||||
}
|
||||
})
|
||||
observer.observe(document.documentElement, {
|
||||
childList: true,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,7 @@ export const loadWithPJAX = (url: string, element: HTMLElement) => {
|
|||
|
||||
export function useOnPJAXDone(callback: () => void) {
|
||||
useEvent('pjax:end', callback, document) // legacy support
|
||||
// 'turbo:render' should be the best timing but GitHub has attached a mutation observer on body to block that
|
||||
// TODO: fire at turbo:render
|
||||
useEvent('turbo:load', callback, document)
|
||||
useEvent('turbo:render', callback, document)
|
||||
}
|
||||
|
||||
export function useRedirectedEvents(
|
||||
|
|
|
|||
Loading…
Reference in a new issue