selfprivacy.org.app/lib/ui/pages/server_details/charts/cpu_chart.dart

213 lines
6.9 KiB
Dart
Raw Normal View History

import 'package:easy_localization/easy_localization.dart';
2022-09-15 15:40:02 +00:00
import 'package:fl_chart/fl_chart.dart';
2024-01-31 05:14:23 +00:00
import 'package:flutter/material.dart';
2022-09-15 15:40:02 +00:00
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
import 'package:selfprivacy/logic/models/metrics.dart';
2022-09-15 15:40:02 +00:00
import 'package:selfprivacy/ui/pages/server_details/charts/bottom_title.dart';
class CpuChart extends StatelessWidget {
const CpuChart({
required this.data,
required this.period,
required this.start,
super.key,
2022-09-15 15:40:02 +00:00
});
final List<TimeSeriesData> data;
final Period period;
final DateTime start;
List<FlSpot> getSpots() {
var i = 0;
final List<FlSpot> res = [];
for (final d in data) {
res.add(FlSpot(i.toDouble(), d.value));
i++;
}
return res;
}
String screenReaderDescription(final BuildContext context) {
final lastData = data.last;
final lastValue = lastData.value;
final averageUsage =
data.map((final e) => e.value).reduce((final a, final b) => a + b) /
data.length;
final maxUsage = data
.map((final e) => e.value)
.reduce((final a, final b) => a > b ? a : b);
final maxUsageTime = data.firstWhere((final e) => e.value == maxUsage).time;
final label = 'resource_chart.cpu_chart_screen_reader_explanation'.tr(
namedArgs: {
'period': 'resource_chart.${period.name}'.tr(),
'lastValue': lastValue.toStringAsFixed(1),
'averageUsage': averageUsage.toStringAsFixed(1),
'maxUsage': maxUsage.toStringAsFixed(1),
'maxUsageTime': DateFormat('HH:mm dd MMMM', context.locale.languageCode)
.format(maxUsageTime),
},
);
return label;
}
2022-09-15 15:40:02 +00:00
@override
Widget build(final BuildContext context) => Semantics(
label: screenReaderDescription(context),
child: LineChart(
LineChartData(
lineTouchData: LineTouchData(
enabled: true,
touchTooltipData: LineTouchTooltipData(
getTooltipColor: (final LineBarSpot _) =>
Theme.of(context).colorScheme.surface,
tooltipPadding: const EdgeInsets.all(8),
getTooltipItems: (final List<LineBarSpot> touchedBarSpots) {
final List<LineTooltipItem> res = [];
2022-09-15 15:40:02 +00:00
for (final spot in touchedBarSpots) {
final value = spot.y;
final date = data[spot.x.toInt()].time;
2022-09-15 15:40:02 +00:00
res.add(
LineTooltipItem(
'${value.toStringAsFixed(2)}% at ${DateFormat('HH:mm dd.MM.yyyy').format(date)}',
TextStyle(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
2022-09-15 15:40:02 +00:00
),
);
}
2022-09-15 15:40:02 +00:00
return res;
},
2022-09-15 15:40:02 +00:00
),
),
lineBarsData: [
LineChartBarData(
spots: getSpots(),
isCurved: false,
barWidth: 2,
color: Theme.of(context).colorScheme.primary,
dotData: const FlDotData(
show: false,
),
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.primary.withOpacity(0.5),
Theme.of(context).colorScheme.primary.withOpacity(0.0),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
2022-09-15 15:40:02 +00:00
),
),
],
minY: 0,
// Maximal value of data by 100 step
maxY: 100,
minX: 0,
titlesData: FlTitlesData(
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
interval: 40,
reservedSize: 30,
getTitlesWidget: (final value, final titleMeta) => Padding(
padding: const EdgeInsets.all(8.0),
child: ExcludeSemantics(
child: Text(
bottomTitle(
value.toInt(),
data,
period,
2022-09-15 15:40:02 +00:00
),
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: Theme.of(context)
.colorScheme
.onSurfaceVariant,
),
),
),
2022-09-15 15:40:02 +00:00
),
showTitles: true,
2022-09-15 15:40:02 +00:00
),
),
leftTitles: const AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
2022-09-15 15:40:02 +00:00
),
rightTitles: const AxisTitles(
sideTitles: SideTitles(
showTitles: false,
),
2022-09-15 15:40:02 +00:00
),
),
gridData: FlGridData(
show: true,
drawVerticalLine: true,
horizontalInterval: 25,
verticalInterval: 40,
getDrawingHorizontalLine: (final value) => FlLine(
2022-09-15 15:40:02 +00:00
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
strokeWidth: 1,
2022-09-15 15:40:02 +00:00
),
getDrawingVerticalLine: (final value) => FlLine(
2022-09-15 15:40:02 +00:00
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
strokeWidth: 1,
2022-09-15 15:40:02 +00:00
),
),
borderData: FlBorderData(
show: true,
border: Border(
bottom: BorderSide(
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
width: 1,
),
left: BorderSide(
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
width: 1,
),
right: BorderSide(
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
width: 1,
),
top: BorderSide(
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
width: 1,
),
2022-09-15 15:40:02 +00:00
),
),
),
),
);
bool checkToShowTitle(
final double minValue,
final double maxValue,
final SideTitles sideTitles,
final double appliedInterval,
final double value,
) {
if (value < 0) {
return false;
} else if (value == 0) {
return true;
}
final localValue = value - minValue;
final v = localValue / 20;
return v - v.floor() == 0;
}
}