Skip to content

Commit a753081

Browse files
committed
Refactor persisted properties scroll into shared hook
1 parent 7371537 commit a753081

File tree

16 files changed

+212
-25
lines changed

16 files changed

+212
-25
lines changed

Core/GDCore/Project/Object.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ Object& Object::ResetPersistentUuid() {
147147
return *this;
148148
}
149149

150+
const gd::String& Object::GetPersistentUuid() const {
151+
if (persistentUuid.empty()) {
152+
persistentUuid = UUID::MakeUuid4();
153+
}
154+
return persistentUuid;
155+
}
156+
150157
Object& Object::ClearPersistentUuid() {
151158
persistentUuid = "";
152159
objectVariables.ClearPersistentUuid();

Core/GDCore/Project/Object.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ class GD_CORE_API Object {
242242
*/
243243
Object& ResetPersistentUuid();
244244

245+
/**
246+
* \brief Return the persistent UUID, used to recognize
247+
* the same object between serialization.
248+
*/
249+
const gd::String& GetPersistentUuid() const;
250+
245251
/**
246252
* \brief Remove the persistent UUID - when the object no
247253
* longer need to be recognized between serializations.

GDevelop.js/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ export class gdObject extends EmscriptenObject {
789789
serializeTo(element: SerializerElement): void;
790790
unserializeFrom(project: Project, element: SerializerElement): void;
791791
resetPersistentUuid(): gdObject;
792+
getPersistentUuid(): string;
792793
clearPersistentUuid(): gdObject;
793794
}
794795

GDevelop.js/types/gdobject.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ declare class gdObject {
2020
serializeTo(element: gdSerializerElement): void;
2121
unserializeFrom(project: gdProject, element: gdSerializerElement): void;
2222
resetPersistentUuid(): gdObject;
23+
getPersistentUuid(): string;
2324
clearPersistentUuid(): gdObject;
2425
delete(): void;
2526
ptr: number;

newIDE/app/src/AssetStore/InstallAsset.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ export const addAssetToProject = async ({
285285
);
286286
// The name was overwritten after unserialization.
287287
object.setName(newName);
288+
object.resetPersistentUuid();
288289
object.setAssetStoreId(asset.id);
289290
if (project.hasEventsBasedObject(object.getType())) {
290291
const customObjectConfiguration = gd.asCustomObjectConfiguration(

newIDE/app/src/EditorFunctions/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,7 @@ const createOrReplaceObject: EditorFunction = {
10841084
project
10851085
);
10861086
newObject.setName(targetObjectName); // Unserialization has overwritten the name.
1087+
newObject.resetPersistentUuid();
10871088

10881089
// Update behaviors shared data for the scene where the object was duplicated.
10891090
if (target_object_scope === 'global') {

newIDE/app/src/InstancesEditor/CompactInstancePropertiesEditor/index.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { IconContainer } from '../../UI/IconContainer';
4040
import { getHelpLink } from '../../Utils/HelpLink';
4141
import Window from '../../Utils/Window';
4242
import { type ResourceManagementProps } from '../../ResourcesList/ResourceSource';
43+
import { usePersistedScrollPosition } from '../../Utils/UsePersistedScrollPosition';
4344
import EmptyMessage from '../../UI/EmptyMessage';
4445
import CompactBehaviorsEditorService from '../../ObjectEditor/CompactObjectPropertiesEditor/CompactBehaviorsEditorService';
4546

@@ -165,6 +166,31 @@ export const CompactInstancePropertiesEditor = ({
165166
}
166167
}, []);
167168

169+
const scrollKey = instances
170+
.map((instance: gdInitialInstance) => '' + instance.ptr)
171+
.join(';');
172+
173+
const selectedObjectForScroll = React.useMemo(() => {
174+
if (!instances.length) return null;
175+
176+
return getObjectByName(
177+
globalObjectsContainer,
178+
objectsContainer,
179+
instances[0].getObjectName()
180+
);
181+
}, [globalObjectsContainer, instances, objectsContainer]);
182+
183+
const persistedScrollId = selectedObjectForScroll
184+
? selectedObjectForScroll.getPersistentUuid()
185+
: null;
186+
187+
const onScroll = usePersistedScrollPosition({
188+
project,
189+
scrollViewRef,
190+
scrollKey,
191+
persistedScrollId,
192+
});
193+
168194
const { object, instanceSchema, allVisibleBehaviors } = React.useMemo<{|
169195
object?: gdObject,
170196
instanceSchema?: Schema,
@@ -313,9 +339,8 @@ export const CompactInstancePropertiesEditor = ({
313339
ref={scrollViewRef}
314340
autoHideScrollbar
315341
style={styles.scrollView}
316-
key={instances
317-
.map((instance: gdInitialInstance) => '' + instance.ptr)
318-
.join(';')}
342+
key={scrollKey}
343+
onScroll={onScroll}
319344
>
320345
<Column expand noMargin id="instance-properties-editor">
321346
<Column>

newIDE/app/src/MainFrame/EditorTabs/UseEditorTabsStateSaving.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ const useEditorTabsStateSaving = ({
9696
setEditorStateForProject(
9797
currentProjectId,
9898
editorState.editors.length === 0
99-
? undefined
99+
? { editorTabs: null }
100100
: { editorTabs: editorState }
101101
);
102102
},
@@ -127,7 +127,8 @@ const useEditorTabsStateSaving = ({
127127
const hasAPreviousSaveForEditorTabsState = React.useCallback(
128128
(project: gdProject) => {
129129
const projectId = project.getProjectUuid();
130-
return !!getEditorStateForProject(projectId);
130+
const editorState = getEditorStateForProject(projectId);
131+
return !!(editorState && editorState.editorTabs);
131132
},
132133
[getEditorStateForProject]
133134
);
@@ -136,7 +137,7 @@ const useEditorTabsStateSaving = ({
136137
(project: gdProject): number => {
137138
const projectId = project.getProjectUuid();
138139
const editorState = getEditorStateForProject(projectId);
139-
if (!editorState) return 0;
140+
if (!editorState || !editorState.editorTabs) return 0;
140141
let shouldOpenSavedCurrentTab = true;
141142

142143
const editorsOpeningOptions = editorState.editorTabs.editors

newIDE/app/src/MainFrame/Preferences/PreferencesContext.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ export const allAlertMessages: Array<{
175175
* type and add a setter into `Preferences` type. Then, update the
176176
* preference dialog.
177177
*/
178+
export type EditorStateForProject = {|
179+
editorTabs: EditorTabsPersistedState | null,
180+
propertiesPanelScroll: { [string]: number },
181+
|};
182+
183+
// $FlowFixMe[deprecated-utility]
184+
export type EditorStateForProjectUpdate = $Shape<EditorStateForProject>;
185+
178186
export type PreferencesValues = {|
179187
language: string,
180188
autoDownloadUpdates: boolean,
@@ -226,7 +234,7 @@ export type PreferencesValues = {|
226234
[featureId: string]: {| dates: [number] |},
227235
},
228236
displaySaveReminder: {| activated: boolean |}, // Store as object in case we need to add options.
229-
editorStateByProject: { [string]: { editorTabs: EditorTabsPersistedState } },
237+
editorStateByProject: { [string]: EditorStateForProject },
230238
fetchPlayerTokenForPreviewAutomatically: boolean,
231239
previewCrashReportUploadLevel: string,
232240
gamesDashboardOrderBy: GamesDashboardOrderBy,
@@ -346,10 +354,10 @@ export type Preferences = {|
346354
setDisplaySaveReminder: ({| activated: boolean |}) => void,
347355
getEditorStateForProject: (
348356
projectId: string
349-
) => ?{| editorTabs: EditorTabsPersistedState |},
357+
) => ?EditorStateForProject,
350358
setEditorStateForProject: (
351359
projectId: string,
352-
editorState?: {| editorTabs: EditorTabsPersistedState |}
360+
editorState: EditorStateForProjectUpdate | null
353361
) => void,
354362
setFetchPlayerTokenForPreviewAutomatically: (enabled: boolean) => void,
355363
setPreviewCrashReportUploadLevel: (level: string) => void,

newIDE/app/src/MainFrame/Preferences/PreferencesProvider.js

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import PreferencesContext, {
55
initialPreferences,
66
type Preferences,
77
type AlertMessageIdentifier,
8+
type EditorStateForProject,
9+
type EditorStateForProjectUpdate,
810
} from './PreferencesContext';
911
import optionalRequire from '../../Utils/OptionalRequire';
1012
import { getIDEVersion } from '../../Version';
@@ -21,7 +23,6 @@ import { type EditorMosaicNode } from '../../UI/EditorMosaic';
2123
import { type FileMetadataAndStorageProviderName } from '../../ProjectsStorage';
2224
import defaultShortcuts from '../../KeyboardShortcuts/DefaultShortcuts';
2325
import { type CommandName } from '../../CommandPalette/CommandsList';
24-
import { type EditorTabsPersistedState } from '../EditorTabs/EditorTabsHandler';
2526
import {
2627
getBrowserLanguageOrLocale,
2728
setLanguageInDOM,
@@ -1249,24 +1250,54 @@ export default class PreferencesProvider extends React.Component<Props, State> {
12491250
}
12501251

12511252
_getEditorStateForProject(projectId: string): any {
1252-
return this.state.values.editorStateByProject[projectId];
1253+
const editorState = this.state.values.editorStateByProject[projectId];
1254+
if (!editorState) return null;
1255+
1256+
return {
1257+
editorTabs: editorState.editorTabs == null ? null : editorState.editorTabs,
1258+
propertiesPanelScroll: editorState.propertiesPanelScroll || {},
1259+
};
12531260
}
12541261

12551262
_setEditorStateForProject(
12561263
projectId: string,
1257-
editorState?: {| editorTabs: EditorTabsPersistedState |}
1264+
editorState: EditorStateForProjectUpdate | null
12581265
) {
12591266
this.setState(
1260-
state => ({
1261-
values: {
1262-
...state.values,
1263-
editorStateByProject: {
1264-
...state.values.editorStateByProject,
1265-
// $FlowFixMe[incompatible-type]
1266-
[projectId]: editorState,
1267+
state => {
1268+
const nextEditorStateByProject = {
1269+
...state.values.editorStateByProject,
1270+
};
1271+
1272+
if (editorState === null) {
1273+
delete nextEditorStateByProject[projectId];
1274+
} else {
1275+
const previousEditorState = state.values.editorStateByProject[projectId] || {
1276+
editorTabs: null,
1277+
propertiesPanelScroll: {},
1278+
};
1279+
const mergedEditorState: EditorStateForProject = {
1280+
...previousEditorState,
1281+
...editorState,
1282+
};
1283+
1284+
if (
1285+
mergedEditorState.editorTabs === null &&
1286+
Object.keys(mergedEditorState.propertiesPanelScroll).length === 0
1287+
) {
1288+
delete nextEditorStateByProject[projectId];
1289+
} else {
1290+
nextEditorStateByProject[projectId] = mergedEditorState;
1291+
}
1292+
}
1293+
1294+
return {
1295+
values: {
1296+
...state.values,
1297+
editorStateByProject: nextEditorStateByProject,
12671298
},
1268-
},
1269-
}),
1299+
};
1300+
},
12701301
() => this._persistValuesToLocalStorage(this.state)
12711302
);
12721303
}

0 commit comments

Comments
 (0)