From 4590c754ce47fe263e42e1caf9b7e815e0acf083 Mon Sep 17 00:00:00 2001 From: Zeke Zhang <958414905@qq.com> Date: Fri, 9 Aug 2024 11:45:22 +0800 Subject: [PATCH] feat: support to add Settings block in mobile (#5025) * feat: support to add Settings block in mobile * style(Popup): clear the margin-bottom of the last block * refactor: extract hideDivider * fix: fix form values --- .../adaptor-of-desktop/ActionDrawer.style.ts | 16 +++++- .../adaptor-of-desktop/ActionDrawer.tsx | 53 +++++++++++++------ .../adaptor-of-desktop/FilterAction.tsx | 2 +- .../client/adaptor-of-desktop/hideDivider.tsx | 24 +++++++++ .../MobileTabsForMobileActionPage.tsx | 17 +----- .../plugin-mobile/src/client/index.tsx | 6 +++ .../settings-block/MobileSettings.tsx | 29 ++++++++++ .../MobileSettingsBlockInitializer.tsx | 31 +++++++++++ .../settings-block/schemaSettings.tsx | 34 ++++++++++++ .../dynamic-page/content/initializer.tsx | 6 +++ .../plugin-mobile/src/locale/en-US.json | 3 +- .../plugin-mobile/src/locale/zh-CN.json | 3 +- .../src/client/hooks/useThemeSettings.tsx | 2 +- 13 files changed, 190 insertions(+), 36 deletions(-) create mode 100644 packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/hideDivider.tsx create mode 100644 packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx create mode 100644 packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettingsBlockInitializer.tsx create mode 100644 packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/schemaSettings.tsx diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.style.ts b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.style.ts index 45c56276f2..4088834957 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.style.ts +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.style.ts @@ -24,8 +24,7 @@ export const useMobileActionDrawerStyle = createStyles(({ css, token }: any) => // to match the button named 'Add block' & + .nb-grid-container > .nb-grid > .nb-grid-warp > .ant-btn { - // 18px is the token marginBlock value - margin: 12px 12px calc(12px + 18px); + margin: 12px; } `, @@ -48,6 +47,15 @@ export const useMobileActionDrawerStyle = createStyles(({ css, token }: any) => overflow-y: auto; overflow-x: hidden; background-color: ${token.colorBgLayout}; + + // clear the margin-bottom of the last block + & > .nb-grid-container > .nb-grid > .nb-grid-warp > .nb-grid-row:nth-last-child(2) .noco-card-item { + margin-bottom: 0; + + & > .ant-card { + margin-bottom: 0 !important; + } + } `, footer: css` @@ -62,6 +70,10 @@ export const useMobileActionDrawerStyle = createStyles(({ css, token }: any) => z-index: 1000; border-top: 1px solid ${token.colorSplit}; background-color: ${token.colorBgLayout}; + + .ant-btn { + margin-left: 8px; + } `, }; }); diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx index 5dad502e64..6e0e7baea6 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/ActionDrawer.tsx @@ -7,7 +7,7 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { observer, RecursionField, useField, useFieldSchema } from '@formily/react'; +import { ISchema, observer, RecursionField, useField, useFieldSchema } from '@formily/react'; import { Action, SchemaComponent, useActionContext } from '@nocobase/client'; import { ConfigProvider } from 'antd'; import { Popup } from 'antd-mobile'; @@ -17,7 +17,7 @@ import { useMobileActionDrawerStyle } from './ActionDrawer.style'; import { BasicZIndexProvider, MIN_Z_INDEX_INCREMENT, useBasicZIndex } from './BasicZIndexProvider'; import { usePopupContainer } from './FilterAction'; -export const ActionDrawerUsedInMobile = observer((props: { footerNodeName?: string }) => { +export const ActionDrawerUsedInMobile: any = observer((props: { footerNodeName?: string }) => { const fieldSchema = useFieldSchema(); const field = useField(); const { visible, setVisible } = useActionContext(); @@ -25,6 +25,13 @@ export const ActionDrawerUsedInMobile = observer((props: { footerNodeName?: stri const { styles } = useMobileActionDrawerStyle(); const { basicZIndex } = useBasicZIndex(); + // this schema need to add padding in the content area of the popup + const isSpecialSchema = isChangePasswordSchema(fieldSchema) || isEditProfileSchema(fieldSchema); + + const footerNodeName = isSpecialSchema ? 'Action.Drawer.Footer' : props.footerNodeName; + + const specialStyle = isSpecialSchema ? { backgroundColor: 'white' } : {}; + const newZIndex = basicZIndex + MIN_Z_INDEX_INCREMENT; const zIndexStyle = useMemo(() => { @@ -34,7 +41,7 @@ export const ActionDrawerUsedInMobile = observer((props: { footerNodeName?: stri }, [newZIndex]); const footerSchema = fieldSchema.reduceProperties((buf, s) => { - if (s['x-component'] === props.footerNodeName) { + if (s['x-component'] === footerNodeName) { return s; } return buf; @@ -81,24 +88,32 @@ export const ActionDrawerUsedInMobile = observer((props: { footerNodeName?: stri - { - return s['x-component'] !== props.footerNodeName; - }} - /> - {/* used to offset the margin-bottom of the last block */} - {/* The number 1 is to prevent the scroll bar from appearing */} -
+ {isSpecialSchema ? ( +
+ { + return s['x-component'] !== footerNodeName; + }} + /> +
+ ) : ( + { + return s['x-component'] !== footerNodeName; + }} + /> + )} {footerSchema ? ( -
+
{ - return s['x-component'] === props.footerNodeName; + return s['x-component'] === footerNodeName; }} />
@@ -125,3 +140,11 @@ export const useToAdaptActionDrawerToMobile = () => { }; }, []); }; + +function isEditProfileSchema(schema: ISchema) { + return schema.title === `{{t("Edit profile")}}`; +} + +function isChangePasswordSchema(schema: ISchema) { + return schema.title === `{{t("Change password")}}`; +} diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/FilterAction.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/FilterAction.tsx index 7975881223..4370e8449b 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/FilterAction.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/FilterAction.tsx @@ -108,7 +108,7 @@ export const useToAdaptFilterActionToMobile = () => { }; /** - * 之所以不直接使用 mobile-container 作为容器,是因为会影响到区块的拖拽功能。详见:https://nocobase.height.app/T-4959 + * 之所以不直接在 mobile-container 中设置 transform,是因为会影响到子页面区块的拖拽功能。详见:https://nocobase.height.app/T-4959 * @param visible * @returns */ diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/hideDivider.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/hideDivider.tsx new file mode 100644 index 0000000000..2309f255ec --- /dev/null +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/hideDivider.tsx @@ -0,0 +1,24 @@ +/** + * 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 { Schema } from '@nocobase/utils'; + +// 隐藏 Grid 组件的左右 divider,因为移动端不需要在一行中并列展示两个区块 +export function hideDivider(schema: Schema) { + schema?.mapProperties((schema) => { + if (schema['x-component'] === 'Grid') { + schema['x-component-props'] = { + ...schema['x-component-props'], + showDivider: false, + }; + } + }); + + return schema; +} diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/mobile-action-page/MobileTabsForMobileActionPage.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/mobile-action-page/MobileTabsForMobileActionPage.tsx index 16c601aa82..ce6b10cbde 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/mobile-action-page/MobileTabsForMobileActionPage.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/adaptor-of-desktop/mobile-action-page/MobileTabsForMobileActionPage.tsx @@ -7,7 +7,7 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react'; +import { observer, RecursionField, useField, useFieldSchema } from '@formily/react'; import { css, DndContext, @@ -27,6 +27,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { MobilePageHeader } from '../../pages/dynamic-page'; import { MobilePageContentContainer } from '../../pages/dynamic-page/content/MobilePageContentContainer'; import { useStyles } from '../../pages/dynamic-page/header/tabs'; +import { hideDivider } from '../hideDivider'; import { useMobileTabsForMobileActionPageStyle } from './MobileTabsForMobileActionPage.style'; export const MobileTabsForMobileActionPage: any = observer( @@ -162,17 +163,3 @@ MobileTabsForMobileActionPage.TabPane = observer( ); MobileTabsForMobileActionPage.Designer = TabsOfPC.Designer; - -// 隐藏 Grid 组件的左右 divider,因为移动端不需要在一行中并列展示两个区块 -function hideDivider(tabPaneSchema: Schema) { - tabPaneSchema?.mapProperties((schema) => { - if (schema['x-component'] === 'Grid') { - schema['x-component-props'] = { - ...schema['x-component-props'], - showDivider: false, - }; - } - }); - - return tabPaneSchema; -} diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx index 58520ce162..9c485a5b87 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/index.tsx @@ -45,6 +45,9 @@ import { // 导出 JSBridge,会挂在到 window 上 import './js-bridge'; +import { MobileSettings } from './mobile-blocks/settings-block/MobileSettings'; +import { MobileSettingsBlockInitializer } from './mobile-blocks/settings-block/MobileSettingsBlockInitializer'; +import { MobileSettingsBlockSchemaSettings } from './mobile-blocks/settings-block/schemaSettings'; import { MobileCheckerProvider } from './providers'; export * from './desktop-mode'; @@ -135,6 +138,7 @@ export class PluginMobileClient extends Plugin { mobileTabBarLinkSettings, mobilePageTabsSettings, mobileNavigationBarLinkSettings, + MobileSettingsBlockSchemaSettings, ); } @@ -150,6 +154,8 @@ export class PluginMobileClient extends Plugin { MobilePageTabs, MobileNavigationActionBar, MobileNotFoundPage, + MobileSettingsBlockInitializer, + MobileSettings, }); } diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx new file mode 100644 index 0000000000..bf5e00692a --- /dev/null +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx @@ -0,0 +1,29 @@ +/** + * 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 { cx, SettingsMenu, SortableItem, useDesigner, useToken } from '@nocobase/client'; +import React, { useMemo } from 'react'; + +export const InternalSettings = () => { + const Designer = useDesigner(); + const { token } = useToken(); + const style = useMemo(() => { + return { + marginBottom: token.marginBlock, + }; + }, [token.marginBlock]); + + return ( + + + + + ); +}; +export const MobileSettings = InternalSettings; diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettingsBlockInitializer.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettingsBlockInitializer.tsx new file mode 100644 index 0000000000..eabe31a328 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettingsBlockInitializer.tsx @@ -0,0 +1,31 @@ +/** + * 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 { SettingOutlined } from '@ant-design/icons'; +import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '@nocobase/client'; +import React from 'react'; + +export const MobileSettingsBlockInitializer = () => { + const itemConfig = useSchemaInitializerItem(); + const { insert } = useSchemaInitializer(); + return ( + } + onClick={async () => { + insert({ + type: 'void', + 'x-component': 'MobileSettings', + 'x-settings': 'blockSettings:mobileSettings', + 'x-component-props': {}, + }); + }} + {...itemConfig} + /> + ); +}; diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/schemaSettings.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/schemaSettings.tsx new file mode 100644 index 0000000000..603d04ba5e --- /dev/null +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/schemaSettings.tsx @@ -0,0 +1,34 @@ +/** + * 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 { SchemaSettings } from '@nocobase/client'; +import { usePluginTranslation } from '../../locale'; + +export const MobileSettingsBlockSchemaSettings = new SchemaSettings({ + name: 'blockSettings:mobileSettings', + items: [ + { + name: 'delete', + type: 'remove', + useComponentProps() { + const { t } = usePluginTranslation(); + + return { + removeParentsIfNoChildren: true, + confirm: { + title: t('Delete settings block'), + }, + breakRemoveOn: { + 'x-component': 'Grid', + }, + }; + }, + }, + ], +}); diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/initializer.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/initializer.tsx index de22d591e8..48d93b2170 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/initializer.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/initializer.tsx @@ -8,6 +8,7 @@ */ import { SchemaInitializer, gridRowColWrap } from '@nocobase/client'; +import { generatePluginTranslationTemplate } from '../../../locale'; export const mobileAddBlockInitializer = new SchemaInitializer({ title: '{{t("Add block")}}', @@ -60,6 +61,11 @@ export const mobileAddBlockInitializer = new SchemaInitializer({ title: '{{t("Markdown")}}', Component: 'MarkdownBlockInitializer', }, + { + name: 'settings', + title: generatePluginTranslationTemplate('Settings'), + Component: 'MobileSettingsBlockInitializer', + }, ], }, ], diff --git a/packages/plugins/@nocobase/plugin-mobile/src/locale/en-US.json b/packages/plugins/@nocobase/plugin-mobile/src/locale/en-US.json index f99605a80b..43c0b120ef 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/locale/en-US.json +++ b/packages/plugins/@nocobase/plugin-mobile/src/locale/en-US.json @@ -20,5 +20,6 @@ "Title field is required": "Title field is required", "Icon field is required": "Icon field is required", "Desktop data blocks": "Desktop data blocks", - "Other desktop blocks": "Other desktop blocks" + "Other desktop blocks": "Other desktop blocks", + "Settings": "Settings" } diff --git a/packages/plugins/@nocobase/plugin-mobile/src/locale/zh-CN.json b/packages/plugins/@nocobase/plugin-mobile/src/locale/zh-CN.json index 58c7f52b16..f24a8fedd5 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/locale/zh-CN.json +++ b/packages/plugins/@nocobase/plugin-mobile/src/locale/zh-CN.json @@ -21,5 +21,6 @@ "Title field is required": "标题必填", "Icon field is required": "图标必填", "Desktop data blocks": "桌面端数据区块", - "Other desktop blocks": "其他桌面端区块" + "Other desktop blocks": "其他桌面端区块", + "Settings": "设置" } diff --git a/packages/plugins/@nocobase/plugin-theme-editor/src/client/hooks/useThemeSettings.tsx b/packages/plugins/@nocobase/plugin-theme-editor/src/client/hooks/useThemeSettings.tsx index bbfc376208..abb1331bf2 100644 --- a/packages/plugins/@nocobase/plugin-theme-editor/src/client/hooks/useThemeSettings.tsx +++ b/packages/plugins/@nocobase/plugin-theme-editor/src/client/hooks/useThemeSettings.tsx @@ -7,7 +7,7 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { SelectWithTitle, useAPIClient, useCurrentUserContext, useSystemSettings } from '@nocobase/client'; +import { SelectWithTitle, useCurrentUserContext, useSystemSettings } from '@nocobase/client'; import { error } from '@nocobase/utils/client'; import { MenuProps } from 'antd'; import React, { useEffect, useMemo } from 'react';