diff --git a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js
index 097fec257137..09f26460956a 100644
--- a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js
+++ b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js
@@ -41,6 +41,7 @@ import { formatProductPrice } from '../ProductPriceTag';
import AuthenticatedUserContext from '../../Profile/AuthenticatedUserContext';
import { PrivateAssetPackTile, PromoBundleAssetPackCard } from '../ShopTiles';
import { AssetStoreContext } from '../AssetStoreContext';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
const cellSpacing = 8;
@@ -290,7 +291,10 @@ const PrivateAssetPackInformationPage = ({
setAssetPack(assetPack);
setSellerPublicProfile(profile);
} catch (error) {
- if (error.response && error.response.status === 404) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
setErrorText(
Asset pack not found - An error occurred, please try again
diff --git a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackPurchaseDialog.js b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackPurchaseDialog.js
index daebbc79028f..48a2071e4f49 100644
--- a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackPurchaseDialog.js
+++ b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackPurchaseDialog.js
@@ -25,6 +25,7 @@ import {
purchaseAppStoreProduct,
} from '../../Utils/AppStorePurchases';
import Form from '../../UI/Form';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
const PasswordPromptDialog = (props: {
passwordValue: string,
@@ -131,10 +132,13 @@ const PrivateAssetPackPurchaseDialog = ({
});
Window.openExternalURL(checkoutUrl);
} catch (error) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
if (
- error.response &&
- error.response.status === 403 &&
- error.response.data.code === 'auth/wrong-password'
+ extractedStatusAndCode &&
+ extractedStatusAndCode.status === 403 &&
+ extractedStatusAndCode.code === 'auth/wrong-password'
) {
await showAlert({
title: t`Operation not allowed`,
diff --git a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetsAuthorizationProvider.js b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetsAuthorizationProvider.js
index 3e644740ee25..c929c2bb129f 100644
--- a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetsAuthorizationProvider.js
+++ b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetsAuthorizationProvider.js
@@ -18,6 +18,7 @@ import {
getAuthorizationTokenForPrivateAssets,
} from '../../Utils/GDevelopServices/Shop';
import PrivateAssetsAuthorizationContext from './PrivateAssetsAuthorizationContext';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
type Props = {| children: React.Node |};
@@ -94,7 +95,10 @@ const PrivateAssetsAuthorizationProvider = ({ children }: Props) => {
});
return asset;
} catch (error) {
- if (error.response && error.response.status === 404) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
// If the token is expired, fetch a new one and try again.
token = await fetchAuthorizationToken(userId);
const asset = await getPrivateAsset(assetShortHeader, token, {
diff --git a/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateInformationPage.js b/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateInformationPage.js
index 7fcc48899855..886becb81894 100644
--- a/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateInformationPage.js
+++ b/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateInformationPage.js
@@ -37,6 +37,7 @@ import { formatProductPrice } from '../ProductPriceTag';
import AuthenticatedUserContext from '../../Profile/AuthenticatedUserContext';
import { capitalize } from 'lodash';
import FlatButton from '../../UI/FlatButton';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
const styles = {
disabledText: { opacity: 0.6 },
@@ -123,7 +124,10 @@ const PrivateGameTemplateInformationPage = ({
setGameTemplate(gameTemplate);
setSellerPublicProfile(profile);
} catch (error) {
- if (error.response && error.response.status === 404) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
setErrorText(
Game template not found - An error occurred, please try again
diff --git a/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplatePurchaseDialog.js b/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplatePurchaseDialog.js
index c0dd5774a9cd..d213f16dc294 100644
--- a/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplatePurchaseDialog.js
+++ b/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplatePurchaseDialog.js
@@ -25,6 +25,7 @@ import {
purchaseAppStoreProduct,
} from '../../Utils/AppStorePurchases';
import Form from '../../UI/Form';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
const PasswordPromptDialog = (props: {
passwordValue: string,
@@ -131,10 +132,13 @@ const PrivateGameTemplatePurchaseDialog = ({
});
Window.openExternalURL(checkoutUrl);
} catch (error) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
if (
- error.response &&
- error.response.status === 403 &&
- error.response.data.code === 'auth/wrong-password'
+ extractedStatusAndCode &&
+ extractedStatusAndCode.status === 403 &&
+ extractedStatusAndCode.code === 'auth/wrong-password'
) {
await showAlert({
title: t`Operation not allowed`,
diff --git a/newIDE/app/src/ExportAndShare/ShareDialog/ExportLauncher.js b/newIDE/app/src/ExportAndShare/ShareDialog/ExportLauncher.js
index 5c66a47772a2..4898cd4d3a31 100644
--- a/newIDE/app/src/ExportAndShare/ShareDialog/ExportLauncher.js
+++ b/newIDE/app/src/ExportAndShare/ShareDialog/ExportLauncher.js
@@ -35,6 +35,7 @@ import {
addCreateBadgePreHookIfNotClaimed,
TRIVIAL_FIRST_WEB_EXPORT,
} from '../../Utils/GDevelopServices/Badge';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
type State = {|
exportStep: BuildStep,
@@ -169,8 +170,11 @@ export default class ExportLauncher extends Component {
try {
// Try to fetch the game to see if it's registered but do not do anything with it.
await getGame(getAuthorizationHeader, userId, gameId);
- } catch (err) {
- if (err.response.status === 404) {
+ } catch (error) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.code === 404) {
// If the game is not registered, register it before launching the export.
const authorName =
this.props.project.getAuthor() || 'Unspecified publisher';
diff --git a/newIDE/app/src/ExportAndShare/ShareDialog/InviteHome.js b/newIDE/app/src/ExportAndShare/ShareDialog/InviteHome.js
index e328911503f4..b67621f88a48 100644
--- a/newIDE/app/src/ExportAndShare/ShareDialog/InviteHome.js
+++ b/newIDE/app/src/ExportAndShare/ShareDialog/InviteHome.js
@@ -33,6 +33,7 @@ import useAlertDialog from '../../UI/Alert/useAlertDialog';
import SelectField from '../../UI/SelectField';
import SelectOption from '../../UI/SelectOption';
import Form from '../../UI/Form';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
export const emailRegex = /^(.+)@(.+)$/;
@@ -177,11 +178,14 @@ const InviteHome = ({ cloudProjectId }: Props) => {
setProjectUserAcls(collaboratorProjectUserAcls);
} catch (error) {
console.error('Unable to fetch the project user acls', error);
- if (error.response && error.response.status === 404) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
setFetchError('project-not-found');
return;
}
- if (error.response && error.response.status === 403) {
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 403) {
setFetchError('project-not-owned');
return;
}
@@ -263,35 +267,39 @@ const InviteHome = ({ cloudProjectId }: Props) => {
await fetchProjectUserAcls();
} catch (error) {
console.error('Unable to add collaborator', error);
- if (error.response && error.response.status === 400) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 400) {
if (
- error.response.data.code ===
+ extractedStatusAndCode.code ===
'project-user-acl-creation/user-already-added'
) {
setAddError('user-already-added');
return;
}
if (
- error.response.data.code === 'project-user-acl-creation/user-is-owner'
+ extractedStatusAndCode.code ===
+ 'project-user-acl-creation/user-is-owner'
) {
setAddError('user-owner');
return;
}
}
- if (error.response && error.response.status === 404) {
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
setAddError('user-not-found');
return;
}
- if (error.response && error.response.status === 403) {
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 403) {
if (
- error.response.data.code ===
+ extractedStatusAndCode.code ===
'project-user-acl-creation/collaborators-not-allowed'
) {
setAddError('not-allowed');
return;
}
if (
- error.response.data.code ===
+ extractedStatusAndCode.code ===
'project-user-acl-creation/too-many-guest-collaborators-on-project'
) {
setAddError('max-guest-collaborators');
diff --git a/newIDE/app/src/ExportAndShare/ShareDialog/index.js b/newIDE/app/src/ExportAndShare/ShareDialog/index.js
index 2d6f3befeba6..9ac05095b7df 100644
--- a/newIDE/app/src/ExportAndShare/ShareDialog/index.js
+++ b/newIDE/app/src/ExportAndShare/ShareDialog/index.js
@@ -19,6 +19,7 @@ import PreferencesContext from '../../MainFrame/Preferences/PreferencesContext';
import { type FileMetadata, type StorageProvider } from '../../ProjectsStorage';
import { useOnlineStatus } from '../../Utils/OnlineStatus';
import ErrorBoundary from '../../UI/ErrorBoundary';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
export type ShareTab = 'invite' | 'publish';
export type ExporterSection = 'browser' | 'desktop' | 'mobile';
@@ -184,13 +185,16 @@ const ShareDialog = ({
project.getProjectUuid()
);
setGame(game);
- } catch (err) {
- console.error('Unable to load the game', err);
- if (err && err.status === 404) {
+ } catch (error) {
+ console.error('Unable to load the game', error);
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
setGameError('not-found');
return;
}
- if (err && err.status === 403) {
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 403) {
setGameError('not-owned');
return;
}
diff --git a/newIDE/app/src/GameDashboard/GameRegistration.js b/newIDE/app/src/GameDashboard/GameRegistration.js
index e8a5d93f433f..6da3a768c6cf 100644
--- a/newIDE/app/src/GameDashboard/GameRegistration.js
+++ b/newIDE/app/src/GameDashboard/GameRegistration.js
@@ -13,6 +13,7 @@ import {
getGame,
registerGame,
} from '../Utils/GDevelopServices/Game';
+import { extractGDevelopApiErrorStatusAndCode } from '../Utils/GDevelopServices/Errors';
export type GameRegistrationProps = {|
project: ?gdProject,
@@ -65,19 +66,25 @@ export const GameRegistration = ({
);
setUnavailableReason(null);
setGame(game);
- } catch (err) {
- console.error(err);
- if (err.response) {
- if (err.response.status === 403) {
+ } catch (error) {
+ console.error(
+ `Unable to get the game ${project.getProjectUuid()}`,
+ error
+ );
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode) {
+ if (extractedStatusAndCode.status === 403) {
setUnavailableReason('unauthorized');
return;
- } else if (err.response.status === 404) {
+ } else if (extractedStatusAndCode.status === 404) {
setUnavailableReason('not-existing');
return;
}
}
- setError(err);
+ setError(error);
}
},
[project, getAuthorizationHeader, profile]
diff --git a/newIDE/app/src/GameDashboard/LeaderboardAdmin/index.js b/newIDE/app/src/GameDashboard/LeaderboardAdmin/index.js
index feb65ca57aaa..c3987e9376b7 100644
--- a/newIDE/app/src/GameDashboard/LeaderboardAdmin/index.js
+++ b/newIDE/app/src/GameDashboard/LeaderboardAdmin/index.js
@@ -72,6 +72,7 @@ import MaxLeaderboardCountAlertMessage from './MaxLeaderboardCountAlertMessage';
import useAlertDialog from '../../UI/Alert/useAlertDialog';
import Paper from '../../UI/Paper';
import SwitchHorizontal from '../../UI/CustomSvgIcons/SwitchHorizontal';
+import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
type Props = {|
onLoading: boolean => void,
@@ -312,12 +313,15 @@ export const LeaderboardAdmin = ({
setApiError(null);
try {
await listLeaderboards();
- } catch (err) {
- if (err.response && err.response.status === 404) {
+ } catch (error) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
setDisplayGameRegistration(true);
return;
}
- console.error('An error occurred when fetching leaderboards', err);
+ console.error('An error occurred when fetching leaderboards', error);
setApiError({
action: 'leaderboardsFetching',
message: (
@@ -406,12 +410,15 @@ export const LeaderboardAdmin = ({
setApiError(null);
try {
await resetLeaderboard();
- } catch (err) {
- console.error('An error occurred when resetting leaderboard', err);
+ } catch (error) {
+ console.error('An error occurred when resetting leaderboard', error);
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
setApiError({
action: 'leaderboardReset',
message:
- err.status && err.status === 409 ? (
+ extractedStatusAndCode && extractedStatusAndCode.status === 409 ? (
This leaderboard is already resetting, please wait a bit, close
the dialog, come back and try again.
diff --git a/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/ProjectFileListItem.js b/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/ProjectFileListItem.js
index 793a075e3ee9..8afb9ab00c21 100644
--- a/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/ProjectFileListItem.js
+++ b/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/ProjectFileListItem.js
@@ -36,6 +36,7 @@ import { type LastModifiedInfo } from './utils';
import DotBadge from '../../../../UI/DotBadge';
import { type FileMetadata } from '../../../../ProjectsStorage';
import StatusIndicator from './StatusIndicator';
+import { extractGDevelopApiErrorStatusAndCode } from '../../../../Utils/GDevelopServices/Errors';
const electron = optionalRequire('electron');
const path = optionalRequire('path');
@@ -260,8 +261,11 @@ export const ProjectFileListItem = ({
await deleteCloudProject(authenticatedUser, fileMetadata.fileIdentifier);
authenticatedUser.onCloudProjectsChanged();
} catch (error) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
const message =
- error.response && error.response.status === 403
+ extractedStatusAndCode && extractedStatusAndCode.status === 403
? t`You don't have permissions to delete this project.`
: t`An error occurred when saving the project. Please try again later.`;
showAlert({
diff --git a/newIDE/app/src/MainFrame/EditorContainers/HomePage/TeamSection/TeamSection.spec.js b/newIDE/app/src/MainFrame/EditorContainers/HomePage/TeamSection/TeamSection.spec.js
index 440db9f1ef60..801234a3f2ee 100644
--- a/newIDE/app/src/MainFrame/EditorContainers/HomePage/TeamSection/TeamSection.spec.js
+++ b/newIDE/app/src/MainFrame/EditorContainers/HomePage/TeamSection/TeamSection.spec.js
@@ -9,6 +9,7 @@ const getDefaultUser = ({ id }: { id: string }) => ({
description: null,
username: null,
donateLink: null,
+ discordUsername: null,
email: `${id}@email.net`,
getGameStatsEmail: false,
getNewsletterEmail: false,
diff --git a/newIDE/app/src/MainFrame/index.js b/newIDE/app/src/MainFrame/index.js
index 41d662e0be23..22de38246ca8 100644
--- a/newIDE/app/src/MainFrame/index.js
+++ b/newIDE/app/src/MainFrame/index.js
@@ -184,6 +184,7 @@ import useEditorTabsStateSaving from './EditorTabs/UseEditorTabsStateSaving';
import { type PrivateGameTemplateListingData } from '../Utils/GDevelopServices/Shop';
import PixiResourcesLoader from '../ObjectsRendering/PixiResourcesLoader';
import useResourcesWatcher from './ResourcesWatcher';
+import { extractGDevelopApiErrorStatusAndCode } from '../Utils/GDevelopServices/Errors';
const GD_STARTUP_TIMES = global.GD_STARTUP_TIMES || [];
const gd: libGDevelop = global.gd;
@@ -2489,8 +2490,11 @@ const MainFrame = (props: Props) => {
_replaceSnackMessage(i18n._(t`Project properly saved`));
}
} catch (error) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
const message =
- error.response && error.response.status === 403
+ extractedStatusAndCode && extractedStatusAndCode.status === 403
? t`You don't have permissions to save this project. Please choose another location.`
: t`An error occurred when saving the project. Please try again later.`;
showAlert({
diff --git a/newIDE/app/src/Profile/AuthenticatedUserProfileDetails.js b/newIDE/app/src/Profile/AuthenticatedUserProfileDetails.js
index 63543c435187..b74511b62506 100644
--- a/newIDE/app/src/Profile/AuthenticatedUserProfileDetails.js
+++ b/newIDE/app/src/Profile/AuthenticatedUserProfileDetails.js
@@ -58,6 +58,7 @@ const AuthenticatedUserProfileDetails = ({
? { ...authenticatedUser.profile, email: firebaseUser.email }
: null
}
+ subscription={authenticatedUser.subscription}
isAuthenticatedUserProfile
onOpenChangeEmailDialog={onOpenChangeEmailDialog}
onOpenEditProfileDialog={onOpenEditProfileDialog}
diff --git a/newIDE/app/src/Profile/AuthenticatedUserProvider.js b/newIDE/app/src/Profile/AuthenticatedUserProvider.js
index f168d3289397..8f8f1d263c77 100644
--- a/newIDE/app/src/Profile/AuthenticatedUserProvider.js
+++ b/newIDE/app/src/Profile/AuthenticatedUserProvider.js
@@ -52,6 +52,7 @@ import { Trans } from '@lingui/macro';
import Snackbar from '@material-ui/core/Snackbar';
import RequestDeduplicator from '../Utils/RequestDeduplicator';
import { burstCloudProjectAutoSaveCache } from '../ProjectsStorage/CloudStorageProvider/CloudProjectOpener';
+import { extractGDevelopApiErrorStatusAndCode } from '../Utils/GDevelopServices/Errors';
type Props = {|
authentication: Authentication,
@@ -419,7 +420,10 @@ export default class AuthenticatedUserProvider extends React.Component<
},
})),
error => {
- if (error.response.status === 404) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
console.warn(
'List recommendations endpoint returned 404, user might not have completed survey.'
);
@@ -773,6 +777,7 @@ export default class AuthenticatedUserProvider extends React.Component<
getNewsletterEmail: payload.getNewsletterEmail,
appLanguage: preferences.language,
donateLink: payload.donateLink,
+ discordUsername: payload.discordUsername,
communityLinks: payload.communityLinks,
survey: payload.survey,
}
diff --git a/newIDE/app/src/Profile/EditProfileDialog.js b/newIDE/app/src/Profile/EditProfileDialog.js
index 10371fcacaa4..96a8e9c739f4 100644
--- a/newIDE/app/src/Profile/EditProfileDialog.js
+++ b/newIDE/app/src/Profile/EditProfileDialog.js
@@ -14,6 +14,7 @@ import {
import {
communityLinksConfig,
donateLinkConfig,
+ discordUsernameConfig,
type UsernameAvailability,
type CommunityLinkType,
} from '../Utils/GDevelopServices/User';
@@ -111,6 +112,9 @@ const EditProfileDialog = ({
profile.description || ''
);
const [donateLink, setDonateLink] = React.useState(profile.donateLink || '');
+ const [discordUsername, setDiscordUsername] = React.useState(
+ profile.discordUsername || ''
+ );
const [personalWebsiteLink, setPersonalWebsiteLink] = React.useState(
communityLinks.personalWebsiteLink || ''
);
@@ -192,6 +196,7 @@ const EditProfileDialog = ({
getGameStatsEmail,
getNewsletterEmail,
donateLink,
+ discordUsername,
communityLinks: {
personalWebsiteLink,
personalWebsite2Link,
@@ -296,6 +301,20 @@ const EditProfileDialog = ({
isValidatingUsername={isValidatingUsername}
disabled={actionInProgress}
/>
+ Discord username}
+ fullWidth
+ translatableHintText={t`Your Discord username`}
+ onChange={(e, value) => {
+ setDiscordUsername(value);
+ }}
+ disabled={actionInProgress}
+ maxLength={discordUsernameConfig.maxLength}
+ helperMarkdownText={i18n._(
+ t`Add your Discord username to get access to a dedicated channel if you have a subscription! Join the [GDevelop Discord](https://discord.gg/gdevelop).`
+ )}
+ />
Bio}
diff --git a/newIDE/app/src/Profile/ProfileDetails.js b/newIDE/app/src/Profile/ProfileDetails.js
index 47f02c5406e4..adf8b74899f5 100644
--- a/newIDE/app/src/Profile/ProfileDetails.js
+++ b/newIDE/app/src/Profile/ProfileDetails.js
@@ -31,9 +31,17 @@ import Link from '../UI/Link';
import {
communityLinksConfig,
type CommunityLinks,
+ syncDiscordUsername,
} from '../Utils/GDevelopServices/User';
import { PrivateAssetPackTile } from '../AssetStore/ShopTiles';
import AuthenticatedUserContext from './AuthenticatedUserContext';
+import IconButton from '../UI/IconButton';
+import Refresh from '../UI/CustomSvgIcons/Refresh';
+import Check from '../UI/CustomSvgIcons/Check';
+import { MarkdownText } from '../UI/MarkdownText';
+import useAlertDialog from '../UI/Alert/useAlertDialog';
+import { type Subscription } from '../Utils/GDevelopServices/Usage';
+import { extractGDevelopApiErrorStatusAndCode } from '../Utils/GDevelopServices/Errors';
const getAssetPackColumnsFromWidth = (width: WidthType) => {
switch (width) {
@@ -90,12 +98,14 @@ type DisplayedProfile = {
username: ?string,
description: ?string,
donateLink: ?string,
+ discordUsername: ?string,
+isEmailAutogenerated?: boolean, // the "+" allows handling both public and private profile
+communityLinks?: CommunityLinks, // the "+" allows handling both public and private profile
};
type Props = {|
profile: ?DisplayedProfile,
+ subscription?: ?Subscription,
isAuthenticatedUserProfile?: boolean,
error?: ?Error,
onRetry?: () => void,
@@ -107,6 +117,7 @@ type Props = {|
const ProfileDetails = ({
profile,
+ subscription,
isAuthenticatedUserProfile,
error,
onRetry,
@@ -115,7 +126,9 @@ const ProfileDetails = ({
assetPacksListingDatas,
onAssetPackOpen,
}: Props) => {
+ const email = profile ? profile.email : null;
const donateLink = profile ? profile.donateLink : null;
+ const discordUsername = profile ? profile.discordUsername : null;
const communityLinks = (profile && profile.communityLinks) || {};
const personalWebsiteLink = communityLinks
? communityLinks.personalWebsiteLink
@@ -133,6 +146,49 @@ const ProfileDetails = ({
const discordServerLink = profile ? communityLinks.discordServerLink : null;
const windowWidth = useResponsiveWindowWidth();
const { receivedAssetPacks } = React.useContext(AuthenticatedUserContext);
+ const { getAuthorizationHeader } = React.useContext(AuthenticatedUserContext);
+ const { showAlert } = useAlertDialog();
+
+ const [
+ discordUsernameSyncStatus,
+ setDiscordUsernameSyncStatus,
+ ] = React.useState(null);
+
+ const onSyncDiscordUsername = React.useCallback(
+ async () => {
+ if (!profile) return;
+ setDiscordUsernameSyncStatus('syncing');
+ try {
+ await syncDiscordUsername(getAuthorizationHeader, profile.id);
+ setDiscordUsernameSyncStatus('success');
+ } catch (error) {
+ console.error('Error while syncing discord username:', error);
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(
+ error
+ );
+ if (
+ extractedStatusAndCode &&
+ extractedStatusAndCode.status === 400 &&
+ extractedStatusAndCode.code ===
+ 'discord-role-update/discord-user-not-found'
+ ) {
+ showAlert({
+ title: t`Discord user not found`,
+ message: t`Ensure you don't have any typo in your username and that you have joined the GDevelop Discord server.`,
+ });
+ return;
+ }
+ showAlert({
+ title: t`Discord username sync failed`,
+ message: t`Something went wrong while syncing your Discord username. Please try again later.`,
+ });
+ } finally {
+ // Wait a bit to avoid spam and allow showing the success icon.
+ setTimeout(() => setDiscordUsernameSyncStatus(null), 3000);
+ }
+ },
+ [getAuthorizationHeader, profile, showAlert]
+ );
const assetPackTiles = React.useMemo(
() => {
@@ -219,7 +275,7 @@ const ProfileDetails = ({
{({ i18n }) => (
-
+
)}
- {isAuthenticatedUserProfile && profile.email && (
+ {isAuthenticatedUserProfile && email && (
Email
- {profile.email}
+ {email}
+
+ )}
+ {(isAuthenticatedUserProfile || !!discordUsername) && ( // Always show on private profile.
+
+
+
+ Discord username
+
+ {isAuthenticatedUserProfile &&
+ !!subscription &&
+ !!subscription.planId &&
+ !!discordUsername && (
+
+ {discordUsernameSyncStatus === 'success' ? (
+
+ ) : (
+
+ )}
+
+ )}
+
+
+ {!isAuthenticatedUserProfile ? (
+ discordUsername
+ ) : !discordUsername ? (
+ !subscription || !subscription.planId ? (
+
+ ) : (
+
+ )
+ ) : (
+ <>
+ {discordUsername}
+ {(!subscription || !subscription.planId) && (
+ <>
+ {' - '}
+
+ >
+ )}
+ >
+ )}
+
)}
@@ -332,9 +441,7 @@ const ProfileDetails = ({
Donate link
-
- {profile.donateLink || No link defined.}
-
+ {donateLink || No link defined.}
)}
{isAuthenticatedUserProfile && (
diff --git a/newIDE/app/src/Profile/Subscription/SubscriptionPendingDialog.js b/newIDE/app/src/Profile/Subscription/SubscriptionPendingDialog.js
index aea2dba569a5..04b5ce557af5 100644
--- a/newIDE/app/src/Profile/Subscription/SubscriptionPendingDialog.js
+++ b/newIDE/app/src/Profile/Subscription/SubscriptionPendingDialog.js
@@ -1,5 +1,6 @@
// @flow
-import { Trans } from '@lingui/macro';
+import { Trans, t } from '@lingui/macro';
+import { I18n } from '@lingui/react';
import React from 'react';
import FlatButton from '../../UI/FlatButton';
@@ -11,6 +12,10 @@ import UserVerified from '../../UI/CustomSvgIcons/UserVerified';
import Text from '../../UI/Text';
import { useInterval } from '../../Utils/UseInterval';
import CircularProgress from '../../UI/CircularProgress';
+import TextField from '../../UI/TextField';
+import { discordUsernameConfig } from '../../Utils/GDevelopServices/User';
+import PreferencesContext from '../../MainFrame/Preferences/PreferencesContext';
+import LeftLoader from '../../UI/LeftLoader';
type Props = {|
onClose: Function,
@@ -33,99 +38,165 @@ export default function SubscriptionPendingDialog({
},
hasPlan ? null : 3900
);
+ const currentDiscordUsername =
+ !!authenticatedUser && !!authenticatedUser.profile
+ ? authenticatedUser.profile.discordUsername
+ : null;
+
+ const [discordUsername, setDiscordUsername] = React.useState('');
+ const [isLoading, setIsLoading] = React.useState(false);
+ const { values: preferences } = React.useContext(PreferencesContext);
+
+ const onEdit = React.useCallback(
+ async () => {
+ if (!authenticatedUser || !authenticatedUser.profile) return;
+ if (!discordUsername) return;
+ setIsLoading(true);
+ try {
+ await authenticatedUser.onEditProfile(
+ {
+ discordUsername,
+ },
+ preferences,
+ { throwError: false }
+ );
+ } catch (error) {
+ console.error('Error while editing profile:', error);
+ // Ignore errors, we will let the user retry in their profile.
+ } finally {
+ setIsLoading(false);
+ }
+ },
+ [authenticatedUser, discordUsername, preferences]
+ );
+
+ const onFinish = React.useCallback(
+ async () => {
+ // If the user has edited their Discord username, send it to the server before closing.
+ if (!!discordUsername) {
+ await onEdit();
+ }
+ onClose();
+ },
+ [onClose, onEdit, discordUsername]
+ );
return (
- }
- actions={[
- hasPlan ? (
- Done!}
- key="close"
- primary
- onClick={onClose}
- />
- ) : (
- Cancel and close}
- key="close"
- primary={false}
- onClick={onClose}
- />
- ),
- ]}
- onRequestClose={onClose}
- maxWidth="sm"
- open
- >
- {!hasPlan ? (
-
-
-
-
- Thanks for getting a subscription and supporting GDevelop!
- {' '}
- {'💜'}
-
-
-
-
-
-
- Your browser will now open to enter your payment details.
-
-
-
-
-
-
-
-
- Waiting for the subscription confirmation...
-
-
-
-
-
-
- Once you're done, come back to GDevelop and your account will be
- upgraded automatically, unlocking the extra exports and online
- services.
-
-
-
-
- ) : (
-
-
-
-
- Thanks for getting a subscription and supporting GDevelop!
- {' '}
- {'💜'}
-
-
-
-
-
-
-
- Your new plan is now activated.
-
-
-
-
-
-
-
- Your account is upgraded, with the extra exports and online
- services. If you wish to change later, come back to your profile
- and choose another plan.
-
-
-
-
+
+ {({ i18n }) => (
+
)}
-
+
);
}
diff --git a/newIDE/app/src/Utils/GDevelopServices/Authentication.js b/newIDE/app/src/Utils/GDevelopServices/Authentication.js
index 357b1d2fb9cb..262bd67d3d8f 100644
--- a/newIDE/app/src/Utils/GDevelopServices/Authentication.js
+++ b/newIDE/app/src/Utils/GDevelopServices/Authentication.js
@@ -33,6 +33,7 @@ export type Profile = {|
isStudent: boolean,
isEmailAutogenerated: boolean,
donateLink: ?string,
+ discordUsername: ?string,
communityLinks?: CommunityLinks,
survey?: UserSurvey,
@@ -66,6 +67,7 @@ export type EditForm = {|
+getGameStatsEmail: boolean,
+getNewsletterEmail: boolean,
+donateLink: string,
+ +discordUsername: string,
+communityLinks: CommunityLinks,
|};
@@ -77,6 +79,7 @@ export type PatchUserPayload = {
+appLanguage?: string,
+isCreator?: boolean,
+donateLink?: string,
+ +discordUsername?: string,
+communityLinks?: CommunityLinks,
+survey?: UserSurvey,
};
@@ -322,6 +325,7 @@ export default class Authentication {
appLanguage,
isCreator,
donateLink,
+ discordUsername,
communityLinks,
survey,
}: PatchUserPayload
@@ -342,6 +346,7 @@ export default class Authentication {
appLanguage,
isCreator,
donateLink,
+ discordUsername,
communityLinks,
survey,
},
diff --git a/newIDE/app/src/Utils/GDevelopServices/Badge.js b/newIDE/app/src/Utils/GDevelopServices/Badge.js
index d1c751ebdc50..13616f280806 100644
--- a/newIDE/app/src/Utils/GDevelopServices/Badge.js
+++ b/newIDE/app/src/Utils/GDevelopServices/Badge.js
@@ -3,6 +3,7 @@ import axios from 'axios';
import { GDevelopUserApi } from './ApiConfigs';
import { type AuthenticatedUser } from '../../Profile/AuthenticatedUserContext';
+import { extractGDevelopApiErrorStatusAndCode } from './Errors';
export const TRIVIAL_FIRST_EVENT = 'trivial_first-event';
export const TRIVIAL_FIRST_BEHAVIOR = 'trivial_first-behavior';
@@ -73,11 +74,12 @@ const createOrEnsureBadgeForUser = async (
);
onBadgesChanged();
return response.data;
- } catch (err) {
- if (err.response && err.response.status === 409) {
+ } catch (error) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(error);
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 409) {
console.warn('Badge already exists');
} else {
- throw err;
+ throw error;
}
}
};
diff --git a/newIDE/app/src/Utils/GDevelopServices/Project.js b/newIDE/app/src/Utils/GDevelopServices/Project.js
index 58f8b4a72729..e15ba49fd9ea 100644
--- a/newIDE/app/src/Utils/GDevelopServices/Project.js
+++ b/newIDE/app/src/Utils/GDevelopServices/Project.js
@@ -9,6 +9,7 @@ import PromisePool from '@supercharge/promise-pool';
import { getFileSha512TruncatedTo256 } from '../FileHasher';
import { isNativeMobileApp } from '../Platform';
import { unzipFirstEntryOfBlob } from '../Zip.js/Utils';
+import { extractGDevelopApiErrorStatusAndCode } from './Errors';
export const CLOUD_PROJECT_NAME_MAX_LENGTH = 50;
export const PROJECT_RESOURCE_MAX_SIZE_IN_BYTES = 15 * 1000 * 1000;
@@ -153,7 +154,8 @@ const refetchCredentialsForProjectAndRetryIfUnauthorized = async (
const response = await apiCall();
return response;
} catch (error) {
- if (error.response && error.response.status === 403) {
+ const extractedStatusAndCode = extractGDevelopApiErrorStatusAndCode(error);
+ if (extractedStatusAndCode && extractedStatusAndCode.status === 403) {
await getCredentialsForCloudProject(authenticatedUser, cloudProjectId);
const response = await apiCall();
return response;
diff --git a/newIDE/app/src/Utils/GDevelopServices/User.js b/newIDE/app/src/Utils/GDevelopServices/User.js
index 24d648354aa3..fd0c8c7ddd6a 100644
--- a/newIDE/app/src/Utils/GDevelopServices/User.js
+++ b/newIDE/app/src/Utils/GDevelopServices/User.js
@@ -116,6 +116,7 @@ export type UserPublicProfile = {|
username: ?string,
description: ?string,
donateLink: ?string,
+ discordUsername: ?string,
communityLinks: CommunityLinks,
iconUrl: string,
|};
@@ -337,6 +338,21 @@ export const getUsernameAvailability = async (
return response.data;
};
+export const syncDiscordUsername = async (
+ getAuthorizationHeader: () => Promise,
+ userId: string
+): Promise => {
+ const authorizationHeader = await getAuthorizationHeader();
+ await axios.post(
+ `${GDevelopUserApi.baseUrl}/user/${userId}/action/update-discord-role`,
+ {},
+ {
+ headers: { Authorization: authorizationHeader },
+ params: { userId },
+ }
+ );
+};
+
const simpleUrlRegex = /^https:\/\/[^ ]+$/;
const profileLinkFormattingErrorMessage = (
Please enter a valid URL, starting with https://
@@ -358,6 +374,10 @@ export const donateLinkConfig = {
maxLength: 150,
};
+export const discordUsernameConfig = {
+ maxLength: 32,
+};
+
export const communityLinksConfig = {
personalWebsiteLink: {
icon: ,
diff --git a/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeBehaviorsRegistry.js b/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeBehaviorsRegistry.js
index 074e36c97d12..fe32c518990f 100644
--- a/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeBehaviorsRegistry.js
+++ b/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeBehaviorsRegistry.js
@@ -69,6 +69,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: '4ian',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -102,6 +103,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: '4ian',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -110,6 +112,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -161,6 +164,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Bouh',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -191,6 +195,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Bouh',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -225,6 +230,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: '4ian',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -233,6 +239,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -263,6 +270,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -294,6 +302,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -330,6 +339,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -338,6 +348,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -373,6 +384,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -381,6 +393,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -415,6 +428,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: '4ian',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -423,6 +437,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -479,6 +494,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -487,6 +503,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -521,6 +538,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -529,6 +547,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -563,6 +582,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -571,6 +591,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -605,6 +626,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -613,6 +635,7 @@ export const fakeBehaviorsRegistry: BehaviorsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
diff --git a/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeExtensionsRegistry.js b/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeExtensionsRegistry.js
index 3247e9f467ab..c767fe8d3b18 100644
--- a/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeExtensionsRegistry.js
+++ b/newIDE/app/src/fixtures/GDevelopServicesTestData/FakeExtensionsRegistry.js
@@ -38,6 +38,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake author',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -46,6 +47,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -75,6 +77,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake author',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -83,6 +86,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -113,6 +117,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'arthuro555',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -142,6 +147,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #EQ2',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -172,6 +178,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: '4ian',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -202,6 +209,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'arthuro555',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -231,6 +239,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Bouh',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -259,6 +268,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'arthuro555',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -288,6 +298,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #oj2',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -317,6 +328,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #pn1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -348,6 +360,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #2w2',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -356,6 +369,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -385,6 +399,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake author',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -393,6 +408,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -422,6 +438,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: '4ian',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -454,6 +471,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -462,6 +480,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Gx1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -494,6 +513,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -502,6 +522,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #YV2',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -532,6 +553,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -561,6 +583,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -592,6 +615,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #YV2',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -600,6 +624,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Bouh',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -629,6 +654,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Tw1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -660,6 +686,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Bouh',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -668,6 +695,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'arthuro555',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -701,6 +729,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -709,6 +738,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #pn1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -717,6 +747,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -745,6 +776,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'arthuro555',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -775,6 +807,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -805,6 +838,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -835,6 +869,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Tw1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -864,6 +899,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -896,6 +932,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'arthuro555',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -904,6 +941,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Bouh',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -933,6 +971,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -962,6 +1001,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'arthuro555',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -991,6 +1031,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #xJ3',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -1023,6 +1064,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #oq2',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -1031,6 +1073,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -1060,6 +1103,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -1093,6 +1137,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'D8H',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -1101,6 +1146,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake user #Cg1',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
@@ -1130,6 +1176,7 @@ export const fakeExtensionsRegistry: ExtensionsRegistry & {
username: 'Fake author',
description: '',
donateLink: null,
+ discordUsername: null,
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
},
diff --git a/newIDE/app/src/fixtures/GDevelopServicesTestData/index.js b/newIDE/app/src/fixtures/GDevelopServicesTestData/index.js
index 68a03759a1ee..f5874c072607 100644
--- a/newIDE/app/src/fixtures/GDevelopServicesTestData/index.js
+++ b/newIDE/app/src/fixtures/GDevelopServicesTestData/index.js
@@ -150,6 +150,7 @@ export const indieUserProfile: Profile = {
isStudent: false,
isEmailAutogenerated: false,
donateLink: 'https://www.paypal.me/indie-user',
+ discordUsername: 'indie-user#1234',
communityLinks: {
personalWebsiteLink: 'https://indie-user.com',
personalWebsite2Link: 'https://indie-user2.com',
diff --git a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js
index 6bebfa60e62a..ad2cb1ca9b96 100644
--- a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js
+++ b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js
@@ -79,6 +79,7 @@ PrivateAsset.parameters = {
username: 'Clem',
description: "I'm Clement\n\ntada",
donateLink: 'https://ko-fi/clem',
+ discordUsername: 'indie-user#1234',
personalWebsiteLink: 'https://indie-user.com',
personalWebsite2Link: 'https://indie-user2.com',
twitterUsername: 'indie-user',
@@ -131,6 +132,7 @@ PrivateAsset.parameters = {
username: 'Clem',
description: "I'm Clement\n\ntada",
donateLink: 'https://ko-fi/clem',
+ discordUsername: 'indie-user#1234',
personalWebsiteLink: 'https://indie-user.com',
personalWebsite2Link: 'https://indie-user2.com',
twitterUsername: 'indie-user',
@@ -147,6 +149,7 @@ PrivateAsset.parameters = {
username: 'Clem2',
description: "I'm Clement 2\n\ntada",
donateLink: 'https://ko-fi/clem2',
+ discordUsername: 'indie-user#12345',
personalWebsiteLink: 'https://indie-user.com',
personalWebsite2Link: 'https://indie-user2.com',
twitterUsername: 'indie-user',
diff --git a/newIDE/app/src/stories/componentStories/Profile/EditProfileDialog.stories.js b/newIDE/app/src/stories/componentStories/Profile/EditProfileDialog.stories.js
index 6cc28d602a38..62f792d314e4 100644
--- a/newIDE/app/src/stories/componentStories/Profile/EditProfileDialog.stories.js
+++ b/newIDE/app/src/stories/componentStories/Profile/EditProfileDialog.stories.js
@@ -33,6 +33,7 @@ const defaultProps = {
updatedAt: 12345,
appLanguage: 'en',
donateLink: 'https://www.gdevelop-app.com',
+ discordUsername: 'indie-user#1234',
communityLinks: {
personalWebsiteLink: 'https://indie-user.com',
personalWebsite2Link: 'https://indie-user2.com',
diff --git a/newIDE/app/src/stories/componentStories/Profile/Subscription/SubscriptionPendingDialog.stories.js b/newIDE/app/src/stories/componentStories/Profile/Subscription/SubscriptionPendingDialog.stories.js
index a97e55923e3b..de4cda8f1e1c 100644
--- a/newIDE/app/src/stories/componentStories/Profile/Subscription/SubscriptionPendingDialog.stories.js
+++ b/newIDE/app/src/stories/componentStories/Profile/Subscription/SubscriptionPendingDialog.stories.js
@@ -5,6 +5,7 @@ import { action } from '@storybook/addon-actions';
import muiDecorator from '../../../ThemeDecorator';
import paperDecorator from '../../../PaperDecorator';
import {
+ indieUserProfile,
fakeSilverAuthenticatedUser,
fakeAuthenticatedUserWithNoSubscription,
} from '../../../../fixtures/GDevelopServicesTestData';
@@ -22,9 +23,25 @@ export const DefaultNoSubscription = () => (
onClose={action('on close')}
/>
);
-export const AuthenticatedUserWithSubscription = () => (
+
+export const AuthenticatedUserWithSubscriptionAndDiscordUsernameAlreadyFilled = () => (
);
+
+const fakeProfileWithoutDiscordUsername = {
+ ...indieUserProfile,
+ discordUsername: '',
+};
+
+export const AuthenticatedUserWithSubscriptionButWithoutDiscordUsername = () => (
+
+);
diff --git a/newIDE/app/src/stories/componentStories/ProfileDetails.stories.js b/newIDE/app/src/stories/componentStories/ProfileDetails.stories.js
index ed9ffe7290ee..e95adedd1233 100644
--- a/newIDE/app/src/stories/componentStories/ProfileDetails.stories.js
+++ b/newIDE/app/src/stories/componentStories/ProfileDetails.stories.js
@@ -6,7 +6,10 @@ import muiDecorator from '../ThemeDecorator';
import paperDecorator from '../PaperDecorator';
import ProfileDetails from '../../Profile/ProfileDetails';
-import { indieUserProfile } from '../../fixtures/GDevelopServicesTestData';
+import {
+ indieUserProfile,
+ subscriptionForBusinessUser,
+} from '../../fixtures/GDevelopServicesTestData';
import { type Profile } from '../../Utils/GDevelopServices/Authentication';
import { type PrivateAssetPackListingData } from '../../Utils/GDevelopServices/Shop';
@@ -51,17 +54,43 @@ const getAssetPacksListingData = (
},
];
-export const MyProfile = () => (
+export const MyCompleteProfileWithSubscription = () => (
+
+);
+
+export const MyCompleteProfileWithoutSubscription = () => (
);
+export const MyProfileWithoutDiscordUsernameNorSubscription = () => (
+
+);
+
+export const MyProfileWithoutDiscordUsernameButWithSubscription = () => (
+
+);
+
export const OtherUserProfile = () => (
);
-export const IncompleteUserProfile = () => (
+export const OtherUserIncompleteProfile = () => (
);
diff --git a/newIDE/app/src/stories/componentStories/PublicProfileDialog.stories.js b/newIDE/app/src/stories/componentStories/PublicProfileDialog.stories.js
index 1ec5407af6df..5f96c644830d 100644
--- a/newIDE/app/src/stories/componentStories/PublicProfileDialog.stories.js
+++ b/newIDE/app/src/stories/componentStories/PublicProfileDialog.stories.js
@@ -17,6 +17,7 @@ const indieUserWithoutUsernameNorDescriptionProfile: Profile = {
username: null,
description: null,
donateLink: null,
+ discordUsername: null,
communityLinks: {},
};
diff --git a/newIDE/app/src/stories/componentStories/UserChip/UserPublicProfileChip.stories.js b/newIDE/app/src/stories/componentStories/UserChip/UserPublicProfileChip.stories.js
index dc69a20adc7c..175f15e52ae0 100644
--- a/newIDE/app/src/stories/componentStories/UserChip/UserPublicProfileChip.stories.js
+++ b/newIDE/app/src/stories/componentStories/UserChip/UserPublicProfileChip.stories.js
@@ -19,6 +19,7 @@ export const UserPublicProfileChip = () => (
username: 'username',
description: 'something',
donateLink: 'https://myurl.com',
+ discordUsername: 'username#1234',
communityLinks: {},
iconUrl: 'https://resources.gdevelop-app.com/avatars/4ian.png',
}}