@nstudio/ui-collectionview 5.1.9-alpha.5 → 5.1.10

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.
package/index.ios.js CHANGED
@@ -1,5 +1,6 @@
1
- import { ChangeType, ContentView, Observable, Property, ProxyViewContainer, Trace, Utils, View, paddingBottomProperty, paddingLeftProperty, paddingRightProperty, paddingTopProperty, profile } from '@nativescript/core';
2
- import { CLog, CLogTypes, CollectionViewBase, ViewTemplateType, getUUID, isBounceEnabledProperty, isScrollEnabledProperty, itemTemplatesProperty, orientationProperty, reorderLongPressEnabledProperty, reorderingEnabledProperty, reverseLayoutProperty, scrollBarIndicatorVisibleProperty } from './common';
1
+ import { ChangeType, ContentView, Length, Observable, Property, ProxyViewContainer, Trace, Utils, View, booleanConverter, paddingBottomProperty, paddingLeftProperty, paddingRightProperty, paddingTopProperty, profile } from '@nativescript/core';
2
+ import { reorderLongPressEnabledProperty, reorderingEnabledProperty, reverseLayoutProperty, scrollBarIndicatorVisibleProperty } from '.';
3
+ import { CLog, CLogTypes, CollectionViewBase, ListViewViewTypes, isBounceEnabledProperty, isScrollEnabledProperty, itemTemplatesProperty, orientationProperty } from './common';
3
4
  export * from './common';
4
5
  const infinity = Utils.layout.makeMeasureSpec(0, Utils.layout.UNSPECIFIED);
5
6
  export var ContentInsetAdjustmentBehavior;
@@ -32,38 +33,37 @@ export const contentInsetAdjustmentBehaviorProperty = new Property({
32
33
  valueConverter: parseContentInsetAdjustmentBehavior,
33
34
  defaultValue: ContentInsetAdjustmentBehavior.Automatic,
34
35
  });
