mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
1 Commits
lava-shade
...
allow-bump
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7d161d7b8f |
@@ -109,9 +109,9 @@ namespace gdjs {
|
||||
// Uncomment to test the case of a failing loading:
|
||||
// return 'https://gd.games.wronglink';
|
||||
|
||||
const baseUrl = 'https://gd.games';
|
||||
// const baseUrl = 'https://gd.games';
|
||||
// Uncomment to test locally:
|
||||
// const baseUrl = 'http://localhost:4000';
|
||||
const baseUrl = 'http://localhost:4000';
|
||||
|
||||
const url = new URL(
|
||||
`${baseUrl}/games/${gameId}/lobbies${_lobbyId ? `/${_lobbyId}` : ''}`
|
||||
@@ -627,8 +627,8 @@ namespace gdjs {
|
||||
},
|
||||
// Specify the origin to avoid leaking the playerToken.
|
||||
// Replace with '*' to test locally.
|
||||
'https://gd.games'
|
||||
// '*'
|
||||
// 'https://gd.games'
|
||||
'*'
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -85,6 +85,8 @@ export const localCordovaExportPipeline: ExportPipeline<
|
||||
</Column>
|
||||
) : null,
|
||||
|
||||
shouldSuggestBumpingVersionNumber: () => true,
|
||||
|
||||
renderExportFlow: (props: ExportFlowProps) => (
|
||||
<ExportFlow {...props} exportPipelineName={exportPipelineName} />
|
||||
),
|
||||
|
@@ -85,6 +85,8 @@ export const localElectronExportPipeline: ExportPipeline<
|
||||
</Column>
|
||||
) : null,
|
||||
|
||||
shouldSuggestBumpingVersionNumber: () => true,
|
||||
|
||||
renderExportFlow: (props: ExportFlowProps) => (
|
||||
<ExportFlow {...props} exportPipelineName={exportPipelineName} />
|
||||
),
|
||||
|
@@ -76,6 +76,8 @@ export const localOnlineElectronExportPipeline: ExportPipeline<
|
||||
|
||||
renderHeader: props => <SetupExportHeader {...props} />,
|
||||
|
||||
shouldSuggestBumpingVersionNumber: () => true,
|
||||
|
||||
renderExportFlow: (props: ExportFlowProps) => (
|
||||
<ExportFlow {...props} exportPipelineName={exportPipelineName} />
|
||||
),
|
||||
|
@@ -36,11 +36,10 @@ import {
|
||||
} from '../../Utils/GDevelopServices/Badge';
|
||||
import { extractGDevelopApiErrorStatusAndCode } from '../../Utils/GDevelopServices/Errors';
|
||||
import { type EventsFunctionsExtensionsState } from '../../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsContext';
|
||||
import inc from 'semver/functions/inc';
|
||||
import Toggle from '../../UI/Toggle';
|
||||
import PlaceholderLoader from '../../UI/PlaceholderLoader';
|
||||
import AlertMessage from '../../UI/AlertMessage';
|
||||
import { type GameAvailabilityError } from '../../GameDashboard/GameRegistration';
|
||||
import ProjectVersionSelector from './ProjectVersionSelector';
|
||||
|
||||
type State = {|
|
||||
exportStep: BuildStep,
|
||||
@@ -52,6 +51,7 @@ type State = {|
|
||||
shouldBumpVersionNumber: boolean,
|
||||
exportState: any,
|
||||
doneFooterOpen: boolean,
|
||||
selectedVersionNumber: string,
|
||||
|};
|
||||
|
||||
type Props = {|
|
||||
@@ -70,10 +70,6 @@ type Props = {|
|
||||
onRefreshBuilds: () => Promise<void>,
|
||||
|};
|
||||
|
||||
const getIncrementedVersionNumber = (project: gdProject) => {
|
||||
return inc(project.getVersion(), 'patch', { loose: true });
|
||||
};
|
||||
|
||||
const getBuildQuota = (
|
||||
authenticatedUser: AuthenticatedUser,
|
||||
onlineBuildType: ?string
|
||||
@@ -107,8 +103,8 @@ export default class ExportLauncher extends Component<Props, State> {
|
||||
exportState: this.props.exportPipeline.getInitialExportState(
|
||||
this.props.project
|
||||
),
|
||||
selectedVersionNumber: this.props.project.getVersion(),
|
||||
};
|
||||
_candidateBumpedVersionNumber = '';
|
||||
buildsWatcher = new BuildsWatcher();
|
||||
launchWholeExport: ({|
|
||||
i18n: I18nType,
|
||||
@@ -128,10 +124,6 @@ export default class ExportLauncher extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this._setupAchievementHook();
|
||||
|
||||
this._candidateBumpedVersionNumber = getIncrementedVersionNumber(
|
||||
props.project
|
||||
);
|
||||
}
|
||||
componentDidUpdate(prevProps: Props, prevState: State) {
|
||||
this._setupAchievementHook();
|
||||
@@ -350,13 +342,7 @@ export default class ExportLauncher extends Component<Props, State> {
|
||||
exportState: this.state.exportState,
|
||||
};
|
||||
|
||||
if (
|
||||
exportPipeline.shouldSuggestBumpingVersionNumber &&
|
||||
exportPipeline.shouldSuggestBumpingVersionNumber() &&
|
||||
this.state.shouldBumpVersionNumber
|
||||
) {
|
||||
project.setVersion(this._candidateBumpedVersionNumber);
|
||||
}
|
||||
project.setVersion(this.state.selectedVersionNumber);
|
||||
|
||||
setStep('export');
|
||||
this.setState({
|
||||
@@ -515,8 +501,8 @@ export default class ExportLauncher extends Component<Props, State> {
|
||||
(exportStep === 'done' && !isBuildRunning) || errored;
|
||||
const isUsingOnlineBuildNonAuthenticated =
|
||||
!!exportPipeline.onlineBuildType && !authenticatedUser.authenticated;
|
||||
const isOnlineBuildIncludedInSubscription =
|
||||
!!buildQuota && buildQuota.max > 0;
|
||||
const isIncludedInSubscriptionIfOnline =
|
||||
!exportPipeline.onlineBuildType || (!!buildQuota && buildQuota.max > 0);
|
||||
const hasSomeBuildsRunning = hasBuildsCurrentlyRunning();
|
||||
|
||||
return (
|
||||
@@ -559,7 +545,7 @@ export default class ExportLauncher extends Component<Props, State> {
|
||||
exportPipeline.renderTutorial()}
|
||||
</Column>
|
||||
)}
|
||||
<Column expand justifyContent="center">
|
||||
<Column expand justifyContent="center" alignItems="center">
|
||||
{!isUsingOnlineBuildNonAuthenticated && (
|
||||
<Line alignItems="center" justifyContent="center">
|
||||
{exportPipeline.renderHeader({
|
||||
@@ -575,28 +561,16 @@ export default class ExportLauncher extends Component<Props, State> {
|
||||
</Line>
|
||||
)}
|
||||
{!isUsingOnlineBuildNonAuthenticated &&
|
||||
isOnlineBuildIncludedInSubscription &&
|
||||
exportPipeline.shouldSuggestBumpingVersionNumber &&
|
||||
exportPipeline.shouldSuggestBumpingVersionNumber() &&
|
||||
isIncludedInSubscriptionIfOnline &&
|
||||
!isExportAndBuildCompleteOrErrored && (
|
||||
<Line noMargin>
|
||||
<Toggle
|
||||
labelPosition="right"
|
||||
toggled={this.state.shouldBumpVersionNumber}
|
||||
label={
|
||||
<Trans>
|
||||
Increase version number to{' '}
|
||||
{this._candidateBumpedVersionNumber}
|
||||
</Trans>
|
||||
}
|
||||
onToggle={(e, toggled) => {
|
||||
this.setState({
|
||||
shouldBumpVersionNumber: toggled,
|
||||
});
|
||||
}}
|
||||
disabled={isExportingOrWaitingForBuild}
|
||||
/>
|
||||
</Line>
|
||||
<ProjectVersionSelector
|
||||
project={project}
|
||||
versionNumber={this.state.selectedVersionNumber}
|
||||
onVersionNumberChanged={versionNumber => {
|
||||
this.setState({ selectedVersionNumber: versionNumber });
|
||||
}}
|
||||
disabled={isExportingOrWaitingForBuild}
|
||||
/>
|
||||
)}
|
||||
{!!exportPipeline.limitedBuilds &&
|
||||
authenticatedUser.authenticated &&
|
||||
|
@@ -0,0 +1,217 @@
|
||||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import { Trans, t } from '@lingui/macro';
|
||||
import { I18n } from '@lingui/react';
|
||||
import inc from 'semver/functions/inc';
|
||||
import { ResponsiveLineStackLayout } from '../../UI/Layout';
|
||||
import AuthenticatedUserContext from '../../Profile/AuthenticatedUserContext';
|
||||
import { getBuilds } from '../../Utils/GDevelopServices/Build';
|
||||
import SelectOption from '../../UI/SelectOption';
|
||||
import SelectField from '../../UI/SelectField';
|
||||
import TextField from '../../UI/TextField';
|
||||
import { Column, Line } from '../../UI/Grid';
|
||||
import FlatButton from '../../UI/FlatButton';
|
||||
import HelpIcon from '../../UI/HelpIcon';
|
||||
|
||||
const gd: libGDevelop = global.gd;
|
||||
|
||||
const styles = {
|
||||
buttonStyle: {
|
||||
flexShrink: 0,
|
||||
marginTop: 17,
|
||||
},
|
||||
container: {
|
||||
maxWidth: 400,
|
||||
},
|
||||
};
|
||||
|
||||
const getIncrementedVersionNumber = (project: gdProject) => {
|
||||
return inc(project.getVersion(), 'patch', { loose: true });
|
||||
};
|
||||
|
||||
type Props = {|
|
||||
project: gdProject,
|
||||
disabled: boolean,
|
||||
versionNumber: string,
|
||||
onVersionNumberChanged: string => void,
|
||||
|};
|
||||
|
||||
const ProjectVersionSelector = ({
|
||||
project,
|
||||
disabled,
|
||||
versionNumber,
|
||||
onVersionNumberChanged,
|
||||
}: Props) => {
|
||||
const { getAuthorizationHeader, profile } = React.useContext(
|
||||
AuthenticatedUserContext
|
||||
);
|
||||
const [recentBuildGameVersions, setRecentBuildGameVersions] = React.useState<
|
||||
string[]
|
||||
>([project.getVersion()]);
|
||||
const [isLoading, setIsLoading] = React.useState(true);
|
||||
|
||||
const fetchRecentBuildGameVersions = React.useCallback(
|
||||
async () => {
|
||||
try {
|
||||
const gameId = project.getProjectUuid();
|
||||
if (!gameId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userId = profile ? profile.id : null;
|
||||
if (!userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const recentBuilds = await getBuilds(
|
||||
getAuthorizationHeader,
|
||||
userId,
|
||||
gameId
|
||||
);
|
||||
const allVersions = recentBuilds
|
||||
.map(build => build.gameVersion)
|
||||
.filter(Boolean)
|
||||
.concat([project.getVersion()]);
|
||||
const sortedVersions = allVersions.sort((a, b) => {
|
||||
return a.localeCompare(b);
|
||||
});
|
||||
const uniqueVersions = Array.from(new Set(sortedVersions));
|
||||
setRecentBuildGameVersions(uniqueVersions);
|
||||
} catch (error) {
|
||||
console.error('Unable to fetch recent build versions:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[getAuthorizationHeader, profile, project]
|
||||
);
|
||||
|
||||
const isMultiplayerExtensionUsed = React.useMemo(
|
||||
() =>
|
||||
gd.UsedExtensionsFinder.scanProject(project)
|
||||
.getUsedExtensions()
|
||||
.toNewVectorString()
|
||||
.toJSArray()
|
||||
.some(extensionName => extensionName === 'Multiplayer'),
|
||||
[project]
|
||||
);
|
||||
|
||||
React.useEffect(
|
||||
() => {
|
||||
fetchRecentBuildGameVersions();
|
||||
},
|
||||
[fetchRecentBuildGameVersions]
|
||||
);
|
||||
|
||||
const isCurrentValueInGameVersionsList =
|
||||
!!recentBuildGameVersions &&
|
||||
recentBuildGameVersions.find(
|
||||
recentGameVersion => recentGameVersion === versionNumber
|
||||
);
|
||||
|
||||
const [isFreeTextField, setIsFreeTextField] = React.useState(false);
|
||||
|
||||
const switchFieldType = () => {
|
||||
if (isFreeTextField && !isCurrentValueInGameVersionsList) {
|
||||
// If the current value is not in the list of versions when switching to the select field,
|
||||
// go back to the current project version, to ensure a value is always selected.
|
||||
onVersionNumberChanged(project.getVersion());
|
||||
} else {
|
||||
// If switching to the free text field, increment the current project version,
|
||||
// as we expect the user to enter a new version.
|
||||
onVersionNumberChanged(getIncrementedVersionNumber(project));
|
||||
}
|
||||
setIsFreeTextField(!isFreeTextField);
|
||||
};
|
||||
|
||||
const onChangeSelectValue = (event, value) => {
|
||||
onVersionNumberChanged(event.target.value);
|
||||
};
|
||||
|
||||
const onChangeTextValue = (e, value) => {
|
||||
onVersionNumberChanged(value);
|
||||
};
|
||||
|
||||
const isDisabled = disabled || isLoading;
|
||||
|
||||
const selectOptions = recentBuildGameVersions.map(buildVersion => (
|
||||
<SelectOption
|
||||
key={buildVersion}
|
||||
value={buildVersion}
|
||||
label={buildVersion}
|
||||
shouldNotTranslate
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
));
|
||||
|
||||
return (
|
||||
<I18n>
|
||||
{({ i18n }) => (
|
||||
<div style={styles.container}>
|
||||
<Column noMargin expand>
|
||||
<ResponsiveLineStackLayout
|
||||
justifyContent="center"
|
||||
alignItems="start"
|
||||
>
|
||||
{!isFreeTextField ? (
|
||||
<SelectField
|
||||
id="game-version-select-field"
|
||||
value={versionNumber}
|
||||
onChange={onChangeSelectValue}
|
||||
margin="dense"
|
||||
floatingLabelText={<Trans>Game version</Trans>}
|
||||
floatingLabelFixed
|
||||
translatableHintText={t`Choose a game version`}
|
||||
fullWidth
|
||||
helperMarkdownText={
|
||||
isMultiplayerExtensionUsed
|
||||
? i18n._(
|
||||
t`Bump the version if you want your players to join different lobbies.`
|
||||
)
|
||||
: null
|
||||
}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
{selectOptions}
|
||||
</SelectField>
|
||||
) : (
|
||||
<TextField
|
||||
id="game-version-text-field"
|
||||
onChange={onChangeTextValue}
|
||||
floatingLabelText={<Trans>Game version</Trans>}
|
||||
value={versionNumber}
|
||||
floatingLabelFixed
|
||||
fullWidth
|
||||
helperMarkdownText={
|
||||
isMultiplayerExtensionUsed
|
||||
? i18n._(
|
||||
t`Bump the version if you want your players to join different lobbies.`
|
||||
)
|
||||
: null
|
||||
}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
)}
|
||||
<FlatButton
|
||||
id="switch-game-version-text-select"
|
||||
label={
|
||||
isFreeTextField ? (
|
||||
<Trans>Select version</Trans>
|
||||
) : (
|
||||
<Trans>Bump version</Trans>
|
||||
)
|
||||
}
|
||||
onClick={switchFieldType}
|
||||
style={styles.buttonStyle}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
</ResponsiveLineStackLayout>
|
||||
</Column>
|
||||
</div>
|
||||
)}
|
||||
</I18n>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectVersionSelector;
|
@@ -44,6 +44,7 @@ export type Build = {
|
||||
targets?: Array<TargetName>,
|
||||
createdAt?: number, // Not defined for old builds.
|
||||
updatedAt: number,
|
||||
gameVersion?: string,
|
||||
};
|
||||
|
||||
export type BuildArtifactKeyName =
|
||||
@@ -222,6 +223,7 @@ export const buildElectron = (
|
||||
type: 'electron-build',
|
||||
targets: targets.join(','),
|
||||
gameId,
|
||||
gameVersion: options.gameVersion,
|
||||
filename: getBuildExtensionlessFilename(options),
|
||||
payWithCredits,
|
||||
},
|
||||
@@ -253,6 +255,7 @@ export const buildWeb = (
|
||||
type: 'web-build',
|
||||
targets: 's3',
|
||||
gameId,
|
||||
gameVersion: options.gameVersion,
|
||||
payWithCredits,
|
||||
},
|
||||
headers: {
|
||||
@@ -293,6 +296,7 @@ export const buildCordovaAndroid = (
|
||||
targets: targets.join(','),
|
||||
gameId,
|
||||
filename: getBuildExtensionlessFilename(options),
|
||||
gameVersion: options.gameVersion,
|
||||
payWithCredits,
|
||||
},
|
||||
headers: {
|
||||
@@ -332,6 +336,7 @@ export const buildCordovaIos = (
|
||||
targets: targets.join(','),
|
||||
gameId,
|
||||
filename: getBuildExtensionlessFilename(options),
|
||||
gameVersion: options.gameVersion,
|
||||
payWithCredits,
|
||||
},
|
||||
headers: {
|
||||
|
Reference in New Issue
Block a user