From f685afaa98abcb98bcba4d7b977ec8b425b3abf9 Mon Sep 17 00:00:00 2001 From: Prajakta Kamble Date: Sun, 28 Jun 2026 08:53:59 +0530 Subject: [PATCH 1/4] fix: cancel stream subscriptions in BoardStateProvider dispose UsbSerial.usbEventStream?.listen() and Connectivity() .onConnectivityChanged.listen() were called without storing the returned StreamSubscription objects, so they could never be cancelled. This causes a memory leak on every hot-restart or re-initialization as subscriptions accumulate. Fix: store both subscriptions in _usbSubscription and _connectivitySubscription fields, and cancel them in dispose(). --- lib/providers/board_state_provider.dart | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/providers/board_state_provider.dart b/lib/providers/board_state_provider.dart index ec0f87c50..0ca7c56eb 100644 --- a/lib/providers/board_state_provider.dart +++ b/lib/providers/board_state_provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/foundation.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; @@ -23,6 +25,8 @@ class BoardStateProvider extends ChangeNotifier { int pslabVersion = 0; int pslabFirmwareVersion = 0; bool _isProcessing = false; + StreamSubscription? _usbSubscription; + StreamSubscription>? _connectivitySubscription; final ValueNotifier legacyFirmwareNotifier = ValueNotifier(null); @@ -44,7 +48,7 @@ class BoardStateProvider extends ChangeNotifier { if (configProvider.config.autoStart) { if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) { - UsbSerial.usbEventStream?.listen( + _usbSubscription = UsbSerial.usbEventStream?.listen( (UsbEvent usbEvent) async { if (usbEvent.event == UsbEvent.ACTION_USB_ATTACHED) { if (_isProcessing) return; @@ -68,7 +72,7 @@ class BoardStateProvider extends ChangeNotifier { } } - Connectivity() + _connectivitySubscription = Connectivity() .onConnectivityChanged .listen((List results) { if (results.contains(ConnectivityResult.none)) { @@ -120,4 +124,12 @@ class BoardStateProvider extends ChangeNotifier { } return false; } + + @override + void dispose() { + _usbSubscription?.cancel(); + _connectivitySubscription?.cancel(); + legacyFirmwareNotifier.dispose(); + super.dispose(); + } } From 5936ac6aae1961c6b2feacf2ed55065a20d207e8 Mon Sep 17 00:00:00 2001 From: Prajakta Kamble Date: Mon, 29 Jun 2026 08:06:36 +0530 Subject: [PATCH 2/4] fix: suppress deprecated coroutine warning in Windows CMake build The latest Visual Studio removed support for experimental C++ features (/await compiler option, ), causing the Windows Flutter build to fail with error STL1011. Adding _SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS to the existing add_definitions call suppresses the error so Windows builds work again while a permanent upstream fix is awaited in the permission_handler_windows plugin. Fixes #3246 --- windows/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 4fda1124e..be992493e 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -30,7 +30,8 @@ set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") # Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE -D_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS) # Compilation settings that should be applied to most targets. # From c7331b788470059ee1842fc229faa837079172fd Mon Sep 17 00:00:00 2001 From: Prajakta Kamble Date: Mon, 29 Jun 2026 08:18:44 +0530 Subject: [PATCH 3/4] fix: add error handling for launchUrl in About Us screen The feedback link in about_us_screen.dart called launchUrl() with no canLaunchUrl check or try/catch block. If the URL fails to launch, this throws an unhandled exception and crashes the app. Added canLaunchUrl check consistent with how other links in the same file are already handled. Fixes #XXXX --- lib/view/about_us_screen.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/view/about_us_screen.dart b/lib/view/about_us_screen.dart index b2711f065..c4b411b2e 100644 --- a/lib/view/about_us_screen.dart +++ b/lib/view/about_us_screen.dart @@ -135,7 +135,12 @@ class _AboutUsScreenState extends State { style: const TextStyle(fontSize: 15), ), onTap: () async { - await launchUrl(Uri.parse(appLocalizations.feedbackForm)); + final uri = Uri.parse(appLocalizations.feedbackForm); + if (await canLaunchUrl(uri)) { + await launchUrl(uri); + } else { + debugPrint('Could not launch ${appLocalizations.feedbackForm}'); + } }, ), const Divider(thickness: 0.5), From ce302f385ff35b04710360fe5b8b7cda6237bd42 Mon Sep 17 00:00:00 2001 From: Prajakta Kamble Date: Mon, 29 Jun 2026 12:40:57 +0530 Subject: [PATCH 4/4] chore: apply dart format to about_us_screen --- lib/view/about_us_screen.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/view/about_us_screen.dart b/lib/view/about_us_screen.dart index c4b411b2e..57d979e37 100644 --- a/lib/view/about_us_screen.dart +++ b/lib/view/about_us_screen.dart @@ -137,9 +137,11 @@ class _AboutUsScreenState extends State { onTap: () async { final uri = Uri.parse(appLocalizations.feedbackForm); if (await canLaunchUrl(uri)) { - await launchUrl(uri); + await launchUrl(uri); } else { - debugPrint('Could not launch ${appLocalizations.feedbackForm}'); + debugPrint( + 'Could not launch ${appLocalizations.feedbackForm}', + ); } }, ), @@ -167,7 +169,8 @@ class _AboutUsScreenState extends State { ); } else if (snapshot.hasError) { logger.e( - "Error getting version information: ${snapshot.error.toString()}"); + "Error getting version information: ${snapshot.error.toString()}", + ); return Text( appLocalizations.error, style: const TextStyle(fontSize: 15),