36
+ export const estimatedItemSizeProperty = new Property({
37
+ name: 'estimatedItemSize',
38
+ defaultValue: true,
39
+ valueConverter: booleanConverter,
40
+ });
41
+ export const autoSizeProperty = new Property({
42
+ name: 'autoSize',
43
+ defaultValue: false,
44
+ valueConverter: booleanConverter,
45
+ });
46
+ export var SnapPosition;
47
+ (function (SnapPosition) {
48
+ SnapPosition[SnapPosition["START"] = -1] = "START";
49
+ SnapPosition[SnapPosition["END"] = 1] = "END";
50
+ })(SnapPosition || (SnapPosition = {}));
35
51
  export class CollectionView extends CollectionViewBase {
52
+ // dragDelegate: UICollectionViewDragDelegateImpl;
53
+ // dropDelegate: UICollectionViewDropDelegateImpl;
36
54
  constructor() {
37
55
  super();
38
56
  this._preparingCell = false;
39
- this._visibleCells = new Set();
57
+ this.autoSize = false;
40
58
  this.reorderStartingRow = -1;
41
59
  this.reorderEndingRow = -1;
42
60
  this.manualDragging = false;
43
61
  this.scrollEnabledBeforeDragging = true;
44
- this.cellRegistrations = {};
62
+ this.estimatedItemSize = true;
45
63
  this.needsScrollStartEvent = false;
46
64
  this.isScrolling = false;
47
- this.updateVisibleCells = Utils.throttle(() => {
48
- if (!this.nativeViewProtected) {
49
- return;
50
- }
51
- if (this.hasListeners(CollectionViewBase.itemRecyclingEvent)) {
52
- this._visibleCells.forEach((cell) => {
53
- if (!this.nativeViewProtected.visibleCells.containsObject(cell)) {
54
- this.notify({
55
- eventName: CollectionViewBase.itemRecyclingEvent,
56
- index: -1,
57
- object: this,
58
- item: null,
59
- view: cell.view,
60
- });
61
- this._visibleCells.delete(cell);
62
- }
63
- });
64
- }
65
- }, 100);
66
65
  this._map = new Map();
66
+ // this._sizes = new Array<number[]>();
67
67
  }
68
68
  createNativeView() {
69
69
  let layout;
@@ -71,28 +71,37 @@ export class CollectionView extends CollectionViewBase {
71
71
  layout = this._layout = CollectionViewBase.layoutStyles[this.layoutStyle].createLayout(this);
72
72
  }
73
73
  else {
74
- layout = this._layout = UICollectionViewFlowLayout.alloc().init();
74
+ layout = this._layout = UICollectionViewFlowLayoutImpl.initWithOwner(this);
75
+ // layout = this._layout = UICollectionViewFlowLayout.new();
75
76
  }
76
77
  if (layout instanceof UICollectionViewFlowLayout) {
77
78
  layout.minimumLineSpacing = 0;
78
79
  layout.minimumInteritemSpacing = 0;
79
80
  }
80
- const view = UICollectionView.alloc().initWithFrameCollectionViewLayout(CGRectMake(0, 0, 0, 0), layout);
81
+ // const view = UICollectionViewImpl.initWithFrameCollectionViewLayout(CGRectMake(0, 0, 0, 0), layout) as UICollectionViewImpl;
82
+ const view = UICollectionViewImpl.initWithOwner(this, layout);
81
83
  view.backgroundColor = UIColor.clearColor;
84
+ this._itemTemplatesInternal.forEach((t) => {
85
+ view.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
86
+ });
82
87
  view.autoresizesSubviews = false;
83
88
  view.autoresizingMask = 0 /* UIViewAutoresizing.None */;
84
89
  this.lastContentOffset = view.contentOffset;
85
90
  return view;
86
91
  }
87
- // onTemplateAdded(t) {
88
- // super.onTemplateAdded(t);
89
- // if (this.nativeViewProtected) {
90
- // // this.nativeViewProtected.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
91
- // }
92
- // }
92
+ onTemplateAdded(t) {
93
+ super.onTemplateAdded(t);
94
+ if (this.nativeViewProtected) {
95
+ this.nativeViewProtected.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
96
+ }
97
+ }
93
98
  initNativeView() {
94
99
  super.initNativeView();
95
- this.setupDataSource();
100
+ const nativeView = this.nativeViewProtected;
101
+ this._dataSource = CollectionViewDataSource.initWithOwner(this);
102
+ nativeView.dataSource = this._dataSource;
103
+ // this.dragDelegate = nativeView.dragDelegate = UICollectionViewDragDelegateImpl.initWithOwner(this);
104
+ // this.dropDelegate = nativeView.dropDelegate = UICollectionViewDropDelegateImpl.initWithOwner(this);
96
105
  // delegate will be set in first onLayout because we need computed _effectiveColWidth and _effectiveRowHeight
97
106
  this._measureCellMap = new Map();
98
107
  // waterfall requires the delegate to be set as soon as possible
@@ -103,141 +112,20 @@ export class CollectionView extends CollectionViewBase {
103
112
  this._delegate = layoutStyle.createDelegate(this);
104
113
  this.nativeViewProtected.delegate = this._delegate;
105
114
  }
106
- this._setNativeClipToBounds();
107
- }
108
- setupDataSource() {
109
- // Important: cell's must be registered before creating the datasource
110
- // eg: they can *not* be created within the initWithCollectionViewCellProvider
111
- const templateKeys = this._itemTemplatesInternal.keys();
112
- for (const key of templateKeys) {
113
- // register cell for each template type
114
- this.cellRegistrations[key] = UICollectionViewCellRegistration.registrationWithCellClassConfigurationHandler(CollectionViewCell.class(), (view, indexPath, identifier) => {
115
- const templateType = this._getItemTemplateType(indexPath);
116
- // console.log('registrationWithCellClassConfigurationHandler templateType:', templateType)
117
- const cell = view;
118
- const firstRender = !cell.view;
119
- if (Trace.isEnabled()) {
120
- CLog(CLogTypes.log, 'cellProvider for row:', indexPath.row, ' templateType:', templateType);
121
- }
122
- this._prepareCell(cell, indexPath, templateType);
123
- // the cell layout will be called from NSCellView layoutSubviews
124
- const cellView = cell.view;
125
- if (!firstRender && cellView['isLayoutRequired']) {
126
- this.layoutCell(indexPath.row, cell, cellView);
127
- }
128
- return cell;
129
- });
130
- }
131
- this._dataSource = UICollectionViewDiffableDataSource.alloc().initWithCollectionViewCellProvider(this.nativeView, (view, indexPath, identifier) => {
132
- return this.nativeViewProtected.dequeueConfiguredReusableCellWithRegistrationForIndexPathItem(this.cellRegistrations[this._getItemTemplateType(indexPath)], indexPath, identifier);
133
- });
134
- this.setupHeaderFooter();
135
- if (!this.sections) {
136
- // every collectionview must have at least 1 section
137
- this.sections = [
138
- {
139
- identifier: getUUID(),
140
- key: 'default',
141
- },
142
- ];
143
- }
144
- if (this.items?.length) {
145
- this.refreshDataSourceSnapshot(this.getDefaultSectionIdentifier());
146
- }
147
- this.nativeView.dataSource = this._dataSource;
148
- }
149
- refreshDataSourceSnapshot(sectionIdentifier) {
150
- if (this.items) {
151
- this.modifyDataSourceSnapshot(ChangeType.Add, [], sectionIdentifier, false, true);
152
- }
153
- }
154
- modifyDataSourceSnapshot(type, identifiers, sectionIdentifier, animate = true, reload = false) {
155
- if (this.items) {
156
- if (!this._dataSourceSnapshot || reload) {
157
- this._dataSourceSnapshot = NSDiffableDataSourceSnapshot.alloc().init();
158
- this._dataSourceSnapshot.appendSectionsWithIdentifiers(this.sections.map((s) => s.identifier));
159
- }
160
- else {
161
- this._dataSourceSnapshot = this._dataSource.snapshot();
162
- }
163
- if (Trace.isEnabled()) {
164
- CLog(CLogTypes.info, 'modifyDataSourceSnapshot identifiers: ', type, identifiers);
165
- }
166
- // console.log('modifyDataSourceSnapshot identifiers: ', type, identifiers);
167
- switch (type) {
168
- case ChangeType.Add:
169
- const itemIdentifiers = [];
170
- if (reload) {
171
- this.items.forEach(() => {
172
- // forEach works well with ObservableArray and Array
173
- itemIdentifiers.push(getUUID());
174
- });
175
- }
176
- if (identifiers.length) {
177
- itemIdentifiers.push(...identifiers);
178
- }
179
- if (sectionIdentifier) {
180
- this._dataSourceSnapshot.appendItemsWithIdentifiersIntoSectionWithIdentifier(itemIdentifiers, sectionIdentifier);
181
- }
182
- else {
183
- this._dataSourceSnapshot.appendItemsWithIdentifiers(itemIdentifiers);
184
- }
185
- break;
186
- case ChangeType.Update:
187
- this._dataSourceSnapshot.reloadItemsWithIdentifiers(identifiers);
188
- break;
189
- case ChangeType.Delete:
190
- this._dataSourceSnapshot.deleteItemsWithIdentifiers(identifiers);
191
- break;
192
- }
193
- if (this.isAnimationEnabled) {
194
- this._dataSource.applySnapshotAnimatingDifferences(this._dataSourceSnapshot, this.loadingMore ? false : animate);
195
- }
196
- else {
197
- this._dataSource.applySnapshotUsingReloadData(this._dataSourceSnapshot);
198
- }
199
- }
200
- }
201
- getDefaultSectionIdentifier() {
202
- // each collectionview must have at least 1 section
203
- return this.sections[0].identifier;
204
- }
205
- setupHeaderFooter() {
206
- if (!this.headerKey) {
207
- // TODO: work on keyed header for multiple sections
208
- this.headerKey = ViewTemplateType.Header;
209
- }
210
- if (this.headerItemTemplate) {
211
- this.headerRegistration = UICollectionViewSupplementaryRegistration.registrationWithSupplementaryClassElementKindConfigurationHandler(CollectionViewCell.class(), this.headerKey, (cell, elementKind, indexPath) => {
212
- this._prepareHeaderFooter(cell, indexPath, this.headerKey, ViewTemplateType.Header);
213
- });
214
- }
215
- if (!this.footerKey) {
216
- // TODO: work on keyed footer for multiple sections
217
- this.footerKey = ViewTemplateType.Footer;
218
- }
219
- if (this.footerItemTemplate) {
220
- this.footerRegistration = UICollectionViewSupplementaryRegistration.registrationWithSupplementaryClassElementKindConfigurationHandler(CollectionViewCell.class(), this.footerKey, (cell, elementKind, indexPath) => {
221
- this._prepareHeaderFooter(cell, indexPath, this.footerKey, ViewTemplateType.Footer);
222
- });
223
- }
224
- if (this.headerItemTemplate || this.footerItemTemplate) {
225
- this._dataSource.supplementaryViewProvider = (view, elementKind, indexPath) => {
226
- if (this.headerRegistration && elementKind == this.headerKey) {
227
- return this.nativeViewProtected.dequeueConfiguredReusableSupplementaryViewWithRegistrationForIndexPath(this.headerRegistration, indexPath);
228
- }
229
- else if (this.footerRegistration) {
230
- return this.nativeViewProtected.dequeueConfiguredReusableSupplementaryViewWithRegistrationForIndexPath(this.footerRegistration, indexPath);
231
- }
232
- };
115
+ else if (this.autoSize) {
116
+ this._delegate = UICollectionViewDelegateImpl.initWithOwner(this);
117
+ this.nativeViewProtected.delegate = this._delegate;
233
118
  }
119
+ this._setNativeClipToBounds();
234
120
  }
235
121
  disposeNativeView() {
236
122
  if (Trace.isEnabled()) {
237
123
  CLog(CLogTypes.log, 'disposeNativeView');
238
124
  }
239
- const nativeView = this.nativeView;
125
+ const nativeView = this.nativeViewProtected;
240
126
  nativeView.delegate = null;
127
+ // nativeView.dragDelegate = null;
128
+ // nativeView.dropDelegate = null;
241
129
  this._delegate = null;
242
130
  nativeView.dataSource = null;
243
131
  this._dataSource = null;
@@ -254,6 +142,13 @@ export class CollectionView extends CollectionViewBase {
254
142
  get _childrenCount() {
255
143
  return this._map.size;
256
144
  }
145
+ onLoaded() {
146
+ super.onLoaded();
147
+ // we need refreshVisibleItems
148
+ // if some items were updated while unloaded they wont re layout
149
+ // after this (because we are not a Layout view)
150
+ this.refreshVisibleItems();
151
+ }
257
152
  eachChild(callback) {
258
153
  // used for css updates (like theme change)
259
154
  this._map.forEach((view) => {
@@ -267,12 +162,45 @@ export class CollectionView extends CollectionViewBase {
267
162
  }
268
163
  }
269
164
  });
165
+ // we need to call on measure cells too
166
+ // otherwise they would not get notified of some css changes
167
+ // like fontScale change
168
+ this._measureCellMap?.forEach((view) => {
169
+ callback(view.view);
170
+ });
171
+ }
172
+ async eachChildAsync(callback) {
173
+ // used for css updates (like theme change)
174
+ const children = [...this._map.values()];
175
+ for (let index = 0; index < children.length; index++) {
176
+ const view = children[index];
177
+ if (view.parent instanceof CollectionView) {
178
+ await callback(view);
179
+ }
180
+ else {
181
+ // in some cases (like item is unloaded from another place (like angular) view.parent becomes undefined)
182
+ if (view.parent) {
183
+ await callback(view.parent);
184
+ }
185
+ }
186
+ }
270
187
  }
271
188
  getViewForItemAtIndex(index) {
272
189
  let result;
273
190
  if (this.nativeViewProtected) {
191
+ // when the collectionview is not loaded anymore, cellForItemAtIndexPath wont return
192
+ // then we use our cached map to get the view
274
193
  const cell = this.nativeViewProtected.cellForItemAtIndexPath(NSIndexPath.indexPathForRowInSection(index, 0));
275
- return cell?.view;
194
+ if (cell) {
195
+ return cell?.view;
196
+ }
197
+ else {
198
+ for (const [cell, view] of this._map) {
199
+ if (cell.currentIndex === index) {
200
+ return view;
201
+ }
202
+ }
203
+ }
276
204
  }
277
205
  return result;
278
206
  }
@@ -341,13 +269,29 @@ export class CollectionView extends CollectionViewBase {
341
269
  return;
342
270
  }
343
271
  switch (gesture.state) {
344
- case 1 /* UIGestureRecognizerState.Began */:
345
- const selectedIndexPath = collectionView.indexPathForItemAtPoint(gesture.locationInView(collectionView));
272
+ case 1 /* UIGestureRecognizerState.Began */: {
273
+ let point = gesture.locationInView(collectionView);
274
+ const selectedIndexPath = collectionView.indexPathForItemAtPoint(point);
275
+ const view = this.getViewForItemAtIndex(selectedIndexPath.row);
276
+ if (view) {
277
+ const size = view.nativeViewProtected.bounds.size;
278
+ point = gesture.locationInView(view.nativeViewProtected);
279
+ this.draggingStartDelta = [point.x - size.width / 2, point.y - size.height / 2];
280
+ }
346
281
  collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath);
347
282
  break;
348
- case 2 /* UIGestureRecognizerState.Changed */:
349
- collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(collectionView));
283
+ }
284
+ case 2 /* UIGestureRecognizerState.Changed */: {
285
+ const point = gesture.locationInView(collectionView);
286
+ let x = point.x;
287
+ let y = point.y;
288
+ if (this.draggingStartDelta) {
289
+ x -= this.draggingStartDelta[0];
290
+ y -= this.draggingStartDelta[1];
291
+ }
292
+ collectionView.updateInteractiveMovementTargetPosition(CGPointMake(x, y));
350
293
  break;
294
+ }
351
295
  case 3 /* UIGestureRecognizerState.Ended */:
352
296
  collectionView.endInteractiveMovement();
353
297
  this.handleReorderEnd();
@@ -358,21 +302,27 @@ export class CollectionView extends CollectionViewBase {
358
302
  break;
359
303
  }
360
304
  }
305
+ // @ts-ignore
361
306
  [contentInsetAdjustmentBehaviorProperty.setNative](value) {
362
307
  this.nativeViewProtected.contentInsetAdjustmentBehavior = value;
363
308
  }
309
+ // @ts-ignore
364
310
  [paddingTopProperty.setNative](value) {
365
311
  this._setPadding({ top: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingTop) });
366
312
  }
