@nocobase/plugin-mobile-client 0.10.0-alpha.2 → 0.10.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/lib/client/core/bridge/injects.d.ts +1 -1
  2. package/lib/client/core/bridge/injects.js +3 -3
  3. package/lib/client/core/schema/components/container/Container.Designer.js +27 -26
  4. package/lib/client/core/schema/components/menu/Menu.Item.js +2 -18
  5. package/lib/client/core/schema/components/menu/schema.js +3 -2
  6. package/lib/client/core/schema/components/page/Page.Designer.js +24 -23
  7. package/lib/client/core/schema/components/page/Page.js +40 -33
  8. package/lib/client/core/schema/components/settings/Settings.js +7 -7
  9. package/lib/client/locale/index.d.ts +1 -1
  10. package/lib/client/router/Application.js +22 -16
  11. package/lib/client/router/RouteSwitchProvider.js +1 -1
  12. package/lib/server/migrations/20230620203217-mobile-ui-schema-uid.d.ts +4 -0
  13. package/lib/server/migrations/20230620203217-mobile-ui-schema-uid.js +56 -0
  14. package/lib/server/plugin.js +48 -3
  15. package/package.json +7 -7
  16. package/src/client/core/bridge/injects.ts +6 -5
  17. package/src/client/core/schema/components/container/Container.Designer.tsx +7 -6
  18. package/src/client/core/schema/components/menu/Menu.Item.tsx +2 -18
  19. package/src/client/core/schema/components/menu/schema.ts +4 -2
  20. package/src/client/core/schema/components/page/Page.Designer.tsx +6 -5
  21. package/src/client/core/schema/components/page/Page.tsx +78 -55
  22. package/src/client/core/schema/components/settings/Settings.tsx +2 -2
  23. package/src/client/router/Application.tsx +19 -6
  24. package/src/client/router/RouteSwitchProvider.tsx +1 -1
  25. package/src/server/migrations/20230620203217-mobile-ui-schema-uid.ts +26 -0
  26. package/src/server/plugin.ts +40 -2
@@ -9,5 +9,5 @@ interface InvokeFunction {
9
9
  }, cb?: () => void): void;
10
10
  }
11
11
  export declare const invoke: InvokeFunction;
12
- export declare const isJSBridge: boolean;
12
+ export declare const isJSBridge: () => boolean;
13
13
  export {};
@@ -4,10 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.isJSBridge = exports.invoke = void 0;
7
- const JsBridge = window.JsBridge;
7
+ const getJsBridge = () => window.JsBridge;
8
8
  const invoke = (params, cb) => {
9
- JsBridge.invoke(params, cb);
9
+ return getJsBridge().invoke(params, cb);
10
10
  };
11
11
  exports.invoke = invoke;
12
- const isJSBridge = !!JsBridge;
12
+ const isJSBridge = () => !!getJsBridge();
13
13
  exports.isJSBridge = isJSBridge;
