Improve wording and design across the publishing flow to Liluo

+ display game consolidated analytics on the analytics page
This commit is contained in:
Clément Pasteau
2022-02-16 17:48:09 +01:00
committed by GitHub
parent 582e71e9d3
commit 4d7514c2bf
4 changed files with 174 additions and 69 deletions

View File

@@ -66,7 +66,7 @@ const ExportHome = ({
<div style={styles.titleContainer}>
<Line>
<Text size="title">
<Trans>Share with friends</Trans>
<Trans>Publish and share with friends on Liluo.io</Trans>
</Text>
</Line>
</div>
@@ -89,7 +89,7 @@ const ExportHome = ({
<div style={styles.titleContainer}>
<Line>
<Text size="title">
<Trans>Publish your game</Trans>
<Trans>Publish your game on other stores</Trans>
</Text>
</Line>
</div>

View File

@@ -39,6 +39,7 @@ import {
type Game,
} from '../../Utils/GDevelopServices/Game';
import AuthenticatedUserContext from '../../Profile/AuthenticatedUserContext';
import AlertMessage from '../../UI/AlertMessage';
const styles = {
icon: {
@@ -51,8 +52,8 @@ export const ExplanationHeader = () => (
<Line>
<Text align="center">
<Trans>
Generate a unique link to share your game, playable from any computer
or mobile phone's browser.
Generate a unique link, playable from any computer or mobile phone's
browser.
</Trans>
</Text>
</Line>
@@ -85,11 +86,12 @@ export const WebProjectLink = ({
const exportPending = !errored && exportStep !== '' && exportStep !== 'done';
const isBuildComplete = build && build.status === 'complete';
const isBuildPublished = build && game && build.id === game.publicWebBuildId;
const gameUrl = getGameUrl(game);
const buildUrl =
exportPending || !isBuildComplete
? null
: isBuildPublished
? getGameUrl(game)
? gameUrl
: getBuildArtifactUrl(build, 's3Key');
const loadGame = React.useCallback(
@@ -244,53 +246,76 @@ export const WebProjectLink = ({
</Line>
)}
{isBuildPublished && !navigator.share && (
<Line justifyContent="flex-end">
<FacebookShareButton
url={buildUrl}
style={styles.icon}
quote={`Try the game I just created with GDevelop.io`}
hashtag="#gdevelop"
>
<FacebookIcon size={32} round />
</FacebookShareButton>
<RedditShareButton
url={buildUrl}
title={`Try the game I just created with r/gdevelop`}
style={styles.icon}
>
<RedditIcon size={32} round />
</RedditShareButton>
<TwitterShareButton
title={`Try the game I just created with GDevelop.io`}
hashtags={['gdevelop']}
url={buildUrl}
style={styles.icon}
>
<TwitterIcon size={32} round />
</TwitterShareButton>
<WhatsappShareButton
title={`Try the game I just created with GDevelop.io`}
url={buildUrl}
style={styles.icon}
>
<WhatsappIcon size={32} round />
</WhatsappShareButton>
<EmailShareButton
subject="My GDevelop game"
body="Try the game I just created with GDevelop.io"
url={buildUrl}
style={styles.icon}
>
<EmailIcon size={32} round />
</EmailShareButton>
<Line justifyContent="space-between">
<Column justifyContent="center">
<AlertMessage kind="info">
<Trans>
This link is unique to your game. Show what you made to
the community!
</Trans>
</AlertMessage>
</Column>
<Column justifyContent="flex-end">
<Line>
<FacebookShareButton
url={buildUrl}
style={styles.icon}
quote={`Try the game I just created with GDevelop.io`}
hashtag="#gdevelop"
>
<FacebookIcon size={32} round />
</FacebookShareButton>
<RedditShareButton
url={buildUrl}
title={`Try the game I just created with r/gdevelop`}
style={styles.icon}
>
<RedditIcon size={32} round />
</RedditShareButton>
<TwitterShareButton
title={`Try the game I just created with GDevelop.io`}
hashtags={['gdevelop']}
url={buildUrl}
style={styles.icon}
>
<TwitterIcon size={32} round />
</TwitterShareButton>
<WhatsappShareButton
title={`Try the game I just created with GDevelop.io`}
url={buildUrl}
style={styles.icon}
>
<WhatsappIcon size={32} round />
</WhatsappShareButton>
<EmailShareButton
subject="My GDevelop game"
body="Try the game I just created with GDevelop.io"
url={buildUrl}
style={styles.icon}
>
<EmailIcon size={32} round />
</EmailShareButton>
</Line>
</Column>
</Line>
)}
{!isBuildPublished && (
<Line justifyContent="center">
<RaisedButton
label={<Trans>Publish this build to the game's page</Trans>}
onClick={onUpdatePublicBuild}
/>
<Line>
<AlertMessage
kind="info"
renderRightButton={() => (
<RaisedButton
label={<Trans>Update your game</Trans>}
onClick={onUpdatePublicBuild}
/>
)}
>
<Trans>
This link is private so you can share it with friends and
testers. When you're ready you can update your Liluo.io game
page.
</Trans>
</AlertMessage>
</Line>
)}
</Column>

View File

@@ -38,6 +38,12 @@ import PlaceholderLoader from '../UI/PlaceholderLoader';
import PublicGamePropertiesDialog from '../ProjectManager/PublicGamePropertiesDialog';
import TextField from '../UI/TextField';
const styles = {
tableRowStatColumn: {
width: 100,
},
};
export type GamesDetailsTab = 'details' | 'builds' | 'analytics';
type Props = {|
@@ -140,7 +146,8 @@ export const GameDetailsDialog = ({
const { id } = profile;
try {
setPublicGame(null); // Public game will auto update when game is updated.
// Set public game to null as it will be refetched automatically by the callback above.
setPublicGame(null);
const gameId = project.getProjectUuid();
const updatedGame = await updateGame(getAuthorizationHeader, id, gameId, {
authorName: project.getAuthor() || 'Unspecified publisher',
@@ -167,6 +174,30 @@ export const GameDetailsDialog = ({
}
};
const unpublishGame = React.useCallback(
async () => {
if (!profile) return;
const { id } = profile;
try {
// Set public game to null as it will be refetched automatically by the callback above.
setPublicGame(null);
const updatedGame = await updateGame(
getAuthorizationHeader,
id,
game.id,
{
publicWebBuildId: null,
}
);
onGameUpdated(updatedGame);
} catch (err) {
console.error('Unable to update the game', err);
}
},
[game, getAuthorizationHeader, profile, onGameUpdated]
);
const authorUsernames =
publicGame && publicGame.authors
? publicGame.authors.map(author => author.username).filter(Boolean)
@@ -275,7 +306,7 @@ export const GameDetailsDialog = ({
<FlatButton
onClick={() => {
const answer = Window.showConfirmDialog(
"Are you sure you want to unregister this game? You won't get access to analytics and metrics, unless you register it again."
"Are you sure you want to unregister this game? \n\nIt will disappear from your games dashboard and you won't get access to analytics, unless you register it again."
);
if (!answer) return;
@@ -285,6 +316,23 @@ export const GameDetailsDialog = ({
label={<Trans>Unregister this game</Trans>}
/>
<Spacer />
{publicGame.publicWebBuildId && (
<>
<RaisedButton
onClick={() => {
const answer = Window.showConfirmDialog(
'Are you sure you want to unpublish this game? \n\nThis will make your Liluo unique game URL not accessible anymore. \n\nYou can decide anytime to publish it again.'
);
if (!answer) return;
unpublishGame();
}}
label={<Trans>Unpublish from Liluo</Trans>}
/>
<Spacer />
</>
)}
<RaisedButton
primary
onClick={() => setIsPublicGamePropertiesDialogOpen(true)}
@@ -314,6 +362,48 @@ export const GameDetailsDialog = ({
</PlaceholderError>
) : (
<ColumnStackLayout expand>
<Line noMargin alignItems="center">
<Text size="title">
<Trans>Consolidated metrics</Trans>
</Text>
<Spacer />
{!publicGame && <CircularProgress size={20} />}
</Line>
<Table>
<TableBody>
<TableRow>
<TableRowColumn>
<Trans>Last week sessions count</Trans>
</TableRowColumn>
<TableRowColumn style={styles.tableRowStatColumn}>
{publicGame &&
publicGame.metrics &&
publicGame.metrics.lastWeekSessionsCount
? publicGame.metrics.lastWeekSessionsCount
: '-'}
</TableRowColumn>
</TableRow>
<TableRow>
<TableRowColumn>
<Trans>Last year sessions count</Trans>
</TableRowColumn>
<TableRowColumn style={styles.tableRowStatColumn}>
{publicGame &&
publicGame.metrics &&
publicGame.metrics.lastYearSessionsCount
? publicGame.metrics.lastYearSessionsCount
: '-'}
</TableRowColumn>
</TableRow>
</TableBody>
</Table>
<Line noMargin alignItems="center">
<Text size="title">
<Trans>Daily metrics</Trans>
</Text>
<Spacer />
{isGameMetricsLoading && <CircularProgress size={20} />}
</Line>
<Line noMargin>
<SelectField
fullWidth
@@ -360,20 +450,13 @@ export const GameDetailsDialog = ({
</Trans>
</AlertMessage>
) : null}
<Line noMargin alignItems="center">
<Text size="title">
<Trans>Main metrics</Trans>
</Text>
<Spacer />
{isGameMetricsLoading && <CircularProgress size={20} />}
</Line>
<Table>
<TableBody>
<TableRow>
<TableRowColumn>
<Trans>Players count</Trans>
</TableRowColumn>
<TableRowColumn>
<TableRowColumn style={styles.tableRowStatColumn}>
{gameRollingMetrics && gameRollingMetrics.players
? gameRollingMetrics.players.d0Players
: '-'}
@@ -383,7 +466,7 @@ export const GameDetailsDialog = ({
<TableRowColumn>
<Trans>Sessions count</Trans>
</TableRowColumn>
<TableRowColumn>
<TableRowColumn style={styles.tableRowStatColumn}>
{gameRollingMetrics && gameRollingMetrics.sessions
? gameRollingMetrics.sessions.d0Sessions
: '-'}
@@ -393,7 +476,7 @@ export const GameDetailsDialog = ({
<TableRowColumn>
<Trans>New players count</Trans>
</TableRowColumn>
<TableRowColumn>
<TableRowColumn style={styles.tableRowStatColumn}>
{gameRollingMetrics && gameRollingMetrics.players
? gameRollingMetrics.players.d0NewPlayers
: '-'}
@@ -408,13 +491,6 @@ export const GameDetailsDialog = ({
metrics for your game.
</AlertMessage>
) : null}
<Line noMargin alignItems="center">
<Text size="title">
<Trans>Retention of players</Trans>
</Text>
<Spacer />
{isGameMetricsLoading && <CircularProgress size={20} />}
</Line>
<Table>
<TableBody>
{[1, 2, 3, 4, 5, 6, 7].map(dayIndex => (
@@ -422,7 +498,7 @@ export const GameDetailsDialog = ({
<TableRowColumn>
<Trans>Day {dayIndex} retained players</Trans>
</TableRowColumn>
<TableRowColumn>
<TableRowColumn style={styles.tableRowStatColumn}>
{gameRollingMetrics &&
gameRollingMetrics.retention &&
gameRollingMetrics.retention[

View File

@@ -11,6 +11,10 @@ export type PublicGame = {
publicWebBuildId?: ?string,
description?: string,
authors: Array<UserPublicProfile>,
metrics?: {
lastWeekSessionsCount: number,
lastYearSessionsCount: number,
},
};
export type Game = {