@arcblock/ux 2.10.25 → 2.10.27

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,6 +28,12 @@ function Header({
28
28
  minWidth: brandWrapperMinWidth
29
29
  };
30
30
  useEffect(() => {
31
+ const {
32
+ searchParams
33
+ } = new URL(window.location.href);
34
+ if (searchParams.get('inviter')) {
35
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
36
+ }
31
37
  if (logoRef.current) {
32
38
  setBrandWrapperMinWidth(`${logoRef.current.offsetWidth}px`);
33
39
  }
@@ -93,6 +93,14 @@ function Dashboard({
93
93
  homeLink: defaultHomeLink,
94
94
  ...headerProps
95
95
  };
96
+ useEffect(() => {
97
+ const {
98
+ searchParams
99
+ } = new URL(window.location.href);
100
+ if (searchParams.get('inviter')) {
101
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
102
+ }
103
+ }, []);
96
104
  return /*#__PURE__*/_jsxs(Wrapper, {
97
105
  ...rest,
98
106
  className: classes,
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState } from 'react';
2
+ import { useEffect, useState } from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import Helmet from 'react-helmet';
5
5
  import { AppBar, Container, Drawer, Divider, IconButton, Link, List, ListItem, ListItemText, Toolbar, Typography } from '@mui/material';
@@ -29,6 +29,14 @@ export default function Layout({
29
29
  const onToggleDrawer = () => {
30
30
  setDrawerOpen(!drawerOpen);
31
31
  };
32
+ useEffect(() => {
33
+ const {
34
+ searchParams
35
+ } = new URL(window.location.href);
36
+ if (searchParams.get('inviter')) {
37
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
38
+ }
39
+ }, []);
32
40
  if (contentOnly) {
33
41
  return /*#__PURE__*/_jsx(Container, {
34
42
  children: children
@@ -1,13 +1,16 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import PropTypes from 'prop-types';
3
3
  import { useRef } from 'react';
4
- import { useMemoizedFn, useReactive } from 'ahooks';
4
+ import { useCreation, useMemoizedFn, useReactive } from 'ahooks';
5
5
  import { Box, ClickAwayListener, Divider, Fade, IconButton, MenuItem, MenuList, Paper, Popper } from '@mui/material';
6
6
  import { Icon } from '@iconify/react';
7
7
  import PersonOutlineRoundedIcon from '@iconify-icons/material-symbols/person-outline-rounded';
8
8
  import FilterVintageOutlineRoundedIcon from '@iconify-icons/material-symbols/filter-vintage-outline-rounded';
9
9
  import AccountCircleOffOutlineRoundedIcon from '@iconify-icons/material-symbols/account-circle-off-outline-rounded';
10
+ import InviteIcon from '@iconify-icons/material-symbols/featured-seasonal-and-gifts-rounded';
11
+ import Copy from 'copy-to-clipboard';
10
12
  import noop from 'lodash/noop';
13
+ import Toast from '../../Toast';
11
14
  import DidAvatar from '../../Avatar';
12
15
  import { getUserAvatar } from '../../Util';
13
16
  import UserInfo from './user-info';
@@ -16,6 +19,11 @@ import { DASHBOARD_URL, PROFILE_URL } from '../../Util/constant';
16
19
  import SessionPermission from '../../SessionPermission';
17
20
  import { translations } from '../libs/translation';
18
21
  import { translate } from '../../Locale/util';
22
+ const getInviteLink = inviter => {
23
+ const url = new URL(window.location.href);
24
+ url.searchParams.set('inviter', inviter);
25
+ return url.toString();
26
+ };
19
27
  export default function LoggedIn({
20
28
  session,
21
29
  dark,
@@ -27,6 +35,9 @@ export default function LoggedIn({
27
35
  const t = useMemoizedFn((key, data = {}) => {
28
36
  return translate(translations, key, locale, 'en', data);
29
37
  });
38
+ const isInviteEnabled = useCreation(() => {
39
+ return !!globalThis?.blocklet?.settings?.invite?.enabled;
40
+ });
30
41
  const popperAnchorRef = useRef(null);
31
42
  const currentState = useReactive({
32
43
  open: false
@@ -69,6 +80,12 @@ export default function LoggedIn({
69
80
  onTogglePopper(false);
70
81
  session.bindWallet(onBindWallet);
71
82
  });
83
+ const handleOpenInvite = useMemoizedFn(() => {
84
+ onTogglePopper(false);
85
+ const link = getInviteLink(session.user.did);
86
+ Copy(link);
87
+ Toast.success(t('inviteCopied'));
88
+ });
72
89
  return /*#__PURE__*/_jsxs(_Fragment, {
73
90
  children: [/*#__PURE__*/_jsx(IconButton, {
74
91
  ref: popperAnchorRef,
@@ -155,6 +172,14 @@ export default function LoggedIn({
155
172
  textDecoration: 'none',
156
173
  color: 'inherit'
157
174
  }
175
+ }), isInviteEnabled && /*#__PURE__*/_jsx(SessionMenuItem, {
176
+ icon: InviteIcon,
177
+ title: t('invite'),
178
+ onClick: handleOpenInvite,
179
+ sx: {
180
+ display: 'block',
181
+ color: 'inherit'
182
+ }
158
183
  }), /*#__PURE__*/_jsx(Divider, {
159
184
  sx: {
160
185
  m: '0!important',
@@ -4,6 +4,8 @@ export const translations = {
4
4
  connectDIDWallet: 'Connect your DID Wallet for enhanced security',
5
5
  switch: 'Switch',
6
6
  profile: 'Profile',
7
+ invite: 'Invite friends',
8
+ inviteCopied: 'Your invite link has been copied to the clipboard. Send it to your friends to complete the invitation',
7
9
  dashboard: 'Dashboard',
8
10
  logout: 'Sign Out',
9
11
  addAnotherAccount: 'Add another account'
@@ -12,6 +14,8 @@ export const translations = {
12
14
  connectDIDWallet: '连接你的 DID Wallet 获得更高的安全性',
13
15
  switch: '切换',
14
16
  profile: '个人中心',
17
+ invite: '邀请好友',
18
+ inviteCopied: '你的专属链接已经复制到剪贴板,发送给朋友即可完成邀请',
15
19
  dashboard: '控制台',
16
20
  logout: '退出登录',
17
21
  addAnotherAccount: '添加账户'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/ux",
3
- "version": "2.10.25",
3
+ "version": "2.10.27",
4
4
  "description": "Common used react components for arcblock products",
5
5
  "keywords": [
6
6
  "react",
@@ -59,12 +59,12 @@
59
59
  "react": ">=18.2.0",
60
60
  "react-router-dom": ">=6.22.3"
61
61
  },
62
- "gitHead": "c08068e4f1992102d89bc2fc54c93a864453bf24",
62
+ "gitHead": "22f8b70a73928fc915274ee0f609e96f330b1d2e",
63
63
  "dependencies": {
64
64
  "@arcblock/did-motif": "^1.1.13",
65
- "@arcblock/icons": "^2.10.25",
66
- "@arcblock/nft-display": "^2.10.25",
67
- "@arcblock/react-hooks": "^2.10.25",
65
+ "@arcblock/icons": "^2.10.27",
66
+ "@arcblock/nft-display": "^2.10.27",
67
+ "@arcblock/react-hooks": "^2.10.27",
68
68
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
69
69
  "@fontsource/inter": "^5.0.16",
70
70
  "@fontsource/ubuntu-mono": "^5.0.18",
@@ -76,7 +76,7 @@
76
76
  "@testing-library/react": "^14.0.0",
77
77
  "@types/mui-datatables": "^4.3.12",
78
78
  "ahooks": "^3.7.10",
79
- "axios": "^1.7.2",
79
+ "axios": "^1.7.5",
80
80
  "base64-url": "^2.3.3",
81
81
  "copy-to-clipboard": "^3.3.2",
82
82
  "core-js": "^3.25.5",
@@ -26,6 +26,11 @@ function Header({
26
26
  const style = { minWidth: brandWrapperMinWidth };
27
27
 
28
28
  useEffect(() => {
29
+ const { searchParams } = new URL(window.location.href);
30
+ if (searchParams.get('inviter')) {
31
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
32
+ }
33
+
29
34
  if (logoRef.current) {
30
35
  setBrandWrapperMinWidth(`${logoRef.current.offsetWidth}px`);
31
36
  }
@@ -66,6 +66,13 @@ function Dashboard({ children, title, headerProps, links = [], fullWidth, dense,
66
66
  ...headerProps,
67
67
  };
68
68
 
69
+ useEffect(() => {
70
+ const { searchParams } = new URL(window.location.href);
71
+ if (searchParams.get('inviter')) {
72
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
73
+ }
74
+ }, []);
75
+
69
76
  return (
70
77
  <Wrapper {...rest} className={classes}>
71
78
  <Helmet title={title} key={title} />
@@ -1,4 +1,4 @@
1
- import { useState } from 'react';
1
+ import { useEffect, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import Helmet from 'react-helmet';
4
4
  import {
@@ -43,6 +43,13 @@ export default function Layout({
43
43
  setDrawerOpen(!drawerOpen);
44
44
  };
45
45
 
46
+ useEffect(() => {
47
+ const { searchParams } = new URL(window.location.href);
48
+ if (searchParams.get('inviter')) {
49
+ window.localStorage.setItem('inviter', searchParams.get('inviter'));
50
+ }
51
+ }, []);
52
+
46
53
  if (contentOnly) {
47
54
  return <Container>{children}</Container>;
48
55
  }
@@ -1,13 +1,16 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import { useRef } from 'react';
3
- import { useMemoizedFn, useReactive } from 'ahooks';
3
+ import { useCreation, useMemoizedFn, useReactive } from 'ahooks';
4
4
  import { Box, ClickAwayListener, Divider, Fade, IconButton, MenuItem, MenuList, Paper, Popper } from '@mui/material';
5
5
  import { Icon } from '@iconify/react';
6
6
  import PersonOutlineRoundedIcon from '@iconify-icons/material-symbols/person-outline-rounded';
7
7
  import FilterVintageOutlineRoundedIcon from '@iconify-icons/material-symbols/filter-vintage-outline-rounded';
8
8
  import AccountCircleOffOutlineRoundedIcon from '@iconify-icons/material-symbols/account-circle-off-outline-rounded';
9
+ import InviteIcon from '@iconify-icons/material-symbols/featured-seasonal-and-gifts-rounded';
10
+ import Copy from 'copy-to-clipboard';
9
11
  import noop from 'lodash/noop';
10
12
 
13
+ import Toast from '../../Toast';
11
14
  import DidAvatar from '../../Avatar';
12
15
  import { getUserAvatar } from '../../Util';
13
16
  import UserInfo from './user-info';
@@ -17,10 +20,19 @@ import SessionPermission from '../../SessionPermission';
17
20
  import { translations } from '../libs/translation';
18
21
  import { translate } from '../../Locale/util';
19
22
 
23
+ const getInviteLink = (inviter) => {
24
+ const url = new URL(window.location.href);
25
+ url.searchParams.set('inviter', inviter);
26
+ return url.toString();
27
+ };
28
+
20
29
  export default function LoggedIn({ session, dark, onBindWallet, isBlocklet, locale, size }) {
21
30
  const t = useMemoizedFn((key, data = {}) => {
22
31
  return translate(translations, key, locale, 'en', data);
23
32
  });
33
+ const isInviteEnabled = useCreation(() => {
34
+ return !!globalThis?.blocklet?.settings?.invite?.enabled;
35
+ });
24
36
  const popperAnchorRef = useRef(null);
25
37
  const currentState = useReactive({
26
38
  open: false,
@@ -66,6 +78,14 @@ export default function LoggedIn({ session, dark, onBindWallet, isBlocklet, loca
66
78
  onTogglePopper(false);
67
79
  session.bindWallet(onBindWallet);
68
80
  });
81
+
82
+ const handleOpenInvite = useMemoizedFn(() => {
83
+ onTogglePopper(false);
84
+ const link = getInviteLink(session.user.did);
85
+ Copy(link);
86
+ Toast.success(t('inviteCopied'));
87
+ });
88
+
69
89
  return (
70
90
  <>
71
91
  <IconButton
@@ -132,6 +152,14 @@ export default function LoggedIn({ session, dark, onBindWallet, isBlocklet, loca
132
152
  href={PROFILE_URL}
133
153
  sx={{ display: 'block', textDecoration: 'none', color: 'inherit' }}
134
154
  />
155
+ {isInviteEnabled && (
156
+ <SessionMenuItem
157
+ icon={InviteIcon}
158
+ title={t('invite')}
159
+ onClick={handleOpenInvite}
160
+ sx={{ display: 'block', color: 'inherit' }}
161
+ />
162
+ )}
135
163
  <Divider sx={{ m: '0!important', borderColor: colors.strokeSep }} />
136
164
  </>
137
165
  ) : null}
@@ -4,6 +4,9 @@ export const translations = {
4
4
  connectDIDWallet: 'Connect your DID Wallet for enhanced security',
5
5
  switch: 'Switch',
6
6
  profile: 'Profile',
7
+ invite: 'Invite friends',
8
+ inviteCopied:
9
+ 'Your invite link has been copied to the clipboard. Send it to your friends to complete the invitation',
7
10
  dashboard: 'Dashboard',
8
11
  logout: 'Sign Out',
9
12
  addAnotherAccount: 'Add another account',
@@ -12,6 +15,8 @@ export const translations = {
12
15
  connectDIDWallet: '连接你的 DID Wallet 获得更高的安全性',
13
16
  switch: '切换',
14
17
  profile: '个人中心',
18
+ invite: '邀请好友',
19
+ inviteCopied: '你的专属链接已经复制到剪贴板,发送给朋友即可完成邀请',
15
20
  dashboard: '控制台',
16
21
  logout: '退出登录',
17
22
  addAnotherAccount: '添加账户',