diff --git a/fluxer_app/src/components/modals/tabs/AccountSecurityTab.tsx b/fluxer_app/src/components/modals/tabs/AccountSecurityTab.tsx index c51aaf8c..93a84498 100644 --- a/fluxer_app/src/components/modals/tabs/AccountSecurityTab.tsx +++ b/fluxer_app/src/components/modals/tabs/AccountSecurityTab.tsx @@ -37,6 +37,7 @@ const AccountSecurityTab: React.FC = observer(() => { const {t} = useLingui(); const user = UserStore.currentUser; const [showMaskedEmail, setShowMaskedEmail] = useState(false); + const [showMaskedPhone, setShowMaskedPhone] = useState(false); const [passkeys, setPasskeys] = useState>([]); const [loadingPasskeys, setLoadingPasskeys] = useState(false); const [enablingSmsMfa, setEnablingSmsMfa] = useState(false); @@ -100,9 +101,11 @@ const AccountSecurityTab: React.FC = observer(() => { loadingPasskeys={loadingPasskeys} enablingSmsMfa={enablingSmsMfa} disablingSmsMfa={disablingSmsMfa} + showMaskedPhone={showMaskedPhone} loadPasskeys={loadPasskeys} setEnablingSmsMfa={setEnablingSmsMfa} setDisablingSmsMfa={setDisablingSmsMfa} + setShowMaskedPhone={setShowMaskedPhone} /> diff --git a/fluxer_app/src/components/modals/tabs/account_security_tab/Inline.tsx b/fluxer_app/src/components/modals/tabs/account_security_tab/Inline.tsx index 640ad9e7..aae4655e 100644 --- a/fluxer_app/src/components/modals/tabs/account_security_tab/Inline.tsx +++ b/fluxer_app/src/components/modals/tabs/account_security_tab/Inline.tsx @@ -36,6 +36,7 @@ export const AccountSecurityInlineTab = observer(() => { const {t} = useLingui(); const user = UserStore.currentUser; const [showMaskedEmail, setShowMaskedEmail] = useState(false); + const [showMaskedPhone, setShowMaskedPhone] = useState(false); const [passkeys, setPasskeys] = useState>([]); const [loadingPasskeys, setLoadingPasskeys] = useState(false); const [enablingSmsMfa, setEnablingSmsMfa] = useState(false); @@ -89,9 +90,11 @@ export const AccountSecurityInlineTab = observer(() => { loadingPasskeys={loadingPasskeys} enablingSmsMfa={enablingSmsMfa} disablingSmsMfa={disablingSmsMfa} + showMaskedPhone={showMaskedPhone} loadPasskeys={loadPasskeys} setEnablingSmsMfa={setEnablingSmsMfa} setDisablingSmsMfa={setDisablingSmsMfa} + setShowMaskedPhone={setShowMaskedPhone} /> diff --git a/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.module.css b/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.module.css index dd220d40..921cd60a 100644 --- a/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.module.css +++ b/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.module.css @@ -97,6 +97,48 @@ gap: 0.5rem; } +.phoneRow { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +@media (min-width: 640px) { + .phoneRow { + flex-direction: row; + align-items: center; + gap: 0.5rem; + } +} + +.phoneText { + color: var(--text-primary-muted); + font-size: 0.875rem; +} + +.phoneTextSelectable { + user-select: text; + -webkit-user-select: text; +} + +.toggleButton { + margin-top: 0.1em; + text-align: left; + color: var(--text-link); + font-size: 0.875rem; + cursor: pointer; +} + +.toggleButton:hover { + text-decoration: underline; +} + +@media (min-width: 640px) { + .toggleButton { + text-align: center; + } +} + .claimButton { align-self: flex-start; } diff --git a/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.tsx b/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.tsx index e0f91cbe..e4c74514 100644 --- a/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.tsx +++ b/fluxer_app/src/components/modals/tabs/account_security_tab/SecurityTab.tsx @@ -41,6 +41,15 @@ import type React from 'react'; const logger = new Logger('SecurityTab'); +const maskPhone = (phone: string): string => { + if (phone.length <= 4) { + return phone.replace(/./g, '*'); + } + const lastTwo = phone.slice(-2); + const masked = phone.slice(0, -2).replace(/\d/g, '*'); + return `${masked}${lastTwo}`; +}; + interface SecurityTabProps { user: UserRecord; isClaimed: boolean; @@ -51,9 +60,11 @@ interface SecurityTabProps { loadingPasskeys: boolean; enablingSmsMfa: boolean; disablingSmsMfa: boolean; + showMaskedPhone: boolean; loadPasskeys: () => Promise; setEnablingSmsMfa: React.Dispatch>; setDisablingSmsMfa: React.Dispatch>; + setShowMaskedPhone: (show: boolean) => void; } export const SecurityTabContent: React.FC = observer( @@ -67,9 +78,11 @@ export const SecurityTabContent: React.FC = observer( loadingPasskeys, enablingSmsMfa, disablingSmsMfa, + showMaskedPhone, loadPasskeys, setEnablingSmsMfa, setDisablingSmsMfa, + setShowMaskedPhone, }) => { const {t, i18n} = useLingui(); @@ -344,13 +357,24 @@ export const SecurityTabContent: React.FC = observer(
Phone Number
-
- {user.phone ? ( - Phone number added: {user.phone} - ) : ( + {user.phone ? ( +
+ + {showMaskedPhone ? user.phone : maskPhone(user.phone)} + + +
+ ) : ( +
Add a phone number to enable SMS two-factor authentication - )} -
+
+ )} {user.phone ? (