diff --git a/Core/GDCore/Extensions/Builtin/AdvancedExtension.cpp b/Core/GDCore/Extensions/Builtin/AdvancedExtension.cpp index 7a7b190b08a9..6b0d19f26a8e 100644 --- a/Core/GDCore/Extensions/Builtin/AdvancedExtension.cpp +++ b/Core/GDCore/Extensions/Builtin/AdvancedExtension.cpp @@ -33,7 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( "", "res/functions/expression_black.svg", "res/functions/expression_black.svg") - .SetHelpPath("/events/functions/return") + .SetHelpPath("/events/functions/#return-a-value-from-a-function") .AddParameter("expression", _("The number to be returned")) .SetRelevantForFunctionEventsOnly() .MarkAsAdvanced(); @@ -48,7 +48,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( "", "res/functions/expression_black.svg", "res/functions/expression_black.svg") - .SetHelpPath("/events/functions/return") + .SetHelpPath("/all-features/advanced/reference/#actions") .AddParameter("string", _("The text to be returned")) .SetRelevantForFunctionEventsOnly() .MarkAsAdvanced(); @@ -62,7 +62,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( "", "res/functions/condition_black.svg", "res/functions/condition_black.svg") - .SetHelpPath("/events/functions/return") + .SetHelpPath("/all-features/advanced/reference/#actions") .AddParameter("trueorfalse", _("Should the condition be true or false?")) .SetRelevantForFunctionEventsOnly() .MarkAsAdvanced(); @@ -77,7 +77,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( "", "res/functions/extension_black.svg", "res/functions/extension_black.svg") - .SetHelpPath("/events/functions/return") + .SetHelpPath("/all-features/advanced/reference/#actions") .AddParameter("functionParameterName", _("Parameter name"), "variable") .AddParameter("scenevar", _("Scene variable")) .SetHidden() @@ -92,7 +92,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( "", "res/functions/extension_black.svg", "res/functions/extension_black.svg") - .SetHelpPath("/events/functions/return") + .SetHelpPath("/all-features/advanced/reference/#actions") .AddParameter("functionParameterName", _("Parameter name"), "variable") .AddParameter("variable", _("Variable")) .SetRelevantForFunctionEventsOnly() @@ -108,7 +108,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( "", "res/functions/extension_black.svg", "res/functions/extension_black.svg") - .SetHelpPath("/events/functions/return") + .SetHelpPath("/all-features/advanced/reference/#actions") .AddParameter("functionParameterName", _("Parameter name"), "variable") .AddParameter("scenevar", _("Scene variable")) .SetHidden() @@ -123,7 +123,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( "", "res/functions/extension_black.svg", "res/functions/extension_black.svg") - .SetHelpPath("/events/functions/return") + .SetHelpPath("/all-features/advanced/reference/#actions") .AddParameter("functionParameterName", _("Parameter name"), "variable") .AddParameter("variable", _("Variable")) .SetRelevantForFunctionEventsOnly() diff --git a/Core/GDCore/Extensions/Builtin/MathematicalToolsExtension.cpp b/Core/GDCore/Extensions/Builtin/MathematicalToolsExtension.cpp index 1e7b593b8757..18b0979bd328 100644 --- a/Core/GDCore/Extensions/Builtin/MathematicalToolsExtension.cpp +++ b/Core/GDCore/Extensions/Builtin/MathematicalToolsExtension.cpp @@ -28,7 +28,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension( _("Random integer"), "", "res/dice-6.svg") - .SetHelpPath("/all-features/expressions") + .SetHelpPath("/events/expressions/#expressions") .AddParameter("expression", _("Maximum value")); extension @@ -37,7 +37,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension( _("Random integer in range"), "", "res/dice-6.svg") - .SetHelpPath("/all-features/expressions") + .SetHelpPath("/events/expressions/#expressions") .AddParameter("expression", _("Minimum value")) .AddParameter("expression", _("Maximum value")); @@ -47,7 +47,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension( _("Random float"), "", "res/dice-6.svg") - .SetHelpPath("/all-features/expressions") + .SetHelpPath("/events/expressions/#expressions") .AddParameter("expression", _("Maximum value")); extension @@ -56,7 +56,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension( _("Random float in range"), "", "res/dice-6.svg") - .SetHelpPath("/all-features/expressions") + .SetHelpPath("/events/expressions/#expressions") .AddParameter("expression", _("Minimum value")) .AddParameter("expression", _("Maximum value")); @@ -66,7 +66,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension( _("Random value in steps"), "", "res/dice-6.svg") - .SetHelpPath("/all-features/expressions") + .SetHelpPath("/events/expressions/#expressions") .AddParameter("expression", _("Minimum value")) .AddParameter("expression", _("Maximum value")) .AddParameter("expression", _("Step")); @@ -476,7 +476,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension( _("The number Pi (3.1415...)"), "", "res/mathfunction.png") - .SetHelpPath("/all-features/expressions"); + .SetHelpPath("/events/expressions/#expressions"); extension .AddExpression("lerpAngle", diff --git a/Core/GDCore/Extensions/Builtin/SceneExtension.cpp b/Core/GDCore/Extensions/Builtin/SceneExtension.cpp index e11eec3b0da2..20a0da0beba9 100644 --- a/Core/GDCore/Extensions/Builtin/SceneExtension.cpp +++ b/Core/GDCore/Extensions/Builtin/SceneExtension.cpp @@ -44,7 +44,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/conditions/depart24.png", "res/conditions/depart.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .MarkAsSimple(); @@ -60,7 +60,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/conditions/depart24.png", "res/conditions/depart.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .MarkAsSimple(); @@ -72,7 +72,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/texte.png", "res/actions/texte.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .AddParameter("sceneName", _("Name of the scene to check")) .MarkAsSimple(); @@ -85,7 +85,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/replaceScene24.png", "res/actions/replaceScene.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .AddParameter("sceneName", _("Name of the new scene")) .AddParameter("yesorno", _("Stop any other paused scenes?")) @@ -102,7 +102,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/pushScene24.png", "res/actions/pushScene.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .AddParameter("sceneName", _("Name of the new scene")) .MarkAsAdvanced(); @@ -117,7 +117,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/popScene24.png", "res/actions/popScene.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .MarkAsAdvanced(); @@ -129,7 +129,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/quit24.png", "res/actions/quit.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .MarkAsAdvanced(); @@ -141,7 +141,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/background24.png", "res/actions/background.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .AddParameter("color", _("Color")) .MarkAsAdvanced(); @@ -155,7 +155,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/window24.png", "res/actions/window.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", "") .AddParameter("yesorno", _("Deactivate input when focus is lost")) .MarkAsAdvanced(); @@ -171,7 +171,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension( "", "res/actions/window24.png", "res/actions/window.png") - .SetHelpPath("/interface/scene-editor/events") + .SetHelpPath("/interface/events-editor/") .AddCodeOnlyParameter("currentScene", ""); extension diff --git a/newIDE/app/src/AssetStore/ExtensionStore/ExtensionDetailPanel.js b/newIDE/app/src/AssetStore/ExtensionStore/ExtensionDetailPanel.js index 38df6616b672..ac6d205d5c56 100644 --- a/newIDE/app/src/AssetStore/ExtensionStore/ExtensionDetailPanel.js +++ b/newIDE/app/src/AssetStore/ExtensionStore/ExtensionDetailPanel.js @@ -1,5 +1,6 @@ // @flow import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import FlatButton from '../../UI/FlatButton'; import RaisedButton from '../../UI/RaisedButton'; @@ -285,132 +286,141 @@ const ExtensionDetailPanel = ({ : null; return ( - - - - - - {extensionUpdate && - installedExtension && - extensionShortHeader.version !== installedExtension.getVersion() ? ( - {`Version ${installedExtension.getVersion()} (${ - extensionShortHeader.version - } available)`} - ) : ( - {`Version ${extensionShortHeader.version}`} - )} - - -
- {extensionShortHeader.authors && - extensionShortHeader.authors.map(author => ( - + {({ i18n }) => ( + + + + + + {extensionUpdate && + installedExtension && + extensionShortHeader.version !== + installedExtension.getVersion() ? ( + {`Version ${installedExtension.getVersion()} (${ + extensionShortHeader.version + } available)`} + ) : ( + {`Version ${extensionShortHeader.version}`} + )} + + +
+ {extensionShortHeader.authors && + extensionShortHeader.authors.map(author => ( + + ))} +
+
+
+ {shouldDisplayButtons && onInstall && ( + + + - ))} -
+ +
+ )}
- - {shouldDisplayButtons && onInstall && ( - - - - - - )} - - - {extensionHeader - ? extensionHeader.shortDescription - : typeof extensionShortHeader.shortDescription === 'string' - ? extensionShortHeader.shortDescription || '' - : ''} - - - {extensionHeader && ( - - )} - {extensionShortHeader.tier === 'experimental' && ( - - - This is an extension made by a community member and it only got - through a light review by the GDevelop extension team. As such, we - can't guarantee it meets all the quality standards of fully reviewed - extensions. - - - )} - {!isCompatible && ( - - - Unfortunately, this extension requires a newer version of GDevelop - to work. Update GDevelop to be able to use this extension in your - project. - - - )} - {!extensionHeader && !error && } - {!extensionHeader && error && ( - - - Can't load the extension registry. Verify your internet connection - or try again later. - - - )} - {newBreakingChangesText && ( - <> - - Breaking changes + + {extensionHeader + ? extensionHeader.shortDescription + : typeof extensionShortHeader.shortDescription === 'string' + ? extensionShortHeader.shortDescription || '' + : ''} - - - )} - {oldBreakingChangesText && ( - - - - Previous breaking changes (no longer relevant) - - - - - - - )} - - {shouldDisplayButtons && - extensionHeader && - extensionHeader.helpPath && ( - + {extensionHeader && ( + )} - {shouldDisplayButtons && isAlreadyInstalled && ( - Report an issue} - onClick={() => onUserReportIssue()} - /> - )} - -
+ {extensionShortHeader.tier === 'experimental' && ( + + + This is an extension made by a community member and it only got + through a light review by the GDevelop extension team. As such, + we can't guarantee it meets all the quality standards of fully + reviewed extensions. + + + )} + {!isCompatible && ( + + + Unfortunately, this extension requires a newer version of + GDevelop to work. Update GDevelop to be able to use this + extension in your project. + + + )} + {!extensionHeader && !error && } + {!extensionHeader && error && ( + + + Can't load the extension registry. Verify your internet + connection or try again later. + + + )} + {newBreakingChangesText && ( + <> + + Breaking changes + + + + )} + {oldBreakingChangesText && ( + + + + Previous breaking changes (no longer relevant) + + + + + + + )} + + {shouldDisplayButtons && + extensionHeader && + extensionHeader.helpPath && ( + + )} + {shouldDisplayButtons && isAlreadyInstalled && ( + Report an issue} + onClick={() => onUserReportIssue()} + /> + )} + + + )} + ); }; diff --git a/newIDE/app/src/AssetStore/ExtensionStore/ExtensionInstallDialog.js b/newIDE/app/src/AssetStore/ExtensionStore/ExtensionInstallDialog.js index 72ac6420f47b..19c8d831a6ab 100644 --- a/newIDE/app/src/AssetStore/ExtensionStore/ExtensionInstallDialog.js +++ b/newIDE/app/src/AssetStore/ExtensionStore/ExtensionInstallDialog.js @@ -1,5 +1,6 @@ // @flow import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import Dialog, { DialogPrimaryButton } from '../../UI/Dialog'; import FlatButton from '../../UI/FlatButton'; @@ -64,71 +65,76 @@ const ExtensionInstallDialog = ({ } = extensionDetail; return ( - Back} - primary={false} - onClick={onClose} - disabled={isInstalling} - />, - onInstall ? ( - - - - ) : null, - ]} - // $FlowFixMe[incompatible-type] - secondaryActions={[ - onEdit ? ( - Open in editor} - onClick={onEdit} + + {({ i18n }) => ( + Back} + primary={false} + onClick={onClose} + disabled={isInstalling} + />, + onInstall ? ( + + + + ) : null, + ]} + // $FlowFixMe[incompatible-type] + secondaryActions={[ + onEdit ? ( + Open in editor} + onClick={onEdit} + /> + ) : ( + undefined + ), + isAlreadyInstalled ? ( + Report an issue} + onClick={() => onUserReportIssue()} + /> + ) : ( + undefined + ), + extensionHeader && extensionHeader.helpPath ? ( + + ) : ( + undefined + ), + ].filter(Boolean)} + open + cannotBeDismissed={isInstalling} + onRequestClose={onClose} + onApply={onInstall ? onInstallExtension : onClose} + > + - ) : ( - undefined - ), - isAlreadyInstalled ? ( - Report an issue} - onClick={() => onUserReportIssue()} - /> - ) : ( - undefined - ), - extensionHeader && extensionHeader.helpPath ? ( - - ) : ( - undefined - ), - ].filter(Boolean)} - open - cannotBeDismissed={isInstalling} - onRequestClose={onClose} - onApply={onInstall ? onInstallExtension : onClose} - > - - + + )} + ); }; diff --git a/newIDE/app/src/AssetStore/ExtensionStore/ExtensionsSearchDialog.js b/newIDE/app/src/AssetStore/ExtensionStore/ExtensionsSearchDialog.js index 214201e222c0..5ee17835cd06 100644 --- a/newIDE/app/src/AssetStore/ExtensionStore/ExtensionsSearchDialog.js +++ b/newIDE/app/src/AssetStore/ExtensionStore/ExtensionsSearchDialog.js @@ -132,7 +132,11 @@ const ExtensionsSearchDialog = ({ />, ]} secondaryActions={[ - , + , eventsFunctionsExtensionOpener ? ( } diff --git a/newIDE/app/src/AssetStore/NewObjectDialog.js b/newIDE/app/src/AssetStore/NewObjectDialog.js index 6618973809e5..b4ac5c2c00a2 100644 --- a/newIDE/app/src/AssetStore/NewObjectDialog.js +++ b/newIDE/app/src/AssetStore/NewObjectDialog.js @@ -544,7 +544,11 @@ function NewObjectDialog({ New object} secondaryActions={[ - , + , ]} actions={[ , ]} secondaryActions={[ - , + , ]} open onRequestClose={onClose} diff --git a/newIDE/app/src/Debugger/DebuggerContent.js b/newIDE/app/src/Debugger/DebuggerContent.js index 500c58b2bd0b..f1c701535f98 100644 --- a/newIDE/app/src/Debugger/DebuggerContent.js +++ b/newIDE/app/src/Debugger/DebuggerContent.js @@ -1,6 +1,7 @@ // @flow import { Trans } from '@lingui/macro'; import { t } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import EditorMosaic, { type EditorMosaicInterface } from '../UI/EditorMosaic'; @@ -121,150 +122,176 @@ export default class DebuggerContent extends React.Component { rawMode, } = this.state; - const editors = { - inspectors: { - type: 'primary', - title: t`Inspectors`, - toolbarControls: [], - renderEditor: () => ( - - - - Refresh} - onClick={onRefresh} - primary - /> - - - this.setState({ - selectedInspector, - selectedInspectorFullPath, - }) - } - /> - - - ), - }, - 'selected-inspector': { - type: 'primary', - noTitleBar: true, - renderEditor: () => ( - - - - {selectedInspector ? ( - rawMode ? ( - - onEdit(selectedInspectorFullPath.concat(path), newValue) + return ( + + {({ i18n }) => { + const editors = { + inspectors: { + type: 'primary', + title: t`Inspectors`, + toolbarControls: [], + renderEditor: () => ( + + + + Refresh} + onClick={onRefresh} + primary + /> + + + this.setState({ + selectedInspector, + selectedInspectorFullPath, + }) } /> - ) : ( - selectedInspector.renderInspector( - get(gameData, selectedInspectorFullPath, null), - { - onCall: (path, args) => - onCall(selectedInspectorFullPath.concat(path), args), - onEdit: (path, newValue) => - onEdit( - selectedInspectorFullPath.concat(path), - newValue - ), - } - ) || ( - - - No inspector, choose another element in the list or - toggle the raw data view. - - - ) - ) - ) : ( - - {gameData ? ( - Choose an element to inspect in the list - ) : ( - - Pause the game (from the toolbar) or hit refresh (on the - left) to inspect the game - - )} - - )} - - - - - -
- } - uncheckedIcon={} - checked={rawMode} - onCheck={(e, enabled) => - this.setState({ - rawMode: enabled, - }) - } - /> -
-
-
-
- ), - }, - profiler: { - type: 'secondary', - title: t`Profiler`, - renderEditor: () => ( - - ), - }, - console: { - type: 'secondary', - title: t`Console`, - renderEditor: () => ( - - - - ), - }, - }; + + + ), + }, + 'selected-inspector': { + type: 'primary', + noTitleBar: true, + renderEditor: () => ( + + + + {selectedInspector ? ( + rawMode ? ( + + onEdit( + selectedInspectorFullPath.concat(path), + newValue + ) + } + /> + ) : ( + selectedInspector.renderInspector( + get(gameData, selectedInspectorFullPath, null), + { + onCall: (path, args) => + onCall( + selectedInspectorFullPath.concat(path), + args + ), + onEdit: (path, newValue) => + onEdit( + selectedInspectorFullPath.concat(path), + newValue + ), + } + ) || ( + + + No inspector, choose another element in the list + or toggle the raw data view. + + + ) + ) + ) : ( + + {gameData ? ( + + Choose an element to inspect in the list + + ) : ( + + Pause the game (from the toolbar) or hit refresh + (on the left) to inspect the game + + )} + + )} + + + + + +
+ } + uncheckedIcon={} + checked={rawMode} + onCheck={(e, enabled) => + this.setState({ + rawMode: enabled, + }) + } + /> +
+
+
+
+ ), + }, + profiler: { + type: 'secondary', + title: t`Profiler`, + renderEditor: () => ( + + ), + }, + console: { + type: 'secondary', + title: t`Console`, + renderEditor: () => ( + + + + ), + }, + }; - return ( - - {({ getDefaultEditorMosaicNode, setDefaultEditorMosaicNode }) => ( - (this._editors = editors)} - // $FlowFixMe[incompatible-type] - editors={editors} - centralNodeId="selected-inspector" - initialNodes={ - // $FlowFixMe[incompatible-type] - getDefaultEditorMosaicNode('debugger') || initialMosaicEditorNodes - } - onPersistNodes={node => - setDefaultEditorMosaicNode('debugger', node) - } - onOpenedEditorsChanged={onOpenedEditorsChanged} - /> - )} - + return ( + + {({ getDefaultEditorMosaicNode, setDefaultEditorMosaicNode }) => ( + (this._editors = editors)} + // $FlowFixMe[incompatible-type] + editors={editors} + centralNodeId="selected-inspector" + initialNodes={ + // $FlowFixMe[incompatible-type] + getDefaultEditorMosaicNode('debugger') || + initialMosaicEditorNodes + } + onPersistNodes={node => + setDefaultEditorMosaicNode('debugger', node) + } + onOpenedEditorsChanged={onOpenedEditorsChanged} + /> + )} + + ); + }} + ); } } diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/BehaviorMethodSelectorDialog.js b/newIDE/app/src/EventsFunctionsExtensionEditor/BehaviorMethodSelectorDialog.js index 86025108e000..845c508be15e 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/BehaviorMethodSelectorDialog.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/BehaviorMethodSelectorDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import { type EventsFunctionCreationParameters } from '../EventsFunctionsList/EventsFunctionTreeViewItemContent'; @@ -30,173 +31,187 @@ export default function BehaviorMethodSelectorDialog({ const [showAdvanced, setShowAdvanced] = React.useState(false); return ( - Choose a new behavior function ("method")} - secondaryActions={[ - , - ]} - actions={[ - Cancel} - keyboardFocused={true} - onClick={onCancel} - key={'close'} - />, - ]} - open - onRequestClose={onCancel} - maxWidth="sm" - > - - Action} - description={ - - An action that can be used on objects with the behavior. You can - define the action parameters: objects, texts, numbers, layers, - etc... - - } - onChoose={onChoose} - /> - Condition} - description={ - - A condition that can be used on objects with the behavior. You can - define the condition parameters: objects, texts, numbers, layers, - etc... - - } - onChoose={onChoose} - /> - Expression} - description={ - - An expression that can be used on objects with the behavior. Can - either return a number or a string, and take some parameters. - - } - onChoose={onChoose} - /> - - Lifecycle methods - - - Events that will be run once, when an object is created with this - behavior being attached to it. - - } - /> - - Events that will be run at every frame (roughly 60 times per - second), for every object that has the behavior attached, before - the events from the events sheet are launched. - - } - /> - - Events that will be run once, after the object is removed from the - scene and before it is entirely removed from memory. - - } - /> - {showAdvanced && ( - <> - - Other lifecycle methods - + + {({ i18n }) => ( + Choose a new behavior function ("method")} + secondaryActions={[ + , + ]} + actions={[ + Cancel} + keyboardFocused={true} + onClick={onCancel} + key={'close'} + />, + ]} + open + onRequestClose={onCancel} + maxWidth="sm" + > + Action} + description={ + + An action that can be used on objects with the behavior. You + can define the action parameters: objects, texts, numbers, + layers, etc... + + } onChoose={onChoose} + /> + Condition} description={ - Events that will be run once when the behavior is deactivated - on an object (step events won't be run until the behavior is - activated again). + A condition that can be used on objects with the behavior. You + can define the condition parameters: objects, texts, numbers, + layers, etc... } + onChoose={onChoose} /> + Expression} + description={ + + An expression that can be used on objects with the behavior. + Can either return a number or a string, and take some + parameters. + + } + onChoose={onChoose} + /> + + Lifecycle methods + - Events that will be run once when the behavior is re-activated - on an object (after it was previously deactivated). + Events that will be run once, when an object is created with + this behavior being attached to it. } /> Events that will be run at every frame (roughly 60 times per second), for every object that has the behavior attached, - after the events from the events sheet. + before the events from the events sheet are launched. + + } + /> + + Events that will be run once, after the object is removed from + the scene and before it is entirely removed from memory. } /> - - )} - - - {!showAdvanced ? ( - } - primary={false} - onClick={() => setShowAdvanced(true)} - label={Show other lifecycle functions (advanced)} - /> - ) : ( - } - primary={false} - onClick={() => setShowAdvanced(false)} - label={Hide other lifecycle functions (advanced)} - /> - )} - - + {showAdvanced && ( + <> + + Other lifecycle methods + + + Events that will be run once when the behavior is + deactivated on an object (step events won't be run until + the behavior is activated again). + + } + /> + + Events that will be run once when the behavior is + re-activated on an object (after it was previously + deactivated). + + } + /> + + Events that will be run at every frame (roughly 60 times + per second), for every object that has the behavior + attached, after the events from the events sheet. + + } + /> + + )} + + + {!showAdvanced ? ( + } + primary={false} + onClick={() => setShowAdvanced(true)} + label={Show other lifecycle functions (advanced)} + /> + ) : ( + } + primary={false} + onClick={() => setShowAdvanced(false)} + label={Hide other lifecycle functions (advanced)} + /> + )} + + + )} + ); } diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorEditor.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorEditor.js index 122659c0df32..28bdeaf7b279 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorEditor.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedBehaviorEditor.js @@ -230,6 +230,7 @@ export default function EventsBasedBehaviorEditor({ diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedObjectEditor.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedObjectEditor.js index a769b1080811..86f62ef8b6a9 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedObjectEditor.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedBehaviorOrObjectEditor/EventsBasedObjectEditor.js @@ -241,6 +241,7 @@ export default function EventsBasedObjectEditor({ diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedObjectSelectorDialog.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedObjectSelectorDialog.js index e3d023239a4b..a956945b53ff 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedObjectSelectorDialog.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsBasedObjectSelectorDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import { type EventsBasedObjectCreationParameters } from '../EventsFunctionsList/EventsBasedObjectTreeViewItemContent'; @@ -52,56 +53,61 @@ export default function EventsBasedObjectSelectorDialog({ onCancel, }: Props): React.Node { return ( - Choose a new object type} - actions={[ - Cancel} - keyboardFocused={true} - onClick={onCancel} - key={'close'} - />, - ]} - secondaryActions={[ - , - ]} - open - onRequestClose={onCancel} - maxWidth="sm" - > - - } - name={2D object} - onChoose={() => - onChoose({ - isRenderedIn3D: false, - }) - } - description={ - - An object that can be moved, rotated and scaled in 2D. - - } - /> - } - name={3D object} - onChoose={() => - onChoose({ - isRenderedIn3D: true, - }) - } - description={ - - An object that can be moved, rotated and scaled in 3D. - - } - /> - - + + {({ i18n }) => ( + Choose a new object type} + actions={[ + Cancel} + keyboardFocused={true} + onClick={onCancel} + key={'close'} + />, + ]} + secondaryActions={[ + , + ]} + open + onRequestClose={onCancel} + maxWidth="sm" + > + + } + name={2D object} + onChoose={() => + onChoose({ + isRenderedIn3D: false, + }) + } + description={ + + An object that can be moved, rotated and scaled in 2D. + + } + /> + } + name={3D object} + onChoose={() => + onChoose({ + isRenderedIn3D: true, + }) + } + description={ + + An object that can be moved, rotated and scaled in 3D. + + } + /> + + + )} + ); } diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/ExtensionFunctionSelectorDialog.js b/newIDE/app/src/EventsFunctionsExtensionEditor/ExtensionFunctionSelectorDialog.js index 770bc6fec6ad..dd4d134462cc 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/ExtensionFunctionSelectorDialog.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/ExtensionFunctionSelectorDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import { type EventsFunctionCreationParameters } from '../EventsFunctionsList/EventsFunctionTreeViewItemContent'; @@ -76,184 +77,196 @@ export default function ExtensionFunctionSelectorDialog({ const [showAdvanced, setShowAdvanced] = React.useState(false); return ( - Choose a new extension function} - actions={[ - Cancel} - keyboardFocused={true} - onClick={onCancel} - key={'close'} - />, - ]} - secondaryActions={[ - , - ]} - open - onRequestClose={onCancel} - maxWidth="sm" - > - - Action} - description={ - - An action that can be used in other events sheet. You can define - the action parameters: objects, texts, numbers, layers, etc... - - } - onChoose={onChoose} - /> - Condition} - description={ - - A condition that can be used in other events sheet. You can define - the condition parameters: objects, texts, numbers, layers, etc... - - } - onChoose={onChoose} - /> - Expression} - description={ - - An expression that can be used in formulas. Can either return a - number or a string, and take some parameters. - - } - onChoose={onChoose} - /> - {showAdvanced && ( - - - Lifecycle functions (advanced) - + + {({ i18n }) => ( + Choose a new extension function} + actions={[ + Cancel} + keyboardFocused={true} + onClick={onCancel} + key={'close'} + />, + ]} + secondaryActions={[ + , + ]} + open + onRequestClose={onCancel} + maxWidth="sm" + > + Action} description={ - Events that will be run once when the first scene of the game - is loaded, before any other events. + An action that can be used in other events sheet. You can + define the action parameters: objects, texts, numbers, layers, + etc... } onChoose={onChoose} /> Condition} description={ - Events that will be run once when a scene of the game is - loaded, before the scene events. + A condition that can be used in other events sheet. You can + define the condition parameters: objects, texts, numbers, + layers, etc... } onChoose={onChoose} /> - Events that will be run at every frame (roughly 60 times per - second), before the events from the events sheet of the scene. - - } - onChoose={onChoose} - /> - - Events that will be run at every frame (roughly 60 times per - second), after the events from the events sheet of the scene. - - } - onChoose={onChoose} - /> - - Events that will be run once when a scene is paused (another - scene is run on top of it). - - } - onChoose={onChoose} - /> - - Events that will be run once when a scene is resumed (after it - was previously paused). - - } - onChoose={onChoose} - /> - Expression} description={ - Events that will be run once when a scene is about to be - unloaded from memory. The previous scene that was paused will - be resumed after this. + An expression that can be used in formulas. Can either return + a number or a string, and take some parameters. } onChoose={onChoose} /> - - )} - - - {!showAdvanced ? ( - } - primary={false} - onClick={() => setShowAdvanced(true)} - label={Show lifecycle functions (advanced)} - /> - ) : ( - } - primary={false} - onClick={() => setShowAdvanced(false)} - label={Hide lifecycle functions (advanced)} - /> - )} - - + {showAdvanced && ( + + + Lifecycle functions (advanced) + + + Events that will be run once when the first scene of the + game is loaded, before any other events. + + } + onChoose={onChoose} + /> + + Events that will be run once when a scene of the game is + loaded, before the scene events. + + } + onChoose={onChoose} + /> + + Events that will be run at every frame (roughly 60 times + per second), before the events from the events sheet of + the scene. + + } + onChoose={onChoose} + /> + + Events that will be run at every frame (roughly 60 times + per second), after the events from the events sheet of the + scene. + + } + onChoose={onChoose} + /> + + Events that will be run once when a scene is paused + (another scene is run on top of it). + + } + onChoose={onChoose} + /> + + Events that will be run once when a scene is resumed + (after it was previously paused). + + } + onChoose={onChoose} + /> + + Events that will be run once when a scene is about to be + unloaded from memory. The previous scene that was paused + will be resumed after this. + + } + onChoose={onChoose} + /> + + )} + + + {!showAdvanced ? ( + } + primary={false} + onClick={() => setShowAdvanced(true)} + label={Show lifecycle functions (advanced)} + /> + ) : ( + } + primary={false} + onClick={() => setShowAdvanced(false)} + label={Hide lifecycle functions (advanced)} + /> + )} + +
+ )} + ); } diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/ObjectMethodSelectorDialog.js b/newIDE/app/src/EventsFunctionsExtensionEditor/ObjectMethodSelectorDialog.js index 5eaa33c3d47c..ecfd63b9a268 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/ObjectMethodSelectorDialog.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/ObjectMethodSelectorDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import { type EventsFunctionCreationParameters } from '../EventsFunctionsList/EventsFunctionTreeViewItemContent'; @@ -30,144 +31,152 @@ export default function ObjectMethodSelectorDialog({ const [showAdvanced, setShowAdvanced] = React.useState(false); return ( - Choose a new object function ("method")} - secondaryActions={[ - , - ]} - actions={[ - Cancel} - keyboardFocused={true} - onClick={onCancel} - key={'close'} - />, - ]} - open - onRequestClose={onCancel} - maxWidth="sm" - > - - Action} - description={ - - An action that can be used on the object. You can define the - action parameters: objects, texts, numbers, layers, etc... - - } - onChoose={onChoose} - /> - Condition} - description={ - - A condition that can be used on the object. You can define the - condition parameters: objects, texts, numbers, layers, etc... - - } - onChoose={onChoose} - /> - Expression} - description={ - - An expression that can be used on the object. Can either return a - number or a string, and take some parameters. - - } - onChoose={onChoose} - /> - - Lifecycle methods - - - Events that will be run once, when an object is created. - - } - /> - - Events that will be run at every frame (roughly 60 times per - second), for every object, after the events from the events sheet. - - } - /> - - Events that will be run once, after the object is removed from the - scene and before it is entirely removed from memory. - - } - /> - {showAdvanced && ( - <> + + {({ i18n }) => ( + Choose a new object function ("method")} + secondaryActions={[ + , + ]} + actions={[ + Cancel} + keyboardFocused={true} + onClick={onCancel} + key={'close'} + />, + ]} + open + onRequestClose={onCancel} + maxWidth="sm" + > + + Action} + description={ + + An action that can be used on the object. You can define the + action parameters: objects, texts, numbers, layers, etc... + + } + onChoose={onChoose} + /> + Condition} + description={ + + A condition that can be used on the object. You can define the + condition parameters: objects, texts, numbers, layers, etc... + + } + onChoose={onChoose} + /> + Expression} + description={ + + An expression that can be used on the object. Can either + return a number or a string, and take some parameters. + + } + onChoose={onChoose} + /> - Other lifecycle methods + Lifecycle methods + Events that will be run once, when an object is created. + + } + /> + - Events that will be run when the preview is being - hot-reloaded. + Events that will be run at every frame (roughly 60 times per + second), for every object, after the events from the events + sheet. + + } + /> + + Events that will be run once, after the object is removed from + the scene and before it is entirely removed from memory. } /> - - )} - - - {!showAdvanced ? ( - } - primary={false} - onClick={() => setShowAdvanced(true)} - label={Show other lifecycle functions (advanced)} - /> - ) : ( - } - primary={false} - onClick={() => setShowAdvanced(false)} - label={Hide other lifecycle functions (advanced)} - /> - )} - - + {showAdvanced && ( + <> + + Other lifecycle methods + + + Events that will be run when the preview is being + hot-reloaded. + + } + /> + + )} + + + {!showAdvanced ? ( + } + primary={false} + onClick={() => setShowAdvanced(true)} + label={Show other lifecycle functions (advanced)} + /> + ) : ( + } + primary={false} + onClick={() => setShowAdvanced(false)} + label={Hide other lifecycle functions (advanced)} + /> + )} + + + )} + ); } diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/ExtensionExporterDialog.js b/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/ExtensionExporterDialog.js index 944e077f099c..299bc3812e75 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/ExtensionExporterDialog.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/ExtensionExporterDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import FlatButton from '../../UI/FlatButton'; import Dialog, { DialogPrimaryButton } from '../../UI/Dialog'; @@ -99,61 +100,69 @@ const ExtensionExporterDialog = (props: Props): React.Node => { 'gdevelop-extension-store'; return ( - Export extension} - secondaryActions={[ - , - Submit an update - ) : ( - Submit to the community - ) - } - onClick={() => openGitHubIssue(isFromTheStore)} - />, - ]} - actions={[ - Close} - keyboardFocused={true} - onClick={() => { - props.onClose(); - }} - key="close" - />, - } - primary - label={Export to a file} - onClick={() => { - exportExtension( - props.project, - props.eventsFunctionsExtension, - eventsFunctionsExtensionsState - ); - }} - />, - ]} - open - onRequestClose={props.onClose} - maxWidth="sm" - > - - - - - You can export the extension to a file to easily import it in - another project. If your extension is providing useful and - reusable functions or behaviors, consider sharing it with the - GDevelop community! - - - - - + + {({ i18n }) => ( + Export extension} + secondaryActions={[ + , + Submit an update + ) : ( + Submit to the community + ) + } + onClick={() => openGitHubIssue(isFromTheStore)} + />, + ]} + actions={[ + Close} + keyboardFocused={true} + onClick={() => { + props.onClose(); + }} + key="close" + />, + } + primary + label={Export to a file} + onClick={() => { + exportExtension( + props.project, + props.eventsFunctionsExtension, + eventsFunctionsExtensionsState + ); + }} + />, + ]} + open + onRequestClose={props.onClose} + maxWidth="sm" + > + + + + + You can export the extension to a file to easily import it in + another project. If your extension is providing useful and + reusable functions or behaviors, consider sharing it with the + GDevelop community! + + + + + + )} + ); }; diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/index.js b/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/index.js index 516bfad41dc8..ef6f650cffe5 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/index.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/OptionsEditorDialog/index.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import Dialog from '../../UI/Dialog'; import FlatButton from '../../UI/FlatButton'; @@ -42,78 +43,86 @@ export default function OptionsEditorDialog({ const eventsFunctionsExtensionWriter = eventsFunctionsExtensionsState.getEventsFunctionsExtensionWriter(); return ( - {eventsFunctionsExtension.getName()} options} - secondaryActions={[ - , - eventsFunctionsExtensionWriter ? ( - } - key="export" - label={Export extension} - onClick={() => { - setExportDialogOpen(true); - }} - disabled={isLoading} - /> - ) : null, - ]} - actions={[ - Close} - primary={true} - keyboardFocused={true} - onClick={onClose} - disabled={isLoading} - key={'close'} - />, - ]} - open={open} - fixedContent={ - Options, - }, - { - value: 'dependencies', - label: Dependencies, - }, + + {({ i18n }) => ( + {eventsFunctionsExtension.getName()} options} + secondaryActions={[ + , + eventsFunctionsExtensionWriter ? ( + } + key="export" + label={Export extension} + onClick={() => { + setExportDialogOpen(true); + }} + disabled={isLoading} + /> + ) : null, ]} - /> - } - cannotBeDismissed={isLoading} - onRequestClose={isLoading ? () => {} : onClose} - maxWidth="md" - > - {currentTab === 'options' && ( - - - - )} - {currentTab === 'dependencies' && ( - - - - )} - {exportDialogOpen && ( - setExportDialogOpen(false)} - /> + actions={[ + Close} + primary={true} + keyboardFocused={true} + onClick={onClose} + disabled={isLoading} + key={'close'} + />, + ]} + open={open} + fixedContent={ + Options, + }, + { + value: 'dependencies', + label: Dependencies, + }, + ]} + /> + } + cannotBeDismissed={isLoading} + onRequestClose={isLoading ? () => {} : onClose} + maxWidth="md" + > + {currentTab === 'options' && ( + + + + )} + {currentTab === 'dependencies' && ( + + + + )} + {exportDialogOpen && ( + setExportDialogOpen(false)} + /> + )} + )} - + ); } diff --git a/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js b/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js index 72408352a16d..504a40246590 100644 --- a/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js +++ b/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js @@ -1,6 +1,7 @@ // @flow import { Trans } from '@lingui/macro'; import { t } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import Dialog, { DialogPrimaryButton } from '../../UI/Dialog'; @@ -21,7 +22,7 @@ import { } from '.'; import AlertMessage from '../../UI/AlertMessage'; import DismissableAlertMessage from '../../UI/DismissableAlertMessage'; -import CompactEventsFunctionParametersEditor from '../../EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/CompactEventsFunctionParametersEditor'; +import { CompactEventsFunctionParametersEditor } from '../../EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/CompactEventsFunctionParametersEditor'; import { CompactEventsFunctionPropertiesEditor } from '../../EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/CompactEventsFunctionPropertiesEditor'; import HelpButton from '../../UI/HelpButton'; import { ColumnStackLayout, ResponsiveLineStackLayout } from '../../UI/Layout'; @@ -150,202 +151,210 @@ export default class EventsFunctionExtractorDialog extends React.Component< }; return ( - Extract the events in a function} - secondaryActions={[ - , - ]} - actions={[ - Cancel} - onClick={onClose} - />, - Create} - primary - disabled={ - !canCreateEventsFunction(project, extensionName, eventsFunction) - } - onClick={onApply} - />, - ]} - open - cannotBeDismissed - onRequestClose={onClose} - onApply={onApply} - maxWidth="sm" - > - - - After creating a function, it will be usable in the events sheet. - Functions are grouped by extensions. Choose, or enter the name of a - new extension, and a function name, then configure the function and - its parameters. - - - - Extension (storing the function) - } - value={ - createNewExtension - ? CREATE_NEW_EXTENSION_PLACEHOLDER - : extensionName + + {({ i18n }) => ( + Extract the events in a function} + secondaryActions={[ + , + ]} + actions={[ + Cancel} + onClick={onClose} + />, + Create} + primary + disabled={ + !canCreateEventsFunction( + project, + extensionName, + eventsFunction + ) } - onChange={(e, i, extensionName) => { - if (extensionName === CREATE_NEW_EXTENSION_PLACEHOLDER) { - this.setState({ - createNewExtension: true, - extensionName: '', - }); - } else { - this.setState({ - createNewExtension: false, - extensionName, - }); - } - }} - fullWidth + onClick={onApply} + />, + ]} + open + cannotBeDismissed + onRequestClose={onClose} + onApply={onApply} + maxWidth="sm" + > + + - {eventsFunctionsExtensions.map(eventsFunctionsExtension => ( - + + + Extension (storing the function) + } + value={ + createNewExtension + ? CREATE_NEW_EXTENSION_PLACEHOLDER + : extensionName + } + onChange={(e, i, extensionName) => { + if (extensionName === CREATE_NEW_EXTENSION_PLACEHOLDER) { + this.setState({ + createNewExtension: true, + extensionName: '', + }); + } else { + this.setState({ + createNewExtension: false, + extensionName, + }); + } + }} + fullWidth + > + {eventsFunctionsExtensions.map(eventsFunctionsExtension => ( + + ))} + `} + /> + + {createNewExtension ? ( + New extension name} + onChange={(extensionName: string) => + this.setState({ extensionName }) + } + fullWidth + errorText={ + !validateExtensionNameUniqueness( + project, + extensionName + ) ? ( + + This name is already taken by another extension. + + ) : !validateExtensionName(extensionName) ? ( + + This name is not valid. Only use alphanumeric + characters (0-9, a-z) and underscores. + + ) : ( + undefined + ) + } + /> + ) : null} + + + Function name} + onChange={(functionName: string) => { + eventsFunction.setName(functionName); + this.forceUpdate(); + }} + fullWidth + errorText={ + !validateEventsFunctionNameUniqueness( + project, + extensionName, + eventsFunction + ) ? ( + + This name is already taken by another function. Choose + another name. + + ) : !validateEventsFunctionName( + eventsFunction.getName() + ) ? ( + + This name is not valid. Only use alphanumeric + characters (0-9, a-z) and underscores. + + ) : ( + undefined + ) } /> - ))} - `} - /> - - {createNewExtension ? ( - New extension name} - onChange={(extensionName: string) => - this.setState({ extensionName }) - } - fullWidth - errorText={ - !validateExtensionNameUniqueness(project, extensionName) ? ( - - This name is already taken by another extension. - - ) : !validateExtensionName(extensionName) ? ( + + {hasLotsOfParameters ? ( + + - This name is not valid. Only use alphanumeric characters - (0-9, a-z) and underscores. + This function will have a lot of parameters. Consider + creating groups or functions for a smaller set of + objects so that the function is easier to reuse. - ) : ( - undefined - ) - } - /> - ) : null} - - - Function name} - onChange={(functionName: string) => { - eventsFunction.setName(functionName); + + + ) : null} + + { + // Force re-running logic to see if Create button is disabled. this.forceUpdate(); }} - fullWidth - errorText={ - !validateEventsFunctionNameUniqueness( - project, - extensionName, - eventsFunction - ) ? ( - - This name is already taken by another function. Choose - another name. - - ) : !validateEventsFunctionName(eventsFunction.getName()) ? ( - - This name is not valid. Only use alphanumeric characters - (0-9, a-z) and underscores. - - ) : ( - undefined - ) - } + freezeEventsFunctionType + getFunctionGroupNames={this._getFunctionGroupNames} /> - - {hasLotsOfParameters ? ( - - - - This function will have a lot of parameters. Consider - creating groups or functions for a smaller set of objects so - that the function is easier to reuse. - - - - ) : null} - - { - // Force re-running logic to see if Create button is disabled. - this.forceUpdate(); - }} - freezeEventsFunctionType - getFunctionGroupNames={this._getFunctionGroupNames} - /> - {this._projectScopedContainersAccessor && ( - { - // Force the dialog to adapt its size - this.forceUpdate(); - }} - onFunctionParameterWillBeRenamed={() => { - // Won't happen as the editor is freezed. - }} - onFunctionParameterTypeChanged={() => { - // Won't happen as the editor is freezed. - }} - onWillInstallExtension={() => { - // Won't happen as the editor is freezed. - }} - onExtensionInstalled={() => { - // Won't happen as the editor is freezed. - }} - freezeParameters - /> - )} - - + {this._projectScopedContainersAccessor && ( + { + // Force the dialog to adapt its size + this.forceUpdate(); + }} + onFunctionParameterWillBeRenamed={() => { + // Won't happen as the editor is freezed. + }} + onFunctionParameterTypeChanged={() => { + // Won't happen as the editor is freezed. + }} + freezeParameters + /> + )} + + + )} + ); } } diff --git a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js index 9be1b6dc0752..f956fbc87f71 100644 --- a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js +++ b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionEditorDialog.js @@ -1,5 +1,5 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; import { I18n } from '@lingui/react'; import { type I18n as I18nType } from '@lingui/core'; @@ -16,7 +16,6 @@ import InstructionOrObjectSelector, { } from './InstructionOrObjectSelector'; import InstructionOrExpressionSelector from './InstructionOrExpressionSelector'; import HelpButton from '../../UI/HelpButton'; -import { isRelativePathToDocumentationRoot } from '../../Utils/HelpLink'; import { type EventsScope } from '../../InstructionOrExpression/EventsScope'; import { SelectColumns } from '../../UI/Responsive/SelectColumns'; import { useResponsiveWindowSize } from '../../UI/Responsive/ResponsiveWindowMeasurer'; @@ -164,6 +163,16 @@ const InstructionEditorDialog = ({ const { isMobile, windowSize, isMediumScreen } = useResponsiveWindowSize(); const isLargeScreen = windowSize === 'large' || windowSize === 'xlarge'; const instructionType: string = instruction.getType(); + const instructionMetadata = getInstructionMetadata({ + instructionType, + isCondition, + project, + }); + const rawHelpPath = instructionMetadata + ? instructionMetadata.getHelpPath() + : null; + const validHelpPath = + rawHelpPath && rawHelpPath !== 'MISSING' ? rawHelpPath : null; const [ newBehaviorDialogOpen, setNewBehaviorDialogOpen, @@ -328,15 +337,6 @@ const InstructionEditorDialog = ({ [step, shouldAutofocusInput] ); - const instructionMetadata = getInstructionMetadata({ - instructionType, - isCondition, - project, - }); - const instructionHelpPage = instructionMetadata - ? instructionMetadata.getHelpPath() - : undefined; - const renderInstructionOrObjectSelector = () => ( {({ i18n }) => ( @@ -449,21 +449,16 @@ const InstructionEditorDialog = ({ ) : null, Help - ) : isCondition ? ( - Help for this condition + validHelpPath ? ( + isCondition ? ( + See this condition + ) : ( + See this action + ) ) : ( - Help for this action + Events ) } />, diff --git a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js index 842361ae0c81..7bbc14c8b82b 100644 --- a/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js +++ b/newIDE/app/src/EventsSheet/InstructionEditor/InstructionParametersEditor.js @@ -10,10 +10,7 @@ import EmptyMessage from '../../UI/EmptyMessage'; import ParameterRenderingService from '../ParameterRenderingService'; import HelpButton from '../../UI/HelpButton'; import HelpIcon from '../../UI/HelpIcon'; -import { - isRelativePathToDocumentationRoot, - isDocumentationAbsoluteUrl, -} from '../../Utils/HelpLink'; +import { isDocumentationAbsoluteUrl } from '../../Utils/HelpLink'; import { type ResourceManagementProps } from '../../ResourcesList/ResourceSource'; import { Column, Line, Spacer } from '../../UI/Grid'; import AlertMessage from '../../UI/AlertMessage'; @@ -495,20 +492,12 @@ const InstructionParametersEditor: React.ComponentType<{ )} - {!noHelpButton && - helpPage && - isRelativePathToDocumentationRoot(helpPage) && ( - Help for this condition - ) : ( - Help for this action - ) - } - /> - )} + {!noHelpButton && ( + + )} diff --git a/newIDE/app/src/EventsSheet/ParameterFields/GenericExpressionField/ExpressionParametersEditorDialog.js b/newIDE/app/src/EventsSheet/ParameterFields/GenericExpressionField/ExpressionParametersEditorDialog.js index 6b7ae8551352..bb7c5d3ad916 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/GenericExpressionField/ExpressionParametersEditorDialog.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/GenericExpressionField/ExpressionParametersEditorDialog.js @@ -1,6 +1,8 @@ // @flow import React from 'react'; -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; import { type EventsScope } from '../../../InstructionOrExpression/EventsScope'; import ExpressionParametersEditor from './ExpressionParametersEditor'; import Dialog, { DialogPrimaryButton } from '../../../UI/Dialog'; @@ -52,55 +54,62 @@ const ExpressionParametersEditorDialog = ({ ); return ( - Enter the expression parameters} - id="expression-parameters-editor-dialog" - open - actions={[ - Apply} - primary - onClick={() => onDone(parameterValues)} - />, - ]} - secondaryActions={ - expressionMetadata.getHelpPath() - ? [ - , - ] - : [] - } - onRequestClose={onRequestClose} - onApply={() => onDone(parameterValues)} - > - -
- {expressionMetadata.getDescription()} - { - setParameterValues( - parameterValues.map((oldValue, index) => - index === editedIndex ? value : oldValue - ) - ); - }} - parameterRenderingService={parameterRenderingService} - /> -
-
-
+ + {({ i18n }) => ( + Enter the expression parameters} + id="expression-parameters-editor-dialog" + open + actions={[ + Apply} + primary + onClick={() => onDone(parameterValues)} + />, + ]} + secondaryActions={ + expressionMetadata.getHelpPath() + ? [ + , + ] + : [] + } + onRequestClose={onRequestClose} + onApply={() => onDone(parameterValues)} + > + +
+ {expressionMetadata.getDescription()} + { + setParameterValues( + parameterValues.map((oldValue, index) => + index === editedIndex ? value : oldValue + ) + ); + }} + parameterRenderingService={parameterRenderingService} + /> +
+
+
+ )} +
); }; diff --git a/newIDE/app/src/ExportAndShare/Builds/BuildsDialog.js b/newIDE/app/src/ExportAndShare/Builds/BuildsDialog.js index 65aff241d221..f563f4f18c50 100644 --- a/newIDE/app/src/ExportAndShare/Builds/BuildsDialog.js +++ b/newIDE/app/src/ExportAndShare/Builds/BuildsDialog.js @@ -1,5 +1,7 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; import React from 'react'; import Dialog from '../../UI/Dialog'; @@ -29,30 +31,38 @@ const BuildsDialog = ({ if (!open) return null; return ( - {game.gameName} builds} - actions={[ - Close} - key="close" - primary={false} - onClick={onClose} - />, - ]} - secondaryActions={[ - , - ]} - onRequestClose={onClose} - open={open} - > - - + + {({ i18n }) => ( + {game.gameName} builds} + actions={[ + Close} + key="close" + primary={false} + onClick={onClose} + />, + ]} + secondaryActions={[ + , + ]} + onRequestClose={onClose} + open={open} + > + + + )} + ); }; diff --git a/newIDE/app/src/ExportAndShare/GenericExporters/OnlineCordovaExport.js b/newIDE/app/src/ExportAndShare/GenericExporters/OnlineCordovaExport.js index 824c151fcae6..c25b870d5702 100644 --- a/newIDE/app/src/ExportAndShare/GenericExporters/OnlineCordovaExport.js +++ b/newIDE/app/src/ExportAndShare/GenericExporters/OnlineCordovaExport.js @@ -1,5 +1,7 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; import * as React from 'react'; import Text from '../../UI/Text'; import { Column, Line } from '../../UI/Grid'; @@ -31,135 +33,143 @@ export const SetupExportHeader = ({ if (!!build && build.status === 'complete') return null; return ( - - - - - Packaging your game for Android will create an APK file that can be - installed on Android phones or an Android App Bundle that can be - published to Google Play. - - - - - { - const targetName = event.target.value; - updateExportState(prevExportState => ({ - ...prevExportState, - targets: [targetName], - })); - }} - > - } - label={ + + {({ i18n }) => ( + + + - APK (for testing on device or sharing outside Google Play) + Packaging your game for Android will create an APK file that can + be installed on Android phones or an Android App Bundle that can + be published to Google Play. - } - /> - } - label={ - Android App Bundle (for publishing on Google Play) - } - /> - - - Signing options} - onClick={() => { - updateExportState(prevExportState => ({ - ...prevExportState, - signingDialogOpen: true, - })); - }} - disabled={ - exportState.targets[0] !== 'androidAppBundle' || isExporting - } - /> - - - {exportState.signingDialogOpen && ( - Signing options} - actions={[ - Close} - primary - keyboardFocused - onClick={() => { + + + + { + const targetName = event.target.value; + updateExportState(prevExportState => ({ + ...prevExportState, + targets: [targetName], + })); + }} + > + } + label={ + + APK (for testing on device or sharing outside Google Play) + + } + /> + } + label={ + + Android App Bundle (for publishing on Google Play) + + } + /> + + + Signing options} + onClick={() => { + updateExportState(prevExportState => ({ + ...prevExportState, + signingDialogOpen: true, + })); + }} + disabled={ + exportState.targets[0] !== 'androidAppBundle' || isExporting + } + /> + + + {exportState.signingDialogOpen && ( + Signing options} + actions={[ + Close} + primary + keyboardFocused + onClick={() => { + updateExportState(prevExportState => ({ + ...prevExportState, + signingDialogOpen: false, + })); + }} + />, + ]} + secondaryActions={[ + , + ]} + open + onRequestClose={() => { updateExportState(prevExportState => ({ ...prevExportState, signingDialogOpen: false, })); }} - />, - ]} - secondaryActions={[ - , - ]} - open - onRequestClose={() => { - updateExportState(prevExportState => ({ - ...prevExportState, - signingDialogOpen: false, - })); - }} - maxWidth="sm" - > - - - Choose the upload key to use to identify your Android App Bundle. - In most cases you don't need to change this. Use the "Old upload - key" if you used to publish your game as an APK and you activated - Play App Signing before switching to Android App Bundle. - - - { - const keystore = event.target.value; - updateExportState(prevExportState => ({ - ...prevExportState, - keystore, - })); - }} - > - } - label={Default upload key (recommended)} - /> - } - label={ + maxWidth="sm" + > + - Old, legacy upload key (only if you used to publish your game - as an APK and already activated Play App Signing) + Choose the upload key to use to identify your Android App + Bundle. In most cases you don't need to change this. Use the + "Old upload key" if you used to publish your game as an APK + and you activated Play App Signing before switching to Android + App Bundle. - } - /> - } - label={Custom upload key (not available yet)} - disabled - /> - - + + { + const keystore = event.target.value; + updateExportState(prevExportState => ({ + ...prevExportState, + keystore, + })); + }} + > + } + label={Default upload key (recommended)} + /> + } + label={ + + Old, legacy upload key (only if you used to publish your + game as an APK and already activated Play App Signing) + + } + /> + } + label={Custom upload key (not available yet)} + disabled + /> + + + )} + )} - +
); }; diff --git a/newIDE/app/src/ExportAndShare/ShareDialog/index.js b/newIDE/app/src/ExportAndShare/ShareDialog/index.js index d630c4d29add..9f04fe8753eb 100644 --- a/newIDE/app/src/ExportAndShare/ShareDialog/index.js +++ b/newIDE/app/src/ExportAndShare/ShareDialog/index.js @@ -1,5 +1,7 @@ // @flow import { Trans, t } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; import * as React from 'react'; import Dialog from '../../UI/Dialog'; import HelpButton from '../../UI/HelpButton'; @@ -206,110 +208,121 @@ const ShareDialog = ({ if (!project) return null; - const mainActions = [ - Close} - key="close" - primary={false} - onClick={onClose} - disabled={isNavigationDisabled} - />, - ]; - - const secondaryActions = - currentTab === 'publish' - ? [ - exporter ? ( - - ) : null, - Exports : See all exports - } - onClick={openBuildDialog} - disabled={isNavigationDisabled || !isOnline} - />, - ].filter(Boolean) - : [ - + {({ i18n }) => { + const mainActions = [ + Close} + key="close" + primary={false} + onClick={onClose} + disabled={isNavigationDisabled} />, ]; - return ( - Share} - // $FlowFixMe[incompatible-type] - actions={mainActions} - // $FlowFixMe[incompatible-type] - secondaryActions={secondaryActions} - onRequestClose={onClose} - open - fixedContent={ - Publish, - id: 'publish-tab', - disabled: isNavigationDisabled, - }, - { - value: 'invite', - label: Invite, - id: 'invite-tab', - disabled: isNavigationDisabled, - }, - ]} - /> - } - flexColumnBody - > - {currentTab === 'invite' && ( - - )} - {currentTab === 'publish' && ( - - )} - {gameAndBuildsManager.game && ( - setBuildsDialogOpen(false)} - authenticatedUser={authenticatedUser} - game={gameAndBuildsManager.game} - onGameUpdated={gameAndBuildsManager.setGame} - /> - )} - + const secondaryActions = + currentTab === 'publish' + ? [ + exporter ? ( + + ) : null, + Exports + ) : ( + See all exports + ) + } + onClick={openBuildDialog} + disabled={isNavigationDisabled || !isOnline} + />, + ].filter(Boolean) + : [ + , + ]; + + return ( + Share} + // $FlowFixMe[incompatible-type] + actions={mainActions} + // $FlowFixMe[incompatible-type] + secondaryActions={secondaryActions} + onRequestClose={onClose} + open + fixedContent={ + Publish, + id: 'publish-tab', + disabled: isNavigationDisabled, + }, + { + value: 'invite', + label: Invite, + id: 'invite-tab', + disabled: isNavigationDisabled, + }, + ]} + /> + } + flexColumnBody + > + {currentTab === 'invite' && ( + + )} + {currentTab === 'publish' && ( + + )} + {gameAndBuildsManager.game && ( + setBuildsDialogOpen(false)} + authenticatedUser={authenticatedUser} + game={gameAndBuildsManager.game} + onGameUpdated={gameAndBuildsManager.setGame} + /> + )} + + ); + }} + ); }; diff --git a/newIDE/app/src/ExportAndShare/SigningCredentials/SigningCredentialsDialog/index.js b/newIDE/app/src/ExportAndShare/SigningCredentials/SigningCredentialsDialog/index.js index 0a74c739aa42..be50454fa25f 100644 --- a/newIDE/app/src/ExportAndShare/SigningCredentials/SigningCredentialsDialog/index.js +++ b/newIDE/app/src/ExportAndShare/SigningCredentials/SigningCredentialsDialog/index.js @@ -2,7 +2,9 @@ import * as React from 'react'; import Dialog from '../../../UI/Dialog'; -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; import { type AuthenticatedUser } from '../../../Profile/AuthenticatedUserContext'; import { getUserSigningCredentials, @@ -93,77 +95,89 @@ export const SigningCredentialsDialog = ({ ] = React.useState(null); return ( - Signing Credentials} - actions={[ - Close} - onClick={onClose} - />, - ]} - secondaryActions={[ - , - signingCredentials && signingCredentials.length > 0 ? ( - } - label={Add new} - onClick={() => - setCreateIosSigningCredentialsOpenWithTab(currentTab) - } - /> - ) : null, - ]} - fixedContent={ - Apple Certificates & Profiles, - }, - { - value: 'apple-auth-key', - label: Auth Key (App Store upload), - }, + + {({ i18n }) => ( + Signing Credentials} + actions={[ + Close} + onClick={onClose} + />, ]} - /> - } - onRequestClose={onClose} - > - {currentTab === 'apple-certificate' && ( - setCreateIosSigningCredentialsOpenWithTab(currentTab)} - /> - )} - {currentTab === 'apple-auth-key' && ( - setCreateIosSigningCredentialsOpenWithTab(currentTab)} - /> - )} - {createIosSigningCredentialsOpenWithTab && ( - { - setCreateIosSigningCredentialsOpenWithTab(null); - onRefreshSigningCredentials(); - }} - /> + secondaryActions={[ + , + signingCredentials && signingCredentials.length > 0 ? ( + } + label={Add new} + onClick={() => + setCreateIosSigningCredentialsOpenWithTab(currentTab) + } + /> + ) : null, + ]} + fixedContent={ + Apple Certificates & Profiles, + }, + { + value: 'apple-auth-key', + label: Auth Key (App Store upload), + }, + ]} + /> + } + onRequestClose={onClose} + > + {currentTab === 'apple-certificate' && ( + + setCreateIosSigningCredentialsOpenWithTab(currentTab) + } + /> + )} + {currentTab === 'apple-auth-key' && ( + + setCreateIosSigningCredentialsOpenWithTab(currentTab) + } + /> + )} + {createIosSigningCredentialsOpenWithTab && ( + { + setCreateIosSigningCredentialsOpenWithTab(null); + onRefreshSigningCredentials(); + }} + /> + )} + )} - + ); }; diff --git a/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardAppearanceDialog.js b/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardAppearanceDialog.js index 191361324a70..28f2e06bc767 100644 --- a/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardAppearanceDialog.js +++ b/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardAppearanceDialog.js @@ -258,6 +258,7 @@ function LeaderboardAppearanceDialog({ key="help" helpPagePath="/interface/games-dashboard/leaderboard-administration" anchor="change_the_appearance_of_a_leaderboard" + scopeName={i18n._(t`Leaderboard appearance`)} />, ]} actions={[ diff --git a/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardOptionsDialog.js b/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardOptionsDialog.js index 2271ce0ab331..8bb32a8af28f 100644 --- a/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardOptionsDialog.js +++ b/newIDE/app/src/GameDashboard/LeaderboardAdmin/LeaderboardOptionsDialog.js @@ -138,6 +138,7 @@ function LeaderboardOptionsDialog({ key="help" helpPagePath="/interface/games-dashboard/leaderboard-administration" anchor="change_the_appearance_of_a_leaderboard" + scopeName={i18n._(t`Leaderboard options`)} />, ]} actions={[ diff --git a/newIDE/app/src/HotReload/HotReloadLogsDialog.js b/newIDE/app/src/HotReload/HotReloadLogsDialog.js index 45bca59d2392..e5690c61bc85 100644 --- a/newIDE/app/src/HotReload/HotReloadLogsDialog.js +++ b/newIDE/app/src/HotReload/HotReloadLogsDialog.js @@ -1,5 +1,7 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; import * as React from 'react'; import Dialog, { DialogPrimaryButton } from '../UI/Dialog'; import HelpButton from '../UI/HelpButton'; @@ -31,60 +33,68 @@ export default function HotReloadLogsDialog({ } return ( - The 3D editor or the game crashed - ) : ( - Restarting the preview from scratch is required - ) - } - actions={[ - Close} - key="close" - primary={false} - onClick={onClose} - />, - } - label={ + + {({ i18n }) => ( + Relaunch the 3D editor + The 3D editor or the game crashed ) : ( - Close and launch a new preview + Restarting the preview from scratch is required ) } - key="new-preview" - primary - onClick={onLaunchNewPreview} - />, - ]} - secondaryActions={[ - , - ]} - onRequestClose={onClose} - open - > - - - - {isForEditor ? ( + actions={[ + Close} + key="close" + primary={false} + onClick={onClose} + />, + } + label={ + isForEditor ? ( + Relaunch the 3D editor + ) : ( + Close and launch a new preview + ) + } + key="new-preview" + primary + onClick={onLaunchNewPreview} + />, + ]} + secondaryActions={[ + , + ]} + onRequestClose={onClose} + open + > + + - The 3D editor, or some logic/code inside the game, has - encountered an unhandled exception or error. It's necessary to - restart the 3D editor. + {isForEditor ? ( + + The 3D editor, or some logic/code inside the game, has + encountered an unhandled exception or error. It's necessary + to restart the 3D editor. + + ) : ( + + Your latest changes could not be applied to the preview(s) + being run. You should start a new preview instead to make + sure that all your changes are reflected in the game. + + )} - ) : ( - - Your latest changes could not be applied to the preview(s) being - run. You should start a new preview instead to make sure that - all your changes are reflected in the game. - - )} - - - - + + + + )} + ); } diff --git a/newIDE/app/src/LayersList/LayerEditorDialog.js b/newIDE/app/src/LayersList/LayerEditorDialog.js index 8f109bcca6b1..dd8b90a10150 100644 --- a/newIDE/app/src/LayersList/LayerEditorDialog.js +++ b/newIDE/app/src/LayersList/LayerEditorDialog.js @@ -1,5 +1,7 @@ // @flow import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; import * as React from 'react'; import FlatButton from '../UI/FlatButton'; import Dialog, { DialogPrimaryButton } from '../UI/Dialog'; @@ -204,338 +206,347 @@ const LayerEditorDialog = ({ ); return ( - {layer.getName()} properties - ) : ( - Base layer properties - ) - } - open - secondaryActions={[ - , - , - ]} - actions={[ - Cancel} - onClick={onCancelChanges} - key={'Cancel'} - />, - Apply} - primary - onClick={() => onApply(hasAnyEffectBeenAdded)} - key={'Apply'} - />, - ]} - onRequestClose={onCancelChanges} - onApply={() => onApply(hasAnyEffectBeenAdded)} - fullHeight - flexColumnBody - fixedContent={ - Properties, - }, - { - value: 'effects', - label: Effects, - }, + + {({ i18n }) => ( + {layer.getName()} properties + ) : ( + Base layer properties + ) + } + open + secondaryActions={[ + , + , ]} - /> - } - > - {currentTab === 'properties' && ( - - {layer.isLightingLayer() ? ( - - - The lighting layer renders an ambient light on the scene. All - lights should be placed on this layer so that shadows are - properly rendered. By default, the layer follows the base layer - camera. Uncheck this if you want to manually move the camera - using events. - - - ) : null} - - Camera positioning - - Default camera behavior} - value={layer.getDefaultCameraBehavior()} - onChange={(e, i, value: string) => { - layer.setDefaultCameraBehavior(value); - forceUpdate(); - }} - > - - Cancel} + onClick={onCancelChanges} + key={'Cancel'} + />, + Apply} + primary + onClick={() => onApply(hasAnyEffectBeenAdded)} + key={'Apply'} + />, + ]} + onRequestClose={onCancelChanges} + onApply={() => onApply(hasAnyEffectBeenAdded)} + fullHeight + flexColumnBody + fixedContent={ + Properties, + }, + { + value: 'effects', + label: Effects, + }, + ]} /> - - - Visibility and instances ordering - - - - There are {instancesCount} instances of objects on this layer. - - - {!project.getUseDeprecatedZeroAsDefaultZOrder() && ( - - - - - - Objects created using events on this layer will be given a - "Z order" of {highestZOrder + 1}, so that they appear in - front of all objects of this layer. You can change this - using the action to change an object Z order, after using - an action to create it. - - - - - - )} - Hide the layer} - checked={!layer.getVisibility()} - onCheck={(e, checked) => { - layer.setVisibility(!checked); - forceUpdate(); - notifyOfChange(); - }} - tooltipOrHelperText={ - - This setting changes the visibility of the entire layer. Objects - on the layer will not be treated as "hidden" for event - conditions or actions. - - } - /> - {!layer.isLightingLayer() && ( + } + > + {currentTab === 'properties' && ( + {layer.isLightingLayer() ? ( + + + The lighting layer renders an ambient light on the scene. + All lights should be placed on this layer so that shadows + are properly rendered. By default, the layer follows the + base layer camera. Uncheck this if you want to manually move + the camera using events. + + + ) : null} - 3D settings + Camera positioning Rendering type} - value={layer.getRenderingType()} - onChange={(e, i, newValue: string) => { - layer.setRenderingType(newValue); + floatingLabelText={Default camera behavior} + value={layer.getDefaultCameraBehavior()} + onChange={(e, i, value: string) => { + layer.setDefaultCameraBehavior(value); forceUpdate(); }} > - - - {layer.getRenderingType() !== '2d' && ( + + Visibility and instances ordering + + + + There are {instancesCount} instances of objects on this layer. + + + {!project.getUseDeprecatedZeroAsDefaultZOrder() && ( + + + + + + Objects created using events on this layer will be + given a "Z order" of {highestZOrder + 1}, so that they + appear in front of all objects of this layer. You can + change this using the action to change an object Z + order, after using an action to create it. + + + + + + )} + Hide the layer} + checked={!layer.getVisibility()} + onCheck={(e, checked) => { + layer.setVisibility(!checked); + forceUpdate(); + notifyOfChange(); + }} + tooltipOrHelperText={ + + This setting changes the visibility of the entire layer. + Objects on the layer will not be treated as "hidden" for + event conditions or actions. + + } + /> + {!layer.isLightingLayer() && ( - - Camera type} - value={layer.getCameraType()} - onChange={(e, i, newValue: string) => { - layer.setCameraType(newValue); - checkNearPlaneDistanceError( - layer.getCamera3DNearPlaneDistance() - ); - forceUpdate(); - }} - > - - - - Field of view (in degrees) - } - floatingLabelFixed - disabled={layer.getCameraType() !== 'perspective'} + + 3D settings + + Rendering type} + value={layer.getRenderingType()} + onChange={(e, i, newValue: string) => { + layer.setRenderingType(newValue); + forceUpdate(); + }} + > + - - - Near plane distance} - floatingLabelFixed + - Far plane distance} - floatingLabelFixed + - - + + {layer.getRenderingType() !== '2d' && ( + + + Camera type} + value={layer.getCameraType()} + onChange={(e, i, newValue: string) => { + layer.setCameraType(newValue); + checkNearPlaneDistanceError( + layer.getCamera3DNearPlaneDistance() + ); + forceUpdate(); + }} + > + + + + Field of view (in degrees) + } + floatingLabelFixed + disabled={layer.getCameraType() !== 'perspective'} + /> + + + Near plane distance} + floatingLabelFixed + /> + Far plane distance} + floatingLabelFixed + /> + + Maximum 2D drawing distance + } + floatingLabelFixed + /> + + )} + + )} + {layer.isLightingLayer() ? ( + + + Lighting settings + + Automatically follow the base layer.} + checked={layer.isFollowingBaseLayerCamera()} + onCheck={(e, checked) => { + layer.setFollowBaseLayerCamera(checked); + forceUpdate(); + notifyOfChange(); + }} + /> + Maximum 2D drawing distance - } - floatingLabelFixed + floatingLabelText={Ambient light color} + disableAlpha + color={rgbColorToRGBString({ + r: layer.getAmbientLightColorRed(), + g: layer.getAmbientLightColorGreen(), + b: layer.getAmbientLightColorBlue(), + })} + onChange={newColor => { + const currentRgbColor = { + r: layer.getAmbientLightColorRed(), + g: layer.getAmbientLightColorGreen(), + b: layer.getAmbientLightColorBlue(), + }; + const newRgbColor = rgbStringAndAlphaToRGBColor(newColor); + if ( + newRgbColor && + (newRgbColor.r !== currentRgbColor.r || + newRgbColor.g !== currentRgbColor.g || + newRgbColor.b !== currentRgbColor.b) + ) { + layer.setAmbientLightColor( + newRgbColor.r, + newRgbColor.g, + newRgbColor.b + ); + forceUpdate(); + notifyOfChange(); + } + }} /> - + + ) : ( + // Add some space to avoid a dialog to short that would show scrollbars + + + + )} )} - {layer.isLightingLayer() ? ( - - - Lighting settings - - Automatically follow the base layer.} - checked={layer.isFollowingBaseLayerCamera()} - onCheck={(e, checked) => { - layer.setFollowBaseLayerCamera(checked); - forceUpdate(); - notifyOfChange(); - }} - /> - Ambient light color} - disableAlpha - color={rgbColorToRGBString({ - r: layer.getAmbientLightColorRed(), - g: layer.getAmbientLightColorGreen(), - b: layer.getAmbientLightColorBlue(), - })} - onChange={newColor => { - const currentRgbColor = { - r: layer.getAmbientLightColorRed(), - g: layer.getAmbientLightColorGreen(), - b: layer.getAmbientLightColorBlue(), - }; - const newRgbColor = rgbStringAndAlphaToRGBColor(newColor); - if ( - newRgbColor && - (newRgbColor.r !== currentRgbColor.r || - newRgbColor.g !== currentRgbColor.g || - newRgbColor.b !== currentRgbColor.b) - ) { - layer.setAmbientLightColor( - newRgbColor.r, - newRgbColor.g, - newRgbColor.b - ); - forceUpdate(); - notifyOfChange(); - } - }} - /> - - ) : ( - // Add some space to avoid a dialog to short that would show scrollbars - - - - + {currentTab === 'effects' && ( + { + if (layout) { + gd.WholeProjectRefactorer.renameLayerEffectInScene( + project, + layout, + layer, + oldName, + newName + ); + } else if (eventsFunctionsExtension && eventsBasedObject) { + gd.WholeProjectRefactorer.renameLayerEffectInEventsBasedObject( + project, + eventsFunctionsExtension, + eventsBasedObject, + layer, + oldName, + newName + ); + } + }} + onEffectsUpdated={() => { + forceUpdate(); /*Force update to ensure dialog is properly positioned*/ + notifyOfChange(); + }} + onEffectAdded={() => { + setAnyEffectBeenAdded(true); + }} + /> )} - - )} - {currentTab === 'effects' && ( - { - if (layout) { - gd.WholeProjectRefactorer.renameLayerEffectInScene( - project, - layout, - layer, - oldName, - newName - ); - } else if (eventsFunctionsExtension && eventsBasedObject) { - gd.WholeProjectRefactorer.renameLayerEffectInEventsBasedObject( - project, - eventsFunctionsExtension, - eventsBasedObject, - layer, - oldName, - newName - ); - } - }} - onEffectsUpdated={() => { - forceUpdate(); /*Force update to ensure dialog is properly positioned*/ - notifyOfChange(); - }} - onEffectAdded={() => { - setAnyEffectBeenAdded(true); - }} - /> + )} - + ); }; diff --git a/newIDE/app/src/Leaderboard/LeaderboardDialog.js b/newIDE/app/src/Leaderboard/LeaderboardDialog.js index 24172dbe77f3..eeea514e0695 100644 --- a/newIDE/app/src/Leaderboard/LeaderboardDialog.js +++ b/newIDE/app/src/Leaderboard/LeaderboardDialog.js @@ -5,7 +5,9 @@ import { LeaderboardAdmin } from '../GameDashboard/LeaderboardAdmin'; import Dialog from '../UI/Dialog'; import FlatButton from '../UI/FlatButton'; import HelpButton from '../UI/HelpButton'; -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import { type I18n as I18nType } from '@lingui/core'; type Props = {| onClose: () => void, @@ -22,36 +24,41 @@ const LeaderboardDialog = ({ }: Props): React.Node => { const [isLoading, setIsLoading] = React.useState(false); return ( - Leaderboards} - id="leaderboard-admin-dialog" - actions={[ - Close} - disabled={isLoading} - onClick={onClose} - key={'Close'} - />, - ]} - secondaryActions={[ - , - ]} - open={open} - cannotBeDismissed={isLoading} - onRequestClose={onClose} - flexBody - fullHeight - > - - + + {({ i18n }) => ( + Leaderboards} + id="leaderboard-admin-dialog" + actions={[ + Close} + disabled={isLoading} + onClick={onClose} + key={'Close'} + />, + ]} + secondaryActions={[ + , + ]} + open={open} + cannotBeDismissed={isLoading} + onRequestClose={onClose} + flexBody + fullHeight + > + + + )} + ); }; diff --git a/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js b/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js index 730fa5c21202..4bfcbda2ec3c 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js +++ b/newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import EventsSheet, { type EventsSheetInterface } from '../../EventsSheet'; import RaisedButton from '../../UI/RaisedButton'; @@ -253,81 +254,94 @@ export class ExternalEventsEditorContainer extends React.Component< }; return ( -
- {layout && ( - (this.editor = editor)} - setToolbar={this.props.setToolbar} - onOpenLayout={this.props.onOpenLayout} - resourceManagementProps={this.props.resourceManagementProps} - openInstructionOrExpression={this.props.openInstructionOrExpression} - onCreateEventsFunction={this.onCreateEventsFunction} - onBeginCreateEventsFunction={this.onBeginCreateEventsFunction} - unsavedChanges={this.props.unsavedChanges} - project={project} - // $FlowFixMe[incompatible-type] - scope={scope} - globalObjectsContainer={project.getObjects()} - objectsContainer={layout.getObjects()} - projectScopedContainersAccessor={ - // $FlowFixMe[incompatible-type] - new ProjectScopedContainersAccessor(scope) - } - events={externalEvents.getEvents()} - onOpenSettings={this.openExternalPropertiesDialog} - settingsIcon={editSceneIconReactNode} - onOpenExternalEvents={this.props.onOpenExternalEvents} - isActive={this.props.isActive} - hotReloadPreviewButtonProps={this.props.hotReloadPreviewButtonProps} - onWillInstallExtension={this.props.onWillInstallExtension} - onExtensionInstalled={this.props.onExtensionInstalled} - // Scene events don't have parameters - editEventsFunctionParameter={() => {}} - /> - )} - {!layout && ( - - - + + {({ i18n }) => ( +
+ {layout && ( + (this.editor = editor)} + setToolbar={this.props.setToolbar} + onOpenLayout={this.props.onOpenLayout} + resourceManagementProps={this.props.resourceManagementProps} + openInstructionOrExpression={ + this.props.openInstructionOrExpression + } + onCreateEventsFunction={this.onCreateEventsFunction} + onBeginCreateEventsFunction={this.onBeginCreateEventsFunction} + unsavedChanges={this.props.unsavedChanges} + project={project} + // $FlowFixMe[incompatible-type] + scope={scope} + globalObjectsContainer={project.getObjects()} + objectsContainer={layout.getObjects()} + projectScopedContainersAccessor={ + // $FlowFixMe[incompatible-type] + new ProjectScopedContainersAccessor(scope) + } + events={externalEvents.getEvents()} + onOpenSettings={this.openExternalPropertiesDialog} + settingsIcon={editSceneIconReactNode} + onOpenExternalEvents={this.props.onOpenExternalEvents} + isActive={this.props.isActive} + hotReloadPreviewButtonProps={ + this.props.hotReloadPreviewButtonProps + } + onWillInstallExtension={this.props.onWillInstallExtension} + onExtensionInstalled={this.props.onExtensionInstalled} + // Scene events don't have parameters + editEventsFunctionParameter={() => {}} + /> + )} + {!layout && ( + + + + + To edit the external events, choose the scene in which it + will be included + + + + Choose the scene} + primary + onClick={this.openExternalPropertiesDialog} + /> + + + Watch tutorial} + renderIfNotFound={ + + } + /> + + + + )} + Configure the external events} + helpTexts={[ - To edit the external events, choose the scene in which it will - be included - - - - Choose the scene} - primary - onClick={this.openExternalPropertiesDialog} - /> - - - Watch tutorial} - renderIfNotFound={ - - } - /> - - - + In order to use these external events, you still need to add a + "Link" event in the events sheet of the corresponding scene + , + ]} + open={this.state.externalPropertiesDialogOpen} + project={project} + onChoose={this.saveExternalProperties} + layoutName={this.getAssociatedLayoutName()} + onClose={() => + this.setState({ externalPropertiesDialogOpen: false }) + } + /> +
)} - Configure the external events} - helpTexts={[ - - In order to use these external events, you still need to add a - "Link" event in the events sheet of the corresponding scene - , - ]} - open={this.state.externalPropertiesDialogOpen} - project={project} - onChoose={this.saveExternalProperties} - layoutName={this.getAssociatedLayoutName()} - onClose={() => this.setState({ externalPropertiesDialogOpen: false })} - /> -
+ ); } } diff --git a/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js b/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js index 0a92f2656522..f6f6a80046b1 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js +++ b/newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import RaisedButton from '../../UI/RaisedButton'; @@ -340,126 +341,145 @@ export class ExternalLayoutEditorContainer extends React.Component< ); return ( -
- {layout && ( - (this.editor = editor)} - project={project} - projectScopedContainersAccessor={projectScopedContainersAccessor} - layout={layout} - externalLayout={externalLayout} - eventsFunctionsExtension={null} - eventsBasedObject={null} - eventsBasedObjectVariant={null} - globalObjectsContainer={project.getObjects()} - objectsContainer={layout.getObjects()} - layersContainer={layout.getLayers()} - initialInstances={externalLayout.getInitialInstances()} - getInitialInstancesEditorSettings={() => - prepareInstancesEditorSettings( - serializeToJSObject( - externalLayout.getAssociatedEditorSettings() - ), - Math.max( - project.getGameResolutionWidth(), - project.getGameResolutionHeight() - ) - ) - } - onOpenEvents={this.props.onOpenEvents} - onOpenMoreSettings={this.openExternalPropertiesDialog} - isActive={isActive} - previewDebuggerServer={this.props.previewDebuggerServer} - openBehaviorEvents={this.props.openBehaviorEvents} - onExtractAsExternalLayout={this.props.onExtractAsExternalLayout} - onExtractAsEventBasedObject={this.props.onExtractAsEventBasedObject} - onOpenEventBasedObjectEditor={ - this.props.onOpenEventBasedObjectEditor - } - onOpenEventBasedObjectVariantEditor={ - this.props.onOpenEventBasedObjectVariantEditor - } - onObjectEdited={objectWithContext => - this.props.onSceneObjectEdited(layout, objectWithContext) - } - onObjectsDeleted={() => this.props.onSceneObjectsDeleted(layout)} - // It's only used to refresh events-based object variants. - onObjectGroupEdited={() => {}} - onObjectGroupsDeleted={() => {}} - // Nothing to do as events-based objects can't have external layout. - onEventsBasedObjectChildrenEdited={() => {}} - onWillInstallExtension={this.props.onWillInstallExtension} - onExtensionInstalled={this.props.onExtensionInstalled} - onDeleteEventsBasedObjectVariant={ - this.props.onDeleteEventsBasedObjectVariant - } - onEffectAdded={this.props.onEffectAdded} - onObjectListsModified={this.props.onObjectListsModified} - triggerHotReloadInGameEditorIfNeeded={ - this.props.triggerHotReloadInGameEditorIfNeeded - } - /> - )} - {!layout && ( - - - + + {({ i18n }) => ( +
+ {layout && ( + (this.editor = editor)} + project={project} + projectScopedContainersAccessor={ + projectScopedContainersAccessor + } + layout={layout} + externalLayout={externalLayout} + eventsFunctionsExtension={null} + eventsBasedObject={null} + eventsBasedObjectVariant={null} + globalObjectsContainer={project.getObjects()} + objectsContainer={layout.getObjects()} + layersContainer={layout.getLayers()} + initialInstances={externalLayout.getInitialInstances()} + getInitialInstancesEditorSettings={() => + prepareInstancesEditorSettings( + serializeToJSObject( + externalLayout.getAssociatedEditorSettings() + ), + Math.max( + project.getGameResolutionWidth(), + project.getGameResolutionHeight() + ) + ) + } + onOpenEvents={this.props.onOpenEvents} + onOpenMoreSettings={this.openExternalPropertiesDialog} + isActive={isActive} + previewDebuggerServer={this.props.previewDebuggerServer} + openBehaviorEvents={this.props.openBehaviorEvents} + onExtractAsExternalLayout={this.props.onExtractAsExternalLayout} + onExtractAsEventBasedObject={ + this.props.onExtractAsEventBasedObject + } + onOpenEventBasedObjectEditor={ + this.props.onOpenEventBasedObjectEditor + } + onOpenEventBasedObjectVariantEditor={ + this.props.onOpenEventBasedObjectVariantEditor + } + onObjectEdited={objectWithContext => + this.props.onSceneObjectEdited(layout, objectWithContext) + } + onObjectsDeleted={() => + this.props.onSceneObjectsDeleted(layout) + } + // It's only used to refresh events-based object variants. + onObjectGroupEdited={() => {}} + onObjectGroupsDeleted={() => {}} + // Nothing to do as events-based objects can't have external layout. + onEventsBasedObjectChildrenEdited={() => {}} + onWillInstallExtension={this.props.onWillInstallExtension} + onExtensionInstalled={this.props.onExtensionInstalled} + onDeleteEventsBasedObjectVariant={ + this.props.onDeleteEventsBasedObjectVariant + } + onEffectAdded={this.props.onEffectAdded} + onObjectListsModified={this.props.onObjectListsModified} + triggerHotReloadInGameEditorIfNeeded={ + this.props.triggerHotReloadInGameEditorIfNeeded + } + /> + )} + {!layout && ( + + + + + To edit the external layout, choose the scene in which it + will be included + + + + Choose the scene} + primary + onClick={this.openExternalPropertiesDialog} + /> + + + Watch tutorial} + renderIfNotFound={ + + } + /> + + + + )} + Configure the external layout} + helpTexts={[ + + In order to see your objects in the scene, you need to add an + action "Create objects from external layout" in your events + sheet. + , - To edit the external layout, choose the scene in which it will - be included - - - - Choose the scene} - primary - onClick={this.openExternalPropertiesDialog} - /> - - - Watch tutorial} - renderIfNotFound={ - - } - /> - - - + You can also launch a preview from this external layout, but + remember that it will still create objects from the scene, as + well as trigger its events. Make sure to disable any action + loading the external layout before doing so to avoid having + duplicate objects! + , + ]} + open={this.state.externalPropertiesDialogOpen} + project={project} + layoutName={this.getAssociatedLayoutName()} + onChoose={this.saveExternalProperties} + onClose={() => + this.setState({ externalPropertiesDialogOpen: false }) + } + /> +
)} - Configure the external layout} - helpTexts={[ - - In order to see your objects in the scene, you need to add an - action "Create objects from external layout" in your events sheet. - , - - You can also launch a preview from this external layout, but - remember that it will still create objects from the scene, as well - as trigger its events. Make sure to disable any action loading the - external layout before doing so to avoid having duplicate objects! - , - ]} - open={this.state.externalPropertiesDialogOpen} - project={project} - layoutName={this.getAssociatedLayoutName()} - onChoose={this.saveExternalProperties} - onClose={() => this.setState({ externalPropertiesDialogOpen: false })} - /> -
+ ); } } diff --git a/newIDE/app/src/ObjectEditor/Editors/CustomObjectPropertiesEditor/NewVariantDialog.js b/newIDE/app/src/ObjectEditor/Editors/CustomObjectPropertiesEditor/NewVariantDialog.js index ffa29c4559b8..a8247260edf6 100644 --- a/newIDE/app/src/ObjectEditor/Editors/CustomObjectPropertiesEditor/NewVariantDialog.js +++ b/newIDE/app/src/ObjectEditor/Editors/CustomObjectPropertiesEditor/NewVariantDialog.js @@ -1,5 +1,6 @@ // @flow import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import FlatButton from '../../../UI/FlatButton'; import Dialog, { DialogPrimaryButton } from '../../../UI/Dialog'; @@ -31,55 +32,60 @@ const NewVariantDialog = ({ ); return ( - Create a new variant} - id="create-variant-dialog" - actions={[ - Cancel} - onClick={onCancel} - />, - Create} - primary - onClick={apply} - />, - ]} - secondaryActions={[ - , - ]} - onRequestClose={onCancel} - onApply={apply} - open - maxWidth="sm" - > - - {isDuplicationBeforeEdition && ( - - - This variant can't be modified directly. It must be duplicated - first. - - - )} - Variant name} - floatingLabelFixed - value={variantName} - translatableHintText={t`Variant name`} - onChange={setVariantName} - autoFocus="desktop" - /> - - + + {({ i18n }) => ( + Create a new variant} + id="create-variant-dialog" + actions={[ + Cancel} + onClick={onCancel} + />, + Create} + primary + onClick={apply} + />, + ]} + secondaryActions={[ + , + ]} + onRequestClose={onCancel} + onApply={apply} + open + maxWidth="sm" + > + + {isDuplicationBeforeEdition && ( + + + This variant can't be modified directly. It must be duplicated + first. + + + )} + Variant name} + floatingLabelFixed + value={variantName} + translatableHintText={t`Variant name`} + onChange={setVariantName} + autoFocus="desktop" + /> + + + )} + ); }; diff --git a/newIDE/app/src/ObjectEditor/ObjectEditorDialog.js b/newIDE/app/src/ObjectEditor/ObjectEditorDialog.js index 78c0e707d432..2192bce75e3d 100644 --- a/newIDE/app/src/ObjectEditor/ObjectEditorDialog.js +++ b/newIDE/app/src/ObjectEditor/ObjectEditorDialog.js @@ -1,6 +1,7 @@ // @flow import { Trans } from '@lingui/macro'; import { t } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import FlatButton from '../UI/FlatButton'; import ObjectsEditorService from './ObjectsEditorService'; @@ -177,6 +178,38 @@ const InnerDialog = (props: InnerDialogProps) => { project.getCurrentPlatform(), object.getType() ); + const objectDisplayName = objectMetadata + ? objectMetadata.getFullName() + : null; + + const isSpriteObject = object.getType() === 'Sprite'; + const spriteHasAnimations = + isSpriteObject && + gd.asSpriteConfiguration(object.getConfiguration()).getAnimationsCount() > + 0; + + const contextualHelpPagePath = (() => { + if (currentTab === 'behaviors') return '/behaviors'; + if (currentTab === 'variables') + return '/all-features/variables/object-variables'; + if (currentTab === 'effects') return '/objects/effects'; + if (isSpriteObject) return '/objects/sprite'; + return helpPagePath || '/objects'; + })(); + + const contextualHelpAnchor = (() => { + if (isSpriteObject && spriteHasAnimations) return 'adding-an-animation'; + return undefined; + })(); + + const contextualLabel = (() => { + if (currentTab === 'behaviors') return Behaviors; + if (currentTab === 'variables') return Object Variables; + if (currentTab === 'effects') return Effects; + if (isSpriteObject && spriteHasAnimations) return Animations; + if (objectDisplayName) return {objectDisplayName}; + return undefined; + })(); const EditorComponent: ?React.ComponentType = props.editorComponent; @@ -257,206 +290,223 @@ const InnerDialog = (props: InnerDialogProps) => { ); return ( - Edit {objectName}} - key={object && object.ptr} - actions={[ - Cancel} - onClick={onCancelChanges} - />, - Apply} - id="apply-button" - primary - onClick={onApply} - />, - ]} - secondaryActions={[ - , - , - ]} - onRequestClose={onCancelChanges} - onApply={onApply} - open={props.open} - fullHeight - flexBody - fixedContent={ - Properties, - value: 'properties', - }, - { - label: Behaviors, - value: 'behaviors', - id: 'behaviors-tab', - }, - { - label: Variables, - value: 'variables', - }, - objectMetadata.hasDefaultBehavior( - 'EffectCapability::EffectBehavior' - ) - ? { - label: Effects, - value: 'effects', - } - : null, - ].filter(Boolean)} - /> - } - id="object-editor-dialog" - > - {currentTab === 'properties' && EditorComponent ? ( - + {() => ( + Edit {objectName}} + key={object && object.ptr} + actions={[ + Cancel} + onClick={onCancelChanges} + />, + Apply} + id="apply-button" + primary + onClick={onApply} + />, + ]} + secondaryActions={[ + Objects} + />, + , + ]} + onRequestClose={onCancelChanges} + onApply={onApply} + open={props.open} + fullHeight + flexBody + fixedContent={ + Properties, + value: 'properties', + }, + { + label: Behaviors, + value: 'behaviors', + id: 'behaviors-tab', + }, + { + label: Variables, + value: 'variables', + }, + objectMetadata.hasDefaultBehavior( + 'EffectCapability::EffectBehavior' + ) + ? { + label: Effects, + value: 'effects', + } + : null, + ].filter(Boolean)} + /> } + id="object-editor-dialog" > - ( - Object name} - floatingLabelFixed - value={objectName} - translatableHintText={t`Object Name`} - onChange={newObjectName => { - if (newObjectName === objectName) return; - - setObjectName(getValidatedObjectOrGroupName(newObjectName)); - notifyOfChange(); - }} - autoFocus="desktop" + {currentTab === 'properties' && EditorComponent ? ( + + ( + Object name} + floatingLabelFixed + value={objectName} + translatableHintText={t`Object Name`} + onChange={newObjectName => { + if (newObjectName === objectName) return; + + setObjectName( + getValidatedObjectOrGroupName(newObjectName) + ); + notifyOfChange(); + }} + autoFocus="desktop" + /> + )} + onOpenEventBasedObjectEditor={onOpenEventBasedObjectEditor} + onOpenEventBasedObjectVariantEditor={ + onOpenEventBasedObjectVariantEditor + } + onDeleteEventsBasedObjectVariant={ + onDeleteEventsBasedObjectVariant + } /> - )} - onOpenEventBasedObjectEditor={onOpenEventBasedObjectEditor} - onOpenEventBasedObjectVariantEditor={ - onOpenEventBasedObjectVariantEditor - } - onDeleteEventsBasedObjectVariant={onDeleteEventsBasedObjectVariant} - /> - - ) : null} - {currentTab === 'behaviors' && ( - - )} - {currentTab === 'variables' && ( - - {object.getVariables().count() > 0 && DismissableTutorialMessage && ( - - - {DismissableTutorialMessage} - - + + ) : null} + {currentTab === 'behaviors' && ( + )} - Add your first object variable - } - emptyPlaceholderDescription={ - - These variables hold additional information on an object. - - } - helpPagePath={'/all-features/variables/object-variables'} - onComputeAllVariableNames={onComputeAllVariableNames} - onVariablesUpdated={notifyOfChange} - isListLocked={isVariableListLocked} - /> - - )} - {currentTab === 'effects' && ( - { - if (layout) { - gd.WholeProjectRefactorer.renameObjectEffectInScene( - project, - layout, - object, - oldName, - newName - ); - } else if (eventsFunctionsExtension && eventsBasedObject) { - gd.WholeProjectRefactorer.renameObjectEffectInEventsBasedObject( - project, - eventsFunctionsExtension, - eventsBasedObject, - object, - oldName, - newName - ); - } - }} - onEffectsUpdated={() => { - forceUpdate(); /*Force update to ensure dialog is properly positioned*/ - notifyOfChange(); - }} - onEffectAdded={() => { - setAnyEffectBeenAdded(true); - }} - /> + {currentTab === 'variables' && ( + + {object.getVariables().count() > 0 && DismissableTutorialMessage && ( + + + {DismissableTutorialMessage} + + + )} + Add your first object variable + } + emptyPlaceholderDescription={ + + These variables hold additional information on an object. + + } + helpPagePath={'/all-features/variables/object-variables'} + onComputeAllVariableNames={onComputeAllVariableNames} + onVariablesUpdated={notifyOfChange} + isListLocked={isVariableListLocked} + /> + + )} + {currentTab === 'effects' && ( + { + if (layout) { + gd.WholeProjectRefactorer.renameObjectEffectInScene( + project, + layout, + object, + oldName, + newName + ); + } else if (eventsFunctionsExtension && eventsBasedObject) { + gd.WholeProjectRefactorer.renameObjectEffectInEventsBasedObject( + project, + eventsFunctionsExtension, + eventsBasedObject, + object, + oldName, + newName + ); + } + }} + onEffectsUpdated={() => { + forceUpdate(); /*Force update to ensure dialog is properly positioned*/ + notifyOfChange(); + }} + onEffectAdded={() => { + setAnyEffectBeenAdded(true); + }} + /> + )} + )} - + ); }; diff --git a/newIDE/app/src/ObjectGroupEditor/EditedObjectGroupEditorDialog.js b/newIDE/app/src/ObjectGroupEditor/EditedObjectGroupEditorDialog.js index 4415fed3390a..0d5caec7b817 100644 --- a/newIDE/app/src/ObjectGroupEditor/EditedObjectGroupEditorDialog.js +++ b/newIDE/app/src/ObjectGroupEditor/EditedObjectGroupEditorDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import FlatButton from '../UI/FlatButton'; import ObjectGroupEditor from '.'; @@ -142,100 +143,122 @@ const EditedObjectGroupEditorDialog = ({ ); return ( - Edit {group.getName()}} - key={group.ptr} - actions={[ - Cancel} - keyboardFocused - onClick={onCancelChanges} - />, - Apply} - primary - onClick={apply} - />, - ]} - secondaryActions={[ - , - ]} - onRequestClose={onCancelChanges} - onApply={apply} - open - fullHeight - flexBody - fixedContent={ - Objects, - value: 'objects', - }, - { - label: Variables, - value: 'variables', - }, + + {({ i18n }) => ( + Edit {group.getName()}} + key={group.ptr} + actions={[ + Cancel} + keyboardFocused + onClick={onCancelChanges} + />, + Apply} + primary + onClick={apply} + />, ]} - /> - } - > - {currentTab === 'objects' && - (isObjectListLocked && group.getAllObjectsNames().size() === 0 ? ( - - - {Empty group} - - - {This object group is empty and locked.} - - - ) : ( - - ))} - {currentTab === 'variables' && ( - - {groupVariablesContainer.count() > 0 && DismissableTutorialMessage && ( - - - {DismissableTutorialMessage} + secondaryActions={[ + , + ]} + onRequestClose={onCancelChanges} + onApply={apply} + open + fullHeight + flexBody + fixedContent={ + Objects, + value: 'objects', + }, + { + label: Variables, + value: 'variables', + }, + ]} + /> + } + > + {currentTab === 'objects' && + (isObjectListLocked && group.getAllObjectsNames().size() === 0 ? ( + + + {Empty group} + + + {This object group is empty and locked.} + - + ) : ( + + ))} + {currentTab === 'variables' && ( + + {groupVariablesContainer.count() > 0 && + DismissableTutorialMessage && ( + + + {DismissableTutorialMessage} + + + )} + Add your first object group variable + } + emptyPlaceholderDescription={ + + These variables hold additional information and are + available on all objects of the group. + + } + helpPagePath={'/all-features/variables/object-variables'} + onComputeAllVariableNames={onComputeAllVariableNames} + onVariablesUpdated={notifyOfVariableChange} + isListLocked={isVariableListLocked} + /> + )} - Add your first object group variable - } - emptyPlaceholderDescription={ - - These variables hold additional information and are available on - all objects of the group. - - } - helpPagePath={'/all-features/variables/object-variables'} - onComputeAllVariableNames={onComputeAllVariableNames} - onVariablesUpdated={notifyOfVariableChange} - isListLocked={isVariableListLocked} - /> - + )} - + ); }; diff --git a/newIDE/app/src/ObjectGroupEditor/NewObjectGroupEditorDialog.js b/newIDE/app/src/ObjectGroupEditor/NewObjectGroupEditorDialog.js index a0c731c0435a..cb24aad1c615 100644 --- a/newIDE/app/src/ObjectGroupEditor/NewObjectGroupEditorDialog.js +++ b/newIDE/app/src/ObjectGroupEditor/NewObjectGroupEditorDialog.js @@ -1,5 +1,6 @@ // @flow import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import FlatButton from '../UI/FlatButton'; import ObjectGroupEditor from '.'; @@ -80,63 +81,71 @@ const NewObjectGroupEditorDialog = ({ ); return ( - Create a new group} - id="create-group-dialog" - actions={[ - Cancel} - onClick={onCancel} - />, - Create} - primary - onClick={apply} - />, - ]} - secondaryActions={[ - , - ]} - onRequestClose={onCancel} - onApply={apply} - open - maxWidth="sm" - fixedContent={ - - {!isGroupAlreadyAdded && ( - Group name} - floatingLabelFixed - value={objectGroupName} - translatableHintText={t`Group name`} - onChange={setObjectGroupName} - autoFocus="desktop" - /> - )} - Add any object variable to the group} - checked={shouldSpreadAnyVariables} - onCheck={(e, checked) => setShouldSpreadAnyVariables(checked)} + + {({ i18n }) => ( + Create a new group} + id="create-group-dialog" + actions={[ + Cancel} + onClick={onCancel} + />, + Create} + primary + onClick={apply} + />, + ]} + secondaryActions={[ + , + ]} + onRequestClose={onCancel} + onApply={apply} + open + maxWidth="sm" + fixedContent={ + + {!isGroupAlreadyAdded && ( + Group name} + floatingLabelFixed + value={objectGroupName} + translatableHintText={t`Group name`} + onChange={setObjectGroupName} + autoFocus="desktop" + /> + )} + Add any object variable to the group} + checked={shouldSpreadAnyVariables} + onCheck={(e, checked) => setShouldSpreadAnyVariables(checked)} + /> + + } + > + - - } - > - - + + )} + ); }; diff --git a/newIDE/app/src/Profile/CreateAccountDialog.js b/newIDE/app/src/Profile/CreateAccountDialog.js index f4907c3ba861..1bf21f76ff4c 100644 --- a/newIDE/app/src/Profile/CreateAccountDialog.js +++ b/newIDE/app/src/Profile/CreateAccountDialog.js @@ -1,6 +1,7 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import FlatButton from '../UI/FlatButton'; import Dialog, { DialogPrimaryButton } from '../UI/Dialog'; @@ -152,78 +153,89 @@ const CreateAccountDialog = ({ }; return ( - Cancel} - key="close" - primary={false} - onClick={onClose} - />, - - Create account} - id="create-account-button" - primary - disabled={!canCreateAccount} - onClick={createAccount} - /> - , - ]} - secondaryActions={[ - , - ]} - cannotBeDismissed={createAccountInProgress} - onApply={createAccount} - onRequestClose={() => { - if (!createAccountInProgress) onClose(); - }} - maxWidth="md" - open - flexColumnBody - > - - { + + {({ i18n }) => ( + Cancel} + key="close" + primary={false} + onClick={onClose} + />, + + Create account} + id="create-account-button" + primary + disabled={!canCreateAccount} + onClick={createAccount} + /> + , + ]} + secondaryActions={[ + , + ]} + cannotBeDismissed={createAccountInProgress} + onApply={createAccount} + onRequestClose={() => { + if (!createAccountInProgress) onClose(); + }} + maxWidth="md" + open + flexColumnBody + > - - - Welcome to GDevelop! - + { + + + + Welcome to GDevelop! + + + } +
+ +
- } -
- -
-
-
+ + )} + ); }; diff --git a/newIDE/app/src/Profile/CreateAccountWithPurchaseClaimDialog.js b/newIDE/app/src/Profile/CreateAccountWithPurchaseClaimDialog.js index 5ea224b64d34..8e98485ff5ac 100644 --- a/newIDE/app/src/Profile/CreateAccountWithPurchaseClaimDialog.js +++ b/newIDE/app/src/Profile/CreateAccountWithPurchaseClaimDialog.js @@ -1,6 +1,7 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import FlatButton from '../UI/FlatButton'; import Dialog, { DialogPrimaryButton } from '../UI/Dialog'; @@ -105,81 +106,96 @@ const CreateAccountWithPurchaseClaimDialog = ({ }; return ( - Cancel} - key="close" - primary={false} - onClick={onClose} - />, - - Create account} - id="create-account-button" - primary - disabled={!canCreateAccount} - onClick={createAccount} - /> - , - ]} - secondaryActions={[ - , - ]} - cannotBeDismissed={createAccountInProgress} - onApply={createAccount} - onRequestClose={() => { - if (!createAccountInProgress) onClose(); - }} - maxWidth="md" - open - flexColumnBody - > - - - {claimedProduct.productType === 'BUNDLE' && ( - - )} - - Create an account to activate your purchase! - - -
- -
-
-
+ + {({ i18n }) => ( + Cancel} + key="close" + primary={false} + onClick={onClose} + />, + + Create account} + id="create-account-button" + primary + disabled={!canCreateAccount} + onClick={createAccount} + /> + , + ]} + secondaryActions={[ + , + ]} + cannotBeDismissed={createAccountInProgress} + onApply={createAccount} + onRequestClose={() => { + if (!createAccountInProgress) onClose(); + }} + maxWidth="md" + open + flexColumnBody + > + + + {claimedProduct.productType === 'BUNDLE' && ( + + )} + + Create an account to activate your purchase! + + +
+ +
+
+
+ )} +
); }; diff --git a/newIDE/app/src/Profile/LoginDialog.js b/newIDE/app/src/Profile/LoginDialog.js index 018599c2e4f9..a93ac8ccf656 100644 --- a/newIDE/app/src/Profile/LoginDialog.js +++ b/newIDE/app/src/Profile/LoginDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import Dialog, { DialogPrimaryButton } from '../UI/Dialog'; @@ -81,8 +82,12 @@ const LoginDialog = ({ , ]; - const secondaryActions = [ - , + const secondaryActions = (i18n: any) => [ + , ]; const dialogContent = ( @@ -118,22 +123,26 @@ const LoginDialog = ({ ); return ( - - {dialogContent} - + + {({ i18n }) => ( + + {dialogContent} + + )} + ); }; diff --git a/newIDE/app/src/Profile/LoginWithPurchaseClaimDialog.js b/newIDE/app/src/Profile/LoginWithPurchaseClaimDialog.js index fd9c79ed5116..fcd9a8ba795e 100644 --- a/newIDE/app/src/Profile/LoginWithPurchaseClaimDialog.js +++ b/newIDE/app/src/Profile/LoginWithPurchaseClaimDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import Dialog, { DialogPrimaryButton } from '../UI/Dialog'; @@ -100,8 +101,12 @@ const LoginWithPurchaseClaimDialog = ({ , ]; - const secondaryActions = [ - , + const secondaryActions = (i18n: any) => [ + , ]; const dialogContent = ( @@ -144,22 +149,26 @@ const LoginWithPurchaseClaimDialog = ({ ); return ( - - {dialogContent} - + + {({ i18n }) => ( + + {dialogContent} + + )} + ); }; diff --git a/newIDE/app/src/Profile/ProfileDialog.js b/newIDE/app/src/Profile/ProfileDialog.js index 212746b0f430..425550120afc 100644 --- a/newIDE/app/src/Profile/ProfileDialog.js +++ b/newIDE/app/src/Profile/ProfileDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import React from 'react'; import FlatButton from '../UI/FlatButton'; @@ -140,128 +141,136 @@ const ProfileDialog = ({ onClose }: Props) => { !!authenticatedUser.subscription.isTeacher; return ( - My profile : null} - actions={[ - Close} - key="close" - primary={false} - onClick={onClose} - />, - ]} - secondaryActions={[ - , - isConnected && ( - Logout} - key="logout" - onClick={onLogout} - disabled={isUserLoading} - /> - ), - } - label={ - isMobile ? Redeem : Redeem a code - } - key="redeem-code" - disabled={isUserLoading} - primary={false} - onClick={() => { - if (authenticatedUser.authenticated) { - openRedeemCodeDialog(); - } else { - authenticatedUser.onOpenCreateAccountDialog(); - } - }} - />, - ]} - onRequestClose={onClose} - open - fullHeight={!!isConnected} - maxWidth={isConnected ? 'md' : 'sm'} - flexColumnBody - > - {!isConnected && authenticatedUser.loginState === 'loggingIn' ? ( - - ) : authenticatedUser.authenticated && authenticatedUser.profile ? ( - - - - {isStudentAccount ? null : ( - + {({ i18n }) => ( + My profile : null} + actions={[ + Close} + key="close" + primary={false} + onClick={onClose} + />, + ]} + secondaryActions={[ + , + isConnected && ( + Logout} + key="logout" + onClick={onLogout} + disabled={isUserLoading} /> - )} - {!isStudentAccount && !isTeacherAccount && ( - - + ), + } + label={ + isMobile ? Redeem : Redeem a code + } + key="redeem-code" + disabled={isUserLoading} + primary={false} + onClick={() => { + if (authenticatedUser.authenticated) { + openRedeemCodeDialog(); + } else { + authenticatedUser.onOpenCreateAccountDialog(); + } + }} + />, + ]} + onRequestClose={onClose} + open + fullHeight={!!isConnected} + maxWidth={isConnected ? 'md' : 'sm'} + flexColumnBody + > + {!isConnected && authenticatedUser.loginState === 'loggingIn' ? ( + + ) : authenticatedUser.authenticated && authenticatedUser.profile ? ( + + + + {isStudentAccount ? null : ( + + )} + {!isStudentAccount && !isTeacherAccount && ( - - GDevelop credits - - - - Get perks and cloud benefits when getting closer to your - game launch.{' '} - - Window.openExternalURL( - 'https://wiki.gdevelop.io/gdevelop5/interface/profile/credits' - ) - } - > - Learn more - - - + + + + GDevelop credits + + + + Get perks and cloud benefits when getting closer to + your game launch.{' '} + + Window.openExternalURL( + 'https://wiki.gdevelop.io/gdevelop5/interface/profile/credits' + ) + } + > + Learn more + + + + + + - - + )} + {!isStudentAccount && ( + + )} + {isConnected && ( +
+ +
+ )}
- )} - {!isStudentAccount && ( - - )} - {isConnected && ( -
- -
- )} -
-
- ) : ( - - - Create an account to register your games and to get access to - metrics collected anonymously, like the number of daily players - and retention of the players after a few days. - - } - /> - + + ) : ( + + + Create an account to register your games and to get access + to metrics collected anonymously, like the number of daily + players and retention of the players after a few days. + + } + /> + + )} +
)} - + ); }; diff --git a/newIDE/app/src/ProjectManager/ProjectPropertiesDialog.js b/newIDE/app/src/ProjectManager/ProjectPropertiesDialog.js index 5b29ba28ec08..afaefc3b4833 100644 --- a/newIDE/app/src/ProjectManager/ProjectPropertiesDialog.js +++ b/newIDE/app/src/ProjectManager/ProjectPropertiesDialog.js @@ -416,6 +416,7 @@ const ProjectPropertiesDialog = (props: Props) => { , hotReloadPreviewButtonProps ? ( , ]} onRequestClose={onCancel} diff --git a/newIDE/app/src/SceneEditor/ExtractAsExternalLayoutDialog.js b/newIDE/app/src/SceneEditor/ExtractAsExternalLayoutDialog.js index 1e896ddfe075..e95e39709fe3 100644 --- a/newIDE/app/src/SceneEditor/ExtractAsExternalLayoutDialog.js +++ b/newIDE/app/src/SceneEditor/ExtractAsExternalLayoutDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import FlatButton from '../UI/FlatButton'; import Text from '../UI/Text'; @@ -27,46 +28,51 @@ export default function ExtractAsExternalLayoutDialog({ ]); return ( - Extract as an external layout} - actions={[ - Cancel} - primary={false} - onClick={onCancel} - />, - Move instances} - primary={true} - onClick={apply} - />, - ]} - secondaryActions={[ - , - ]} - onRequestClose={onCancel} - onApply={apply} - open - maxWidth="sm" - > - - - - Selected instances will be moved to a new external layout. - - - External layout name} - fullWidth - value={chosenName} - onChange={(e, value) => setChosenName(value)} - /> - - + + {({ i18n }) => ( + Extract as an external layout} + actions={[ + Cancel} + primary={false} + onClick={onCancel} + />, + Move instances} + primary={true} + onClick={apply} + />, + ]} + secondaryActions={[ + , + ]} + onRequestClose={onCancel} + onApply={apply} + open + maxWidth="sm" + > + + + + Selected instances will be moved to a new external layout. + + + External layout name} + fullWidth + value={chosenName} + onChange={(e, value) => setChosenName(value)} + /> + + + )} + ); } diff --git a/newIDE/app/src/UI/HelpButton/index.js b/newIDE/app/src/UI/HelpButton/index.js index e65133000dc7..50c78b4dad59 100644 --- a/newIDE/app/src/UI/HelpButton/index.js +++ b/newIDE/app/src/UI/HelpButton/index.js @@ -12,6 +12,7 @@ type PropsType = { helpPagePath: ?string, label?: React.Node, anchor?: string, + scopeName?: string, }; /** @@ -33,7 +34,14 @@ const HelpButton = (props: PropsType): null | React.Node => { Help} + label={ + props.label || + (props.scopeName ? ( + About {props.scopeName} + ) : ( + Help + )) + } icon={} /> ) : ( diff --git a/newIDE/app/src/VariablesList/GlobalAndSceneVariablesDialog.js b/newIDE/app/src/VariablesList/GlobalAndSceneVariablesDialog.js index 80187637057d..64102156e7fa 100644 --- a/newIDE/app/src/VariablesList/GlobalAndSceneVariablesDialog.js +++ b/newIDE/app/src/VariablesList/GlobalAndSceneVariablesDialog.js @@ -1,9 +1,8 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; -import VariablesEditorDialog, { - type VariableDialogOpeningProps, -} from './VariablesEditorDialog'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import VariablesEditorDialog from './VariablesEditorDialog'; import { type HotReloadPreviewButtonProps } from '../HotReload/HotReloadPreviewButton'; import EventsRootVariablesFinder from '../Utils/EventsRootVariablesFinder'; import { ProjectScopedContainersAccessor } from '../InstructionOrExpression/EventsScope'; @@ -15,7 +14,8 @@ type Props = {| onCancel: () => void, hotReloadPreviewButtonProps: HotReloadPreviewButtonProps | null, isGlobalTabInitiallyOpen?: boolean, - initiallySelectedVariable: VariableDialogOpeningProps | null, + initiallySelectedVariableName?: string, + shouldCreateInitiallySelectedVariable?: boolean, isListLocked: boolean, |}; @@ -26,7 +26,8 @@ const GlobalAndSceneVariablesDialog = ({ onApply, hotReloadPreviewButtonProps, isGlobalTabInitiallyOpen, - initiallySelectedVariable, + initiallySelectedVariableName, + shouldCreateInitiallySelectedVariable, isListLocked, }: Props): React.Node => { const { @@ -105,30 +106,38 @@ const GlobalAndSceneVariablesDialog = ({ ); return ( - {layout.getName()} variables - ) : ( - Extension variables - ) - } - // $FlowFixMe[incompatible-type] - tabs={tabs} - initiallyOpenTabId={ - isGlobalTabInitiallyOpen ? 'global-variables' : 'scene-variables' - } - initiallySelectedVariable={initiallySelectedVariable} - helpPagePath={'/all-features/variables/scene-variables'} - hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} - id="global-and-scene-variables-dialog" - isListLocked={isListLocked} - /> + + {({ i18n }) => ( + {layout.getName()} variables + ) : ( + Extension variables + ) + } + // $FlowFixMe[incompatible-type] + tabs={tabs} + initiallyOpenTabId={ + isGlobalTabInitiallyOpen ? 'global-variables' : 'scene-variables' + } + initiallySelectedVariableName={initiallySelectedVariableName} + shouldCreateInitiallySelectedVariable={ + shouldCreateInitiallySelectedVariable + } + helpPagePath={'/all-features/variables/scene-variables'} + scopeName={i18n._(t`Variables`)} + hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} + id="global-and-scene-variables-dialog" + isListLocked={isListLocked} + /> + )} + ); }; diff --git a/newIDE/app/src/VariablesList/GlobalVariablesDialog.js b/newIDE/app/src/VariablesList/GlobalVariablesDialog.js index 147475916166..77b3db62b222 100644 --- a/newIDE/app/src/VariablesList/GlobalVariablesDialog.js +++ b/newIDE/app/src/VariablesList/GlobalVariablesDialog.js @@ -1,9 +1,8 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; -import VariablesEditorDialog, { - type VariableDialogOpeningProps, -} from './VariablesEditorDialog'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import VariablesEditorDialog from './VariablesEditorDialog'; import { type HotReloadPreviewButtonProps } from '../HotReload/HotReloadPreviewButton'; import EventsRootVariablesFinder from '../Utils/EventsRootVariablesFinder'; import { ProjectScopedContainersAccessor } from '../InstructionOrExpression/EventsScope'; @@ -14,7 +13,8 @@ type Props = {| onApply: (selectedVariableName: string | null) => void, onCancel: () => void, hotReloadPreviewButtonProps: HotReloadPreviewButtonProps | null, - initiallySelectedVariable: VariableDialogOpeningProps | null, + initiallySelectedVariableName?: string, + shouldCreateInitiallySelectedVariable?: boolean, isListLocked: boolean, |}; @@ -24,7 +24,8 @@ const GlobalVariablesDialog = ({ onCancel, onApply, hotReloadPreviewButtonProps, - initiallySelectedVariable, + initiallySelectedVariableName, + shouldCreateInitiallySelectedVariable, isListLocked, }: Props): React.Node => { const onComputeAllVariableNames = React.useCallback( @@ -63,21 +64,29 @@ const GlobalVariablesDialog = ({ ); return ( - Global variables} - // $FlowFixMe[incompatible-type] - tabs={tabs} - initiallySelectedVariable={initiallySelectedVariable} - helpPagePath={'/all-features/variables/global-variables'} - hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} - id="global-variables-dialog" - isListLocked={isListLocked} - /> + + {({ i18n }) => ( + Global variables} + // $FlowFixMe[incompatible-type] + tabs={tabs} + initiallySelectedVariableName={initiallySelectedVariableName} + shouldCreateInitiallySelectedVariable={ + shouldCreateInitiallySelectedVariable + } + helpPagePath={'/all-features/variables/global-variables'} + scopeName={i18n._(t`Global variables`)} + hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} + id="global-variables-dialog" + isListLocked={isListLocked} + /> + )} + ); }; diff --git a/newIDE/app/src/VariablesList/LocalVariablesDialog.js b/newIDE/app/src/VariablesList/LocalVariablesDialog.js index ee30b9bbec92..0e7070232d24 100644 --- a/newIDE/app/src/VariablesList/LocalVariablesDialog.js +++ b/newIDE/app/src/VariablesList/LocalVariablesDialog.js @@ -1,9 +1,8 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; -import VariablesEditorDialog, { - type VariableDialogOpeningProps, -} from './VariablesEditorDialog'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import VariablesEditorDialog from './VariablesEditorDialog'; import { ProjectScopedContainersAccessor } from '../InstructionOrExpression/EventsScope'; type Props = {| @@ -16,7 +15,8 @@ type Props = {| onRemoveLoopIndexVariable?: () => void, onApply: (selectedVariableName: string | null) => void, onCancel: () => void, - initiallySelectedVariable: VariableDialogOpeningProps | null, + initiallySelectedVariableName: string, + shouldCreateInitiallySelectedVariable?: boolean, isListLocked: boolean, |}; @@ -30,7 +30,8 @@ const LocalVariablesDialog = ({ open, onCancel, onApply, - initiallySelectedVariable, + initiallySelectedVariableName, + shouldCreateInitiallySelectedVariable, isListLocked, }: Props): React.Node => { const tabs = React.useMemo( @@ -55,21 +56,29 @@ const LocalVariablesDialog = ({ ); return ( - Local variables} - // $FlowFixMe[incompatible-type] - tabs={tabs} - helpPagePath={'/all-features/variables/local-variables'} - id="local-variables-dialog" - initiallySelectedVariable={initiallySelectedVariable} - hotReloadPreviewButtonProps={null} - isListLocked={isListLocked} - /> + + {({ i18n }) => ( + Local variables} + // $FlowFixMe[incompatible-type] + tabs={tabs} + helpPagePath={'/all-features/variables/local-variables'} + scopeName={i18n._(t`Local variables`)} + id="local-variables-dialog" + initiallySelectedVariableName={initiallySelectedVariableName} + shouldCreateInitiallySelectedVariable={ + shouldCreateInitiallySelectedVariable + } + hotReloadPreviewButtonProps={null} + isListLocked={isListLocked} + /> + )} + ); }; diff --git a/newIDE/app/src/VariablesList/ObjectGroupVariablesDialog.js b/newIDE/app/src/VariablesList/ObjectGroupVariablesDialog.js index 3212decea102..11ff540fb0bf 100644 --- a/newIDE/app/src/VariablesList/ObjectGroupVariablesDialog.js +++ b/newIDE/app/src/VariablesList/ObjectGroupVariablesDialog.js @@ -1,5 +1,6 @@ // @flow -import { Trans } from '@lingui/macro'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; import * as React from 'react'; import FlatButton from '../UI/FlatButton'; import Dialog, { DialogPrimaryButton } from '../UI/Dialog'; @@ -149,71 +150,76 @@ const ObjectGroupVariablesDialog = ({ ); return ( - {objectGroup.getName()} variables} - actions={[ - Cancel} - onClick={onCancel} - key="Cancel" - />, - Apply} - primary - onClick={apply} - key="Apply" - id="apply-button" - />, - ]} - secondaryActions={[ - hotReloadPreviewButtonProps ? ( - - ) : null, - , - ]} - onRequestClose={onCancel} - onApply={apply} - open={open} - flexBody - fullHeight - id="object-group-variables-dialog" - > - - {groupVariablesContainer.count() > 0 && DismissableTutorialMessage && ( - - {DismissableTutorialMessage} - - )} - Add your first object group variable - } - emptyPlaceholderDescription={ - - These variables hold additional information and are available on - all objects of the group. - - } - helpPagePath={'/all-features/variables/object-variables'} - onComputeAllVariableNames={onComputeAllVariableNames} - onVariablesUpdated={notifyOfVariableChange} - onSelectedVariableChange={onSelectedVariableChange} - isListLocked={isListLocked} - /> - - + + {({ i18n }) => ( + {objectGroup.getName()} variables} + actions={[ + Cancel} + onClick={onCancel} + key="Cancel" + />, + Apply} + primary + onClick={apply} + key="Apply" + id="apply-button" + />, + ]} + secondaryActions={[ + hotReloadPreviewButtonProps ? ( + + ) : null, + , + ]} + onRequestClose={onCancel} + onApply={apply} + open={open} + flexBody + fullHeight + id="object-group-variables-dialog" + > + + {groupVariablesContainer.count() > 0 && DismissableTutorialMessage && ( + + {DismissableTutorialMessage} + + )} + Add your first object group variable + } + emptyPlaceholderDescription={ + + These variables hold additional information and are available + on all objects of the group. + + } + helpPagePath={'/all-features/variables/object-variables'} + onComputeAllVariableNames={onComputeAllVariableNames} + onVariablesUpdated={notifyOfVariableChange} + onSelectedVariableChange={onSelectedVariableChange} + isListLocked={isListLocked} + /> + + + )} + ); }; diff --git a/newIDE/app/src/VariablesList/ObjectInstanceVariablesDialog.js b/newIDE/app/src/VariablesList/ObjectInstanceVariablesDialog.js index d076b67a76c2..cff3d313be72 100644 --- a/newIDE/app/src/VariablesList/ObjectInstanceVariablesDialog.js +++ b/newIDE/app/src/VariablesList/ObjectInstanceVariablesDialog.js @@ -1,9 +1,8 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; -import VariablesEditorDialog, { - type VariableDialogOpeningProps, -} from './VariablesEditorDialog'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import VariablesEditorDialog from './VariablesEditorDialog'; import { type HotReloadPreviewButtonProps } from '../HotReload/HotReloadPreviewButton'; import EventsRootVariablesFinder from '../Utils/EventsRootVariablesFinder'; import { ProjectScopedContainersAccessor } from '../InstructionOrExpression/EventsScope'; @@ -20,7 +19,7 @@ type Props = {| onApply: (selectedVariableName: string | null) => void, onCancel: () => void, hotReloadPreviewButtonProps: HotReloadPreviewButtonProps, - initiallySelectedVariable: VariableDialogOpeningProps | null, + initiallySelectedVariableName?: string, onEditObjectVariables: () => void, isListLocked: boolean, |}; @@ -35,7 +34,7 @@ const ObjectInstanceVariablesDialog = ({ onCancel, onApply, hotReloadPreviewButtonProps, - initiallySelectedVariable, + initiallySelectedVariableName, projectScopedContainersAccessor, onEditObjectVariables, isListLocked, @@ -82,23 +81,28 @@ const ObjectInstanceVariablesDialog = ({ ); return ( - Instance variables} - // $FlowFixMe[incompatible-type] - tabs={tabs} - initiallySelectedVariable={initiallySelectedVariable} - helpPagePath={'/all-features/variables/instance-variables'} - hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} - id="instance-variables-dialog" - onEditObjectVariables={onEditObjectVariables} - isListLocked={isListLocked} - /> + + {({ i18n }) => ( + Instance variables} + // $FlowFixMe[incompatible-type] + tabs={tabs} + initiallySelectedVariableName={initiallySelectedVariableName} + helpPagePath={'/all-features/variables/instance-variables'} + scopeName={i18n._(t`Instance variables`)} + hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} + id="instance-variables-dialog" + onEditObjectVariables={onEditObjectVariables} + isListLocked={isListLocked} + /> + )} + ); }; diff --git a/newIDE/app/src/VariablesList/ObjectVariablesDialog.js b/newIDE/app/src/VariablesList/ObjectVariablesDialog.js index 0693e01e60aa..ab5caa6770b7 100644 --- a/newIDE/app/src/VariablesList/ObjectVariablesDialog.js +++ b/newIDE/app/src/VariablesList/ObjectVariablesDialog.js @@ -1,9 +1,8 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; -import VariablesEditorDialog, { - type VariableDialogOpeningProps, -} from './VariablesEditorDialog'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import VariablesEditorDialog from './VariablesEditorDialog'; import { type HotReloadPreviewButtonProps } from '../HotReload/HotReloadPreviewButton'; import { ProjectScopedContainersAccessor } from '../InstructionOrExpression/EventsScope'; @@ -17,7 +16,8 @@ type Props = {| onApply: (selectedVariableName: string | null) => void, onCancel: () => void, hotReloadPreviewButtonProps: HotReloadPreviewButtonProps | null, - initiallySelectedVariable: VariableDialogOpeningProps | null, + initiallySelectedVariableName?: string, + shouldCreateInitiallySelectedVariable?: boolean, onComputeAllVariableNames: () => Array, isListLocked: boolean, |}; @@ -31,7 +31,8 @@ const ObjectVariablesDialog = ({ onCancel, onApply, hotReloadPreviewButtonProps, - initiallySelectedVariable, + initiallySelectedVariableName, + shouldCreateInitiallySelectedVariable, projectScopedContainersAccessor, onComputeAllVariableNames, isListLocked, @@ -55,23 +56,31 @@ const ObjectVariablesDialog = ({ ); return ( - {objectName} variables} - // $FlowFixMe[incompatible-type] - tabs={tabs} - initiallySelectedVariable={initiallySelectedVariable} - helpPagePath={'/all-features/variables/object-variables'} - hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} - id="object-variables-dialog" - isListLocked={isListLocked} - /> + + {({ i18n }) => ( + {objectName} variables} + // $FlowFixMe[incompatible-type] + tabs={tabs} + initiallySelectedVariableName={initiallySelectedVariableName} + shouldCreateInitiallySelectedVariable={ + shouldCreateInitiallySelectedVariable + } + helpPagePath={'/all-features/variables/object-variables'} + scopeName={i18n._(t`Object variables`)} + hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} + id="object-variables-dialog" + isListLocked={isListLocked} + /> + )} + ); }; diff --git a/newIDE/app/src/VariablesList/SceneVariablesDialog.js b/newIDE/app/src/VariablesList/SceneVariablesDialog.js index 1270963aaca3..190362920613 100644 --- a/newIDE/app/src/VariablesList/SceneVariablesDialog.js +++ b/newIDE/app/src/VariablesList/SceneVariablesDialog.js @@ -1,9 +1,8 @@ // @flow import * as React from 'react'; -import { Trans } from '@lingui/macro'; -import VariablesEditorDialog, { - type VariableDialogOpeningProps, -} from './VariablesEditorDialog'; +import { t, Trans } from '@lingui/macro'; +import { I18n } from '@lingui/react'; +import VariablesEditorDialog from './VariablesEditorDialog'; import { type HotReloadPreviewButtonProps } from '../HotReload/HotReloadPreviewButton'; import EventsRootVariablesFinder from '../Utils/EventsRootVariablesFinder'; import { ProjectScopedContainersAccessor } from '../InstructionOrExpression/EventsScope'; @@ -15,7 +14,8 @@ type Props = {| onApply: (selectedVariableName: string | null) => void, onCancel: () => void, hotReloadPreviewButtonProps: HotReloadPreviewButtonProps | null, - initiallySelectedVariable: VariableDialogOpeningProps | null, + initiallySelectedVariableName?: string, + shouldCreateInitiallySelectedVariable?: boolean, isListLocked: boolean, |}; @@ -26,7 +26,8 @@ const SceneVariablesDialog = ({ onCancel, onApply, hotReloadPreviewButtonProps, - initiallySelectedVariable, + initiallySelectedVariableName, + shouldCreateInitiallySelectedVariable, isListLocked, }: Props): React.Node => { const onComputeAllVariableNames = React.useCallback( @@ -65,21 +66,29 @@ const SceneVariablesDialog = ({ ); return ( - {layout.getName()} variables} - // $FlowFixMe[incompatible-type] - tabs={tabs} - initiallySelectedVariable={initiallySelectedVariable} - helpPagePath={'/all-features/variables/scene-variables'} - hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} - id="scene-variables-dialog" - isListLocked={isListLocked} - /> + + {({ i18n }) => ( + {layout.getName()} variables} + // $FlowFixMe[incompatible-type] + tabs={tabs} + initiallySelectedVariableName={initiallySelectedVariableName} + shouldCreateInitiallySelectedVariable={ + shouldCreateInitiallySelectedVariable + } + helpPagePath={'/all-features/variables/scene-variables'} + scopeName={i18n._(t`Scene variables`)} + hotReloadPreviewButtonProps={hotReloadPreviewButtonProps} + id="scene-variables-dialog" + isListLocked={isListLocked} + /> + )} + ); }; diff --git a/newIDE/app/src/VariablesList/VariablesEditorDialog.js b/newIDE/app/src/VariablesList/VariablesEditorDialog.js index c7e532d60335..ead3dd557000 100644 --- a/newIDE/app/src/VariablesList/VariablesEditorDialog.js +++ b/newIDE/app/src/VariablesList/VariablesEditorDialog.js @@ -62,6 +62,7 @@ type Props = {| hotReloadPreviewButtonProps: HotReloadPreviewButtonProps | null, helpPagePath: ?string, + scopeName?: string, id?: string, |}; @@ -74,6 +75,7 @@ const VariablesEditorDialog = ({ project, hotReloadPreviewButtonProps, helpPagePath, + scopeName, id, tabs, initiallyOpenTabId, @@ -247,7 +249,11 @@ const VariablesEditorDialog = ({ /> ) : null, helpPagePath ? ( - + ) : null, ]} onRequestClose={onCancelChanges}