@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,618 +1,21 @@
1
- import { use, useEffect, useRef, useState } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { Box, Divider, Skeleton } from '@mui/material';
4
- import {
5
- useCreation,
6
- useDebounceFn,
7
- useMemoizedFn,
8
- useMount,
9
- usePrevious,
10
- useSize,
11
- useUpdate,
12
- useUpdateEffect,
13
- } from 'ahooks';
14
- import noop from 'lodash/noop';
15
- import isUndefined from 'lodash/isUndefined';
16
-
17
- import CloseButton from '@arcblock/ux/lib/CloseButton';
18
- import {
19
- LOGIN_PROVIDER,
20
- LOGIN_PROVIDER_NAME,
21
- OAUTH_PROVIDER,
22
- DID_CONNECT_MEDIUM_WIDTH,
23
- DID_CONNECT_SMALL_WIDTH,
24
- } from '@arcblock/ux/lib/Util/constant';
25
- import QRCode from '@arcblock/ux/lib/QRCode';
26
- import { DIDConnectFooter, withContainer, withUxTheme } from '@arcblock/ux/lib/DIDConnect';
27
- import { useTheme } from '@arcblock/ux/lib/Theme';
28
- import ProviderIcon from '@arcblock/ux/lib/DIDConnect/provider-icon';
29
-
30
- import '@fontsource/lexend/400.css';
31
- import '@fontsource/lexend/600.css';
1
+ import { lazy, Suspense } from 'react';
2
+ import { withContainer, withUxTheme } from '@arcblock/ux/lib/DIDConnect';
32
3
 
33
4
  import withBlocklet from './with-blocklet';
34
5
  import withBridgeCall from './with-bridge-call';
35
6
  import useSecurity from './hooks/security';
7
+ import FallbackConnect from './fallback-connect';
36
8
 
