-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Bug
The firmware update popup appears multiple times layered on top of each other (reported ~15 stacked dialogs). User has to cancel each one individually.
Root Cause
File: app/lib/providers/device_provider.dart
The flow is:
- BLE device connects →
_onDeviceConnected()→_checkFirmwareUpdates() _checkFirmwareUpdates()callscheckFirmwareUpdates()(async network call with up to 3 retries), then callsshowFirmwareUpdateDialog()after a 500ms delayshowFirmwareUpdateDialog()calls FluttershowDialog()which stacks on the navigator — each call adds a new dialog layer
The problem: there is no guard against concurrent or repeated calls. When BLE connection flickers (connect/disconnect/reconnect rapidly — common with Bluetooth), _onDeviceConnected fires each time. Each invocation spawns an independent async chain that eventually shows its own dialog. There is no _isFirmwareDialogShowing flag or similar mutex.
Existing guards in showFirmwareUpdateDialog() check _havingNewFirmware, _isFirmwareUpdateInProgress, and _isOnFirmwareUpdatePage — but none of these prevent multiple dialogs from stacking since _havingNewFirmware stays true across all calls once the firmware check returns.
Similarly, _checkFirmwareUpdates checks _isFirmwareUpdateInProgress but has no _isCheckingFirmware lock, so multiple parallel checks can run.
Fix
Two guards needed:
- Add
_isCheckingFirmwareflag to_checkFirmwareUpdates()— return early if already checking:
bool _isCheckingFirmware = false;
void _checkFirmwareUpdates() async {
if (_isFirmwareUpdateInProgress || _isCheckingFirmware) return;
_isCheckingFirmware = true;
try {
await checkFirmwareUpdates();
if (_havingNewFirmware) {
Future.delayed(const Duration(milliseconds: 500), () {
final context = MyApp.navigatorKey.currentContext;
if (context != null) showFirmwareUpdateDialog(context);
});
}
} finally {
_isCheckingFirmware = false;
}
}- Add
_isFirmwareDialogShowingflag toshowFirmwareUpdateDialog()— prevent stacking:
bool _isFirmwareDialogShowing = false;
void showFirmwareUpdateDialog(BuildContext context) {
if (_isFirmwareDialogShowing || !_havingNewFirmware || ...) return;
_isFirmwareDialogShowing = true;
showDialog(
context: context,
builder: ...,
).then((_) {
_isFirmwareDialogShowing = false;
});
}Repro
- Have an Omi device with a firmware update available
- Be in an area with unstable BLE (or toggle Bluetooth rapidly)
- Each reconnect stacks another firmware update dialog
cc @BasedHardware/omi