313 lines
11 KiB
Dart
313 lines
11 KiB
Dart
|
import 'package:double_back_to_close_app/double_back_to_close_app.dart';
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||
|
import 'package:IQ/app/global/converted_bytes.dart';
|
||
|
import 'package:IQ/app/global/global_snackbar.dart';
|
||
|
import 'package:IQ/app/global/text_widget.dart';
|
||
|
import 'package:IQ/app/modules/LiveData/models/livedata.dart';
|
||
|
import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart';
|
||
|
import 'package:IQ/app/modules/home/providers/user.dart';
|
||
|
import 'package:IQ/main.dart';
|
||
|
import 'package:syncfusion_flutter_charts/charts.dart';
|
||
|
import 'package:flutter/material.dart' as td;
|
||
|
import 'package:IQ/app/global/static_informs.dart';
|
||
|
import 'package:get/get.dart';
|
||
|
import 'dart:convert';
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_client_sse/flutter_client_sse.dart';
|
||
|
import 'dart:async';
|
||
|
|
||
|
class LiveDataView extends StatefulWidget {
|
||
|
const LiveDataView({super.key});
|
||
|
|
||
|
@override
|
||
|
State<LiveDataView> createState() => _LiveDataViewState();
|
||
|
}
|
||
|
|
||
|
class _LiveDataViewState extends State<LiveDataView> {
|
||
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
||
|
List<LiveData> chartData = [];
|
||
|
late ChartSeriesController _rxChartSeriesController;
|
||
|
late ChartSeriesController _txChartSeriesController;
|
||
|
LiveData? liveData;
|
||
|
TooltipBehavior? tooltipBehavior;
|
||
|
var liveDataUrl = storage.read('liveDataUrl');
|
||
|
var token = storage.read('token');
|
||
|
bool isDataLoaded = false;
|
||
|
|
||
|
getLiveData() {
|
||
|
// I edit on the package on stream closing
|
||
|
SSEClient.subscribeToSSE(
|
||
|
url: "$liveDataUrl$token",
|
||
|
header: {
|
||
|
"Cookie":
|
||
|
'jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2NDMyMTAyMzEsImV4cCI6MTY0MzgxNTAzMX0.U0aCAM2fKE1OVnGFbgAU_UVBvNwOMMquvPY8QaLD138; Path=/; Expires=Wed, 02 Feb 2022 15:17:11 GMT; HttpOnly; SameSite=Strict',
|
||
|
"Accept": "text/event-stream",
|
||
|
"Cache-Control": "no-cache",
|
||
|
},
|
||
|
).listen((event) {
|
||
|
liveData = LiveData.fromJson(jsonDecode(event.data!));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
int count = 19;
|
||
|
|
||
|
void _updateDataSource(Timer timer) {
|
||
|
chartData.add(
|
||
|
LiveData(
|
||
|
time: count++,
|
||
|
rxRate: (liveData?.rxRate)! * 8,
|
||
|
txRate: (liveData?.txRate)! * 8,
|
||
|
rx: liveData?.rx,
|
||
|
tx: liveData?.tx,
|
||
|
),
|
||
|
);
|
||
|
chartData.removeAt(0);
|
||
|
|
||
|
_rxChartSeriesController.updateDataSource(
|
||
|
addedDataIndexes: [chartData.length - 1],
|
||
|
removedDataIndexes: [0],
|
||
|
);
|
||
|
_txChartSeriesController.updateDataSource(
|
||
|
addedDataIndexes: [chartData.length - 1],
|
||
|
removedDataIndexes: [0],
|
||
|
);
|
||
|
}
|
||
|
|
||
|
List<LiveData> getCartData() {
|
||
|
List<LiveData> sampleChartData = [];
|
||
|
for (int i = 1; i < 19; i++) {
|
||
|
sampleChartData.add(
|
||
|
LiveData(
|
||
|
time: i,
|
||
|
rxRate: 0,
|
||
|
txRate: 0,
|
||
|
rx: 0,
|
||
|
tx: 0,
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
return sampleChartData;
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
chartData = getCartData();
|
||
|
getLiveData();
|
||
|
if (liveData != null) {
|
||
|
Timer.periodic(const Duration(seconds: 1), _updateDataSource);
|
||
|
}
|
||
|
tooltipBehavior = TooltipBehavior(enable: true);
|
||
|
super.initState();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void dispose() {
|
||
|
super.dispose();
|
||
|
isDataLoaded = false;
|
||
|
SSEClient.unsubscribeFromSSE();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
var stackedContainer = Container(
|
||
|
height: 250,
|
||
|
decoration: BoxDecoration(
|
||
|
color: brandColor,
|
||
|
image: const DecorationImage(
|
||
|
image: AssetImage('assets/background.png'),
|
||
|
fit: BoxFit.fill,
|
||
|
),
|
||
|
),
|
||
|
child: Column(
|
||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
|
children: [
|
||
|
SizedBox(height: MediaQuery.of(context).viewPadding.top),
|
||
|
Container(
|
||
|
margin: const EdgeInsets.symmetric(
|
||
|
horizontal: 15,
|
||
|
),
|
||
|
child: Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
|
children: [
|
||
|
Container(
|
||
|
margin: const EdgeInsets.only(
|
||
|
top: 5,
|
||
|
right: 15,
|
||
|
),
|
||
|
child: Row(
|
||
|
children: [
|
||
|
SvgPicture.asset(
|
||
|
"assets/2/icon.svg",
|
||
|
height: 20,
|
||
|
width: 71.16,
|
||
|
),
|
||
|
const SizedBox(width: 10),
|
||
|
Image.asset("assets/logo.png"),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(width: 10),
|
||
|
Row(
|
||
|
children: [
|
||
|
Text(
|
||
|
user?.data?.firstname ?? ' . . . ',
|
||
|
style: const TextStyle(
|
||
|
fontSize: 20,
|
||
|
color: Colors.white,
|
||
|
fontWeight: FontWeight.normal,
|
||
|
),
|
||
|
),
|
||
|
IconButton(
|
||
|
onPressed: () {
|
||
|
scaffoldKey.currentState?.openEndDrawer();
|
||
|
},
|
||
|
icon: const Icon(
|
||
|
Icons.menu,
|
||
|
color: Colors.white,
|
||
|
size: 40,
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
Column(
|
||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||
|
children: [
|
||
|
SvgPicture.asset(
|
||
|
'assets/dataflow.svg',
|
||
|
color: Colors.white,
|
||
|
fit: BoxFit.contain,
|
||
|
height: 80,
|
||
|
width: 80,
|
||
|
),
|
||
|
TextWidget(
|
||
|
text: 'data_stream_screen_title'.tr,
|
||
|
color: Colors.white,
|
||
|
fontSize: 24,
|
||
|
fontWeight: FontWeight.w300,
|
||
|
textAlign: TextAlign.center,
|
||
|
),
|
||
|
const SizedBox(height: 10),
|
||
|
],
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
);
|
||
|
return Directionality(
|
||
|
textDirection:
|
||
|
defaultLocale != "en" ? td.TextDirection.ltr : td.TextDirection.rtl,
|
||
|
child: Scaffold(
|
||
|
backgroundColor: backgroundColor,
|
||
|
drawerScrimColor: Colors.black.withOpacity(0.7),
|
||
|
key: scaffoldKey,
|
||
|
endDrawer: const DrawerSideView(),
|
||
|
drawerEdgeDragWidth: widthSize(context),
|
||
|
body: DoubleBackToCloseApp(
|
||
|
snackBar: snackBar,
|
||
|
child: Stack(
|
||
|
children: [
|
||
|
Column(
|
||
|
children: [
|
||
|
const SizedBox(height: 270),
|
||
|
Container(
|
||
|
height: 400,
|
||
|
decoration: BoxDecoration(
|
||
|
color: Colors.white,
|
||
|
borderRadius: const BorderRadius.all(
|
||
|
Radius.circular(20),
|
||
|
),
|
||
|
border: Border.all(
|
||
|
color: borderColor,
|
||
|
width: 1,
|
||
|
),
|
||
|
),
|
||
|
padding: const EdgeInsets.all(20),
|
||
|
margin: const EdgeInsets.only(right: 10, left: 10),
|
||
|
child: Container(
|
||
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
||
|
margin: const EdgeInsets.symmetric(vertical: 20),
|
||
|
child: SfCartesianChart(
|
||
|
legend: Legend(
|
||
|
isVisible: true,
|
||
|
position: LegendPosition.bottom,
|
||
|
),
|
||
|
tooltipBehavior: tooltipBehavior,
|
||
|
backgroundColor: Colors.white,
|
||
|
borderColor: borderColor,
|
||
|
borderWidth: 0,
|
||
|
isTransposed: false,
|
||
|
margin: const EdgeInsets.symmetric(
|
||
|
horizontal: 15,
|
||
|
),
|
||
|
plotAreaBackgroundColor: Colors.white,
|
||
|
plotAreaBorderColor: borderColor,
|
||
|
plotAreaBorderWidth: 0,
|
||
|
selectionGesture: ActivationMode.singleTap,
|
||
|
selectionType: SelectionType.point,
|
||
|
enableAxisAnimation: true,
|
||
|
primaryXAxis: NumericAxis(
|
||
|
majorGridLines: const MajorGridLines(width: 0),
|
||
|
edgeLabelPlacement: EdgeLabelPlacement.shift,
|
||
|
interval: 3,
|
||
|
title: AxisTitle(text: 'Time (seconds)'),
|
||
|
),
|
||
|
primaryYAxis: NumericAxis(
|
||
|
axisLabelFormatter: (AxisLabelRenderDetails details) {
|
||
|
return ChartAxisLabel(
|
||
|
formatBytes(details.value.toInt(), 0),
|
||
|
details.textStyle,
|
||
|
);
|
||
|
},
|
||
|
borderWidth: 1,
|
||
|
borderColor: Colors.white,
|
||
|
edgeLabelPlacement: EdgeLabelPlacement.shift,
|
||
|
labelAlignment: LabelAlignment.center,
|
||
|
majorGridLines: MajorGridLines(
|
||
|
width: 1,
|
||
|
color: borderColor,
|
||
|
),
|
||
|
axisLine: const AxisLine(width: 0),
|
||
|
majorTickLines: const MajorTickLines(size: 0),
|
||
|
),
|
||
|
series: <LineSeries<LiveData, int>>[
|
||
|
LineSeries<LiveData, int>(
|
||
|
name: "Upload",
|
||
|
onRendererCreated:
|
||
|
(ChartSeriesController chartSeriesController) {
|
||
|
_txChartSeriesController = chartSeriesController;
|
||
|
},
|
||
|
dataSource: chartData,
|
||
|
color: brandColor,
|
||
|
xValueMapper: (LiveData data, _) => data.time,
|
||
|
yValueMapper: (LiveData data, _) => data.txRate,
|
||
|
),
|
||
|
LineSeries<LiveData, int>(
|
||
|
name: "Download",
|
||
|
onRendererCreated:
|
||
|
(ChartSeriesController chartSeriesController) {
|
||
|
_rxChartSeriesController = chartSeriesController;
|
||
|
},
|
||
|
dataSource: chartData,
|
||
|
color: const Color.fromARGB(255, 255, 12, 12),
|
||
|
xValueMapper: (LiveData data, _) => data.time,
|
||
|
yValueMapper: (LiveData data, _) => data.rxRate,
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
stackedContainer,
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|