37
- import { SessionContext } from '../Session/context';
38
- import { StateProvider, useStateContext } from './contexts/state';
39
- import ConnectProviderList from './components/login-item/connect-provider-list';
40
- import AutoHeight from './components/auto-height';
41
- import useToken from './hooks/token';
42
- import { useOAuth } from '../OAuth';
43
- import ConnectStatus from './components/connect-status';
44
- import { usePasskey } from '../Passkey/context';
45
- import { API_DID_PREFIX, DEFAULT_TIMEOUT, BUSY_STATUS, CHECK_STATUS_INTERVAL } from '../constant';
46
- import { getWebWalletUrl } from '../utils';
47
- import DIDConnectTitle from './components/did-connect-title';
48
- import DownloadTips from './components/download-tips';
49
- import useProviderList from './hooks/provider-list';
50
- import useAuthUrl from './hooks/auth-url';
51
- import { getWalletDid } from '../User/use-did';
52
-
53
- function Connect({
54
- hideCloseButton = false,
55
- mode = 'dialog',
56
- action,
57
- baseUrl = '',
58
- checkFn,
59
- checkInterval = CHECK_STATUS_INTERVAL,
60
- checkTimeout = DEFAULT_TIMEOUT * 1000,
61
- prefix = API_DID_PREFIX,
62
- tokenKey = '_t_',
63
- locale = 'en',
64
- encKey = '_ek_',
65
- autoConnect = true,
66
- forceConnected = true,
67
- saveConnect = true,
68
- useSocket = true,
69
- allowWallet = true,
70
- provider = '',
71
- messages = {},
72
- passkeyBehavior = 'none',
73
- webWalletUrl = getWebWalletUrl(),
74
- enabledConnectTypes = ['web', 'mobile', ...Object.keys(OAUTH_PROVIDER)],
75
- extraContent = null,
76
- disableSwitchApp = false,
77
- magicToken = undefined,
78
- customItems = [],
79
- onClose = noop,
80
- onError = noop,
81
- onSuccess = noop,
82
- onRecreateSession = noop,
83
- setColor = noop,
84
- }) {
85
- const theme = useTheme();
86
- const forceUpdate = useUpdate();
87
- const sessionCtx = use(SessionContext);
88
- const currentUserDid = getWalletDid(sessionCtx?.session?.user);
89
-
90
- const {
91
- t,
92
- staticState,
93
- connectState,
94
- extraParams,
95
- currentAppInfo,
96
- currentAppColor,
97
- // 插件相关
98
- selectedPlugin,
99
- blocklet,
100
- masterBlocklet,
101
- showWalletOptions,
102
- setShowWalletOptions,
103
- } = useStateContext();
104
- const { state, generate, cancelWhenScanned } = useToken({
105
- action,
106
- baseUrl,
107
- checkFn,
108
- checkInterval,
109
- checkTimeout,
110
- extraParams,
111
- prefix,
112
- onError,
113
- onSuccess,
114
- locale,
115
- tokenKey,
116
- encKey,
117
- autoConnect,
118
- forceConnected: forceConnected === true ? currentUserDid || true : forceConnected,
119
- saveConnect,
120
- useSocket,
121
- allowWallet,
122
- provider,
123
- });
124
- const refreshingToken = useRef(false);
125
- const rootRef = useRef(null);
126
- const size = useSize(rootRef);
127
- const isSmallView = useCreation(() => {
128
- if (size) {
129
- return size.width < DID_CONNECT_MEDIUM_WIDTH - 50;
130
- }
131
- return true;
132
- }, [size, size?.width]);
133
-
134
- const [isInitSmallView, setIsInitSmallView] = useState(false);
135
-
136
- useMount(() => {
137
- setIsInitSmallView(size?.width < DID_CONNECT_MEDIUM_WIDTH - 50);
138
- });
139
-
140
- const { oauthState, setBaseUrl } = useOAuth();
141
- const { passkeyState, setTargetAppPid } = usePasskey();
142
-
143
- useMount(() => {
144
- setBaseUrl(baseUrl);
145
- setTargetAppPid(blocklet?.appPid);
146
- // 每次打开 did-connect,都重置状态
147
- state.reset();
148
- oauthState.reset();
149
- passkeyState.reset();
150
- });
151
-
152
- useEffect(() => {
153
- setColor(currentAppColor);
154
- // eslint-disable-next-line react-hooks/exhaustive-deps
155
- }, [currentAppColor]);
156
-
157
- const statusMessages = useCreation(() => {
158
- return {
159
- confirm: messages.confirm,
160
- success: messages.success,
161
- error: selectedPlugin?.state?.error || state.error || passkeyState.error || oauthState.error || '',
162
- };
163
- }, [
164
- messages.confirm,
165
- messages.success,
166
- state.error,
167
- oauthState.error,
168
- passkeyState.error,
169
- selectedPlugin?.state?.error,
170
- ]);
171
-
172
- const showStatus = useCreation(() => {
173
- return (
174
- BUSY_STATUS.includes(passkeyState.status) ||
175
- BUSY_STATUS.includes(oauthState.status) ||
176
- BUSY_STATUS.includes(state.status) ||
177
- BUSY_STATUS.includes(selectedPlugin?.state?.computedStatus)
178
- );
179
- }, [state.status, oauthState.status, passkeyState.status, selectedPlugin?.state?.computedStatus]);
180
-
181
- const handleReset = useMemoizedFn(async () => {
182
- onRecreateSession();
183
- oauthState.reset();
184
- passkeyState.reset();
185
- await generate(false);
186
- });
187
- const handleRetry = useMemoizedFn(() => {
188
- connectState?.retryConnect();
189
- });
190
- const handleCancel = useMemoizedFn(() => {
191
- onRecreateSession();
192
- oauthState.reset();
193
- passkeyState.reset();
194
- selectedPlugin?.state?.reset();
195
- staticState.current.cancelCount++;
196
- cancelWhenScanned();
197
- });
198
-
199
- const { run: debounceHandleTimeout } = useDebounceFn(
200
- () => {
201
- if (refreshingToken.current) return;
202
- if (state.status === 'timeout') {
203
- refreshingToken.current = true;
204
- state.reset();
205
- handleReset();
206
- refreshingToken.current = false;
207
- }
208
- },
209
- { leading: true, trailing: false }
210
- );
211
- // eslint-disable-next-line react-hooks/exhaustive-deps
212
- useEffect(debounceHandleTimeout, [state.status]);
213
-
214
- const chooseMethod = useCreation(() => {
215
- return LOGIN_PROVIDER_NAME[connectState.chooseMethod] || 'DID Wallet';
216
- }, [connectState.chooseMethod]);
217
-
218
- const { providerList, hideQRCode, hideChooseList } = useProviderList({
219
- action: state.action,
220
- sourceAppPid: connectState?.sourceAppPid,
221
- allowWallet,
222
- passkeyBehavior,
223
- webWalletUrl,
224
- mode,
225
- blocklet: connectState?.sourceAppPid ? masterBlocklet : blocklet,
226
- isSmallView,
227
- });
228
-
229
- const prevSourceAppPid = usePrevious(connectState?.sourceAppPid);
230
-
231
- // 切换了当前展示的应用后,需要重新生成二维码
232
- useUpdateEffect(() => {
233
- // HACK: connectState.sourceAppPid 是用户在页面中执行操作修改的值,最开始的时候就是 undefined,并在 did-connect 页面加载后,会由 app-info 触发一次更新(无论如何都会触发,这一次更新不应该触发 generate)
234
- if (isUndefined(prevSourceAppPid)) {
235
- return;
236
- }
237
- generate();
238
- }, [connectState?.sourceAppPid]);
239
-
240
- const getSpacingNumber = (value) => {
241
- const spacingValue = theme.spacing(value);
242
- return parseInt(spacingValue, 10);
243
- };
244
- const closeButton = useCreation(() => {
245
- return hideCloseButton ? null : (
246
- <CloseButton
247
- onClose={onClose}
248
- sx={{
249
- position: 'absolute',
250
- right: 14,
251
- top: 14,
252
- }}
253
- />
254
- );
255
- }, [hideCloseButton, onClose]);
256
-
257
- let content = null;
258
- if (showStatus) {
259
- content = (
260
- <Box
261
- sx={{
262
- flex: 1,
263
- display: 'flex',
264
- alignItems: 'center',
265
- justifyContent: 'center',
266
- }}>
267
- <Box>
268
- <ConnectStatus
269
- status={selectedPlugin?.state?.computedStatus || oauthState.status || passkeyState.status || state.status}
270
- nextWorkflow={state.nextWorkflow}
271
- mfaCode={state.mfaCode}
272
- onCancel={handleCancel}
273
- onRetry={handleRetry}
274
- onClose={onClose}
275
- messages={statusMessages}
276
- locale={locale}
277
- className="did-connect__auth-status auth-status"
278
- loadingIcon={
279
- connectState.chooseMethod ? (
280
- <ProviderIcon provider={connectState.chooseMethod} sx={{ color: 'text.primary' }} />
281
- ) : null
282
- }
283
- chooseMethod={chooseMethod}
284
- hideRetry={connectState.chooseMethod === 'email'}
285
- hideBack={!!magicToken}
286
- />
287
- </Box>
288
- </Box>
289
- );
290
- }
291
-
292
- const urlWithParams = useAuthUrl({ disableSwitchApp, tokenState: state });
293
-
294
- // 防止二维码抖动,使用 useCreation 进行缓存
295
- const qrcode = useCreation(() => {
296
- const backgroundColor = theme.mode === 'dark' ? theme.palette.grey[600] : 'white';
297
-
298
- let qrcodeSize = hideChooseList ? 240 - getSpacingNumber(3) * 2 : 196 - getSpacingNumber(2) * 2;
299
- let padding = hideChooseList ? 3 : 2;
300
- // 如果显示钱包登录,将 download tips 移动到顶部,调整间距,增加二维码的尺寸和内边距
301
- if (showWalletOptions) {
302
- padding = 1;
303
- qrcodeSize += getSpacingNumber(padding) * 2;
304
- }
305
- return (
306
- <Box
307
- className="did-connect__qrcode"
308
- sx={{
309
- p: padding,
310
- width: (hideChooseList ? 240 : 196) + getSpacingNumber(1) * 2,
311
- height: (hideChooseList ? 240 : 196) + getSpacingNumber(1) * 2,
312
- }}>
313
- {state.url ? (
314
- <QRCode
315
- data={urlWithParams}
316
- size={qrcodeSize}
317
- sx={{
318
- width: qrcodeSize + getSpacingNumber(1) * 2,
319
- height: qrcodeSize + getSpacingNumber(1) * 2,
320
- flex: 1,
321
- backgroundColor,
322
- p: 1,
323
- fontSize: 0,
324
- textAlign: 'center',
325
- boxSizing: 'border-box',
326
- borderRadius: 1,
327
- border: '1px solid',
328
- borderColor: 'divider',
329
- }}
330
- config={{
331
- backgroundOptions: {
332
- color: backgroundColor,
333
- },
334
- }}
335
- />
336
- ) : (
337
- <Skeleton
338
- animation="wave"
339
- variant="rectangular"
340
- sx={{
341
- position: 'absolute',
342
- left: getSpacingNumber(2) + 1,
343
- right: getSpacingNumber(2) + 1,
344
- top: getSpacingNumber(2) + 1,
345
- bottom: getSpacingNumber(2) + 1,
346
- borderRadius: 1,
347
- zIndex: 1,
348
- width: 'auto',
349
- height: 'auto',
350
- }}
351
- />
352
- )}
353
- </Box>
354
- );
355
- }, [urlWithParams, hideChooseList, showWalletOptions]);
356
-
357
- const didConnectFlexDirection = useCreation(() => {
358
- if (hideChooseList) {
359
- return 'column-reverse';
360
- }
361
- if (!hideQRCode && isInitSmallView) {
362
- return 'column';
363
- }
364
- return 'row';
365
- }, [hideChooseList, isInitSmallView, hideQRCode]);
366
-
367
- const qrcodeContent = useCreation(() => {
368
- if (!qrcode) return null;
369
- return (
370
- <Box
371
- sx={{
372
- display: 'flex',
373
- alignItems: 'center',
374
- overflowX: 'auto',
375
- overflowY: 'visible',
376
- maxWidth: '100%',
377
- margin: 'auto',
378
- }}>
379
- <Box
380
- sx={{
381
- fontSize: 0,
382
- position: 'relative',
383
- ...(showWalletOptions
384
- ? {
385
- mt: hideChooseList ? 4 : 2.5,
386
- mb: hideChooseList ? 0 : 0,
387
- }
388
- : {
389
- mb: hideChooseList ? 4 : 2.5,
390
- mt: 0,
391
- }),
392
- }}>
393
- {qrcode}
394
- <Box
395
- sx={{
396
- position: 'absolute',
397
- color: 'text.secondary',
398
- fontSize: 12,
399
- zIndex: 1,
400
- whiteSpace: 'nowrap',
401
- ...(showWalletOptions
402
- ? {
403
- top: hideChooseList ? -8 : -4,
404
- transform: 'translateY(-100%)',
405
- }
406
- : {
407
- bottom: hideChooseList ? -8 : -4,
408
- transform: 'translateY(100%)',
409
- }),
410
- left: 0,
411
- right: 0,
412
- textAlign: 'center',
413
- }}>
414
- {t('scanWithWallet1')} <DownloadTips /> {t('scanWithWallet2')}
415
- </Box>
416
- </Box>
417
- </Box>
418
- );
419
- }, [qrcode, hideChooseList, showWalletOptions]);
420
-
421
- const fallbackContent = (
422
- <Box
423
- className="did-connect__body"
424
- sx={{
425
- display: 'flex',
426
- flexDirection: didConnectFlexDirection,
427
- justifyContent: 'center',
428
- alignItems: 'stretch',
429
- flex: 1,
430
- gap: !hideQRCode && isSmallView ? 0 : 1.5,
431
- overflow: 'visible',
432
- px: hideChooseList ? 2 : 0,
433
- }}>
434
- {!showStatus && !hideQRCode ? (
435
- <>
436
- {qrcodeContent}
437
- {hideChooseList ? null : (
438
- <Box>
439
- <Divider
440
- orientation="vertical"
441
- sx={{
442
- fontSize: 12,
443
- color: 'text.hint',
444
- '&::before, &::after': {
445
- borderColor: 'divider',
446
- },
447
- }}>
448
- or
449
- </Divider>
450
- </Box>
451
- )}
452
- </>
453
- ) : null}
454
- <Box
455
- sx={{
456
- display: 'flex',
457
- flex: 1,
458
- }}>
459
- {/* eslint-disable-next-line no-nested-ternary */}
460
- {content}
461
- <ConnectProviderList
462
- slotProps={{
463
- root: {
464
- sx: [showStatus ? { display: 'none' } : {}],
465
- },
466
- }}
467
- allowWallet={allowWallet}
468
- size={hideQRCode && mode !== 'dialog' ? 'normal' : 'small'}
469
- tokenState={state}
470
- hideQRCode={hideQRCode}
471
- messages={messages}
472
- tokenKey={tokenKey}
473
- onSuccess={onSuccess}
474
- passkeyBehavior={passkeyBehavior}
475
- webWalletUrl={webWalletUrl}
476
- extraContent={extraContent}
477
- enabledConnectTypes={enabledConnectTypes}
478
- onReset={handleReset}
479
- disableSwitchApp={disableSwitchApp}
480
- forceUpdate={forceUpdate}
481
- magicToken={magicToken}
482
- baseUrl={baseUrl}
483
- customItems={customItems}
484
- providerList={providerList}
485
- qrcode={qrcodeContent}
486
- />
487
- </Box>
488
- </Box>
489
- );
490
- let contentResult = fallbackContent;
491
- if (selectedPlugin) {
492
- contentResult = selectedPlugin.renderPlaceholder({
493
- fallback: fallbackContent,
494
- forceUpdate,
495
- onSuccess,
496
- onError,
497
- });
498
- } else {
499
- contentResult = fallbackContent;
500
- }
501
-
502
- const containerWidth = hideQRCode || showStatus ? DID_CONNECT_SMALL_WIDTH : DID_CONNECT_MEDIUM_WIDTH;
9
+ const LazyConnect = lazy(() => import('./connect'));
503
10
 
11
+ function WrapConnect(props) {
504
12
  return (
505
- <Box
506
- ref={rootRef}
507
- className="did-connect__root"
508
- sx={{
509
- backgroundColor: 'background.default',
510
- display: 'flex',
511
- flexDirection: 'column',
512
- height: '100%',
513
- position: 'relative',
514
- maxWidth: '100%',
515
- width:
516
- // eslint-disable-next-line no-nested-ternary
517
- mode === 'drawer' ? '100%' : showWalletOptions ? containerWidth - 20 : containerWidth,
518
- transition: 'width 0.2s ease-in-out',
519
- margin: 'auto',
520
- p: 3,
521
- pb: 0,
522
- gap: 2.5,
523
- }}>
524
- <Box data-did-auth-url={state.url} sx={{ display: 'none' }} />
525
- <DIDConnectTitle
526
- title={messages.title}
527
- description={messages.scan}
528
- extraContent={extraContent}
529
- disableSwitchApp={disableSwitchApp}
530
- showWalletOptions={showWalletOptions}
531
- onBack={() => setShowWalletOptions(false)}
532
- />
533
- <AutoHeight initHeight={24 + 16 + 32}>{contentResult}</AutoHeight>
534
- <DIDConnectFooter currentAppInfo={currentAppInfo} currentAppColor={currentAppColor} />
535
- {closeButton}
536
- </Box>
13
+ <Suspense fallback={<FallbackConnect />}>
14
+ <LazyConnect {...props} />
15
+ </Suspense>
537
16
  );
538
17
  }
539
18
 
540
- Connect.propTypes = {
541
- mode: PropTypes.oneOf(['dialog', 'drawer', 'page']),
542
-
543
- action: PropTypes.string.isRequired,
544
- baseUrl: PropTypes.string,
545
- checkFn: PropTypes.func.isRequired,
546
- checkInterval: PropTypes.number,
547
- checkTimeout: PropTypes.number,
548
- // extraParams: PropTypes.object, // 需要使用 useStateContext 中导出的
549
- prefix: PropTypes.string,
550
- messages: PropTypes.object,
551
- tokenKey: PropTypes.string,
552
- locale: PropTypes.oneOf(['en', 'zh', '']),
553
- encKey: PropTypes.string,
554
- autoConnect: PropTypes.bool,
555
- forceConnected: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
556
- saveConnect: PropTypes.bool,
557
- useSocket: PropTypes.bool,
558
- extraContent: PropTypes.any,
559
- passkeyBehavior: PropTypes.oneOf(['none', 'both', 'only-existing', 'only-new']),
560
- enabledConnectTypes: PropTypes.arrayOf(PropTypes.oneOf(['web', 'mobile', ...Object.keys(OAUTH_PROVIDER)])),
561
- webWalletUrl: PropTypes.string,
562
-
563
- allowWallet: PropTypes.bool,
564
- provider: PropTypes.oneOf([LOGIN_PROVIDER.WALLET, ...Object.keys(OAUTH_PROVIDER), '']),
565
- hideCloseButton: PropTypes.bool,
566
- disableSwitchApp: PropTypes.bool,
567
- onClose: PropTypes.func,
568
- onError: PropTypes.func,
569
- onSuccess: PropTypes.func,
570
- onRecreateSession: PropTypes.func,
571
- setColor: PropTypes.func,
572
- magicToken: PropTypes.string,
573
- customItems: PropTypes.arrayOf(PropTypes.node),
574
- };
575
-
576
- function WrapConnect({ testOnlyBorderColor = undefined, ...props }) {
577
- const { checkFn, extraParams = {}, blocklet, masterBlocklet, action, locale = 'en' } = props;
578
- if (typeof checkFn !== 'function') {
579
- throw new Error('Cannot initialize did connect component without a fetchFn');
580
- }
581
-
582
- return (
583
- <StateProvider
584
- blocklet={blocklet}
585
- masterBlocklet={masterBlocklet}
586
- action={action}
587
- locale={locale}
588
- extraParams={extraParams}
589
- testOnlyBorderColor={testOnlyBorderColor}
590
- sx={{
591
- position: 'relative',
592
- width: '100%',
593
- height: '100%',
594
- lineHeight: 1.2,
595
- color: 'grey.700',
596
- '&, & *, & *:before, & *:after': {
597
- fontFamily: 'Lexend', // 保持跟 DID Wallet 一致
598
- boxSizing: 'border-box',
599
- },
600
- }}>
601
- <Connect {...props} />
602
- </StateProvider>
603
- );
604
- }
605
-
606
- WrapConnect.propTypes = {
607
- checkFn: PropTypes.func.isRequired,
608
- extraParams: PropTypes.object,
609
- blocklet: PropTypes.object.isRequired,
610
- masterBlocklet: PropTypes.object,
611
- action: PropTypes.string.isRequired,
612
- locale: PropTypes.string,
613
- testOnlyBorderColor: PropTypes.string,
614
- };
615
-
616
19
  export default withUxTheme(withBridgeCall(withBlocklet(withContainer(WrapConnect))));
617
20
 
618
21
  export { useSecurity };
@@ -8,9 +8,9 @@ import LoginMethodItem from '../../components/login-item/login-method-item';
8
8
  import { useStateContext } from '../../contexts/state';
9
9
 
10
10
  export default function EmailListItem({ ...rest }) {
11
- const { setSelectedPlugin, getPlugin, connectState } = useStateContext();
11
+ const { setSelectedPlugin, getPlugin, connectState, lastLoginMethod } = useStateContext();
12
12
  const handleConnect = useMemoizedFn(() => {
13
- localStorage.setItem(GA_LAST_LOGIN_METHOD, 'email');
13
+ localStorage.setItem(GA_LAST_LOGIN_METHOD, LOGIN_PROVIDER.EMAIL);
14
14
  const plugin = getPlugin(LOGIN_PROVIDER.EMAIL);
15
15
  plugin.state.reset();
16
16
  plugin.state.status = 'creating';
@@ -21,6 +21,7 @@ export default function EmailListItem({ ...rest }) {
21
21
  return (
22
22
  <LoginMethodItem
23
23
  {...rest}
24
+ isLatest={lastLoginMethod && lastLoginMethod === LOGIN_PROVIDER.EMAIL}
24
25
  title={LOGIN_PROVIDER_NAME[LOGIN_PROVIDER.EMAIL]}
25
26
  icon={mailFilledIcon}
26
27
  onClick={handleConnect}
@@ -6,12 +6,12 @@ import cloneDeep from 'lodash/cloneDeep';
6
6
  import isFunction from 'lodash/isFunction';
7
7
  import isUndefined from 'lodash/isUndefined';
8
8
  import { joinURL, withQuery } from 'ufo';
9
- import { getFederatedEnabled, getMaster } from '@arcblock/ux/lib/Util/federated';
10
9
  import PQueue from 'p-queue';
11
10
  import { useTheme } from '@arcblock/ux/lib/Theme';
12
11
  import { getCookieOptions } from '@arcblock/ux/lib/Util';
13
12
  import Cookie from 'js-cookie';
14
13
  import { useBrowser } from '@arcblock/react-hooks';
14
+ import { getFederatedEnabled, getMaster } from '@arcblock/ux/lib/Util/federated';
15
15
 
16
16
  import { SessionContext } from '../Session/context';
17
17
  import { runPopup, openPopup, updateConnectedInfo, getAppId } from '../utils';
@@ -67,6 +67,7 @@ export default function PasskeyActions({
67
67
  sx = {},
68
68
  mode = 'normal',
69
69
  onClick = noop,
70
+ isLatest = false,
70
71
  }) {
71
72
  const currentAction = useRef('');
72
73
  const passkeyDialogRef = useRef(null);
@@ -149,6 +150,8 @@ export default function PasskeyActions({
149
150
  <>
150
151
  {['both', 'only-existing'].includes(behavior) ? (
151
152
  <PasskeyAction
153
+ isLatest={isLatest}
154
+ t={t}
152
155
  action="verifying"
153
156
  state={passkeyState}
154
157
  title={t('usePasskey')}
@@ -167,6 +170,7 @@ export default function PasskeyActions({
167
170
  {['both', 'only-new'].includes(behavior) ? (
168
171
  <>
169
172
  <PasskeyAction
173
+ t={t}
170
174
  action="creating"
171
175
  state={passkeyState}
172
176
  title={createButtonText || t('createPasskey')}
@@ -209,4 +213,5 @@ PasskeyActions.propTypes = {
209
213
  mode: PropTypes.oneOf(['simple', 'normal']),
210
214
  onClick: PropTypes.func,
211
215
  ref: PropTypes.any,
216
+ isLatest: PropTypes.bool,
212
217
  };