Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,15 @@ class MessageColumn extends ColumnData<LogData>
// The current summary is generally the first 200 chars of details.
data.summary!,
theme.regularTextStyle,
brightness: theme.brightness,
),
if (hasSummary && hasDetails())
TextSpan(text: ' • ', style: theme.subtleTextStyle),
if (hasDetails())
...textSpansFromAnsi(
detailsComputed ? data.details! : '<fetching>',
theme.subtleTextStyle,
brightness: theme.brightness,
),
],
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ class DisplayProvider extends StatelessWidget {
children: textSpansFromAnsi(
variable.text ?? '',
theme.subtleFixedFontStyle,
brightness: theme.brightness,
),
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class _ConsoleOutputState extends State<_ConsoleOutput>
children: textSpansFromAnsi(
line.text,
theme.regularTextStyle,
brightness: theme.brightness,
),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class _DisplayProviderState extends State<DisplayProvider> {
children: textSpansFromAnsi(
widget.variable.text!,
theme.subtleFixedFontStyle,
brightness: theme.brightness,
),
),
),
Expand Down
28 changes: 23 additions & 5 deletions packages/devtools_app/lib/src/shared/primitives/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -545,30 +545,48 @@ class DebugTimingLogger {
}
}

List<TextSpan> textSpansFromAnsi(String input, TextStyle defaultStyle) {
List<TextSpan> textSpansFromAnsi(
String input,
TextStyle defaultStyle, {
required Brightness brightness,
}) {
final parser = AnsiParser(input);
return parser.parse().map((entry) {
final styled = entry.bold || entry.fgColor != null || entry.bgColor != null;
return TextSpan(
text: entry.text,
style: styled
? TextStyle(
color: ansiToColor(entry.fgColor),
backgroundColor: ansiToColor(entry.bgColor),
color: ansiToColor(entry.fgColor, brightness: brightness),
backgroundColor: ansiToColor(entry.bgColor, brightness: brightness),
fontWeight: entry.bold ? FontWeight.bold : FontWeight.normal,
)
: defaultStyle,
);
}).toList();
}

Color? ansiToColor(List<int>? ansiInput) {
Color? ansiToColor(List<int>? ansiInput, {required Brightness brightness}) {
if (ansiInput == null) {
return null;
}

assert(ansiInput.length == 3, 'Ansi color list should contain 3 elements');
return Color.fromRGBO(ansiInput[0], ansiInput[1], ansiInput[2], 1);
final color = Color.fromRGBO(ansiInput[0], ansiInput[1], ansiInput[2], 1);
return _ansiColorVisibleOnBackground(color, brightness);
}

/// Adjusts ANSI colors that would be unreadable against the DevTools background.
Color _ansiColorVisibleOnBackground(Color color, Brightness brightness) {
final hsl = HSLColor.fromColor(color);
if (brightness == Brightness.dark) {
if (hsl.lightness < 0.2) {
return hsl.withLightness(0.65).toColor();
}
} else if (hsl.lightness > 0.85) {
return hsl.withLightness(0.25).toColor();
}
return color;
}

/// An extension on [LogicalKeySet] to provide user-facing names for key
Expand Down
29 changes: 29 additions & 0 deletions packages/devtools_app/test/shared/primitives/utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,35 @@ void main() {
equals('http://127.0.0.1:9100'),
);
});

group('ansiToColor', () {
test('lightens dark colors on dark backgrounds', () {
const black = Color.fromRGBO(0, 0, 0, 1);
final adjusted = ansiToColor([0, 0, 0], brightness: Brightness.dark)!;
expect(adjusted, isNot(equals(black)));
expect(adjusted.computeLuminance(), greaterThan(0.2));
});

test('darkens light colors on light backgrounds', () {
const white = Color.fromRGBO(255, 255, 255, 1);
final adjusted = ansiToColor([255, 255, 255], brightness: Brightness.light)!;
expect(adjusted, isNot(equals(white)));
expect(adjusted.computeLuminance(), lessThan(0.5));
});

test('preserves readable colors', () {
const red = Color.fromRGBO(187, 0, 0, 1);
expect(
ansiToColor([187, 0, 0], brightness: Brightness.dark),
equals(red),
);
expect(
ansiToColor([187, 0, 0], brightness: Brightness.light),
equals(red),
);
});
});
});
}

class _SubtractionResult {
Expand Down