@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.
- package/lib/Connect/assets/locale.js +4 -2
- package/lib/Connect/components/login-item/connect-choose-list.js +120 -114
- package/lib/Connect/components/login-item/connect-provider-list.js +187 -180
- package/lib/Connect/components/login-item/login-method-item.js +63 -47
- package/lib/Connect/components/login-item/passkey-login-item.js +17 -15
- package/lib/Connect/components/login-item/wallet-login-options.js +42 -40
- package/lib/Connect/connect.js +88 -86
- package/lib/Connect/contexts/state.js +73 -64
- package/lib/Connect/hooks/provider-list.js +43 -33
- package/lib/Connect/plugins/email/list-item.js +19 -18
- package/lib/Passkey/actions.js +80 -75
- package/lib/package.json.js +1 -1
- package/package.json +5 -5
- package/src/Connect/assets/locale.js +2 -0
- package/src/Connect/components/login-item/connect-choose-list.jsx +12 -5
- package/src/Connect/components/login-item/connect-provider-list.jsx +11 -4
- package/src/Connect/components/login-item/login-method-item.jsx +24 -7
- package/src/Connect/components/login-item/passkey-login-item.jsx +3 -1
- package/src/Connect/components/login-item/wallet-login-options.jsx +3 -2
- package/src/Connect/connect.jsx +2 -0
- package/src/Connect/contexts/state.jsx +10 -0
- package/src/Connect/hooks/provider-list.js +43 -17
- package/src/Connect/plugins/email/list-item.jsx +3 -2
- package/src/Passkey/actions.jsx +5 -0
|
@@ -1,56 +1,66 @@
|
|
|
1
|
-
import { useBrowser as
|
|
2
|
-
import { useRequest as
|
|
3
|
-
import
|
|
4
|
-
import { LOGIN_PROVIDER as
|
|
5
|
-
import { getFederatedEnabled as
|
|
6
|
-
import { useState as
|
|
7
|
-
const
|
|
1
|
+
import { useBrowser as k } from "@arcblock/react-hooks";
|
|
2
|
+
import { useRequest as y, useCreation as L } from "ahooks";
|
|
3
|
+
import n from "lodash/isNil";
|
|
4
|
+
import { LOGIN_PROVIDER as s } from "@arcblock/ux/lib/Util/constant";
|
|
5
|
+
import { getFederatedEnabled as A, getMaster as C, getBlockletData as T } from "@arcblock/ux/lib/Util/federated";
|
|
6
|
+
import { useState as I } from "react";
|
|
7
|
+
const S = async ({ sourceAppPid: a }) => {
|
|
8
8
|
const t = globalThis?.blocklet;
|
|
9
9
|
if (!t)
|
|
10
10
|
return {
|
|
11
|
-
[
|
|
11
|
+
[s.WALLET]: {
|
|
12
12
|
order: 0,
|
|
13
13
|
enabled: !0,
|
|
14
14
|
showQrcode: !0
|
|
15
15
|
},
|
|
16
|
-
[
|
|
16
|
+
[s.PASSKEY]: {
|
|
17
17
|
order: 1,
|
|
18
18
|
enabled: !0
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
-
const
|
|
22
|
-
return
|
|
23
|
-
},
|
|
24
|
-
const t = await
|
|
25
|
-
return Object.entries(t).map(([e,
|
|
21
|
+
const l = A(t), e = C(t);
|
|
22
|
+
return l && e?.appPid && a === e?.appPid ? (await T(e.appUrl))?.settings?.authentication || {} : t?.settings?.authentication || {};
|
|
23
|
+
}, B = async ({ sourceAppPid: a } = {}) => {
|
|
24
|
+
const t = await S({ sourceAppPid: a });
|
|
25
|
+
return Object.entries(t).map(([e, o]) => ({ ...o, provider: e })).filter((e) => e.enabled).sort((e, o) => !n(e?.order) && !n(o?.order) ? e.order - o.order : n(e?.order) ? 1 : -1);
|
|
26
26
|
};
|
|
27
|
-
function
|
|
28
|
-
allowWallet:
|
|
27
|
+
function Y({
|
|
28
|
+
allowWallet: a = !0,
|
|
29
29
|
passkeyBehavior: t = "none",
|
|
30
|
-
action:
|
|
30
|
+
action: l,
|
|
31
31
|
sourceAppPid: e,
|
|
32
|
-
mode:
|
|
33
|
-
blocklet:
|
|
34
|
-
isSmallView:
|
|
32
|
+
mode: o = "dialog",
|
|
33
|
+
blocklet: b = globalThis.blocklet,
|
|
34
|
+
isSmallView: p = !1,
|
|
35
|
+
lastLoginMethod: u = ""
|
|
35
36
|
}) {
|
|
36
|
-
const [
|
|
37
|
+
const [P, g] = I(!1), w = ["login", "invite", "connect-to-did-space", "connect-to-did-domain", "destroy-self"], c = k(), { data: h = [] } = y(
|
|
37
38
|
async () => {
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
return
|
|
39
|
+
g(!0);
|
|
40
|
+
const d = await B({ sourceAppPid: e });
|
|
41
|
+
return g(!1), d;
|
|
41
42
|
},
|
|
42
43
|
{ refreshDeps: [e] }
|
|
43
|
-
),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
), f = L(() => h.filter((r) => r.name === s.WALLET ? a : r.name === s.PASSKEY ? t !== "none" && !c.wallet && !c.arcSphere : r.name === s.EMAIL ? b?.settings?.notification?.email?.enabled ?? !1 : !(r.type === "oauth" && !w.includes(l))).sort((r, i) => {
|
|
45
|
+
if (u) {
|
|
46
|
+
const m = r.provider === u, v = i.provider === u;
|
|
47
|
+
if (m && !v)
|
|
48
|
+
return -1;
|
|
49
|
+
if (!m && v)
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
return !n(r?.order) && !n(i?.order) ? r.order - i.order : n(r?.order) ? n(i?.order) ? 0 : 1 : -1;
|
|
53
|
+
}), [h, u]), E = L(() => {
|
|
54
|
+
const d = o === "drawer" || p && c.mobile.any;
|
|
55
|
+
return globalThis?.blocklet ? !!(f.find((i) => i.provider === s.WALLET)?.showQrcode !== !0 || d) : !!d;
|
|
56
|
+
}, [o, p, f]);
|
|
47
57
|
return {
|
|
48
|
-
hideChooseList:
|
|
49
|
-
hideQRCode:
|
|
50
|
-
providerList:
|
|
51
|
-
loadingProviderList:
|
|
58
|
+
hideChooseList: L(() => !1),
|
|
59
|
+
hideQRCode: E,
|
|
60
|
+
providerList: f,
|
|
61
|
+
loadingProviderList: P
|
|
52
62
|
};
|
|
53
63
|
}
|
|
54
64
|
export {
|
|
55
|
-
|
|
65
|
+
Y as default
|
|
56
66
|
};
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import
|
|
3
|
-
import { useMemoizedFn as
|
|
1
|
+
import { jsx as c } from "react/jsx-runtime";
|
|
2
|
+
import l from "prop-types";
|
|
3
|
+
import { useMemoizedFn as a } from "ahooks";
|
|
4
4
|
import p from "@iconify-icons/tabler/mail-filled";
|
|
5
|
-
import { LOGIN_PROVIDER as
|
|
6
|
-
import { GA_LAST_LOGIN_METHOD as
|
|
5
|
+
import { LOGIN_PROVIDER as t, LOGIN_PROVIDER_NAME as I } from "@arcblock/ux/lib/Util/constant";
|
|
6
|
+
import { GA_LAST_LOGIN_METHOD as L } from "@arcblock/ux/lib/withTracker/constant";
|
|
7
7
|
import f from "../../components/login-item/login-method-item.js";
|
|
8
|
-
import { useStateContext as
|
|
9
|
-
function
|
|
10
|
-
const { setSelectedPlugin:
|
|
11
|
-
localStorage.setItem(
|
|
12
|
-
const
|
|
13
|
-
|
|
8
|
+
import { useStateContext as M } from "../../contexts/state.js";
|
|
9
|
+
function u({ ...i }) {
|
|
10
|
+
const { setSelectedPlugin: n, getPlugin: r, connectState: m, lastLoginMethod: e } = M(), s = a(() => {
|
|
11
|
+
localStorage.setItem(L, t.EMAIL);
|
|
12
|
+
const o = r(t.EMAIL);
|
|
13
|
+
o.state.reset(), o.state.status = "creating", m.chooseMethod = t.EMAIL, n(o);
|
|
14
14
|
});
|
|
15
|
-
return /* @__PURE__ */
|
|
15
|
+
return /* @__PURE__ */ c(
|
|
16
16
|
f,
|
|
17
17
|
{
|
|
18
|
-
...
|
|
19
|
-
|
|
18
|
+
...i,
|
|
19
|
+
isLatest: e && e === t.EMAIL,
|
|
20
|
+
title: I[t.EMAIL],
|
|
20
21
|
icon: p,
|
|
21
|
-
onClick:
|
|
22
|
+
onClick: s
|
|
22
23
|
}
|
|
23
24
|
);
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
-
onClick:
|
|
26
|
+
u.propTypes = {
|
|
27
|
+
onClick: l.func
|
|
27
28
|
};
|
|
28
29
|
export {
|
|
29
|
-
|
|
30
|
+
u as default
|
|
30
31
|
};
|
package/lib/Passkey/actions.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { jsxs as q, Fragment as D, jsx as n } from "react/jsx-runtime";
|
|
2
|
-
import { useRef as I, useEffect as
|
|
2
|
+
import { useRef as I, useEffect as L, useImperativeHandle as M } from "react";
|
|
3
3
|
import z from "lodash/trim";
|
|
4
4
|
import e from "prop-types";
|
|
5
5
|
import k from "js-cookie";
|
|
6
|
-
import { CircularProgress as
|
|
6
|
+
import { CircularProgress as B } from "@mui/material";
|
|
7
7
|
import { Icon as S } from "@iconify/react";
|
|
8
|
-
import { getCookieOptions as
|
|
8
|
+
import { getCookieOptions as H } from "@arcblock/ux/lib/Util";
|
|
9
9
|
import { useMemoizedFn as v } from "ahooks";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import { mergeSx as
|
|
14
|
-
import { usePasskey as
|
|
15
|
-
import { logger as
|
|
16
|
-
import
|
|
17
|
-
import
|
|
10
|
+
import V from "@iconify-icons/material-symbols/passkey-rounded";
|
|
11
|
+
import $ from "@iconify-icons/material-symbols/person-add-rounded";
|
|
12
|
+
import G from "lodash/noop";
|
|
13
|
+
import { mergeSx as K } from "@arcblock/ux/lib/Util/style";
|
|
14
|
+
import { usePasskey as N } from "./context.js";
|
|
15
|
+
import { logger as W, getWebAuthnErrorMessage as Y } from "../utils.js";
|
|
16
|
+
import J from "../Connect/components/login-item/login-method-item.js";
|
|
17
|
+
import Q from "./dialog.js";
|
|
18
18
|
import { VERIFY_CODE_LENGTH as w } from "./constants.js";
|
|
19
|
-
function x({ action: d, onClick:
|
|
19
|
+
function x({ action: d, onClick: c, title: s, state: f, dense: l = !1, icon: u, ...m }) {
|
|
20
20
|
return /* @__PURE__ */ n(
|
|
21
|
-
|
|
21
|
+
J,
|
|
22
22
|
{
|
|
23
|
-
...
|
|
24
|
-
icon:
|
|
25
|
-
|
|
23
|
+
...m,
|
|
24
|
+
icon: f[d] ? /* @__PURE__ */ n(
|
|
25
|
+
B,
|
|
26
26
|
{
|
|
27
27
|
size: "1em",
|
|
28
28
|
sx: {
|
|
@@ -32,11 +32,11 @@ function x({ action: d, onClick: a, title: i, state: c, dense: f = !1, icon: l,
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
) :
|
|
35
|
+
) : u,
|
|
36
36
|
iconScale: 1,
|
|
37
|
-
title:
|
|
38
|
-
onClick:
|
|
39
|
-
sx:
|
|
37
|
+
title: s,
|
|
38
|
+
onClick: c,
|
|
39
|
+
sx: K(l ? { p: 1, backgroundColor: "transparent" } : {}, m?.sx)
|
|
40
40
|
}
|
|
41
41
|
);
|
|
42
42
|
}
|
|
@@ -48,104 +48,108 @@ x.propTypes = {
|
|
|
48
48
|
dense: e.bool,
|
|
49
49
|
icon: e.any.isRequired
|
|
50
50
|
};
|
|
51
|
-
function
|
|
51
|
+
function U({
|
|
52
52
|
ref: d = null,
|
|
53
|
-
action:
|
|
54
|
-
behavior:
|
|
55
|
-
onSuccess:
|
|
56
|
-
onError:
|
|
57
|
-
extraParams:
|
|
58
|
-
createButtonText:
|
|
53
|
+
action: c,
|
|
54
|
+
behavior: s = "none",
|
|
55
|
+
onSuccess: f,
|
|
56
|
+
onError: l,
|
|
57
|
+
extraParams: u = {},
|
|
58
|
+
createButtonText: m = "",
|
|
59
59
|
createMode: T = "register",
|
|
60
60
|
dense: P = !1,
|
|
61
61
|
slotProps: R = {},
|
|
62
|
-
sx:
|
|
63
|
-
mode:
|
|
64
|
-
onClick: E =
|
|
62
|
+
sx: b = {},
|
|
63
|
+
mode: h = "normal",
|
|
64
|
+
onClick: E = G,
|
|
65
|
+
isLatest: j = !1
|
|
65
66
|
}) {
|
|
66
|
-
const
|
|
67
|
+
const p = I(""), C = I(null), { t: i, loginPasskey: O, logoutPasskey: _, passkeyState: o } = N(), A = v(async (a = "") => {
|
|
67
68
|
try {
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
...
|
|
71
|
-
action:
|
|
72
|
-
credentialId:
|
|
73
|
-
}), t =
|
|
74
|
-
k.remove("connected_did", t), k.remove("connected_pk", t), k.remove("connected_wallet_os", t),
|
|
75
|
-
} catch (
|
|
76
|
-
|
|
77
|
-
const t =
|
|
78
|
-
|
|
69
|
+
o.verifying = !0, o.error = "", a || (o.verifyingStatus = "");
|
|
70
|
+
const r = await O({
|
|
71
|
+
...u,
|
|
72
|
+
action: c,
|
|
73
|
+
credentialId: a
|
|
74
|
+
}), t = H({ expireInDays: 7 });
|
|
75
|
+
k.remove("connected_did", t), k.remove("connected_pk", t), k.remove("connected_wallet_os", t), o.verifying = !1, r?.sessionToken && (await f({ ...r, encrypted: !1 }, (F) => F), o.verifyingStatus = "succeed");
|
|
76
|
+
} catch (r) {
|
|
77
|
+
W.error("Failed to verify passkey", r);
|
|
78
|
+
const t = Y(r, i("verifyPasskeyFailed"), i);
|
|
79
|
+
o.verifying = !1, o.error = t, o.verifyingStatus = "error", await _(), l(new Error(t));
|
|
79
80
|
}
|
|
80
81
|
}), y = v(
|
|
81
|
-
(
|
|
82
|
-
if (!
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
if (!/^\d+$/.test(
|
|
86
|
-
|
|
87
|
-
const t = document.getElementById(`code-input-${
|
|
82
|
+
(a) => {
|
|
83
|
+
if (!o.sent) return;
|
|
84
|
+
a.preventDefault();
|
|
85
|
+
const r = z(a.clipboardData.getData("text/plain").slice(0, w));
|
|
86
|
+
if (!/^\d+$/.test(r)) return;
|
|
87
|
+
o.code = r.padEnd(w, " ");
|
|
88
|
+
const t = document.getElementById(`code-input-${r.length}`);
|
|
88
89
|
t && t.focus();
|
|
89
90
|
},
|
|
90
|
-
[
|
|
91
|
+
[o]
|
|
91
92
|
);
|
|
92
|
-
|
|
93
|
+
L(() => (document.addEventListener("paste", y), () => {
|
|
93
94
|
document.removeEventListener("paste", y);
|
|
94
95
|
}), [y]);
|
|
95
96
|
const g = v(() => {
|
|
96
|
-
|
|
97
|
+
p.current === "verifying" ? A() : p.current === "creating" && C.current.open();
|
|
97
98
|
});
|
|
98
99
|
return M(d, () => ({
|
|
99
100
|
click: g
|
|
100
|
-
})),
|
|
101
|
-
["both", "only-existing"].includes(
|
|
101
|
+
})), s === "none" ? null : /* @__PURE__ */ q(D, { children: [
|
|
102
|
+
["both", "only-existing"].includes(s) ? /* @__PURE__ */ n(
|
|
102
103
|
x,
|
|
103
104
|
{
|
|
105
|
+
isLatest: j,
|
|
106
|
+
t: i,
|
|
104
107
|
action: "verifying",
|
|
105
|
-
state:
|
|
106
|
-
title:
|
|
108
|
+
state: o,
|
|
109
|
+
title: i("usePasskey"),
|
|
107
110
|
onClick: () => {
|
|
108
|
-
|
|
111
|
+
p.current = "verifying", g(), E();
|
|
109
112
|
},
|
|
110
113
|
dense: P,
|
|
111
114
|
slotProps: R,
|
|
112
|
-
sx:
|
|
113
|
-
mode:
|
|
114
|
-
icon: /* @__PURE__ */ n(S, { icon:
|
|
115
|
+
sx: b,
|
|
116
|
+
mode: h,
|
|
117
|
+
icon: /* @__PURE__ */ n(S, { icon: V, fontSize: "1em" })
|
|
115
118
|
}
|
|
116
119
|
) : null,
|
|
117
|
-
["both", "only-new"].includes(
|
|
120
|
+
["both", "only-new"].includes(s) ? /* @__PURE__ */ q(D, { children: [
|
|
118
121
|
/* @__PURE__ */ n(
|
|
119
122
|
x,
|
|
120
123
|
{
|
|
124
|
+
t: i,
|
|
121
125
|
action: "creating",
|
|
122
|
-
state:
|
|
123
|
-
title:
|
|
126
|
+
state: o,
|
|
127
|
+
title: m || i("createPasskey"),
|
|
124
128
|
onClick: () => {
|
|
125
|
-
|
|
129
|
+
p.current = "creating", g(), E();
|
|
126
130
|
},
|
|
127
131
|
dense: P,
|
|
128
132
|
slotProps: R,
|
|
129
|
-
sx:
|
|
130
|
-
mode:
|
|
131
|
-
icon: /* @__PURE__ */ n(S, { icon:
|
|
133
|
+
sx: b,
|
|
134
|
+
mode: h,
|
|
135
|
+
icon: /* @__PURE__ */ n(S, { icon: $, fontSize: "1em" })
|
|
132
136
|
}
|
|
133
137
|
),
|
|
134
138
|
/* @__PURE__ */ n(
|
|
135
|
-
|
|
139
|
+
Q,
|
|
136
140
|
{
|
|
137
141
|
ref: C,
|
|
138
|
-
action:
|
|
142
|
+
action: c,
|
|
139
143
|
createMode: T,
|
|
140
|
-
extraParams:
|
|
141
|
-
onSuccess:
|
|
142
|
-
onError:
|
|
144
|
+
extraParams: u,
|
|
145
|
+
onSuccess: f,
|
|
146
|
+
onError: l
|
|
143
147
|
}
|
|
144
148
|
)
|
|
145
149
|
] }) : null
|
|
146
150
|
] });
|
|
147
151
|
}
|
|
148
|
-
|
|
152
|
+
U.propTypes = {
|
|
149
153
|
action: e.string.isRequired,
|
|
150
154
|
onSuccess: e.func.isRequired,
|
|
151
155
|
onError: e.func.isRequired,
|
|
@@ -158,8 +162,9 @@ Q.propTypes = {
|
|
|
158
162
|
sx: e.oneOfType([e.object, e.array]),
|
|
159
163
|
mode: e.oneOf(["simple", "normal"]),
|
|
160
164
|
onClick: e.func,
|
|
161
|
-
ref: e.any
|
|
165
|
+
ref: e.any,
|
|
166
|
+
isLatest: e.bool
|
|
162
167
|
};
|
|
163
168
|
export {
|
|
164
|
-
|
|
169
|
+
U as default
|
|
165
170
|
};
|
package/lib/package.json.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcblock/did-connect-react",
|
|
3
|
-
"version": "3.4.
|
|
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,10 +32,10 @@
|
|
|
32
32
|
"url": "https://github.com/ArcBlock/ux/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@arcblock/bridge": "3.4.
|
|
35
|
+
"@arcblock/bridge": "3.4.1",
|
|
36
36
|
"@arcblock/did": "^1.28.1",
|
|
37
|
-
"@arcblock/icons": "3.4.
|
|
38
|
-
"@arcblock/react-hooks": "3.4.
|
|
37
|
+
"@arcblock/icons": "3.4.1",
|
|
38
|
+
"@arcblock/react-hooks": "3.4.1",
|
|
39
39
|
"@arcblock/ws": "^1.28.1",
|
|
40
40
|
"@blocklet/constant": "^1.17.7",
|
|
41
41
|
"@fontsource/lexend": "^5.2.9",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
82
82
|
"jest": "^29.7.0"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
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 } =
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
};
|