standby method

dynamic standby({
  1. BuildContext? sliverContext,
  2. bool isRemove = false,
  3. int changeCount = 1,
  4. ChatScrollObserverHandleMode mode = ChatScrollObserverHandleMode.normal,
  5. ChatScrollObserverRefIndexType refIndexType = ChatScrollObserverRefIndexType.relativeIndexStartFromCacheExtent,
  6. @Deprecated('It will be removed in version 2, please use [refItemIndex] instead') int refItemRelativeIndex = 0,
  7. @Deprecated('It will be removed in version 2, please use [refItemIndexAfterUpdate] instead') int refItemRelativeIndexAfterUpdate = 0,
  8. int refItemIndex = 0,
  9. int refItemIndexAfterUpdate = 0,
  10. ChatScrollObserverCustomAdjustPosition? customAdjustPosition,
  11. ChatScrollObserverCustomAdjustPositionDelta? customAdjustPositionDelta,
})

Prepare to adjust position for sliver.

The changeCount parameter is used only when isRemove parameter is false.

The mode parameter is used to specify the processing mode.

refItemRelativeIndex parameter and refItemRelativeIndexAfterUpdate parameter are only used when the mode is ChatScrollObserverHandleMode.specified. Usage: When you insert a new message, assign the index of the reference message before insertion to refItemIndex, and assign the index of the reference message after insertion to refItemIndexAfterUpdate. Note that they should refer to the index of the same message.

Implementation

standby({
  BuildContext? sliverContext,
  bool isRemove = false,
  int changeCount = 1,
  ChatScrollObserverHandleMode mode = ChatScrollObserverHandleMode.normal,
  ChatScrollObserverRefIndexType refIndexType =
      ChatScrollObserverRefIndexType.relativeIndexStartFromCacheExtent,
  @Deprecated(
      'It will be removed in version 2, please use [refItemIndex] instead')
  int refItemRelativeIndex = 0,
  @Deprecated(
      'It will be removed in version 2, please use [refItemIndexAfterUpdate] instead')
  int refItemRelativeIndexAfterUpdate = 0,
  int refItemIndex = 0,
  int refItemIndexAfterUpdate = 0,
  ChatScrollObserverCustomAdjustPosition? customAdjustPosition,
  ChatScrollObserverCustomAdjustPositionDelta? customAdjustPositionDelta,
}) async {
  innerMode = mode;
  this.isRemove = isRemove;
  this.changeCount = changeCount;
  observeSwitchShrinkWrap();

  int _innerRefItemIndex;
  int _innerRefItemIndexAfterUpdate;
  double _innerRefItemLayoutOffset;
  switch (mode) {
    case ChatScrollObserverHandleMode.normal:
      final firstItemModel = observerController.observeFirstItem(
        sliverContext: sliverContext,
      );
      if (firstItemModel == null) return;
      _innerRefItemIndex = firstItemModel.index;
      _innerRefItemIndexAfterUpdate = _innerRefItemIndex + changeCount;
      _innerRefItemLayoutOffset = firstItemModel.layoutOffset;
      break;
    case ChatScrollObserverHandleMode.generative:
      final firstItemModel = observerController.observeFirstItem(
        sliverContext: sliverContext,
      );
      if (firstItemModel == null) return;
      int index = firstItemModel.index + changeCount;
      final model = observerController.observeItem(
        sliverContext: sliverContext,
        index: index,
      );
      if (model == null) return;
      _innerRefItemIndex = index;
      _innerRefItemIndexAfterUpdate = index;
      _innerRefItemLayoutOffset = model.layoutOffset;
      break;
    case ChatScrollObserverHandleMode.specified:
      // Prioritize the values ​​of [refItemIndex] and [refItemIndexAfterUpdate]
      int _refItemIndex =
          refItemIndex != 0 ? refItemIndex : refItemRelativeIndex;
      int _refItemIndexAfterUpdate = refItemIndexAfterUpdate != 0
          ? refItemIndexAfterUpdate
          : refItemRelativeIndexAfterUpdate;

      switch (refIndexType) {
        case ChatScrollObserverRefIndexType.relativeIndexStartFromCacheExtent:
          final firstItemModel = observerController.observeFirstItem(
            sliverContext: sliverContext,
          );
          if (firstItemModel == null) return;
          int index = firstItemModel.index + _refItemIndex;
          final model = observerController.observeItem(
            sliverContext: sliverContext,
            index: index,
          );
          if (model == null) return;
          _innerRefItemIndex = index;
          _innerRefItemIndexAfterUpdate =
              firstItemModel.index + _refItemIndexAfterUpdate;
          _innerRefItemLayoutOffset = model.layoutOffset;
          break;
        case ChatScrollObserverRefIndexType.relativeIndexStartFromDisplaying:
          final observeResult = await observerController.dispatchOnceObserve(
            isForce: true,
            isDependObserveCallback: false,
          );
          if (!observeResult.isSuccess) return;
          final currentFirstDisplayingChildIndex =
              observeResult.observeResult?.firstChild?.index ?? 0;
          int index = currentFirstDisplayingChildIndex + _refItemIndex;
          final model = observerController.observeItem(
            sliverContext: sliverContext,
            index: index,
          );
          if (model == null) return;
          _innerRefItemIndex = index;
          _innerRefItemIndexAfterUpdate =
              currentFirstDisplayingChildIndex + _refItemIndexAfterUpdate;
          _innerRefItemLayoutOffset = model.layoutOffset;
          break;
        case ChatScrollObserverRefIndexType.itemIndex:
          final model = observerController.observeItem(
            sliverContext: sliverContext,
            index: _refItemIndex,
          );
          if (model == null) return;
          _innerRefItemIndex = _refItemIndex;
          _innerRefItemIndexAfterUpdate = _refItemIndexAfterUpdate;
          _innerRefItemLayoutOffset = model.layoutOffset;
          break;
      }
  }
  // Record value.
  innerIsNeedFixedPosition = true;
  innerRefItemIndex = _innerRefItemIndex;
  innerRefItemIndexAfterUpdate = _innerRefItemIndexAfterUpdate;
  innerRefItemLayoutOffset = _innerRefItemLayoutOffset;
  this.customAdjustPosition = customAdjustPosition;
  this.customAdjustPositionDelta = customAdjustPositionDelta;

  // When the heights of items are similar, the viewport will not call
  // [performLayout], In this case, the [adjustPositionForNewDimensions] of
  // [ScrollPhysics] will not be called, which makes the function of keeping
  // position invalid.
  //
  // So here let it record a layout-time correction to the scroll offset, and
  // call [markNeedsLayout] to prompt the viewport to be re-layout to solve
  // the above problem.
  //
  // Related issue
  // https://github.com/fluttercandies/flutter_scrollview_observer/issues/64
  final ctx = observerController.fetchSliverContext();
  if (ctx == null) return;
  final obj = ObserverUtils.findRenderObject(ctx);
  if (obj == null) return;
  final viewport = ObserverUtils.findViewport(obj);
  if (viewport == null) return;
  if (!viewport.offset.hasPixels) return;
  viewport.offset.correctBy(0);
  viewport.markNeedsLayout();
}