313
+ // @ts-ignore
367
314
  [paddingRightProperty.setNative](value) {
368
315
  this._setPadding({ right: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingRight) });
369
316
  }
317
+ // @ts-ignore
370
318
  [paddingBottomProperty.setNative](value) {
371
319
  this._setPadding({ bottom: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingBottom) });
372
320
  }
321
+ // @ts-ignore
373
322
  [paddingLeftProperty.setNative](value) {
374
323
  this._setPadding({ left: Utils.layout.toDeviceIndependentPixels(this.effectivePaddingLeft) });
375
324
  }
325
+ // @ts-ignore
376
326
  [orientationProperty.setNative](value) {
377
327
  const layout = this._layout;
378
328
  if (layout instanceof UICollectionViewFlowLayout) {
@@ -385,20 +335,25 @@ export class CollectionView extends CollectionViewBase {
385
335
  }
386
336
  this.updateScrollBarVisibility(this.scrollBarIndicatorVisible);
387
337
  }
338
+ // @ts-ignore
388
339
  [isScrollEnabledProperty.setNative](value) {
389
340
  this.nativeViewProtected.scrollEnabled = value;
390
341
  this.scrollEnabledBeforeDragging = value;
391
342
  }
343
+ // @ts-ignore
392
344
  [isBounceEnabledProperty.setNative](value) {
393
345
  this.nativeViewProtected.bounces = value;
394
346
  // this.nativeViewProtected.alwaysBounceHorizontal = value;
395
347
  }
348
+ // @ts-ignore
396
349
  [itemTemplatesProperty.getDefault]() {
397
350
  return null;
398
351
  }
352
+ // @ts-ignore
399
353
  [reverseLayoutProperty.setNative](value) {
400
354
  this.nativeViewProtected.transform = value ? CGAffineTransformMakeRotation(-Math.PI) : null;
401
355
  }
356
+ // @ts-ignore
402
357
  [reorderLongPressEnabledProperty.setNative](value) {
403
358
  if (value) {
404
359
  if (!this.reorderLongPressGesture) {
@@ -416,6 +371,7 @@ export class CollectionView extends CollectionViewBase {
416
371
  }
417
372
  }
418
373
  }
374
+ // @ts-ignore
419
375
  [reorderingEnabledProperty.setNative](value) {
420
376
  if (value) {
421
377
  this.on('touch', this.onReorderingTouch, this);
@@ -424,9 +380,11 @@ export class CollectionView extends CollectionViewBase {
424
380
  this.off('touch', this.onReorderingTouch, this);
425
381
  }
426
382
  }
383
+ // @ts-ignore
427
384
  [scrollBarIndicatorVisibleProperty.getDefault]() {
428
385
  return true;
429
386
  }
387
+ // @ts-ignore
430
388
  [scrollBarIndicatorVisibleProperty.setNative](value) {
431
389
  this.updateScrollBarVisibility(value);
432
390
  }
@@ -448,6 +406,10 @@ export class CollectionView extends CollectionViewBase {
448
406
  }
449
407
  onLayout(left, top, right, bottom) {
450
408
  super.onLayout(left, top, right, bottom);
409
+ const layoutView = this.nativeViewProtected?.collectionViewLayout;
410
+ if (!layoutView) {
411
+ return;
412
+ }
451
413
  const p = CollectionViewBase.plugins[this.layoutStyle];
452
414
  if (p && p.onLayout) {
453
415
  p.onLayout(this, left, top, right, bottom);
@@ -456,10 +418,6 @@ export class CollectionView extends CollectionViewBase {
456
418
  const p = CollectionViewBase.plugins[k];
457
419
  p.onLayout && p.onLayout(this, left, top, right, bottom);
458
420
  });
459
- const layoutView = this.nativeViewProtected.collectionViewLayout;
460
- if (!layoutView) {
461
- return;
462
- }
463
421
  if (!this._delegate) {
464
422
  const layoutStyle = CollectionViewBase.layoutStyles[this.layoutStyle];
465
423
  if (layoutStyle && layoutStyle.createDelegate) {
@@ -479,25 +437,66 @@ export class CollectionView extends CollectionViewBase {
479
437
  // this._delegate._owner = new WeakRef(this);
480
438
  this.nativeViewProtected.delegate = this._delegate;
481
439
  }
440
+ this.updateRowColSize();
441
+ // there is no need to call refresh if it was triggered before with same size.
442
+ // this refresh is just to handle size change
443
+ const layoutKey = this._innerWidth + '_' + this._innerHeight;
444
+ if (this._lastLayoutKey !== layoutKey) {
445
+ this.refresh();
446
+ }
447
+ }
448
+ updateRowColSize() {
449
+ const layoutView = this.nativeViewProtected?.collectionViewLayout;
482
450
  if (layoutView instanceof UICollectionViewFlowLayout) {
483
451
  if (this._effectiveRowHeight && this._effectiveColWidth) {
484
452
  layoutView.itemSize = CGSizeMake(Utils.layout.toDeviceIndependentPixels(this._effectiveColWidth), Utils.layout.toDeviceIndependentPixels(this._effectiveRowHeight));
485
453
  }
486
- else {
454
+ else if (this.estimatedItemSize && !this.autoSize) {
487
455
  layoutView.estimatedItemSize = CGSizeMake(Utils.layout.toDeviceIndependentPixels(this._effectiveColWidth), Utils.layout.toDeviceIndependentPixels(this._effectiveRowHeight));
488
456
  }
457
+ layoutView.invalidateLayout();
489
458
  }
490
- layoutView.invalidateLayout();
491
- // there is no need to call refresh if it was triggered before with same size.
492
- // this refresh is just to handle size change
493
- const layoutKey = this._innerWidth + '_' + this._innerHeight;
494
- if (this._lastLayoutKey !== layoutKey) {
495
- this.refresh();
496
- }
459
+ }
460
+ _onRowHeightPropertyChanged(oldValue, newValue) {
461
+ this.updateRowColSize();
462
+ this.refresh();
463
+ }
464
+ _onColWidthPropertyChanged(oldValue, newValue) {
465
+ this.updateRowColSize();
466
+ this.refresh();
497
467
  }
498
468
  isHorizontal() {
499
469
  return this.orientation === 'horizontal';
500
470
  }
471
+ clearCachedSize(...indexes) {
472
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
473
+ if (sizes) {
474
+ indexes.forEach((index) => {
475
+ if (index < sizes.count) {
476
+ sizes.replaceObjectAtIndexWithObject(index, NSValue.valueWithCGSize(CGSizeZero));
477
+ }
478
+ });
479
+ }
480
+ }
481
+ layoutAttributesForElementsInRect(attributesArray, rect) {
482
+ if (this.itemOverlap) {
483
+ let currentDeltaX = 0;
484
+ let currentDeltaY = 0;
485
+ for (let index = 0; index < attributesArray.count; index++) {
486
+ const attributes = attributesArray.objectAtIndex(index);
487
+ if (attributes.representedElementCategory === 0 /* UICollectionElementCategory.Cell */) {
488
+ const row = attributes.indexPath.row;
489
+ if (this.itemOverlap) {
490
+ attributes.zIndex = row;
491
+ }
492
+ const itemOverlap = this.itemOverlap(this.getItemAtIndex(row), row);
493
+ currentDeltaX += Utils.layout.toDeviceIndependentPixels(Length.toDevicePixels(itemOverlap[1], 0) + Length.toDevicePixels(itemOverlap[3], 0));
494
+ currentDeltaY += Utils.layout.toDeviceIndependentPixels(Length.toDevicePixels(itemOverlap[0], 0) + Length.toDevicePixels(itemOverlap[2], 0));
495
+ attributes.center = CGPointMake(attributes.center.x + currentDeltaX, attributes.center.y + currentDeltaY);
496
+ }
497
+ }
498
+ }
499
+ }
501
500
  onSourceCollectionChanged(event) {
502
501
  const view = this.nativeViewProtected;
503
502
  if (!view || this._dataUpdatesSuspended || !this._lastLayoutKey) {
@@ -506,97 +505,132 @@ export class CollectionView extends CollectionViewBase {
506
505
  if (Trace.isEnabled()) {
507
506
  CLog(CLogTypes.log, 'onItemsChanged', ChangeType.Update, event.action, event.index, event.addedCount, event.removed && event.removed.length);
508
507
  }
509
- // console.log('----')
510
- // console.log('event.action:', event.action)
511
- // console.log('event.addedCount:', event.addedCount);
512
- // console.log('event.removed:', event.removed);
513
- // console.log('event.index:', event.index)
514
- // console.log(' >')
515
- const sectionIdentifier = this._dataSource.sectionIdentifierForIndex(0);
516
- // console.log(' sectionIdentifier:', sectionIdentifier)
517
- const contentOffset = view.contentOffset;
508
+ // we need to clear stored cell sizes and it wont be correct anymore
509
+ // this.clearCellSize();
510
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
511
+ const performBatchUpdatesCompletion = (c) => {
512
+ // if we are not "presented" (viewController hidden) then performBatchUpdatesCompletion would crash
513
+ const viewIsLoaded = !!this.page?.viewController ? !!this.page.viewController.view.window : true;
514
+ if (viewIsLoaded) {
515
+ view.performBatchUpdatesCompletion(c, null);
516
+ }
517
+ else {
518
+ this.refresh();
519
+ }
520
+ };
518
521
  switch (event.action) {
519
522
  case ChangeType.Delete: {
520
- const deleteIdentifiers = [];
523
+ const indexes = NSMutableArray.new();
521
524
  for (let index = 0; index < event.addedCount; index++) {
522
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index + index, sectionIdentifier);
523
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath);
524
- // console.log(' delete identifier:', identifier)
525
- deleteIdentifiers.push(identifier);
525
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index + index, 0));
526
+ if (sizes) {
527
+ sizes.removeObjectAtIndex(event.index);
528
+ }
526
529
  }
530
+ // this._sizes.splice(event.index, event.addedCount);
527
531
  this.unbindUnusedCells(event.removed);
528
- this.modifyDataSourceSnapshot(ChangeType.Delete, deleteIdentifiers, sectionIdentifier);
532
+ if (Trace.isEnabled()) {
533
+ CLog(CLogTypes.info, 'deleteItemsAtIndexPaths', indexes.count);
534
+ }
535
+ performBatchUpdatesCompletion(() => {
536
+ view.deleteItemsAtIndexPaths(indexes);
537
+ });
529
538
  return;
530
539
  }
531
540
  case ChangeType.Update: {
532
- const updateIdentifiers = [];
533
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index, sectionIdentifier);
534
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath);
535
- // console.log(' update identifier:', identifier)
536
- updateIdentifiers.push(identifier);
537
- this.modifyDataSourceSnapshot(ChangeType.Update, updateIdentifiers, sectionIdentifier);
541
+ const indexes = NSMutableArray.new();
542
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index, 0));
543
+ if (sizes && event.index < sizes.count) {
544
+ sizes.replaceObjectAtIndexWithObject(event.index, NSValue.valueWithCGSize(CGSizeZero));
545
+ }
546
+ // this._sizes[event.index] = null;
547
+ if (Trace.isEnabled()) {
548
+ CLog(CLogTypes.info, 'reloadItemsAtIndexPaths', event.index, indexes.count);
549
+ }
550
+ performBatchUpdatesCompletion(() => {
551
+ view.reloadItemsAtIndexPaths(indexes);
552
+ });
538
553
  return;
539
554
  }
540
555
  case ChangeType.Add: {
541
- const addIdentifiers = [];
556
+ const indexes = NSMutableArray.new();
542
557
  for (let index = 0; index < event.addedCount; index++) {
543
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index + index, sectionIdentifier);
544
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath) || getUUID();
545
- // console.log(' add identifier:', identifier)
546
- addIdentifiers.push(identifier);
558
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index + index, 0));
559
+ if (sizes) {
560
+ sizes.insertObjectAtIndex(NSValue.valueWithCGSize(CGSizeZero), event.index);
561
+ }
562
+ // this._sizes.splice(index, 0, null);
547
563
  }
