view method
Renders the current model state for display.
This method is called after every update to refresh the screen. It should return either a String or a View object.
Guidelines
- Keep view functions pure - no side effects
- View should only depend on model state
- Use string interpolation or StringBuffer for complex views
- Consider terminal width/height for responsive layouts
Example
@override
String view() {
final buffer = StringBuffer();
// Header
buffer.writeln('╔════════════════════════════╗');
buffer.writeln('║ My Application ║');
buffer.writeln('╚════════════════════════════╝');
buffer.writeln();
// Content
if (loading) {
buffer.writeln('Loading...');
} else {
for (final item in items) {
final prefix = item == selectedItem ? '▸ ' : ' ';
buffer.writeln('$prefix$item');
}
}
buffer.writeln();
// Footer
buffer.writeln('↑/↓: Navigate Enter: Select q: Quit');
return buffer.toString();
}
Implementation
@override
String view() {
if (_files.isEmpty) {
return _styles.emptyDirectory
.height(_height)
.maxHeight(_height)
.render('Bummer. No Files Found.');
}
final buffer = StringBuffer();
for (var i = 0; i < _files.length; i++) {
if (i < _min || i > _max) continue;
final file = _files[i];
final isSelected = i == _selected;
final disabled = !canSelect(file.name) && !file.isDirectory;
if (isSelected) {
_renderSelectedRow(buffer, file, disabled);
} else {
_renderNormalRow(buffer, file, disabled);
}
buffer.writeln();
}
// Pad with empty lines to fill height
final lines = buffer.toString().split('\n');
for (var i = lines.length; i <= _height; i++) {
buffer.writeln();
}
return buffer.toString();
}