@smarterplan/ngx-smarterplan-core 1.4.11 → 1.4.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/esm2022/lib/services/matterport-import.service.mjs +2 -57
  2. package/esm2022/lib/services/matterport-navigation.service.mjs +131 -1
  3. package/esm2022/lib/services/matterport-tag-copy.service.mjs +865 -0
  4. package/esm2022/lib/services/matterport-tag.service.mjs +175 -54
  5. package/esm2022/lib/services/matterport.service.mjs +267 -39
  6. package/esm2022/lib/services/models/equipment.service.mjs +16 -1
  7. package/esm2022/lib/services/models/navigation.service.mjs +4 -1
  8. package/esm2022/lib/services/models/poi.service.mjs +86 -8
  9. package/esm2022/lib/services/models/ticket.service.mjs +3 -2
  10. package/esm2022/lib/services/s3.service.mjs +12 -1
  11. package/esm2022/lib/services/utils/matterport-transform.util.mjs +39 -0
  12. package/esm2022/lib/services/viewer.service.mjs +8 -1
  13. package/esm2022/lib/types.service.mjs +9 -1
  14. package/esm2022/public-api.mjs +4 -1
  15. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +1590 -156
  16. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
  17. package/lib/services/matterport-navigation.service.d.ts +25 -0
  18. package/lib/services/matterport-tag-copy.service.d.ts +129 -0
  19. package/lib/services/matterport-tag.service.d.ts +61 -7
  20. package/lib/services/matterport.service.d.ts +81 -1
  21. package/lib/services/models/equipment.service.d.ts +8 -0
  22. package/lib/services/models/poi.service.d.ts +14 -0
  23. package/lib/services/s3.service.d.ts +8 -0
  24. package/lib/services/utils/matterport-transform.util.d.ts +21 -0
  25. package/lib/types.service.d.ts +18 -0
  26. package/package.json +1 -1
  27. package/public-api.d.ts +2 -0
