Client reported crashes, wrong/frozen data and that the app floods the adapter MCU. See docs/FIX_2026-10-12.md for the full analysis. - Poller: strictly one request outstanding; next request only after a valid 128-byte reply or a 500 ms timeout, then a quiet period + buffer flush. Default 100 ms (10 Hz), minimum 80 ms. DTC clear/probe share the same lock. - BtNotifier: filter the adapter's default (no-ECU-data) frame instead of holding last values; EcuDataStatus + status banner; auto-reconnect on link loss, stalls or long default-only runs (rate-limited). A reconnect still in flight when the user disconnects is discarded. - S300 offsets corrected by column counting (trims, PA, ERR00-03, Eth, SW5, AF); INJ/AIN little-endian; fan = SW5 FANC only. Default-frame detection requires bytes 0-16 and 32-36. - KPro RPM/MAP2/AIN little-endian (RPM still needs a bench check). - Crash hardening: zone/Flutter/platform error handlers to an in-app log (copyable from Debug); permissions requested before listing devices. - Remove temporary debug prints; graph redraws live; polling options 100-300 ms, persisted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
63 lines
2.0 KiB
Dart
63 lines
2.0 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import 'core/logging/app_log.dart';
|
|
import 'core/providers/theme_provider.dart';
|
|
import 'ui/theme/app_theme.dart';
|
|
import 'ui/screens/bt_picker/bt_picker_screen.dart';
|
|
|
|
void main() {
|
|
runZonedGuarded(() {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// Catch every Dart-side error, log it (copyable from the Debug screen)
|
|
// and keep the app running instead of showing a red/grey error screen.
|
|
FlutterError.onError = (FlutterErrorDetails details) {
|
|
AppLog.e('Flutter error', details.exception, details.stack);
|
|
};
|
|
WidgetsBinding.instance.platformDispatcher.onError = (error, stack) {
|
|
AppLog.e('Uncaught platform error', error, stack);
|
|
return true;
|
|
};
|
|
// Release only: keep Flutter's red error screen in debug builds so
|
|
// layout/build errors stay visible during development.
|
|
if (kReleaseMode) {
|
|
ErrorWidget.builder = (FlutterErrorDetails details) => const Center(
|
|
child: Padding(
|
|
padding: EdgeInsets.all(16),
|
|
child: Text(
|
|
'Something went wrong on this screen.\n'
|
|
'Open Debug → Copy log and send it to support.',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(color: Colors.grey),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
AppLog.i('App start');
|
|
runApp(const ProviderScope(child: HvbtApp()));
|
|
}, (error, stack) {
|
|
AppLog.e('Uncaught zone error', error, stack);
|
|
});
|
|
}
|
|
|
|
class HvbtApp extends ConsumerWidget {
|
|
const HvbtApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final themeVariant = ref.watch(themeProvider);
|
|
|
|
return MaterialApp(
|
|
title: 'HV BT Dashboard',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: AppTheme.build(themeVariant),
|
|
home: const BtPickerScreen(),
|
|
);
|
|
}
|
|
}
|