From 702e7f1b67f8395a67490880be2b495fbb94948d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Pasteau?= <4895034+ClementPasteau@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:32:13 +0100 Subject: [PATCH] Games can be played inside the Play section --- .../playerauthenticationtools.ts | 3 +- newIDE/app/src/AssetStore/AssetDetails.js | 29 +- newIDE/app/src/AssetStore/AssetsList.js | 41 +-- .../PrivateAssetPackInformationPage.js | 29 +- .../PrivateGameTemplateInformationPage.js | 37 +- .../GameDashboard/Feedbacks/FeedbackCard.js | 21 +- .../EditorContainers/HomePage/HomePageMenu.js | 6 +- .../EditorContainers/HomePage/PlaySection.js | 60 ---- .../PlaySection/GamesPlatformFrame.js | 112 ++++++ .../PlaySection/GamesPlatformFrameContext.js | 334 ++++++++++++++++++ .../HomePage/PlaySection/index.js | 42 +++ newIDE/app/src/MainFrame/Providers.js | 13 +- newIDE/app/src/MainFrame/RouterContext.js | 3 +- newIDE/app/src/MainFrame/TabsTitlebar.js | 7 +- newIDE/app/src/MainFrame/index.js | 28 +- .../app/src/Profile/PublicProfileContext.js | 199 ++++++++++- newIDE/app/src/Profile/PublicProfileDialog.js | 21 +- .../app/src/Profile/PublicProfileProvider.js | 56 --- newIDE/app/src/UI/ClosableTabs.js | 2 + newIDE/app/src/UI/GdGamesFrame.js | 3 + newIDE/app/src/UI/Toolbar.js | 1 + .../app/src/UI/User/UserPublicProfileChip.js | 4 +- .../User/UserPublicProfileTextWithAvatar.js | 4 +- newIDE/app/src/Utils/GDevelopServices/User.js | 16 + .../AssetStore/AssetDetails.stories.js | 2 +- 25 files changed, 830 insertions(+), 243 deletions(-) delete mode 100644 newIDE/app/src/MainFrame/EditorContainers/HomePage/PlaySection.js create mode 100644 newIDE/app/src/MainFrame/EditorContainers/HomePage/PlaySection/GamesPlatformFrame.js create mode 100644 newIDE/app/src/MainFrame/EditorContainers/HomePage/PlaySection/GamesPlatformFrameContext.js create mode 100644 newIDE/app/src/MainFrame/EditorContainers/HomePage/PlaySection/index.js delete mode 100644 newIDE/app/src/Profile/PublicProfileProvider.js diff --git a/Extensions/PlayerAuthentication/playerauthenticationtools.ts b/Extensions/PlayerAuthentication/playerauthenticationtools.ts index f2e308ba5a09..3655386255ac 100644 --- a/Extensions/PlayerAuthentication/playerauthenticationtools.ts +++ b/Extensions/PlayerAuthentication/playerauthenticationtools.ts @@ -461,8 +461,7 @@ namespace gdjs { checkOrigin: boolean; onDone?: (status: 'logged' | 'errored' | 'dismissed') => void; }) { - const allowedOrigins = ['https://liluo.io', 'https://gd.games']; - // const allowedOrigins = ['localhost:4000']; + const allowedOrigins = ['https://liluo.io', 'https://gd.games', 'http://localhost:4000']; // Check origin of message. if (checkOrigin && !allowedOrigins.includes(event.origin)) { diff --git a/newIDE/app/src/AssetStore/AssetDetails.js b/newIDE/app/src/AssetStore/AssetDetails.js index 176aeae88e3f..076c3982961c 100644 --- a/newIDE/app/src/AssetStore/AssetDetails.js +++ b/newIDE/app/src/AssetStore/AssetDetails.js @@ -40,9 +40,9 @@ import { } from '../Utils/GDevelopServices/User'; import ArrowRight from '../UI/CustomSvgIcons/ArrowRight'; import ArrowLeft from '../UI/CustomSvgIcons/ArrowLeft'; -import PublicProfileDialog from '../Profile/PublicProfileDialog'; import Skeleton from '@material-ui/lab/Skeleton'; import { AssetPreviewImage } from './AssetPreviewImage'; +import PublicProfileContext from '../Profile/PublicProfileContext'; const FIXED_HEIGHT = 250; const FIXED_WIDTH = 300; @@ -129,10 +129,7 @@ export const AssetDetails = React.forwardRef( const [authorPublicProfiles, setAuthorPublicProfiles] = React.useState< UserPublicProfile[] >([]); - const [ - selectedAuthorPublicProfile, - setSelectedAuthorPublicProfile, - ] = React.useState(null); + const { openUserPublicProfile } = React.useContext(PublicProfileContext); const scrollView = React.useRef(null); React.useImperativeHandle(ref, () => ({ @@ -317,7 +314,13 @@ export const AssetDetails = React.forwardRef( key={userPublicProfile.id} href="#" onClick={() => - setSelectedAuthorPublicProfile(userPublicProfile) + openUserPublicProfile({ + userId: userPublicProfile.id, + callbacks: { + onAssetPackOpen: onPrivateAssetPackSelection, + onGameTemplateOpen: onPrivateGameTemplateSelection, + }, + }) } > {username} @@ -540,20 +543,6 @@ export const AssetDetails = React.forwardRef( /> - {selectedAuthorPublicProfile && ( - setSelectedAuthorPublicProfile(null)} - onAssetPackOpen={assetPack => { - onPrivateAssetPackSelection(assetPack); - setSelectedAuthorPublicProfile(null); - }} - onGameTemplateOpen={gameTemplate => { - onPrivateGameTemplateSelection(gameTemplate); - setSelectedAuthorPublicProfile(null); - }} - /> - )} ); diff --git a/newIDE/app/src/AssetStore/AssetsList.js b/newIDE/app/src/AssetStore/AssetsList.js index ac796d86542c..fdd9815a8a44 100644 --- a/newIDE/app/src/AssetStore/AssetsList.js +++ b/newIDE/app/src/AssetStore/AssetsList.js @@ -42,7 +42,6 @@ import { type UserPublicProfile, } from '../Utils/GDevelopServices/User'; import Link from '../UI/Link'; -import PublicProfileDialog from '../Profile/PublicProfileDialog'; import Window from '../Utils/Window'; import Breadcrumbs from '../UI/Breadcrumbs'; import { getFolderTagsFromAssetShortHeaders } from './TagsHelper'; @@ -52,6 +51,7 @@ import FlatButton from '../UI/FlatButton'; import HelpIcon from '../UI/HelpIcon'; import { OwnedProductLicense } from './ProductLicense/ProductLicenseOptions'; import { getUserProductPurchaseUsageType } from './ProductPageHelper'; +import PublicProfileContext from '../Profile/PublicProfileContext'; const ASSETS_DISPLAY_LIMIT = 60; @@ -299,10 +299,7 @@ const AssetsList = React.forwardRef( authorPublicProfile, setAuthorPublicProfile, ] = React.useState(null); - const [ - openAuthorPublicProfileDialog, - setOpenAuthorPublicProfileDialog, - ] = React.useState(false); + const { openUserPublicProfile } = React.useContext(PublicProfileContext); const [ isNavigatingInsideFolder, setIsNavigatingInsideFolder, @@ -855,7 +852,19 @@ const AssetsList = React.forwardRef( by{' '} setOpenAuthorPublicProfileDialog(true)} + onClick={() => + openUserPublicProfile({ + userId: authorPublicProfile.id, + callbacks: { + onAssetPackOpen: onPrivateAssetPackSelection + ? onPrivateAssetPackSelection + : undefined, + onGameTemplateOpen: onPrivateGameTemplateSelection + ? onPrivateGameTemplateSelection + : undefined, + }, + }) + } href="#" > {authorPublicProfile.username || ''} @@ -976,26 +985,6 @@ const AssetsList = React.forwardRef( // It's not an audio pack. !isAssetPackAudioOnly(openedAssetPack)) && noResultComponent} - {onPrivateAssetPackSelection && - onPrivateGameTemplateSelection && - openAuthorPublicProfileDialog && - authorPublicProfile && ( - setOpenAuthorPublicProfileDialog(false)} - onAssetPackOpen={assetPackListingData => { - onPrivateAssetPackSelection(assetPackListingData); - setOpenAuthorPublicProfileDialog(false); - setAuthorPublicProfile(null); - }} - onGameTemplateOpen={gameTemplateListingData => { - onPrivateGameTemplateSelection(gameTemplateListingData); - setOpenAuthorPublicProfileDialog(false); - setAuthorPublicProfile(null); - }} - /> - )} - {currentPage && assetShortHeaders && assetShortHeaders.length > getPageBreakAssetUpperIndex(0) && ( diff --git a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js index 0af7e4a9e4f6..98218cfa7412 100644 --- a/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js +++ b/newIDE/app/src/AssetStore/PrivateAssets/PrivateAssetPackInformationPage.js @@ -29,7 +29,6 @@ import { getUserPublicProfile, type UserPublicProfile, } from '../../Utils/GDevelopServices/User'; -import PublicProfileDialog from '../../Profile/PublicProfileDialog'; import Link from '../../UI/Link'; import ResponsiveMediaGallery from '../../UI/ResponsiveMediaGallery'; import { @@ -64,6 +63,7 @@ import PasswordPromptDialog from '../PasswordPromptDialog'; import Window from '../../Utils/Window'; import RaisedButton from '../../UI/RaisedButton'; import PrivateAssetPackPurchaseDialog from './PrivateAssetPackPurchaseDialog'; +import PublicProfileContext from '../../Profile/PublicProfileContext'; const cellSpacing = 8; @@ -206,10 +206,7 @@ const PrivateAssetPackInformationPage = ({ const [isRedeemingProduct, setIsRedeemingProduct] = React.useState( false ); - const [ - openSellerPublicProfileDialog, - setOpenSellerPublicProfileDialog, - ] = React.useState(false); + const { openUserPublicProfile } = React.useContext(PublicProfileContext); const [ sellerPublicProfile, setSellerPublicProfile, @@ -612,7 +609,13 @@ const PrivateAssetPackInformationPage = ({ - setOpenSellerPublicProfileDialog(true) + openUserPublicProfile({ + userId: sellerPublicProfile.id, + callbacks: { + onAssetPackOpen, + onGameTemplateOpen, + }, + }) } href="#" > @@ -791,20 +794,6 @@ const PrivateAssetPackInformationPage = ({ ) : null} - {openSellerPublicProfileDialog && ( - setOpenSellerPublicProfileDialog(false)} - onAssetPackOpen={assetPackListingData => { - onAssetPackOpen(assetPackListingData); - setOpenSellerPublicProfileDialog(false); - }} - onGameTemplateOpen={gameTemplateListingData => { - onGameTemplateOpen(gameTemplateListingData); - setOpenSellerPublicProfileDialog(false); - }} - /> - )} {displayPasswordPrompt && ( (null); const [isFetching, setIsFetching] = React.useState(false); - const [ - openSellerPublicProfileDialog, - setOpenSellerPublicProfileDialog, - ] = React.useState(false); + const { openUserPublicProfile } = React.useContext(PublicProfileContext); const [ sellerPublicProfile, setSellerPublicProfile, @@ -494,7 +491,13 @@ const PrivateGameTemplateInformationPage = ({ - setOpenSellerPublicProfileDialog(true) + openUserPublicProfile({ + userId: sellerPublicProfile.id, + callbacks: { + onAssetPackOpen, + onGameTemplateOpen, + }, + }) } href="#" > @@ -633,28 +636,6 @@ const PrivateGameTemplateInformationPage = ({ ) : null} - {openSellerPublicProfileDialog && ( - setOpenSellerPublicProfileDialog(false)} - onGameTemplateOpen={ - onGameTemplateOpen - ? (gameTemplate: PrivateGameTemplateListingData) => { - setOpenSellerPublicProfileDialog(false); - onGameTemplateOpen(gameTemplate); - } - : undefined - } - onAssetPackOpen={ - onAssetPackOpen - ? (assetPack: PrivateAssetPackListingData) => { - setOpenSellerPublicProfileDialog(false); - onAssetPackOpen(assetPack); - } - : undefined - } - /> - )} {displayPasswordPrompt && ( (false); + const { openUserPublicProfile } = React.useContext(PublicProfileContext); + const commenterPlayerId = comment.playerId; const processComment = async (newProcessed: boolean, i18n: I18nType) => { if (!profile) return; @@ -283,9 +280,11 @@ const FeedbackCard = ({ )} )} - {comment.playerId ? ( + {commenterPlayerId ? ( setOpenPlayerPublicProfileDialog(true)} + onClick={() => + openUserPublicProfile({ userId: commenterPlayerId }) + } href="#" > @@ -324,12 +323,6 @@ const FeedbackCard = ({ - {comment.playerId && openPlayerPublicProfileDialog && ( - setOpenPlayerPublicProfileDialog(false)} - /> - )} )} diff --git a/newIDE/app/src/MainFrame/EditorContainers/HomePage/HomePageMenu.js b/newIDE/app/src/MainFrame/EditorContainers/HomePage/HomePageMenu.js index 3d366c68419b..af3eb0642d12 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/HomePage/HomePageMenu.js +++ b/newIDE/app/src/MainFrame/EditorContainers/HomePage/HomePageMenu.js @@ -24,6 +24,8 @@ import AuthenticatedUserContext from '../../../Profile/AuthenticatedUserContext' import { isNativeMobileApp } from '../../../Utils/Platform'; export const styles = { + // Ensure it's always interactive, even when another iframe disable pointer events. + container: { pointerEvents: 'all', display: 'flex' }, drawerContent: { height: '100%', width: 250, @@ -189,7 +191,7 @@ export const HomePageMenu = ({ ]; return ( - <> +
- +
); }; diff --git a/newIDE/app/src/MainFrame/EditorContainers/HomePage/PlaySection.js b/newIDE/app/src/MainFrame/EditorContainers/HomePage/PlaySection.js deleted file mode 100644 index b31cb7519e1e..000000000000 --- a/newIDE/app/src/MainFrame/EditorContainers/HomePage/PlaySection.js +++ /dev/null @@ -1,60 +0,0 @@ -// @flow -import * as React from 'react'; -import { Trans } from '@lingui/macro'; -import SectionContainer, { SectionRow } from './SectionContainer'; -import GDevelopThemeContext from '../../../UI/Theme/GDevelopThemeContext'; -import PlaceHolderLoader from '../../../UI/PlaceholderLoader'; -import ErrorBoundary from '../../../UI/ErrorBoundary'; -import PromotionsSlideshow from '../../../Promotions/PromotionsSlideshow'; -import { AnnouncementsFeed } from '../../../AnnouncementsFeed'; -import { ColumnStackLayout } from '../../../UI/Layout'; - -const styles = { - iframe: { - border: 0, - }, -}; - -const PlaySection = () => { - const gdevelopTheme = React.useContext(GDevelopThemeContext); - const paletteType = gdevelopTheme.palette.type; - const [iframeHeight, setIframeHeight] = React.useState(null); - - window.addEventListener('message', event => { - if ( - event.origin === 'https://gd.games' && - event.data.id === 'set-embedded-height' - ) { - setIframeHeight(event.data.height); - } - }); - - return ( - - - - - -