mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 04:15:19 +00:00
fix(mobile): fix the issue of preview images being covered by page (#5535)
* refactor(mobile): replace mobile BasicZIndexProvider with zIndexContext from core library * fix(mobile): fix the issue of preview images being covered by page
This commit is contained in:
parent
c43933e51b
commit
9e5355cbed
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
export * from './Action';
|
||||
export * from './Action.Designer';
|
||||
export * from './ActionBar';
|
||||
export * from './context';
|
||||
export * from './hooks';
|
||||
@ -15,5 +16,5 @@ export * from './hooks/useGetAriaLabelOfAction';
|
||||
export * from './hooks/useGetAriaLabelOfDrawer';
|
||||
export * from './hooks/useGetAriaLabelOfModal';
|
||||
export * from './hooks/useGetAriaLabelOfPopover';
|
||||
export * from './Action.Designer';
|
||||
export * from './types';
|
||||
export * from './zIndexContext';
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { expect, test } from '@nocobase/test/e2e';
|
||||
import { shouldDisplayImageNormally } from './templates';
|
||||
|
||||
test.describe('zIndex', () => {
|
||||
test('should display image normally', async ({ page, mockMobilePage, mockRecord }) => {
|
||||
const nocoPage = await mockMobilePage(shouldDisplayImageNormally).waitForInit();
|
||||
const record = await mockRecord('image');
|
||||
await nocoPage.goto();
|
||||
|
||||
const title = record.attachment[0].title;
|
||||
|
||||
// 通过鼠标 hover 到 Add block 按钮来检查是否符合预期
|
||||
const check = async (level: number) => {
|
||||
try {
|
||||
switch (level) {
|
||||
case 0:
|
||||
await page.getByLabel('schema-initializer-Grid-').hover({ timeout: 300 });
|
||||
break;
|
||||
case 1:
|
||||
await page.getByLabel('schema-initializer-Grid-popup').hover({ timeout: 300 });
|
||||
break;
|
||||
case 2:
|
||||
await page.getByLabel('schema-initializer-Grid-popup').nth(1).hover({ timeout: 300 });
|
||||
break;
|
||||
case 3:
|
||||
await page.getByLabel('schema-initializer-Grid-popup').nth(2).hover({ timeout: 300 });
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
await page.waitForTimeout(300);
|
||||
await expect(page.getByText('Desktop data blocks')).not.toBeVisible();
|
||||
};
|
||||
|
||||
// 1. 在主页面,点击图片预览,图片不能被主页面盖住
|
||||
await page.getByRole('link', { name: title }).click();
|
||||
await page.waitForTimeout(300);
|
||||
await check(0);
|
||||
await page.getByLabel('Close lightbox').click();
|
||||
|
||||
// 2. 进入第一层子页面,然后点击图片预览, 图片不能被子页面盖住
|
||||
await page.getByLabel('action-Action.Link-View-view-').click();
|
||||
await page.getByRole('link', { name: title }).nth(1).click();
|
||||
await page.waitForTimeout(300);
|
||||
await check(1);
|
||||
await page.getByLabel('Close lightbox').click();
|
||||
|
||||
// 3. 进入第二层子页面,然后点击图片预览, 图片不能被子页面盖住
|
||||
await page.getByLabel('action-Action-Edit-update-').click();
|
||||
await page.getByRole('link', { name: title }).nth(2).click();
|
||||
await page.waitForTimeout(300);
|
||||
await check(2);
|
||||
await page.getByLabel('Close lightbox').click();
|
||||
|
||||
// 4. 进入第三层子页面,然后点击图片预览, 图片不能被子页面盖住
|
||||
await page.getByLabel('action-Action-Edit-update-').nth(2).click();
|
||||
await page.getByRole('link', { name: title }).nth(3).click();
|
||||
await page.waitForTimeout(300);
|
||||
await check(3);
|
||||
await page.getByLabel('Close lightbox').click();
|
||||
});
|
||||
});
|
@ -8,14 +8,14 @@
|
||||
*/
|
||||
|
||||
import { ISchema, observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||
import { Action, SchemaComponent, useActionContext } from '@nocobase/client';
|
||||
import { Action, SchemaComponent, useActionContext, useZIndexContext, zIndexContext } from '@nocobase/client';
|
||||
import { ConfigProvider } from 'antd';
|
||||
import { Popup } from 'antd-mobile';
|
||||
import { CloseOutline } from 'antd-mobile-icons';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useMobileActionDrawerStyle } from './ActionDrawer.style';
|
||||
import { BasicZIndexProvider, MIN_Z_INDEX_INCREMENT, useBasicZIndex } from './BasicZIndexProvider';
|
||||
import { usePopupContainer } from './FilterAction';
|
||||
import { MIN_Z_INDEX_INCREMENT } from './zIndex';
|
||||
|
||||
export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?: string }) => {
|
||||
const fieldSchema = useFieldSchema();
|
||||
@ -23,7 +23,7 @@ export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?:
|
||||
const { visible, setVisible } = useActionContext();
|
||||
const { popupContainerRef, visiblePopup } = usePopupContainer(visible);
|
||||
const { styles } = useMobileActionDrawerStyle();
|
||||
const { basicZIndex } = useBasicZIndex();
|
||||
const parentZIndex = useZIndexContext();
|
||||
|
||||
// this schema need to add padding in the content area of the popup
|
||||
const isSpecialSchema = isChangePasswordSchema(fieldSchema) || isEditProfileSchema(fieldSchema);
|
||||
@ -32,7 +32,7 @@ export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?:
|
||||
|
||||
const specialStyle = isSpecialSchema ? { backgroundColor: 'white' } : {};
|
||||
|
||||
const newZIndex = basicZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
const newZIndex = parentZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
|
||||
const zIndexStyle = useMemo(() => {
|
||||
return {
|
||||
@ -66,7 +66,7 @@ export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?:
|
||||
}, [newZIndex]);
|
||||
|
||||
return (
|
||||
<BasicZIndexProvider basicZIndex={newZIndex}>
|
||||
<zIndexContext.Provider value={newZIndex}>
|
||||
<ConfigProvider theme={theme}>
|
||||
<Popup
|
||||
visible={visiblePopup}
|
||||
@ -120,7 +120,7 @@ export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?:
|
||||
) : null}
|
||||
</Popup>
|
||||
</ConfigProvider>
|
||||
</BasicZIndexProvider>
|
||||
</zIndexContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
const BasicZIndexContext = React.createContext<{
|
||||
basicZIndex: number;
|
||||
}>({
|
||||
basicZIndex: 0,
|
||||
});
|
||||
|
||||
/**
|
||||
* used to accumulate z-index in nested popups
|
||||
* @param props
|
||||
* @returns
|
||||
*/
|
||||
export const BasicZIndexProvider: React.FC<{ basicZIndex: number }> = (props) => {
|
||||
const value = useMemo(() => ({ basicZIndex: props.basicZIndex }), [props.basicZIndex]);
|
||||
return <BasicZIndexContext.Provider value={value}>{props.children}</BasicZIndexContext.Provider>;
|
||||
};
|
||||
|
||||
export const useBasicZIndex = () => {
|
||||
return React.useContext(BasicZIndexContext);
|
||||
};
|
||||
|
||||
// minimum z-index increment
|
||||
export const MIN_Z_INDEX_INCREMENT = 10;
|
@ -7,14 +7,14 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { Filter, withDynamicSchemaProps } from '@nocobase/client';
|
||||
import { Filter, useZIndexContext, withDynamicSchemaProps } from '@nocobase/client';
|
||||
import { ConfigProvider } from 'antd';
|
||||
import { Popup } from 'antd-mobile';
|
||||
import { CloseOutline } from 'antd-mobile-icons';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useMobileActionDrawerStyle } from './ActionDrawer.style';
|
||||
import { MIN_Z_INDEX_INCREMENT, useBasicZIndex } from './BasicZIndexProvider';
|
||||
import { MIN_Z_INDEX_INCREMENT } from './zIndex';
|
||||
|
||||
const OriginFilterAction = Filter.Action;
|
||||
|
||||
@ -24,11 +24,11 @@ export const FilterAction = withDynamicSchemaProps((props) => {
|
||||
{...props}
|
||||
Container={(props) => {
|
||||
const { visiblePopup, popupContainerRef } = usePopupContainer(props.open);
|
||||
const { basicZIndex } = useBasicZIndex();
|
||||
const parentZIndex = useZIndexContext();
|
||||
const { styles } = useMobileActionDrawerStyle();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const newZIndex = basicZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
const newZIndex = parentZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const closePopup = useCallback(() => {
|
||||
@ -116,9 +116,9 @@ export const usePopupContainer = (visible: boolean) => {
|
||||
const [mobileContainer] = useState<HTMLElement>(() => document.querySelector('.mobile-container'));
|
||||
const [visiblePopup, setVisiblePopup] = useState(false);
|
||||
const popupContainerRef = React.useRef<HTMLDivElement>(null);
|
||||
const { basicZIndex } = useBasicZIndex();
|
||||
const parentZIndex = useZIndexContext();
|
||||
|
||||
const newZIndex = basicZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
const newZIndex = parentZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
|
||||
useEffect(() => {
|
||||
if (!visible) {
|
||||
|
@ -8,22 +8,23 @@
|
||||
*/
|
||||
|
||||
import { useField } from '@formily/react';
|
||||
import { useZIndexContext, zIndexContext } from '@nocobase/client';
|
||||
import { ConfigProvider } from 'antd';
|
||||
import { Popup } from 'antd-mobile';
|
||||
import { CloseOutline } from 'antd-mobile-icons';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { BasicZIndexProvider, MIN_Z_INDEX_INCREMENT, useBasicZIndex } from './BasicZIndexProvider';
|
||||
import { usePopupContainer } from './FilterAction';
|
||||
import { useInternalPopoverNesterUsedInMobileStyle } from './InternalPopoverNester.style';
|
||||
import { MIN_Z_INDEX_INCREMENT } from './zIndex';
|
||||
|
||||
const Container = (props) => {
|
||||
const { onOpenChange } = props;
|
||||
const { visiblePopup, popupContainerRef } = usePopupContainer(props.open);
|
||||
const { styles } = useInternalPopoverNesterUsedInMobileStyle();
|
||||
const field = useField();
|
||||
const { basicZIndex } = useBasicZIndex();
|
||||
const parentZIndex = useZIndexContext();
|
||||
|
||||
const newZIndex = basicZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
const newZIndex = parentZIndex + MIN_Z_INDEX_INCREMENT;
|
||||
const title = field.title || '';
|
||||
|
||||
const zIndexStyle = useMemo(() => {
|
||||
@ -49,7 +50,7 @@ const Container = (props) => {
|
||||
}, [newZIndex]);
|
||||
|
||||
return (
|
||||
<BasicZIndexProvider basicZIndex={newZIndex}>
|
||||
<zIndexContext.Provider value={newZIndex}>
|
||||
<ConfigProvider theme={theme}>
|
||||
<div onClick={openPopup}>{props.children}</div>
|
||||
<Popup
|
||||
@ -77,7 +78,7 @@ const Container = (props) => {
|
||||
<div style={{ height: 50 }}></div>
|
||||
</Popup>
|
||||
</ConfigProvider>
|
||||
</BasicZIndexProvider>
|
||||
</zIndexContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -16,12 +16,14 @@ import {
|
||||
useActionContext,
|
||||
useApp,
|
||||
useTabsContext,
|
||||
useZIndexContext,
|
||||
zIndexContext,
|
||||
} from '@nocobase/client';
|
||||
import _ from 'lodash';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { usePluginTranslation } from '../../locale';
|
||||
import { BasicZIndexProvider, MIN_Z_INDEX_INCREMENT, useBasicZIndex } from '../BasicZIndexProvider';
|
||||
import { MIN_Z_INDEX_INCREMENT } from '../zIndex';
|
||||
import { useMobileActionPageStyle } from './MobileActionPage.style';
|
||||
import { MobileTabsForMobileActionPage } from './MobileTabsForMobileActionPage';
|
||||
|
||||
@ -94,11 +96,11 @@ export const MobileActionPage = ({ level, footerNodeName }) => {
|
||||
const { styles } = useMobileActionPageStyle();
|
||||
const tabContext = useTabsContext();
|
||||
const containerDOM = useMemo(() => document.querySelector('.nb-mobile-subpages-slot'), []);
|
||||
const { basicZIndex } = useBasicZIndex();
|
||||
const parentZIndex = useZIndexContext();
|
||||
|
||||
// in nested popups, basicZIndex is an accumulated value to ensure that
|
||||
// the z-index of the current level is always higher than the previous level
|
||||
const newZIndex = basicZIndex + MIN_Z_INDEX_INCREMENT + (level || 1);
|
||||
const newZIndex = parentZIndex + MIN_Z_INDEX_INCREMENT + (level || 1);
|
||||
|
||||
const footerSchema = fieldSchema.reduceProperties((buf, s) => {
|
||||
if (s['x-component'] === footerNodeName) {
|
||||
@ -118,7 +120,7 @@ export const MobileActionPage = ({ level, footerNodeName }) => {
|
||||
}
|
||||
|
||||
const actionPageNode = (
|
||||
<BasicZIndexProvider basicZIndex={newZIndex}>
|
||||
<zIndexContext.Provider value={newZIndex}>
|
||||
<div className={styles.container} style={zIndexStyle}>
|
||||
<TabsContextProvider {...tabContext} tabBarExtraContent={<BackButtonUsedInSubPage />} tabBarGutter={48}>
|
||||
<SchemaComponent components={components} schema={fieldSchema} onlyRenderProperties />
|
||||
@ -136,7 +138,7 @@ export const MobileActionPage = ({ level, footerNodeName }) => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</BasicZIndexProvider>
|
||||
</zIndexContext.Provider>
|
||||
);
|
||||
|
||||
if (containerDOM) {
|
||||
|
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
// minimum z-index increment
|
||||
export const MIN_Z_INDEX_INCREMENT = 10;
|
@ -18,12 +18,12 @@ import {
|
||||
OpenModeProvider,
|
||||
useAssociationFieldModeContext,
|
||||
usePlugin,
|
||||
zIndexContext,
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { isDesktop } from 'react-device-detect';
|
||||
|
||||
import { ActionDrawerUsedInMobile, useToAdaptActionDrawerToMobile } from '../adaptor-of-desktop/ActionDrawer';
|
||||
import { BasicZIndexProvider } from '../adaptor-of-desktop/BasicZIndexProvider';
|
||||
import { useToAdaptFilterActionToMobile } from '../adaptor-of-desktop/FilterAction';
|
||||
import { InternalPopoverNesterUsedInMobile } from '../adaptor-of-desktop/InternalPopoverNester';
|
||||
import { MobileActionPage } from '../adaptor-of-desktop/mobile-action-page/MobileActionPage';
|
||||
@ -102,9 +102,9 @@ export const Mobile = () => {
|
||||
<ResetSchemaOptionsProvider>
|
||||
<AssociationFieldModeProvider modeToComponent={modeToComponent}>
|
||||
{/* the z-index of all popups and subpages will be based on this value */}
|
||||
<BasicZIndexProvider basicZIndex={1000}>
|
||||
<zIndexContext.Provider value={100}>
|
||||
<MobileRouter />
|
||||
</BasicZIndexProvider>
|
||||
</zIndexContext.Provider>
|
||||
</AssociationFieldModeProvider>
|
||||
</ResetSchemaOptionsProvider>
|
||||
</MobileAppProvider>
|
||||
|
Loading…
Reference in New Issue
Block a user