@arcblock/did-connect-react 3.3.10 → 3.4.1

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 (39) hide show
  1. package/lib/Connect/assets/locale.js +4 -2
  2. package/lib/Connect/components/login-item/connect-choose-list.js +120 -114
  3. package/lib/Connect/components/login-item/connect-provider-list.js +187 -180
  4. package/lib/Connect/components/login-item/login-method-item.js +63 -47
  5. package/lib/Connect/components/login-item/passkey-login-item.js +17 -15
  6. package/lib/Connect/components/login-item/wallet-login-options.js +42 -40
  7. package/lib/Connect/connect.js +503 -0
  8. package/lib/Connect/contexts/state.js +74 -65
  9. package/lib/Connect/fallback-connect.js +53 -0
  10. package/lib/Connect/hooks/provider-list.js +45 -29
  11. package/lib/Connect/index.js +13 -502
  12. package/lib/Connect/plugins/email/list-item.js +19 -18
  13. package/lib/Connect/use-connect.js +10 -10
  14. package/lib/OAuth/context.js +3 -3
  15. package/lib/Passkey/actions.js +80 -75
  16. package/lib/Passkey/context.js +3 -3
  17. package/lib/Passkey/dialog.js +7 -7
  18. package/lib/Session/assets/did-spaces-guide-cover.svg.js +74 -98
  19. package/lib/Session/index.js +189 -189
  20. package/lib/package.json.js +1 -1
  21. package/lib/utils.js +2 -2
  22. package/package.json +8 -8
  23. package/src/Connect/assets/locale.js +2 -0
  24. package/src/Connect/components/login-item/connect-choose-list.jsx +12 -5
  25. package/src/Connect/components/login-item/connect-provider-list.jsx +11 -4
  26. package/src/Connect/components/login-item/login-method-item.jsx +24 -7
  27. package/src/Connect/components/login-item/passkey-login-item.jsx +3 -1
  28. package/src/Connect/components/login-item/wallet-login-options.jsx +3 -2
  29. package/src/Connect/connect.jsx +618 -0
  30. package/src/Connect/contexts/state.jsx +10 -0
  31. package/src/Connect/fallback-connect.jsx +47 -0
  32. package/src/Connect/hooks/provider-list.js +48 -17
  33. package/src/Connect/index.jsx +8 -605
  34. package/src/Connect/plugins/email/list-item.jsx +3 -2
  35. package/src/Connect/use-connect.jsx +1 -1
  36. package/src/Passkey/actions.jsx +5 -0
  37. package/src/Session/assets/did-spaces-guide-cover.svg +1 -128
  38. package/src/Session/index.jsx +3 -4
  39. package/src/utils.js +2 -2
