@abtnode/ux 1.16.28-next-5a717317 → 1.16.28

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 (59) hide show
  1. package/lib/actions.js +8 -6
  2. package/lib/analytics/traffic.js +4 -10
  3. package/lib/blocklet/authentication/federated/federated-detail-dialog.js +2 -2
  4. package/lib/blocklet/blocklet-source.js +2 -2
  5. package/lib/blocklet/component/add-component/add-component-core.js +3 -2
  6. package/lib/blocklet/component/component-cell-mount-poin.js +164 -0
  7. package/lib/blocklet/component/component-cell.js +83 -84
  8. package/lib/blocklet/component/configuration.js +52 -36
  9. package/lib/blocklet/component/did-space/connect-to.js +4 -4
  10. package/lib/blocklet/component/index.js +29 -38
  11. package/lib/blocklet/component/navigation/navigation-dialog.js +2 -3
  12. package/lib/blocklet/component/space-connector.js +3 -3
  13. package/lib/blocklet/component/space-selector.js +2 -2
  14. package/lib/blocklet/component/store-blocklet-list.js +3 -3
  15. package/lib/blocklet/logo-uploader.js +2 -2
  16. package/lib/blocklet/notification/push-kit.js +1 -1
  17. package/lib/blocklet/preferences/index.js +3 -3
  18. package/lib/blocklet/publish/create-release/header.js +36 -31
  19. package/lib/blocklet/publish/create-release/index.js +54 -21
  20. package/lib/blocklet/publish/create-release/keep-now-resources.js +15 -0
  21. package/lib/blocklet/publish/create-release/release-stepper.js +4 -4
  22. package/lib/blocklet/publish/create-release/{resources.js → resource-select.js} +8 -7
  23. package/lib/blocklet/publish/create-release/resource-upload.js +105 -0
  24. package/lib/blocklet/publish/project-list.js +6 -0
  25. package/lib/blocklet/publish/release-list.js +4 -4
  26. package/lib/blocklet/publish/utils/validate-params.js +4 -4
  27. package/lib/blocklet/purchase/component-purchase.js +2 -2
  28. package/lib/blocklet/router/action/add-rule.js +31 -18
  29. package/lib/blocklet/router/rule-actions.js +8 -1
  30. package/lib/blocklet/storage/connect-to.js +4 -4
  31. package/lib/blocklet/storage/item.js +3 -3
  32. package/lib/blocklet/util.js +4 -4
  33. package/lib/hooks/url-evaluation.js +2 -2
  34. package/lib/hooks/use-app-logo.js +4 -4
  35. package/lib/hooks/use-bundle-logo.js +4 -4
  36. package/lib/invitation/invitation-receive.js +1 -1
  37. package/lib/locales/ar.js +12 -5
  38. package/lib/locales/de.js +11 -4
  39. package/lib/locales/en.js +11 -4
  40. package/lib/locales/es.js +11 -4
  41. package/lib/locales/fr.js +11 -4
  42. package/lib/locales/hi.js +11 -4
  43. package/lib/locales/i18n.db +0 -0
  44. package/lib/locales/id.js +11 -4
  45. package/lib/locales/ja.js +11 -4
  46. package/lib/locales/ko.js +11 -4
  47. package/lib/locales/pt.js +11 -4
  48. package/lib/locales/ru.js +11 -4
  49. package/lib/locales/th.js +11 -4
  50. package/lib/locales/vi.js +11 -4
  51. package/lib/locales/zh-tw.js +12 -5
  52. package/lib/locales/zh.js +12 -5
  53. package/lib/store/connect-actions.js +2 -2
  54. package/lib/store/item.js +2 -2
  55. package/lib/team/members/util.js +3 -3
  56. package/lib/util/index.js +18 -18
  57. package/lib/util/join-url-keep-search.js +2 -2
  58. package/lib/util/spaces.js +4 -2
  59. package/package.json +19 -20
@@ -1,9 +1,9 @@
1
1
  import styled from '@emotion/styled';
2
2
  import classnames from 'classnames';
3
3
  import PropTypes from 'prop-types';
4
- import { useEffect, useRef } from 'react';
4
+ import React, { useEffect, useRef } from 'react';
5
5
  import useSetState from 'react-use/lib/useSetState';
6
- import joinUrl from 'url-join';
6
+ import { joinURL } from 'ufo';
7
7
  import { Box } from '@mui/material';
8
8
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
9
9
  import { hasStartEngine } from '@blocklet/meta/lib/engine';
@@ -14,6 +14,7 @@ import { useNodeContext } from '../../../contexts/node';
14
14
  import { axios } from '../../../util/api';
15
15
  import StopBox from './stop-box';
16
16
  import Tree from './tree';
