diff --git a/apps/dcellar-web-ui/CHANGELOG.json b/apps/dcellar-web-ui/CHANGELOG.json
index d27e4eb3..fae71c3d 100644
--- a/apps/dcellar-web-ui/CHANGELOG.json
+++ b/apps/dcellar-web-ui/CHANGELOG.json
@@ -1,6 +1,18 @@
{
"name": "dcellar-web-ui",
"entries": [
+ {
+ "version": "0.4.0",
+ "tag": "dcellar-web-ui_v0.4.0",
+ "date": "Mon, 25 Mar 2024 04:02:13 GMT",
+ "comments": {
+ "minor": [
+ {
+ "comment": "Support create on chain folder & share virtual path"
+ }
+ ]
+ }
+ },
{
"version": "0.3.1",
"tag": "dcellar-web-ui_v0.3.1",
diff --git a/apps/dcellar-web-ui/CHANGELOG.md b/apps/dcellar-web-ui/CHANGELOG.md
index 2ef316e6..6360cf5c 100644
--- a/apps/dcellar-web-ui/CHANGELOG.md
+++ b/apps/dcellar-web-ui/CHANGELOG.md
@@ -1,6 +1,13 @@
# Change Log - dcellar-web-ui
-This log was last generated on Wed, 20 Mar 2024 07:14:31 GMT and should not be manually modified.
+This log was last generated on Mon, 25 Mar 2024 04:02:13 GMT and should not be manually modified.
+
+## 0.4.0
+Mon, 25 Mar 2024 04:02:13 GMT
+
+### Minor changes
+
+- Support create on chain folder & share virtual path
## 0.3.1
Wed, 20 Mar 2024 07:14:31 GMT
diff --git a/apps/dcellar-web-ui/package.json b/apps/dcellar-web-ui/package.json
index d3fa57d1..7728b3d8 100644
--- a/apps/dcellar-web-ui/package.json
+++ b/apps/dcellar-web-ui/package.json
@@ -1,6 +1,6 @@
{
"name": "dcellar-web-ui",
- "version": "0.3.1",
+ "version": "0.4.0",
"private": false,
"scripts": {
"dev": "node ./scripts/dev.js -p 3200",
diff --git a/apps/dcellar-web-ui/src/components/common/DCTable/ListEmpty.tsx b/apps/dcellar-web-ui/src/components/common/DCTable/ListEmpty.tsx
index 4581654d..ef371c67 100644
--- a/apps/dcellar-web-ui/src/components/common/DCTable/ListEmpty.tsx
+++ b/apps/dcellar-web-ui/src/components/common/DCTable/ListEmpty.tsx
@@ -1,12 +1,12 @@
import { IconFont } from '@/components/IconFont';
import styled from '@emotion/styled';
import { Box, Flex, Text } from '@node-real/uikit';
-import { PropsWithChildren, memo } from 'react';
+import { PropsWithChildren, memo, ReactNode } from 'react';
interface ListEmptyProps extends PropsWithChildren {
empty: boolean;
title: string;
- desc: string;
+ desc: ReactNode;
type: string;
h?: number;
}
diff --git a/apps/dcellar-web-ui/src/components/layout/Header/Account/index.tsx b/apps/dcellar-web-ui/src/components/layout/Header/Account/index.tsx
index a982c54b..42292ecf 100644
--- a/apps/dcellar-web-ui/src/components/layout/Header/Account/index.tsx
+++ b/apps/dcellar-web-ui/src/components/layout/Header/Account/index.tsx
@@ -5,6 +5,7 @@ import {
PopoverContent,
PopoverContentProps,
PopoverTrigger,
+ Portal,
} from '@node-real/uikit';
import { TransferEntry } from './TransferEntry';
import { Address } from './Address';
@@ -21,11 +22,13 @@ export const Account = () => {
-
-
-
-
-
+
+
+
+
+
+
+
);
};
diff --git a/apps/dcellar-web-ui/src/modules/object/components/CreateFolderOperation.tsx b/apps/dcellar-web-ui/src/modules/object/components/CreateFolderOperation.tsx
index c8af3f6c..44ce685b 100644
--- a/apps/dcellar-web-ui/src/modules/object/components/CreateFolderOperation.tsx
+++ b/apps/dcellar-web-ui/src/modules/object/components/CreateFolderOperation.tsx
@@ -64,7 +64,7 @@ import {
} from '@node-real/uikit';
import { useAsyncEffect, useUnmount } from 'ahooks';
import BigNumber from 'bignumber.js';
-import { isEmpty } from 'lodash-es';
+import { isEmpty, last, trimEnd } from 'lodash-es';
import { ChangeEvent, memo, useCallback, useEffect, useMemo, useState } from 'react';
import { useAccount } from 'wagmi';
import { TotalFees } from './TotalFees';
@@ -73,6 +73,7 @@ interface CreateFolderOperationProps {
selectBucket: TBucket;
bucketAccountDetail: AccountInfo;
primarySp: SpEntity;
+ chainFolder?: string;
refetch?: (name?: string) => void;
onClose?: () => void;
}
@@ -80,6 +81,7 @@ interface CreateFolderOperationProps {
export const CreateFolderOperation = memo(function CreateFolderDrawer({
refetch = () => {},
onClose = () => {},
+ chainFolder: chainFolderName,
selectBucket: bucket,
bucketAccountDetail: accountDetail,
primarySp,
@@ -102,7 +104,8 @@ export const CreateFolderOperation = memo(function C
const { settlementFee } = useSettlementFee(PaymentAddress);
const [balanceEnough, setBalanceEnough] = useState(true);
const [loading, setLoading] = useState(false);
- const [inputFolderName, setInputFolderName] = useState('');
+ const initFolderName = last(trimEnd(chainFolderName || '', '/').split('/'));
+ const [inputFolderName, setInputFolderName] = useState(initFolderName || '');
const [formErrors, setFormErrors] = useState([]);
const [usedNames, setUsedNames] = useState([]);
@@ -288,7 +291,7 @@ export const CreateFolderOperation = memo(function C
errors.push('Cannot consist of slash(/).');
}
const folderNames = folderList.map((folder) => folder.name);
- if (folderNames.includes(value)) {
+ if (folderNames.includes(value) && !chainFolderName) {
errors.push('Folder name already exists.');
}
setFormErrors(errors);
@@ -382,10 +385,16 @@ export const CreateFolderOperation = memo(function C
return (
<>
- Create a Folder
+ {chainFolderName ? 'Create on chain folder' : 'Create a Folder'}
- Use folders to group objects in your bucket. Folder names can't contain
- "/".
+ {chainFolderName ? (
+ 'Convert your existing path to an on chain folder to view detailed data on the chain and obtain additional features.'
+ ) : (
+ <>
+ Use folders to group objects in your bucket. Folder names can't contain
+ "/".
+ >
+ )}
@@ -396,6 +405,7 @@ export const CreateFolderOperation = memo(function C
Name
e.key === 'Enter' && onCreateFolder()}
value={inputFolderName}
onChange={onFolderNameChange}
diff --git a/apps/dcellar-web-ui/src/modules/object/components/CreateObject.tsx b/apps/dcellar-web-ui/src/modules/object/components/CreateObject.tsx
index 6bef772d..f938b30e 100644
--- a/apps/dcellar-web-ui/src/modules/object/components/CreateObject.tsx
+++ b/apps/dcellar-web-ui/src/modules/object/components/CreateObject.tsx
@@ -98,7 +98,7 @@ export const CreateObject = memo(function NewObject({
>
);
- const folderExist = !objectCommonPrefix ? true : !!objectRecords[completeCommonPrefix + '/'];
+ const folderExist = !objectCommonPrefix || !!objectRecords[completeCommonPrefix + '/'];
const invalidPath =
pathSegments.some((name) => new Blob([name]).size > MAX_FOLDER_NAME_LEN) || !folderExist;
diff --git a/apps/dcellar-web-ui/src/modules/object/components/DeleteObjectOperation.tsx b/apps/dcellar-web-ui/src/modules/object/components/DeleteObjectOperation.tsx
index f3371afd..9083157e 100644
--- a/apps/dcellar-web-ui/src/modules/object/components/DeleteObjectOperation.tsx
+++ b/apps/dcellar-web-ui/src/modules/object/components/DeleteObjectOperation.tsx
@@ -117,7 +117,8 @@ export const DeleteObjectOperation = memo(
);
return (
GfSpListObjectsByBucketNameResponse.KeyCount === '1' &&
- GfSpListObjectsByBucketNameResponse.Objects[0].ObjectInfo.ObjectName === objectName
+ // virtual path
+ GfSpListObjectsByBucketNameResponse.Objects[0]?.ObjectInfo.ObjectName === objectName
);
};
diff --git a/apps/dcellar-web-ui/src/modules/object/components/DetailFolderOperation.tsx b/apps/dcellar-web-ui/src/modules/object/components/DetailFolderOperation.tsx
index 3e61e283..da6b0e3d 100644
--- a/apps/dcellar-web-ui/src/modules/object/components/DetailFolderOperation.tsx
+++ b/apps/dcellar-web-ui/src/modules/object/components/DetailFolderOperation.tsx
@@ -16,10 +16,15 @@ import { convertObjectKey } from '@/utils/common';
import { formatId } from '@/utils/string';
import { formatFullTime } from '@/utils/time';
import { ResourceTags_Tag } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/types';
-import { Divider, Flex, QDrawerBody, QDrawerHeader, Text } from '@node-real/uikit';
+import { Box, Divider, Flex, QDrawerBody, QDrawerHeader, Text } from '@node-real/uikit';
import { useMount, useUnmount } from 'ahooks';
import { last } from 'lodash-es';
-import { memo } from 'react';
+import { memo, useMemo, useState } from 'react';
+import { MOCK_EMPTY_FOLDER_OBJECT } from '@/modules/object/constant';
+import { ObjectMeta } from '@bnb-chain/greenfield-js-sdk/dist/esm/types/sp/Common';
+import { DCLink } from '@/components/common/DCLink';
+import { Tips } from '@/components/common/Tips';
+import { DCButton } from '@/components/common/DCButton';
interface DetailFolderOperationProps {
objectName: string;
@@ -32,13 +37,28 @@ export const DetailFolderOperation = memo(
const dispatch = useAppDispatch();
const completeCommonPrefix = useAppSelector((root) => root.object.completeCommonPrefix);
const objectRecords = useAppSelector((root) => root.object.objectRecords);
+ // const objectOperation = useAppSelector((root) => root.object.objectOperation);
+ // const [id, operation, params] = objectOperation[1];
+ // const preOperation = usePrevious(operation);
+ // const preObjectName = usePrevious(params?.objectName);
- const selectObjectInfo = useModalValues(
- objectRecords[[selectBucket.BucketName, objectName].join('/')] || {},
+ const cacheKey = [selectBucket.BucketName, objectName].join('/');
+ const mockMeta: ObjectMeta = useMemo(
+ () => ({
+ ...MOCK_EMPTY_FOLDER_OBJECT,
+ ObjectInfo: {
+ ...MOCK_EMPTY_FOLDER_OBJECT.ObjectInfo,
+ ObjectName: objectName,
+ BucketName: selectBucket.BucketName,
+ },
+ }),
+ [objectName, selectBucket.BucketName],
);
+ const selectObjectInfo = useModalValues(objectRecords[cacheKey] || mockMeta);
const objectInfo = useModalValues(selectObjectInfo.ObjectInfo);
+ const [folderExist, setFolderExist] = useState(true);
const folderName = last(objectName.replace(/\/$/, '').split('/'));
- const loading = !objectInfo;
+ const loading = !(cacheKey in objectRecords) && folderExist;
const onEditTags = () => {
const lowerKeyTags = selectObjectInfo.ObjectInfo?.Tags?.Tags.map((item) =>
@@ -53,7 +73,7 @@ export const DetailFolderOperation = memo(
);
};
- useMount(async () => {
+ const getFolderObjectList = async () => {
const _query = new URLSearchParams();
_query.append('delimiter', '/');
_query.append('maxKeys', '2');
@@ -70,16 +90,24 @@ export const DetailFolderOperation = memo(
const [res, error] = await getListObjects(params);
// should never happen
- if (error || !res || res.code !== 0) return false;
+ if (error || !res || res.code !== 0) return;
const { GfSpListObjectsByBucketNameResponse } = res.body!;
+ const list = GfSpListObjectsByBucketNameResponse!;
// 更新文件夹objectInfo
- dispatch(
- setObjectList({
- path: completeCommonPrefix,
- list: GfSpListObjectsByBucketNameResponse || [],
- infoOnly: true,
- }),
- );
+ dispatch(setObjectList({ path: completeCommonPrefix, list, infoOnly: true }));
+ return list;
+ };
+
+ // useAsyncEffect(async () => {
+ // if (preObjectName !== objectInfo.ObjectName || preOperation !== 'create_folder') return;
+ // await getFolderObjectList();
+ // }, [preOperation, preObjectName, objectInfo.ObjectName]);
+
+ useMount(async () => {
+ const list = await getFolderObjectList();
+ if (!list) return;
+ // virtual path
+ setFolderExist(list.Objects[0]?.ObjectInfo.ObjectName.endsWith('/') || false);
});
useUnmount(() => dispatch(setObjectEditTagsData([DEFAULT_TAG])));
@@ -101,13 +129,64 @@ export const DetailFolderOperation = memo(
>
{folderName}
-
- --
+
+ {folderExist ? (
+ '--'
+ ) : (
+
+ This is a folder simulated by a path.{' '}
+
+
+ {
+ "This path doesn't exist as an entity on the blockchain and lacks chain information."
+ }
+
+
+ Learn more
+
+
+ }
+ />
+
+ )}
-
+
+ {!folderExist && (
+
+
+ dispatch(
+ setObjectOperation({
+ operation: ['', 'create_folder', { objectName: objectInfo.ObjectName }],
+ }),
+ )
+ }
+ position={'absolute'}
+ right={24}
+ top={70}
+ >
+ Create on chain folder
+
+
+ )}
{renderPropRow(
'Date created',
loading ? '' : formatFullTime(+objectInfo.CreateAt * 1000),
diff --git a/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx b/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx
index d64e193b..6082ac5d 100644
--- a/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx
+++ b/apps/dcellar-web-ui/src/modules/object/components/ObjectList.tsx
@@ -50,13 +50,14 @@ import { formatBytes } from '@/utils/formatter';
import { pickAction, removeAction } from '@/utils/object';
import { apolloUrlTemplate } from '@/utils/string';
import { formatTime, getMillisecond } from '@/utils/time';
-import { Flex } from '@node-real/uikit';
+import { Box, Flex } from '@node-real/uikit';
import { useAsyncEffect, useUpdateEffect } from 'ahooks';
import { ColumnProps } from 'antd/es/table';
import dayjs from 'dayjs';
import { find, uniq, without, xor } from 'lodash-es';
import { memo, useCallback } from 'react';
import { OBJECT_ERROR_TYPES, ObjectErrorType } from '../ObjectError';
+import Link from 'next/link';
// import { ManageObjectTagsDrawer } from './ManageObjectTagsDrawer';
export type ObjectActionValueType =
@@ -127,6 +128,7 @@ export const ObjectList = memo(function ObjectList({ shareMode
const bucket = bucketRecords[currentBucketName];
const accountDetail = useAppSelector(selectAccount(bucket?.PaymentAddress));
+ const currentPathExist = !objectCommonPrefix || !!objectRecords[completeCommonPrefix + '/'];
const filtered =
!!objectNameFilter.trim() ||
objectTypeFilter.length ||
@@ -197,33 +199,45 @@ export const ObjectList = memo(function ObjectList({ shareMode
const empty = !loading && !sortedList.length;
const loadingComponent = { spinning: loading, indicator: };
- const renderEmpty = useCallback(
- () => (
-
- {!filtered && !shareMode && }
+ const renderEmpty = useCallback(() => {
+ const type = isBucketDiscontinue && !filtered ? 'discontinue' : 'empty-object';
+ const title = (() => {
+ if (filtered || shareMode) return 'No Results';
+ if (isBucketDiscontinue) return 'Discontinue Notice';
+ if (!currentPathExist && isBucketOwner) return 'No Objects Under This Path';
+ return 'Upload Objects and Start Your Work Now';
+ })();
+
+ const desc = (() => {
+ if (filtered || shareMode) return 'No results found. Please try different conditions.';
+ if (isBucketDiscontinue)
+ return 'This bucket were marked as discontinued and will be deleted by SP soon. ';
+ if (!currentPathExist && isBucketOwner)
+ return (
+
+ The path no longer exists on DCellar. You can{' '}
+ return to the bucket list and
+ continue your work.
+
+ );
+ return `To avoid data loss during testnet phase, the file size should not exceed ${formatBytes(
+ SINGLE_OBJECT_MAX_SIZE,
+ )}.`;
+ })();
+ return (
+
+ {!filtered && !shareMode && currentPathExist && }
- ),
- [isBucketDiscontinue, empty, filtered, shareMode],
- );
+ );
+ }, [
+ isBucketDiscontinue,
+ isBucketOwner,
+ empty,
+ filtered,
+ shareMode,
+ currentPathExist,
+ currentBucketName,
+ ]);
const columns: ColumnProps[] = [
{
@@ -481,6 +495,15 @@ export const ObjectList = memo(function ObjectList({ shareMode
openLink(link);
return;
}
+
+ const forVirtualPath = {
+ ObjectInfo: {
+ BucketName: record.bucketName,
+ ObjectName: record.objectName,
+ Visibility: record.visibility,
+ },
+ };
+
switch (menu) {
case 'detail':
case 'delete':
@@ -503,7 +526,11 @@ export const ObjectList = memo(function ObjectList({ shareMode
return dispatch(
setObjectOperation({
level: 1,
- operation: [`${record.bucketName}/${record.objectName}`, menu],
+ operation: [
+ `${record.bucketName}/${record.objectName}`,
+ menu,
+ record.objectName.endsWith('/') ? { selectObjectInfo: forVirtualPath } : {},
+ ],
}),
);
}
diff --git a/apps/dcellar-web-ui/src/modules/object/components/ObjectOperations.tsx b/apps/dcellar-web-ui/src/modules/object/components/ObjectOperations.tsx
index a5ef1cf7..1a0b296d 100644
--- a/apps/dcellar-web-ui/src/modules/object/components/ObjectOperations.tsx
+++ b/apps/dcellar-web-ui/src/modules/object/components/ObjectOperations.tsx
@@ -46,7 +46,8 @@ export const ObjectOperations = memo(function ObjectOpera
const [id, operation, params] = objectOperation[level];
const bucketName = params?.bucketName || currentBucketName;
const _operation = useModalValues(operation);
- const selectObjectInfo = objectRecords[id] || {};
+ // params?.selectObjectInfo for offchain folder mock data
+ const selectObjectInfo = objectRecords[id] || params?.selectObjectInfo || {};
const _selectObjectInfo = useModalValues(selectObjectInfo);
const { BucketName } = _selectObjectInfo.ObjectInfo || {};
const selectBucket = useModalValues(bucketRecords[BucketName || bucketName] || {});
@@ -130,6 +131,7 @@ export const ObjectOperations = memo(function ObjectOpera
case 'create_folder':
return (
(function SharePermissi
dispatch(
setObjectOperation({
level: 1,
- operation: [`${bucketName}/${objectInfo.ObjectName}`, 'share'],
+ operation: [
+ `${bucketName}/${objectInfo.ObjectName}`,
+ 'share',
+ { selectObjectInfo },
+ ],
}),
);
}}
diff --git a/apps/dcellar-web-ui/src/modules/object/constant.ts b/apps/dcellar-web-ui/src/modules/object/constant.ts
index b4eb8f13..71da7677 100644
--- a/apps/dcellar-web-ui/src/modules/object/constant.ts
+++ b/apps/dcellar-web-ui/src/modules/object/constant.ts
@@ -1,3 +1,5 @@
+import { ObjectMeta } from '@bnb-chain/greenfield-js-sdk/dist/esm/types/sp/Common';
+
export const GAS_FEE_DOC = 'https://docs.nodereal.io/docs/dcellar-faq#fee-related';
export const PREPAID_FEE_DOC = 'https://docs.nodereal.io/docs/dcellar-faq#fee-related';
export const SETTLEMENT_FEE_DOC = 'https://docs.nodereal.io/docs/dcellar-faq#fee-related';
@@ -44,6 +46,46 @@ const AUTH_EXPIRED = 'Authentication Expired';
const WALLET_CONFIRM = 'Please confirm the transaction in your wallet.';
export const EMPTY_TX_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000';
+
+export const MOCK_EMPTY_FOLDER_OBJECT: ObjectMeta = {
+ ObjectInfo: {
+ Owner: '0xDB8040c64d24840BD1D6BcAC7112D2A143CC2EEa',
+ Creator: '0xDB8040c64d24840BD1D6BcAC7112D2A143CC2EEa',
+ BucketName: '',
+ ObjectName: '',
+ Id: 0,
+ LocalVirtualGroupId: 0,
+ PayloadSize: 0,
+ Visibility: 3,
+ ContentType: 'text/plain',
+ CreateAt: 1711002963,
+ ObjectStatus: 1,
+ RedundancyType: 0,
+ SourceType: 0,
+ Checksums: [
+ 'Xfbg4nYTWdMKgnUFjimfzAOBU0VF9Vz0PkGYP11MlFY=',
+ 'Xfbg4nYTWdMKgnUFjimfzAOBU0VF9Vz0PkGYP11MlFY=',
+ 'Xfbg4nYTWdMKgnUFjimfzAOBU0VF9Vz0PkGYP11MlFY=',
+ 'Xfbg4nYTWdMKgnUFjimfzAOBU0VF9Vz0PkGYP11MlFY=',
+ 'Xfbg4nYTWdMKgnUFjimfzAOBU0VF9Vz0PkGYP11MlFY=',
+ 'Xfbg4nYTWdMKgnUFjimfzAOBU0VF9Vz0PkGYP11MlFY=',
+ 'Xfbg4nYTWdMKgnUFjimfzAOBU0VF9Vz0PkGYP11MlFY=',
+ ],
+ Tags: {
+ Tags: [],
+ },
+ },
+ LockedBalance: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ Removed: false,
+ UpdateAt: 3075455,
+ DeleteAt: 0,
+ DeleteReason: '',
+ Operator: '0x0000000000000000000000000000000000000000',
+ CreateTxHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ UpdateTxHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ SealTxHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
+};
+
export {
AUTH_EXPIRED,
BUTTON_GOT_IT,
diff --git a/apps/dcellar-web-ui/src/pages/share/index.tsx b/apps/dcellar-web-ui/src/pages/share/index.tsx
index b1c3ec83..b618acf5 100644
--- a/apps/dcellar-web-ui/src/pages/share/index.tsx
+++ b/apps/dcellar-web-ui/src/pages/share/index.tsx
@@ -108,7 +108,11 @@ const SharePage: NextPage = (props) => {
};
if (!loginAccount) {
- const objectInfo = await headObject(bucketName, objectName);
+ let objectInfo = await headObject(bucketName, objectName);
+ // for virtual path
+ if (objectName.endsWith('/') && !objectInfo) {
+ objectInfo = { bucketName, objectName } as ObjectInfo;
+ }
setObjectInfo(objectInfo);
setQuotaData({} as IQuotaProps);
return;
@@ -120,7 +124,12 @@ const SharePage: NextPage = (props) => {
) {
logout(true);
}
- setObjectInfo(objectInfo);
+ let _objectInfo = objectInfo;
+ // for virtual path
+ if (objectName.endsWith('/') && !objectInfo) {
+ _objectInfo = { bucketName, objectName } as ObjectInfo;
+ }
+ setObjectInfo(_objectInfo);
setQuotaData(quotaData || ({} as IQuotaProps));
}, [specifiedSp, walletConnected]);
diff --git a/apps/dcellar-web-ui/src/utils/string.ts b/apps/dcellar-web-ui/src/utils/string.ts
index 34668535..e8ac7ce9 100644
--- a/apps/dcellar-web-ui/src/utils/string.ts
+++ b/apps/dcellar-web-ui/src/utils/string.ts
@@ -60,6 +60,7 @@ export const trimAddress = (
return trimLongStr(formatAddress(address), maxLength, headLen, footLen);
};
+// todo emoji characters encoding
// encodeURIComponent() uses the same encoding algorithm as described in encodeURI(). It escapes all characters except:
// A–Z a–z 0–9 - _ . ! ~ * ' ( )
export const encodeObjectName = (pathName: string) => {
@@ -98,7 +99,11 @@ export const encodeObjectName = (pathName: string) => {
encodedPathName += '%' + hexStr.toUpperCase();
} else {
// others characters
- encodedPathName += encodeURI(s);
+ try {
+ encodedPathName += encodeURI(s);
+ } catch (e) {
+ encodedPathName += s;
+ }
}
}
}