import 'package:flutter/material.dart'; import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:scrobbles/models/data/topartists.dart'; import 'package:scrobbles/ui/widgets/abstracts/custom_line_chart.dart'; class ChartTopArtistsStream extends CustomLineChart { const ChartTopArtistsStream({super.key, required this.chartData}); final TopArtistsData chartData; @override double get verticalTicksInterval => 10; @override String get verticalAxisTitleSuffix => '%'; @override Widget build(BuildContext context) { if (chartData.topArtistsStream.keys.isEmpty) { return SizedBox( height: chartHeight, ); } final horizontalScale = getHorizontalScaleFromDates(chartData.topArtistsStream.keys); return SizedBox( height: chartHeight, child: LineChart( LineChartData( lineBarsData: getDataStreamLine(), betweenBarsData: getBetweenBarsData(), borderData: noBorderData, gridData: horizontalGridData, titlesData: getTitlesData(), lineTouchData: const LineTouchData(enabled: false), minX: horizontalScale['min'], maxX: horizontalScale['max'], maxY: getNextRoundNumber(getMaxVerticalValue(), verticalTicksInterval), minY: 0, ), duration: const Duration(milliseconds: 250), ), ); } double getMaxVerticalValue() { double maxValue = 0; for (var dateAsString in chartData.topArtistsStream.keys) { double totalValue = 0.0; final List<TopArtistsStreamDataValue> artists = chartData.topArtistsStream[dateAsString] ?? []; for (var artist in artists) { final double value = artist.value; totalValue = totalValue + value; } if (totalValue > maxValue) { maxValue = totalValue; } } return maxValue; } List<LineChartBarData> getDataStreamLine() { final int artistsCount = chartData.topArtistsStream[chartData.topArtistsStream.keys.first]?.length ?? 0; List<LineChartBarData> lines = []; LineChartBarData getZeroHorizontalLine() { final baseColor = getColorFromIndex(0); final borderColor = baseColor.darken(20); List<FlSpot> spots = []; for (var dateAsString in chartData.topArtistsStream.keys) { final double date = DateTime.parse(dateAsString).millisecondsSinceEpoch.toDouble(); spots.add(FlSpot(date, 0)); } return LineChartBarData( color: borderColor, dotData: const FlDotData(show: false), spots: spots, ); } // First horizontal "zero" line lines.add(getZeroHorizontalLine()); LineChartBarData getLinesFromIndex(int index) { final baseColor = getColorFromIndex(index); final borderColor = baseColor.darken(20); List<FlSpot> spots = []; for (var dateAsString in chartData.topArtistsStream.keys) { final double date = DateTime.parse(dateAsString).millisecondsSinceEpoch.toDouble(); List<TopArtistsStreamDataValue> artists = chartData.topArtistsStream[dateAsString] ?? []; double value = 0; for (int i = 0; i <= index; i++) { value = value + artists[i].value; } spots.add(FlSpot(date, value)); } return LineChartBarData( isCurved: true, curveSmoothness: 0.25, color: borderColor, dotData: const FlDotData(show: false), spots: spots, ); } Iterable<int>.generate(artistsCount) .toList() .map((index) => lines.add(getLinesFromIndex(index))) .toList(); return lines; } List<BetweenBarsData> getBetweenBarsData() { final int artistsCount = chartData.topArtistsStream[chartData.topArtistsStream.keys.first]?.length ?? 0; return Iterable<int>.generate(artistsCount) .toList() .map((index) => BetweenBarsData( fromIndex: index, toIndex: index + 1, color: getColorFromIndex(index), )) .toList(); } @override Widget getHorizontalTitlesWidget(double value, TitleMeta meta) { return getHorizontalTitlesWidgetWithDate(value, meta); } }