mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-19 05:55:34 +09:00
feat(expressions): remove the unfinished packs feature (#2250)
This commit is contained in:
1 parent
0eef611b6d
commit
b8f8d8d859
159 files changed
+42
-6863
No files matched your search
@@ -12,7 +12,7 @@ import {InviteAcceptFailedModal} from '@app/features/invite/components/alerts/In
|
||||
import {InvitesDisabledModal} from '@app/features/invite/components/alerts/InvitesDisabledModal';
|
||||
import {InviteAcceptModal} from '@app/features/invite/components/modals/InviteAcceptModal';
|
||||
import Invites from '@app/features/invite/state/Invites';
|
||||
import {isGroupDmInvite, isGuildInvite, isPackInvite} from '@app/features/invite/types/InviteTypes';
|
||||
import {isGroupDmInvite, isGuildInvite} from '@app/features/invite/types/InviteTypes';
|
||||
import GuildMembers from '@app/features/member/state/GuildMembers';
|
||||
import {UserBannedFromGuildModal} from '@app/features/moderation/components/alerts/UserBannedFromGuildModal';
|
||||
import {UserIpBannedFromGuildModal} from '@app/features/moderation/components/alerts/UserIpBannedFromGuildModal';
|
||||
@@ -20,10 +20,9 @@ import * as NavigationCommands from '@app/features/navigation/commands/Navigatio
|
||||
import {http} from '@app/features/platform/transport/RestTransport';
|
||||
import {HttpError} from '@app/features/platform/types/EndpointError';
|
||||
import {Logger} from '@app/features/platform/utils/AppLogger';
|
||||
import {failureCode, failureMessage} from '@app/features/platform/utils/ResponseInspection';
|
||||
import {failureCode} from '@app/features/platform/utils/ResponseInspection';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import * as ToastCommands from '@app/features/ui/commands/ToastCommands';
|
||||
import Users from '@app/features/user/state/Users';
|
||||
import {APIErrorCodes} from '@fluxer/constants/src/ApiErrorCodes';
|
||||
import {ME} from '@fluxer/constants/src/AppConstants';
|
||||
@@ -31,8 +30,7 @@ import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants';
|
||||
import {GuildFeatures} from '@fluxer/constants/src/GuildConstants';
|
||||
import type {Invite} from '@fluxer/schema/src/domains/invite/InviteSchemas';
|
||||
import type {I18n} from '@lingui/core';
|
||||
import {msg, plural} from '@lingui/core/macro';
|
||||
import {Trans} from '@lingui/react/macro';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
|
||||
const ACCOUNT_VERIFICATION_REQUIRED_DESCRIPTOR = msg({
|
||||
message: 'Account verification required',
|
||||
@@ -44,74 +42,6 @@ const PLEASE_VERIFY_YOUR_ACCOUNT_BY_SETTING_AN_EMAIL_DESCRIPTOR = msg({
|
||||
comment:
|
||||
'Body of the error modal shown when an unclaimed (guest) account tries to accept a community invite. Tells the user to complete sign-up first.',
|
||||
});
|
||||
const EMOJI_PACK_LIMIT_REACHED_DESCRIPTOR = msg({
|
||||
message: 'Emoji pack limit reached',
|
||||
comment:
|
||||
'Title of the error modal when installing an emoji pack via invite is rejected because the user is at the install limit.',
|
||||
});
|
||||
const YOU_HAVE_REACHED_THE_LIMIT_FOR_INSTALLING_EMOJI_DESCRIPTOR = msg({
|
||||
message: "You're at the install limit. Remove one to add another.",
|
||||
comment: 'Fallback body of the emoji pack install-limit error modal when no exact limit is known.',
|
||||
});
|
||||
const EMOJI_PACK_CREATION_LIMIT_REACHED_DESCRIPTOR = msg({
|
||||
message: 'Emoji pack creation limit reached',
|
||||
comment:
|
||||
'Title of the error modal when creating a new emoji pack is rejected because the user is at the creation limit.',
|
||||
});
|
||||
const YOU_HAVE_REACHED_THE_LIMIT_FOR_CREATING_EMOJI_DESCRIPTOR = msg({
|
||||
message: "You're at the creation limit. Delete one to create another.",
|
||||
comment: 'Fallback body of the emoji pack creation-limit error modal when no exact limit is known.',
|
||||
});
|
||||
const STICKER_PACK_LIMIT_REACHED_DESCRIPTOR = msg({
|
||||
message: 'Sticker pack limit reached',
|
||||
comment:
|
||||
'Title of the error modal when installing a sticker pack via invite is rejected because the user is at the install limit.',
|
||||
});
|
||||
const YOU_HAVE_REACHED_THE_LIMIT_FOR_INSTALLING_STICKER_DESCRIPTOR = msg({
|
||||
message: "You're at the install limit. Remove one to add another.",
|
||||
comment: 'Fallback body of the sticker pack install-limit error modal when no exact limit is known.',
|
||||
});
|
||||
const STICKER_PACK_CREATION_LIMIT_REACHED_DESCRIPTOR = msg({
|
||||
message: 'Sticker pack creation limit reached',
|
||||
comment:
|
||||
'Title of the error modal when creating a new sticker pack is rejected because the user is at the creation limit.',
|
||||
});
|
||||
const YOU_HAVE_REACHED_THE_LIMIT_FOR_CREATING_STICKER_DESCRIPTOR = msg({
|
||||
message: "You're at the creation limit. Delete one to create another.",
|
||||
comment: 'Fallback body of the sticker pack creation-limit error modal when no exact limit is known.',
|
||||
});
|
||||
const CANNOT_INSTALL_EMOJI_PACK_DESCRIPTOR = msg({
|
||||
message: 'Cannot install emoji pack',
|
||||
comment: 'Title of the error modal when installing an emoji pack via invite is rejected for missing permissions.',
|
||||
});
|
||||
const CANNOT_INSTALL_STICKER_PACK_DESCRIPTOR = msg({
|
||||
message: 'Cannot install sticker pack',
|
||||
comment: 'Title of the error modal when installing a sticker pack via invite is rejected for missing permissions.',
|
||||
});
|
||||
const YOU_DON_T_HAVE_PERMISSION_TO_INSTALL_THIS_DESCRIPTOR = msg({
|
||||
message: "You can't install this emoji pack.",
|
||||
comment: 'Body of the error modal when installing an emoji pack via invite is rejected for missing permissions.',
|
||||
});
|
||||
const YOU_DON_T_HAVE_PERMISSION_TO_INSTALL_THIS_2_DESCRIPTOR = msg({
|
||||
message: "You can't install this sticker pack.",
|
||||
comment: 'Body of the error modal when installing a sticker pack via invite is rejected for missing permissions.',
|
||||
});
|
||||
const UNABLE_TO_INSTALL_EMOJI_PACK_DESCRIPTOR = msg({
|
||||
message: 'Unable to install emoji pack',
|
||||
comment: 'Generic title for the error modal when an emoji pack invite fails with an unrecognized error code.',
|
||||
});
|
||||
const UNABLE_TO_INSTALL_STICKER_PACK_DESCRIPTOR = msg({
|
||||
message: 'Unable to install sticker pack',
|
||||
comment: 'Generic title for the error modal when a sticker pack invite fails with an unrecognized error code.',
|
||||
});
|
||||
const FAILED_TO_INSTALL_THIS_EMOJI_PACK_PLEASE_TRY_DESCRIPTOR = msg({
|
||||
message: "Couldn't install this emoji pack. Try again later.",
|
||||
comment: 'Generic body for the error modal when an emoji pack invite fails with an unrecognized error code.',
|
||||
});
|
||||
const FAILED_TO_INSTALL_THIS_STICKER_PACK_PLEASE_TRY_DESCRIPTOR = msg({
|
||||
message: "Couldn't install this sticker pack. Try again later.",
|
||||
comment: 'Generic body for the error modal when a sticker pack invite fails with an unrecognized error code.',
|
||||
});
|
||||
const logger = new Logger('Invites');
|
||||
const ACCEPT_INVITE_BODY = {} as Invite;
|
||||
const isUnclaimedAccountInviteError = (code?: string): boolean => {
|
||||
@@ -133,21 +63,6 @@ function guildInviteFeatures(invite: Invite | null): Array<string> {
|
||||
return invite && isGuildInvite(invite) && Array.isArray(invite.guild.features) ? invite.guild.features : [];
|
||||
}
|
||||
|
||||
function showPackInstalledToast(invite: Invite): void {
|
||||
if (!isPackInvite(invite)) {
|
||||
return;
|
||||
}
|
||||
ToastCommands.createToast({
|
||||
type: 'success',
|
||||
children:
|
||||
invite.pack.type === 'emoji' ? (
|
||||
<Trans>Emoji pack {invite.pack.name} has been installed.</Trans>
|
||||
) : (
|
||||
<Trans>Sticker pack {invite.pack.name} has been installed.</Trans>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
function removeInviteIfMissing(code: string, responseErr: HttpError | null, errorCode?: string): void {
|
||||
if (responseErr?.status === 404 || errorCode === APIErrorCodes.UNKNOWN_INVITE) {
|
||||
logger.debug(`Invite ${code} not found, removing from store`);
|
||||
@@ -283,11 +198,6 @@ export async function acceptAndTransitionToChannel(code: string, i18n: I18n): Pr
|
||||
if (!invite) {
|
||||
throw new Error(`Invite ${code} returned no data`);
|
||||
}
|
||||
if (isPackInvite(invite)) {
|
||||
await accept(code);
|
||||
showPackInstalledToast(invite);
|
||||
return;
|
||||
}
|
||||
if (isGroupDmInvite(invite)) {
|
||||
const channelId = invite.channel.id;
|
||||
logger.debug(`Accepting group DM invite ${code} and opening channel ${channelId}`);
|
||||
@@ -296,7 +206,7 @@ export async function acceptAndTransitionToChannel(code: string, i18n: I18n): Pr
|
||||
return;
|
||||
}
|
||||
if (!isGuildInvite(invite)) {
|
||||
throw new Error(`Invite ${code} is not a guild, group DM, or pack invite`);
|
||||
throw new Error(`Invite ${code} is not a guild or group DM invite`);
|
||||
}
|
||||
const channelId = invite.channel.id;
|
||||
const inviteTargetAllowed = shouldOpenInviteGuildChannel(invite.channel.type);
|
||||
@@ -324,9 +234,6 @@ export async function acceptAndTransitionToChannel(code: string, i18n: I18n): Pr
|
||||
const errorCode = failureCode(error);
|
||||
logger.error(`Failed to accept invite and transition for code ${code}:`, error);
|
||||
removeInviteIfMissing(code, responseErr, errorCode);
|
||||
if (handlePackInviteError({invite, errorCode, responseErr, i18n})) {
|
||||
throw error;
|
||||
}
|
||||
showGuildInviteAcceptFailure(i18n, invite, errorCode, responseErr);
|
||||
throw error;
|
||||
}
|
||||
@@ -342,169 +249,6 @@ export async function openAcceptModal(code: string): Promise<void> {
|
||||
);
|
||||
}
|
||||
|
||||
interface HandlePackInviteErrorParams {
|
||||
invite: Invite | null;
|
||||
errorCode?: string;
|
||||
responseErr?: HttpError | null;
|
||||
i18n: I18n;
|
||||
}
|
||||
|
||||
interface PackLimitPayload {
|
||||
packType?: 'emoji' | 'sticker';
|
||||
limit?: number;
|
||||
action?: 'create' | 'install';
|
||||
}
|
||||
|
||||
const getPackLimitPayload = (responseErr?: HttpError | null): PackLimitPayload | null => {
|
||||
const body = responseErr?.body;
|
||||
if (!body || typeof body !== 'object') return null;
|
||||
const record = body as Record<string, unknown>;
|
||||
const data = record.data;
|
||||
if (!data || typeof data !== 'object') return null;
|
||||
const dataRecord = data as Record<string, unknown>;
|
||||
const limit = dataRecord.limit;
|
||||
const packType = dataRecord.pack_type;
|
||||
const action = dataRecord.action;
|
||||
return {
|
||||
packType: packType === 'emoji' || packType === 'sticker' ? packType : undefined,
|
||||
limit: typeof limit === 'number' ? limit : undefined,
|
||||
action: action === 'create' || action === 'install' ? action : undefined,
|
||||
};
|
||||
};
|
||||
const buildPackLimitStrings = (
|
||||
i18n: I18n,
|
||||
packType: 'emoji' | 'sticker',
|
||||
action: 'install' | 'create',
|
||||
limit?: number,
|
||||
): {title: string; message: string} => {
|
||||
switch (packType) {
|
||||
case 'emoji': {
|
||||
switch (action) {
|
||||
case 'install': {
|
||||
const title = i18n._(EMOJI_PACK_LIMIT_REACHED_DESCRIPTOR);
|
||||
const message =
|
||||
typeof limit === 'number'
|
||||
? plural(
|
||||
{count: limit},
|
||||
{
|
||||
one: "You're at the limit of # installed emoji pack. Remove one to add another.",
|
||||
other: "You're at the limit of # installed emoji packs. Remove one to add another.",
|
||||
},
|
||||
)
|
||||
: i18n._(YOU_HAVE_REACHED_THE_LIMIT_FOR_INSTALLING_EMOJI_DESCRIPTOR);
|
||||
return {title, message};
|
||||
}
|
||||
default: {
|
||||
const title = i18n._(EMOJI_PACK_CREATION_LIMIT_REACHED_DESCRIPTOR);
|
||||
const message =
|
||||
typeof limit === 'number'
|
||||
? plural(
|
||||
{count: limit},
|
||||
{
|
||||
one: "You're at the limit of # emoji pack. Delete one to create another.",
|
||||
other: "You're at the limit of # emoji packs. Delete one to create another.",
|
||||
},
|
||||
)
|
||||
: i18n._(YOU_HAVE_REACHED_THE_LIMIT_FOR_CREATING_EMOJI_DESCRIPTOR);
|
||||
return {title, message};
|
||||
}
|
||||
}
|
||||
}
|
||||
default: {
|
||||
switch (action) {
|
||||
case 'install': {
|
||||
const title = i18n._(STICKER_PACK_LIMIT_REACHED_DESCRIPTOR);
|
||||
const message =
|
||||
typeof limit === 'number'
|
||||
? plural(
|
||||
{count: limit},
|
||||
{
|
||||
one: "You're at the limit of # installed sticker pack. Remove one to add another.",
|
||||
other: "You're at the limit of # installed sticker packs. Remove one to add another.",
|
||||
},
|
||||
)
|
||||
: i18n._(YOU_HAVE_REACHED_THE_LIMIT_FOR_INSTALLING_STICKER_DESCRIPTOR);
|
||||
return {title, message};
|
||||
}
|
||||
default: {
|
||||
const title = i18n._(STICKER_PACK_CREATION_LIMIT_REACHED_DESCRIPTOR);
|
||||
const message =
|
||||
typeof limit === 'number'
|
||||
? plural(
|
||||
{count: limit},
|
||||
{
|
||||
one: "You're at the limit of # sticker pack. Delete one to create another.",
|
||||
other: "You're at the limit of # sticker packs. Delete one to create another.",
|
||||
},
|
||||
)
|
||||
: i18n._(YOU_HAVE_REACHED_THE_LIMIT_FOR_CREATING_STICKER_DESCRIPTOR);
|
||||
return {title, message};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function handlePackInviteError(params: HandlePackInviteErrorParams): boolean {
|
||||
const {invite, errorCode, responseErr, i18n} = params;
|
||||
if (!invite || !isPackInvite(invite)) {
|
||||
return false;
|
||||
}
|
||||
const isEmojiPack = invite.pack.type === 'emoji';
|
||||
const cannotInstallTitle = isEmojiPack
|
||||
? i18n._(CANNOT_INSTALL_EMOJI_PACK_DESCRIPTOR)
|
||||
: i18n._(CANNOT_INSTALL_STICKER_PACK_DESCRIPTOR);
|
||||
const cannotInstallMessage = isEmojiPack
|
||||
? i18n._(YOU_DON_T_HAVE_PERMISSION_TO_INSTALL_THIS_DESCRIPTOR)
|
||||
: i18n._(YOU_DON_T_HAVE_PERMISSION_TO_INSTALL_THIS_2_DESCRIPTOR);
|
||||
const defaultTitle = isEmojiPack
|
||||
? i18n._(UNABLE_TO_INSTALL_EMOJI_PACK_DESCRIPTOR)
|
||||
: i18n._(UNABLE_TO_INSTALL_STICKER_PACK_DESCRIPTOR);
|
||||
const defaultMessage = isEmojiPack
|
||||
? i18n._(FAILED_TO_INSTALL_THIS_EMOJI_PACK_PLEASE_TRY_DESCRIPTOR)
|
||||
: i18n._(FAILED_TO_INSTALL_THIS_STICKER_PACK_PLEASE_TRY_DESCRIPTOR);
|
||||
if (errorCode === APIErrorCodes.MISSING_ACCESS) {
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<GenericErrorModal
|
||||
title={cannotInstallTitle}
|
||||
message={cannotInstallMessage}
|
||||
data-flx="invite.invite-commands.handle-pack-invite-error.generic-error-modal"
|
||||
/>
|
||||
)),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
if (errorCode === APIErrorCodes.MAX_PACKS) {
|
||||
const payload = getPackLimitPayload(responseErr);
|
||||
const packType = payload?.packType ?? invite.pack.type;
|
||||
const action = payload?.action ?? 'install';
|
||||
const limit = payload?.limit;
|
||||
const {title, message} = buildPackLimitStrings(i18n, packType, action, limit);
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<GenericErrorModal
|
||||
title={title}
|
||||
message={message}
|
||||
data-flx="invite.invite-commands.handle-pack-invite-error.generic-error-modal--2"
|
||||
/>
|
||||
)),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
const fallbackMessage = responseErr ? failureMessage(responseErr) : null;
|
||||
ModalCommands.push(
|
||||
modal(() => (
|
||||
<GenericErrorModal
|
||||
title={defaultTitle}
|
||||
message={fallbackMessage || defaultMessage}
|
||||
data-flx="invite.invite-commands.handle-pack-invite-error.generic-error-modal--3"
|
||||
/>
|
||||
)),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function create(
|
||||
channelId: string,
|
||||
params?: {max_age?: number; max_uses?: number; temporary?: boolean},
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {Endpoints} from '@app/features/app/constants/Endpoints';
|
||||
import {http} from '@app/features/platform/transport/RestTransport';
|
||||
import {Logger} from '@app/features/platform/utils/AppLogger';
|
||||
import type {PackInviteMetadataResponse} from '@fluxer/schema/src/domains/invite/InviteSchemas';
|
||||
|
||||
const logger = new Logger('PackInvites');
|
||||
|
||||
export interface CreatePackInviteParams {
|
||||
packId: string;
|
||||
maxUses?: number;
|
||||
maxAge?: number;
|
||||
unique?: boolean;
|
||||
}
|
||||
|
||||
interface PackInviteRequestBody {
|
||||
max_uses: number;
|
||||
max_age: number;
|
||||
unique: boolean;
|
||||
}
|
||||
|
||||
function packInviteRequestBody(params: CreatePackInviteParams): PackInviteRequestBody {
|
||||
return {
|
||||
max_uses: params.maxUses ?? 0,
|
||||
max_age: params.maxAge ?? 0,
|
||||
unique: params.unique ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
async function requestPackInvite(params: CreatePackInviteParams): Promise<PackInviteMetadataResponse> {
|
||||
const response = await http.post<PackInviteMetadataResponse>(Endpoints.PACK_INVITES(params.packId), {
|
||||
body: packInviteRequestBody(params),
|
||||
});
|
||||
return response.body;
|
||||
}
|
||||
|
||||
function rethrowPackInviteFailure(packId: string, error: unknown): never {
|
||||
logger.error(`Failed to create invite for pack ${packId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
export async function createInvite(params: CreatePackInviteParams): Promise<PackInviteMetadataResponse> {
|
||||
try {
|
||||
logger.debug(`Creating invite for pack ${params.packId}`);
|
||||
return await requestPackInvite(params);
|
||||
} catch (error) {
|
||||
rethrowPackInviteFailure(params.packId, error);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user