@abtnode/ux 1.16.17-beta-5d4664f8 → 1.16.17-beta-2ac96448

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.
@@ -1,14 +1,17 @@
1
- import React, { useState, useContext } from 'react';
1
+ import React, { useState, useContext, lazy, useRef } from 'react';
2
2
  import styled from '@emotion/styled';
3
3
  import PropTypes from 'prop-types';
4
4
  import get from 'lodash/get';
5
5
  import isEqual from 'lodash/isEqual';
6
+ import classnames from 'classnames';
7
+ import joinUrl from 'url-join';
6
8
  import Box from '@mui/material/Box';
7
9
  import Switch from '@mui/material/Switch';
8
10
  import Divider from '@mui/material/Divider';
9
11
  import { LocaleContext } from '@arcblock/ux/lib/Locale/context';
10
12
  import Button from '@arcblock/ux/lib/Button';
11
13
  import LoopIcon from '@mui/icons-material/Loop';
14
+ import Avatar from '@mui/material/Avatar';
12
15
  import { EVENTS } from '@abtnode/constant';
13
16
  import { BLOCKLET_CONFIGURABLE_KEY, SUPPORTED_LANGUAGES } from '@blocklet/constant';
14
17
  import { getWhoCanAccess } from '@blocklet/meta/lib/util';
@@ -22,19 +25,34 @@ import Permission, { withPermission } from '../permission';
22
25
  import ClearCache from '../clear-cache';
23
26
  import AppSk from './preferences/app-sk';
24
27
  import TransferOwner from './transfer-owner';
28
+ import useAppLogo from '../hooks/use-app-logo';
25
29
  import { jsx as _jsx } from "react/jsx-runtime";
26
30
  import { jsxs as _jsxs } from "react/jsx-runtime";
27
31
  const languages = Object.keys(SUPPORTED_LANGUAGES).map(x => ({
28
32
  code: x,
29
33
  name: SUPPORTED_LANGUAGES[x].nativeName
30
34
  }));
35
+
36
+ // eslint-disable-next-line import/no-unresolved
37
+ const UploaderComponent = /*#__PURE__*/lazy(() => import('@blocklet/uploader/react').then(res => ({
38
+ default: res.Uploader
39
+ })));
40
+ const uploadPrefix = '/blocklet/logo/upload';
31
41
  function BlockletEnvironment({
32
42
  blocklet,
33
43
  onUpdate,
34
44
  hasPermission,
35
45
  ...rest
36
46
  }) {
37
- const node = useNodeContext();
47
+ const {
48
+ api,
49
+ inService,
50
+ prefix,
51
+ getSessionInHeader,
52
+ ws: {
53
+ useSubscription
54
+ }
55
+ } = useNodeContext();
38
56
  const {
39
57
  t
40
58
  } = useContext(LocaleContext);
@@ -44,12 +62,28 @@ function BlockletEnvironment({
44
62
  const whoCanAccess = getWhoCanAccess(blocklet);
45
63
  const publicToStore = blocklet?.settings?.publicToStore;
46
64
  const disabled = loading || !hasPermission;
65
+ const uploaderLogoRef = useRef(null);
47
66
  const {
48
- inService,
49
- ws: {
50
- useSubscription
67
+ logoUrl,
68
+ rectLogoUrl,
69
+ faviconUrl
70
+ } = useAppLogo({
71
+ blocklet
72
+ });
73
+ const [apiPathProps, setApiPathProps] = useState();
74
+ const uploadLogoPrefix = joinUrl(prefix, uploadPrefix, 'square', blocklet.meta.did);
75
+ const uploadLogoRectPrefix = joinUrl(prefix, uploadPrefix, 'rect', blocklet.meta.did);
76
+ const uploadLogoFaviconPrefix = joinUrl(prefix, uploadPrefix, 'favicon', blocklet.meta.did);
77
+ const openUploader = uploaderPrefix => {
78
+ if (!hasPermission) {
79
+ return;
51
80
  }
52
- } = node;
81
+ setApiPathProps({
82
+ uploader: uploaderPrefix,
83
+ disableMediaKitPrefix: true
84
+ });
85
+ uploaderLogoRef.current.open();
86
+ };
53
87
  const {
54
88
  did
55
89
  } = blocklet.meta;
@@ -71,10 +105,6 @@ function BlockletEnvironment({
71
105
  const deletable = !customDelete || customDelete.value === 'yes';
72
106
  const customLanguages = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LANGUAGES);
73
107
  const customUrl = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_URL);
74
- const customLogoSquare = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_SQUARE);
75
- const customLogoRect = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_RECT);
76
- const customLogoFavicon = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_FAVICON);
77
- const customLogoDeprecated = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO);
78
108
  const copyrightOwner = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_COPYRIGHT_OWNER);
