From 187fcf4abf51e1fd4cda12c57b8209701df853dc Mon Sep 17 00:00:00 2001 From: "Sanders (aider)" Date: Sun, 4 May 2025 14:39:18 +0300 Subject: [PATCH] fix: persist pie slice selection on tap --- .../lib/widgets/spending_pie_chart.dart | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/finance_app/lib/widgets/spending_pie_chart.dart b/finance_app/lib/widgets/spending_pie_chart.dart index 2f00436..693735c 100644 --- a/finance_app/lib/widgets/spending_pie_chart.dart +++ b/finance_app/lib/widgets/spending_pie_chart.dart @@ -69,23 +69,23 @@ class SpendingPieChart extends StatelessWidget { PieChartData( // Handle touch events on the pie chart pieTouchData: PieTouchData( - touchCallback: (FlTouchEvent event, pieTouchResponse) { - // Ignore events not related to interaction - if (!event.isInterestedForInteractions || - pieTouchResponse == null || - pieTouchResponse.touchedSection == null) { - // If touch ends outside a section, deselect - if (event is FlPanEndEvent || event is FlTapUpEvent) { + touchCallback: (FlTouchEvent event, PieTouchResponse? pieTouchResponse) { + // We are only interested in TapUp events to trigger selection changes + if (event is FlTapUpEvent) { + final section = pieTouchResponse?.touchedSection; + if (section != null) { + // Tap occurred ON a section + final touchedIndex = section.touchedSectionIndex; + // Toggle selection: if tapped section is already selected, deselect (-1), otherwise select it. + onSelectPieCategory(touchedIndex == selectedPieIndex ? -1 : touchedIndex); + } else { + // Tap occurred OUTSIDE any section + // Deselect if something was selected if (selectedPieIndex != -1) { - onSelectPieCategory(-1); // Deselect + onSelectPieCategory(-1); } } - return; } - // Get the index of the touched section - final touchedIndex = pieTouchResponse.touchedSection!.touchedSectionIndex; - // Call the callback, toggling selection if the same slice is touched again - onSelectPieCategory(touchedIndex == selectedPieIndex ? -1 : touchedIndex); }, ), borderData: FlBorderData(show: false), // No border around the chart @@ -130,6 +130,11 @@ class SpendingPieChart extends StatelessWidget { // Builds the text displayed in the center when a slice is selected Widget _buildCenterText(BuildContext context, NumberFormat formatter) { final theme = Theme.of(context); + // Check if selectedPieIndex is valid before accessing categories + if (selectedPieIndex < 0 || selectedPieIndex >= categories.length) { + // Return an empty container or default text if index is invalid + return _buildDefaultCenterText(context, formatter); + } final selectedCategory = categories[selectedPieIndex]; return Column( mainAxisAlignment: MainAxisAlignment.center, @@ -189,6 +194,10 @@ class SpendingPieChart extends StatelessWidget { final isDark = Theme.of(context).brightness == Brightness.dark; final theme = Theme.of(context); final isSelected = index == selectedPieIndex; // Check if this item is selected + // Check if index is valid before accessing categories + if (index < 0 || index >= categories.length) { + return const SizedBox.shrink(); // Return empty if index is invalid + } final category = categories[index]; // Calculate percentage, handle totalExpenses being zero final percentage = totalExpenses > 0 ? (category.amount / totalExpenses * 100) : 0.0; @@ -256,6 +265,12 @@ class SpendingPieChart extends StatelessWidget { final isDark = Theme.of(context).brightness == Brightness.dark; return List.generate(categories.length, (i) { + // Check if index is valid before accessing categories + if (i < 0 || i >= categories.length) { + // This should ideally not happen if List.generate is used correctly, + // but adding a safeguard. + return PieChartSectionData(); // Return an empty section + } final isTouched = i == selectedPieIndex; // Check if this slice is selected // Make selected slice slightly larger final double radius = isTouched ? 65 : 55;