update method
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,
);
}
}