548
- this.modifyDataSourceSnapshot(ChangeType.Add, addIdentifiers, sectionIdentifier);
564
+ if (Trace.isEnabled()) {
565
+ CLog(CLogTypes.info, 'insertItemsAtIndexPaths', indexes.count);
566
+ }
567
+ performBatchUpdatesCompletion(() => {
568
+ view.insertItemsAtIndexPaths(indexes);
569
+ });
549
570
  return;
550
571
  }
551
572
  case ChangeType.Splice: {
552
- const added = event.addedCount;
553
- const removed = (event.removed && event.removed.length) || 0;
554
- if (added > 0 && added === removed) {
555
- const spliceIdentifiers = [];
556
- for (let index = 0; index < added; index++) {
557
- const indexPath = NSIndexPath.indexPathForRowInSection(event.index + index, sectionIdentifier);
558
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath) || getUUID();
559
- // console.log(' splice, update identifier:', identifier)
560
- spliceIdentifiers.push(identifier);
561
- }
562
- this.modifyDataSourceSnapshot(ChangeType.Update, spliceIdentifiers, sectionIdentifier);
563
- }
564
- else {
565
- if (event.removed && event.removed.length > 0) {
566
- const removeIdentifiers = [];
567
- for (let index = 0; index < event.removed.length; index++) {
568
- const indexPath = NSIndexPath.indexPathForItemInSection(event.index + index, sectionIdentifier);
569
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath);
570
- // console.log(' splice, remove identifier:', identifier)
571
- removeIdentifiers.push(identifier);
573
+ performBatchUpdatesCompletion(() => {
574
+ const added = event.addedCount;
575
+ const removed = (event.removed && event.removed.length) || 0;
576
+ if (added > 0 && added === removed) {
577
+ const indexes = NSMutableArray.new();
578
+ for (let index = 0; index < added; index++) {
579
+ indexes.addObject(NSIndexPath.indexPathForRowInSection(event.index + index, 0));
580
+ if (sizes && event.index + index < sizes.count) {
581
+ sizes.replaceObjectAtIndexWithObject(event.index + index, NSValue.valueWithCGSize(CGSizeZero));
582
+ }
583
+ // this._sizes[event.index + index] = null;
572
584
  }
573
- this.unbindUnusedCells(event.removed);
574
- this.modifyDataSourceSnapshot(ChangeType.Delete, removeIdentifiers, sectionIdentifier);
585
+ view.reloadItemsAtIndexPaths(indexes);
575
586
  }
576
- if (event.addedCount > 0) {
577
- const identifiers = [];
578
- for (let index = 0; index < event.addedCount; index++) {
579
- const indexPath = NSIndexPath.indexPathForItemInSection(event.index + index, sectionIdentifier);
580
- const identifier = this._dataSource.itemIdentifierForIndexPath(indexPath) || getUUID();
581
- // console.log(' splice, add identifier:', identifier)
582
- identifiers.push(identifier);
587
+ else {
588
+ if (event.removed && event.removed.length > 0) {
589
+ const indexes = NSMutableArray.new();
590
+ for (let index = 0; index < event.removed.length; index++) {
591
+ indexes.addObject(NSIndexPath.indexPathForItemInSection(event.index + index, 0));
592
+ if (sizes) {
593
+ sizes.removeObjectAtIndex(event.index);
594
+ }
595
+ }
596
+ // this._sizes.splice(event.index, event.removed.length);
597
+ this.unbindUnusedCells(event.removed);
598
+ if (Trace.isEnabled()) {
599
+ CLog(CLogTypes.info, 'deleteItemsAtIndexPaths', indexes.count);
600
+ }
601
+ view.deleteItemsAtIndexPaths(indexes);
602
+ }
603
+ if (event.addedCount > 0) {
604
+ const indexes = NSMutableArray.alloc().init();
605
+ for (let index = 0; index < event.addedCount; index++) {
606
+ indexes.addObject(NSIndexPath.indexPathForItemInSection(event.index + index, 0));
607
+ if (sizes) {
608
+ sizes.insertObjectAtIndex(NSValue.valueWithCGSize(CGSizeZero), event.index);
609
+ }
610
+ // this._sizes.splice(event.index, 0, null);
611
+ }
612
+ if (Trace.isEnabled()) {
613
+ CLog(CLogTypes.info, 'insertItemsAtIndexPaths', indexes.count);
614
+ }
615
+ view.insertItemsAtIndexPaths(indexes);
583
616
  }
584
- this.modifyDataSourceSnapshot(ChangeType.Add, identifiers, sectionIdentifier);
585
617
  }
586
- }
587
- // view.collectionViewLayout.invalidateLayout();
588
- break;
618
+ // view.collectionViewLayout.invalidateLayout();
619
+ });
620
+ return;
589
621
  }
590
622
  }
591
- // this.refresh();
592
- view.contentOffset = contentOffset;
593
- this.loadingMore = false;
623
+ this.refresh();
594
624
  }
