Skip to content

Commit

Permalink
Add field to enter the GitHub username in user profile
Browse files Browse the repository at this point in the history
  • Loading branch information
4ian committed Apr 23, 2024
1 parent 266f0f2 commit b570e10
Show file tree
Hide file tree
Showing 17 changed files with 496 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ const GetStartedSection = ({
// Artificial delay to build up expectations.
recommendationsGettingDelayPromise.current = delay(2500);
await Promise.all([
onEditProfile({ survey }, preferences, { throwError: true }),
onEditProfile({ survey }, preferences),
recommendationsGettingDelayPromise.current,
]);
sendUserSurveyCompleted();
Expand Down
36 changes: 4 additions & 32 deletions newIDE/app/src/Profile/Achievement/UserAchievements.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// @flow

import { Trans } from '@lingui/macro';
import React, { useState, useEffect, useCallback } from 'react';
import React from 'react';
import AlertMessage from '../../UI/AlertMessage';

import { Line } from '../../UI/Grid';
import { ResponsiveLineStackLayout } from '../../UI/Layout';
import Text from '../../UI/Text';
import {
getAchievements,
type Badge,
type Achievement,
} from '../../Utils/GDevelopServices/Badge';
Expand All @@ -19,6 +18,7 @@ import { useResponsiveWindowSize } from '../../UI/Responsive/ResponsiveWindowMea
import PlaceholderLoader from '../../UI/PlaceholderLoader';

type Props = {|
achievements: ?Array<Achievement>,
badges: ?Array<Badge>,
displayUnclaimedAchievements: boolean,
displayNotifications: boolean,
Expand All @@ -41,44 +41,16 @@ const styles = {
};

const UserAchievements = ({
achievements,
badges,
displayUnclaimedAchievements,
displayNotifications,
}: Props) => {
const [achievements, setAchievements] = useState<?Array<Achievement>>(null);
const [displayError, setDisplayError] = useState<boolean>(false);
const { isMobile } = useResponsiveWindowSize();

const fetchAchievements = useCallback(async () => {
try {
setDisplayError(false);
const achievements = await getAchievements();
setAchievements(achievements);
} catch (err) {
console.error(`Error when fetching achievements: ${err}`);
setDisplayError(true);
}
}, []);

useEffect(
() => {
fetchAchievements();
},
[fetchAchievements]
);

return (
<ResponsiveLineStackLayout>
{displayError ? (
<Line>
<AlertMessage kind="error">
<Trans>Unable to display your achievements for now.</Trans>{' '}
<Trans>
Please check your internet connection or try again later.
</Trans>
</AlertMessage>
</Line>
) : !!badges && !!achievements ? (
{!!badges && !!achievements ? (
<>
<div style={styles.leftContainer}>
<div
Expand Down
7 changes: 4 additions & 3 deletions newIDE/app/src/Profile/AuthenticatedUserContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { type PreferencesValues } from '../MainFrame/Preferences/PreferencesContext';
import { type CloudProjectWithUserAccessInfo } from '../Utils/GDevelopServices/Project';
import { User as FirebaseUser } from 'firebase/auth';
import { type Badge } from '../Utils/GDevelopServices/Badge';
import { type Badge, type Achievement } from '../Utils/GDevelopServices/Badge';
import { type Recommendation } from '../Utils/GDevelopServices/User';
import { type Notification } from '../Utils/GDevelopServices/Notification';
import {
Expand Down Expand Up @@ -57,8 +57,7 @@ export type AuthenticatedUser = {|
) => Promise<void>,
onEditProfile: (
payload: PatchUserPayload,
preferences: PreferencesValues,
options: {| throwError: boolean |}
preferences: PreferencesValues
) => Promise<void>,
onResetPassword: ForgotPasswordForm => Promise<void>,
onOpenLoginDialog: () => void,
Expand All @@ -82,6 +81,7 @@ export type AuthenticatedUser = {|
|}) => void,
onAcceptGameStatsEmail: (value: boolean) => Promise<void>,
getAuthorizationHeader: () => Promise<string>,
achievements: ?Array<Achievement>,
|};

export const initialAuthenticatedUser = {
Expand Down Expand Up @@ -129,6 +129,7 @@ export const initialAuthenticatedUser = {
onOpenEmailVerificationDialog: () => {},
onAcceptGameStatsEmail: async () => {},
getAuthorizationHeader: () => Promise.reject(new Error('Unimplemented')),
achievements: null,
};

export const authenticatedUserLoggedOutAttributes = {
Expand Down
1 change: 1 addition & 0 deletions newIDE/app/src/Profile/AuthenticatedUserProfileDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const AuthenticatedUserProfileDetails = ({
: null
}
subscription={authenticatedUser.subscription}
achievements={authenticatedUser.achievements}
isAuthenticatedUserProfile
onOpenChangeEmailDialog={onOpenChangeEmailDialog}
onOpenEditProfileDialog={onOpenEditProfileDialog}
Expand Down
69 changes: 61 additions & 8 deletions newIDE/app/src/Profile/AuthenticatedUserProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import {
listDefaultRecommendations,
listRecommendations,
} from '../Utils/GDevelopServices/User';
import {
type Achievement,
getAchievements,
} from '../Utils/GDevelopServices/Badge';
import Authentication, {
type LoginForm,
type RegisterForm,
Expand Down Expand Up @@ -840,6 +844,17 @@ export default class AuthenticatedUserProvider extends React.Component<
badges,
},
}));

// Load achievements only once, as they are the same across all users.
if (!this.state.authenticatedUser.achievements) {
const achievements = await getAchievements();
this.setState(({ authenticatedUser }) => ({
authenticatedUser: {
...authenticatedUser,
achievements,
},
}));
}
} catch (error) {
console.error('Error while loading user badges:', error);
}
Expand Down Expand Up @@ -991,8 +1006,7 @@ export default class AuthenticatedUserProvider extends React.Component<

_doEdit = async (
payload: PatchUserPayload,
preferences: PreferencesValues,
{ throwError }: {| throwError: boolean |}
preferences: PreferencesValues
) => {
const { authentication } = this.props;
if (!authentication) return;
Expand All @@ -1013,17 +1027,16 @@ export default class AuthenticatedUserProvider extends React.Component<
appLanguage: preferences.language,
donateLink: payload.donateLink,
discordUsername: payload.discordUsername,
githubUsername: payload.githubUsername,
communityLinks: payload.communityLinks,
survey: payload.survey,
}
);
await this._fetchUserProfileWithoutThrowingErrors();
this.openEditProfileDialog(false);
} catch (apiCallError) {
this.setState({ apiCallError });
if (throwError) {
throw apiCallError;
}

throw apiCallError;
} finally {
this.setState({
editInProgress: false,
Expand Down Expand Up @@ -1259,6 +1272,36 @@ export default class AuthenticatedUserProvider extends React.Component<
});
};

_onUpdateGithubStar = async (
githubUsername: string,
preferences: PreferencesValues
) => {
const { authentication } = this.props;

await this._doEdit(
{
githubUsername,
},
preferences
);

this.setState({
editInProgress: true,
});
try {
const response = authentication.updateGitHubStar(
authentication.getAuthorizationHeader
);
this._fetchUserBadges();

return response;
} finally {
this.setState({
editInProgress: false,
});
}
};

render() {
return (
<PreferencesContext.Consumer>
Expand Down Expand Up @@ -1288,10 +1331,20 @@ export default class AuthenticatedUserProvider extends React.Component<
this.state.editProfileDialogOpen && (
<EditProfileDialog
profile={this.state.authenticatedUser.profile}
achievements={this.state.authenticatedUser.achievements}
badges={this.state.authenticatedUser.badges}
subscription={this.state.authenticatedUser.subscription}
onClose={() => this.openEditProfileDialog(false)}
onEdit={form =>
this._doEdit(form, preferences, { throwError: false })
onEdit={async form => {
try {
await this._doEdit(form, preferences);
this.openEditProfileDialog(false);
} catch (error) {
// Ignore errors, we will let the user retry in their profile.
}
}}
onUpdateGitHubStar={githubUsername =>
this._onUpdateGithubStar(githubUsername, preferences)
}
onDelete={this._doDeleteAccount}
actionInProgress={
Expand Down

0 comments on commit b570e10

Please sign in to comment.