update method

  1. @override
(DiffReviewModel, Cmd?) update(
  1. Msg msg
)
override

Updates the component state in response to a message.

Returns the updated component (often this) and an optional command.

Implementation

@override
(DiffReviewModel, Cmd?) update(Msg msg) {
  switch (msg) {
    case DiffReviewSelectMsg(:final key):
      return (_select(key), null);
    case DiffReviewClearSelectionMsg():
      return (_select(null), null);
    case DiffReviewMoveMsg(:final delta):
      if (delta == 0) return (this, null);
      final keys = document.navigation(
        selected?.side ?? DiffCommentSide.right,
      );
      if (keys.isEmpty) return (this, null);
      final current = selected == null
          ? -1
          : document.navigationIndex(selected!.side, selected!);
      final index = current < 0
          ? (delta > 0 ? 0 : keys.length - 1)
          : (current + delta).clamp(0, keys.length - 1);
      return (_select(keys[index]), null);
    case DiffReviewSideMsg(:final side):
      final key = selected;
      if (key == null || key.side == side) return (this, null);
      final counterpart = document.counterpart(key);
      if (counterpart != null) return (_select(counterpart), null);
      final anchor = selectedAnchor;
      if (anchor == null || diff.viewMode != DiffViewMode.sideBySide) {
        return (this, null);
      }
      for (final candidate in diff.layout.anchorsAtRow(anchor.renderLine)) {
        if (candidate.side == side) {
          return (_select(candidate.key), null);
        }
      }
      return (this, null);
    case DiffReviewToggleRangeMsg():
      if (selected == null) return (this, null);
      return (
        DiffReviewModel._(
          document,
          diff,
          threads,
          selected,
          rangeStart == null ? selected : null,
          expandedThreadIds,
        ),
        null,
      );
    case DiffReviewClearRangeMsg():
      if (rangeStart == null) return (this, null);
      return (
        DiffReviewModel._(
          document,
          diff,
          threads,
          selected,
          null,
          expandedThreadIds,
        ),
        null,
      );
    case DiffReviewExpandMsg(:final threadId, :final expanded):
      if (!threads.containsKey(threadId) ||
          expandedThreadIds.contains(threadId) == expanded) {
        return (this, null);
      }
      final ids = {...expandedThreadIds};
      expanded ? ids.add(threadId) : ids.remove(threadId);
      return (
        DiffReviewModel._(
          document,
          diff,
          threads,
          selected,
          rangeStart,
          Set.unmodifiable(ids),
        ),
        null,
      );
    case DiffReviewThreadsMsg():
      if (msg.documentId != document.id ||
          msg.revision != document.revision) {
        return (this, null);
      }
      final next = _threadMap(msg.threads);
      return (
        DiffReviewModel._(
          document,
          diff,
          next,
          selected,
          rangeStart,
          Set.unmodifiable(expandedThreadIds.where(next.containsKey)),
        ),
        null,
      );
    case DiffReviewLoadMsg():
      final next = DiffReviewModel(
        documentId: msg.documentId,
        revision: msg.revision,
        diff: msg.diff,
        threads: msg.threads,
      );
      if (document.id != msg.documentId ||
          document.revision != msg.revision) {
        return (next, null);
      }
      final key = selected != null && next.document.contains(selected!)
          ? selected
          : null;
      final start =
          key != null &&
              rangeStart != null &&
              next.document.contains(rangeStart!)
          ? rangeStart
          : null;
      return (
        DiffReviewModel._(
          next.document,
          next.diff,
          next.threads,
          key,
          start,
          Set.unmodifiable(expandedThreadIds.where(next.threads.containsKey)),
        ),
        null,
      );
    case DiffReviewPresentationMsg():
      final width = msg.width ?? diff.width;
      final height = msg.height ?? diff.height;
      final mode = msg.viewMode ?? diff.viewMode;
      final wrap = msg.wrapLines ?? diff.wrapLines;
      if (width <= 0 || height <= 0) {
        throw ArgumentError('Review viewport dimensions must be positive.');
      }
      final geometryChanged =
          width != diff.width ||
          mode != diff.viewMode ||
          wrap != diff.wrapLines;
      if (!geometryChanged && height == diff.height) return (this, null);
      final next = geometryChanged
          ? diff
                .copyWith(
                  width: width,
                  height: height,
                  viewMode: mode,
                  wrapLines: wrap,
                  horizontalOffset: mode != diff.viewMode ? 0 : null,
                  viewport: diff.viewport.copyWith(
                    width: width,
                    height: height,
                  ),
                )
                .rerender()
          : diff.copyWith(
              height: height,
              viewport: diff.viewport.copyWith(height: height),
            );
      return (
        DiffReviewModel._(
          document,
          next,
          threads,
          selected,
          rangeStart,
          expandedThreadIds,
        ),
        null,
      );
    default:
      final (next, cmd) = diff.update(msg);
      return (
        identical(next, diff)
            ? this
            : DiffReviewModel._(
                document,
                next,
                threads,
                selected,
                rangeStart,
                expandedThreadIds,
              ),
        cmd,
      );
  }
}