@@ -4,24 +4,16 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.ContainerDesigner = void 0;
7
- function _client() {
8
- const data = require("@nocobase/client");
9
- _client = function _client() {
7
+ function _icons() {
8
+ const data = require("@ant-design/icons");
9
+ _icons = function _icons() {
10
10
  return data;
11
11
  };
12
12
  return data;
13
13
  }
14
14
  function _react() {
15
- const data = _interopRequireDefault(require("react"));
16
- _react = function _react() {
17
- return data;
18
- };
19
- return data;
20
- }
21
- var _locale = require("../../../../locale");
22
- function _react2() {
23
15
  const data = require("@formily/react");
24
- _react2 = function _react2() {
16
+ _react = function _react() {
25
17
  return data;
26
18
  };
27
19
  return data;
@@ -33,14 +25,13 @@ function _shared() {
33
25
  };
34
26
  return data;
35
27
  }
36
- function _reactRouterDom() {
37
- const data = require("react-router-dom");
38
- _reactRouterDom = function _reactRouterDom() {
28
+ function _client() {
29
+ const data = require("@nocobase/client");
30
+ _client = function _client() {
39
31
  return data;
40
32
  };
41
33
  return data;
42
34
  }
43
- var _helpers = require("../../helpers");
44
35
  function _antd() {
45
36
  const data = require("antd");
46
37
  _antd = function _antd() {
@@ -48,14 +39,23 @@ function _antd() {
48
39
  };
49
40
  return data;
50
41
  }
51
- function _icons() {
52
- const data = require("@ant-design/icons");
53
- _icons = function _icons() {
42
+ function _react2() {
43
+ const data = _interopRequireDefault(require("react"));
44
+ _react2 = function _react2() {
54
45
  return data;
55
46
  };
56
47
  return data;
57
48
  }
49
+ function _reactRouterDom() {
50
+ const data = require("react-router-dom");
51
+ _reactRouterDom = function _reactRouterDom() {
52
+ return data;
53
+ };
54
+ return data;
55
+ }
56
+ var _locale = require("../../../../locale");
58
57
  var _common = require("../../common");
58
+ var _helpers = require("../../helpers");
59
59
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
60
60
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
61
61
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -67,27 +67,28 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
67
67
  const ContainerDesigner = () => {
68
68
  const _useTranslation = (0, _locale.useTranslation)(),
69
69
  t = _useTranslation.t;
70
- const fieldSchema = (0, _react2().useFieldSchema)();
70
+ const fieldSchema = (0, _react().useFieldSchema)();
71
71
  const _useDesignable = (0, _client().useDesignable)(),
72
72
  dn = _useDesignable.dn;
73
73
  const tabBarSchema = fieldSchema.reduceProperties((schema, next) => schema || next['x-component'] === 'MTabBar' && next);
74
74
  const navigate = (0, _reactRouterDom().useNavigate)();
75
- const field = (0, _react2().useField)();
75
+ const field = (0, _react().useField)();
76
76
  const schemaSettingsProps = {
77
77
  dn,
78
78
  field,
79
79
  fieldSchema
80
80
  };
81
- return _react().default.createElement(_client().SchemaSettings, _objectSpread({
82
- title: _react().default.createElement(_antd().Button, {
81
+ return _react2().default.createElement(_client().SchemaSettings, _objectSpread({
82
+ title: _react2().default.createElement(_antd().Button, {
83
83
  style: {
84
84
  borderColor: 'rgb(241, 139, 98)',
85
- color: 'rgb(241, 139, 98)'
85
+ color: 'rgb(241, 139, 98)',
86
+ width: '100%'
86
87
  },
87
- icon: _react().default.createElement(_icons().MenuOutlined, null),
88
+ icon: _react2().default.createElement(_icons().MenuOutlined, null),
88
89
  type: "dashed"
89
90
  }, t('App level Configuration'))
90
- }, schemaSettingsProps), _react().default.createElement(_client().SchemaSettings.SwitchItem, {
91
+ }, schemaSettingsProps), _react2().default.createElement(_client().SchemaSettings.SwitchItem, {
91
92
  checked: !!tabBarSchema,
92
93
  title: t('Enable TabBar'),
93
94
  onChange: function () {
@@ -48,6 +48,7 @@ function _reactRouterDom() {
48
48
  }
49
49
  var _locale = require("../../../../locale");
50
50
  var _hooks = require("../../hooks");
51
+ var _schema = require("./schema");
51
52
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
52
53
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
53
54
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
@@ -94,24 +95,7 @@ const MenuItemDesigner = () => {
94
95
  return _react2().default.createElement(_client().GeneralSchemaDesigner, null, _react2().default.createElement(_client().SchemaSettings.ModalItem, {
95
96
  title: t('Edit menu info'),
96
97
  initialValues: field.componentProps,
97
- schema: {
98
- properties: {
99
- name: {
100
- type: 'string',
101
- title: t('Menu name'),
102
- required: true,
103
- 'x-component': 'Input',
104
- 'x-decorator': 'FormItem'
105
- },
106
- icon: {
107
- required: true,
108
- 'x-decorator': 'FormItem',
109
- 'x-component': 'IconPicker',
110
- title: t('Icon'),
111
- 'x-component-props': {}
112
- }
113
- }
114
- },
98
+ schema: _schema.menuItemSchema,
115
99
  onSubmit: onUpdateComponentProps
116
100
  }), _react2().default.createElement(_client().SchemaSettings.Remove, {
117
101
  key: "remove",
@@ -4,11 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.menuItemSchema = void 0;
7
+ var _locale = require("../../../../locale");
7
8
  const menuItemSchema = {
8
9
  properties: {
9
10
  name: {
10
11
  type: 'string',
11
- title: `{{t('Menu name')}}`,
12
+ title: (0, _locale.generateNTemplate)('Menu name'),
12
13
  required: true,
13
14
  'x-component': 'Input',
14
15
  'x-decorator': 'FormItem'
@@ -16,7 +17,7 @@ const menuItemSchema = {
16
17
  icon: {
17
18
  'x-decorator': 'FormItem',
18
19
  'x-component': 'IconPicker',
19
- title: `{{t('Icon')}}`,
20
+ title: (0, _locale.generateNTemplate)('Icon'),
20
21
  'x-component-props': {}
21
22
  }
22
23
  }
@@ -4,32 +4,30 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.PageDesigner = void 0;
7
- function _client() {
8
- const data = require("@nocobase/client");
9
- _client = function _client() {
7
+ function _icons() {
8
+ const data = require("@ant-design/icons");
9
+ _icons = function _icons() {
10
10
  return data;
11
11
  };
12
12
  return data;
13
13
  }
14
14
  function _react() {
15
- const data = _interopRequireDefault(require("react"));
15
+ const data = require("@formily/react");
16
16
  _react = function _react() {
17
17
  return data;
18
18
  };
19
19
  return data;
20
20
  }
21
- var _locale = require("../../../../locale");
22
- function _react2() {
23
- const data = require("@formily/react");
24
- _react2 = function _react2() {
21
+ function _shared() {
22
+ const data = require("@formily/shared");
23
+ _shared = function _shared() {
25
24
  return data;
26
25
  };
27
26
  return data;
28
27
  }
29
- var _helpers = require("../../helpers");
30
- function _shared() {
31
- const data = require("@formily/shared");
32
- _shared = function _shared() {
28
+ function _client() {
29
+ const data = require("@nocobase/client");
30
+ _client = function _client() {
33
31
  return data;
34
32
  };
35
33
  return data;
@@ -41,13 +39,15 @@ function _antd() {
41
39
  };
42
40
  return data;
43
41
  }
44
- function _icons() {
45
- const data = require("@ant-design/icons");
46
- _icons = function _icons() {
42
+ function _react2() {
43
+ const data = _interopRequireDefault(require("react"));
44
+ _react2 = function _react2() {
47
45
  return data;
48
46
  };
49
47
  return data;
50
48
  }
49
+ var _locale = require("../../../../locale");
50
+ var _helpers = require("../../helpers");
51
51
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
52
52
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
53
53
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -61,27 +61,28 @@ const PageDesigner = props => {
61
61
  const showBack = props.showBack;
62
62
  const _useTranslation = (0, _locale.useTranslation)(),
63
63
  t = _useTranslation.t;
64
- const fieldSchema = (0, _react2().useFieldSchema)();
64
+ const fieldSchema = (0, _react().useFieldSchema)();
65
65
  const _useDesignable = (0, _client().useDesignable)(),
66
66
  dn = _useDesignable.dn;
67
67
  const headerSchema = fieldSchema === null || fieldSchema === void 0 ? void 0 : (_fieldSchema$properti = fieldSchema.properties) === null || _fieldSchema$properti === void 0 ? void 0 : _fieldSchema$properti['header'];
68
68
  const tabsSchema = fieldSchema === null || fieldSchema === void 0 ? void 0 : (_fieldSchema$properti2 = fieldSchema.properties) === null || _fieldSchema$properti2 === void 0 ? void 0 : _fieldSchema$properti2['tabs'];
69
- const field = (0, _react2().useField)();
69
+ const field = (0, _react().useField)();
70
70
  const schemaSettingsProps = {
71
71
  dn,
72
72
  field,
73
73
  fieldSchema
74
74
  };
75
- return _react().default.createElement(_client().SchemaSettings, _objectSpread({
76
- title: _react().default.createElement(_antd().Button, {
75
+ return _react2().default.createElement(_client().SchemaSettings, _objectSpread({
76
+ title: _react2().default.createElement(_antd().Button, {
77
77
  style: {
78
78
  borderColor: 'rgb(241, 139, 98)',
79
- color: 'rgb(241, 139, 98)'
79
+ color: 'rgb(241, 139, 98)',
80
+ width: '100%'
80
81
  },
81
- icon: _react().default.createElement(_icons().MenuOutlined, null),
82
+ icon: _react2().default.createElement(_icons().MenuOutlined, null),
82
83
  type: "dashed"
83
84
  }, t('Page configuration'))
84
- }, schemaSettingsProps), _react().default.createElement(_client().SchemaSettings.SwitchItem, {
85
+ }, schemaSettingsProps), _react2().default.createElement(_client().SchemaSettings.SwitchItem, {
85
86
  checked: !!headerSchema,
86
87
  title: t('Enable Header'),
87
88
  onChange: function () {
@@ -108,7 +109,7 @@ const PageDesigner = props => {
108
109
  }
109
110
  return onChange;
110
111
  }()
111
- }), _react().default.createElement(_client().SchemaSettings.SwitchItem, {
112
+ }), _react2().default.createElement(_client().SchemaSettings.SwitchItem, {
112
113
  checked: !!tabsSchema,
113
114
  title: t('Enable Tabs'),
114
115
  onChange: function () {
@@ -78,65 +78,72 @@ const InternalPage = props => {
78
78
  // Only support globalActions in page
79
79
  const onlyInPage = fieldSchema.root === fieldSchema.parent;
80
80
  let hasGlobalActions = false;
81
- if (!tabsSchema) {
81
+ if (!tabsSchema && fieldSchema.properties) {
82
82
  hasGlobalActions = (0, _helpers.countGridCol)(fieldSchema.properties['grid'], 2) === 1;
83
- } else if (searchParams.has('tab') && ((_tabsSchema$propertie = tabsSchema.properties) === null || _tabsSchema$propertie === void 0 ? void 0 : _tabsSchema$propertie[searchParams.get('tab')])) {
83
+ } else if (searchParams.has('tab') && (tabsSchema === null || tabsSchema === void 0 ? void 0 : (_tabsSchema$propertie = tabsSchema.properties) === null || _tabsSchema$propertie === void 0 ? void 0 : _tabsSchema$propertie[searchParams.get('tab')])) {
84
84
  var _tabsSchema$propertie2, _tabsSchema$propertie3;
85
85
  hasGlobalActions = (0, _helpers.countGridCol)((_tabsSchema$propertie2 = tabsSchema.properties[searchParams.get('tab')]) === null || _tabsSchema$propertie2 === void 0 ? void 0 : (_tabsSchema$propertie3 = _tabsSchema$propertie2.properties) === null || _tabsSchema$propertie3 === void 0 ? void 0 : _tabsSchema$propertie3['grid'], 2) === 1;
86
- } else if (tabsSchema.properties) {
86
+ } else if (tabsSchema === null || tabsSchema === void 0 ? void 0 : tabsSchema.properties) {
87
87
  const schema = Object.values(tabsSchema.properties).sort((t1, t2) => t1['x-index'] - t2['x-index'])[0];
88
88
  if (schema) {
89
89
  setTimeout(() => {
90
- setSearchParams([['tab', schema.name.toString()]]);
90
+ setSearchParams([['tab', schema.name.toString()]], {
91
+ replace: true
92
+ });
91
93
  });
92
94
  }
93
95
  }
94
96
  const onTabsChange = (0, _react2().useCallback)(key => {
95
- setSearchParams([['tab', key]]);
97
+ setSearchParams([['tab', key]], {
98
+ replace: true
99
+ });
96
100
  }, [setSearchParams]);
97
- const GlobalActionProvider = (0, _react2().useMemo)(() => {
101
+ const GlobalActionProvider = (0, _react2().useCallback)(props => {
98
102
  if (hasGlobalActions) {
99
- return _client().ActionBarProvider;
103
+ return _react2().default.createElement(_client().TabsContextProvider, null, _react2().default.createElement(_client().ActionBarProvider, {
104
+ container: (typeof props.active !== 'undefined' ? props.active : true) && onlyInPage ? document.getElementById('nb-position-container') : null,
105
+ forceProps: {
106
+ layout: 'one-column',
107
+ className: globalActionCSS
108
+ }
109
+ }, props.children));
100
110
  }
101
- return props => _react2().default.createElement(_react2().default.Fragment, null, props.children);
102
- }, [hasGlobalActions]);
103
- return _react2().default.createElement(GlobalActionProvider, {
104
- container: hasGlobalActions && onlyInPage ? document.getElementById('nb-position-container') : null,
105
- forceProps: {
106
- layout: 'one-column',
107
- className: globalActionCSS
108
- }
109
- }, _react2().default.createElement(_client().SortableItem, {
111
+ return _react2().default.createElement(_react2().default.Fragment, null, props.children);
112
+ }, [hasGlobalActions, onlyInPage]);
113
+ return _react2().default.createElement(_client().SortableItem, {
110
114
  eid: "nb-mobile-scroll-wrapper",
111
115
  className: (0, _css().cx)('nb-mobile-page', (0, _css().css)`
112
- background: #f0f2f5;
113
- display: flex;
114
- flex-direction: column;
115
- width: 100%;
116
- height: 100%;
117
- overflow-x: hidden;
118
- overflow-y: auto;
119
- padding-bottom: var(--nb-spacing);
120
- `)
116
+ background: #f0f2f5;
117
+ display: flex;
118
+ flex-direction: column;
119
+ width: 100%;
120
+ height: 100%;
121
+ overflow-x: hidden;
122
+ overflow-y: auto;
123
+ padding-bottom: var(--nb-spacing);
124
+ `)
121
125
  }, _react2().default.createElement(Designer, _objectSpread({}, fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema['x-designer-props'])), _react2().default.createElement("div", {
122
126
  style: {
123
127
  paddingBottom: tabsSchema ? null : 'var(--nb-spacing)'
124
128
  },
125
129
  className: (0, _css().cx)('nb-mobile-page-header', (0, _css().css)`
126
- & > .ant-tabs > .ant-tabs-nav {
127
- background: #fff;
128
- padding: 0 var(--nb-spacing);
130
+ & > .ant-tabs > .ant-tabs-nav {
131
+ .ant-tabs-tab {
132
+ margin: 0 !important;
133
+ padding: 0 16px !important;
129
134
  }
130
- display: flex;
131
- flex-direction: column;
132
- `)
135
+ background: #fff;
136
+ }
137
+ display: flex;
138
+ flex-direction: column;
139
+ `)
133
140
  }, _react2().default.createElement(_react().RecursionField, {
134
141
  schema: fieldSchema,
135
142
  filterProperties: s => {
136
143
  return 'MHeader' === s['x-component'];
137
144
  }
138
145
  }), _react2().default.createElement(_client().TabsContextProvider, {
139
- deep: false,
146
+ PaneRoot: GlobalActionProvider,
140
147
  activeKey: searchParams.get('tab'),
141
148
  onChange: onTabsChange
142
149
  }, _react2().default.createElement(_react().RecursionField, {
@@ -144,7 +151,7 @@ const InternalPage = props => {
144
151
  filterProperties: s => {
145
152
  return 'Tabs' === s['x-component'];
146
153
  }
147
- }))), !tabsSchema && _react2().default.createElement(_react().RecursionField, {
154
+ }))), _react2().default.createElement(GlobalActionProvider, null, !tabsSchema && _react2().default.createElement(_react().RecursionField, {
148
155
  schema: fieldSchema,
149
156
  filterProperties: s => {
150
157
  return s['x-component'] !== 'MHeader';
@@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.MSettings = exports.InternalSettings = void 0;
7
- function _react() {
8
- const data = _interopRequireDefault(require("react"));
9
- _react = function _react() {
7
+ function _css() {
8
+ const data = require("@emotion/css");
9
+ _css = function _css() {
10
10
  return data;
11
11
  };
12
12
  return data;
@@ -18,14 +18,14 @@ function _client() {
18
18
  };
19
19
  return data;
20
20
  }
21
- var _Settings = require("./Settings.Designer");
22
- function _css() {
23
- const data = require("@emotion/css");
24
- _css = function _css() {
21
+ function _react() {
22
+ const data = _interopRequireDefault(require("react"));
23
+ _react = function _react() {
25
24
  return data;
26
25
  };
27
26
  return data;
28
27
  }
28
+ var _Settings = require("./Settings.Designer");
29
29
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
30
30
  const InternalSettings = () => {
31
31
  const Designer = (0, _client().useDesigner)();
@@ -1,4 +1,4 @@
1
1
  export declare const NAMESPACE = "mobile-client";
2
2
  export declare function lang(key: string): string;
3
3
  export declare function generateNTemplate(key: string): string;
4
- export declare function useTranslation(): import("react-i18next").UseTranslationResponse<("mobile-client" | "client")[], undefined>;
4
+ export declare function useTranslation(): import("react-i18next").UseTranslationResponse<("client" | "mobile-client")[], undefined>;
@@ -4,36 +4,36 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- function _react() {
8
- const data = _interopRequireWildcard(require("react"));
9
- _react = function _react() {
7
+ function _css() {
8
+ const data = require("@emotion/css");
9
+ _css = function _css() {
10
10
  return data;
11
11
  };
12
12
  return data;
13
13
  }
14
- function _reactRouterDom() {
15
- const data = require("react-router-dom");
16
- _reactRouterDom = function _reactRouterDom() {
14
+ function _client() {
15
+ const data = require("@nocobase/client");
16
+ _client = function _client() {
17
17
  return data;
18
18
  };
19
19
  return data;
20
20
  }
21
- function _client() {
22
- const data = require("@nocobase/client");
23
- _client = function _client() {
21
+ function _react() {
22
+ const data = _interopRequireWildcard(require("react"));
23
+ _react = function _react() {
24
24
  return data;
25
25
  };
26
26
  return data;
27
27
  }
28
- function _css() {
29
- const data = require("@emotion/css");
30
- _css = function _css() {
28
+ function _reactRouterDom() {
29
+ const data = require("react-router-dom");
30
+ _reactRouterDom = function _reactRouterDom() {
31
31
  return data;
32
32
  };
33
33
  return data;
34
34
  }
35
- var _InterfaceProvider = require("./InterfaceProvider");
36
35
  var _core = require("../core");
36
+ var _InterfaceProvider = require("./InterfaceProvider");
37
37
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
38
38
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
39
39
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
@@ -98,8 +98,14 @@ const modalProps = _objectSpread(_objectSpread({}, drawerProps), {}, {
98
98
  position: absolute;
99
99
  `
100
100
  });
101
+ const useMobileSchemaUid = () => {
102
+ var _ctx$data, _ctx$data$data, _ctx$data$data$option;
103
+ const ctx = (0, _client().useSystemSettings)();
104
+ return ctx === null || ctx === void 0 ? void 0 : (_ctx$data = ctx.data) === null || _ctx$data === void 0 ? void 0 : (_ctx$data$data = _ctx$data.data) === null || _ctx$data$data === void 0 ? void 0 : (_ctx$data$data$option = _ctx$data$data.options) === null || _ctx$data$data$option === void 0 ? void 0 : _ctx$data$data$option.mobileSchemaUid;
105
+ };
101
106
  const MApplication = props => {
102
- const route = (0, _client().useRoute)();
107
+ const mobileSchemaUid = useMobileSchemaUid();
108
+ console.log('mobileSchemaUid', mobileSchemaUid);
103
109
  const params = (0, _reactRouterDom().useParams)();
104
110
  const interfaceContext = (0, _InterfaceProvider.useInterfaceContext)();
105
111
  const Provider = (0, _react().useMemo)(() => {
@@ -119,8 +125,8 @@ const MApplication = props => {
119
125
  overflow: hidden;
120
126
  `)
121
127
  }, params.name && !params.name.startsWith('tab_') ? _react().default.createElement(_reactRouterDom().Outlet, null) : _react().default.createElement(_client().RemoteSchemaComponent, {
122
- key: route.uiSchemaUid,
123
- uid: route.uiSchemaUid
128
+ key: mobileSchemaUid,
129
+ uid: mobileSchemaUid
124
130
  }, props.children), _react().default.createElement("div", {
125
131
  id: "nb-position-container"
126
132
  })))));
@@ -43,7 +43,7 @@ const RouterSwitchProvider = props => {
43
43
  const location = (0, _reactRouterDom().useLocation)();
44
44
  const navigate = (0, _reactRouterDom().useNavigate)();
45
45
  (0, _react().useEffect)(() => {
46
- if (_bridge.isJSBridge) {
46
+ if ((0, _bridge.isJSBridge)()) {
47
47
  if (location.pathname.includes('/admin')) {
48
48
  navigate('/mobile');
49
49
  }
@@ -0,0 +1,4 @@
1
+ import { Migration } from '@nocobase/server';
2
+ export default class extends Migration {
3
+ up(): Promise<void>;
4
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ function _server() {
8
+ const data = require("@nocobase/server");
9
+ _server = function _server() {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
14
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
15
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
16
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
17
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
18
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
19
+ class _default extends _server().Migration {
20
+ up() {
21
+ var _this = this;
22
+ return _asyncToGenerator(function* () {
23
+ var _instance$get;
24
+ const systemSettings = _this.db.getRepository('systemSettings');
25
+ let instance = yield systemSettings.findOne();
26
+ const uiRoutes = _this.db.getRepository('uiRoutes');
27
+ const routes = yield uiRoutes.find();
28
+ var _iterator = _createForOfIteratorHelper(routes),
29
+ _step;
30
+ try {
31
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
32
+ var _route$options;
33
+ const route = _step.value;
34
+ if (route.uiSchemaUid && (route === null || route === void 0 ? void 0 : (_route$options = route.options) === null || _route$options === void 0 ? void 0 : _route$options.component) === 'MApplication') {
35
+ const options = instance.options || {};
36
+ options['mobileSchemaUid'] = route.uiSchemaUid;
37
+ instance.set('options', options);
38
+ instance.changed('options', true);
39
+ yield instance.save();
40
+ return;
41
+ }
42
+ }
43
+ } catch (err) {
44
+ _iterator.e(err);
45
+ } finally {
46
+ _iterator.f();
47
+ }
48
+ instance = yield systemSettings.findOne();
49
+ if (!((_instance$get = instance.get('options')) === null || _instance$get === void 0 ? void 0 : _instance$get.mobileSchemaUid)) {
50
+ throw new Error('mobileSchemaUid invalid');
51
+ }
52
+ _this.app.log.info('systemSettings.options', instance.toJSON());
53
+ })();
54
+ }
55
+ }
56
+ exports.default = _default;
@@ -11,6 +11,13 @@ function _server() {
11
11
  };
12
12
  return data;
13
13
  }
14
+ function _path() {
15
+ const data = require("path");
16
+ _path = function _path() {
17
+ return data;
18
+ };
19
+ return data;
20
+ }
14
21
  var _routes = require("./routes");
15
22
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
16
23
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -20,12 +27,21 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar
20
27
  class MobileClientPlugin extends _server().Plugin {
21
28
  afterAdd() {}
22
29
  load() {
23
- return _asyncToGenerator(function* () {})();
30
+ var _this = this;
31
+ return _asyncToGenerator(function* () {
32
+ _this.db.addMigrations({
33
+ namespace: 'client',
34
+ directory: (0, _path().resolve)(__dirname, './migrations'),
35
+ context: {
36
+ plugin: _this
37
+ }
38
+ });
39
+ })();
24
40
  }
25
41
  install() {
26
- var _this = this;
42
+ var _this2 = this;
27
43
  return _asyncToGenerator(function* () {
28
- const repository = _this.app.db.getRepository('uiRoutes');
44
+ const repository = _this2.app.db.getRepository('uiRoutes');
29
45
  var _iterator = _createForOfIteratorHelper(_routes.routes),
30
46
  _step;
31
47
  try {
@@ -40,6 +56,35 @@ class MobileClientPlugin extends _server().Plugin {
40
56
  } finally {
41
57
  _iterator.f();
42
58
  }
59
+ const uiSchemas = _this2.db.getRepository('uiSchemas');
60
+ const systemSettings = _this2.db.getRepository('systemSettings');
61
+ const schema = yield uiSchemas.insert({
62
+ type: 'void',
63
+ 'x-component': 'MContainer',
64
+ 'x-designer': 'MContainer.Designer',
65
+ 'x-component-props': {},
66
+ properties: {
67
+ page: {
68
+ type: 'void',
69
+ 'x-component': 'MPage',
70
+ 'x-designer': 'MPage.Designer',
71
+ 'x-component-props': {},
72
+ properties: {
73
+ grid: {
74
+ type: 'void',
75
+ 'x-component': 'Grid',
76
+ 'x-initializer': 'MBlockInitializers',
77
+ 'x-component-props': {
78
+ showDivider: false
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ });
85
+ const instance = yield systemSettings.findOne();
86
+ instance.set('options.mobileSchemaUid', schema['x-uid']);
87
+ yield instance.save();
43
88
  })();
44
89
  }
45
90
  afterEnable() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/plugin-mobile-client",
3
- "version": "0.10.0-alpha.2",
3
+ "version": "0.10.0-alpha.4",
4
4
  "main": "lib/server/index.js",
5
5
  "displayName": "Mobile-client",
6
6
  "displayName.zh-CN": "移动端",
@@ -8,11 +8,11 @@
8
8
  "description.zh-CN": "提供移动端访问",
9
9
  "devDependencies": {
10
10
  "@emotion/css": "^11.7.1",
11
- "@formily/antd": "2.2.24",
12
- "@formily/react": "2.2.24",
13
- "@formily/shared": "2.2.24",
14
- "@nocobase/server": "0.10.0-alpha.2",
15
- "@nocobase/test": "0.10.0-alpha.2",
11
+ "@formily/antd": "2.2.26",
12
+ "@formily/react": "2.2.26",
13
+ "@formily/shared": "2.2.26",
14
+ "@nocobase/server": "0.10.0-alpha.4",
15
+ "@nocobase/test": "0.10.0-alpha.4",
16
16
  "@types/react": "^17.0.0",
17
17
  "@types/react-dom": "^17.0.0",
18
18
  "antd": "^4.24.8",
@@ -24,5 +24,5 @@
24
24
  "dependencies": {
25
25
  "antd-mobile": "^5.29.1"
26
26
  },
27
- "gitHead": "85028ae1733fcbd46ecd5d291dacbdc175f7f073"
27
+ "gitHead": "62dacadb2a83d30cb36dda9074f2f3a072a37484"
28
28
  }
@@ -3,12 +3,13 @@ interface InvokeFunction {
3
3
  (params: { action: 'moveTaskToBack' }, cb?: () => void): void;
4
4
  }
5
5
 
6
- const JsBridge = (window as any).JsBridge as {
7
- invoke: InvokeFunction;
8
- };
6
+ const getJsBridge = () =>
7
+ (window as any).JsBridge as {
8
+ invoke: InvokeFunction;
9
+ };
9
10
 
10
11
  export const invoke: InvokeFunction = (params, cb) => {
11
- JsBridge.invoke(params, cb);
12
+ return getJsBridge().invoke(params, cb);
12
13
  };
13
14
 
14
- export const isJSBridge = !!JsBridge;
15
+ export const isJSBridge = () => !!getJsBridge();
@@ -1,13 +1,13 @@
1
- import { SchemaSettings, useDesignable } from '@nocobase/client';
2
- import React from 'react';
3
- import { generateNTemplate, useTranslation } from '../../../../locale';
1
+ import { MenuOutlined } from '@ant-design/icons';
4
2
  import { Schema, useField, useFieldSchema } from '@formily/react';
5
3
  import { uid } from '@formily/shared';
6
- import { useNavigate } from 'react-router-dom';
7
- import { findSchema } from '../../helpers';
4
+ import { SchemaSettings, useDesignable } from '@nocobase/client';
8
5
  import { Button } from 'antd';
9
- import { MenuOutlined } from '@ant-design/icons';
6
+ import React from 'react';
7
+ import { useNavigate } from 'react-router-dom';
8
+ import { generateNTemplate, useTranslation } from '../../../../locale';
10
9
  import { PageSchema } from '../../common';
10
+ import { findSchema } from '../../helpers';
11
11
 
12
12
  export const ContainerDesigner = () => {
13
13
  const { t } = useTranslation();
@@ -32,6 +32,7 @@ export const ContainerDesigner = () => {
32
32
  style={{
33
33
  borderColor: 'rgb(241, 139, 98)',
34
34
  color: 'rgb(241, 139, 98)',
35
+ width: '100%',
35
36
  }}
36
37
  icon={<MenuOutlined />}
37
38
  type="dashed"
@@ -6,6 +6,7 @@ import React from 'react';
6
6
  import { useLocation, useNavigate, useParams } from 'react-router-dom';
7
7
  import { useTranslation } from '../../../../locale';
8
8
  import { useSchemaPatch } from '../../hooks';
9
+ import { menuItemSchema } from './schema';
9
10
 
10
11
  interface MMenuItemProps extends ListItemProps {
11
12
  name: string;
@@ -56,24 +57,7 @@ const MenuItemDesigner: React.FC = () => {
56
57
  <SchemaSettings.ModalItem
57
58
  title={t('Edit menu info')}
58
59
  initialValues={field.componentProps}
59
- schema={{
60
- properties: {
61
- name: {
62
- type: 'string',
63
- title: t('Menu name'),
64
- required: true,
65
- 'x-component': 'Input',
66
- 'x-decorator': 'FormItem',
67
- },
68
- icon: {
69
- required: true,
70
- 'x-decorator': 'FormItem',
71
- 'x-component': 'IconPicker',
72
- title: t('Icon'),
73
- 'x-component-props': {},
74
- },
75
- },
76
- }}
60
+ schema={menuItemSchema}
77
61
  onSubmit={onUpdateComponentProps}
78
62
  />
79
63
  <SchemaSettings.Remove
@@ -1,8 +1,10 @@
1
+ import { generateNTemplate } from '../../../../locale';
2
+
1
3
  export const menuItemSchema = {
2
4
  properties: {
3
5
  name: {
4
6
  type: 'string',
5
- title: `{{t('Menu name')}}`,
7
+ title: generateNTemplate('Menu name'),
6
8
  required: true,
7
9
  'x-component': 'Input',
8
10
  'x-decorator': 'FormItem',
@@ -10,7 +12,7 @@ export const menuItemSchema = {
10
12
  icon: {
11
13
  'x-decorator': 'FormItem',
12
14
  'x-component': 'IconPicker',
13
- title: `{{t('Icon')}}`,
15
+ title: generateNTemplate('Icon'),
14
16
  'x-component-props': {},
15
17
  },
16
18
  },
@@ -1,11 +1,11 @@
1
- import { GeneralSchemaDesigner, SchemaSettings, useDesignable } from '@nocobase/client';
2
- import React from 'react';
3
- import { generateNTemplate, useTranslation } from '../../../../locale';
1
+ import { MenuOutlined } from '@ant-design/icons';
4
2
  import { useField, useFieldSchema } from '@formily/react';
5
- import { findGridSchema } from '../../helpers';
6
3
  import { uid } from '@formily/shared';
4
+ import { SchemaSettings, useDesignable } from '@nocobase/client';
7
5
  import { Button } from 'antd';
8
- import { MenuOutlined } from '@ant-design/icons';
6
+ import React from 'react';
7
+ import { generateNTemplate, useTranslation } from '../../../../locale';
8
+ import { findGridSchema } from '../../helpers';
9
9
 
10
10
  export const PageDesigner = (props) => {
11
11
  const { showBack } = props;
@@ -28,6 +28,7 @@ export const PageDesigner = (props) => {
28
28
  style={{
29
29
  borderColor: 'rgb(241, 139, 98)',
30
30
  color: 'rgb(241, 139, 98)',
31
+ width: '100%',
31
32
  }}
32
33
  icon={<MenuOutlined />}
33
34
  type="dashed"
@@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
2
2
  import { RecursionField, useFieldSchema } from '@formily/react';
3
3
  import { ActionBarProvider, SortableItem, TabsContextProvider, useDesigner } from '@nocobase/client';
4
4
  import { TabsProps } from 'antd';
5
- import React, { useCallback, useMemo } from 'react';
5
+ import React, { useCallback } from 'react';
6
6
  import { useSearchParams } from 'react-router-dom';
7
7
  import { countGridCol } from '../../helpers';
8
8
  import { PageDesigner } from './Page.Designer';
@@ -28,90 +28,113 @@ const InternalPage: React.FC = (props) => {
28
28
  // Only support globalActions in page
29
29
  const onlyInPage = fieldSchema.root === fieldSchema.parent;
30
30
  let hasGlobalActions = false;
31
- if (!tabsSchema) {
31
+ if (!tabsSchema && fieldSchema.properties) {
32
32
  hasGlobalActions = countGridCol(fieldSchema.properties['grid'], 2) === 1;
33
- } else if (searchParams.has('tab') && tabsSchema.properties?.[searchParams.get('tab')]) {
33
+ } else if (searchParams.has('tab') && tabsSchema?.properties?.[searchParams.get('tab')]) {
34
34
  hasGlobalActions = countGridCol(tabsSchema.properties[searchParams.get('tab')]?.properties?.['grid'], 2) === 1;
35
- } else if (tabsSchema.properties) {
35
+ } else if (tabsSchema?.properties) {
36
36
  const schema = Object.values(tabsSchema.properties).sort((t1, t2) => t1['x-index'] - t2['x-index'])[0];
37
37
  if (schema) {
38
38
  setTimeout(() => {
39
- setSearchParams([['tab', schema.name.toString()]]);
39
+ setSearchParams([['tab', schema.name.toString()]], {
40
+ replace: true,
41
+ });
40
42
  });
41
43
  }
42
44
  }
43
45
 
44
46
  const onTabsChange = useCallback<TabsProps['onChange']>(
45
47
  (key) => {
46
- setSearchParams([['tab', key]]);
48
+ setSearchParams([['tab', key]], {
49
+ replace: true,
50
+ });
47
51
  },
48
52
  [setSearchParams],
49
53
  );
50
54
 
51
- const GlobalActionProvider = useMemo(() => {
52
- if (hasGlobalActions) {
53
- return ActionBarProvider;
54
- }
55
- return (props) => <>{props.children}</>;
56
- }, [hasGlobalActions]);
55
+ const GlobalActionProvider = useCallback(
56
+ (props) => {
57
+ if (hasGlobalActions) {
58
+ return (
59
+ <TabsContextProvider>
60
+ <ActionBarProvider
61
+ container={
62
+ (typeof props.active !== 'undefined' ? props.active : true) && onlyInPage
63
+ ? document.getElementById('nb-position-container')
64
+ : null
65
+ }
66
+ forceProps={{
67
+ layout: 'one-column',
68
+ className: globalActionCSS,
69
+ }}
70
+ >
71
+ {props.children}
72
+ </ActionBarProvider>
73
+ </TabsContextProvider>
74
+ );
75
+ }
76
+ return <>{props.children}</>;
77
+ },
78
+ [hasGlobalActions, onlyInPage],
79
+ );
57
80
 
58
81
  return (
59
- <GlobalActionProvider
60
- container={hasGlobalActions && onlyInPage ? document.getElementById('nb-position-container') : null}
61
- forceProps={{
62
- layout: 'one-column',
63
- className: globalActionCSS,
64
- }}
82
+ <SortableItem
83
+ eid="nb-mobile-scroll-wrapper"
84
+ className={cx(
85
+ 'nb-mobile-page',
86
+ css`
87
+ background: #f0f2f5;
88
+ display: flex;
89
+ flex-direction: column;
90
+ width: 100%;
91
+ height: 100%;
92
+ overflow-x: hidden;
93
+ overflow-y: auto;
94
+ padding-bottom: var(--nb-spacing);
95
+ `,
96
+ )}
65
97
  >
66
- <SortableItem
67
- eid="nb-mobile-scroll-wrapper"
98
+ <Designer {...fieldSchema?.['x-designer-props']}></Designer>
99
+ <div
100
+ style={{
101
+ paddingBottom: tabsSchema ? null : 'var(--nb-spacing)',
102
+ }}
68
103
  className={cx(
69
- 'nb-mobile-page',
104
+ 'nb-mobile-page-header',
70
105
  css`
71
- background: #f0f2f5;
106
+ & > .ant-tabs > .ant-tabs-nav {
107
+ .ant-tabs-tab {
108
+ margin: 0 !important;
109
+ padding: 0 16px !important;
110
+ }
111
+ background: #fff;
112
+ }
72
113
  display: flex;
73
114
  flex-direction: column;
74
- width: 100%;
75
- height: 100%;
76
- overflow-x: hidden;
77
- overflow-y: auto;
78
- padding-bottom: var(--nb-spacing);
79
115
  `,
80
116
  )}
81
117
  >
82
- <Designer {...fieldSchema?.['x-designer-props']}></Designer>
83
- <div
84
- style={{
85
- paddingBottom: tabsSchema ? null : 'var(--nb-spacing)',
118
+ <RecursionField
119
+ schema={fieldSchema}
120
+ filterProperties={(s) => {
121
+ return 'MHeader' === s['x-component'];
86
122
  }}
87
- className={cx(
88
- 'nb-mobile-page-header',
89
- css`
90
- & > .ant-tabs > .ant-tabs-nav {
91
- background: #fff;
92
- padding: 0 var(--nb-spacing);
93
- }
94
- display: flex;
95
- flex-direction: column;
96
- `,
97
- )}
123
+ ></RecursionField>
124
+ <TabsContextProvider
125
+ PaneRoot={GlobalActionProvider}
126
+ activeKey={searchParams.get('tab')}
127
+ onChange={onTabsChange}
98
128
  >
99
129
  <RecursionField
100
130
  schema={fieldSchema}
101
131
  filterProperties={(s) => {
102
- return 'MHeader' === s['x-component'];
132
+ return 'Tabs' === s['x-component'];
103
133
  }}
104
134
  ></RecursionField>
105
- <TabsContextProvider deep={false} activeKey={searchParams.get('tab')} onChange={onTabsChange}>
106
- <RecursionField
107
- schema={fieldSchema}
108
- filterProperties={(s) => {
109
- return 'Tabs' === s['x-component'];
110
- }}
111
- ></RecursionField>
112
- </TabsContextProvider>
113
- </div>
114
-
135
+ </TabsContextProvider>
136
+ </div>
137
+ <GlobalActionProvider>
115
138
  {!tabsSchema && (
116
139
  <RecursionField
117
140
  schema={fieldSchema}
@@ -120,8 +143,8 @@ const InternalPage: React.FC = (props) => {
120
143
  }}
121
144
  ></RecursionField>
122
145
  )}
123
- </SortableItem>
124
- </GlobalActionProvider>
146
+ </GlobalActionProvider>
147
+ </SortableItem>
125
148
  );
126
149
  };
127
150
 
@@ -1,7 +1,7 @@
1
- import React from 'react';
1
+ import { css, cx } from '@emotion/css';
2
2
  import { SettingsMenu, SortableItem, useDesigner } from '@nocobase/client';
3
+ import React from 'react';
3
4
  import { SettingsDesigner } from './Settings.Designer';
4
- import { css, cx } from '@emotion/css';
5
5
  export const InternalSettings = () => {
6
6
  const Designer = useDesigner();
7
7
  return (
@@ -1,10 +1,16 @@
1
- import React, { useMemo } from 'react';
2
- import { Outlet, useParams } from 'react-router-dom';
3
- import { ActionContextProvider, AdminProvider, RemoteSchemaComponent, useRoute, useViewport } from '@nocobase/client';
4
1
  import { css, cx } from '@emotion/css';
5
- import { useInterfaceContext } from './InterfaceProvider';
2
+ import {
3
+ ActionContextProvider,
4
+ AdminProvider,
5
+ RemoteSchemaComponent,
6
+ useSystemSettings,
7
+ useViewport,
8
+ } from '@nocobase/client';
6
9
  import { DrawerProps, ModalProps } from 'antd';
10
+ import React, { useMemo } from 'react';
11
+ import { Outlet, useParams } from 'react-router-dom';
7
12
  import { MobileCore } from '../core';
13
+ import { useInterfaceContext } from './InterfaceProvider';
8
14
 
9
15
  const commonCSSVariables = css`
10
16
  --nb-spacing: 14px;
@@ -66,8 +72,14 @@ const modalProps = {
66
72
  `,
67
73
  };
68
74
 
75
+ const useMobileSchemaUid = () => {
76
+ const ctx = useSystemSettings();
77
+ return ctx?.data?.data?.options?.mobileSchemaUid;
78
+ };
79
+
69
80
  const MApplication: React.FC = (props) => {
70
- const route = useRoute();
81
+ const mobileSchemaUid = useMobileSchemaUid();
82
+ console.log('mobileSchemaUid', mobileSchemaUid);
71
83
  const params = useParams<{ name: string }>();
72
84
  const interfaceContext = useInterfaceContext();
73
85
  const Provider = useMemo(() => {
@@ -99,10 +111,11 @@ const MApplication: React.FC = (props) => {
99
111
  {params.name && !params.name.startsWith('tab_') ? (
100
112
  <Outlet />
101
113
  ) : (
102
- <RemoteSchemaComponent key={route.uiSchemaUid} uid={route.uiSchemaUid}>
114
+ <RemoteSchemaComponent key={mobileSchemaUid} uid={mobileSchemaUid}>
103
115
  {props.children}
104
116
  </RemoteSchemaComponent>
105
117
  )}
118
+ {/* Global action will insert here */}
106
119
  <div id="nb-position-container"></div>
107
120
  </div>
108
121
  </ActionContextProvider>
@@ -10,7 +10,7 @@ export const RouterSwitchProvider = (props) => {
10
10
  const location = useLocation();
11
11
  const navigate = useNavigate();
12
12
  useEffect(() => {
13
- if (isJSBridge) {
13
+ if (isJSBridge()) {
14
14
  if (location.pathname.includes('/admin')) {
15
15
  navigate('/mobile');
16
16
  }
@@ -0,0 +1,26 @@
1
+ import { Model } from '@nocobase/database';
2
+ import { Migration } from '@nocobase/server';
3
+
4
+ export default class extends Migration {
5
+ async up() {
6
+ const systemSettings = this.db.getRepository('systemSettings');
7
+ let instance: Model = await systemSettings.findOne();
8
+ const uiRoutes = this.db.getRepository('uiRoutes');
9
+ const routes = await uiRoutes.find();
10
+ for (const route of routes) {
11
+ if (route.uiSchemaUid && route?.options?.component === 'MApplication') {
12
+ const options = instance.options || {};
13
+ options['mobileSchemaUid'] = route.uiSchemaUid;
14
+ instance.set('options', options);
15
+ instance.changed('options', true);
16
+ await instance.save();
17
+ return;
18
+ }
19
+ }
20
+ instance = await systemSettings.findOne();
21
+ if (!instance.get('options')?.mobileSchemaUid) {
22
+ throw new Error('mobileSchemaUid invalid');
23
+ }
24
+ this.app.log.info('systemSettings.options', instance.toJSON());
25
+ }
26
+ }
@@ -1,10 +1,19 @@
1
- import { InstallOptions, Plugin } from '@nocobase/server';
1
+ import { Plugin } from '@nocobase/server';
2
+ import { resolve } from 'path';
2
3
  import { routes } from './routes';
3
4
 
4
5
  export class MobileClientPlugin extends Plugin {
5
6
  afterAdd() {}
6
7
 
7
- async load() {}
8
+ async load() {
9
+ this.db.addMigrations({
10
+ namespace: 'client',
11
+ directory: resolve(__dirname, './migrations'),
12
+ context: {
13
+ plugin: this,
14
+ },
15
+ });
16
+ }
8
17
 
9
18
  async install() {
10
19
  const repository = this.app.db.getRepository('uiRoutes');
@@ -13,6 +22,35 @@ export class MobileClientPlugin extends Plugin {
13
22
  values,
14
23
  });
15
24
  }
25
+ const uiSchemas = this.db.getRepository<any>('uiSchemas');
26
+ const systemSettings = this.db.getRepository('systemSettings');
27
+ const schema = await uiSchemas.insert({
28
+ type: 'void',
29
+ 'x-component': 'MContainer',
30
+ 'x-designer': 'MContainer.Designer',
31
+ 'x-component-props': {},
32
+ properties: {
33
+ page: {
34
+ type: 'void',
35
+ 'x-component': 'MPage',
36
+ 'x-designer': 'MPage.Designer',
37
+ 'x-component-props': {},
38
+ properties: {
39
+ grid: {
40
+ type: 'void',
41
+ 'x-component': 'Grid',
42
+ 'x-initializer': 'MBlockInitializers',
43
+ 'x-component-props': {
44
+ showDivider: false,
45
+ },
46
+ },
47
+ },
48
+ },
49
+ },
50
+ });
51
+ const instance = await systemSettings.findOne();
52
+ instance.set('options.mobileSchemaUid', schema['x-uid']);
53
+ await instance.save();
16
54
  }
17
55
 
18
56
  async afterEnable() {}