79
109
  const copyrightYear = blocklet.environments.find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_COPYRIGHT_YEAR);
80
110
  const configurableEnvs = [{
@@ -89,22 +119,6 @@ function BlockletEnvironment({
89
119
  key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_URL,
90
120
  description: t('blocklet.config.appUrl'),
91
121
  value: customUrl ? customUrl.value : ''
92
- }, {
93
- key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_SQUARE,
94
- description: t('blocklet.config.logoSquare'),
95
- value: customLogoSquare ? customLogoSquare.value : ''
96
- }, {
97
- key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_RECT,
98
- description: t('blocklet.config.logoRect'),
99
- value: customLogoRect ? customLogoRect.value : ''
100
- }, {
101
- key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_FAVICON,
102
- description: t('blocklet.config.logoFavicon'),
103
- value: customLogoFavicon ? customLogoFavicon.value : ''
104
- }, {
105
- key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO,
106
- description: t('blocklet.config.logo'),
107
- value: customLogoDeprecated ? customLogoDeprecated.value : ''
108
122
  }, {
109
123
  key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_COPYRIGHT_OWNER,
110
124
  description: t('blocklet.config.copyrightOwner'),
@@ -135,7 +149,7 @@ function BlockletEnvironment({
135
149
  } = e.target;
136
150
  const {
137
151
  blocklet: data
138
- } = await node.api.configPublicToStore({
152
+ } = await api.configPublicToStore({
139
153
  input: {
140
154
  did: blocklet.meta.did,
141
155
  publicToStore: checked
@@ -167,7 +181,7 @@ function BlockletEnvironment({
167
181
  setLoading(true);
168
182
  const {
169
183
  blocklet: data
170
- } = await node.api.configBlocklet({
184
+ } = await api.configBlocklet({
171
185
  input: {
172
186
  did: blocklet.meta.did,
173
187
  configs: params
@@ -191,7 +205,7 @@ function BlockletEnvironment({
191
205
  } = e.target;
192
206
  const {
193
207
  blocklet: data
194
- } = await node.api.configBlocklet({
208
+ } = await api.configBlocklet({
195
209
  input: {
196
210
  did: blocklet.meta.did,
197
211
  configs: [{
@@ -216,7 +230,7 @@ function BlockletEnvironment({
216
230
  try {
217
231
  setLoading(true);
218
232
  const corsAllowedOrigins = newValue.length ? newValue : ['__none__'];
219
- await node.api.updateRoutingSite({
233
+ await api.updateRoutingSite({
220
234
  input: {
221
235
  id: site.id,
222
236
  corsAllowedOrigins,
@@ -239,7 +253,7 @@ function BlockletEnvironment({
239
253
  try {
240
254
  const {
241
255
  blocklet: data
242
- } = await node.api.configBlocklet({
256
+ } = await api.configBlocklet({
243
257
  input: {
244
258
  did: blocklet.meta.did,
245
259
  configs: [{
@@ -255,6 +269,11 @@ function BlockletEnvironment({
255
269
  setLoading(false);
256
270
  }
257
271
  };
272
+ const uploaderStyle = {
273
+ '&::after': {
274
+ content: `"${t('common.switch')}"`
275
+ }
276
+ };
258
277
  return /*#__PURE__*/_jsxs(Div, {
259
278
  ...rest,
260
279
  children: [configurableEnvs.map(item => /*#__PURE__*/_jsxs(Box, {
@@ -275,6 +294,95 @@ function BlockletEnvironment({
275
294
  onSubmit: value => onSubmitConfig(item.key, value)
276
295
  })]
277
296
  })), /*#__PURE__*/_jsx(Box, {
297
+ className: "config-form",
298
+ component: Divider,
299
+ my: 3
300
+ }), /*#__PURE__*/_jsx(Box, {
301
+ className: "config-label",
302
+ fontSize: 14,
303
+ mb: 1,
304
+ sx: {
305
+ flexGrow: 0,
306
+ width: 'auto'
307
+ },
308
+ children: t('blocklet.config.logoSquare')
309
+ }), /*#__PURE__*/_jsx(Box, {
310
+ className: classnames('uploader-wrapper', hasPermission && 'enabled'),
311
+ sx: uploaderStyle,
312
+ onClick: () => openUploader(uploadLogoPrefix),
313
+ children: /*#__PURE__*/_jsx(Avatar, {
314
+ sx: {
315
+ height: 80,
316
+ width: 80
317
+ },
318
+ variant: "square",
319
+ alt: "Blocklet Logo",
320
+ src: logoUrl
321
+ })
322
+ }), /*#__PURE__*/_jsx(Box, {
323
+ className: "config-label",
324
+ fontSize: 14,
325
+ mt: 4,
326
+ children: t('blocklet.config.logoRect')
327
+ }), /*#__PURE__*/_jsx(Box, {
328
+ mb: 1.5,
329
+ className: "config-desc",
330
+ children: t('blocklet.config.logoRectDesc')
331
+ }), /*#__PURE__*/_jsx(Box, {
332
+ className: classnames('uploader-wrapper', hasPermission && 'enabled'),
333
+ sx: uploaderStyle,
334
+ onClick: () => openUploader(uploadLogoRectPrefix),
335
+ children: /*#__PURE__*/_jsx("img", {
336
+ alt: "Blocklet Rect Logo",
337
+ src: rectLogoUrl,
338
+ style: {
339
+ height: '80px'
340
+ }
341
+ })
342
+ }), /*#__PURE__*/_jsx(Box, {
343
+ className: "config-label",
344
+ fontSize: 14,
345
+ mt: 4,
346
+ children: t('blocklet.config.logoFavicon')
347
+ }), /*#__PURE__*/_jsx(Box, {
348
+ mb: 1.5,
349
+ className: "config-desc",
350
+ children: t('blocklet.config.logoFaviconDesc')
351
+ }), /*#__PURE__*/_jsx(Box, {
352
+ sx: {
353
+ display: 'inline-flex',
354
+ cursor: hasPermission ? 'pointer' : 'default'
355
+ },
356
+ onClick: () => openUploader(uploadLogoFaviconPrefix),
357
+ children: /*#__PURE__*/_jsx(Avatar, {
358
+ variant: "square",
359
+ sx: {
360
+ width: 20,
361
+ height: 20
362
+ },
363
+ alt: "Blocklet Favicon Logo",
364
+ src: faviconUrl
365
+ })
366
+ }), /*#__PURE__*/_jsx(UploaderComponent, {
367
+ id: "\u200Buploader-logo",
368
+ ref: uploaderLogoRef,
369
+ popup: true,
370
+ onUploadFinish: () => {
371
+ uploaderLogoRef.current.close();
372
+ },
373
+ plugins: [],
374
+ apiPathProps: apiPathProps,
375
+ coreProps: {
376
+ restrictions: {
377
+ allowedFileTypes: ['image/*', '.jpg', '.jpeg', '.png', '.gif', '.svg'],
378
+ maxFileSize: 1024 * 1024 * 10,
379
+ maxNumberOfFiles: 1
380
+ }
381
+ },
382
+ tusProps: {
383
+ headers: getSessionInHeader
384
+ }
385
+ }, "uploader-logo"), /*#__PURE__*/_jsx(Box, {
278
386
  className: "config-form",
279
387
  children: whoCanAccess === 'all' && blocklet.source === 'registry' && /*#__PURE__*/_jsxs(Box, {
280
388
  className: "config-item",
@@ -485,7 +593,6 @@ const Div = styled.div`
485
593
  flex-shrink: 0;
486
594
  padding: 0 24px;
487
595
  transform: translate(0, 0);
488
- max-height: 60vh;
489
596
  }
490
597
  }
491
598
 
@@ -509,4 +616,34 @@ const Div = styled.div`
509
616
  .form-item {
510
617
  margin-top: 0;
511
618
  }
619
+
620
+ .uploader-wrapper {
621
+ display: inline-flex;
622
+ position: relative;
623
+ font-size: 0px;
624
+ &.enabled {
625
+ cursor: pointer;
626
+ }
627
+ &::after {
628
+ display: none;
629
+ }
630
+ &.enabled::after {
631
+ display: block;
632
+ opacity: 0;
633
+ position: absolute;
634
+ bottom: 0;
635
+ background: rgba(0, 0, 0, 0.2);
636
+ left: 0;
637
+ right: 0;
638
+ height: 2.2em;
639
+ color: white;
640
+ text-align: center;
641
+ font-size: 12px;
642
+ line-height: 2em;
643
+ transition: opacity 0.3s ease;
644
+ }
645
+ &:hover::after {
646
+ opacity: 1;
647
+ }
648
+ }
512
649
  `;
@@ -582,7 +582,7 @@ export default function CreateRelease({
582
582
  maxNumberOfFiles: 1
583
583
  }
584
584
  }
585
- }, "uploader-screenshot"), /*#__PURE__*/_jsx(UploaderComponent, {
585
+ }, "uploader-logo"), /*#__PURE__*/_jsx(UploaderComponent, {
586
586
  id: "\u200Buploader-screenshot",
587
587
  ref: uploaderScreenshotRef,
588
588
  popup: true,
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+ import { Typography } from '@mui/material';
3
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
4
+ import Toast from '@arcblock/ux/lib/Toast';
5
+ import SwitchControl from '../component/switch-control';
6
+ import { useBlockletStorageContext } from '../../contexts/blocklet-storage';
7
+
8
+ /**
9
+ * @description
10
+ * @param {{
11
+ * style: import('react').CSSProperties
12
+ * }} {...rest}
13
+ * @return {*}
14
+ */
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+ function AutoBackup({
17
+ ...rest
18
+ }) {
19
+ const {
20
+ t
21
+ } = useLocaleContext();
22
+ const {
23
+ autoBackup,
24
+ updateAutoBackup
25
+ } = useBlockletStorageContext();
26
+ const configAutoBackup = async () => {
27
+ try {
28
+ const enabled = !autoBackup.enabled;
29
+ await updateAutoBackup({
30
+ enabled
31
+ });
32
+ Toast.success(enabled ? t('storage.spaces.autoBackup.enabled') : t('storage.spaces.autoBackup.disabled'));
33
+ } catch (error) {
34
+ Toast.error(error.message);
35
+ }
36
+ };
37
+ return /*#__PURE__*/_jsx(SwitchControl, {
38
+ checked: Boolean(autoBackup?.enabled),
39
+ onChange: configAutoBackup,
40
+ name: "enableWelcomePage",
41
+ labelProps: {
42
+ label: /*#__PURE__*/_jsx(Typography, {
43
+ marginRight: "8px",
44
+ children: /*#__PURE__*/_jsx("span", {
45
+ children: t('storage.spaces.autoBackup.title')
46
+ })
47
+ })
48
+ },
49
+ style: {
50
+ ...rest.style
51
+ }
52
+ });
53
+ }
54
+ AutoBackup.propTypes = {};
55
+ export default AutoBackup;
@@ -9,6 +9,7 @@ import { useBlockletContext } from '../../contexts/blocklet';
9
9
  import { useNodeContext } from '../../contexts/node';
10
10
  import DiskInfo from '../disk-info';
11
11
  import { useBlockletStorageContext } from '../../contexts/blocklet-storage';
12
+ import AutoBackup from './auto-backup';
12
13
 
13
14
  /**
14
15
  * @typedef {{
@@ -72,7 +73,12 @@ function Connected() {
72
73
  children: [/*#__PURE__*/_jsx(Typography, {
73
74
  fontSize: "1.2rem",
74
75
  fontWeight: "bold",
76
+ flexGrow: 1,
75
77
  children: t('storage.spaces.connected.title')
78
+ }), /*#__PURE__*/_jsx(AutoBackup, {
79
+ style: {
80
+ marginRight: '32px'
81
+ }
76
82
  }), /*#__PURE__*/_jsx(ConnectTo, {})]
77
83
  }), /*#__PURE__*/_jsx(Box, {
78
84
  children: shouldShowLoading ? /*#__PURE__*/_jsx(Box, {
@@ -9,10 +9,12 @@ import useSpaceGateways from '../hooks/use-space-gateways';
9
9
  import { useNodeContext } from './node';
10
10
  import useBackupProgress from '../hooks/use-backup-progress';
11
11
  import useBackups from '../hooks/use-backups';
12
+ import { useAutoBackup } from '../hooks/use-auto-backup';
12
13
 
13
14
  /**
14
15
  * @typedef {import('../blocklet/storage/connected').SpaceGateway} SpaceGateway
15
16
  * @typedef {import('@abtnode/client').Backup} Backup
17
+ * @typedef {import('@abtnode/client').AutoBackup} AutoBackup
16
18
  */
17
19
 
18
20
  /**
@@ -25,12 +27,14 @@ import useBackups from '../hooks/use-backups';
25
27
  * refreshSpaceGateways: () => void,
26
28
  * spaceGatewaysLoading: boolean,
27
29
  * spaceGatewayIsSelected: (spaceGateway: SpaceGateway) => boolean,
30
+ * updateAutoBackup: (autoBackup: { enabled: boolean }) => Promise<void>,
28
31
  *
29
32
  * backupEndpoint: string,
30
33
  * backupProgress: any,
31
34
  * backups: Backup[],
32
35
  * backupsLoading: boolean,
33
36
  * refreshBackupEndpoint: () => void,
37
+ * autoBackup: AutoBackup,
34
38
  * }} BlockletStorageContextType
35
39
  */
36
40
 
@@ -78,6 +82,10 @@ function BlockletStorageProvider({
78
82
  setLoading: setBackupsLoading
79
83
  });
80
84
  const [selectedSpaceGateway, setSelectedSpaceGateway] = useState(spaceGateways?.find(x => x.endpoint === backupEndpoint));
85
+ const [autoBackupRefresh, setAutoBackupRefresh] = useState(false);
86
+ const autoBackup = useAutoBackup({
87
+ deps: [autoBackupRefresh]
88
+ });
81
89
 
82
90
  /**
83
91
  * @description
@@ -172,9 +180,26 @@ function BlockletStorageProvider({
172
180
  * @param {SpaceGateway} spaceGateway
173
181
  */
174
182
  const spaceGatewayIsSelected = spaceGateway => spaceGateway?.endpoint === backupEndpoint;
183
+
184
+ /**
185
+ * @description
186
+ * @param {AutoBackup} value
187
+ */
188
+ const updateAutoBackup = async value => {
189
+ await api.updateAutoBackup({
190
+ input: {
191
+ did: blocklet.meta.did,
192
+ autoBackup: value
193
+ }
194
+ });
195
+ refreshAutoBackup();
196
+ };
175
197
  const refreshBackupEndpoint = () => {
176
198
  setBackupEndpointRefresh(p => !p);
177
199
  };
200
+ const refreshAutoBackup = () => {
201
+ setAutoBackupRefresh(x => !x);
202
+ };
178
203
  return /*#__PURE__*/_jsx(Provider, {
179
204
  value: {
180
205
  spaceGateways,
@@ -185,11 +210,13 @@ function BlockletStorageProvider({
185
210
  refreshSpaceGateways,
186
211
  spaceGatewaysLoading,
187
212
  spaceGatewayIsSelected,
213
+ updateAutoBackup,
188
214
  backupEndpoint,
189
215
  backupProgress,
190
216
  backups,
191
217
  backupsLoading,
192
- refreshBackupEndpoint
218
+ refreshBackupEndpoint,
219
+ autoBackup
193
220
  },
194
221
  children: children
195
222
  });
@@ -1,16 +1,32 @@
1
1
  import joinUrl from 'url-join';
2
+ import { BLOCKLET_CONFIGURABLE_KEY } from '@blocklet/constant';
2
3
  import { useNodeContext } from '../contexts/node';
3
- import { isInstalling } from '../util';
4
+ import { isInstalling, getLogoHash } from '../util';
5
+ const getSearch = (blocklet, customLogo) => {
6
+ let search = '?v=';
7
+ if (customLogo) {
8
+ search += getLogoHash(customLogo);
9
+ } else {
10
+ search += `${blocklet?.meta?.version}${isInstalling(blocklet?.status) ? '~' : ''}`;
11
+ }
12
+ return search;
13
+ };
4
14
  export default function useAppLogo({
5
15
  blocklet
6
16
  }) {
7
17
  const {
8
18
  inService
9
19
  } = useNodeContext();
20
+ const customLogo = (blocklet?.environments || []).find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_SQUARE)?.value;
21
+ const customRectLogo = (blocklet?.environments || []).find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_RECT)?.value;
22
+ const customFavicon = (blocklet?.environments || []).find(x => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_LOGO_FAVICON)?.value;
10
23
  const prefix = window.env?.apiPrefix || '/';
11
- const search = `?v=${blocklet?.meta?.version}${isInstalling(blocklet?.status) ? '~' : ''}`;
12
- const logoUrl = joinUrl(prefix, `/blocklet/logo/${inService ? '' : blocklet.meta.did}`, search);
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));
13
27
  return {
14
- logoUrl
28
+ logoUrl,
29
+ rectLogoUrl,
30
+ faviconUrl
15
31
  };
16
32
  }
@@ -0,0 +1,33 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ import { useAsyncEffect } from 'ahooks';
3
+ import { useState } from 'react';
4
+ import { useBlockletContext } from '../contexts/blocklet';
5
+ import { useNodeContext } from '../contexts/node';
6
+ export function useAutoBackup({
7
+ deps
8
+ } = {
9
+ deps: []
10
+ }) {
11
+ /** @type {{ blocklet: import('@abtnode/client').BlockletState }} */
12
+ const {
13
+ blocklet
14
+ } = useBlockletContext();
15
+ /** @type {{api: import('@abtnode/client')}} */
16
+ const {
17
+ api
18
+ } = useNodeContext();
19
+ const [autoBackup, setAutoBackup] = useState(null);
20
+ useAsyncEffect(async () => {
21
+ if (blocklet?.meta?.did) {
22
+ const {
23
+ autoBackup: data
24
+ } = await api.getAutoBackup({
25
+ input: {
26
+ did: blocklet.meta.did
27
+ }
28
+ });
29
+ setAutoBackup(data);
30
+ }
31
+ }, [blocklet?.meta?.did].concat(deps));
32
+ return autoBackup;
33
+ }
package/es/locales/en.js CHANGED
@@ -278,6 +278,7 @@ module.exports = {
278
278
  succeeded: 'Succeeded',
279
279
  subscription: 'Subscription',
280
280
  support: 'Support',
281
+ switch: 'Switch',
281
282
  team: 'Team',
282
283
  the: 'The',
283
284
  timeAgo: '{time} ago',
@@ -391,10 +392,11 @@ module.exports = {
391
392
  name: 'Blocklet Name',
392
393
  description: 'Blocklet Description',
393
394
  sk: 'Secret key for the blocklet wallet',
394
- logo: '(Deprecated) Logo URL or path for the blocklet',
395
- logoSquare: 'Square logo URL or path for the blocklet (optional, default to logo from blocklet store)',
396
- logoRect: 'Horizontal logo URL or path for the blocklet (optional)',
397
- logoFavicon: 'favicon URL or path for the blocklet (optional, default to square logo)',
395
+ logoSquare: 'App Logo',
396
+ logoRect: 'Rect logo',
397
+ logoRectDesc: 'Usually displayed at the top of the page, default to app logo',
398
+ logoFavicon: 'Favicon',
399
+ logoFaviconDesc: "Usually displayed in the browser's address bar or tab page, default to app logo",
398
400
  clusterSize: 'Instance count when run this blocklet in cluster mode',
399
401
  copyrightOwner: 'Copyright Owner (Display in footer)',
400
402
  copyrightYear: 'Copyright Year (Display in footer)',
@@ -1437,6 +1439,11 @@ module.exports = {
1437
1439
  title: 'Backup',
1438
1440
  records: 'Backup Records'
1439
1441
  },
1442
+ autoBackup: {
1443
+ title: 'Auto backup',
1444
+ enabled: 'Automatic backup is on',
1445
+ disabled: 'Automatic backup is off'
1446
+ },
1440
1447
  backupSuccessfully: 'Backup successfully',
1441
1448
  restore: 'Restore',
1442
1449
  restoreSuccessfully: 'Restore successfully',
package/es/locales/zh.js CHANGED
@@ -283,6 +283,7 @@ module.exports = {
283
283
  succeeded: '成功',
284
284
  subscription: '订阅',
285
285
  support: '服务支持',
286
+ switch: '切换',
286
287
  team: '团队',
287
288
  the: '此',
288
289
  timeAgo: '{time}前',
@@ -395,10 +396,11 @@ module.exports = {
395
396
  name: '应用名称',
396
397
  description: '应用描述',
397
398
  sk: '应用账户私钥',
398
- logo: '(即将废弃)应用 Logo 地址或路径',
399
- logoSquare: '正方形 Logo 地址或路径 (可选,默认使用发布到 Store 的应用Logo)',
400
- logoRect: '横版 Logo 地址或路径 (可选)',
401
- logoFavicon: 'favicon 地址或路径 (可选,默认和正方形 Logo 相同)',
399
+ logoSquare: '应用 Logo',
400
+ logoRect: '横版 Logo',
401
+ logoRectDesc: '通常显示在页面顶部,默认和应用 Logo 相同',
402
+ logoFavicon: 'Favicon',
403
+ logoFaviconDesc: '通常显示在浏览器的地址栏或标签页中,默认和应用 Logo 相同',
402
404
  clusterSize: '以 Cluster 模式启动时的实例数量',
403
405
  copyrightOwner: '版权所有者 (展示在页脚中)',
404
406
  copyrightYear: '版权年份 (展示在页脚中)',
@@ -1441,6 +1443,11 @@ module.exports = {
1441
1443
  title: '备份',
1442
1444
  records: '备份记录'
1443
1445
  },
1446
+ autoBackup: {
1447
+ title: '自动备份',
1448
+ enabled: '自动备份已开启',
1449
+ disabled: '自动备份已关闭'
1450
+ },
1444
1451
  backupSuccessfully: '备份成功',
1445
1452
  restore: '还原',
1446
1453
  restoreSuccessfully: '还原成功',
package/es/util/index.js CHANGED
@@ -614,4 +614,5 @@ export const getSubscriptionURL = async ({
614
614
  return joinUrl(baseUrl, `/${nftId}/subscription?locale=${locale}&return-url=${encodeURIComponent(window.location.href)}`);
615
615
  };
616
616
  export const nanoid = (length = 16) => [...Array(length)].map(() => Math.random().toString(36)[2]).join('');
617
- export const getSystemDomains = domains => domains.filter(x => x.isProtected);
617
+ export const getSystemDomains = domains => domains.filter(x => x.isProtected);
618
+ export const getLogoHash = logo => encodeURIComponent((logo || '').split('/').slice(-1)[0].slice(0, 7));