mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +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
@@ -36,6 +36,7 @@ import * as TextCopyCommands from '@app/features/ui/commands/TextCopyCommands';
|
||||
import * as ToastCommands from '@app/features/ui/commands/ToastCommands';
|
||||
import MobileLayout from '@app/features/ui/state/MobileLayout';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import {blockIfAccountLimited} from '@app/features/user/utils/AccountLimitUtils';
|
||||
import TtsUtils from '@app/features/voice/utils/VoiceTtsUtils';
|
||||
import {
|
||||
ChannelTypes,
|
||||
@@ -632,6 +633,7 @@ export function requestMessageForward(
|
||||
if (!currentUser) {
|
||||
return;
|
||||
}
|
||||
if (blockIfAccountLimited()) return;
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<ForwardModal
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import {
|
||||
AccountTooNewBarrier,
|
||||
DefaultBarrier,
|
||||
NoPhoneNumberBarrier,
|
||||
NotMemberLongEnoughBarrier,
|
||||
SendMessageDisabledBarrier,
|
||||
TimeoutBarrier,
|
||||
@@ -47,8 +46,6 @@ export const VerificationBarrier = observer(({channel}: Props) => {
|
||||
data-flx="channel.verification-barrier.not-member-long-enough-barrier"
|
||||
/>
|
||||
);
|
||||
case VerificationFailureReason.NO_PHONE_NUMBER:
|
||||
return <NoPhoneNumberBarrier data-flx="channel.verification-barrier.no-phone-number-barrier" />;
|
||||
case VerificationFailureReason.SEND_MESSAGE_DISABLED:
|
||||
return <SendMessageDisabledBarrier data-flx="channel.verification-barrier.send-message-disabled-barrier" />;
|
||||
case VerificationFailureReason.TIMED_OUT:
|
||||
|
||||
+5
-1
@@ -2,9 +2,10 @@
|
||||
|
||||
import i18n from '@app/app/I18n';
|
||||
import {GenericErrorModal} from '@app/features/app/components/alerts/GenericErrorModal';
|
||||
import {failureCode} from '@app/features/platform/utils/ResponseInspection';
|
||||
import {failureCode, failureMessage} from '@app/features/platform/utils/ResponseInspection';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {ACCOUNT_LIMITED_NOTICE_DESCRIPTOR} from '@app/features/user/utils/AccountLimitUtils';
|
||||
import {APIErrorCodes} from '@fluxer/constants/src/ApiErrorCodes';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
|
||||
@@ -46,6 +47,9 @@ export function showGroupRecipientAddFailedModal(error: unknown): void {
|
||||
case APIErrorCodes.RATE_LIMITED:
|
||||
message = i18n._(RATE_LIMITED_DESCRIPTOR);
|
||||
break;
|
||||
case APIErrorCodes.ACCOUNT_LIMITED:
|
||||
message = failureMessage(error) || i18n._(ACCOUNT_LIMITED_NOTICE_DESCRIPTOR);
|
||||
break;
|
||||
default:
|
||||
message = i18n._(ADD_TO_GROUP_FAILED_MESSAGE_DESCRIPTOR);
|
||||
break;
|
||||
|
||||
@@ -14,8 +14,10 @@ import {remFromPx} from '@app/features/theme/layout/RemFromPx';
|
||||
import {Button} from '@app/features/ui/button/Button';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {PhoneAddModal} from '@app/features/user/components/modals/PhoneAddModal';
|
||||
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 {ACCOUNT_LIMITED_NOTICE_DESCRIPTOR} from '@app/features/user/utils/AccountLimitUtils';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {Trans, useLingui} from '@lingui/react/macro';
|
||||
import {
|
||||
@@ -23,7 +25,6 @@ import {
|
||||
EnvelopeSimpleIcon,
|
||||
InfoIcon,
|
||||
MegaphoneSimpleIcon,
|
||||
PhoneIcon,
|
||||
ProhibitIcon,
|
||||
ShieldWarningIcon,
|
||||
TimerIcon,
|
||||
@@ -181,13 +182,18 @@ export const UnverifiedEmailBarrier = observer(({onAction}: BarrierProps) => {
|
||||
small={true}
|
||||
onClick={() => {
|
||||
onAction?.();
|
||||
const bounced = Users.currentUser?.emailBounced === true;
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<UserSettingsModal
|
||||
initialTab="account_security"
|
||||
data-flx="channel.barriers.barrier-components.unverified-email-barrier.user-settings-modal"
|
||||
/>
|
||||
)),
|
||||
modal(() =>
|
||||
bounced ? (
|
||||
<BouncedEmailChangeModal data-flx="channel.barriers.barrier-components.unverified-email-barrier.bounced-email-change-modal" />
|
||||
) : (
|
||||
<UserSettingsModal
|
||||
initialTab="account_security"
|
||||
data-flx="channel.barriers.barrier-components.unverified-email-barrier.user-settings-modal"
|
||||
/>
|
||||
),
|
||||
),
|
||||
);
|
||||
}}
|
||||
data-flx="channel.barriers.barrier-components.unverified-email-barrier.button.action"
|
||||
@@ -245,34 +251,20 @@ export const NotMemberLongEnoughBarrier = observer(({initialTimeRemaining = 10 *
|
||||
/>
|
||||
);
|
||||
});
|
||||
export const NoPhoneNumberBarrier = observer(({onAction}: BarrierProps) => {
|
||||
export const AccountLimitedBarrier = observer(() => {
|
||||
const {i18n} = useLingui();
|
||||
return (
|
||||
<BarrierBase
|
||||
message={<Trans>You need to verify a phone number to send messages in this community.</Trans>}
|
||||
message={i18n._(ACCOUNT_LIMITED_NOTICE_DESCRIPTOR)}
|
||||
icon={
|
||||
<PhoneIcon
|
||||
<InfoIcon
|
||||
size={remFromPx(18)}
|
||||
weight="fill"
|
||||
data-flx="channel.barriers.barrier-components.no-phone-number-barrier.phone-icon"
|
||||
data-flx="channel.barriers.barrier-components.account-limited-barrier.info-icon"
|
||||
/>
|
||||
}
|
||||
action={
|
||||
<Button
|
||||
small={true}
|
||||
onClick={() => {
|
||||
onAction?.();
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<PhoneAddModal data-flx="channel.barriers.barrier-components.no-phone-number-barrier.phone-add-modal" />
|
||||
)),
|
||||
);
|
||||
}}
|
||||
data-flx="channel.barriers.barrier-components.no-phone-number-barrier.button.action"
|
||||
>
|
||||
<Trans>Verify phone</Trans>
|
||||
</Button>
|
||||
}
|
||||
data-flx="channel.barriers.barrier-components.no-phone-number-barrier.barrier-base"
|
||||
action={null}
|
||||
data-flx="channel.barriers.barrier-components.account-limited-barrier.barrier-base"
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
+1
-4
@@ -37,10 +37,7 @@ export const DeveloperToolsContextMenu: React.FC<{onClose: () => void}> = observ
|
||||
<MenuGroup data-flx="channel.channel-header-components.developer-tools-context-menu.menu-group--3">
|
||||
<GeneralDeveloperOptionsMenu data-flx="channel.channel-header-components.developer-tools-context-menu.general-developer-options-menu" />
|
||||
<AccountPremiumMenu data-flx="channel.channel-header-components.developer-tools-context-menu.account-premium-menu" />
|
||||
<MockingMenu
|
||||
onClose={onClose}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.mocking-menu"
|
||||
/>
|
||||
<MockingMenu data-flx="channel.channel-header-components.developer-tools-context-menu.mocking-menu" />
|
||||
</MenuGroup>
|
||||
<MenuGroup data-flx="channel.channel-header-components.developer-tools-context-menu.menu-group--4">
|
||||
<NagbarsMenu data-flx="channel.channel-header-components.developer-tools-context-menu.nagbars-menu" />
|
||||
|
||||
-46
@@ -221,34 +221,6 @@ const GEO_BLOCK_OVERLAY_DESCRIPTOR = msg({
|
||||
message: 'Geo block overlay',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTIONS_OVERLAY_DESCRIPTOR = msg({
|
||||
message: 'Required actions overlay',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTION_VARIANT_DESCRIPTOR = msg({
|
||||
message: 'Required action variant',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTION_DEFAULT_TAB_DESCRIPTOR = msg({
|
||||
message: 'Required action default tab',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTION_PHONE_STEP_DESCRIPTOR = msg({
|
||||
message: 'Required action phone step',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTION_RESEND_LOADING_DESCRIPTOR = msg({
|
||||
message: 'Required action resend loading',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTION_RESEND_OUTCOME_DESCRIPTOR = msg({
|
||||
message: 'Required action resend outcome',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTION_REVERIFICATION_TEXT_DESCRIPTOR = msg({
|
||||
message: 'Required action reverification text',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const NO_SEND_PERMISSION_DESCRIPTOR = msg({
|
||||
message: 'No {sendMessagesPermission} permission',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
@@ -324,10 +296,6 @@ const formatDeveloperOptionValue = <K extends keyof DeveloperOptionsState>(
|
||||
case 'mockVerificationBarrier':
|
||||
case 'mockMatureContentGateReason':
|
||||
case 'mockMatureMediaGateReason':
|
||||
case 'mockRequiredActionsMode':
|
||||
case 'mockRequiredActionsSelectedTab':
|
||||
case 'mockRequiredActionsPhoneStep':
|
||||
case 'mockRequiredActionsResendOutcome':
|
||||
case 'mockTitlebarPlatformOverride':
|
||||
case 'mockUpdaterState':
|
||||
return String(value).replace(/_/g, ' ');
|
||||
@@ -448,20 +416,6 @@ export const getDeveloperOptionLabel = (key: keyof DeveloperOptionsState): Messa
|
||||
return UK_GEO_DESCRIPTOR;
|
||||
case 'mockGeoBlocked':
|
||||
return GEO_BLOCK_OVERLAY_DESCRIPTOR;
|
||||
case 'mockRequiredActionsOverlay':
|
||||
return REQUIRED_ACTIONS_OVERLAY_DESCRIPTOR;
|
||||
case 'mockRequiredActionsMode':
|
||||
return REQUIRED_ACTION_VARIANT_DESCRIPTOR;
|
||||
case 'mockRequiredActionsSelectedTab':
|
||||
return REQUIRED_ACTION_DEFAULT_TAB_DESCRIPTOR;
|
||||
case 'mockRequiredActionsPhoneStep':
|
||||
return REQUIRED_ACTION_PHONE_STEP_DESCRIPTOR;
|
||||
case 'mockRequiredActionsResending':
|
||||
return REQUIRED_ACTION_RESEND_LOADING_DESCRIPTOR;
|
||||
case 'mockRequiredActionsResendOutcome':
|
||||
return REQUIRED_ACTION_RESEND_OUTCOME_DESCRIPTOR;
|
||||
case 'mockRequiredActionsReverify':
|
||||
return REQUIRED_ACTION_REVERIFICATION_TEXT_DESCRIPTOR;
|
||||
case 'forceNoSendMessages':
|
||||
return {...NO_SEND_PERMISSION_DESCRIPTOR, values: {sendMessagesPermission: SEND_MESSAGES_PERMISSION}};
|
||||
case 'forceNoAttachFiles':
|
||||
|
||||
+1
-108
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {ATTACH_FILES_PERMISSION, SEND_MESSAGES_PERMISSION} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import RequiredActionModal from '@app/features/auth/components/modals/RequiredActionModal';
|
||||
import {
|
||||
DeveloperOptionCheckbox,
|
||||
DeveloperOptionRadioItems,
|
||||
@@ -12,10 +11,6 @@ import {
|
||||
getGiftDurationOptions,
|
||||
getMatureContentChannelGateOptions,
|
||||
getMatureContentMediaGateOptions,
|
||||
getRequiredActionModeOptions,
|
||||
getRequiredActionPhoneStepOptions,
|
||||
getRequiredActionResendOutcomeOptions,
|
||||
getRequiredActionTabOptions,
|
||||
getVerificationBarrierOptions,
|
||||
} from '@app/features/channel/components/channel_header_components/developer_tools/OptionPresets';
|
||||
import {updateOption} from '@app/features/channel/components/channel_header_components/developer_tools/ResetOptions';
|
||||
@@ -25,7 +20,6 @@ import {remFromPx} from '@app/features/theme/layout/RemFromPx';
|
||||
import {MenuItem} from '@app/features/ui/action_menu/MenuItem';
|
||||
import {MenuItemSlider} from '@app/features/ui/action_menu/MenuItemSlider';
|
||||
import {MenuItemSubmenu} from '@app/features/ui/action_menu/MenuItemSubmenu';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import {msg, plural} from '@lingui/core/macro';
|
||||
import {Trans, useLingui} from '@lingui/react/macro';
|
||||
@@ -57,30 +51,10 @@ const SLOWMODE_TIME_REMAINING_DESCRIPTOR = msg({
|
||||
message: 'Slowmode time remaining',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const REQUIRED_ACTION_FLOW_DESCRIPTOR = msg({
|
||||
message: 'Required action flow',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const MOCK_VARIANT_DESCRIPTOR = msg({
|
||||
message: 'Mock variant',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const MOCK_INCOMING_CALL_DESCRIPTOR = msg({
|
||||
message: 'Mock incoming call',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const DEFAULT_TAB_DESCRIPTOR = msg({
|
||||
message: 'Default tab',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const PHONE_STEP_DESCRIPTOR = msg({
|
||||
message: 'Phone step',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const RESEND_OUTCOME_DESCRIPTOR = msg({
|
||||
message: 'Resend outcome',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
const CONTENT_SAFETY_GATES_DESCRIPTOR = msg({
|
||||
message: 'Content safety gates',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
@@ -190,71 +164,6 @@ const SlowmodeSimulationMenu: React.FC = observer(() => {
|
||||
/>
|
||||
);
|
||||
});
|
||||
const RequiredActionFlowMenu: React.FC<{onOpenOverlay: () => void}> = observer(({onOpenOverlay}) => {
|
||||
const {i18n} = useLingui();
|
||||
const shouldShowDefaultTab = DeveloperOptions.mockRequiredActionsMode === 'email_or_phone';
|
||||
const shouldShowPhoneStep =
|
||||
DeveloperOptions.mockRequiredActionsMode === 'phone' ||
|
||||
(DeveloperOptions.mockRequiredActionsMode === 'email_or_phone' &&
|
||||
DeveloperOptions.mockRequiredActionsSelectedTab === 'phone');
|
||||
return (
|
||||
<MenuItemSubmenu
|
||||
label={i18n._(REQUIRED_ACTION_FLOW_DESCRIPTOR)}
|
||||
render={() => (
|
||||
<>
|
||||
<DeveloperOptionRadioSubmenu
|
||||
label={i18n._(MOCK_VARIANT_DESCRIPTOR)}
|
||||
optionKey="mockRequiredActionsMode"
|
||||
options={getRequiredActionModeOptions()}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.developer-option-radio-submenu"
|
||||
/>
|
||||
<MenuItem
|
||||
disabled={!Users.currentUser}
|
||||
onClick={onOpenOverlay}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.menu-item.open-overlay"
|
||||
>
|
||||
<Trans>Open overlay</Trans>
|
||||
</MenuItem>
|
||||
{shouldShowDefaultTab && (
|
||||
<DeveloperOptionRadioSubmenu
|
||||
label={i18n._(DEFAULT_TAB_DESCRIPTOR)}
|
||||
optionKey="mockRequiredActionsSelectedTab"
|
||||
options={getRequiredActionTabOptions()}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.developer-option-radio-submenu--2"
|
||||
/>
|
||||
)}
|
||||
{shouldShowPhoneStep && (
|
||||
<DeveloperOptionRadioSubmenu
|
||||
label={i18n._(PHONE_STEP_DESCRIPTOR)}
|
||||
optionKey="mockRequiredActionsPhoneStep"
|
||||
options={getRequiredActionPhoneStepOptions()}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.developer-option-radio-submenu--3"
|
||||
/>
|
||||
)}
|
||||
<DeveloperOptionCheckbox
|
||||
optionKey="mockRequiredActionsReverify"
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.developer-option-checkbox"
|
||||
>
|
||||
<Trans>Use reverification text</Trans>
|
||||
</DeveloperOptionCheckbox>
|
||||
<DeveloperOptionCheckbox
|
||||
optionKey="mockRequiredActionsResending"
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.developer-option-checkbox--2"
|
||||
>
|
||||
<Trans>Resend button loading</Trans>
|
||||
</DeveloperOptionCheckbox>
|
||||
<DeveloperOptionRadioSubmenu
|
||||
label={i18n._(RESEND_OUTCOME_DESCRIPTOR)}
|
||||
optionKey="mockRequiredActionsResendOutcome"
|
||||
options={getRequiredActionResendOutcomeOptions()}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.developer-option-radio-submenu--4"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.required-action-flow-menu.menu-item-submenu"
|
||||
/>
|
||||
);
|
||||
});
|
||||
const ContentSafetyGatesMenu: React.FC = () => {
|
||||
const {i18n} = useLingui();
|
||||
return (
|
||||
@@ -344,20 +253,8 @@ const GiftInventoryFlowMenu: React.FC = observer(() => {
|
||||
/>
|
||||
);
|
||||
});
|
||||
export const MockingMenu: React.FC<{onClose: () => void}> = observer(({onClose}) => {
|
||||
export const MockingMenu: React.FC = observer(() => {
|
||||
const {i18n} = useLingui();
|
||||
const openRequiredActionOverlay = () => {
|
||||
ModalCommands.pushWithKeyAfterBottomSheetClose(
|
||||
onClose,
|
||||
ModalCommands.modal(() => (
|
||||
<RequiredActionModal
|
||||
mock={true}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.open-required-action-overlay.required-action-modal"
|
||||
/>
|
||||
)),
|
||||
'required-actions-mock',
|
||||
);
|
||||
};
|
||||
return (
|
||||
<MenuItemSubmenu
|
||||
label={i18n._(MOCKED_PRODUCT_FLOWS_DESCRIPTOR)}
|
||||
@@ -415,10 +312,6 @@ export const MockingMenu: React.FC<{onClose: () => void}> = observer(({onClose})
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.mocking-menu.menu-item-submenu.mock-incoming-call"
|
||||
/>
|
||||
<SlowmodeSimulationMenu data-flx="channel.channel-header-components.developer-tools-context-menu.mocking-menu.slowmode-simulation-menu" />
|
||||
<RequiredActionFlowMenu
|
||||
onOpenOverlay={openRequiredActionOverlay}
|
||||
data-flx="channel.channel-header-components.developer-tools-context-menu.mocking-menu.required-action-flow-menu"
|
||||
/>
|
||||
<ContentSafetyGatesMenu data-flx="channel.channel-header-components.developer-tools-context-menu.mocking-menu.content-safety-gates-menu" />
|
||||
<GiftInventoryFlowMenu data-flx="channel.channel-header-components.developer-tools-context-menu.mocking-menu.gift-inventory-flow-menu" />
|
||||
</>
|
||||
|
||||
+3
-58
@@ -10,7 +10,6 @@ import {
|
||||
NO_TIMER_DESCRIPTOR,
|
||||
} from '@app/features/channel/components/channel_header_components/developer_tools/FormatHelpers';
|
||||
import type {DeveloperOptionsState} from '@app/features/devtools/state/DeveloperOptions';
|
||||
import {EMAIL_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
||||
import {UserPremiumTypes} from '@fluxer/constants/src/UserConstants';
|
||||
import type {I18n} from '@lingui/core';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
@@ -47,42 +46,14 @@ export const NOT_A_MEMBER_LONG_ENOUGH_DESCRIPTOR = msg({
|
||||
message: 'Not a member long enough',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const NO_PHONE_NUMBER_DESCRIPTOR = msg({
|
||||
message: 'No phone number',
|
||||
export const ACCOUNT_LIMITED_DESCRIPTOR = msg({
|
||||
message: 'Account limited',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const SEND_MESSAGES_DISABLED_DESCRIPTOR = msg({
|
||||
message: 'Send messages disabled',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const PHONE_DESCRIPTOR = msg({
|
||||
message: 'Phone',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const EMAIL_OR_PHONE_DESCRIPTOR = msg({
|
||||
message: 'Email or phone',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const ENTER_PHONE_DESCRIPTOR = msg({
|
||||
message: 'Enter phone',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const ENTER_CODE_DESCRIPTOR = msg({
|
||||
message: 'Enter code',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const SUCCESS_DESCRIPTOR = msg({
|
||||
message: 'Success',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const RATE_LIMITED_DESCRIPTOR = msg({
|
||||
message: 'Rate limited',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const SERVICE_ERROR_DESCRIPTOR = msg({
|
||||
message: 'Service error',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
});
|
||||
export const GEO_RESTRICTED_DESCRIPTOR = msg({
|
||||
message: 'Geo restricted',
|
||||
comment: 'Developer tools debug menu label. Internal-only surface for developers; translators may keep this terse.',
|
||||
@@ -137,7 +108,7 @@ export const getVerificationBarrierOptions = (): Array<
|
||||
{value: 'unverified_email', label: UNVERIFIED_EMAIL_DESCRIPTOR},
|
||||
{value: 'account_too_new', label: ACCOUNT_TOO_NEW_DESCRIPTOR},
|
||||
{value: 'not_member_long', label: NOT_A_MEMBER_LONG_ENOUGH_DESCRIPTOR},
|
||||
{value: 'no_phone', label: NO_PHONE_NUMBER_DESCRIPTOR},
|
||||
{value: 'account_limited', label: ACCOUNT_LIMITED_DESCRIPTOR},
|
||||
{value: 'send_message_disabled', label: SEND_MESSAGES_DISABLED_DESCRIPTOR},
|
||||
];
|
||||
export const getCountdownTimerOptions = (
|
||||
@@ -151,32 +122,6 @@ export const getCountdownTimerOptions = (
|
||||
{value: 300000, label: formatDurationMs(i18n, 300000)},
|
||||
{value: 600000, label: formatDurationMs(i18n, 600000)},
|
||||
];
|
||||
export const getRequiredActionModeOptions = (): Array<
|
||||
RadioMenuOption<DeveloperOptionsState['mockRequiredActionsMode']>
|
||||
> => [
|
||||
{value: 'email', label: EMAIL_DESCRIPTOR},
|
||||
{value: 'phone', label: PHONE_DESCRIPTOR},
|
||||
{value: 'email_or_phone', label: EMAIL_OR_PHONE_DESCRIPTOR},
|
||||
];
|
||||
export const getRequiredActionTabOptions = (): Array<
|
||||
RadioMenuOption<DeveloperOptionsState['mockRequiredActionsSelectedTab']>
|
||||
> => [
|
||||
{value: 'email', label: EMAIL_DESCRIPTOR},
|
||||
{value: 'phone', label: PHONE_DESCRIPTOR},
|
||||
];
|
||||
export const getRequiredActionPhoneStepOptions = (): Array<
|
||||
RadioMenuOption<DeveloperOptionsState['mockRequiredActionsPhoneStep']>
|
||||
> => [
|
||||
{value: 'phone', label: ENTER_PHONE_DESCRIPTOR},
|
||||
{value: 'code', label: ENTER_CODE_DESCRIPTOR},
|
||||
];
|
||||
export const getRequiredActionResendOutcomeOptions = (): Array<
|
||||
RadioMenuOption<DeveloperOptionsState['mockRequiredActionsResendOutcome']>
|
||||
> => [
|
||||
{value: 'success', label: SUCCESS_DESCRIPTOR},
|
||||
{value: 'rate_limited', label: RATE_LIMITED_DESCRIPTOR},
|
||||
{value: 'server_error', label: SERVICE_ERROR_DESCRIPTOR},
|
||||
];
|
||||
export const getMatureContentChannelGateOptions = (): Array<
|
||||
RadioMenuOption<DeveloperOptionsState['mockMatureContentGateReason']>
|
||||
> => [
|
||||
|
||||
-7
@@ -50,13 +50,6 @@ export const DEFAULT_DEVELOPER_OPTIONS = {
|
||||
forceMatureMedia: false,
|
||||
mockInUK: false,
|
||||
mockGeoBlocked: false,
|
||||
mockRequiredActionsOverlay: false,
|
||||
mockRequiredActionsMode: 'email',
|
||||
mockRequiredActionsSelectedTab: 'email',
|
||||
mockRequiredActionsPhoneStep: 'phone',
|
||||
mockRequiredActionsResending: false,
|
||||
mockRequiredActionsResendOutcome: 'success',
|
||||
mockRequiredActionsReverify: false,
|
||||
forceNoSendMessages: false,
|
||||
forceNoAttachFiles: false,
|
||||
mockSlowmodeActive: false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {
|
||||
AccountLimitedBarrier,
|
||||
BlockedUserBarrier,
|
||||
SystemDmBarrier,
|
||||
UnclaimedDMBarrier,
|
||||
@@ -78,6 +79,7 @@ export const DMChannelView = observer(({channelId}: DMChannelViewProps) => {
|
||||
const recipient = recipientId ? Users.getUser(recipientId) : null;
|
||||
const isRecipientBlocked = recipientId ? Relationships.isBlocked(recipientId) : false;
|
||||
const isCurrentUserUnclaimed = !Users.currentUser?.isClaimed();
|
||||
const isCurrentUserLimited = Users.currentUser?.accountLimited === true;
|
||||
const isSystemDm = channel ? ChannelUtils.isSystemDmChannel(channel) : false;
|
||||
const isDM = channel?.type === ChannelTypes.DM;
|
||||
const isGroupDM = channel?.type === ChannelTypes.GROUP_DM;
|
||||
@@ -494,6 +496,8 @@ export const DMChannelView = observer(({channelId}: DMChannelViewProps) => {
|
||||
username={NicknameUtils.getNickname(recipient, null)}
|
||||
data-flx="channel.channel-view.dm-channel-view.blocked-user-barrier"
|
||||
/>
|
||||
) : isCurrentUserLimited && !isPersonalNotes ? (
|
||||
<AccountLimitedBarrier data-flx="channel.channel-view.dm-channel-view.account-limited-barrier" />
|
||||
) : isCurrentUserUnclaimed && isDM && !isPersonalNotes && !isGroupDM ? (
|
||||
<UnclaimedDMBarrier data-flx="channel.channel-view.dm-channel-view.unclaimed-dm-barrier" />
|
||||
) : (
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {
|
||||
AccountLimitedBarrier,
|
||||
AccountTooNewBarrier,
|
||||
AnnouncementFollowBarrier,
|
||||
NoPhoneNumberBarrier,
|
||||
NotMemberLongEnoughBarrier,
|
||||
SendMessageDisabledBarrier,
|
||||
UnclaimedAccountBarrier,
|
||||
@@ -40,6 +40,7 @@ import {Button} from '@app/features/ui/button/Button';
|
||||
import MobileLayout from '@app/features/ui/state/MobileLayout';
|
||||
import {Tooltip} from '@app/features/ui/tooltip/Tooltip';
|
||||
import {isPwaOnMobileOrTablet} from '@app/features/ui/utils/PwaUtils';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import {CompactVoiceCallStreamHeaderInfo} from '@app/features/voice/components/CompactVoiceCallStreamHeaderInfo';
|
||||
import {useVoiceCallFullscreenViewState} from '@app/features/voice/components/useVoiceCallAppFullscreen';
|
||||
import {VoiceCallView} from '@app/features/voice/components/VoiceCallView';
|
||||
@@ -389,9 +390,9 @@ export const GuildChannelView = observer(({channelId, guildId}: GuildChannelView
|
||||
data-flx="channel.channel-view.guild-channel-view.render-chat-area.not-member-long-enough-barrier"
|
||||
/>
|
||||
);
|
||||
case 'no_phone':
|
||||
case 'account_limited':
|
||||
return (
|
||||
<NoPhoneNumberBarrier data-flx="channel.channel-view.guild-channel-view.render-chat-area.no-phone-number-barrier" />
|
||||
<AccountLimitedBarrier data-flx="channel.channel-view.guild-channel-view.render-chat-area.account-limited-barrier" />
|
||||
);
|
||||
case 'send_message_disabled':
|
||||
return (
|
||||
@@ -408,6 +409,11 @@ export const GuildChannelView = observer(({channelId, guildId}: GuildChannelView
|
||||
);
|
||||
}
|
||||
}
|
||||
if (Users.currentUser?.accountLimited) {
|
||||
return (
|
||||
<AccountLimitedBarrier data-flx="channel.channel-view.guild-channel-view.render-chat-area.account-limited-barrier--2" />
|
||||
);
|
||||
}
|
||||
return passesVerification ? (
|
||||
renderComposer(inputSuppressed)
|
||||
) : (
|
||||
|
||||
@@ -15,6 +15,7 @@ import {Logger} from '@app/features/platform/utils/AppLogger';
|
||||
import {Button} from '@app/features/ui/button/Button';
|
||||
import * as ToastCommands from '@app/features/ui/commands/ToastCommands';
|
||||
import {Spinner} from '@app/features/ui/components/Spinner';
|
||||
import {handleAccountLimitedError} from '@app/features/user/utils/AccountLimitUtils';
|
||||
import * as WebhookCommands from '@app/features/webhook/commands/WebhookCommands';
|
||||
import {FollowedChannelListItem} from '@app/features/webhook/components/FollowedChannelListItem';
|
||||
import {WebhookListItem} from '@app/features/webhook/components/WebhookListItem';
|
||||
@@ -106,6 +107,7 @@ const ChannelWebhooksTab: React.FC<{channelId: string}> = observer(({channelId})
|
||||
void WebhookCommands.fetchChannelWebhooks({guildId: guildId!, channelId}).catch(() => {});
|
||||
} catch (error) {
|
||||
logger.error('Failed to create webhook', error);
|
||||
if (handleAccountLimitedError(error)) return;
|
||||
showChannelErrorModal({
|
||||
title: i18n._(FAILED_TO_CREATE_WEBHOOK_DESCRIPTOR),
|
||||
message: i18n._(TRY_AGAIN_IN_A_MOMENT_DESCRIPTOR),
|
||||
|
||||
Reference in new issue
Block a user