@@ -1,4 +1,4 @@
1
- const o = "3.3.10", s = {
1
+ const o = "3.4.1", s = {
2
2
  version: o
3
3
  };
4
4
  export {
package/lib/utils.js CHANGED
@@ -6,7 +6,7 @@ import c from "js-cookie";
6
6
  import l from "lodash/isNil";
7
7
  import T from "lodash/isString";
8
8
  import m from "lodash/isUndefined";
9
- import { createAxios as P, BlockletSDK as x } from "@blocklet/js-sdk";
9
+ import { createAxios as P, getBlockletSDK as x } from "@blocklet/js-sdk";
10
10
  import { withQuery as L } from "ufo";
11
11
  import { isValid as w, isFromPublicKey as S } from "@arcblock/did";
12
12
  import { getSafeUrl as C } from "@arcblock/ux/lib/Util/security";
@@ -137,7 +137,7 @@ async function be() {
137
137
  o.searchParams.delete(f);
138
138
  const t = JSON.parse(a.from(r, "base64").toString("utf-8"));
139
139
  if (T(t.forceConnected) && m(t.sourceAppPid)) {
140
- const s = await new x().user.getUserPublicInfo({ did: t.forceConnected });
140
+ const s = await x().user.getUserPublicInfo({ did: t.forceConnected });
141
141
  m(s?.sourceAppPid) || (t.sourceAppPid = s.sourceAppPid);
142
142
  }
143
143
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/did-connect-react",
3
- "version": "3.3.10",
3
+ "version": "3.4.1",
4
4
  "description": "Client side library to work with DID Connect by ArcBlock.",
5
5
  "keywords": [
6
6
  "react",
@@ -32,17 +32,17 @@
32
32
  "url": "https://github.com/ArcBlock/ux/issues"
33
33
  },
34
34
  "dependencies": {
35
- "@arcblock/bridge": "3.3.10",
36
- "@arcblock/did": "^1.27.16",
37
- "@arcblock/icons": "3.3.10",
38
- "@arcblock/react-hooks": "3.3.10",
39
- "@arcblock/ws": "^1.27.16",
35
+ "@arcblock/bridge": "3.4.1",
36
+ "@arcblock/did": "^1.28.1",
37
+ "@arcblock/icons": "3.4.1",
38
+ "@arcblock/react-hooks": "3.4.1",
39
+ "@arcblock/ws": "^1.28.1",
40
40
  "@blocklet/constant": "^1.17.7",
41
41
  "@fontsource/lexend": "^5.2.9",
42
42
  "@iconify-icons/logos": "^1.2.36",
43
43
  "@iconify-icons/material-symbols": "^1.2.58",
44
44
  "@iconify/react": "^5.2.1",
45
- "@ocap/util": "^1.27.16",
45
+ "@ocap/util": "^1.28.1",
46
46
  "@simplewebauthn/browser": "^13.1.0",
47
47
  "ahooks": "^3.8.5",
48
48
  "axios": "^1.10.0",
@@ -81,5 +81,5 @@
81
81
  "eslint-plugin-react-hooks": "^4.6.2",
82
82
  "jest": "^29.7.0"
83
83
  },
84
- "gitHead": "6c98492b766cb7f7486f3a81f3d4e4b0936af163"
84
+ "gitHead": "6101f8f54333c0c376437160147a0b15a1548111"
85
85
  }
@@ -71,6 +71,7 @@ export default {
71
71
  didConnectTitle: 'DID Connect',
72
72
  didConnectDescription: 'Decentralized identities and apps, W3C DID-based, future-ready.',
73
73
  noAuthenticationProvider: 'No authentication provider configured',
74
+ lastUsed: 'Last Used',
74
75
  },
75
76
  zh: {
76
77
  generateError: '二维码生成失败',
@@ -143,5 +144,6 @@ export default {
143
144
  didConnectTitle: 'DID Connect',
144
145
  didConnectDescription: '面向未来的基于 W3C DID 去中心化身份和应用',
145
146
  noAuthenticationProvider: '未配置任何身份验证提供者',
147
+ lastUsed: '上次使用',
146
148
  },
147
149
  };
@@ -48,7 +48,8 @@ export default function ConnectChooseList({
48
48
  const passkeyLoginRef = useRef(null);
49
49
  const { loginOAuth, logoutOAuth, t, oauthState } = useOAuth();
50
50
  const { passkeyState } = usePasskey();
51
- const { extraParams, locale, connectState, plugins, setPlugins, setSelectedPlugin, getPlugin } = useStateContext();
51
+ const { extraParams, locale, connectState, plugins, setPlugins, setSelectedPlugin, getPlugin, lastLoginMethod } =
52
+ useStateContext();
52
53
 
53
54
  const handleLoginOAuth = useMemoizedFn(async (item) => {
54
55
  localStorage.setItem(GA_LAST_LOGIN_METHOD, item.provider);
@@ -111,7 +112,7 @@ export default function ConnectChooseList({
111
112
  if (magicToken && showEmailLogin && plugins.some((plugin) => plugin.name === LOGIN_PROVIDER.EMAIL)) {
112
113
  const plugin = getPlugin(LOGIN_PROVIDER.EMAIL);
113
114
  if (plugin.state.status === 'idle') {
114
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'email');
115
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.EMAIL);
115
116
  plugin.state.reset();
116
117
  plugin.state.magicToken = magicToken;
117
118
  connectState.chooseMethod = LOGIN_PROVIDER.EMAIL;
@@ -160,6 +161,8 @@ export default function ConnectChooseList({
160
161
  ]}>
161
162
  {showMobileLogin && (
162
163
  <MobileLoginItem
164
+ t={t}
165
+ isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
163
166
  ref={walletLoginRef}
164
167
  tokenState={tokenState}
165
168
  sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
@@ -167,7 +170,7 @@ export default function ConnectChooseList({
167
170
  tokenKey={tokenKey}
168
171
  disableSwitchApp={disableSwitchApp}
169
172
  onClick={async () => {
170
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'wallet');
173
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
171
174
  tokenState.reset();
172
175
  await onReset();
173
176
  tokenState.status = 'created';
@@ -181,13 +184,15 @@ export default function ConnectChooseList({
181
184
  )}
182
185
  {showWebLogin && (
183
186
  <WebLoginItem
187
+ isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
184
188
  ref={webLoginRef}
185
189
  tokenState={tokenState}
186
190
  webWalletUrl={webWalletUrl}
191
+ t={t}
187
192
  sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
188
193
  disableSwitchApp={disableSwitchApp}
189
194
  onClick={() => {
190
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'wallet');
195
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
191
196
  // HACK: 在点击插件登录时,直接将状态置为扫码中,避免插件登录时的状态切换
192
197
  tokenState.status = 'scanned';
193
198
  connectState.chooseMethod = 'wallet-web';
@@ -222,6 +227,8 @@ export default function ConnectChooseList({
222
227
  {showOAuthLogin
223
228
  ? oauthProviderList.map((item) => (
224
229
  <LoginMethodItem
230
+ t={t}
231
+ isLatest={lastLoginMethod && lastLoginMethod === item.provider}
225
232
  key={item.provider}
226
233
  title={LOGIN_PROVIDER_NAME[item.provider]}
227
234
  icon={
@@ -254,7 +261,7 @@ export default function ConnectChooseList({
254
261
  behavior={passkeyBehavior}
255
262
  sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
256
263
  onClick={() => {
257
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'passkey');
264
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.PASSKEY);
258
265
  const connectFn = passkeyLoginRef.current.connect;
259
266
  connectState.chooseMethod = 'passkey';
260
267
  connectState.retryConnect = () => {
@@ -65,6 +65,7 @@ export default function ConnectProviderList({
65
65
  getPlugin,
66
66
  showWalletOptions,
67
67
  setShowWalletOptions,
68
+ lastLoginMethod,
68
69
  } = useStateContext();
69
70
 
70
71
  const t = useMemoizedFn((key, data = {}) => {
@@ -127,7 +128,7 @@ export default function ConnectProviderList({
127
128
  });
128
129
 
129
130
  const handleMobileLoginClick = useMemoizedFn(async () => {
130
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'wallet');
131
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
131
132
  tokenState.reset();
132
133
  await onReset();
133
134
  tokenState.status = 'created';
@@ -139,7 +140,7 @@ export default function ConnectProviderList({
139
140
  });
140
141
 
141
142
  const handleWebLoginClick = useMemoizedFn(() => {
142
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'wallet');
143
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.WALLET);
143
144
  // HACK: 在点击插件登录时,直接将状态置为扫码中,避免插件登录时的状态切换
144
145
  tokenState.status = 'scanned';
145
146
  connectState.chooseMethod = 'wallet-web';
@@ -178,7 +179,7 @@ export default function ConnectProviderList({
178
179
  ) {
179
180
  const plugin = getPlugin(LOGIN_PROVIDER.EMAIL);
180
181
  if (plugin.state.status === 'idle') {
181
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'email');
182
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.EMAIL);
182
183
  plugin.state.reset();
183
184
  plugin.state.magicToken = magicToken;
184
185
  connectState.chooseMethod = LOGIN_PROVIDER.EMAIL;
@@ -215,6 +216,8 @@ export default function ConnectProviderList({
215
216
  if (browser.mobile.any && !showWalletOptions) {
216
217
  return (
217
218
  <MobileLoginItem
219
+ t={t}
220
+ isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
218
221
  key={LOGIN_PROVIDER.WALLET}
219
222
  ref={walletLoginRef}
220
223
  tokenState={tokenState}
@@ -233,6 +236,8 @@ export default function ConnectProviderList({
233
236
  hideQRCode || (!hideQRCode && (isSameProtocol || extension) && (!browser.mobile.any || extension));
234
237
  return shouldShowWebLoginItem ? (
235
238
  <WebLoginItem
239
+ t={t}
240
+ isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.WALLET}
236
241
  key={LOGIN_PROVIDER.WALLET}
237
242
  ref={webLoginRef}
238
243
  tokenState={tokenState}
@@ -265,7 +270,7 @@ export default function ConnectProviderList({
265
270
  behavior={passkeyBehavior}
266
271
  sx={[size === 'small' ? { p: 1 } : { p: 2 }]}
267
272
  onClick={() => {
268
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'passkey');
273
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.PASSKEY);
269
274
  const connectFn = passkeyLoginRef.current.connect;
270
275
  connectState.chooseMethod = 'passkey';
271
276
  connectState.retryConnect = () => {
@@ -305,6 +310,8 @@ export default function ConnectProviderList({
305
310
  if (item.type === 'oauth') {
306
311
  return (
307
312
  <LoginMethodItem
313
+ t={t}
314
+ isLatest={lastLoginMethod && lastLoginMethod === item.provider}
308
315
  key={item.provider}
309
316
  title={LOGIN_PROVIDER_NAME[item.provider]}
310
317
  icon={
@@ -2,17 +2,20 @@ import { Box, Tooltip, Typography, useTheme } from '@mui/material';
2
2
  import { Icon } from '@iconify/react';
3
3
  import { isValidElement } from 'react';
4
4
  import PropTypes from 'prop-types';
5
+ import noop from 'lodash/noop';
5
6
  import { mergeSx } from '@arcblock/ux/lib/Util/style';
6
7
  import { LOGIN_PROVIDER_ICON_SIZE } from '@arcblock/ux/lib/Util/constant';
7
8
  import ArrowRightAltRoundedIcon from '@iconify-icons/material-symbols/arrow-right-alt-rounded';
8
9
 
9
10
  export default function LoginMethodItem({
11
+ isLatest = false,
10
12
  title,
11
13
  description = null,
12
14
  icon,
13
15
  iconScale = 0.95,
14
16
  slotProps = {},
15
17
  mode = 'normal',
18
+ t = noop,
16
19
  ...rest
17
20
  }) {
18
21
  const theme = useTheme();
@@ -23,13 +26,16 @@ export default function LoginMethodItem({
23
26
  className="arc-login-item"
24
27
  sx={mergeSx(
25
28
  {
29
+ position: 'relative',
26
30
  display: 'flex',
27
31
  alignItems: 'center',
28
32
  gap: 1,
29
33
  cursor: 'pointer',
30
34
  p: 1.2,
31
35
  borderRadius: 1,
32
- backgroundColor: 'grey.50',
36
+ backgroundColor: isLatest ? 'grey.100' : 'grey.50',
37
+ border: isLatest ? '1px solid' : 'none',
38
+ borderColor: isLatest ? 'grey.100' : 'transparent',
33
39
  textDecoration: 'none',
34
40
  transition: 'background-color 0.5s',
35
41
  '&:hover, &:active, &.did-connect__choose-item__active': {
@@ -100,12 +106,21 @@ export default function LoginMethodItem({
100
106
  </Typography>
101
107
  ) : null}
102
108
  </Box>
103
- <Icon
104
- className="other-item-icon"
105
- icon={ArrowRightAltRoundedIcon}
106
- fontSize="1.3rem"
107
- color={theme.palette.primary.main}
108
- />
109
+ {isLatest ? (
110
+ <Typography
111
+ component="span"
112
+ className="latest-badge"
113
+ style={{ color: theme.palette.text.secondary, fontSize: 11 }}>
114
+ {t('lastUsed')}
115
+ </Typography>
116
+ ) : (
117
+ <Icon
118
+ className="other-item-icon"
119
+ icon={ArrowRightAltRoundedIcon}
120
+ fontSize="1.3rem"
121
+ color={theme.palette.primary.main}
122
+ />
123
+ )}
109
124
  </>
110
125
  ) : null}
111
126
  </Box>
@@ -119,4 +134,6 @@ LoginMethodItem.propTypes = {
119
134
  iconScale: PropTypes.number,
120
135
  slotProps: PropTypes.object,
121
136
  mode: PropTypes.oneOf(['mini', 'simple', 'normal']),
137
+ isLatest: PropTypes.bool,
138
+ t: PropTypes.func,
122
139
  };
@@ -1,13 +1,14 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import { useImperativeHandle, useRef } from 'react';
3
3
  import { useMemoizedFn } from 'ahooks';
4
+ import { LOGIN_PROVIDER } from '@arcblock/ux/lib/Util/constant';
4
5
 
5
6
  import PasskeyActions from '../../../Passkey/actions';
6
7
  import { getAppId } from '../../../utils';
7
8
  import { useStateContext } from '../../contexts/state';
8
9
 
9
10
  export default function PasskeyLoginItem({ ref = null, onSuccess, tokenState, behavior = 'none', ...rest }) {
10
- const { extraParams } = useStateContext();
11
+ const { extraParams, lastLoginMethod } = useStateContext();
11
12
  const passkeyActionRef = useRef(null);
12
13
 
13
14
  const handleSuccess = useMemoizedFn((result) =>
@@ -36,6 +37,7 @@ export default function PasskeyLoginItem({ ref = null, onSuccess, tokenState, be
36
37
  <PasskeyActions
37
38
  {...rest}
38
39
  ref={passkeyActionRef}
40
+ isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.PASSKEY}
39
41
  action={tokenState.action}
40
42
  behavior={behavior}
41
43
  onSuccess={handleSuccess}
@@ -24,7 +24,7 @@ export default function WalletLoginOptions({
24
24
  onWebLoginClick,
25
25
  onBack,
26
26
  }) {
27
- const { locale } = useStateContext();
27
+ const { t, locale } = useStateContext();
28
28
  const browser = useBrowser();
29
29
  const isSameProtocol = checkSameProtocol(webWalletUrl);
30
30
  const extension = detectWalletExtension();
@@ -32,7 +32,6 @@ export default function WalletLoginOptions({
32
32
  const isTablet = useCreation(() => {
33
33
  return browser.mobile.tablet || (!browser.mobile.any && window?.navigator?.maxTouchPoints > 0);
34
34
  }, [browser.mobile.tablet, browser.mobile.any]);
35
-
36
35
  return (
37
36
  <>
38
37
  {qrcode}
@@ -67,6 +66,7 @@ export default function WalletLoginOptions({
67
66
  }}>
68
67
  {isTablet ? (
69
68
  <MobileLoginItem
69
+ t={t}
70
70
  key={LOGIN_PROVIDER.WALLET}
71
71
  ref={walletLoginRef}
72
72
  tokenState={tokenState}
@@ -82,6 +82,7 @@ export default function WalletLoginOptions({
82
82
  <>
83
83
  {(isSameProtocol || extension) && (!browser.mobile.any || extension) ? (
84
84
  <WebLoginItem
85
+ t={t}
85
86
  key={LOGIN_PROVIDER.WALLET}
86
87
  ref={webLoginRef}
87
88
  tokenState={tokenState}