Moving elements in lists

I think you read a thread of me suggesting to Duane that he should not use a top-level data structure. In his case, he stored millions of different keys in a single top-level map. For a small file system (with probably less than 10k files) it won’t make a difference.

I did indeed - this is good to know. I’ll experiment with a couple of different structures to see what works best. Checking this out next, will let ya know where I end up. Now I’ve moved down the POC checklist to the “branching” item - this one seems like it should be pretty straightforward with yjs, fingers crossed.


BTW below is where I ended up re moving items within a parent - what you shared is working like a charm with some small tweaks :slight_smile:. Built on the ideas in this article to create an index (the generateKeyBetween func used but not defined in example below) that would scale to work with most realistic situations - Implementing Fractional Indexing / David Greenspan | Observable.

// the array is ordered using "pos" markers. They represent the order of the items
// this function returns the sorted array
export const getArrayContent = (arr: Y.Array<Y.Map<any>>) =>
  arr
    .toArray()
    .sort((a, b) =>
      a.get('pos') < b.get('pos') ? -1 : a.get('pos') > b.get('pos') ? 1 : 0,

const insertMap = (
  arr: Y.Array<Y.Map<any>>,
  map: Y.Map<any>,
  index: number,
) => {
  moveMap(arr, map, index);

  // always appended, since sort order is not reliant on array order
  arr.push([map]);
};

export const moveMap = (
  arr: Y.Array<Y.Map<any>>,
  map: Y.Map<any>,
  index: number,
) => {
  const sortedArray = getArrayContent(arr);
  const currentIndex = sortedArray.findIndex((i) => i === map);

  let left: Y.Map<any> | null;
  let right: Y.Map<any> | null;
  if (currentIndex >= 0 && currentIndex < index) {
    // we're moving an item down in the list
    left = sortedArray[index] || null;
    right = sortedArray[index + 1] || null;
  } else {
    // we're adding an item for first time, or moving up in list
    left = sortedArray[index - 1] || null;
    right = sortedArray[index] || null;
  }

  const leftIndex = left ? (left.get('pos') as string) : null;
  const rightIndex = right ? (right.get('pos') as string) : null;

  map.set('pos', generateKeyBetween(leftIndex, rightIndex));
};
2 Likes