595
- clearEmbeddedViews() {
596
- this.clearRealizedCells();
597
- // if (this.itemViewDisposer !== undefined) {
598
- // this.itemViewDisposer();
599
- // }
625
+ onItemTemplatesChanged(oldValue, newValue) {
626
+ super.onItemTemplatesChanged(oldValue, newValue);
627
+ if (!this.nativeViewProtected) {
628
+ return;
629
+ }
630
+ const view = this.nativeViewProtected;
631
+ this._itemTemplatesInternal.forEach((t) => {
632
+ view.registerClassForCellWithReuseIdentifier(CollectionViewCell.class(), t.key.toLowerCase());
633
+ });
600
634
  }
601
635
  unbindUnusedCells(removedDataItems) {
602
636
  this._map.forEach((view, nativeView, map) => {
@@ -613,7 +647,16 @@ export class CollectionView extends CollectionViewBase {
613
647
  if (!view) {
614
648
  return;
615
649
  }
650
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
616
651
  const visibles = view.indexPathsForVisibleItems;
652
+ if (sizes) {
653
+ const indexes = Array.from(visibles);
654
+ indexes.forEach((value) => {
655
+ if (value.row < sizes.count) {
656
+ sizes.replaceObjectAtIndexWithObject(value.row, NSValue.valueWithCGSize(CGSizeZero));
657
+ }
658
+ });
659
+ }
617
660
  UIView.performWithoutAnimation(() => {
618
661
  view.performBatchUpdatesCompletion(() => {
619
662
  view.reloadItemsAtIndexPaths(visibles);
@@ -628,6 +671,25 @@ export class CollectionView extends CollectionViewBase {
628
671
  const indexes = Array.from(view.indexPathsForVisibleItems);
629
672
  return indexes.some((visIndex) => visIndex.row === itemIndex);
630
673
  }
674
+ findFirstVisibleItemIndex() {
675
+ const view = this.nativeViewProtected;
676
+ if (!view) {
677
+ return -1;
678
+ }
679
+ return this.getRowIndexPath(view)[0] ?? -1;
680
+ }
681
+ findLastVisibleItemIndex() {
682
+ const view = this.nativeViewProtected;
683
+ if (!view) {
684
+ return -1;
685
+ }
686
+ return this.getRowIndexPath(view).at(-1) ?? -1;
687
+ }
688
+ getRowIndexPath(view) {
689
+ return Array.from(view.indexPathsForVisibleItems)
690
+ .map((e) => e.row)
691
+ .sort((a, b) => a - b);
692
+ }
631
693
  refresh() {
632
694
  if (!this.isLoaded || !this.nativeView) {
633
695
  this._isDataDirty = true;
@@ -638,13 +700,18 @@ export class CollectionView extends CollectionViewBase {
638
700
  if (Trace.isEnabled()) {
639
701
  CLog(CLogTypes.info, 'refresh');
640
702
  }
703
+ // we need to clear stored cell sizes and it wont be correct anymore
704
+ // this.clearCellSize();
705
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
706
+ if (sizes) {
707
+ sizes.removeAllObjects();
708
+ }
641
709
  // clear bindingContext when it is not observable because otherwise bindings to items won't reevaluate
642
710
  this._map.forEach((view, nativeView, map) => {
643
711
  if (!(view.bindingContext instanceof Observable)) {
644
712
  view.bindingContext = null;
645
713
  }
646
714
  });
647
- this.refreshDataSourceSnapshot(this.getDefaultSectionIdentifier());
648
715
  // TODO: this is ugly look here: https://github.com/nativescript-vue/nativescript-vue/issues/525
649
716
  // this.clearRealizedCells();
650
717
  // dispatch_async(main_queue, () => {
@@ -663,8 +730,38 @@ export class CollectionView extends CollectionViewBase {
663
730
  get verticalOffsetY() {
664
731
  return this.nativeViewProtected?.contentOffset.y || 0;
665
732
  }
666
- scrollToIndex(index, animated = true) {
667
- this.nativeViewProtected.scrollToItemAtIndexPathAtScrollPositionAnimated(NSIndexPath.indexPathForItemInSection(index, 0), this.orientation === 'vertical' ? 1 /* UICollectionViewScrollPosition.Top */ : 8 /* UICollectionViewScrollPosition.Left */, animated);
733
+ scrollToIndex(index, animated = true, snap = SnapPosition.START) {
734
+ const nativeView = this.nativeViewProtected;
735
+ if (!nativeView) {
736
+ return;
737
+ }
738
+ const nbItems = nativeView.numberOfItemsInSection(0);
739
+ if (nbItems > 0 && index < nbItems) {
740
+ let scrollPosition = 1 /* UICollectionViewScrollPosition.Top */;
741
+ if (this.orientation === 'vertical') {
742
+ scrollPosition = snap === SnapPosition.START ? 1 /* UICollectionViewScrollPosition.Top */ : 4 /* UICollectionViewScrollPosition.Bottom */;
743
+ }
744
+ else {
745
+ scrollPosition = snap === SnapPosition.START ? 8 /* UICollectionViewScrollPosition.Left */ : 32 /* UICollectionViewScrollPosition.Right */;
746
+ }
747
+ nativeView.scrollToItemAtIndexPathAtScrollPositionAnimated(NSIndexPath.indexPathForItemInSection(index, 0), scrollPosition, animated);
748
+ }
749
+ }
750
+ scrollToOffset(value, animated) {
751
+ const view = this.nativeViewProtected;
752
+ if (view && this.isScrollEnabled) {
753
+ const { width, height } = view.bounds.size;
754
+ let rect;
755
+ if (this.orientation === 'vertical') {
756
+ rect = CGRectMake(0, value, width, height);
757
+ }
758
+ else {
759
+ rect = CGRectMake(value, 0, width, height);
760
+ }
761
+ if (rect) {
762
+ view.scrollRectToVisibleAnimated(rect, animated);
763
+ }
764
+ }
668
765
  }
669
766
  requestLayout() {
670
767
  // When preparing cell don't call super - no need to invalidate our measure when cell desiredSize is changed.
@@ -681,64 +778,17 @@ export class CollectionView extends CollectionViewBase {
681
778
  return args;
682
779
  }
683
780
  _getItemTemplateType(indexPath) {
684
- return (this._itemTemplateSelector ? this._itemTemplateSelector.call(this, this.getItemAtIndex(indexPath.row), indexPath.row, this.items) : this._defaultTemplate.key).toLowerCase();
685
- }
686
- disableIosOverflowSafeArea(parentView) {
687
- if (parentView) {
688
- parentView.iosOverflowSafeAreaEnabled = false;
781
+ const selector = this._itemTemplateSelector;
782
+ let type = this._defaultTemplate.key;
783
+ if (selector) {
784
+ type = selector.call(this, this.getItemAtIndex(indexPath.item), indexPath.item, this.items);
689
785
  }
786
+ return type.toLowerCase();
690
787
  }
691
- _prepareHeaderFooter(cell, indexPath, templateKey, templateType, notForCellSizeComp = true) {
692
- let cellSize;
693
- try {
694
- this._preparingCell = true;
695
- const firstRender = !cell.view;
696
- let view = cell.view;
697
- const index = indexPath.row;
698
- if (!view) {
699
- view = this.getViewForTemplateType(templateKey, templateType);
700
- }
701
- if (Trace.isEnabled()) {
702
- CLog(CLogTypes.log, '_prepareHeaderFooter', index, templateType, !!cell.view, !!view, cell.view !== view, notForCellSizeComp);
703
- }
704
- if (view) {
705
- if (firstRender) {
706
- view['iosIgnoreSafeArea'] = true;
707
- }
708
- view.bindingContext = this.bindingContext;
709
- if (view instanceof ProxyViewContainer) {
710
- const sp = new ContentView();
711
- sp.content = view;
712
- view = sp;
713
- }
714
- if (!cell.view) {
715
- cell.owner = new WeakRef(view);
716
- }
717
- else if (cell.view !== view) {
718
- this._removeContainer(cell);
719
- if (cell.view?.nativeViewProtected) {
720
- cell.view.nativeViewProtected.removeFromSuperview();
721
- }
722
- cell.owner = new WeakRef(view);
723
- }
724
- cell.currentIndex = indexPath.row;
725
- if (view && !view.parent) {
726
- this._addView(view);
727
- const innerView = NSCellView.new();
728
- innerView.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */;
729
- innerView.view = new WeakRef(view);
730
- innerView.addSubview(view.nativeViewProtected);
731
- cell.addSubview(innerView);
732
- }
733
- cellSize = this.measureCell(cell, view, indexPath.row);
734
- }
735
- }
736
- finally {
737
- this._preparingCell = false;
738
- }
739
- return cellSize;
788
+ getItemTemplateContent(index, templateType) {
789
+ return this.getViewForViewType(ListViewViewTypes.ItemView, templateType);
740
790
  }
741
- _prepareCell(cell, indexPath, templateKey, notForCellSizeComp = true) {
791
+ _prepareCell(cell, indexPath, templateType, notForCellSizeComp = true) {
742
792
  let cellSize;
743
793
  try {
744
794
  this._preparingCell = true;
@@ -746,11 +796,11 @@ export class CollectionView extends CollectionViewBase {
746
796
  let view = cell.view;
747
797
  const index = indexPath.row;
748
798
  if (!view) {
749
- view = this.getViewForTemplateType(templateKey);
799
+ view = this.getItemTemplateContent(index, templateType);
750
800
  }
751
801
  const bindingContext = this._prepareItem(view, index);
752
802
  if (Trace.isEnabled()) {
753
- CLog(CLogTypes.log, '_prepareCell', index, templateKey, !!cell.view, !!view, cell.view !== view, notForCellSizeComp);
803
+ CLog(CLogTypes.log, '_prepareCell', index, templateType, !!cell.view, !!view, cell.view !== view, notForCellSizeComp);
754
804
  }
755
805
  const args = this.notifyForItemAtIndex(CollectionViewBase.itemLoadingEvent, view, indexPath.row, bindingContext, cell);
756
806
  view = args.view;
@@ -768,7 +818,7 @@ export class CollectionView extends CollectionViewBase {
768
818
  }
769
819
  else if (cell.view !== view) {
770
820
  this._removeContainer(cell);
771
- if (cell.view?.nativeViewProtected) {
821
+ if (cell.view.nativeViewProtected) {
772
822
  cell.view.nativeViewProtected.removeFromSuperview();
773
823
  }
774
824
  cell.owner = new WeakRef(view);
@@ -782,21 +832,29 @@ export class CollectionView extends CollectionViewBase {
782
832
  const innerView = NSCellView.new();
783
833
  innerView.autoresizingMask = 2 /* UIViewAutoresizing.FlexibleWidth */ | 16 /* UIViewAutoresizing.FlexibleHeight */;
784
834
  innerView.view = new WeakRef(view);
785
- // if (notForCellSizeComp && this.autoReloadItemOnLayout) {
786
- // // for a cell to update correctly on cell layout change we need
787
- // // to do it ourself instead of "propagating it"
788
- // view['performLayout'] = () => {
789
- // if (!this._preparingCell) {
790
- // const index = cell.currentIndex;
791
- // const nativeView = this.nativeViewProtected;
792
- // nativeView.performBatchUpdatesCompletion(() => {
793
- // this.measureCell(cell, view, index);
794
- // this.notifyForItemAtIndex(CollectionViewBase.itemLoadingEvent, view, indexPath.row, view.bindingContext, cell);
795
- // }, null);
796
- // nativeView.collectionViewLayout.invalidateLayout();
797
- // }
798
- // };
799
- // }
835
+ if (notForCellSizeComp && this.autoReloadItemOnLayout) {
836
+ // for a cell to update correctly on cell layout change we need
837
+ // to do it ourself instead of "propagating it"
838
+ view['performLayout'] = () => {
839
+ if (!this._preparingCell && !view['inPerformLayout']) {
840
+ view['inPerformLayout'] = true;
841
+ const index = cell.currentIndex;
842
+ const nativeView = this.nativeViewProtected;
843
+ const sizes = this._delegate instanceof UICollectionViewDelegateImpl ? this._delegate.cachedSizes : null;
844
+ if (sizes && index < sizes.count) {
845
+ sizes.replaceObjectAtIndexWithObject(index, NSValue.valueWithCGSize(CGSizeZero));
846
+ }
847
+ nativeView.performBatchUpdatesCompletion(() => {
848
+ this.notifyForItemAtIndex(CollectionViewBase.itemLoadingEvent, view, indexPath.row, view.bindingContext, cell);
849
+ // the order is important because measureCell will set layout as requested and notifyForItemAtIndex would call requestLayout => endless loop
850
+ this.measureCell(cell, view, index);
851
+ cell.contentView.subviews.objectAtIndex(0)?.layoutSubviews();
852
+ // nativeView.collectionViewLayout.invalidateLayout();
853
+ }, null);
854
+ view['inPerformLayout'] = false;
855
+ }
856
+ };
857
+ }
800
858
  innerView.addSubview(view.nativeViewProtected);
801
859
  cell.contentView.addSubview(innerView);
802
860
  }
@@ -814,6 +872,7 @@ export class CollectionView extends CollectionViewBase {
814
872
  return cellSize;
815
873
  }
816
874
  getCellSize(index) {
875
+ // let result = this._sizes[index];
817
876
  let result;
818
877
  // CLog(CLogTypes.log, 'getCellSize', index, result, this._effectiveColWidth, this._effectiveRowHeight, this.getMeasuredWidth(), this.getMeasuredHeight());
819
878
  if (!result) {
@@ -843,6 +902,12 @@ export class CollectionView extends CollectionViewBase {
843
902
  // return undefined;
844
903
  return result;
845
904
  }
905
+ // public storeCellSize(index: number, value) {
906
+ // this._sizes[index] = value;
907
+ // }
908
+ // public clearCellSize() {
909
+ // this._sizes = new Array<number[]>();
910
+ // }
846
911
  measureCell(cell, cellView, position) {
847
912
  if (cellView) {
848
913
  let width = this._effectiveColWidth;
@@ -858,10 +923,10 @@ export class CollectionView extends CollectionViewBase {
858
923
  width *= spanSize;
859
924
  }
860
925
  }
861
- const widthMeasureSpec = width ? Utils.layout.makeMeasureSpec(width, Utils.layout.EXACTLY) : horizontal ? infinity : Utils.layout.makeMeasureSpec(this._innerWidth, Utils.layout.UNSPECIFIED);
862
- const heightMeasureSpec = height ? Utils.layout.makeMeasureSpec(height, Utils.layout.EXACTLY) : horizontal ? Utils.layout.makeMeasureSpec(this._innerHeight, Utils.layout.UNSPECIFIED) : infinity;
926
+ const widthMeasureSpec = width ? Utils.layout.makeMeasureSpec(width, Utils.layout.EXACTLY) : horizontal ? infinity : Utils.layout.makeMeasureSpec(this._innerWidth, Utils.layout.EXACTLY);
927
+ const heightMeasureSpec = height ? Utils.layout.makeMeasureSpec(height, Utils.layout.EXACTLY) : horizontal ? Utils.layout.makeMeasureSpec(this._innerHeight, Utils.layout.EXACTLY) : infinity;
863
928
  if (Trace.isEnabled()) {
864
- CLog(CLogTypes.log, 'measureCell', position, width, height, widthMeasureSpec, heightMeasureSpec);
929
+ CLog(CLogTypes.log, 'measureCell', position, width, height, this._innerWidth, this._innerHeight, widthMeasureSpec, heightMeasureSpec);
865
930
  }
866
931
  const measuredSize = View.measureChild(this, cellView, widthMeasureSpec, heightMeasureSpec);
867
932
  const result = [measuredSize.measuredWidth, measuredSize.measuredHeight];
@@ -895,6 +960,7 @@ export class CollectionView extends CollectionViewBase {
895
960
  }
896
961
  _removeContainer(cell) {
897
962
  const view = cell.view;
963
+ this.notifyForItemAtIndex(CollectionViewBase.itemDisposingEvent, view, cell.currentIndex, view.bindingContext, cell);
898
964
  // This is to clear the StackLayout that is used to wrap ProxyViewContainer instances.
899
965
  if (!(view.parent instanceof CollectionView)) {
900
966
  this._removeView(view.parent);
@@ -908,15 +974,18 @@ export class CollectionView extends CollectionViewBase {
908
974
  }
909
975
  _setPadding(newPadding) {
910
976
  const layout = this._layout;
911
- const padding = {
912
- top: layout['sectionInset']?.top || 0,
913
- right: layout['sectionInset']?.right || 0,
914
- bottom: layout['sectionInset']?.bottom || 0,
915
- left: layout['sectionInset']?.left || 0,
916
- };
917
- // tslint:disable-next-line:prefer-object-spread
918
- const newValue = Object.assign(padding, newPadding);
919
- layout['sectionInset'] = newValue;
977
+ // Need to guard sectionInset when using custom layouts
978
+ if (layout && layout['sectionInset']) {
979
+ const padding = {
980
+ top: layout['sectionInset'].top,
981
+ right: layout['sectionInset'].right,
982
+ bottom: layout['sectionInset'].bottom,
983
+ left: layout['sectionInset'].left,
984
+ };
985
+ // tslint:disable-next-line:prefer-object-spread
986
+ const newValue = Object.assign(padding, newPadding);
987
+ layout['sectionInset'] = newValue;
988
+ }
920
989
  }
921
990
  numberOfSectionsInCollectionView(collectionView) {
922
991
  if (!this._lastLayoutKey) {
@@ -933,6 +1002,12 @@ export class CollectionView extends CollectionViewBase {
933
1002
  if (!cell) {
934
1003
  cell = CollectionViewCell.new();
935
1004
  }
1005
+ if (this.itemOverlap) {
1006
+ // should we force clipsToBounds? not doing so allows more complex layouts like overlapping
1007
+ // we set zPosition to allow overlap. Should we make it an option?
1008
+ cell.layer.zPosition = indexPath.row;
1009
+ }
1010
+ cell.clipsToBounds = true;
936
1011
  const firstRender = !cell.view;
937
1012
  if (Trace.isEnabled()) {
938
1013
  CLog(CLogTypes.log, 'collectionViewCellForItemAtIndexPath', indexPath.row, templateType, !!cell.view, cell);
@@ -943,30 +1018,10 @@ export class CollectionView extends CollectionViewBase {
943
1018
  if (!firstRender && cellView['isLayoutRequired']) {
944
1019
  this.layoutCell(indexPath.row, cell, cellView);
945
1020
  }
1021
+ // if the cell view is a canvas we need to ensure redraw is called
1022
+ (cellView.content || cellView).nativeViewProtected.setNeedsDisplay();
946
1023
  return cell;
947
1024
  }
948
- // collectionViewViewForSupplementaryElementOfKindAtIndexPath(view: UICollectionView, kind: string, indexPath: NSIndexPath): UICollectionReusableView {
949
- // // const templateType = kind === UICollectionElementKindSectionHeader ? this._headerTemplate.key : this._footerTemplate.key;
950
- // const templateType = kind;
951
- // console.log('templateType:', templateType)
952
- // // let cell = collectionView.dequeueConfiguredReusableSupplementaryViewWithRegistrationForIndexPath(kind, templateType, indexPath) as CollectionViewReusableView;
953
- // let cell = this._dataSource.supplementaryViewProvider(view, kind, indexPath);
954
- // console.log('cell:', cell)
955
- // // if (!cell) {
956
- // // cell = CollectionViewReusableView.new() as CollectionViewReusableView;
957
- // // }
958
- // // const firstRender = !cell.view;
959
- // // if (Trace.isEnabled()) {
960
- // // CLog(CLogTypes.log, 'collectionViewViewForSupplementaryElementOfKindAtIndexPath', indexPath.row, templateType, !!cell.view, cell);
961
- // // }
962
- // // this._prepareHeaderFooter(cell, indexPath, templateType);
963
- // // the cell layout will be called from NSCellView layoutSubviews
964
- // // const cellView: View = cell.view;
965
- // // if (!firstRender && cellView['isLayoutRequired']) {
966
- // // this.layoutCell(indexPath.row, cell, cellView);
967
- // // }
968
- // return cell;
969
- // }
970
1025
  collectionViewWillDisplayCellForItemAtIndexPath(collectionView, cell, indexPath) {
971
1026
  if (this.reverseLayout) {
972
1027
  cell.transform = CGAffineTransformMakeRotation(-Math.PI);
@@ -974,7 +1029,6 @@ export class CollectionView extends CollectionViewBase {
974
1029
  if (this.items) {
975
1030
  const loadMoreItemIndex = this.items.length - this.loadMoreThreshold;
976
1031
  if (indexPath.row === loadMoreItemIndex && this.hasListeners(CollectionViewBase.loadMoreItemsEvent)) {
977
- this.loadingMore = true;
978
1032
  this.notify({
979
1033
  eventName: CollectionViewBase.loadMoreItemsEvent,
980
1034
  object: this,
@@ -985,8 +1039,6 @@ export class CollectionView extends CollectionViewBase {
985
1039
  this.notify({
986
1040
  eventName: CollectionViewBase.displayItemEvent,
987
1041
  index: indexPath.row,
988
- item: null,
989
- view: cell.view,
990
1042
  object: this,
991
1043
  });
992
1044
  }
@@ -996,19 +1048,6 @@ export class CollectionView extends CollectionViewBase {
996
1048
  if (cell.layoutMargins) {
997
1049
  cell.layoutMargins = UIEdgeInsetsZero;
998
1050
  }
999
- this._visibleCells.add(cell);
1000
- }
1001
- collectionViewDidEndDisplayingCellForItemAtIndexPath(collectionView, cell, indexPath) {
1002
- this._visibleCells.delete(cell);
1003
- if (this.hasListeners(CollectionViewBase.itemRecyclingEvent)) {
1004
- this.notify({
1005
- eventName: CollectionViewBase.itemRecyclingEvent,
1006
- index: indexPath.row,
1007
- object: this,
1008
- item: null,
1009
- view: cell.view,
1010
- });
1011
- }
1012
1051
  }
1013
1052
  collectionViewDidSelectItemAtIndexPath(collectionView, indexPath) {
1014
1053
  const cell = collectionView.cellForItemAtIndexPath(indexPath);
@@ -1088,26 +1127,12 @@ export class CollectionView extends CollectionViewBase {
1088
1127
  object: this,
1089
1128
  eventName,
1090
1129
  scrollOffset: offset,
1130
+ scrollSize: size,
1091
1131
  scrollOffsetPercentage: offset / size,
1092
1132
  dx,
1093
1133
  dy: dy + safeAreaInsetsTop,
1094
1134
  };
1095
1135
  }
1096
- scrollToOffset(value, animated) {
1097
- if (this.nativeViewProtected && this.isScrollEnabled) {
1098
- const { width, height } = this.nativeViewProtected.bounds.size;
1099
- let rect;
1100
- if (this.orientation === 'vertical') {
1101
- rect = CGRectMake(0, value, width, height);
1102
- }
1103
- else if (this.orientation === 'horizontal') {
1104
- rect = CGRectMake(value, 0, width, height);
1105
- }
1106
- if (rect) {
1107
- this.nativeViewProtected.scrollRectToVisibleAnimated(rect, animated);
1108
- }
1109
- }
1110
- }
1111
1136
  scrollViewWillBeginDragging(scrollView) {
1112
1137
  this.lastContentOffset = scrollView.contentOffset;
1113
1138
  this.needsScrollStartEvent = true;
@@ -1125,16 +1150,15 @@ export class CollectionView extends CollectionViewBase {
1125
1150
  }
1126
1151
  }
1127
1152
  this.notify(this.computeScrollEventData(scrollView, CollectionViewBase.scrollEvent, dx, dy));
1128
- this.updateVisibleCells();
1129
1153
  }
1130
1154
  stopScrolling(scrollView) {
1131
1155
  if (this.isScrolling) {
1132
1156
  this.isScrolling = false;
1157
+ this.notify(this.computeScrollEventData(scrollView, CollectionViewBase.scrollEndEvent));
1133
1158
  }
1134
1159
  }
1135
1160
  scrollViewDidEndDecelerating(scrollView) {
1136
1161
  this.stopScrolling(scrollView);
1137
- this.notify(this.computeScrollEventData(scrollView, CollectionViewBase.scrollEndEvent));
1138
1162
  }
1139
1163
  scrollViewWillEndDraggingWithVelocityTargetContentOffset(scrollView, velocity, targetContentOffset) {
1140
1164
  this.stopScrolling(scrollView);
@@ -1153,6 +1177,8 @@ __decorate([
1153
1177
  __metadata("design:returntype", void 0)
1154
1178
  ], CollectionView.prototype, "refresh", null);
1155
1179
  contentInsetAdjustmentBehaviorProperty.register(CollectionView);
1180
+ estimatedItemSizeProperty.register(CollectionView);
1181
+ autoSizeProperty.register(CollectionView);
1156
1182
  var NSCellView = /** @class */ (function (_super) {
1157
1183
  __extends(NSCellView, _super);
1158
1184
  function NSCellView() {
@@ -1160,7 +1186,7 @@ var NSCellView = /** @class */ (function (_super) {
1160
1186
  }
1161
1187
  NSCellView.prototype.layoutSubviews = function () {
1162
1188
  _super.prototype.layoutSubviews.call(this);
1163
- var view = this.view && this.view.deref();
1189
+ var view = this.view && this.view.get();
1164
1190
  if (!view) {
1165
1191
  return;
1166
1192
  }
@@ -1186,27 +1212,155 @@ var CollectionViewCell = /** @class */ (function (_super) {
1186
1212
  var _a;
1187
1213
  var owner = (_a = this.owner) === null || _a === void 0 ? void 0 : _a.deref();
1188
1214
  if (owner) {
1189
- var dimensions = { measuredWidth: owner.getMeasuredWidth(), measuredHeight: owner.getMeasuredHeight() };
1215
+ var dimensions = {
1216
+ measuredWidth: owner.getMeasuredWidth(),
1217
+ measuredHeight: owner.getMeasuredHeight(),
1218
+ };
1190
1219
  return CGSizeMake(Utils.layout.toDeviceIndependentPixels(dimensions.measuredWidth), Utils.layout.toDeviceIndependentPixels(dimensions.measuredHeight));
1191
1220
  }
1192
1221
  return targetSize;
1193
1222
  };
1194
1223
  return CollectionViewCell;
1195
1224
  }(UICollectionViewCell));
1196
- var CollectionViewReusableView = /** @class */ (function (_super) {
1197
- __extends(CollectionViewReusableView, _super);
1198
- function CollectionViewReusableView() {
1225
+ var UICollectionViewImpl = /** @class */ (function (_super) {
1226
+ __extends(UICollectionViewImpl, _super);
1227
+ function UICollectionViewImpl() {
1199
1228
  return _super !== null && _super.apply(this, arguments) || this;
1200
1229
  }
1201
- Object.defineProperty(CollectionViewReusableView.prototype, "view", {
1202
- get: function () {
1203
- return this.owner ? this.owner.deref() : null;
1204
- },
1205
- enumerable: true,
1206
- configurable: true
1207
- });
1208
- return CollectionViewReusableView;
1209
- }(UICollectionReusableView));
1230
+ UICollectionViewImpl.prototype.sizeThatFits = function (size) {
1231
+ var _a, _b, _c;
1232
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1233
+ if (owner === null || owner === void 0 ? void 0 : owner.autoSize) {
1234
+ if (this.superview) {
1235
+ (_b = this.superview) === null || _b === void 0 ? void 0 : _b.layoutIfNeeded();
1236
+ }
1237
+ var horizontal = owner.orientation === 'horizontal';
1238
+ // Calculate the total size based on the cells' sizes
1239
+ var width = 0;
1240
+ var height = 0;
1241
+ var dataSource = owner._dataSource;
1242
+ var delegate = owner._delegate;
1243
+ if (dataSource && delegate) {
1244
+ var numberOfItems = dataSource.collectionViewNumberOfItemsInSection(this, 0);
1245
+ for (var index = 0; index < numberOfItems; index++) {
1246
+ var indexPath = NSIndexPath.indexPathForItemInSection(index, 0);
1247
+ var estimatedSize = (_c = delegate.collectionViewLayoutSizeForItemAtIndexPath(this, owner._layout, indexPath)) !== null && _c !== void 0 ? _c : CGSizeZero;
1248
+ if (horizontal) {
1249
+ width = Math.max(width, estimatedSize.width);
1250
+ height += estimatedSize.height;
1251
+ }
1252
+ else {
1253
+ height = Math.max(height, estimatedSize.height);
1254
+ width += estimatedSize.width;
1255
+ }
1256
+ }
1257
+ return CGSizeMake(width, height);
1258
+ }
1259
+ }
1260
+ return _super.prototype.sizeThatFits.call(this, size);
1261
+ };
1262
+ UICollectionViewImpl.initWithOwner = function (owner, layout) {
1263
+ var view = UICollectionViewImpl.alloc().initWithFrameCollectionViewLayout(CGRectMake(0, 0, 0, 0), layout);
1264
+ view._owner = new WeakRef(owner);
1265
+ return view;
1266
+ };
1267
+ return UICollectionViewImpl;
1268
+ }(UICollectionView));
1269
+ var UICollectionViewFlowLayoutImpl = /** @class */ (function (_super) {
1270
+ __extends(UICollectionViewFlowLayoutImpl, _super);
1271
+ function UICollectionViewFlowLayoutImpl() {
1272
+ return _super !== null && _super.apply(this, arguments) || this;
1273
+ }
1274
+ UICollectionViewFlowLayoutImpl.initWithOwner = function (owner) {
1275
+ var layout = UICollectionViewFlowLayoutImpl.new();
1276
+ layout._owner = new WeakRef(owner);
1277
+ return layout;
1278
+ };
1279
+ UICollectionViewFlowLayoutImpl.prototype.invalidationContextForInteractivelyMovingItemsWithTargetPositionPreviousIndexPathsPreviousPosition = function (targetIndexPaths, targetPosition, previousIndexPaths, previousPosition) {
1280
+ var _a;
1281
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1282
+ if (owner && targetIndexPaths.count) {
1283
+ owner.clearCachedSize(targetIndexPaths.objectAtIndex(0).row, previousIndexPaths.objectAtIndex(0).row);
1284
+ }
1285
+ return _super.prototype.invalidationContextForInteractivelyMovingItemsWithTargetPositionPreviousIndexPathsPreviousPosition.call(this, targetIndexPaths, targetPosition, previousIndexPaths, previousPosition);
1286
+ };
1287
+ UICollectionViewFlowLayoutImpl.prototype.layoutAttributesForElementsInRect = function (rect) {
1288
+ var _a;
1289
+ var attributesArray = _super.prototype.layoutAttributesForElementsInRect.call(this, rect);
1290
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1291
+ owner === null || owner === void 0 ? void 0 : owner.layoutAttributesForElementsInRect(attributesArray, rect);
1292
+ return attributesArray;
1293
+ };
1294
+ UICollectionViewFlowLayoutImpl.prototype.shouldInvalidateLayoutForBoundsChange = function (newBounds) {
1295
+ var _a;
1296
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1297
+ if (owner === null || owner === void 0 ? void 0 : owner.itemOverlap) {
1298
+ return true;
1299
+ }
1300
+ return _super.prototype.shouldInvalidateLayoutForBoundsChange.call(this, newBounds);
1301
+ };
1302
+ return UICollectionViewFlowLayoutImpl;
1303
+ }(UICollectionViewFlowLayout));
1304
+ var CollectionViewDataSource = /** @class */ (function (_super) {
1305
+ __extends(CollectionViewDataSource, _super);
1306
+ function CollectionViewDataSource() {
1307
+ return _super !== null && _super.apply(this, arguments) || this;
1308
+ }
1309
+ CollectionViewDataSource.initWithOwner = function (owner) {
1310
+ var delegate = CollectionViewDataSource.new();
1311
+ delegate._owner = new WeakRef(owner);
1312
+ return delegate;
1313
+ };
1314
+ CollectionViewDataSource.prototype.numberOfSectionsInCollectionView = function (collectionView) {
1315
+ var owner = this._owner.deref();
1316
+ if (owner) {
1317
+ return owner.numberOfSectionsInCollectionView(collectionView);
1318
+ }
1319
+ return 0;
1320
+ };
1321
+ CollectionViewDataSource.prototype.collectionViewNumberOfItemsInSection = function (collectionView, section) {
1322
+ var owner = this._owner.deref();
1323
+ if (owner) {
1324
+ return owner.collectionViewNumberOfItemsInSection(collectionView, section);
1325
+ }
1326
+ return 0;
1327
+ };
1328
+ CollectionViewDataSource.prototype.collectionViewCellForItemAtIndexPath = function (collectionView, indexPath) {
1329
+ var owner = this._owner.deref();
1330
+ if (owner) {
1331
+ return owner.collectionViewCellForItemAtIndexPath(collectionView, indexPath);
1332
+ }
1333
+ return null;
1334
+ };
1335
+ CollectionViewDataSource.prototype.collectionViewMoveItemAtIndexPathToIndexPath = function (collectionView, sourceIndexPath, destinationIndexPath) {
1336
+ var owner = this._owner.deref();
1337
+ if (owner) {
1338
+ owner.reorderStartingRow = sourceIndexPath.row;
1339
+ owner.reorderEndingRow = destinationIndexPath.row;
1340
+ // owner._reorderItemInSource(sourceIndexPath.row, destinationIndexPath.row, false);
1341
+ }
1342
+ };
1343
+ CollectionViewDataSource.prototype.collectionViewTargetIndexPathForMoveFromItemAtIndexPathToProposedIndexPath = function (collectionView, originalIndexPath, proposedIndexPath) {
1344
+ var owner = this._owner.deref();
1345
+ if (owner) {
1346
+ owner.reorderEndingRow = proposedIndexPath.row;
1347
+ }
1348
+ return proposedIndexPath;
1349
+ };
1350
+ CollectionViewDataSource.prototype.collectionViewCanMoveItemAtIndexPath = function (collectionView, indexPath) {
1351
+ var owner = this._owner.deref();
1352
+ if (owner) {
1353
+ var result = owner.shouldMoveItemAtIndex(indexPath.row);
1354
+ if (result) {
1355
+ owner.reorderStartingRow = indexPath.row;
1356
+ }
1357
+ return result;
1358
+ }
1359
+ return false;
1360
+ };
1361
+ CollectionViewDataSource.ObjCProtocols = [UICollectionViewDataSource];
1362
+ return CollectionViewDataSource;
1363
+ }(NSObject));
1210
1364
  var UICollectionViewDelegateImpl = /** @class */ (function (_super) {
1211
1365
  __extends(UICollectionViewDelegateImpl, _super);
1212
1366
  function UICollectionViewDelegateImpl() {
@@ -1223,13 +1377,6 @@ var UICollectionViewDelegateImpl = /** @class */ (function (_super) {
1223
1377
  owner.collectionViewWillDisplayCellForItemAtIndexPath(collectionView, cell, indexPath);
1224
1378
  }
1225
1379
  };
1226
- // TODO: find out why for some reason this is not being called when the cell moves out of view
1227
- UICollectionViewDelegateImpl.prototype.collectionViewDidEndDisplayingCellForItemAtIndexPath = function (collectionView, cell, indexPath) {
1228
- var owner = this._owner.deref();
1229
- if (owner) {
1230
- owner.collectionViewDidEndDisplayingCellForItemAtIndexPath(collectionView, cell, indexPath);
1231
- }
1232
- };
1233
1380
  UICollectionViewDelegateImpl.prototype.collectionViewDidSelectItemAtIndexPath = function (collectionView, indexPath) {
1234
1381
  var owner = this._owner.deref();
1235
1382
  if (owner) {
@@ -1280,6 +1427,19 @@ var UICollectionViewDelegateImpl = /** @class */ (function (_super) {
1280
1427
  owner.scrollViewDidEndScrollingAnimation(scrollView);
1281
1428
  }
1282
1429
  };
1430
+ UICollectionViewDelegateImpl.prototype.collectionViewTargetIndexPathForMoveFromItemAtIndexPathToProposedIndexPath = function (collectionView, currentIndexPath, proposedIndexPath) {
1431
+ var _a;
1432
+ if (currentIndexPath === proposedIndexPath) {
1433
+ return proposedIndexPath;
1434
+ }
1435
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1436
+ if (owner && !owner._canReorderToPosition(currentIndexPath.row, proposedIndexPath.row, owner.getItemAtIndex(proposedIndexPath.row))) {
1437
+ return currentIndexPath;
1438
+ }
1439
+ owner._reorderItemInSource(currentIndexPath.row, proposedIndexPath.row, false);
1440
+ owner.clearCachedSize(currentIndexPath.row, proposedIndexPath.row);
1441
+ return proposedIndexPath;
1442
+ };
1283
1443
  UICollectionViewDelegateImpl.ObjCProtocols = [UICollectionViewDelegate, UICollectionViewDelegateFlowLayout];
1284
1444
  return UICollectionViewDelegateImpl;
1285
1445
  }(UICollectionViewCacheDelegateFlowLayout));
@@ -1342,6 +1502,19 @@ var UICollectionViewDelegateFixedSizeImpl = /** @class */ (function (_super) {
1342
1502
  owner.scrollViewDidEndScrollingAnimation(scrollView);
1343
1503
  }
1344
1504
  };
1505
+ UICollectionViewDelegateFixedSizeImpl.prototype.collectionViewTargetIndexPathForMoveFromItemAtIndexPathToProposedIndexPath = function (collectionView, currentIndexPath, proposedIndexPath) {
1506
+ var _a;
1507
+ if (currentIndexPath === proposedIndexPath) {
1508
+ return proposedIndexPath;
1509
+ }
1510
+ var owner = (_a = this._owner) === null || _a === void 0 ? void 0 : _a.deref();
1511
+ if (owner && !owner._canReorderToPosition(currentIndexPath.row, proposedIndexPath.row, owner.getItemAtIndex(proposedIndexPath.row))) {
1512
+ return currentIndexPath;
1513
+ }
1514
+ owner._reorderItemInSource(currentIndexPath.row, proposedIndexPath.row, false);
1515
+ owner.clearCachedSize(currentIndexPath.row, proposedIndexPath.row);
1516
+ return proposedIndexPath;
1517
+ };
1345
1518
  UICollectionViewDelegateFixedSizeImpl.ObjCProtocols = [UICollectionViewDelegate, UICollectionViewDelegateFlowLayout];
1346
1519
  return UICollectionViewDelegateFixedSizeImpl;
1347
1520
  }(NSObject));