Use premium colors in most places where a subscription can be purchased (#7284)

This commit is contained in:
Clément Pasteau
2025-01-06 20:56:49 +01:00
committed by GitHub
parent 3d80709029
commit fbf9710cc5
17 changed files with 268 additions and 401 deletions

View File

@@ -3,66 +3,87 @@ import * as React from 'react';
import { Trans } from '@lingui/macro';
import Text from '../../UI/Text';
import RaisedButton from '../../UI/RaisedButton';
import AlertMessage from '../../UI/AlertMessage';
import { Line, Column } from '../../UI/Grid';
import { type Limits } from '../../Utils/GDevelopServices/Usage';
import GetSubscriptionCard from '../../Profile/Subscription/GetSubscriptionCard';
import AuthenticatedUserContext, {
type AuthenticatedUser,
} from '../../Profile/AuthenticatedUserContext';
import { type Leaderboard } from '../../Utils/GDevelopServices/Play';
import { hasValidSubscriptionPlan } from '../../Utils/GDevelopServices/Usage';
type Props = {|
onUpgrade: () => void,
onClose: () => void,
limits: Limits,
|};
export const checkIfHasTooManyLeaderboards = (
authenticatedUser: AuthenticatedUser,
leaderboards: ?Array<Leaderboard>
) => {
if (!authenticatedUser.authenticated) return false;
const { limits } = authenticatedUser;
if (!limits) return false;
const leaderboardLimits = limits.capabilities.leaderboards;
return (
leaderboards &&
leaderboardLimits &&
leaderboardLimits.maximumCountPerGame > 0 &&
leaderboards.filter(leaderboard => !leaderboard.deletedAt).length >=
leaderboardLimits.maximumCountPerGame
);
};
const MaxLeaderboardCountAlertMessage = () => {
const authenticatedUser = React.useContext(AuthenticatedUserContext);
const { limits, subscription } = authenticatedUser;
if (!limits) return null;
const hasValidSubscription = hasValidSubscriptionPlan(subscription);
const MaxLeaderboardCountAlertMessage = ({
onUpgrade,
onClose,
limits,
}: Props) => {
const leaderboardLimits = limits.capabilities.leaderboards;
if (!leaderboardLimits) return null;
return (
<Line>
<Column expand>
<AlertMessage
kind="warning"
onHide={onClose}
renderRightButton={
leaderboardLimits.canMaximumCountPerGameBeIncreased
? () => (
<RaisedButton
primary
label={<Trans>Check our premiums plans</Trans>}
onClick={onUpgrade}
/>
)
: undefined
}
>
<Text size="block-title">
<Trans>
You've reached your maximum of{' '}
{leaderboardLimits.maximumCountPerGame} leaderboards for your game
</Trans>
</Text>
<Text>
{leaderboardLimits.canMaximumCountPerGameBeIncreased ? (
<Trans>
Upgrade to GDevelop Premium to get more leaderboards, storage,
and one-click packagings!
</Trans>
<GetSubscriptionCard
subscriptionDialogOpeningReason="Leaderboard count per game limit reached"
label={
!hasValidSubscription ? (
<Trans>Upgrade to GDevelop Premium</Trans>
) : (
// This should not happen at the moment since leaderboards are unlimited
// in any paid plans but it could happen in the future with a plan that
// cannot be increased and that has a max number of leaderboards.
<Trans>
To keep using GDevelop leaderboards, consider deleting old,
unused leaderboards.
</Trans>
)}
</Text>
</AlertMessage>
<Trans>Upgrade your Premium Plan</Trans>
)
}
hideButton={!leaderboardLimits.canMaximumCountPerGameBeIncreased}
>
<Line>
<Column noMargin expand>
<Text size="block-title">
<Trans>
You've reached your maximum of{' '}
{leaderboardLimits.maximumCountPerGame} leaderboards for your
game
</Trans>
</Text>
<Text>
{leaderboardLimits.canMaximumCountPerGameBeIncreased ? (
<Trans>
Upgrade to GDevelop Premium to get more leaderboards,
storage, and one-click packagings!
</Trans>
) : (
// This should not happen at the moment since leaderboards are unlimited
// in any paid plans but it could happen in the future with a plan that
// cannot be increased and that has a max number of leaderboards.
<Trans>
To keep using GDevelop leaderboards, consider deleting old,
unused leaderboards.
</Trans>
)}
</Text>
</Column>
</Line>
</GetSubscriptionCard>
</Column>
</Line>
);

View File

@@ -66,8 +66,9 @@ import LeaderboardOptionsDialog, {
import { formatScore } from '../../Leaderboard/LeaderboardScoreFormatter';
import Toggle from '../../UI/Toggle';
import AuthenticatedUserContext from '../../Profile/AuthenticatedUserContext';
import { SubscriptionSuggestionContext } from '../../Profile/Subscription/SubscriptionSuggestionContext';
import MaxLeaderboardCountAlertMessage from './MaxLeaderboardCountAlertMessage';
import MaxLeaderboardCountAlertMessage, {
checkIfHasTooManyLeaderboards,
} from './MaxLeaderboardCountAlertMessage';
import useAlertDialog from '../../UI/Alert/useAlertDialog';
import Paper from '../../UI/Paper';
import SwitchHorizontal from '../../UI/CustomSvgIcons/SwitchHorizontal';
@@ -234,9 +235,6 @@ export const LeaderboardAdmin = ({
fetchLeaderboardEntries,
browsing: { entries, goToNextPage, goToPreviousPage, goToFirstPage },
} = React.useContext(LeaderboardContext);
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
const setIsLoading = React.useCallback(
(yesOrNo: boolean) => {
@@ -332,13 +330,7 @@ export const LeaderboardAdmin = ({
setApiError(null);
try {
if (limits && leaderboards) {
const leaderboardLimits = limits.capabilities.leaderboards;
if (
leaderboardLimits &&
leaderboardLimits.maximumCountPerGame > 0 &&
leaderboards.filter(leaderboard => !leaderboard.deletedAt).length >=
leaderboardLimits.maximumCountPerGame
) {
if (checkIfHasTooManyLeaderboards(authenticatedUser, leaderboards)) {
setDisplayMaxLeaderboardCountReachedWarning(true);
return;
}
@@ -907,20 +899,8 @@ export const LeaderboardAdmin = ({
{({ i18n }) => (
<>
<Column noMargin expand>
{displayMaxLeaderboardCountReachedWarning && limits && (
<MaxLeaderboardCountAlertMessage
onUpgrade={() =>
openSubscriptionDialog({
analyticsMetadata: {
reason: 'Leaderboard count per game limit reached',
},
})
}
onClose={() =>
setDisplayMaxLeaderboardCountReachedWarning(false)
}
limits={limits}
/>
{displayMaxLeaderboardCountReachedWarning && (
<MaxLeaderboardCountAlertMessage />
)}
<ResponsiveLineStackLayout
noMargin

View File

@@ -3,16 +3,14 @@ import * as React from 'react';
import { Trans } from '@lingui/macro';
import Text from '../../../../UI/Text';
import RaisedButton from '../../../../UI/RaisedButton';
import AlertMessage from '../../../../UI/AlertMessage';
import { Line, Column } from '../../../../UI/Grid';
import { type Limits } from '../../../../Utils/GDevelopServices/Usage';
import { type AuthenticatedUser } from '../../../../Profile/AuthenticatedUserContext';
import Gold from '../../../../Profile/Subscription/Icons/Gold';
import AuthenticatedUserContext, {
type AuthenticatedUser,
} from '../../../../Profile/AuthenticatedUserContext';
import GetSubscriptionCard from '../../../../Profile/Subscription/GetSubscriptionCard';
import { hasValidSubscriptionPlan } from '../../../../Utils/GDevelopServices/Usage';
type Props = {|
onUpgrade: () => void,
limits: Limits,
margin?: 'dense',
|};
@@ -31,49 +29,34 @@ export const checkIfHasTooManyCloudProjects = (
: false;
};
export const MaxProjectCountAlertMessage = ({
onUpgrade,
limits,
margin,
}: Props) => {
export const MaxProjectCountAlertMessage = ({ margin }: Props) => {
const authenticatedUser = React.useContext(AuthenticatedUserContext);
const { limits, subscription } = authenticatedUser;
if (!limits) return null;
const hasValidSubscription = hasValidSubscriptionPlan(subscription);
const {
maximumCount,
canMaximumCountBeIncreased,
} = limits.capabilities.cloudProjects;
return (
<Line noMargin>
<Column noMargin expand>
<AlertMessage
kind="warning"
renderLeftIcon={() => (
<Gold
style={{
width: 48,
height: 48,
}}
/>
)}
renderRightButton={
canMaximumCountBeIncreased
? () => (
<Column noMargin>
<RaisedButton
primary
label={
margin === 'dense' ? (
<Trans>Upgrade</Trans>
) : (
<Trans>Upgrade to GDevelop Premium</Trans>
)
}
onClick={onUpgrade}
/>
</Column>
)
: undefined
}
>
<GetSubscriptionCard
subscriptionDialogOpeningReason="Cloud Project limit reached"
label={
margin === 'dense' ? (
<Trans>Upgrade</Trans>
) : !hasValidSubscription ? (
<Trans>Upgrade to GDevelop Premium</Trans>
) : (
<Trans>Upgrade your Premium Plan</Trans>
)
}
hideButton={!canMaximumCountBeIncreased}
>
<Line noMargin={margin === 'dense'}>
<Column noMargin expand>
<Text
size={margin === 'dense' ? 'sub-title' : 'block-title'}
noMargin={margin === 'dense'}
@@ -89,7 +72,7 @@ export const MaxProjectCountAlertMessage = ({
</Text>
<Text noMargin={margin === 'dense'}>
{canMaximumCountBeIncreased ? (
maximumCount === 1 ? (
!hasValidSubscription ? (
<Trans>
Thanks for trying GDevelop! Unlock more projects, publishing,
multiplayer, courses and much more by upgrading.
@@ -107,8 +90,8 @@ export const MaxProjectCountAlertMessage = ({
</Trans>
)}
</Text>
</AlertMessage>
</Column>
</Line>
</Column>
</Line>
</GetSubscriptionCard>
);
};

View File

@@ -47,7 +47,6 @@ import {
checkIfHasTooManyCloudProjects,
MaxProjectCountAlertMessage,
} from './MaxProjectCountAlertMessage';
import { SubscriptionSuggestionContext } from '../../../../Profile/Subscription/SubscriptionSuggestionContext';
import { useProjectsListFor } from './utils';
import { deleteCloudProject } from '../../../../Utils/GDevelopServices/Project';
import { getDefaultRegisterGameProperties } from '../../../../Utils/UseGameAndBuildsManager';
@@ -149,9 +148,6 @@ const CreateSection = ({
const { routeArguments, removeRouteArguments } = React.useContext(
RouterContext
);
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
// $FlowIgnore
const quickCustomizationRecommendation: ?QuickCustomizationRecommendation = React.useMemo(
() => {
@@ -450,20 +446,11 @@ const CreateSection = ({
<SectionContainer
flexBody
renderFooter={
!isMobile && limits && hasTooManyCloudProjects
!isMobile && hasTooManyCloudProjects
? () => (
<Line>
<Column expand>
<MaxProjectCountAlertMessage
limits={limits}
onUpgrade={() =>
openSubscriptionDialog({
analyticsMetadata: {
reason: 'Cloud Project limit reached',
},
})
}
/>
<MaxProjectCountAlertMessage />
</Column>
</Line>
)
@@ -538,18 +525,8 @@ const CreateSection = ({
searchText={searchText}
setSearchText={setSearchText}
/>
{isMobile && limits && hasTooManyCloudProjects && (
<MaxProjectCountAlertMessage
margin="dense"
limits={limits}
onUpgrade={() =>
openSubscriptionDialog({
analyticsMetadata: {
reason: 'Cloud Project limit reached',
},
})
}
/>
{isMobile && hasTooManyCloudProjects && (
<MaxProjectCountAlertMessage margin="dense" />
)}
{quickCustomizationRecommendation && (
<ColumnStackLayout noMargin>

View File

@@ -39,6 +39,9 @@ type Props = {|
label: React.Node,
onPayWithCredits: () => void,
|},
onUpgrade?: () => void,
forceColumnLayout?: boolean,
filter?: 'individual' | 'team' | 'education',
|};
const GetSubscriptionCard = ({
@@ -47,21 +50,26 @@ const GetSubscriptionCard = ({
label,
hideButton,
payWithCreditsOptions,
onUpgrade,
forceColumnLayout,
filter,
}: Props) => {
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
const { isMobile } = useResponsiveWindowSize();
const columnLayout = forceColumnLayout || isMobile;
return (
<div className={classes.premiumContainer}>
<Paper style={styles.paper} background="medium">
<Line expand alignItems="center" noMargin={!isMobile}>
<Line expand alignItems="center" noMargin={!columnLayout}>
<img src="res/diamond.svg" style={styles.diamondIcon} alt="diamond" />
<Column expand justifyContent="center">
<ResponsiveLineStackLayout
alignItems="center"
noColumnMargin
noMargin
forceMobileLayout={columnLayout}
>
<Column noMargin expand>
{children}
@@ -79,10 +87,14 @@ const GetSubscriptionCard = ({
label={label || <Trans>Upgrade</Trans>}
primary
onClick={() => {
if (onUpgrade) {
onUpgrade();
}
openSubscriptionDialog({
analyticsMetadata: {
reason: subscriptionDialogOpeningReason,
},
filter,
});
}}
icon={<CrownShining fontSize="small" />}

View File

@@ -3,20 +3,19 @@
import * as React from 'react';
import { Trans } from '@lingui/macro';
import FlatButton from '../../UI/FlatButton';
import Dialog, { DialogPrimaryButton } from '../../UI/Dialog';
import Star from '@material-ui/icons/Star';
import Favorite from '@material-ui/icons/Favorite';
import Dialog from '../../UI/Dialog';
import AuthenticatedUserContext from '../AuthenticatedUserContext';
import { Column, LargeSpacer, Line } from '../../UI/Grid';
import { Column } from '../../UI/Grid';
import {
sendSubscriptionCheckDialogShown,
sendSubscriptionCheckDismiss,
} from '../../Utils/Analytics/EventSender';
import { SubscriptionSuggestionContext } from './SubscriptionSuggestionContext';
import Text from '../../UI/Text';
import { hasValidSubscriptionPlan } from '../../Utils/GDevelopServices/Usage';
import { isNativeMobileApp } from '../../Utils/Platform';
import InAppTutorialContext from '../../InAppTutorial/InAppTutorialContext';
import GetSubscriptionCard from './GetSubscriptionCard';
import { ColumnStackLayout } from '../../UI/Layout';
export type SubscriptionCheckerInterface = {|
checkUserHasSubscription: () => boolean,
@@ -35,11 +34,6 @@ type Props = {|
isNotShownDuringInAppTutorial?: boolean,
|};
const styles = {
icon: { width: 40, height: 40, marginRight: 20 },
iconText: { flex: 1 },
};
const SubscriptionChecker = React.forwardRef<
Props,
SubscriptionCheckerInterface
@@ -50,9 +44,6 @@ const SubscriptionChecker = React.forwardRef<
) => {
const authenticatedUser = React.useContext(AuthenticatedUserContext);
const [dialogOpen, setDialogOpen] = React.useState<boolean>(false);
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
const closeDialog = () => {
sendSubscriptionCheckDismiss();
@@ -94,7 +85,7 @@ const SubscriptionChecker = React.forwardRef<
return (
<Dialog
open={dialogOpen}
title={mode === 'try' ? <Trans>We need your support!</Trans> : title}
title={title}
actions={[
<FlatButton
label={
@@ -108,67 +99,39 @@ const SubscriptionChecker = React.forwardRef<
primary={false}
onClick={closeDialog}
/>,
<DialogPrimaryButton
label={<Trans>Get a subscription or login</Trans>}
key="subscribe"
primary
onClick={() => {
if (onChangeSubscription) onChangeSubscription();
setDialogOpen(false);
openSubscriptionDialog({
analyticsMetadata: {
reason: id,
preStep: 'subscriptionChecker',
},
});
}}
/>,
]}
onRequestClose={closeDialog}
maxWidth="sm"
>
<Column noMargin>
<Line noMargin alignItems="center">
{mode === 'try' ? (
<Text>
<Trans>
Please get a subscription to keep GDevelop running.
</Trans>
</Text>
) : (
<Text>
<Trans>
To use this feature, you need a GDevelop subscription.
</Trans>
</Text>
)}
</Line>
<Line noMargin alignItems="center">
<Star style={styles.icon} />
<Text style={styles.iconText}>
<Trans>
Get a subscription to gain more one-click exports, cloud
projects, leaderboards and remove the GDevelop splashscreen.
</Trans>
</Text>
</Line>
<Line noMargin alignItems="center">
<Favorite style={styles.icon} />
<Text style={styles.iconText}>
<Trans>
You're also supporting the development of GDevelop, an
open-source software! In the future, more online services will
be available for users with a subscription.
</Trans>
</Text>
</Line>
<LargeSpacer />
<Text align="right">
<b>
<Trans>Thanks!</Trans>
</b>
<ColumnStackLayout noMargin>
<Text size="sub-title">
<Trans>Support What You Love</Trans>
</Text>
</Column>
<Text color="secondary">
<Trans>
Your membership helps the GDevelop company maintain servers, build
new features and keep the open-source project thriving. Our goal:
make game development fast, fun and accessible to all.
</Trans>
</Text>
<GetSubscriptionCard
subscriptionDialogOpeningReason={id}
label={<Trans>Get Premium</Trans>}
onUpgrade={() => {
if (onChangeSubscription) onChangeSubscription();
setDialogOpen(false);
}}
>
<Column noMargin expand>
<Text>
<Trans>
Upgrade to get more cloud projects, publishing, multiplayer,
courses and credits every month with GDevelop Premium.
</Trans>
</Text>
</Column>
</GetSubscriptionCard>
</ColumnStackLayout>
</Dialog>
);
}

View File

@@ -38,6 +38,7 @@ import GDevelopThemeContext from '../../UI/Theme/GDevelopThemeContext';
import PlaceholderError from '../../UI/PlaceholderError';
import Link from '../../UI/Link';
import Window from '../../Utils/Window';
import GetSubscriptionCard from './GetSubscriptionCard';
const styles = {
diamondIcon: {
@@ -82,7 +83,7 @@ const subscriptionOptions: {
title: <Trans>For Education</Trans>,
description: <Trans>Teachers, courses and universities</Trans>,
icon: <EducationPlans style={{ width: 110, height: 100 }} />,
buttonColor: 'primary',
buttonColor: 'premium',
},
};
@@ -386,40 +387,16 @@ const SubscriptionDetails = ({
)
) : !isSubscriptionExpired ? (
isOnOrSimulateMobileApp ? (
<Paper background="medium" variant="outlined" style={styles.paper}>
<ResponsiveLineStackLayout
alignItems="center"
expand
noMargin
noResponsiveLandscape
>
<Column expand noMargin>
<LineStackLayout alignItems="center">
<img
src="res/diamond.svg"
style={styles.diamondIcon}
alt="diamond"
/>
<Text noMargin>
<Trans>
Unlock full access to GDevelop to create without limits!
</Trans>
</Text>
</LineStackLayout>
</Column>
<Column noMargin>
<RaisedButton
label={<Trans>Choose a subscription</Trans>}
primary
onClick={() =>
openSubscriptionDialog({
analyticsMetadata: { reason: 'Consult profile' },
})
}
/>
</Column>
</ResponsiveLineStackLayout>
</Paper>
<GetSubscriptionCard
label={<Trans>Choose a subscription</Trans>}
subscriptionDialogOpeningReason="Consult profile"
>
<Text noMargin>
<Trans>
Unlock full access to GDevelop to create without limits!
</Trans>
</Text>
</GetSubscriptionCard>
) : (
<ResponsiveLineStackLayout noColumnMargin noResponsiveLandscape>
{Object.keys(subscriptionOptions).map(key => {
@@ -477,42 +454,18 @@ const SubscriptionDetails = ({
</ResponsiveLineStackLayout>
)
) : (
<Paper background="medium" variant="outlined" style={styles.paper}>
<ResponsiveLineStackLayout
alignItems="center"
expand
noMargin
noResponsiveLandscape
>
<Column expand noMargin>
<LineStackLayout alignItems="center">
<img
src="res/diamond.svg"
style={styles.diamondIcon}
alt="diamond"
/>
<Text noMargin>
<Trans>
Oh no! Your subscription from the redemption code has
expired. You can renew it by redeeming a new code or getting
a new subscription.
</Trans>
</Text>
</LineStackLayout>
</Column>
<Column noMargin>
<RaisedButton
label={<Trans>Choose a subscription</Trans>}
primary
onClick={() =>
openSubscriptionDialog({
analyticsMetadata: { reason: 'Consult profile' },
})
}
/>
</Column>
</ResponsiveLineStackLayout>
</Paper>
<GetSubscriptionCard
label={<Trans>Choose a subscription</Trans>}
subscriptionDialogOpeningReason="Consult profile"
>
<Text noMargin>
<Trans>
Oh no! Your subscription from the redemption code has expired. You
can renew it by redeeming a new code or getting a new
subscription.
</Trans>
</Text>
</GetSubscriptionCard>
)}
</Column>
);

View File

@@ -791,11 +791,13 @@ export default function SubscriptionDialog({
<Trans>Support What You Love</Trans>
</Text>
<Text size="body" color="secondary">
The GDevelop project is open-source, powered by passion and
community. Your membership helps the GDevelop company maintain
servers, build new features, develop commercial offerings and
keep the open-source project thriving. Our goal: make game
development fast, fun and accessible to all.
<Trans>
The GDevelop project is open-source, powered by passion and
community. Your membership helps the GDevelop company
maintain servers, build new features, develop commercial
offerings and keep the open-source project thriving. Our
goal: make game development fast, fun and accessible to all.
</Trans>
</Text>
</Column>
{getPlanSpecificRequirements(

View File

@@ -20,7 +20,6 @@ import {
checkIfHasTooManyCloudProjects,
MaxProjectCountAlertMessage,
} from '../MainFrame/EditorContainers/HomePage/CreateSection/MaxProjectCountAlertMessage';
import { SubscriptionSuggestionContext } from '../Profile/Subscription/SubscriptionSuggestionContext';
import optionalRequire from '../Utils/OptionalRequire';
import PreferencesContext from '../MainFrame/Preferences/PreferencesContext';
import Checkbox from '../UI/Checkbox';
@@ -132,7 +131,6 @@ const NewProjectSetupDialog = ({
const authenticatedUser = React.useContext(AuthenticatedUserContext);
const { windowSize, isLandscape } = useResponsiveWindowSize();
const {
limits,
authenticated,
onOpenLoginDialog,
onOpenCreateAccountDialog,
@@ -157,9 +155,6 @@ const NewProjectSetupDialog = ({
const { currentlyRunningInAppTutorial } = React.useContext(
InAppTutorialContext
);
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
const [projectNameError, setProjectNameError] = React.useState<?React.Node>(
null
);
@@ -674,17 +669,8 @@ const NewProjectSetupDialog = ({
</Paper>
</Line>
)}
{limits && hasTooManyCloudProjects ? (
<MaxProjectCountAlertMessage
limits={limits}
onUpgrade={() =>
openSubscriptionDialog({
analyticsMetadata: {
reason: 'Cloud Project limit reached',
},
})
}
/>
{hasTooManyCloudProjects ? (
<MaxProjectCountAlertMessage />
) : null}
</ColumnStackLayout>
)}

View File

@@ -13,7 +13,6 @@ import {
checkIfHasTooManyCloudProjects,
MaxProjectCountAlertMessage,
} from '../MainFrame/EditorContainers/HomePage/CreateSection/MaxProjectCountAlertMessage';
import { SubscriptionSuggestionContext } from '../Profile/Subscription/SubscriptionSuggestionContext';
type Props = {|
storageProviders: Array<StorageProvider>,
@@ -27,11 +26,8 @@ const SaveToStorageProviderDialog = ({
onChooseProvider,
}: Props) => {
const authenticatedUser = React.useContext(AuthenticatedUserContext);
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
const { profile, limits, cloudProjects } = authenticatedUser;
const { profile, cloudProjects } = authenticatedUser;
const isLoadingCloudProjects = !!profile && !cloudProjects;
const isCloudProjectsMaximumReached = checkIfHasTooManyCloudProjects(
@@ -67,19 +63,8 @@ const SaveToStorageProviderDialog = ({
}
/>
{storageProvider.internalName === 'Cloud' &&
isCloudProjectsMaximumReached &&
limits && (
<MaxProjectCountAlertMessage
margin="dense"
limits={limits}
onUpgrade={() =>
openSubscriptionDialog({
analyticsMetadata: {
reason: 'Cloud Project limit reached',
},
})
}
/>
isCloudProjectsMaximumReached && (
<MaxProjectCountAlertMessage margin="dense" />
)}
</React.Fragment>
))}

View File

@@ -9,7 +9,6 @@ import RaisedButton from '../UI/RaisedButton';
import { I18n } from '@lingui/react';
import { type Exporter } from '../ExportAndShare/ShareDialog';
import Text from '../UI/Text';
import { type Limits } from '../Utils/GDevelopServices/Usage';
import {
getBuildArtifactUrl,
type Build,
@@ -33,7 +32,6 @@ import {
checkIfHasTooManyCloudProjects,
MaxProjectCountAlertMessage,
} from '../MainFrame/EditorContainers/HomePage/CreateSection/MaxProjectCountAlertMessage';
import { SubscriptionSuggestionContext } from '../Profile/Subscription/SubscriptionSuggestionContext';
import ArrowLeft from '../UI/CustomSvgIcons/ArrowLeft';
type Props = {|
@@ -66,13 +64,9 @@ export const QuickPublish = ({
onLaunchPreview,
}: Props) => {
const authenticatedUser = React.useContext(AuthenticatedUserContext);
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
const {
profile,
onOpenCreateAccountDialog,
limits,
cloudProjects,
getAuthorizationHeader,
} = authenticatedUser;
@@ -94,19 +88,6 @@ export const QuickPublish = ({
});
}, []);
const renderCallout = (limits: Limits) => (
<MaxProjectCountAlertMessage
limits={limits}
onUpgrade={() =>
openSubscriptionDialog({
analyticsMetadata: {
reason: 'Cloud Project limit reached',
},
})
}
/>
);
const isLoadingCloudProjects = !!profile && !cloudProjects;
const isCloudProjectsMaximumReached = checkIfHasTooManyCloudProjects(
authenticatedUser
@@ -203,8 +184,8 @@ export const QuickPublish = ({
{profile ? (
isLoadingCloudProjects ? (
<PlaceholderLoader />
) : cantContinueBecauseCloudProjectsMaximumReached && limits ? (
renderCallout(limits)
) : cantContinueBecauseCloudProjectsMaximumReached ? (
<MaxProjectCountAlertMessage />
) : (
<I18n>
{({ i18n }) => (

View File

@@ -367,7 +367,6 @@ export type SubscriptionDialogDisplayReason =
| 'Consult profile'
| 'Build limit reached'
| 'Leaderboard customization'
| 'Extend redeemed subscription'
| 'Generate project from prompt'
| 'Version history'
| 'Add collaborators on project'

View File

@@ -16,14 +16,13 @@ import { Column, Line } from '../UI/Grid';
import VersionHistory, { type OpenedVersionStatus } from '.';
import UnsavedChangesContext from '../MainFrame/UnsavedChangesContext';
import AlertMessage from '../UI/AlertMessage';
import { ColumnStackLayout } from '../UI/Layout';
import RaisedButton from '../UI/RaisedButton';
import { SubscriptionSuggestionContext } from '../Profile/Subscription/SubscriptionSuggestionContext';
import useAlertDialog from '../UI/Alert/useAlertDialog';
import PlaceholderLoader from '../UI/PlaceholderLoader';
import type { MessageDescriptor } from '../Utils/i18n/MessageDescriptor.flow';
import PlaceholderError from '../UI/PlaceholderError';
import CloudStorageProvider from '../ProjectsStorage/CloudStorageProvider';
import GetSubscriptionCard from '../Profile/Subscription/GetSubscriptionCard';
import Text from '../UI/Text';
const getCloudProjectFileMetadataIdentifier = (
storageProviderInternalName: string,
@@ -96,9 +95,6 @@ const useVersionHistory = ({
}: Props) => {
const { hasUnsavedChanges } = React.useContext(UnsavedChangesContext);
const { showAlert } = useAlertDialog();
const { openSubscriptionDialog } = React.useContext(
SubscriptionSuggestionContext
);
const [
versionsFetchingError,
setVersionsFetchingError,
@@ -447,27 +443,19 @@ const useVersionHistory = ({
</Column>
</Line>
) : !isUserAllowedToSeeVersionHistory ? (
<Line expand>
<ColumnStackLayout>
<AlertMessage kind="info">
<Trans>
Access project history, name saves, restore older versions.
<br />
Upgrade to a Pro plan to get started!
</Trans>
</AlertMessage>
<RaisedButton
primary
label={<Trans>Upgrade my subscription</Trans>}
onClick={() =>
openSubscriptionDialog({
analyticsMetadata: { reason: 'Version history' },
filter: 'team',
})
}
/>
</ColumnStackLayout>
</Line>
<GetSubscriptionCard
subscriptionDialogOpeningReason="Version history"
forceColumnLayout
filter="team"
>
<Text>
<Trans>
Access project history, name saves, restore older versions.
<br />
Upgrade to a Pro plan to get started!
</Trans>
</Text>
</GetSubscriptionCard>
) : !state.versions && versionsFetchingError ? (
<Line expand>
<Column expand>

View File

@@ -2380,7 +2380,7 @@ export const limitsForNoSubscriptionUser: Limits = {
platforms: false,
},
cloudProjects: {
maximumCount: 10,
maximumCount: 3,
canMaximumCountBeIncreased: true,
maximumGuestCollaboratorsPerProject: 0,
},
@@ -2491,7 +2491,7 @@ export const limitsForGoldUser: Limits = {
},
cloudProjects: {
maximumCount: 100,
canMaximumCountBeIncreased: false,
canMaximumCountBeIncreased: true,
maximumGuestCollaboratorsPerProject: 0,
},
leaderboards: {

View File

@@ -1,12 +1,14 @@
// @flow
import * as React from 'react';
import { action } from '@storybook/addon-actions';
import { MaxProjectCountAlertMessage } from '../../../../MainFrame/EditorContainers/HomePage/CreateSection/MaxProjectCountAlertMessage';
import paperDecorator from '../../../PaperDecorator';
import {
limitsForSilverUser,
limitsForGoldUser,
defaultAuthenticatedUserWithNoSubscription,
fakeGoldAuthenticatedUser,
fakeSilverAuthenticatedUser,
fakeStartupAuthenticatedUser,
} from '../../../../fixtures/GDevelopServicesTestData';
import AuthenticatedUserContext from '../../../../Profile/AuthenticatedUserContext';
export default {
title: 'HomePage/CreateSection/MaxProjectCountAlertMessage',
@@ -14,16 +16,34 @@ export default {
decorators: [paperDecorator],
};
export const ForFreeUser = () => (
<AuthenticatedUserContext.Provider
value={defaultAuthenticatedUserWithNoSubscription}
>
<MaxProjectCountAlertMessage />
</AuthenticatedUserContext.Provider>
);
export const ForIndieUser = () => (
<MaxProjectCountAlertMessage
limits={limitsForSilverUser}
onUpgrade={() => action('onUpgrade')()}
/>
<AuthenticatedUserContext.Provider value={fakeSilverAuthenticatedUser}>
<MaxProjectCountAlertMessage />
</AuthenticatedUserContext.Provider>
);
export const ForGoldUser = () => (
<AuthenticatedUserContext.Provider value={fakeGoldAuthenticatedUser}>
<MaxProjectCountAlertMessage />
</AuthenticatedUserContext.Provider>
);
export const ForProUser = () => (
<MaxProjectCountAlertMessage
limits={limitsForGoldUser}
onUpgrade={() => action('onUpgrade')()}
/>
<AuthenticatedUserContext.Provider value={fakeStartupAuthenticatedUser}>
<MaxProjectCountAlertMessage />
</AuthenticatedUserContext.Provider>
);
export const DenseMargins = () => (
<AuthenticatedUserContext.Provider value={fakeSilverAuthenticatedUser}>
<MaxProjectCountAlertMessage margin="dense" />
</AuthenticatedUserContext.Provider>
);

View File

@@ -1,9 +1,9 @@
// @flow
import * as React from 'react';
import { action } from '@storybook/addon-actions';
import paperDecorator from '../../PaperDecorator';
import { limitsReached } from '../../../fixtures/GDevelopServicesTestData';
import { defaultAuthenticatedUserWithNoSubscription } from '../../../fixtures/GDevelopServicesTestData';
import MaxLeaderboardCountAlertMessage from '../../../GameDashboard/LeaderboardAdmin/MaxLeaderboardCountAlertMessage';
import AuthenticatedUserContext from '../../../Profile/AuthenticatedUserContext';
export default {
title: 'Leaderboard/MaxLeaderboardCountAlertMessage',
@@ -12,9 +12,9 @@ export default {
};
export const Default = () => (
<MaxLeaderboardCountAlertMessage
limits={limitsReached}
onUpgrade={() => action('onUpgrade')()}
onClose={() => action('onClose')()}
/>
<AuthenticatedUserContext.Provider
value={defaultAuthenticatedUserWithNoSubscription}
>
<MaxLeaderboardCountAlertMessage />
</AuthenticatedUserContext.Provider>
);

View File

@@ -82,3 +82,20 @@ export const PayWithCreditsOptions = () => (
</GetSubscriptionCard>
</AuthenticatedUserContext.Provider>
);
export const ForceColumnLayout = () => (
<AuthenticatedUserContext.Provider value={fakeNotAuthenticatedUser}>
<GetSubscriptionCard
subscriptionDialogOpeningReason="Build limit reached"
forceColumnLayout
>
<Line>
<Column noMargin>
<Text noMargin>
Upgrade your GDevelop subscription to unlock this packaging.
</Text>
</Column>
</Line>
</GetSubscriptionCard>
</AuthenticatedUserContext.Provider>
);