Skip to content

Commit

Permalink
Add an information button on behaviors (#5505)
Browse files Browse the repository at this point in the history
* Show authors on hovering
* Open extension details on click
  • Loading branch information
D8H authored Jul 27, 2023
1 parent 1e2ffe5 commit b5f0758
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 47 deletions.
52 changes: 46 additions & 6 deletions newIDE/app/src/AssetStore/BehaviorStore/BehaviorListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { type BehaviorShortHeader } from '../../Utils/GDevelopServices/Extension
import ButtonBase from '@material-ui/core/ButtonBase';
import Text from '../../UI/Text';
import { Trans } from '@lingui/macro';
import { Column } from '../../UI/Grid';
import { Line, Column } from '../../UI/Grid';
import { IconContainer } from '../../UI/IconContainer';
import HighlightedText from '../../UI/Search/HighlightedText';
import { type SearchMatch } from '../../UI/Search/UseSearchStructuredItem';
import Chip from '../../UI/Chip';
import { LineStackLayout } from '../../UI/Layout';
import { type SearchableBehaviorMetadata } from './BehaviorStoreContext';
import { UserPublicProfileChip } from '../../UI/User/UserPublicProfileChip';
import Tooltip from '@material-ui/core/Tooltip';
import CircledInfo from '../../UI/CustomSvgIcons/SmallCircledInfo';
import IconButton from '../../UI/IconButton';

const styles = {
button: { width: '100%' },
Expand All @@ -20,9 +24,6 @@ const styles = {
overflow: 'hidden',
width: '100%',
},
icon: {
paddingTop: 4,
},
};

type Props = {|
Expand All @@ -32,6 +33,7 @@ type Props = {|
behaviorShortHeader: BehaviorShortHeader | SearchableBehaviorMetadata,
matches: ?Array<SearchMatch>,
onChoose: () => void,
onShowDetails: () => void,
onHeightComputed: number => void,
|};

Expand All @@ -42,6 +44,7 @@ export const BehaviorListItem = ({
behaviorShortHeader,
matches,
onChoose,
onShowDetails,
onHeightComputed,
}: Props) => {
const alreadyAdded = objectBehaviorsTypes.includes(behaviorShortHeader.type);
Expand Down Expand Up @@ -83,6 +86,16 @@ export const BehaviorListItem = ({
[isEnabled, onChoose]
);

const hasChip =
alreadyAdded ||
isObjectIncompatible ||
behaviorShortHeader.tier === 'community' ||
(behaviorShortHeader.isDeprecated || false);
const hasInfoButton = behaviorShortHeader.authors || false;
const iconStyle = {
paddingTop: hasInfoButton ? 10 : hasChip ? 6 : 4,
};

return (
<ButtonBase
id={id}
Expand All @@ -97,15 +110,15 @@ export const BehaviorListItem = ({
ref={containerRef}
>
<LineStackLayout>
<div style={styles.icon}>
<div style={iconStyle}>
<IconContainer
alt={behaviorShortHeader.fullName}
src={behaviorShortHeader.previewIconUrl}
size={32}
/>
</div>
<Column expand>
<LineStackLayout noMargin alignItems="baseline">
<LineStackLayout noMargin alignItems="center">
<Text
noMargin
allowBrowserAutoTranslate={false}
Expand Down Expand Up @@ -143,6 +156,33 @@ export const BehaviorListItem = ({
color="primary"
/>
)}
{behaviorShortHeader.authors && (
<Tooltip
title={
<Line>
<div style={{ flexWrap: 'wrap' }}>
{behaviorShortHeader.authors.map(author => (
<UserPublicProfileChip
user={author}
key={author.id}
variant="outlined"
/>
))}
</div>
</Line>
}
>
<IconButton
size="small"
onClick={e => {
e.stopPropagation();
onShowDetails();
}}
>
<CircledInfo />
</IconButton>
</Tooltip>
)}
</LineStackLayout>
<Text
noMargin
Expand Down
18 changes: 18 additions & 0 deletions newIDE/app/src/AssetStore/BehaviorStore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import ElementWithMenu from '../../UI/Menu/ElementWithMenu';
import IconButton from '../../UI/IconButton';
import ThreeDotsMenu from '../../UI/CustomSvgIcons/ThreeDotsMenu';
import useAlertDialog from '../../UI/Alert/useAlertDialog';
import ExtensionInstallDialog from '../ExtensionStore/ExtensionInstallDialog';

export const useExtensionUpdateAlertDialog = () => {
const { showConfirmation } = useAlertDialog();
Expand Down Expand Up @@ -60,6 +61,10 @@ export const BehaviorStore = ({
onChoose,
}: Props) => {
const preferences = React.useContext(PreferencesContext);
const [
selectedBehaviorShortHeader,
setSelectedBehaviorShortHeader,
] = React.useState<?BehaviorShortHeader>(null);
const {
filters,
searchResults,
Expand Down Expand Up @@ -258,10 +263,23 @@ export const BehaviorStore = ({
onChoose={() => {
installAndChoose(behaviorShortHeader);
}}
onShowDetails={() => {
if (behaviorShortHeader.headerUrl) {
setSelectedBehaviorShortHeader(behaviorShortHeader);
}
}}
/>
)}
/>
</ColumnStackLayout>
{!!selectedBehaviorShortHeader && (
<ExtensionInstallDialog
project={project}
isInstalling={isInstalling}
extensionShortHeader={selectedBehaviorShortHeader}
onClose={() => setSelectedBehaviorShortHeader(null)}
/>
)}
</React.Fragment>
);
};
63 changes: 35 additions & 28 deletions newIDE/app/src/AssetStore/ExtensionStore/ExtensionInstallDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import FlatButton from '../../UI/FlatButton';
import {
type ExtensionShortHeader,
type ExtensionHeader,
type BehaviorShortHeader,
getExtensionHeader,
isCompatibleWithExtension,
} from '../../Utils/GDevelopServices/Extension';
Expand Down Expand Up @@ -55,10 +56,10 @@ const getTransformedDescription = (extensionHeader: ExtensionHeader) => {
};

type Props = {|
extensionShortHeader: ExtensionShortHeader,
extensionShortHeader: ExtensionShortHeader | BehaviorShortHeader,
isInstalling: boolean,
onClose: () => void,
onInstall: () => Promise<void>,
onInstall?: () => Promise<void>,
onEdit?: () => void,
project: gdProject,
|};
Expand Down Expand Up @@ -114,7 +115,7 @@ const ExtensionInstallDialog = ({
const canInstallExtension = !isInstalling && isCompatible;
const onInstallExtension = React.useCallback(
() => {
if (canInstallExtension) {
if (canInstallExtension && onInstall) {
if (alreadyInstalled) {
let dialogText =
'This extension is already in your project, this will install the latest version. You may have to do some adaptations to make sure your game still works. Do you want to continue?';
Expand Down Expand Up @@ -164,35 +165,37 @@ const ExtensionInstallDialog = ({
onClick={onClose}
disabled={isInstalling}
/>,
<LeftLoader isLoading={isInstalling} key="install">
<DialogPrimaryButton
id="install-extension-button"
label={
!isCompatible ? (
<Trans>Not compatible</Trans>
) : alreadyInstalled ? (
fromStore ? (
extensionUpdate ? (
extensionShortHeader.tier === 'community' ? (
<Trans>Update (could break the project)</Trans>
onInstall ? (
<LeftLoader isLoading={isInstalling} key="install">
<DialogPrimaryButton
id="install-extension-button"
label={
!isCompatible ? (
<Trans>Not compatible</Trans>
) : alreadyInstalled ? (
fromStore ? (
extensionUpdate ? (
extensionShortHeader.tier === 'community' ? (
<Trans>Update (could break the project)</Trans>
) : (
<Trans>Update</Trans>
)
) : (
<Trans>Update</Trans>
<Trans>Re-install</Trans>
)
) : (
<Trans>Re-install</Trans>
<Trans>Replace existing extension</Trans>
)
) : (
<Trans>Replace existing extension</Trans>
<Trans>Install in project</Trans>
)
) : (
<Trans>Install in project</Trans>
)
}
primary
onClick={onInstallExtension}
disabled={!canInstallExtension}
/>
</LeftLoader>,
}
primary
onClick={onInstallExtension}
disabled={!canInstallExtension}
/>
</LeftLoader>
) : null,
]}
secondaryActions={[
onEdit ? (
Expand Down Expand Up @@ -225,7 +228,7 @@ const ExtensionInstallDialog = ({
open
cannotBeDismissed={isInstalling}
onRequestClose={onClose}
onApply={onInstallExtension}
onApply={onInstall ? onInstallExtension : onClose}
>
<ColumnStackLayout expand noMargin>
<Line alignItems="flex-start" noMargin>
Expand All @@ -252,7 +255,11 @@ const ExtensionInstallDialog = ({
</Line>
</Column>
</Line>
<Text noMargin>{extensionShortHeader.shortDescription}</Text>
<Text noMargin>
{extensionHeader
? extensionHeader.shortDescription
: extensionShortHeader.shortDescription || ''}
</Text>
<Divider />
{extensionHeader && (
<MarkdownText
Expand Down
17 changes: 11 additions & 6 deletions newIDE/app/src/AssetStore/ExtensionStore/UseExtensionUpdates.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//@flow
import { diff } from 'semver/functions/diff';
import { useMemo } from 'react';
import type { ExtensionShortHeader } from '../../Utils/GDevelopServices/Extension';
import type {
ExtensionShortHeader,
BehaviorShortHeader,
} from '../../Utils/GDevelopServices/Extension';

type UpdateType = 'patch' | 'minor' | 'major';
type UpdateMetadata = {|
Expand Down Expand Up @@ -43,16 +46,18 @@ const getUpdateMetadataFromVersions = (

export const useExtensionUpdate = (
project: gdProject,
extension: ExtensionShortHeader
extension: ExtensionShortHeader | BehaviorShortHeader
): UpdateMetadata | null => {
return useMemo<UpdateMetadata | null>(
() =>
project.hasEventsFunctionsExtensionNamed(extension.name)
() => {
const extensionName = extension.extensionName || extension.name;
return project.hasEventsFunctionsExtensionNamed(extensionName)
? getUpdateMetadataFromVersions(
project.getEventsFunctionsExtension(extension.name).getVersion(),
project.getEventsFunctionsExtension(extensionName).getVersion(),
extension.version
)
: null,
: null;
},
[project, extension]
);
};
5 changes: 4 additions & 1 deletion newIDE/app/src/BehaviorsEditor/NewBehaviorDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ export default function NewBehaviorDialog({
installExtension
);

const deprecatedBehaviorsInformation = getDeprecatedBehaviorsInformation();
const deprecatedBehaviorsInformation = React.useMemo(
() => getDeprecatedBehaviorsInformation(),
[]
);

const allInstalledBehaviorMetadataList: Array<SearchableBehaviorMetadata> = React.useMemo(
() => {
Expand Down
2 changes: 1 addition & 1 deletion newIDE/app/src/Debugger/DebuggerConsole.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Checkbox from '../UI/Checkbox';

import TimerIcon from '@material-ui/icons/Timer';

import InfoIcon from '../UI/CustomSvgIcons/Info';
import InfoIcon from '../UI/CustomSvgIcons/SquaredInfo';
import WarningIcon from '../UI/CustomSvgIcons/Warning';
import ErrorIcon from '../UI/CustomSvgIcons/Error';
import FilterIcon from '../UI/CustomSvgIcons/Filter';
Expand Down
4 changes: 2 additions & 2 deletions newIDE/app/src/UI/AlertMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Paper from './Paper';
import Cross from './CustomSvgIcons/Cross';
import WarningFilled from './CustomSvgIcons/WarningFilled';
import ErrorFilled from './CustomSvgIcons/ErrorFilled';
import Info from './CustomSvgIcons/Info';
import SquaredInfo from './CustomSvgIcons/SquaredInfo';

const styles = {
icon: { width: 28, height: 28, marginRight: 10, marginLeft: 10 },
Expand Down Expand Up @@ -88,7 +88,7 @@ const AlertMessage = ({
</React.Fragment>
) : (
<React.Fragment>
{kind === 'info' && <Info style={styles.icon} />}
{kind === 'info' && <SquaredInfo style={styles.icon} />}
{kind === 'warning' && (
<WarningFilled
style={{
Expand Down
23 changes: 23 additions & 0 deletions newIDE/app/src/UI/CustomSvgIcons/CircledInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';

export default React.memo(props => (
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7.99999 7.99996C8.36818 7.99996 8.66666 8.29844 8.66666 8.66663V9.99996C8.66666 10.3681 8.36818 10.6666 7.99999 10.6666C7.6318 10.6666 7.33332 10.3681 7.33332 9.99996V8.66663C7.33332 8.29844 7.6318 7.99996 7.99999 7.99996Z"
fill="#FAFAFA"
/>
<path
d="M7.99999 6.66663C8.36818 6.66663 8.66666 6.36815 8.66666 5.99996C8.66666 5.63177 8.36818 5.33329 7.99999 5.33329C7.6318 5.33329 7.33332 5.63177 7.33332 5.99996C7.33332 6.36815 7.6318 6.66663 7.99999 6.66663Z"
fill="#FAFAFA"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7.99999 3.66663C5.60676 3.66663 3.66666 5.60673 3.66666 7.99996C3.66666 10.3932 5.60676 12.3333 7.99999 12.3333C10.3932 12.3333 12.3333 10.3932 12.3333 7.99996C12.3333 5.60673 10.3932 3.66663 7.99999 3.66663ZM2.66666 7.99996C2.66666 5.05444 5.05447 2.66663 7.99999 2.66663C10.9455 2.66663 13.3333 5.05444 13.3333 7.99996C13.3333 10.9455 10.9455 13.3333 7.99999 13.3333C5.05447 13.3333 2.66666 10.9455 2.66666 7.99996Z"
fill="#FAFAFA"
/>
</SvgIcon>
));
23 changes: 23 additions & 0 deletions newIDE/app/src/UI/CustomSvgIcons/SmallCircledInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';

export default React.memo(props => (
<SvgIcon {...props} width="22" height="22" viewBox="-2 -2 20 20" fill="none">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7.99999 7.99996C8.36818 7.99996 8.66666 8.29844 8.66666 8.66663V9.99996C8.66666 10.3681 8.36818 10.6666 7.99999 10.6666C7.6318 10.6666 7.33332 10.3681 7.33332 9.99996V8.66663C7.33332 8.29844 7.6318 7.99996 7.99999 7.99996Z"
fill="#FAFAFA"
/>
<path
d="M7.99999 6.66663C8.36818 6.66663 8.66666 6.36815 8.66666 5.99996C8.66666 5.63177 8.36818 5.33329 7.99999 5.33329C7.6318 5.33329 7.33332 5.63177 7.33332 5.99996C7.33332 6.36815 7.6318 6.66663 7.99999 6.66663Z"
fill="#FAFAFA"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7.99999 3.66663C5.60676 3.66663 3.66666 5.60673 3.66666 7.99996C3.66666 10.3932 5.60676 12.3333 7.99999 12.3333C10.3932 12.3333 12.3333 10.3932 12.3333 7.99996C12.3333 5.60673 10.3932 3.66663 7.99999 3.66663ZM2.66666 7.99996C2.66666 5.05444 5.05447 2.66663 7.99999 2.66663C10.9455 2.66663 13.3333 5.05444 13.3333 7.99996C13.3333 10.9455 10.9455 13.3333 7.99999 13.3333C5.05447 13.3333 2.66666 10.9455 2.66666 7.99996Z"
fill="#FAFAFA"
/>
</SvgIcon>
));
File renamed without changes.
Loading

0 comments on commit b5f0758

Please sign in to comment.