17
+ import keepNowResources from './keep-now-resources';
17
18
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
18
19
  const fillParent = (nodes, parentId) => {
19
20
  nodes.forEach(node => {
@@ -31,7 +32,7 @@ const parseUrl = (component, projectId, releaseId, locale, initUrl) => {
31
32
  const {
32
33
  exportApi = '/'
33
34
  } = component?.meta.resource || {};
34
- const urlObj = new URL(joinUrl('http://127.0.0.1', component.mountPoint, exportApi || '/').replace(/\/+/g, '/'));
35
+ const urlObj = new URL(joinURL('http://127.0.0.1', component.mountPoint, exportApi || '/').replace(/\/+/g, '/'));
35
36
  urlObj.searchParams.set('projectId', projectId);
36
37
  urlObj.searchParams.set('releaseId', releaseId);
37
38
  urlObj.searchParams.set('local', locale);
@@ -89,7 +90,7 @@ const getNodeIdDependencies = (node, nodeIds) => {
89
90
  };
90
91
  return getDependencies(node, {});
91
92
  };
92
- export default function Resources({
93
+ export default function ResourceSelect({
93
94
  app,
94
95
  component,
95
96
  projectId,
@@ -178,7 +179,7 @@ export default function Resources({
178
179
  const list = res?.resources || [];
179
180
  if (list?.length) {
180
181
  setSelectedResourceIds({
181
- [child.meta.did]: list
182
+ [child.meta.did]: keepNowResources(tree, list)
182
183
  });
183
184
  setSelectedComponentsMapByIds(child.meta.did, tree, list);
184
185
  if (!readOnly) {
@@ -256,7 +257,7 @@ export default function Resources({
256
257
  })]
257
258
  });
258
259
  }
259
- Resources.propTypes = {
260
+ ResourceSelect.propTypes = {
260
261
  component: PropTypes.object.isRequired,
261
262
  app: PropTypes.object.isRequired,
262
263
  projectId: PropTypes.string.isRequired,
@@ -275,7 +276,7 @@ Resources.propTypes = {
275
276
  selectedResourceIds: PropTypes.array.isRequired,
276
277
  setSelectedResourceIds: PropTypes.func.isRequired
277
278
  };
278
- Resources.defaultProps = {
279
+ ResourceSelect.defaultProps = {
279
280
  error: '',
280
281
  release: {
281
282
  id: ''
@@ -0,0 +1,105 @@
1
+ import PropTypes from 'prop-types';
2
+ import { UNOWNED_DID, WELLKNOWN_SERVICE_PATH_PREFIX } from '@abtnode/constant';
3
+ import React, { Suspense, useRef, lazy } from 'react';
4
+ import { Stack, Box, Button, Typography } from '@mui/material';
5
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
6
+ import Toast from '@arcblock/ux/lib/Toast/index';
7
+ import EmptySpinner from '../../../empty-spinner';
8
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ const allowedFileTypes = ['.zip', '.gz'];
10
+ const maxFileSize = 1024 * 1024 * 100; // 100 MB
11
+
12
+ // eslint-disable-next-line import/no-unresolved
13
+ const UploaderComponent = /*#__PURE__*/lazy(() => import('@blocklet/uploader/react').then(res => ({
14
+ default: res.Uploader
15
+ })));
16
+ export default function ResourceUpload({
17
+ app,
18
+ projectId,
19
+ readOnly,
20
+ params,
21
+ setParams
22
+ }) {
23
+ const {
24
+ t
25
+ } = useLocaleContext();
26
+ const uploaderRef = useRef(null);
27
+ const checkCanUpload = () => {
28
+ if (readOnly) {
29
+ return false;
30
+ }
31
+ if (!projectId || projectId === UNOWNED_DID) {
32
+ Toast.error(t('blocklet.publish.errorTip.noFirstDid'));
33
+ return false;
34
+ }
35
+ return true;
36
+ };
37
+ const uploadPrefix = `${WELLKNOWN_SERVICE_PATH_PREFIX}/api/project/${app.meta.did}/${projectId}/resource/upload`;
38
+ return /*#__PURE__*/_jsxs(Box, {
39
+ sx: {
40
+ mt: 3
41
+ },
42
+ children: [/*#__PURE__*/_jsx(Typography, {
43
+ gutterBottom: true,
44
+ children: t('blocklet.publish.resourceUpload')
45
+ }), /*#__PURE__*/_jsxs(Stack, {
46
+ direction: "row",
47
+ alignItems: "center",
48
+ spacing: 1,
49
+ sx: {
50
+ flex: 1,
51
+ cursor: readOnly ? 'default' : 'pointer'
52
+ },
53
+ children: [!!params.uploadedResource && /*#__PURE__*/_jsx(Typography, {
54
+ component: "a",
55
+ href: `${uploadPrefix}/params.uploadedResource`,
56
+ children: params.uploadedResource
57
+ }), !readOnly && /*#__PURE__*/_jsx(Button, {
58
+ variant: "outlined",
59
+ size: "small",
60
+ onClick: () => {
61
+ if (!checkCanUpload()) {
62
+ return;
63
+ }
64
+ uploaderRef.current?.open();
65
+ },
66
+ children: params.uploadedResource ? t('common.change') : t('common.upload')
67
+ })]
68
+ }), /*#__PURE__*/_jsx(Suspense, {
69
+ fallback: /*#__PURE__*/_jsx(EmptySpinner, {}),
70
+ children: /*#__PURE__*/_jsx(UploaderComponent, {
71
+ ref: uploaderRef,
72
+ popup: true,
73
+ onUploadFinish: result => {
74
+ setParams({
75
+ uploadedResource: result.data.filename
76
+ });
77
+ uploaderRef.current?.close();
78
+ },
79
+ plugins: ['ImageEditor'],
80
+ installerProps: {
81
+ disabled: true
82
+ },
83
+ apiPathProps: {
84
+ uploader: uploadPrefix,
85
+ disableMediaKitPrefix: true
86
+ },
87
+ coreProps: {
88
+ restrictions: {
89
+ allowedFileTypes,
90
+ maxFileSize,
91
+ maxNumberOfFiles: 1
92
+ }
93
+ }
94
+ }, "uploader-resource")
95
+ })]
96
+ });
97
+ }
98
+ ResourceUpload.propTypes = {
99
+ app: PropTypes.object.isRequired,
100
+ projectId: PropTypes.string.isRequired,
101
+ readOnly: PropTypes.bool.isRequired,
102
+ params: PropTypes.object.isRequired,
103
+ setParams: PropTypes.func.isRequired
104
+ };
105
+ ResourceUpload.defaultProps = {};
@@ -182,6 +182,9 @@ export default function ProjectList({
182
182
  name: 'blockletDid',
183
183
  options: {
184
184
  customBodyRender: did => {
185
+ if (!did) {
186
+ return null;
187
+ }
185
188
  return /*#__PURE__*/_jsx(DidAddress, {
186
189
  size: 14,
187
190
  compact: true,
@@ -195,6 +198,9 @@ export default function ProjectList({
195
198
  name: 'createdBy',
196
199
  options: {
197
200
  customBodyRender: did => {
201
+ if (!did) {
202
+ return null;
203
+ }
198
204
  return /*#__PURE__*/_jsx(DidAddress, {
199
205
  onClick: () => {
200
206
  navigate(`/.well-known/service/admin/members?did=${did}`);
@@ -2,7 +2,7 @@
2
2
  import React, { useState, useEffect } from 'react';
3
3
  import { Link, useParams } from 'react-router-dom';
4
4
  import styled from '@emotion/styled';
5
- import joinUrl from 'url-join';
5
+ import { joinURL } from 'ufo';
6
6
  import upperFirst from 'lodash/upperFirst';
7
7
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
8
8
  import { Box, useMediaQuery, IconButton, Typography, Tooltip, Breadcrumbs } from '@mui/material';
@@ -234,12 +234,12 @@ export default function ReleaseList() {
234
234
  let downloadUrl = '';
235
235
  const published = release.status === 'published';
236
236
  if (published) {
237
- const blockletMetaUrl = joinUrl(serverEndpoint, `/api/project/${blocklet.meta.did}/${project.id}/${project.lastReleaseId}/release/blocklet.json`);
237
+ const blockletMetaUrl = joinURL(serverEndpoint, `/api/project/${blocklet.meta.did}/${project.id}/${project.lastReleaseId}/release/blocklet.json`);
238
238
  const url = new URL(serverEndpoint);
239
- url.pathname = joinUrl(url.pathname, '/launch-blocklet/agreement');
239
+ url.pathname = joinURL(url.pathname, '/launch-blocklet/agreement');
240
240
  url.searchParams.set('blocklet_meta_url', blockletMetaUrl);
241
241
  installUrl = url.href;
242
- downloadUrl = joinUrl(`${WELLKNOWN_SERVICE_PATH_PREFIX}/api/project/${blocklet.meta.did}/${project.id}/${project.lastReleaseId}/download/${(project.lastReleaseFiles || [])[0]}`);
242
+ downloadUrl = joinURL(`${WELLKNOWN_SERVICE_PATH_PREFIX}/api/project/${blocklet.meta.did}/${project.id}/${project.lastReleaseId}/download/${(project.lastReleaseFiles || [])[0]}`);
243
243
  }
244
244
  return /*#__PURE__*/_jsxs(Box, {
245
245
  display: "flex",
@@ -3,7 +3,7 @@ import { UNOWNED_DID } from '@abtnode/constant';
3
3
  import semver from 'semver';
4
4
  export const validateParams = ({
5
5
  params,
6
- isSelectedResources,
6
+ hasSelectedResources,
7
7
  projectId,
8
8
  status,
9
9
  t
@@ -21,7 +21,7 @@ export const validateParams = ({
21
21
  message: t('blocklet.publish.errorTip.noDid')
22
22
  });
23
23
  }
24
- if (!isSelectedResources) {
24
+ if (!params.uploadedResource && !hasSelectedResources) {
25
25
  errors.push({
26
26
  param: 'blockletResources',
27
27
  message: t('blocklet.publish.errorTip.noResource')
@@ -56,7 +56,7 @@ export const validateParams = ({
56
56
  };
57
57
  export const validateParamsStep = ({
58
58
  params,
59
- isSelectedResources,
59
+ hasSelectedResources,
60
60
  step,
61
61
  t,
62
62
  projectId
@@ -73,7 +73,7 @@ export const validateParamsStep = ({
73
73
  }
74
74
  }
75
75
  if (step === 2) {
76
- if (!isSelectedResources) {
76
+ if (!params.uploadedResource && !hasSelectedResources) {
77
77
  return t('blocklet.publish.errorTip.noResource');
78
78
  }
79
79
  }
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable react/jsx-one-expression-per-line */
2
2
  import { useState, useEffect, useImperativeHandle, forwardRef } from 'react';
3
- import joinUrl from 'url-join';
3
+ import { joinURL } from 'ufo';
4
4
  import { getDisplayName } from '@blocklet/meta/lib/util';
5
5
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
6
6
  import DidConnect from '@arcblock/did-connect/lib/Connect';
@@ -132,7 +132,7 @@ export function ComponentPurchase({
132
132
  purchase: {
133
133
  action: 'acquire-asset',
134
134
  checkFn: axios.create({
135
- baseURL: joinUrl(baseUrl, '/store')
135
+ baseURL: joinURL(baseUrl, '/store')
136
136
  }).get,
137
137
  extraParams: {
138
138
  factory: meta.nftFactory,
@@ -17,7 +17,10 @@ import ConfigRoutingRule from './config-routing-rule';
17
17
  import { formatMountPoint } from '../../../util';
18
18
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
19
19
  export default function AddRule({
20
- children
20
+ children,
21
+ hiddenChildren,
22
+ open,
23
+ onClose
21
24
  }) {
22
25
  const {
23
26
  t
@@ -29,12 +32,13 @@ export default function AddRule({
29
32
  blocklet
30
33
  } = useBlockletContext();
31
34
  const [loading, setLoading] = useState(false);
32
- const [confirmSetting, setConfirmSetting] = useState(null);
35
+ const [showConfirm, setShowConfirm] = useState(false);
33
36
  const teamDid = blocklet.meta.did;
34
37
  const siteId = blocklet.site.id;
35
38
  const onCancel = () => {
39
+ onClose?.();
36
40
  setLoading(false);
37
- setConfirmSetting(null);
41
+ setShowConfirm(false);
38
42
  };
39
43
  const onConfirm = async params => {
40
44
  try {
@@ -81,7 +85,7 @@ export default function AddRule({
81
85
  Toast.error(error.message);
82
86
  } finally {
83
87
  setLoading(false);
84
- setConfirmSetting(null);
88
+ setShowConfirm(false);
85
89
  }
86
90
  };
87
91
  const setting = {
@@ -185,11 +189,11 @@ export default function AddRule({
185
189
  const onMenuItemClick = e => {
186
190
  e.stopPropagation();
187
191
  // eslint-disable-next-line no-unused-expressions
188
- setConfirmSetting(setting);
192
+ setShowConfirm(true);
189
193
  };
190
- return /*#__PURE__*/_jsxs(_Fragment, {
191
- children: [typeof children === 'function' ? children({
192
- loading,
194
+ let child = null;
195
+ if (!hiddenChildren) {
196
+ child = typeof children === 'function' ? children({
193
197
  open: onMenuItemClick
194
198
  }) : /*#__PURE__*/_jsxs(MenuItem, {
195
199
  onClick: onMenuItemClick,
@@ -203,21 +207,30 @@ export default function AddRule({
203
207
  marginRight: 5
204
208
  }
205
209
  }), t('router.rule.add.title')]
206
- }), confirmSetting && /*#__PURE__*/_jsx(Confirm, {
207
- title: confirmSetting.title,
208
- description: confirmSetting.description,
209
- confirm: confirmSetting.confirm,
210
- cancel: confirmSetting.cancel,
211
- params: confirmSetting.params,
212
- onConfirm: confirmSetting.onConfirm,
213
- onCancel: confirmSetting.onCancel,
210
+ });
211
+ }
212
+ return /*#__PURE__*/_jsxs(_Fragment, {
213
+ children: [child, (open || showConfirm) && /*#__PURE__*/_jsx(Confirm, {
214
+ title: setting.title,
215
+ description: setting.description,
216
+ confirm: setting.confirm,
217
+ cancel: setting.cancel,
218
+ params: setting.params,
219
+ onConfirm: setting.onConfirm,
220
+ onCancel: setting.onCancel,
214
221
  color: "primary"
215
222
  })]
216
223
  });
217
224
  }
218
225
  AddRule.propTypes = {
219
- children: PropTypes.any
226
+ children: PropTypes.any,
227
+ onClose: PropTypes.func,
228
+ hiddenChildren: PropTypes.bool,
229
+ open: PropTypes.bool
220
230
  };
221
231
  AddRule.defaultProps = {
222
- children: null
232
+ children: null,
233
+ open: false,
234
+ onClose: null,
235
+ hiddenChildren: false
223
236
  };
@@ -23,7 +23,14 @@ export default function RuleActions(rule) {
23
23
  return /*#__PURE__*/_jsxs(Box, {
24
24
  display: "flex",
25
25
  alignItems: "center",
26
- children: [/*#__PURE__*/_jsx("a", {
26
+ children: [/*#__PURE__*/_jsx(Box, {
27
+ component: "a",
28
+ sx: {
29
+ display: {
30
+ xs: 'flex',
31
+ md: 'none'
32
+ }
33
+ },
27
34
  target: "_blank",
28
35
  href: href,
29
36
  rel: "noopener noreferrer",
@@ -3,7 +3,7 @@ import React, { useState } from 'react';
3
3
  import Button from '@arcblock/ux/lib/Button';
4
4
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
5
5
  import DidConnect from '@arcblock/did-connect/lib/Connect';
6
- import joinUrl from 'url-join';
6
+ import { joinURL } from 'ufo';
7
7
  import toast from '@arcblock/ux/lib/Toast';
8
8
  import SplitButton from '@arcblock/ux/lib/SplitButton';
9
9
  import Dialog from '@arcblock/ux/lib/Dialog';
@@ -53,7 +53,7 @@ function ConnectTo({
53
53
  action: 'connect-to-did-spaces',
54
54
  checkTimeout: 1000 * 300,
55
55
  checkFn: axios.create({
56
- baseURL: joinUrl(window.location.origin, getPathPrefix())
56
+ baseURL: joinURL(window.location.origin, getPathPrefix())
57
57
  }).get,
58
58
  messages: {
59
59
  title: t('storage.spaces.provideNFT.title', {
@@ -198,10 +198,10 @@ function ConnectTo({
198
198
  setAuthorizeConnect(preValue => ({
199
199
  ...preValue,
200
200
  open: true,
201
- prefix: joinUrl(didSpacesCoreUrl, 'space/api/did'),
201
+ prefix: joinURL(didSpacesCoreUrl, 'space/api/did'),
202
202
  baseUrl: new URL(didSpacesCoreUrl).origin,
203
203
  checkFn: axios.create({
204
- baseURL: joinUrl(didSpacesCoreUrl, 'space')
204
+ baseURL: joinURL(didSpacesCoreUrl, 'space')
205
205
  }).get,
206
206
  extraParams: {
207
207
  appDid: blockletInfo.appDid,
@@ -4,7 +4,7 @@ import Button from '@arcblock/ux/lib/Button';
4
4
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
5
5
  import PropTypes from 'prop-types';
6
6
  import Toast from '@arcblock/ux/lib/Toast';
7
- import joinUrl from 'url-join';
7
+ import { joinURL } from 'ufo';
8
8
  import { BLOCKLET_CONFIGURABLE_KEY } from '@blocklet/constant';
9
9
  import DidConnect from '@arcblock/did-connect/lib/Connect';
10
10
  import { useRequest } from 'ahooks';
@@ -176,10 +176,10 @@ function SpaceItem({
176
176
  setAuthorizeConnect(preValue => ({
177
177
  ...preValue,
178
178
  open: true,
179
- prefix: joinUrl(spaceGateway.url, 'space/api/did'),
179
+ prefix: joinURL(spaceGateway.url, 'space/api/did'),
180
180
  baseUrl: new URL(spaceGateway.url).origin,
181
181
  checkFn: axios.create({
182
- baseURL: joinUrl(spaceGateway.url, 'space')
182
+ baseURL: joinURL(spaceGateway.url, 'space')
183
183
  }).get,
184
184
  extraParams: {
185
185
  appDid,
@@ -1,5 +1,5 @@
1
1
  import sortBy from 'lodash/sortBy';
2
- import joinUrl from 'url-join';
2
+ import { joinURL } from 'ufo';
3
3
  import isEmpty from 'lodash/isEmpty';
4
4
  import normalizePathPrefix from '@abtnode/util/lib/normalize-path-prefix';
5
5
  import { forEachBlockletSync, replaceSlotToIp } from '@blocklet/meta/lib/util';
@@ -7,12 +7,12 @@ import { BLOCKLET_APP_SPACE_REQUIREMENT } from '@blocklet/constant';
7
7
  import { SLOT_FOR_IP_DNS_SITE } from '@abtnode/constant';
8
8
  export const getServerUrl = (info, encodeURI = false) => {
9
9
  const adminPath = process.env.NODE_ENV === 'production' ? info.routing.adminPath : '';
10
- return encodeURI ? encodeURIComponent(joinUrl(window.location.origin, adminPath)) : joinUrl(window.location.origin, adminPath);
10
+ return encodeURI ? encodeURIComponent(joinURL(window.location.origin, adminPath)) : joinURL(window.location.origin, adminPath);
11
11
  };
12
12
  export const getLaunchAgreementUrl = (meta, info, storeUrl) => {
13
13
  const serverUrl = getServerUrl(info);
14
- const metaUrl = joinUrl(storeUrl, `/api/blocklets/${meta.did}/blocklet.json`);
15
- const url = new URL(joinUrl(serverUrl, '/launch-blocklet/agreement'));
14
+ const metaUrl = joinURL(storeUrl, `/api/blocklets/${meta.did}/blocklet.json`);
15
+ const url = new URL(joinURL(serverUrl, '/launch-blocklet/agreement'));
16
16
  url.searchParams.set('blocklet_meta_url', metaUrl);
17
17
  url.searchParams.set('from', window.location.href);
18
18
  return url.href;
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect, useMemo, useRef, useContext } from 'react';
2
- import joinUrl from 'url-join';
2
+ import { joinURL } from 'ufo';
3
3
  import memoize from 'lodash/memoize';
4
4
  import { WELLKNOWN_PING_PREFIX } from '@abtnode/constant';
5
5
  import { evaluateURLs } from '@abtnode/util/lib/url-evaluation';
@@ -16,7 +16,7 @@ const ping = memoize(url => {
16
16
  if (hostname === window.location.hostname) {
17
17
  return true;
18
18
  }
19
- return defaultCheckAccessible(joinUrl(origin, WELLKNOWN_PING_PREFIX));
19
+ return defaultCheckAccessible(joinURL(origin, WELLKNOWN_PING_PREFIX));
20
20
  });
21
21
 
22
22
  // url <-> evaluation cache
@@ -1,4 +1,4 @@
1
- import joinUrl from 'url-join';
1
+ import { joinURL } from 'ufo';
2
2
  import { BLOCKLET_CONFIGURABLE_KEY } from '@blocklet/constant';
3
3
  import { useNodeContext } from '../contexts/node';
4
4
  import { isInstalling, getLogoHash } from '../util';
@@ -21,9 +21,9 @@ export default function useAppLogo({
21
21
  const customRectLogo = (blocklet?.environments || []).find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_RECT)?.value;
22
22
  const customFavicon = (blocklet?.environments || []).find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_FAVICON)?.value;
23
23
  const prefix = window.env?.apiPrefix || '/';
24
- const logoUrl = joinUrl(prefix, `/blocklet/logo/${inService ? '' : blocklet.meta.did}`, getSearch(blocklet, customLogo));
25
- const rectLogoUrl = joinUrl(prefix, `/blocklet/logo-rect/${inService ? '' : blocklet.meta.did}`, getSearch(blocklet, customRectLogo));
26
- const faviconUrl = joinUrl(prefix, `/blocklet/logo-favicon/${inService ? '' : blocklet.meta.did}`, getSearch(blocklet, customFavicon));
24
+ const logoUrl = `${joinURL(prefix, `/blocklet/logo/${inService ? '' : blocklet.meta.did}`)}${getSearch(blocklet, customLogo)}`;
25
+ const rectLogoUrl = `${joinURL(prefix, `/blocklet/logo-rect/${inService ? '' : blocklet.meta.did}`)}${getSearch(blocklet, customRectLogo)}`;
26
+ const faviconUrl = `${joinURL(prefix, `/blocklet/logo-favicon/${inService ? '' : blocklet.meta.did}`)}${getSearch(blocklet, customFavicon)}`;
27
27
  return {
28
28
  logoUrl,
29
29
  rectLogoUrl,
@@ -1,4 +1,4 @@
1
- import joinUrl from 'url-join';
1
+ import { joinURL } from 'ufo';
2
2
  import { WELLKNOWN_SERVICE_PATH_PREFIX } from '@abtnode/constant';
3
3
  import { useNodeContext } from '../contexts/node';
4
4
  import { formatRegistryLogoPath, APP_PREFIX, isDownloading, isExtracting } from '../util';
@@ -12,14 +12,14 @@ export default function useAvatar({
12
12
  } = node;
13
13
  const pending = isDownloading(blocklet?.status) || isExtracting(blocklet?.status);
14
14
  const search = `?v=${blocklet?.meta?.version}${pending ? '~' : ''}`;
15
- let logoUrl = inService ? joinUrl(APP_PREFIX, WELLKNOWN_SERVICE_PATH_PREFIX, '/blocklet/logo-bundle', search) : joinUrl(node.imgPrefix, 'blocklet.png');
15
+ let logoUrl = inService ? `${joinURL(APP_PREFIX, WELLKNOWN_SERVICE_PATH_PREFIX, '/blocklet/logo-bundle')}${search}` : joinURL(node.imgPrefix, 'blocklet.png');
16
16
  if (blocklet.source === 'registry' && blocklet.deployedFrom && blocklet.meta.logo) {
17
- logoUrl = joinUrl(blocklet.deployedFrom, formatRegistryLogoPath(blocklet.meta.bundleDid, blocklet.meta.logo), search);
17
+ logoUrl = `${joinURL(blocklet.deployedFrom, formatRegistryLogoPath(blocklet.meta.bundleDid, blocklet.meta.logo))}${search}`;
18
18
  } else {
19
19
  const prefix = window.env.apiPrefix || '/';
20
20
  const components = ancestors.concat(blocklet);
21
21
  const list = inService ? components.slice(1) : components;
22
- logoUrl = joinUrl(prefix, `/blocklet/logo-bundle${list.map(x => `/${x.meta.did}`).join('')}`, search);
22
+ logoUrl = `${joinURL(prefix, `/blocklet/logo-bundle${list.map(x => `/${x.meta.did}`).join('')}`)}${search}`;
23
23
  }
24
24
  return {
25
25
  logoUrl,
@@ -4,7 +4,7 @@ import styled from '@emotion/styled';
4
4
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
5
5
  import DidButton from '@arcblock/did-connect/lib/Button';
6
6
  import { AUTH_SERVICE_PREFIX, API_DID_PREFIX } from '@arcblock/did-connect/lib/constant';
7
- import joinURL from 'url-join';
7
+ import { joinURL } from 'ufo';
8
8
  import { formatDateTime } from '../util';
9
9
  import usePassportId from '../hooks/use-passport-id';
10
10
  import { useSessionContext } from '../contexts/session';
package/lib/locales/ar.js CHANGED
@@ -355,7 +355,8 @@ export default {
355
355
  upload: 'تحميل',
356
356
  blockletStudio: 'استوديو',
357
357
  visitStore: 'زيارة المتجر',
358
- reconnect: 'إعادة الاتصال'
358
+ reconnect: 'إعادة الاتصال',
359
+ change: 'تغيير'
359
360
  },
360
361
  blocklet: {
361
362
  external: 'خارجي',
@@ -675,7 +676,7 @@ export default {
675
676
  componentNotRunning: 'البلوكليت {name} لا يعمل، يرجى تشغيله أولا',
676
677
  releaseEmptyTip: 'لا توجد أي إصدارات هنا',
677
678
  createReleaseTip: 'يمكنك إنشاء إصدار للـ بلوكليت، جنباً إلى جنب مع ملاحظات الإصدار والموارد، ليستخدمها الآخرون.',
678
- createRelease: 'إصدار جديد',
679
+ createRelease: 'إنشاء إصدار',
679
680
  deleteReleaseTip: 'لا يمكن استعادة الإصدار بعد الحذف',
680
681
  createBlockletDid: 'أنشئ من محفظة DID',
681
682
  createReleaseSuccess: 'تم إنشاء الإصدار بنجاح',
@@ -695,7 +696,7 @@ export default {
695
696
  noDescription: 'الوصف المطلوب للكتلة',
696
697
  noNote: 'ملاحظة الإصدار مطلوبة',
697
698
  inValidVersion: 'نسخة الوحدة غير صالحة',
698
- noResource: 'يرجى اختيار المورد المراد ربطه',
699
+ noResource: 'يرجى تحديد موارد التحميل لتضمينها في البلوكليت',
699
700
  noFirstDid: 'يرجى إنشاء بلوكليت ديد أولاً'
700
701
  },
701
702
  packTip: 'حالياً ، يمكن تثبيت البلوكليتس مباشرة كتطبيقات. سيتم تضمين المكونات وتكوينات التطبيق تلقائيًا في البلوكليت.',
@@ -741,7 +742,9 @@ export default {
741
742
  branding: 'صف معلوماتك الأساسية للبلوكليت الخاص بك. ستُعرض هذه المعلومات للمستخدمين في المتجر.'
742
743
  },
743
744
  branding: 'العلامة التجارية',
744
- brandingHelp: 'سيتم عرض مزيد من المعلومات حول البلوكلت في المتجر'
745
+ brandingHelp: 'سيتم عرض مزيد من المعلومات حول البلوكلت في المتجر',
746
+ resourceSelect: 'اختر موردًا من Blocklets',
747
+ resourceUpload: 'قم بتحميل الموارد من قرصك'
745
748
  },
746
749
  titleValidationError: 'يجب أن يكون طول العنوان على الأقل 3 أحرف',
747
750
  descriptionValidationError: 'يجب أن تكون طول الوصف بين 3 و 160 حرفًا'
@@ -891,6 +894,10 @@ export default {
891
894
  monitor: {
892
895
  diskThreshold: 'إرسال تنبيه عند تجاوز استخدام القرص (%)',
893
896
  diskThresholdPlaceholder: 'يرجى تعيين حد التنبيه لاستخدام القرص'
897
+ },
898
+ security: {
899
+ switchLabel: 'عزل نظام الملفات',
900
+ switchTips: 'بعد تعطيل هذا الخيار، فإن نظام ملفات البلوكليت لن يكون عزلًا بعد الآن، مما قد يشكل خطرًا من تلف النظام من قبل البرامج الخبيثة.'
894
901
  }
895
902
  },
896
903
  accessKey: {
@@ -1504,7 +1511,7 @@ export default {
1504
1511
  installedButStopped: 'تم تثبيت التطبيق بنجاح ، ولكن لا يمكن تشغيله. يمكنك بدء تشغيله يدويًا بعد حل مشكلة الحجب.',
1505
1512
  installedButError: 'تم تثبيت التطبيق بنجاح ، ولكن فشل في البدء',
1506
1513
  restoreFailed: 'فشل في استعادة التطبيق، يرجى المحاولة مرة أخرى',
1507
- resourceBlocklet: 'لا يمكن تثبيت الكتلة كتطبيق، يمكنك إضافة هذه الكتلة إلى التطبيقات الحالية.'
1514
+ resourceBlocklet: 'لا يمكن تثبيت بلوكليت الموارد كتطبيق، يمكنك تركيب هذا البلوكليت في التطبيقات الحالية.'
1508
1515
  },
1509
1516
  steps: {
1510
1517
  introduction: 'مقدمة',
package/lib/locales/de.js CHANGED
@@ -355,7 +355,8 @@ export default {
355
355
  upload: 'Hochladen',
356
356
  blockletStudio: 'Studio',
357
357
  visitStore: 'Besuche den Laden',
358
- reconnect: 'Verbinden wiederherstellen'
358
+ reconnect: 'Verbinden wiederherstellen',
359
+ change: 'Ändern'
359
360
  },
360
361
  blocklet: {
361
362
  external: 'Extern',
@@ -675,7 +676,7 @@ export default {
675
676
  componentNotRunning: 'Blocklet {name} läuft nicht, bitte starte es zuerst',
676
677
  releaseEmptyTip: 'Es gibt hier keine Veröffentlichungen',
677
678
  createReleaseTip: 'Du kannst eine Veröffentlichung des Blocklets erstellen, zusammen mit Versionshinweisen und Ressourcen, die andere Personen nutzen können.',
678
- createRelease: 'Neue Veröffentlichung',
679
+ createRelease: 'Erstellen Sie Freigabe',
679
680
  deleteReleaseTip: 'Die Veröffentlichung kann nach Löschung nicht wiederhergestellt werden',
680
681
  createBlockletDid: 'Erstelle aus dem DID Wallet',
681
682
  createReleaseSuccess: 'Freigabe erfolgreich erstellt',
@@ -695,7 +696,7 @@ export default {
695
696
  noDescription: 'Blocklet-Beschreibung ist erforderlich',
696
697
  noNote: 'Versionshinweis wird benötigt',
697
698
  inValidVersion: 'Ungültige Blocklet-Version',
698
- noResource: 'Bitte wählen Sie die Ressource aus, die zugeordnet werden soll',
699
+ noResource: 'Bitte wählen Sie die hochzuladenden Ressourcen aus, die im Blocklet enthalten sein sollen',
699
700
  noFirstDid: 'Bitte erstellen Sie zuerst eine Blocklet-DID'
700
701
  },
701
702
  packTip: 'Derzeit können Blocklets direkt als Anwendungen installiert werden. Komponenten und Anwendungskonfigurationen werden automatisch in das Blocklet aufgenommen.',
@@ -741,7 +742,9 @@ export default {
741
742
  branding: 'Beschreiben Sie die grundlegenden Informationen Ihres Blocklets. Diese Informationen werden den Benutzern im Store angezeigt.'
742
743
  },
743
744
  branding: 'Branding',
744
- brandingHelp: 'Weitere Informationen über den Blocklet werden im Store angezeigt'
745
+ brandingHelp: 'Weitere Informationen über den Blocklet werden im Store angezeigt',
746
+ resourceSelect: 'Wählen Sie eine Ressource aus Blocklets',
747
+ resourceUpload: 'Ressourcen vom Datenträger hochladen'
745
748
  },
746
749
  titleValidationError: 'Die Länge des Titels muss mindestens 3 Zeichen betragen',
747
750
  descriptionValidationError: 'Die Beschreibungslänge muss zwischen 3 und 160 Zeichen liegen'
@@ -891,6 +894,10 @@ export default {
891
894
  monitor: {
892
895
  diskThreshold: 'Sende eine Warnung, wenn die Festplattenauslastung (%) überschritten wird',
893
896
  diskThresholdPlaceholder: 'Bitte legen Sie die Schwelle für die Festplattenauslastungs-Warnung fest'
897
+ },
898
+ security: {
899
+ switchLabel: 'Dateisystemisolierung',
900
+ switchTips: 'Nach Deaktivierung dieser Option befindet sich das Dateisystem des Blocklets nicht mehr in Isolation, was ein Risiko darstellen kann, dass bösartige Software das Dateisystem beschädigt.'
894
901
  }
895
902
  },
896
903
  accessKey: {