Fix lightbox fullscreen issues (#4149)

* Improve lightbox context hook
* Prevent fullscreen drop while loading
* Fix close not working from fullscreen
This commit is contained in:
WithoutPants
2023-09-25 09:35:55 +10:00
committed by GitHub
parent 462943a903
commit 9f5bcca1eb
3 changed files with 285 additions and 260 deletions

View File

@@ -319,12 +319,12 @@ export const LightboxComponent: React.FC<IProps> = ({
});
const close = useCallback(() => {
if (!isFullscreen) {
if (isFullscreen) document.exitFullscreen();
hide();
document.body.style.overflow = "auto";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(Mousetrap as any).unpause();
} else document.exitFullscreen();
}, [isFullscreen, hide]);
const handleClose = (e: React.MouseEvent<HTMLDivElement>) => {
@@ -685,10 +685,7 @@ export const LightboxComponent: React.FC<IProps> = ({
);
}
if (!isVisible) {
return <></>;
}
function renderBody() {
if (images.length === 0 || isLoading || isSwitchingPage) {
return <LoadingIndicator />;
}
@@ -744,12 +741,7 @@ export const LightboxComponent: React.FC<IProps> = ({
: "";
return (
<div
className={CLASSNAME}
role="presentation"
ref={containerRef}
onClick={handleClose}
>
<>
<div className={CLASSNAME_HEADER}>
<div className={CLASSNAME_LEFT_SPACER}>{renderChapterMenu()}</div>
<div className={CLASSNAME_INDICATOR}>
@@ -757,7 +749,9 @@ export const LightboxComponent: React.FC<IProps> = ({
{chapterHeader()} {pageHeader}
</span>
{images.length > 1 ? (
<b ref={indicatorRef}>{`${currentIndex + 1} / ${images.length}`}</b>
<b ref={indicatorRef}>{`${currentIndex + 1} / ${
images.length
}`}</b>
) : undefined}
</div>
<div className={CLASSNAME_RIGHT}>
@@ -831,7 +825,11 @@ export const LightboxComponent: React.FC<IProps> = ({
<Icon icon={faExpand} />
</Button>
)}
<Button variant="link" onClick={() => close()} title="Close Lightbox">
<Button
variant="link"
onClick={() => close()}
title="Close Lightbox"
>
<Icon icon={faTimes} />
</Button>
</div>
@@ -942,6 +940,22 @@ export const LightboxComponent: React.FC<IProps> = ({
</div>
<div></div>
</div>
</>
);
}
if (!isVisible) {
return <></>;
}
return (
<div
className={CLASSNAME}
role="presentation"
ref={containerRef}
onClick={handleClose}
>
{renderBody()}
</div>
);
};

View File

@@ -19,12 +19,21 @@ export interface IState {
onClose?: () => void;
}
interface IContext {
lightboxState: IState;
setLightboxState: (state: Partial<IState>) => void;
}
export const LightboxContext = React.createContext<IContext>({
setLightboxState: () => {},
});
export const LightboxContext = React.createContext<IContext | null>(null);
export function useLightboxContext() {
const context = React.useContext(LightboxContext);
if (!context) {
throw new Error(
"useLightboxContext must be used within a LightboxProvider"
);
}
return context;
}
export const LightboxProvider: React.FC = ({ children }) => {
const [lightboxState, setLightboxState] = useState<IState>({
@@ -53,7 +62,9 @@ export const LightboxProvider: React.FC = ({ children }) => {
};
return (
<LightboxContext.Provider value={{ setLightboxState: setPartialState }}>
<LightboxContext.Provider
value={{ lightboxState, setLightboxState: setPartialState }}
>
{children}
<Suspense fallback={<></>}>
{lightboxState.isVisible && (

View File

@@ -1,13 +1,13 @@
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import * as GQL from "src/core/generated-graphql";
import { LightboxContext, IState } from "./context";
import { IState, useLightboxContext } from "./context";
import { IChapter } from "./types";
export const useLightbox = (
state: Partial<Omit<IState, "isVisible">>,
chapters: IChapter[] = []
) => {
const { setLightboxState } = useContext(LightboxContext);
const { setLightboxState } = useLightboxContext();
useEffect(() => {
setLightboxState({
@@ -50,7 +50,7 @@ export const useLightbox = (
};
export const useGalleryLightbox = (id: string, chapters: IChapter[] = []) => {
const { setLightboxState } = useContext(LightboxContext);
const { setLightboxState } = useLightboxContext();
const pageSize = 40;
const [page, setPage] = useState(1);