mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-23 09:16:54 +00:00
Refactor network chart
This commit is contained in:
parent
11e58981b5
commit
5ca58a0cd3
|
@ -100,7 +100,11 @@
|
|||
"chart": {
|
||||
"month": "Month",
|
||||
"day": "Day",
|
||||
"hour": "Hour"
|
||||
"hour": "Hour",
|
||||
"cpu_title": "CPU Usage",
|
||||
"network_title": "Network Usage",
|
||||
"in": "In",
|
||||
"out": "Out"
|
||||
},
|
||||
"settings": {
|
||||
"allow_autoupgrade": "Allow auto-upgrade",
|
||||
|
|
|
@ -100,7 +100,11 @@
|
|||
"chart": {
|
||||
"month": "Месяц",
|
||||
"day": "День",
|
||||
"hour": "Час"
|
||||
"hour": "Час",
|
||||
"cpu_title": "Использование процессора",
|
||||
"network_title": "Использование сети",
|
||||
"in": "Получено",
|
||||
"out": "Отправлено"
|
||||
},
|
||||
"settings": {
|
||||
"allow_autoupgrade": "Разрешить авто-обноления",
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/ui/components/error/error.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
|
||||
|
@ -14,15 +11,9 @@ class SimpleBlocObserver extends BlocObserver {
|
|||
final Object error,
|
||||
final StackTrace stackTrace,
|
||||
) {
|
||||
final NavigatorState navigator = getIt.get<NavigationService>().navigator!;
|
||||
|
||||
navigator.push(
|
||||
materialRoute(
|
||||
BrandError(
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
),
|
||||
),
|
||||
getIt<NavigationService>().showSnackBar(
|
||||
'Bloc error: ${error.toString()}',
|
||||
);
|
||||
super.onError(bloc, error, stackTrace);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class _Chart extends StatelessWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'CPU Usage',
|
||||
'providers.server.chart.cpu_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
|
@ -36,19 +36,40 @@ class _Chart extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 1),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
BrandText.small('Public Network interface bytes per sec'),
|
||||
const SizedBox(width: 10),
|
||||
const Legend(color: Colors.red, text: 'IN'),
|
||||
const SizedBox(width: 5),
|
||||
const Legend(color: Colors.green, text: 'OUT'),
|
||||
],
|
||||
const SizedBox(height: 8),
|
||||
FilledCard(
|
||||
clipped: false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'providers.server.chart.network_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Legend(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
text: 'providers.server.chart.in'.tr()),
|
||||
const SizedBox(width: 5),
|
||||
Legend(
|
||||
color: Theme.of(context).colorScheme.tertiary,
|
||||
text: 'providers.server.chart.out'.tr()),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
getBandwidthChart(state),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
getBandwidthChart(state),
|
||||
];
|
||||
} else {
|
||||
throw 'wrong state';
|
||||
|
@ -81,6 +102,7 @@ class _Chart extends StatelessWidget {
|
|||
'providers.server.chart.hour'.tr()
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
...charts,
|
||||
],
|
||||
);
|
||||
|
@ -129,7 +151,10 @@ class Legend extends StatelessWidget {
|
|||
children: [
|
||||
_ColoredBox(color: color),
|
||||
const SizedBox(width: 5),
|
||||
BrandText.small(text),
|
||||
Text(
|
||||
text,
|
||||
style: Theme.of(context).textTheme.labelSmall,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -146,9 +171,11 @@ class _ColoredBox extends StatelessWidget {
|
|||
width: 10,
|
||||
height: 10,
|
||||
decoration: BoxDecoration(
|
||||
color: color.withOpacity(0.3),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: color.withOpacity(0.4),
|
||||
border: Border.all(
|
||||
color: color,
|
||||
width: 1.5,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
import 'package:selfprivacy/config/text_themes.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/hetzner_metrics.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_details/charts/bottom_title.dart';
|
||||
|
||||
|
@ -33,91 +33,174 @@ class NetworkChart extends StatelessWidget {
|
|||
}
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => SizedBox(
|
||||
height: 150,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: LineChart(
|
||||
LineChartData(
|
||||
lineTouchData: LineTouchData(enabled: false),
|
||||
lineBarsData: [
|
||||
LineChartBarData(
|
||||
spots: getSpots(listData[0]),
|
||||
isCurved: true,
|
||||
barWidth: 1,
|
||||
color: Colors.red,
|
||||
dotData: FlDotData(
|
||||
show: false,
|
||||
),
|
||||
),
|
||||
LineChartBarData(
|
||||
spots: getSpots(listData[1]),
|
||||
isCurved: true,
|
||||
barWidth: 1,
|
||||
color: Colors.green,
|
||||
dotData: FlDotData(
|
||||
show: false,
|
||||
),
|
||||
),
|
||||
],
|
||||
minY: 0,
|
||||
maxY: [
|
||||
...listData[0].map((final e) => e.value),
|
||||
...listData[1].map((final e) => e.value)
|
||||
].reduce(max) *
|
||||
1.2,
|
||||
minX: listData[0].length - 200,
|
||||
titlesData: FlTitlesData(
|
||||
topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
interval: 20,
|
||||
reservedSize: 50,
|
||||
getTitlesWidget: (final value, final titleMeta) => Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: RotatedBox(
|
||||
quarterTurns: 1,
|
||||
child: Text(
|
||||
bottomTitle(
|
||||
value.toInt(),
|
||||
listData[0],
|
||||
period,
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.purple,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
Widget build(final BuildContext context) => LineChart(
|
||||
LineChartData(
|
||||
lineTouchData: LineTouchData(
|
||||
enabled: true,
|
||||
touchTooltipData: LineTouchTooltipData(
|
||||
tooltipBgColor: Theme.of(context).colorScheme.surface,
|
||||
tooltipPadding: const EdgeInsets.all(8),
|
||||
getTooltipItems: (final List<LineBarSpot> touchedBarSpots) {
|
||||
final List<LineTooltipItem> res = [];
|
||||
|
||||
bool timeShown = false;
|
||||
|
||||
for (final spot in touchedBarSpots) {
|
||||
final value = spot.y;
|
||||
final date = listData[0][spot.x.toInt()].time;
|
||||
|
||||
res.add(
|
||||
LineTooltipItem(
|
||||
'${timeShown ? '' : DateFormat('HH:mm dd.MM.yyyy').format(date)} ${spot.barIndex == 0 ? 'providers.server.chart.in'.tr() : 'providers.server.chart.out'.tr()} ${DiskSize(byte: value.toInt()).toString()}',
|
||||
TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
showTitles: true,
|
||||
),
|
||||
);
|
||||
|
||||
timeShown = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
),
|
||||
),
|
||||
lineBarsData: [
|
||||
// IN
|
||||
LineChartBarData(
|
||||
spots: getSpots(listData[0]),
|
||||
isCurved: false,
|
||||
barWidth: 2,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
dotData: FlDotData(
|
||||
show: false,
|
||||
),
|
||||
leftTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
reservedSize: 50,
|
||||
getTitlesWidget: (final value, final titleMeta) => Padding(
|
||||
padding: const EdgeInsets.only(right: 5),
|
||||
child: Text(
|
||||
value.toInt().toString(),
|
||||
style: progressTextStyleLight.copyWith(
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? BrandColors.gray4
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
interval: [
|
||||
...listData[0].map((final e) => e.value),
|
||||
...listData[1].map((final e) => e.value)
|
||||
].reduce(max) *
|
||||
2 /
|
||||
10,
|
||||
showTitles: 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,
|
||||
),
|
||||
),
|
||||
),
|
||||
gridData: FlGridData(show: true),
|
||||
// OUT
|
||||
LineChartBarData(
|
||||
spots: getSpots(listData[1]),
|
||||
isCurved: false,
|
||||
barWidth: 2,
|
||||
color: Theme.of(context).colorScheme.tertiary,
|
||||
dotData: FlDotData(
|
||||
show: false,
|
||||
),
|
||||
belowBarData: BarAreaData(
|
||||
show: true,
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.tertiary.withOpacity(0.5),
|
||||
Theme.of(context).colorScheme.tertiary.withOpacity(0.0),
|
||||
],
|
||||
begin: Alignment.bottomCenter,
|
||||
end: Alignment.topCenter,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
minY: 0,
|
||||
maxY: [
|
||||
...listData[0].map((final e) => e.value),
|
||||
...listData[1].map((final e) => e.value)
|
||||
].reduce(max) *
|
||||
1.2,
|
||||
minX: listData[0].length - 200,
|
||||
titlesData: FlTitlesData(
|
||||
topTitles: 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: Text(
|
||||
bottomTitle(
|
||||
value.toInt(),
|
||||
listData[0],
|
||||
period,
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
showTitles: true,
|
||||
),
|
||||
),
|
||||
leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
rightTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
reservedSize: 50,
|
||||
getTitlesWidget: (final value, final titleMeta) => Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: Text(
|
||||
DiskSize(byte: value.toInt()).toString(),
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
interval: [
|
||||
...listData[0].map((final e) => e.value),
|
||||
...listData[1].map((final e) => e.value)
|
||||
].reduce(max) *
|
||||
2 /
|
||||
6.5,
|
||||
showTitles: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
gridData: FlGridData(
|
||||
show: true,
|
||||
drawVerticalLine: true,
|
||||
verticalInterval: 40,
|
||||
horizontalInterval: [
|
||||
...listData[0].map((final e) => e.value),
|
||||
...listData[1].map((final e) => e.value)
|
||||
].reduce(max) *
|
||||
2 /
|
||||
6.5,
|
||||
getDrawingHorizontalLine: (final value) => FlLine(
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
|
||||
strokeWidth: 1,
|
||||
),
|
||||
getDrawingVerticalLine: (final value) => FlLine(
|
||||
color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
|
||||
strokeWidth: 1,
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue