1
1
import React , { Component } from 'react' ;
2
2
import PropTypes from 'prop-types' ;
3
3
import { ScrollView , View , StyleSheet , Platform , RefreshControl , ViewPropTypes } from 'react-native' ;
4
- import { shallowEqual , swapArrayElements } from './utils' ;
4
+ import { inRange , shallowEqual , swapArrayElements } from './utils' ;
5
5
import Row from './Row' ;
6
6
7
7
const AUTOSCROLL_INTERVAL = 100 ;
@@ -211,22 +211,12 @@ export default class SortableList extends Component {
211
211
const { horizontal, rowActivationTime, sortingEnabled, renderRow} = this . props ;
212
212
const { animated, order, data, activeRowKey, releasedRowKey, rowsLayouts} = this . state ;
213
213
214
-
215
- let nextX = 0 ;
216
- let nextY = 0 ;
217
-
218
214
return order . map ( ( key , index ) => {
219
215
const style = { [ ZINDEX ] : 0 } ;
220
- const location = { x : 0 , y : 0 } ;
221
-
222
- if ( rowsLayouts ) {
223
- if ( horizontal ) {
224
- location . x = nextX ;
225
- nextX += rowsLayouts [ key ] . width ;
226
- } else {
227
- location . y = nextY ;
228
- nextY += rowsLayouts [ key ] . height ;
229
- }
216
+ let location ;
217
+
218
+ if ( rowsLayouts && rowsLayouts [ key ] ) {
219
+ location = { x : rowsLayouts [ key ] . x , y : rowsLayouts [ key ] . y } ;
230
220
}
231
221
232
222
const active = activeRowKey === key ;
@@ -279,11 +269,14 @@ export default class SortableList extends Component {
279
269
}
280
270
281
271
_onUpdateLayouts ( ) {
272
+ const { horizontal} = this . props ;
273
+ const { order} = this . state ;
274
+
282
275
Promise . all ( [ this . _footerLayout , ...Object . values ( this . _rowsLayouts ) ] )
283
276
. then ( ( [ footerLayout , ...rowsLayouts ] ) => {
284
277
// Can get correct container’s layout only after rows’s layouts.
285
278
this . _container . measure ( ( x , y , width , height , pageX , pageY ) => {
286
- const rowsLayoutsByKey = { } ;
279
+ let rowsLayoutsByKey = { } ;
287
280
let contentHeight = 0 ;
288
281
let contentWidth = 0 ;
289
282
@@ -292,10 +285,12 @@ export default class SortableList extends Component {
292
285
contentHeight += layout . height ;
293
286
contentWidth += layout . width ;
294
287
} ) ;
288
+ rowsLayoutsByKey = this . _getRowsLocations ( rowsLayoutsByKey , order ) ;
295
289
296
290
this . setState ( {
297
291
containerLayout : { x, y, width, height, pageX, pageY} ,
298
292
rowsLayouts : rowsLayoutsByKey ,
293
+ rowsSwapRanges : this . _getRowsSwapRanges ( rowsLayoutsByKey , order ) ,
299
294
footerLayout,
300
295
contentHeight,
301
296
contentWidth,
@@ -306,6 +301,54 @@ export default class SortableList extends Component {
306
301
} ) ;
307
302
}
308
303
304
+ _getRowsLocations ( _rowsLayouts , order ) {
305
+ const { horizontal} = this . props ;
306
+ const rowsLayouts = { } ;
307
+ let nextX = 0 ;
308
+ let nextY = 0 ;
309
+
310
+ for ( let i = 0 , len = order . length ; i < len ; i ++ ) {
311
+ const rowKey = order [ i ] ;
312
+ const rowLayout = _rowsLayouts [ rowKey ] ;
313
+
314
+ rowsLayouts [ rowKey ] = {
315
+ ...rowLayout ,
316
+ x : nextX ,
317
+ y : nextY ,
318
+ } ;
319
+
320
+ if ( horizontal ) {
321
+ nextX += rowLayout . width ;
322
+ } else {
323
+ nextY += rowLayout . height ;
324
+ }
325
+ }
326
+
327
+ return rowsLayouts ;
328
+ }
329
+
330
+ _getRowsSwapRanges ( rowsLayouts , order ) {
331
+ const { horizontal} = this . props ;
332
+ const rowsSwapRanges = { } ;
333
+
334
+ for ( let i = 0 , len = order . length ; i < len ; i ++ ) {
335
+ const rowKey = order [ i ] ;
336
+ const rowLayout = rowsLayouts [ rowKey ] ;
337
+
338
+ rowsSwapRanges [ rowKey ] = horizontal
339
+ ? {
340
+ left : [ rowLayout . x + rowLayout . width / 3 , rowLayout . x + rowLayout . width ] ,
341
+ right : [ rowLayout . x , rowLayout . x + 2 * rowLayout . width / 3 ] ,
342
+ }
343
+ : {
344
+ top : [ rowLayout . y + rowLayout . height / 3 , rowLayout . y + rowLayout . height ] ,
345
+ bottom : [ rowLayout . y , rowLayout . y + 2 * rowLayout . height / 3 ] ,
346
+ } ;
347
+ }
348
+
349
+ return rowsSwapRanges ;
350
+ }
351
+
309
352
_scroll ( animated ) {
310
353
this . _scrollView . scrollTo ( { ...this . _contentOffset , animated} ) ;
311
354
}
@@ -315,7 +358,8 @@ export default class SortableList extends Component {
315
358
* swaps them, else shifts rows.
316
359
*/
317
360
_setOrderOnMove ( ) {
318
- const { activeRowKey, activeRowIndex, order} = this . state ;
361
+ const { activeRowKey, activeRowIndex, order, rowsLayouts} = this . state ;
362
+ const { horizontal} = this . props ;
319
363
320
364
if ( activeRowKey === null || this . _autoScrollInterval ) {
321
365
return ;
@@ -345,9 +389,14 @@ export default class SortableList extends Component {
345
389
nextOrder . splice ( rowUnderActiveIndex , 0 , activeRowKey ) ;
346
390
}
347
391
392
+ const nextRowsLayouts = this . _getRowsLocations ( rowsLayouts , nextOrder ) ;
393
+ const nextRowsSwapRanges = this . _getRowsSwapRanges ( nextRowsLayouts , nextOrder ) ;
394
+
348
395
this . setState ( {
349
396
order : nextOrder ,
350
397
activeRowIndex : rowUnderActiveIndex ,
398
+ rowsLayouts : nextRowsLayouts ,
399
+ rowsSwapRanges : nextRowsSwapRanges ,
351
400
} , ( ) => {
352
401
if ( this . props . onChangeOrder ) {
353
402
this . props . onChangeOrder ( nextOrder ) ;
@@ -357,53 +406,114 @@ export default class SortableList extends Component {
357
406
}
358
407
359
408
/**
360
- * Finds a row, which was covered with the moving row’s half .
409
+ * Finds a row, which was covered with the moving row’s third .
361
410
*/
362
411
_findRowUnderActiveRow ( ) {
363
412
const { horizontal} = this . props ;
364
- const { rowsLayouts, activeRowKey, activeRowIndex, order} = this . state ;
365
- const movingRowLayout = rowsLayouts [ activeRowKey ] ;
366
- const rowLeftX = this . _activeRowLocation . x
367
- const rowRightX = rowLeftX + movingRowLayout . width ;
368
- const rowTopY = this . _activeRowLocation . y ;
369
- const rowBottomY = rowTopY + movingRowLayout . height ;
370
-
371
- for (
372
- let currentRowIndex = 0 , x = 0 , y = 0 , rowsCount = order . length ;
373
- currentRowIndex < rowsCount - 1 ;
374
- currentRowIndex ++
413
+ const { rowsLayouts, rowsSwapRanges, activeRowKey, activeRowIndex, order} = this . state ;
414
+ const movingDirection = this . _movingDirection ;
415
+ const rowsCount = order . length ;
416
+ const activeRowLayout = rowsLayouts [ activeRowKey ] ;
417
+ const activeRowLeftX = this . _activeRowLocation . x
418
+ const activeRowRightX = this . _activeRowLocation . x + activeRowLayout . width ;
419
+ const activeRowTopY = this . _activeRowLocation . y ;
420
+ const activeRowBottomY = this . _activeRowLocation . y + activeRowLayout . height ;
421
+
422
+ const prevRowIndex = activeRowIndex - 1 ;
423
+ const prevRowKey = order [ prevRowIndex ] ;
424
+ const prevRowSwapRages = rowsSwapRanges [ prevRowKey ]
425
+ const nextRowIndex = activeRowIndex + 1 ;
426
+ const nextRowKey = order [ nextRowIndex ] ;
427
+ const nextRowSwapRages = rowsSwapRanges [ nextRowKey ]
428
+
429
+ if ( horizontal
430
+ ? ( movingDirection === 1
431
+ ? (
432
+ ( activeRowIndex === 0 || activeRowLeftX > prevRowSwapRages . right [ 0 ] ) &&
433
+ ( activeRowIndex === rowsCount - 1 || activeRowRightX < nextRowSwapRages . left [ 0 ] )
434
+ )
435
+ : (
436
+ ( activeRowIndex === 0 || activeRowLeftX > prevRowSwapRages . right [ 1 ] ) &&
437
+ ( activeRowIndex === rowsCount - 1 || activeRowRightX < nextRowSwapRages . left [ 1 ] )
438
+ )
439
+ )
440
+ : ( movingDirection === 1
441
+ ? (
442
+ ( activeRowIndex === 0 || activeRowTopY > prevRowSwapRages . bottom [ 0 ] ) &&
443
+ ( activeRowIndex === rowsCount - 1 || activeRowBottomY < nextRowSwapRages . top [ 0 ] )
444
+ )
445
+ : (
446
+ ( activeRowIndex === 0 || activeRowTopY > prevRowSwapRages . bottom [ 1 ] ) &&
447
+ ( activeRowIndex === rowsCount - 1 || activeRowBottomY < nextRowSwapRages . top [ 1 ] )
448
+ )
449
+ )
375
450
) {
376
- const currentRowKey = order [ currentRowIndex ] ;
377
- const currentRowLayout = rowsLayouts [ currentRowKey ] ;
378
- const nextRowIndex = currentRowIndex + 1 ;
379
- const nextRowLayout = rowsLayouts [ order [ nextRowIndex ] ] ;
380
-
381
- x += currentRowLayout . width ;
382
- y += currentRowLayout . height ;
383
-
384
- if ( currentRowKey !== activeRowKey && (
385
- horizontal
386
- ? ( ( x - currentRowLayout . width <= rowLeftX || currentRowIndex === 0 ) && rowLeftX <= x - currentRowLayout . width / 3 )
387
- : ( ( y - currentRowLayout . height <= rowTopY || currentRowIndex === 0 ) && rowTopY <= y - currentRowLayout . height / 3 )
388
- ) ) {
389
- return {
390
- rowKey : order [ currentRowIndex ] ,
391
- rowIndex : currentRowIndex ,
392
- } ;
393
- }
451
+ return {
452
+ rowKey : activeRowKey ,
453
+ rowIndex : activeRowIndex ,
454
+ } ;
455
+ }
394
456
457
+ if ( movingDirection === 1 ) {
395
458
if ( horizontal
396
- ? ( x + nextRowLayout . width / 3 <= rowRightX && ( rowRightX <= x + nextRowLayout . width || nextRowIndex === rowsCount - 1 ) )
397
- : ( y + nextRowLayout . height / 3 <= rowBottomY && ( rowBottomY <= y + nextRowLayout . height || nextRowIndex === rowsCount - 1 ) )
459
+ ? inRange ( activeRowRightX , ... nextRowSwapRages . left )
460
+ : inRange ( activeRowBottomY , ... nextRowSwapRages . top )
398
461
) {
399
- return {
400
- rowKey : order [ nextRowIndex ] ,
462
+ return {
463
+ rowKey : nextRowKey ,
401
464
rowIndex : nextRowIndex ,
402
465
} ;
403
466
}
467
+ } else {
468
+ if ( horizontal
469
+ ? inRange ( activeRowLeftX , ...prevRowSwapRages . right )
470
+ : inRange ( activeRowTopY , ...prevRowSwapRages . bottom )
471
+ ) {
472
+ return {
473
+ rowKey : prevRowKey ,
474
+ rowIndex : prevRowIndex ,
475
+ } ;
476
+ }
404
477
}
405
478
406
- return { rowKey : activeRowKey , rowIndex : activeRowIndex } ;
479
+ // let startIndex = 0;
480
+ // let endIndex = rowsCount - 1;
481
+ // let middleIndex;
482
+ // let it = 0
483
+ // console.log(movingDirection);
484
+ // while (startIndex < endIndex) {
485
+ // middleIndex = Math.floor((endIndex - startIndex) / 2);
486
+
487
+ // if (it++ > 10) {
488
+ // console.log(startIndex, middleIndex, endIndex);
489
+ // break
490
+ // }
491
+ // const middleRowSwapRanges = rowsSwapRanges[middleIndex];
492
+
493
+ // if (horizontal) {
494
+ // if (movingDirection === 1) {
495
+ // if (inRange(activeRowRightX, ...middleRowSwapRanges.left)) break;
496
+ // else if (activeRowRightX < middleRowSwapRanges.left[0]) endIndex = middleIndex;
497
+ // else if (activeRowRightX > middleRowSwapRanges.left[1]) startIndex = middleIndex;
498
+ // } else {
499
+ // if (inRange(activeRowLeftX, ...middleRowSwapRanges.right)) break;
500
+ // else if (activeRowLeftX < middleRowSwapRanges.right[0]) endIndex = middleIndex;
501
+ // else if (activeRowLeftX > middleRowSwapRanges.right[1]) startIndex = middleIndex;
502
+ // }
503
+ // } else {
504
+ // if (movingDirection === 1) {
505
+ // if (inRange(activeRowBottomY, ...middleRowSwapRanges.top)) break;
506
+ // else if (activeRowBottomY < middleRowSwapRanges.top[0]) endIndex = middleIndex;
507
+ // else if (activeRowBottomY > middleRowSwapRanges.top[1]) startIndex = middleIndex;
508
+ // } else {
509
+ // if (inRange(activeRowTopY, ...middleRowSwapRanges.bottom)) break;
510
+ // else if (activeRowTopY < middleRowSwapRanges.bottom[0]) endIndex = middleIndex;
511
+ // else if (activeRowTopY > middleRowSwapRanges.bottom[1]) startIndex = middleIndex;
512
+ // }
513
+ // }
514
+ // }
515
+
516
+ // return {rowKey: order[middleIndex], rowIndex: middleIndex};
407
517
}
408
518
409
519
_scrollOnMove ( e ) {
@@ -567,9 +677,11 @@ export default class SortableList extends Component {
567
677
const prevMovingDirection = this . _movingDirection ;
568
678
569
679
this . _activeRowLocation = location ;
570
- this . _movingDirection = this . props . horizontal
571
- ? prevMovingRowX < this . _activeRowLocation . x
572
- : prevMovingRowY < this . _activeRowLocation . y ;
680
+ this . _movingDirection = (
681
+ this . props . horizontal
682
+ ? prevMovingRowX <= this . _activeRowLocation . x
683
+ : prevMovingRowY <= this . _activeRowLocation . y
684
+ ) ? 1 : - 1 ;
573
685
574
686
this . _movingDirectionChanged = prevMovingDirection !== this . _movingDirection ;
575
687
this . _setOrderOnMove ( ) ;
0 commit comments