122 lines
3.6 KiB
Dart
122 lines
3.6 KiB
Dart
import 'terminal_screen_patch.dart';
|
|
import 'terminal_screen_snapshot.dart';
|
|
|
|
/// Experiment-only state reducer for backend-authored screen snapshots and patches.
|
|
class TerminalScreenState {
|
|
const TerminalScreenState({
|
|
required this.sessionId,
|
|
required this.screenVersion,
|
|
required this.sourceSequence,
|
|
required this.rows,
|
|
required this.columns,
|
|
required this.cursorRow,
|
|
required this.cursorColumn,
|
|
required this.cursorVisible,
|
|
required this.activeBuffer,
|
|
required this.primaryLines,
|
|
required this.alternateLines,
|
|
});
|
|
|
|
final String sessionId;
|
|
final int screenVersion;
|
|
final int sourceSequence;
|
|
final int rows;
|
|
final int columns;
|
|
final int cursorRow;
|
|
final int cursorColumn;
|
|
final bool cursorVisible;
|
|
final String activeBuffer;
|
|
final List<String> primaryLines;
|
|
final List<String> alternateLines;
|
|
|
|
factory TerminalScreenState.fromSnapshot(TerminalScreenSnapshot snapshot) {
|
|
List<String> materialize(TerminalScreenBuffer? buffer) {
|
|
final lines = List<String>.filled(snapshot.rows, '');
|
|
final viewport = buffer?.viewport ?? const <TerminalScreenLine>[];
|
|
for (final line in viewport) {
|
|
if (line.index >= 0 && line.index < lines.length) {
|
|
lines[line.index] = line.text;
|
|
}
|
|
}
|
|
|
|
return lines;
|
|
}
|
|
|
|
return TerminalScreenState(
|
|
sessionId: snapshot.sessionId,
|
|
screenVersion: snapshot.screenVersion,
|
|
sourceSequence: snapshot.sourceSequence,
|
|
rows: snapshot.rows,
|
|
columns: snapshot.columns,
|
|
cursorRow: snapshot.cursorRow,
|
|
cursorColumn: snapshot.cursorColumn,
|
|
cursorVisible: snapshot.cursorVisible,
|
|
activeBuffer: snapshot.activeBuffer,
|
|
primaryLines: materialize(snapshot.primaryBuffer),
|
|
alternateLines: materialize(snapshot.alternateBuffer),
|
|
);
|
|
}
|
|
|
|
bool canApplyPatch(TerminalScreenPatch patch) {
|
|
return sessionId == patch.sessionId &&
|
|
screenVersion == patch.baseScreenVersion;
|
|
}
|
|
|
|
TerminalScreenState applyPatch(TerminalScreenPatch patch) {
|
|
final nextPrimaryLines = List<String>.from(primaryLines, growable: false);
|
|
final nextAlternateLines = List<String>.from(
|
|
alternateLines,
|
|
growable: false,
|
|
);
|
|
final targetLines = patch.activeBuffer == 'alternate'
|
|
? nextAlternateLines
|
|
: nextPrimaryLines;
|
|
for (final operation in patch.operations) {
|
|
if (operation.type != 'replace_lines') {
|
|
continue;
|
|
}
|
|
|
|
for (var index = 0; index < operation.lines.length; index += 1) {
|
|
final row = operation.startRow + index;
|
|
if (row >= 0 && row < targetLines.length) {
|
|
targetLines[row] = operation.lines[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
return TerminalScreenState(
|
|
sessionId: sessionId,
|
|
screenVersion: patch.screenVersion,
|
|
sourceSequence: patch.sourceSequence,
|
|
rows: patch.rows,
|
|
columns: patch.columns,
|
|
cursorRow: patch.cursorRow,
|
|
cursorColumn: patch.cursorColumn,
|
|
cursorVisible: patch.cursorVisible,
|
|
activeBuffer: patch.activeBuffer,
|
|
primaryLines: nextPrimaryLines,
|
|
alternateLines: nextAlternateLines,
|
|
);
|
|
}
|
|
|
|
String toDisplayText() {
|
|
final lines = activeBuffer == 'alternate' ? alternateLines : primaryLines;
|
|
return renderTerminalScreenText(
|
|
lines: lines,
|
|
cursorRow: cursorRow,
|
|
cursorColumn: cursorColumn,
|
|
cursorVisible: cursorVisible,
|
|
);
|
|
}
|
|
|
|
String toReplaySequence() {
|
|
final lines = activeBuffer == 'alternate' ? alternateLines : primaryLines;
|
|
return buildTerminalScreenReplay(
|
|
lines: lines,
|
|
cursorRow: cursorRow,
|
|
cursorColumn: cursorColumn,
|
|
cursorVisible: cursorVisible,
|
|
);
|
|
}
|
|
}
|