@@ -57,6 +57,31 @@ export declare class MatterportNavigationService {
57
57
  * Disable forbidden sweeps. Resolves each sweep ID to sid before calling SDK.
58
58
  */
59
59
  removeForbiddenSweeps(sdk: any, forbiddenSweeps: string[]): Promise<void>;
60
+ /**
61
+ * Move to a position
62
+ * @param sdk
63
+ * @param position
64
+ * @param rotation
65
+ * @param options
66
+ */
67
+ move_to_position(sdk: any, position: {
68
+ x: number;
69
+ y: number;
70
+ z: number;
71
+ }, rotation: {
72
+ yaw: number;
73
+ pitch?: number;
74
+ roll?: number;
75
+ } | null, options?: {
76
+ transition?: 'FLY' | 'INSTANT' | 'IMMEDIATE';
77
+ durationMs?: number;
78
+ anglesInDegrees?: boolean;
79
+ offset?: {
80
+ x: number;
81
+ y: number;
82
+ z: number;
83
+ };
84
+ }): Promise<void>;
60
85
  /**
61
86
  * Returns the current sweep as a **uuid** (for database matching).
62
87
  * The SDK's poseCamera.sweep is a sid; we translate it.
@@ -0,0 +1,129 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { TranslateService } from '@ngx-translate/core';
3
+ import { NavigationService } from './models/navigation.service';
4
+ import { PoiService } from './models/poi.service';
5
+ import { TicketsService } from './models/ticket.service';
6
+ import { EquipmentService } from './models/equipment.service';
7
+ import { Object3DService } from './models/object3D.service';
8
+ import { FeatureService } from './models/feature.service';
9
+ import { MeasurementService } from './models/measurement.service';
10
+ import { CommentService } from './models/comment.service';
11
+ import { BaseUserService } from './user.service';
12
+ import { Vec3 } from './utils/matterport-transform.util';
13
+ import * as i0 from "@angular/core";
14
+ /** Progress snapshot emitted during copyTagsFromVisit(), so the UI can show a live status. */
15
+ export interface CopyProgress {
16
+ phase: 'collecting' | 'tickets' | 'equipments' | 'pois' | 'objects3d' | 'features' | 'measurements' | 'done';
17
+ processedInPhase: number;
18
+ totalInPhase: number;
19
+ processedOverall: number;
20
+ totalOverall: number;
21
+ percent: number;
22
+ errorCount: number;
23
+ }
24
+ /** A single line in the copy log — either a step status (updated in place) or an error (appended once). */
25
+ export interface CopyLogEntry {
26
+ id: string;
27
+ type: 'step' | 'error';
28
+ text: string;
29
+ }
30
+ export declare class MatterportTagCopyService {
31
+ private navigationService;
32
+ private userService;
33
+ private poiService;
34
+ private ticketService;
35
+ private equipmentService;
36
+ private object3DService;
37
+ private featureService;
38
+ private measurementService;
39
+ private commentService;
40
+ private translate;
41
+ copyProgress$: BehaviorSubject<CopyProgress | null>;
42
+ copyLog$: BehaviorSubject<CopyLogEntry[]>;
43
+ private spModule;
44
+ private log;
45
+ private errorSeq;
46
+ constructor(navigationService: NavigationService, userService: BaseUserService, poiService: PoiService, ticketService: TicketsService, equipmentService: EquipmentService, object3DService: Object3DService, featureService: FeatureService, measurementService: MeasurementService, commentService: CommentService, translate: TranslateService);
47
+ copyTagsFromVisit(sourceSpaceId: string, targetSpaceId: string, landmarkSourceA: Vec3, landmarkTargetA: Vec3, landmarkSourceB: Vec3, landmarkTargetB: Vec3): Promise<boolean>;
48
+ /** Adds or updates a step line (identified by stepId) with new text, then republishes the log. */
49
+ private setStepLog;
50
+ /** Appends a new, permanent log line (never overwritten), then republishes the log. */
51
+ private appendErrorLog;
52
+ /** Resets the log for a new run. */
53
+ private resetLog;
54
+ /** Builds and sets a step's log line as "<translated label>: <percent>%", no step numbering. */
55
+ private setStepProgress;
56
+ /** Logs a translated, parameterized error line for a single failed item. */
57
+ private logItemError;
58
+ /** Logs an item-level error, using a specific "missing file / orphaned reference"
59
+ * translation key when the cause is a MissingS3FileError, and the generic per-type
60
+ * key otherwise. Keeps the copy log readable: a missing file is not a bug to
61
+ * investigate the same way a network/permission error is. */
62
+ private logCopyItemError;
63
+ /**
64
+ * Heuristic duplicate-detection: compares title AND description together instead of
65
+ * title alone, to reduce false positives when several source items happen to share
66
+ * the same title. Not a perfect guarantee, but meaningfully more robust.
67
+ */
68
+ private matchesExisting;
69
+ /**
70
+ * Fetches the position of every sweep in a space and returns it as a Map for O(1) lookup.
71
+ * Uses allSettled so a single failing sweep lookup doesn't abort the whole map —
72
+ * that sweep is simply absent from the resulting map (and skipped later).
73
+ */
74
+ private buildNavigationPositionMap;
75
+ /** Applies the rigid transform to a POI coordinate (position + orientation). */
76
+ private getAdjustedCoordinates;
77
+ /**
78
+ * Applies the rigid transform's translation+rotation to a plain {x,y,z} position,
79
+ * WITHOUT adding xRotation/yRotation keys. Used for measurements, whose stored
80
+ * coordinate is a bare position (no orientation), unlike other POI types.
81
+ */
82
+ private getAdjustedPositionOnly;
83
+ /**
84
+ * Finds the closest target sweep, comparing positions in the SAME coordinate frame.
85
+ * Pure in-memory lookup — no network call, thanks to the pre-built position maps.
86
+ */
87
+ private findClosestTargetSweepId;
88
+ /** Generates a short random id, used to give each copied S3 file a fresh, collision-safe key. */
89
+ private generateShortId;
90
+ /**
91
+ * Builds a new S3 key for a copied attachment and sanitizes the filename
92
+ * to prevent AWS Amplify SignatureDoesNotMatch errors.
93
+ */
94
+ private buildCopiedAttachmentKey;
95
+ /**
96
+ * Duplicates an S3 object if a key is present.
97
+ * - If the source file is genuinely missing from S3 (NoSuchKey / orphaned DB reference),
98
+ * throws a MissingS3FileError so the caller can log a clear, specific message and
99
+ * skip the whole item entirely, rather than creating a record with a broken file link.
100
+ * - Any other kind of failure (permissions, network, etc.) still throws a generic Error.
101
+ */
102
+ private copyS3KeyIfPresent;
103
+ /**
104
+ * Duplicates the file referenced by a POI's tagIcon (a JSON string shaped like
105
+ * { src, opacity }, per form-feature.component.ts). If the JSON can't be parsed or
106
+ * has no `src`, the value is returned unchanged rather than risk corrupting it.
107
+ */
108
+ private duplicateTagIcon;
109
+ /**
110
+ * Duplicates tagImageID if it looks like a reference to a file (contains a path
111
+ * separator, whether raw key or pre-signed URL). UNCONFIRMED ASSUMPTION: this
112
+ * field's exact semantics weren't verified — if it's actually an opaque reference
113
+ * to another DB record rather than a file, this heuristic may incorrectly attempt
114
+ * a copy. Confirm the real structure to tighten this if it causes issues.
115
+ */
116
+ private duplicateTagImageID;
117
+ /**
118
+ * Extracts and normalizes the raw S3 key from a stored value (which may be a full URL
119
+ * or already a raw key).
120
+ * IMPORTANT: this must return the RAW (decoded, non URL-encoded) key. Amplify's
121
+ * Storage.copy() already builds and encodes the 'x-amz-copy-source' header internally
122
+ * from the key we give it. Pre-encoding it here caused a double-encoding bug (e.g. a
123
+ * space became "%2520" instead of "%20"), so Storage.copy() looked for a key that never
124
+ * existed on S3, resulting in a NoSuchKey error.
125
+ */
126
+ private extractS3KeyFromValue;
127
+ static ɵfac: i0.ɵɵFactoryDeclaration<MatterportTagCopyService, never>;
128
+ static ɵprov: i0.ɵɵInjectableDeclaration<MatterportTagCopyService>;
129
+ }
@@ -6,6 +6,8 @@ import { BaseTagService } from './tag.service';
6
6
  import * as i0 from "@angular/core";
7
7
  export declare class MatterportTagService {
8
8
  private navigationService;
9
+ /** Name of the common layer every Smarterplan tag is created in. */
10
+ private static readonly SHARED_TAG_LAYER_NAME;
9
11
  dictionnaryTags: Map<string, MattertagData>;
10
12
  tagAddQueue: Promise<any>;
11
13
  mattertagToFollow: string | null;
@@ -16,10 +18,61 @@ export declare class MatterportTagService {
16
18
  tagService: BaseTagService | null;
17
19
  private tagsCurrentOpacity;
18
20
  private tagsCurrentEnabled;
21
+ /**
22
+ * Single layer holding every Smarterplan tag, added to every view of the space so a
23
+ * tag stays in place — same sid, same content — when the user switches between the
24
+ * furnished and the Defurnished view. Tags added to the global sdk.Tag (or to a
25
+ * view's own layer) belong to that view only, which is what made them pop in and out
26
+ * on every view change.
27
+ *
28
+ * Deliberately NOT created with `{ common: true }`: in SDK 26.7.5 a common layer is
29
+ * pushed into `getOrderedModelViews()` at creation time, and that call defaults to
30
+ * `includeDefurnish: false`, so the Defurnished view never receives it — while
31
+ * `View.addLayer()` refuses to repair it ("Layer is common. No need to add."). A
32
+ * plain layer we attach to each view ourselves reaches every view, Defurnished
33
+ * included. See attachSharedTagLayerToViews().
34
+ */
35
+ private sharedTagLayer;
36
+ private sharedTagLayerPromise;
19
37
  constructor(navigationService: MatterportNavigationService);
20
38
  setTagService(service: BaseTagService): void;
21
39
  /** Opens a specific tag in the Matterport viewer by its ID. */
22
40
  goToTag(sdk: any, sid: string): Promise<any>;
41
+ /**
42
+ * Returns the SDK Tag module to use for an operation addressing an existing tag by ID
43
+ * (icon, opacity, position, attachments, removal...): always the global sdk.Tag.
44
+ *
45
+ * A layer-scoped Tag module only exposes the *replayable* mutations, meant to build
46
+ * the layer's own content; applying them to an already-created tag silently does
47
+ * nothing — which is what left every pin white instead of carrying its icon. Only
48
+ * `add` has to go through the layer, see getTagCreationModule().
49
+ */
50
+ getTagModule(sdk: any, tagId: string): any;
51
+ /**
52
+ * Returns the Tag module every new tag must be created through: the shared layer
53
+ * when the View API is available, the global sdk.Tag otherwise.
54
+ */
55
+ getTagCreationModule(sdk: any): Promise<any>;
56
+ /**
57
+ * Creates (once per SDK session) and returns the shared tag layer.
58
+ * Resolves to null when the View API is unavailable, so callers transparently fall
59
+ * back to the global sdk.Tag.
60
+ */
61
+ ensureSharedTagLayer(sdk: any): Promise<any>;
62
+ /**
63
+ * Makes sure the shared layer is part of every view of the space, Defurnished
64
+ * included. This is what actually shares the tags across views, and the reason the
65
+ * layer must not be a common one: the SDK only performs the attachment for
66
+ * non-common layers. Idempotent, so it can run on every view collection update.
67
+ */
68
+ attachSharedTagLayerToViews(sdk: any, views: Iterable<any>): Promise<void>;
69
+ /**
70
+ * Adds a tag through the shared layer so it exists in every view. Falls back
71
+ * to the global sdk.Tag when the View API is unavailable; that call is raced against
72
+ * a timeout as a safety net, since it never resolves while a Defurnished view is
73
+ * active.
74
+ */
75
+ private addTagToSdk;
23
76
  /** Opens the most recently created tag in the viewer. */
24
77
  goToLastTag(sdk: any): Promise<any>;
25
78
  /**
@@ -38,12 +91,6 @@ export declare class MatterportTagService {
38
91
  * If there are no active rooms (e.g., hallway), falls back to returning true.
39
92
  */
40
93
  isTagInRooms(mattertagData: MattertagData, rooms: any[]): boolean;
41
- /**
42
- * Computes the final context-aware opacity for a single tag.
43
- * @param currentFloorSequence Authoritative current floor sequence from sdk.Floor.current
44
- * (null = single-floor model or unknown).
45
- * @param currentRooms Array of active rooms the camera is in.
46
- */
47
94
  /** Returns the ID of the most recently added tag. */
48
95
  getLastTag(): string | null;
49
96
  /**
@@ -64,6 +111,13 @@ export declare class MatterportTagService {
64
111
  * @param mattertagToFollow ID of the cursor tag (never touched).
65
112
  */
66
113
  updateTagsVisibilityForContext(sdk: any, sweepCollection: any, currentCameraMode: CameraMode, mattertagToFollow: string | null, currentFloorSequence?: number | null, currentRooms?: any[]): Promise<void>;
114
+ /**
115
+ * Drops the memoized opacity/enabled state so the next visibility pass re-applies it
116
+ * to every tag. Needed after a view switch (furnished <-> defurnished): the SDK
117
+ * re-renders the shared layer's tags and the cached values would otherwise make
118
+ * updateTagsVisibilityForContext() skip them, leaving tags stuck invisible.
119
+ */
120
+ resetVisibilityCache(): void;
67
121
  /** Removes a specific tag from the viewer and local dictionaries. */
68
122
  deleteMattertagFromId(sdk: any, mattertagID: string): Promise<void>;
69
123
  /** Removes the last added tag from the viewer. */
@@ -74,7 +128,7 @@ export declare class MatterportTagService {
74
128
  * Creates and configures a Mattertag from a POI, handling coordinates, normals, and sweep ID.
75
129
  * Skips creation if a tag for the object already exists.
76
130
  */
77
- createMattertagFromPOI(sdk: any, tagType: PoiType, object: DbObjectType, poi: POI, poseCamera: any, getTagFromElementId: (id: string) => {
131
+ createMattertagFromPOI(sdk: any, tagType: PoiType, object: DbObjectType, poi: POI, getTagFromElementId: (id: string) => {
78
132
  tag: string;
79
133
  sweep: string;
80
134
  }, setTagIconAndOpacity: (sid: string, mt: MattertagData) => Promise<void>, injectHtmlInTag: (type: PoiType, obj: DbObjectType, sid: string) => Promise<void>): Promise<any>;
@@ -2,7 +2,7 @@ import { NgZone } from '@angular/core';
2
2
  import { ActivatedRoute, Router } from '@angular/router';
3
3
  import { Subject } from 'rxjs';
4
4
  import { MattertagData } from '../mattertagData';
5
- import { DbObjectType, IObject3D, MattertagActionMode, POI, PoiType, SpModule } from '../types.service';
5
+ import { DbObjectType, IObject3D, MattertagActionMode, MatterportView, POI, PoiType, SpModule } from '../types.service';
6
6
  import { BaseTagService } from './tag.service';
7
7
  import { BaseVisibilityService } from './baseVisibility.service';
8
8
  import { Config } from '../config';
@@ -104,6 +104,15 @@ export declare class MatterportService {
104
104
  action: string;
105
105
  data: string;
106
106
  }>;
107
+ /** Views (furnished, defurnished...) exposed by the SDK for the current space. */
108
+ private viewsByType;
109
+ private currentView;
110
+ private viewSubscriptions;
111
+ /** Emits the active view every time the user switches between furnished/defurnished. */
112
+ onViewChanged: Subject<MatterportView | null>;
113
+ /** Delay left to the SDK to rebuild the layer's tags after a view switch. */
114
+ private static readonly VIEW_SWITCH_REFRESH_DELAY_MS;
115
+ private viewSwitchRestoreTimer;
107
116
  get mattertagToFollow(): string | null;
108
117
  set mattertagToFollow(value: string | null);
109
118
  get inTransitionMode(): boolean;
@@ -186,10 +195,40 @@ export declare class MatterportService {
186
195
  setRegistredIconForTag(mattertagID: string, iconName: string): Promise<void>;
187
196
  /** Sets the appropriate icon and opacity for a tag based on its type and POI metadata. */
188
197
  setTagIconAndOpacity(mattertagID: string, mattertagData: MattertagData): Promise<void>;
198
+ /**
199
+ * Applies an icon to a tag. The call is awaited and its rejection reported: a
200
+ * silently dropped promise here leaves the pin with its default white look.
201
+ */
202
+ private editTagIcon;
189
203
  /** Navigates the camera to the most recently created tag. */
190
204
  goToLastTag(): Promise<void>;
191
205
  /** Navigates the camera to a specific Mattertag by its ID. */
192
206
  goToTag(mattertagID: string): Promise<void>;
207
+ /**
208
+ * Move the viewer camera to a specific 3D position and apply a rotation.
209
+ * Delegates the heavy lifting to MatterportNavigationService.move_to_position.
210
+ * - position: { x, y, z }
211
+ * - rotation: { yaw, pitch?, roll? } in degrees by default
212
+ * - options: optional transition and conversion settings (see navigation service)
213
+ */
214
+ goToPosition(position: {
215
+ x: number;
216
+ y: number;
217
+ z: number;
218
+ }, rotation?: {
219
+ yaw: number;
220
+ pitch?: number;
221
+ roll?: number;
222
+ } | null, options?: {
223
+ transition?: 'FLY' | 'INSTANT' | 'IMMEDIATE';
224
+ durationMs?: number;
225
+ anglesInDegrees?: boolean;
226
+ offset?: {
227
+ x: number;
228
+ y: number;
229
+ z: number;
230
+ };
231
+ }): Promise<void>;
193
232
  /**
194
233
  * Computes the context-aware opacity for a single tag at the moment it is rendered.
195
234
  * - Cursor tag: always use provided defaultOpacity.
@@ -300,6 +339,47 @@ export declare class MatterportService {
300
339
  * @returns MattertagData
301
340
  */
302
341
  getMatterTagDataForMattertag(mattertagID: string): MattertagData | null;
342
+ /**
343
+ * Subscribes to the SDK View API to keep track of the views available for the space
344
+ * and of the active one. Tags live in a shared common layer, so a view change only
345
+ * requires re-applying their visibility, never re-creating them.
346
+ */
347
+ private initViews;
348
+ /**
349
+ * Forces the opacity/enabled state to be pushed again to every tag. The SDK
350
+ * re-renders the shared layer's tags on a view swap, and the memoized values would
351
+ * otherwise make updateTagsVisibilityForContext() skip them, leaving tags invisible.
352
+ */
353
+ private reapplyTagsVisibility;
354
+ /**
355
+ * Puts the tags back in shape in the view that just became active.
356
+ *
357
+ * Activating a view re-materializes the shared layer's tags from the descriptors
358
+ * recorded when they were added, so everything applied to a tag *afterwards* through
359
+ * the global Tag module is dropped along the way: the custom icon (the pin falls back
360
+ * to the descriptor's white) and the sandbox carrying the hover content. They have to
361
+ * be applied again on the freshly rebuilt tags.
362
+ *
363
+ * Visibility is refreshed straight away so the tags show up without waiting, then
364
+ * content is re-applied once the transition is over — re-applying it too early would
365
+ * target tags the SDK has not rebuilt yet.
366
+ */
367
+ private restoreTagsForActiveView;
368
+ /**
369
+ * Re-applies the icon and the injected HTML of every tag we own. Used after a view
370
+ * switch, see restoreTagsForActiveView().
371
+ */
372
+ private refreshTagsContent;
373
+ private clearViewSubscriptions;
374
+ /** True when the space provides a defurnished view. */
375
+ get hasDefurnishView(): boolean;
376
+ /** True when the defurnished view is the active one. */
377
+ get isDefurnishedView(): boolean;
378
+ /**
379
+ * Switches between the defurnished view and the furnished one.
380
+ * @param returnToStart Move the camera back to the view's start location.
381
+ */
382
+ toggleDefurnishView(returnToStart?: boolean): Promise<void>;
303
383
  action_toolbox_floorplan(): Promise<void>;
304
384
  action_toolbox_inside_view(): void;
305
385
  actionShowAllFloors(): void;
@@ -63,6 +63,14 @@ export declare class EquipmentService extends BaseObjectService {
63
63
  nextToken: string | null;
64
64
  }>;
65
65
  uploadImageForAllEquipments(equipments: Equipment[], imageFile: File): Promise<Equipment[]>;
66
+ /**
67
+ * Creates a Note attached to an equipment from an S3 key that ALREADY exists
68
+ * (as opposed to uploadDoc/uploadImage, which upload a fresh browser File).
69
+ * Used when duplicating equipment attachments during a cross-visit copy: the
70
+ * S3 object itself has already been physically copied by the caller beforehand,
71
+ * so this only needs to record the Note pointing at that new key.
72
+ */
73
+ createNoteWithExistingAttachment(equipmentID: string, attachmentKey: string, type: TypeNote, ownerMissionID: string | null): Promise<Note>;
66
74
  uploadImage(equipment: Equipment, imageFile: File): Promise<Note>;
67
75
  updateEquipment(equip: any, file?: File, noteType?: TypeNote): Promise<Equipment>;
68
76
  getPrefixDoc(type: TypeNote): any;
@@ -19,6 +19,20 @@ export declare class PoiService {
19
19
  updatePoi(poi: {}): Promise<POI>;
20
20
  deletePoi(poiID: string): Promise<POI>;
21
21
  getPoisByMatterportSweepByType(sweep: string, type: PoiType): Promise<POI[]>;
22
+ /**
23
+ * Optimized version: fetches POIs for MANY sweeps in as few GraphQL calls as possible,
24
+ * using an `or: [{ matterportSweepID: { eq } }, ...]` filter instead of looping one
25
+ * request per sweep. This is a DynamoDB Scan with a server-side filter (not a GSI
26
+ * hash-key query), so `or` composition works and collapses N sweep-by-sweep calls
27
+ * into a handful of paginated calls total.
28
+ *
29
+ * NOTE: `in` is NOT supported on this schema's ModelStringInput (older Amplify codegen),
30
+ * hence the `or` composition instead — functionally equivalent for this use case.
31
+ *
32
+ * Chunked because DynamoDB/AppSync filter expressions have a practical size ceiling —
33
+ * splitting keeps each request well within safe limits regardless of space size.
34
+ */
35
+ getPoisByMatterportSweeps(sweeps: string[]): Promise<POI[]>;
22
36
  unsubscribe(): void;
23
37
  static ɵfac: i0.ɵɵFactoryDeclaration<PoiService, never>;
24
38
  static ɵprov: i0.ɵɵInjectableDeclaration<PoiService>;
@@ -12,3 +12,11 @@ export declare const getSignedFile: (path: any) => Promise<string | null>;
12
12
  export declare const downloadFileAsObject: (path: any) => Promise<Object | void>;
13
13
  export declare const getBufferForFileFromS3: (path: any) => Promise<ArrayBuffer>;
14
14
  export declare const uploadJsonToS3: (path: string, json: string, filename: string) => Promise<string>;
15
+ /**
16
+ * Physically duplicates an S3 object to a new key. Used when copying attachments
17
+ * between features/tickets/etc. so the copy is fully independent: deleting the
18
+ * original file later must not affect the copy.
19
+ * IMPORTANT: does NOT swallow errors — callers need the real error (e.g. NoSuchKey)
20
+ * to distinguish an orphaned DB reference from a genuine copy failure.
21
+ */
22
+ export declare const copyFileInS3: (sourceKey: string, destKey: string) => Promise<string>;
@@ -0,0 +1,21 @@
1
+ export interface Vec3 {
2
+ x: number;
3
+ y: number;
4
+ z: number;
5
+ }
6
+ export interface RigidTransform {
7
+ rotationYRad: number;
8
+ refSource: Vec3;
9
+ refTarget: Vec3;
10
+ }
11
+ /**
12
+ * Computes the rigid transform (Y-axis rotation + translation) between two
13
+ * coordinate frames, from 2 pairs of points representing the same physical spot.
14
+ */
15
+ export declare function computeRigidTransform(sourceA: Vec3, targetA: Vec3, sourceB: Vec3, targetB: Vec3): RigidTransform;
16
+ /** Applies the rigid transform to a 3D position (x, y, z). */
17
+ export declare function applyRigidTransformToPoint(p: Vec3, t: RigidTransform): Vec3;
18
+ /** Applies the Y rotation (in degrees) to an orientation angle (a pose's yRotation). */
19
+ export declare function applyRigidTransformToYRotationDeg(yRotationDeg: number, t: RigidTransform): number;
20
+ /** Euclidean distance between two points, useful to validate landmark quality. */
21
+ export declare function distance(a: Vec3, b: Vec3): number;
@@ -842,3 +842,21 @@ export type Object3D = {
842
842
  items: POI[];
843
843
  };
844
844
  } & AWSType;
845
+ export declare enum MatterportViewType {
846
+ BASE = "viewtype.base",
847
+ DEFURNISH = "viewtype.defurnish",
848
+ LAYERED_BASE = "viewtype.layeredbase",
849
+ OTHER = "viewtype.other",
850
+ USER = "viewtype.user"
851
+ }
852
+ export interface MatterportView {
853
+ id: string;
854
+ name: string;
855
+ active: boolean;
856
+ type: MatterportViewType;
857
+ setActive(returnToStart?: boolean): Promise<void>;
858
+ }
859
+ export type MatterportViewCollection = Record<string, MatterportView>;
860
+ export interface MatterportSubscription {
861
+ cancel(): void;
862
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smarterplan/ngx-smarterplan-core",
3
- "version": "1.4.11",
3
+ "version": "1.4.13",
4
4
  "dependencies": {
5
5
  "tslib": "^2.5.0"
6
6
  },
package/public-api.d.ts CHANGED
@@ -18,7 +18,9 @@ export * from './lib/services/filter.service';
18
18
  export * from './lib/services/search.service';
19
19
  export * from './lib/services/zone-drawer.service';
20
20
  export * from './lib/services/matterport-import.service';
21
+ export * from './lib/services/matterport-tag-copy.service';
21
22
  export * from './lib/mattertagData';
23
+ export * from './lib/services/utils/matterport-transform.util';
22
24
  export * from './lib/services/models/profile.service';
23
25
  export * from './lib/services/models/zone.service';
24
26
  export * from './lib/services/models/mission.service';