@arcblock/did-connect-react 3.4.0 → 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.
@@ -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}
@@ -97,6 +97,7 @@ function Connect({
97
97
  masterBlocklet,
98
98
  showWalletOptions,
99
99
  setShowWalletOptions,
100
+ lastLoginMethod,
100
101
  } = useStateContext();
101
102
  const { state, generate, cancelWhenScanned } = useToken({
102
103
  action,
@@ -221,6 +222,7 @@ function Connect({
221
222
  mode,
222
223
  blocklet: connectState?.sourceAppPid ? masterBlocklet : blocklet,
223
224
  isSmallView,
225
+ lastLoginMethod,
224
226
  });
225
227
 
226
228
  const prevSourceAppPid = usePrevious(connectState?.sourceAppPid);
@@ -9,6 +9,7 @@ import { translate } from '@arcblock/ux/lib/Locale/util';
9
9
  import { getCurrentApp, getMaster } from '@arcblock/ux/lib/Util/federated';
10
10
  import { getDIDMotifInfo } from '@arcblock/did-motif';
11
11
  import { getDIDColor, isEthereumDid } from '@arcblock/ux/lib/Util';
12
+ import { GA_LAST_LOGIN_METHOD } from '@arcblock/ux/lib/withTracker/constant';
12
13
 
13
14
  import useApps from '../hooks/use-apps';
14
15
  import { SessionContext } from '../../Session/context';
@@ -68,6 +69,13 @@ function StateProvider({
68
69
  sourceAppPid: extraParams?.sourceAppPid,
69
70
  enableSwitchApp: extraParams?.forceSwitch || extraParams?.enableSwitchApp,
70
71
  });
72
+ const lastLoginMethod = useCreation(() => {
73
+ try {
74
+ return localStorage.getItem(GA_LAST_LOGIN_METHOD);
75
+ } catch (error) {
76
+ return '';
77
+ }
78
+ }, []);
71
79
 
72
80
  const rootRef = useRef(null);
73
81
  const size = useSize(rootRef);
@@ -180,6 +188,8 @@ function StateProvider({
180
188
  // 控制钱包登录的显示
181
189
  showWalletOptions,
182
190
  setShowWalletOptions,
191
+ // 用于记录上一次登录方式
192
+ lastLoginMethod,
183
193
  };
184
194
  }, [
185
195
  browser.wallet,
@@ -56,6 +56,7 @@ export default function useProviderList({
56
56
  mode = 'dialog',
57
57
  blocklet = globalThis.blocklet,
58
58
  isSmallView = false,
59
+ lastLoginMethod = '',
59
60
  }) {
60
61
  const [loadingProviderList, setLoadingProviderList] = useState(false);
61
62
  const actionList = ['login', 'invite', 'connect-to-did-space', 'connect-to-did-domain', 'destroy-self'];
@@ -72,26 +73,51 @@ export default function useProviderList({
72
73
  );
73
74
 
74
75
  const showedLoginProviderList = useCreation(() => {
75
- const result = loginProviderList.filter((item) => {
76
- if (item.name === LOGIN_PROVIDER.WALLET) {
77
- return allowWallet;
78
- }
79
- if (item.name === LOGIN_PROVIDER.PASSKEY) {
80
- return passkeyBehavior !== 'none' && !browser.wallet && !browser.arcSphere;
81
- }
82
- if (item.name === LOGIN_PROVIDER.EMAIL) {
83
- return blocklet?.settings?.notification?.email?.enabled ?? false;
84
- }
76
+ const result = loginProviderList
77
+ .filter((item) => {
78
+ if (item.name === LOGIN_PROVIDER.WALLET) {
79
+ return allowWallet;
80
+ }
81
+ if (item.name === LOGIN_PROVIDER.PASSKEY) {
82
+ return passkeyBehavior !== 'none' && !browser.wallet && !browser.arcSphere;
83
+ }
84
+ if (item.name === LOGIN_PROVIDER.EMAIL) {
85
+ return blocklet?.settings?.notification?.email?.enabled ?? false;
86
+ }
85
87
 
86
- if (item.type === 'oauth') {
87
- if (!actionList.includes(action)) {
88
- return false;
88
+ if (item.type === 'oauth') {
89
+ if (!actionList.includes(action)) {
90
+ return false;
91
+ }
89
92
  }
90
- }
91
- return true;
92
- });
93
+ return true;
94
+ })
95
+ .sort((a, b) => {
96
+ // 优先处理 lastLoginMethod:匹配的项目排在最前面
97
+ if (lastLoginMethod) {
98
+ const aIsLastMethod = a.provider === lastLoginMethod;
99
+ const bIsLastMethod = b.provider === lastLoginMethod;
100
+ if (aIsLastMethod && !bIsLastMethod) {
101
+ return -1;
102
+ }
103
+ if (!aIsLastMethod && bIsLastMethod) {
104
+ return 1;
105
+ }
106
+ }
107
+ // 然后按照 order 属性排序
108
+ if (!isNil(a?.order) && !isNil(b?.order)) {
109
+ return a.order - b.order;
110
+ }
111
+ if (!isNil(a?.order)) {
112
+ return -1;
113
+ }
114
+ if (!isNil(b?.order)) {
115
+ return 1;
116
+ }
117
+ return 0;
118
+ });
93
119
  return result;
94
- }, [loginProviderList]);
120
+ }, [loginProviderList, lastLoginMethod]);
95
121
 
96
122
  const hideQRCode = useCreation(() => {
97
123
  const isMobileView = mode === 'drawer' || (isSmallView && browser.mobile.any);
@@ -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}
@@ -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
  };