diff --git a/common/api/core-backend.api.md b/common/api/core-backend.api.md index 5f392e5c9353..a5d51b98dae5 100644 --- a/common/api/core-backend.api.md +++ b/common/api/core-backend.api.md @@ -3116,7 +3116,7 @@ export abstract class IModelDb extends IModel { // @alpha importSchemaStrings(serializedXmlSchemas: string[]): Promise; // @internal (undocumented) - protected initializeIModelDb(): void; + protected initializeIModelDb(when?: "pullMerge"): void; get isBriefcase(): boolean; isBriefcaseDb(): this is BriefcaseDb; // @internal diff --git a/common/changes/@itwin/core-backend/nick-refreshextentsafterpullchanges_2024-09-23-18-57.json b/common/changes/@itwin/core-backend/nick-refreshextentsafterpullchanges_2024-09-23-18-57.json new file mode 100644 index 000000000000..5fc04f51e269 --- /dev/null +++ b/common/changes/@itwin/core-backend/nick-refreshextentsafterpullchanges_2024-09-23-18-57.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-backend", + "comment": "pulling a changeset with project extents changes now updates the extents of the opened imodel", + "type": "none" + } + ], + "packageName": "@itwin/core-backend" +} \ No newline at end of file diff --git a/core/backend/src/IModelDb.ts b/core/backend/src/IModelDb.ts index 0336ce040dcf..3e9609c14f61 100644 --- a/core/backend/src/IModelDb.ts +++ b/core/backend/src/IModelDb.ts @@ -352,8 +352,8 @@ export abstract class IModelDb extends IModel { } /** @internal */ - protected initializeIModelDb() { - const props = this[_nativeDb].getIModelProps(); + protected initializeIModelDb(when?: "pullMerge") { + const props = this[_nativeDb].getIModelProps(when); super.initialize(props.rootSubject.name, props); if (this._initialized) return; @@ -3008,7 +3008,7 @@ export class BriefcaseDb extends IModelDb { await BriefcaseManager.pullAndApplyChangesets(this, arg ?? {}); if (!this.skipSyncSchemasOnPullAndPush) await SchemaSync.pull(this); - this.initializeIModelDb(); + this.initializeIModelDb("pullMerge"); }); IpcHost.notifyTxns(this, "notifyPulledChanges", this.changeset as ChangesetIndexAndId); @@ -3094,7 +3094,7 @@ export class BriefcaseDb extends IModelDb { // pushing changes requires a writeable briefcase await this.executeWritable(async () => { await BriefcaseManager.pullMergePush(this, arg); - this.initializeIModelDb(); + this.initializeIModelDb("pullMerge"); }); const changeset = this.changeset as ChangesetIndexAndId; diff --git a/core/backend/src/test/standalone/IModelWrite.test.ts b/core/backend/src/test/standalone/IModelWrite.test.ts index 8135991f58e5..4d0cb3ea9db6 100644 --- a/core/backend/src/test/standalone/IModelWrite.test.ts +++ b/core/backend/src/test/standalone/IModelWrite.test.ts @@ -6,7 +6,7 @@ import { AccessToken, DbResult, GuidString, Id64, Id64String } from "@itwin/core-bentley"; import { ChangesetIdWithIndex, Code, ColorDef, - GeometricElement2dProps, GeometryStreamProps, IModel, LockState, QueryRowFormat, RequestNewBriefcaseProps, SchemaState, SubCategoryAppearance, + GeometricElement2dProps, GeometryStreamProps, IModel, IModelVersion, LockState, QueryRowFormat, RequestNewBriefcaseProps, SchemaState, SubCategoryAppearance, } from "@itwin/core-common"; import { Arc3d, IModelJson, Point2d, Point3d } from "@itwin/core-geometry"; import * as chai from "chai"; @@ -839,6 +839,40 @@ describe("IModelWriteTest", () => { rwIModel2.close(); }); + it("pulling a changeset with extents changes should update the extents of the opened imodel", async () => { + const accessToken = await HubWrappers.getAccessToken(TestUserType.Regular); + const version0 = IModelTestUtils.resolveAssetFile("mirukuru.ibim"); + const iModelId = await HubMock.createNewIModel({ iTwinId, iModelName: "projectExtentsTest", version0 }); + const iModel = await HubWrappers.downloadAndOpenBriefcase({ iTwinId, iModelId }); + const changesetIdBeforeExtentsChange = iModel.changeset.id; + const extents = iModel.projectExtents; + const newExtents = extents.clone(); + newExtents.low.x += 100; + newExtents.low.y += 100; + newExtents.high.x += 100; + newExtents.high.y += 100; + iModel.updateProjectExtents(newExtents); + iModel.saveChanges("update project extents"); + await iModel.pushChanges({ description: "update project extents" }); + await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); + const iModelBeforeExtentsChange = await HubWrappers.downloadAndOpenBriefcase({ accessToken, iTwinId, iModelId, asOf: IModelVersion.asOfChangeSet(changesetIdBeforeExtentsChange).toJSON() }); + const extentsBeforePull = iModelBeforeExtentsChange.projectExtents; + // Read the extents fileProperty. + const extentsStrBeforePull = iModelBeforeExtentsChange.queryFilePropertyString({name: "Extents", namespace: "dgn_Db"}); + const ecefLocationBeforeExtentsChange = iModelBeforeExtentsChange.ecefLocation; + await iModelBeforeExtentsChange.pullChanges(); // Pulls the extents change. + const extentsAfterPull = iModelBeforeExtentsChange.projectExtents; + const extentsStrAfterPull = iModelBeforeExtentsChange.queryFilePropertyString({name: "Extents", namespace: "dgn_Db"}); + const ecefLocationAfterExtentsChange = iModelBeforeExtentsChange.ecefLocation; + + expect(ecefLocationBeforeExtentsChange).to.not.be.undefined; + expect(ecefLocationAfterExtentsChange).to.not.be.undefined; + expect(ecefLocationBeforeExtentsChange?.isAlmostEqual(ecefLocationAfterExtentsChange!)).to.be.false; + expect(extentsStrAfterPull).to.not.equal(extentsStrBeforePull); + expect(extentsAfterPull.isAlmostEqual(extentsBeforePull)).to.be.false; + await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModelBeforeExtentsChange); + }); + it("parent lock should suffice when inserting into deeply nested sub-model", async () => { const version0 = IModelTestUtils.resolveAssetFile("test.bim"); const iModelId = await HubMock.createNewIModel({ iTwinId, iModelName: "subModelCoveredByParentLockTest", version0 });