mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
refactor: simplify account standing and verification levels (#3130)
This commit is contained in:
1 parent
1abde06824
commit
1ec8f31253
488 files changed
+10390
-47117
No files matched your search
@@ -72,6 +72,7 @@ export function resolveDmActionErrorContent(
|
||||
): {title: string; message: string} {
|
||||
switch (code) {
|
||||
case APIErrorCodes.NEW_CONVERSATIONS_LIMITED:
|
||||
case APIErrorCodes.ACCOUNT_LIMITED:
|
||||
return {
|
||||
title: i18nGlobal._(GENERIC_TITLE_DESCRIPTOR),
|
||||
message: apiMessage || i18nGlobal._(GENERIC_ERROR_BODY_DESCRIPTOR),
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import styles from '@app/features/app/components/layout/AppLayout.module.css';
|
||||
import {useAppLayoutState} from '@app/features/app/components/layout/app_layout/AppLayoutHooks';
|
||||
import RequiredActionGate from '@app/features/app/components/layout/RequiredActionGate';
|
||||
import Initialization from '@app/features/app/state/Initialization';
|
||||
import * as AuthenticationCommands from '@app/features/auth/commands/AuthenticationCommands';
|
||||
import AccountManager from '@app/features/auth/state/AccountManager';
|
||||
@@ -40,7 +39,6 @@ export const AppLayout = observer(({children}: {children: React.ReactNode}) => {
|
||||
<MediaDeviceStartupPreloadManager data-flx="app.app-layout.media-device-startup-preload-manager" />
|
||||
)}
|
||||
{isAuthenticated && <NewDeviceMonitoringManager data-flx="app.app-layout.new-device-monitoring-manager" />}
|
||||
{isAuthenticated && <RequiredActionGate data-flx="app.app-layout.required-action-gate" />}
|
||||
<div
|
||||
className={clsx(styles.appLayout, appState.isStandalone && styles.appLayoutStandalone)}
|
||||
data-flx="app.app-layout.app-layout"
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {resolveRequiredActionFlow} from '@app/features/auth/components/modals/RequiredActionFlow';
|
||||
import RequiredActionModal from '@app/features/auth/components/modals/RequiredActionModal';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import LayerManager from '@app/features/ui/state/LayerManager';
|
||||
import Modal from '@app/features/ui/state/Modal';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
import {useEffect} from 'react';
|
||||
|
||||
export const REQUIRED_ACTION_MODAL_KEY = 'required-actions';
|
||||
const RequiredActionGate = observer(() => {
|
||||
const requiredActionKey = resolveRequiredActionFlow(Users.currentUser?.requiredActions)?.key ?? null;
|
||||
const isModalOpen = Modal.hasModal(REQUIRED_ACTION_MODAL_KEY);
|
||||
useEffect(() => {
|
||||
if (!requiredActionKey) {
|
||||
if (isModalOpen) {
|
||||
ModalCommands.popWithKey(REQUIRED_ACTION_MODAL_KEY);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!isModalOpen) {
|
||||
LayerManager.closeAll();
|
||||
}
|
||||
ModalCommands.pushWithKey(
|
||||
ModalCommands.modal(() => (
|
||||
<RequiredActionModal mock={false} data-flx="app.required-action-gate.required-action-modal" />
|
||||
)),
|
||||
REQUIRED_ACTION_MODAL_KEY,
|
||||
);
|
||||
}, [isModalOpen, requiredActionKey]);
|
||||
useEffect(
|
||||
() => () => {
|
||||
ModalCommands.popWithKey(REQUIRED_ACTION_MODAL_KEY);
|
||||
},
|
||||
[],
|
||||
);
|
||||
return null;
|
||||
});
|
||||
|
||||
export default RequiredActionGate;
|
||||
+39
-10
@@ -7,6 +7,7 @@ import {NAGBAR_TONES, NagbarToneKind} from '@app/features/app/components/layout/
|
||||
import {OPEN_SETTINGS_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {BouncedEmailChangeModal} from '@app/features/user/components/modals/BouncedEmailChangeModal';
|
||||
import {UserSettingsModal} from '@app/features/user/components/modals/UserSettingsModal';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import * as NicknameUtils from '@app/features/user/utils/NicknameUtils';
|
||||
@@ -19,12 +20,29 @@ const EMAIL_VERIFICATION_NAGBAR_MESSAGE_DESCRIPTOR = msg({
|
||||
comment:
|
||||
'Nagbar warning shown when the current user still needs to verify email. displayName is the user display name.',
|
||||
});
|
||||
const EMAIL_BOUNCED_NAGBAR_MESSAGE_DESCRIPTOR = msg({
|
||||
message: "Hey {displayName}, we can't deliver email to your address. Add a working email to verify your account.",
|
||||
comment:
|
||||
'Nagbar warning shown when emails to the current user address bounce, so the address cannot be verified. displayName is the user display name.',
|
||||
});
|
||||
const ADD_A_WORKING_EMAIL_BUTTON_DESCRIPTOR = msg({
|
||||
message: 'Add a working email',
|
||||
comment: 'Nagbar button that opens the flow to replace an email address that bounced. Keep it concise.',
|
||||
});
|
||||
export const EmailVerificationNagbar = observer(({isMobile}: {isMobile: boolean}) => {
|
||||
const {i18n} = useLingui();
|
||||
const user = Users.currentUser;
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
const isEmailBounced = user.emailBounced === true;
|
||||
const openBouncedEmailChange = () => {
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<BouncedEmailChangeModal data-flx="app.app-layout.nagbars.email-verification-nagbar.open-bounced-email-change.bounced-email-change-modal" />
|
||||
)),
|
||||
);
|
||||
};
|
||||
const openUserSettings = () => {
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
@@ -44,17 +62,28 @@ export const EmailVerificationNagbar = observer(({isMobile}: {isMobile: boolean}
|
||||
>
|
||||
<NagbarContent
|
||||
isMobile={isMobile}
|
||||
message={i18n._(EMAIL_VERIFICATION_NAGBAR_MESSAGE_DESCRIPTOR, {
|
||||
displayName: NicknameUtils.getDisplayName(user),
|
||||
})}
|
||||
message={i18n._(
|
||||
isEmailBounced ? EMAIL_BOUNCED_NAGBAR_MESSAGE_DESCRIPTOR : EMAIL_VERIFICATION_NAGBAR_MESSAGE_DESCRIPTOR,
|
||||
{displayName: NicknameUtils.getDisplayName(user)},
|
||||
)}
|
||||
actions={
|
||||
<NagbarButton
|
||||
isMobile={isMobile}
|
||||
onClick={openUserSettings}
|
||||
data-flx="app.app-layout.nagbars.email-verification-nagbar.nagbar-button.open-user-settings"
|
||||
>
|
||||
{i18n._(OPEN_SETTINGS_DESCRIPTOR)}
|
||||
</NagbarButton>
|
||||
isEmailBounced ? (
|
||||
<NagbarButton
|
||||
isMobile={isMobile}
|
||||
onClick={openBouncedEmailChange}
|
||||
data-flx="app.app-layout.nagbars.email-verification-nagbar.nagbar-button.open-bounced-email-change"
|
||||
>
|
||||
{i18n._(ADD_A_WORKING_EMAIL_BUTTON_DESCRIPTOR)}
|
||||
</NagbarButton>
|
||||
) : (
|
||||
<NagbarButton
|
||||
isMobile={isMobile}
|
||||
onClick={openUserSettings}
|
||||
data-flx="app.app-layout.nagbars.email-verification-nagbar.nagbar-button.open-user-settings"
|
||||
>
|
||||
{i18n._(OPEN_SETTINGS_DESCRIPTOR)}
|
||||
</NagbarButton>
|
||||
)
|
||||
}
|
||||
data-flx="app.app-layout.nagbars.email-verification-nagbar.nagbar-content"
|
||||
/>
|
||||
|
||||
@@ -188,17 +188,12 @@ export const Endpoints = {
|
||||
USER_MFA_WEBAUTHN_MIGRATION_REGISTRATION_OPTIONS: '/users/@me/mfa/webauthn/migration/registration-options',
|
||||
USER_PASSKEY_BRIDGE: '/users/@me/passkey-bridge',
|
||||
USER_PASSKEY_BRIDGE_REDEEM: (ceremonyId: string) => `/users/@me/passkey-bridge/${ceremonyId}/redeem`,
|
||||
USER_PHONE_SEND_VERIFICATION: '/users/@me/phone/send-verification',
|
||||
USER_PHONE_INBOUND_CHALLENGE: '/users/@me/phone/inbound-challenge',
|
||||
USER_PHONE_VERIFY: '/users/@me/phone/verify',
|
||||
USER_REQUIRED_ACTION_PHONE_GATE_ESCAPE: '/users/@me/required-actions/phone-gate-escape',
|
||||
USER_EMAIL_CHANGE_START: '/users/@me/email-change/start',
|
||||
USER_EMAIL_CHANGE_RESEND_ORIGINAL: '/users/@me/email-change/resend-original',
|
||||
USER_EMAIL_CHANGE_VERIFY_ORIGINAL: '/users/@me/email-change/verify-original',
|
||||
USER_EMAIL_CHANGE_REQUEST_NEW: '/users/@me/email-change/request-new',
|
||||
USER_EMAIL_CHANGE_RESEND_NEW: '/users/@me/email-change/resend-new',
|
||||
USER_EMAIL_CHANGE_VERIFY_NEW: '/users/@me/email-change/verify-new',
|
||||
USER_EMAIL_CHANGE_APPLY: '/users/@me/email-change/apply',
|
||||
USER_EMAIL_CHANGE_BOUNCED_REQUEST_NEW: '/users/@me/email-change/bounced/request-new',
|
||||
USER_EMAIL_CHANGE_BOUNCED_RESEND_NEW: '/users/@me/email-change/bounced/resend-new',
|
||||
USER_EMAIL_CHANGE_BOUNCED_VERIFY_NEW: '/users/@me/email-change/bounced/verify-new',
|
||||
|
||||
@@ -100,7 +100,7 @@ const DEFAULT_INSTANCE_FEATURES: InstanceFeatures = {
|
||||
self_hosted: false,
|
||||
presigned_attachment_uploads: false,
|
||||
emails_enabled: false,
|
||||
phone_verification_enabled: true,
|
||||
phone_verification_enabled: false,
|
||||
};
|
||||
|
||||
export const DEFAULT_INSTANCE_REGISTRATION: InstanceRegistration = {
|
||||
@@ -517,10 +517,6 @@ class RuntimeConfig {
|
||||
return this.features.emails_enabled;
|
||||
}
|
||||
|
||||
get phoneVerificationEnabled(): boolean {
|
||||
return this.features.phone_verification_enabled;
|
||||
}
|
||||
|
||||
get productName(): string {
|
||||
return this.appPublic.branding.product_name.trim() || DEFAULT_APP_PUBLIC_CONFIG.branding.product_name;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user