refactor: fix remaining lint warnings and deprecated APIs

- Fix deprecated @ignore in json_serializable models (appState, yourLocation)
- Fix empty catch blocks in compassMapPlugin, globalFiresBottomStats, locationUtils
- Fix no_logic_in_create_state in firesApp, markdownPage, slider
- Fix use_build_context_synchronously in fireAlert
- Fix only_throw_errors in firesApi (8 instances)
- Exclude generated .g.dart files from analysis
- Update deprecated nullable: false to @JsonSerializable()

Build: APK generated successfully, 0 errors, 0 warnings
This commit is contained in:
vjrj 2026-03-07 09:35:59 +01:00
parent 948a609619
commit 862d423f6b
14 changed files with 96 additions and 69 deletions

View file

@ -18,6 +18,7 @@ analyzer:
- 'build/**' - 'build/**'
- 'lib/generated/**' - 'lib/generated/**'
- 'lib/data/models/*g.dart' - 'lib/data/models/*g.dart'
- 'lib/models/*.g.dart'
- '.dart_tool/**' - '.dart_tool/**'
linter: linter:

View file

@ -24,13 +24,15 @@ class _CompassMapPluginWidgetState extends State<CompassMapPluginWidget> {
try { try {
_mapController = MapController.of(context); _mapController = MapController.of(context);
_initRotationMonitoring(); _initRotationMonitoring();
} catch (e) { } catch (_) {
// Ignore - MapController may not be available yet
} }
} }
void _initRotationMonitoring() { void _initRotationMonitoring() {
// Check rotation periodically (every 100ms) to detect changes // Check rotation periodically (every 100ms) to detect changes
_rotationCheckTimer = Timer.periodic(const Duration(milliseconds: 100), (_) { _rotationCheckTimer =
Timer.periodic(const Duration(milliseconds: 100), (_) {
_checkRotation(); _checkRotation();
}); });
@ -59,7 +61,8 @@ class _CompassMapPluginWidgetState extends State<CompassMapPluginWidget> {
try { try {
final MapController controller = MapController.of(context); final MapController controller = MapController.of(context);
controller.rotate(0); controller.rotate(0);
} catch (e) { } catch (_) {
// Ignore - MapController may not be available
} }
} }

View file

@ -55,6 +55,7 @@ class _FireAlertState extends State<FireAlert> {
} }
Widget buildTweetButton() { Widget buildTweetButton() {
final strings = S.of(context);
return Align( return Align(
alignment: const Alignment(0.0, -0.2), alignment: const Alignment(0.0, -0.2),
child: FloatingActionButton( child: FloatingActionButton(
@ -64,13 +65,12 @@ class _FireAlertState extends State<FireAlert> {
openPlacesDialog(_scaffoldKey).then((YourLocation yourLocation) { openPlacesDialog(_scaffoldKey).then((YourLocation yourLocation) {
final String where = final String where =
yourLocation.description.replaceAll(' ', '').split(',')[0]; yourLocation.description.replaceAll(' ', '').split(',')[0];
Share.shareWithResult(S Share.shareWithResult(
.of(context) strings.tweetAboutSelf(yourLocation.description, '#IF$where'));
.tweetAboutSelf(yourLocation.description, '#IF$where'));
}).catchError((Object onError) { }).catchError((Object onError) {
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(S.of(context).errorFirePlaceDialog))); SnackBar(content: Text(strings.errorFirePlaceDialog)));
} }
}); });
}, },

View file

@ -25,23 +25,29 @@ class FiresApp extends StatefulWidget {
final Store<AppState> store; final Store<AppState> store;
@override @override
_FiresAppState createState() => _FiresAppState(store); _FiresAppState createState() => _FiresAppState();
} }
class _FiresAppState extends State<FiresApp> { class _FiresAppState extends State<FiresApp> {
// globals.getIt.registerSingleton // globals.getIt.registerSingleton
_FiresAppState(this.store); _FiresAppState();
final GlobalKey<NavigatorState> navigatorKey = late final Store<AppState> store;
GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
static Widget introWidget(BuildContext context) => IntroPage(); static Widget introWidget(BuildContext context) => IntroPage();
static Widget continueWidget(BuildContext context) => const HomePage(); static Widget continueWidget(BuildContext context) => const HomePage();
@override
void initState() {
super.initState();
store = widget.store;
}
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
IntroPage.routeName: introWidget, IntroPage.routeName: introWidget,
HomePage.routeName: continueWidget, HomePage.routeName: continueWidget,
PrivacyPage.routeName: (BuildContext context) => PrivacyPage(context), PrivacyPage.routeName: (BuildContext context) => PrivacyPage(context),
ActiveFiresPage.routeName: (BuildContext context) => const ActiveFiresPage(), ActiveFiresPage.routeName: (BuildContext context) =>
const ActiveFiresPage(),
Sandbox.routeName: (BuildContext context) => const Sandbox(), Sandbox.routeName: (BuildContext context) => const Sandbox(),
FireAlert.routeName: (BuildContext context) => const FireAlert(), FireAlert.routeName: (BuildContext context) => const FireAlert(),
SupportPage.routeName: (BuildContext context) => const SupportPage(), SupportPage.routeName: (BuildContext context) => const SupportPage(),
@ -51,8 +57,6 @@ class _FiresAppState extends State<FiresApp> {
const MonitoredAreasPage() const MonitoredAreasPage()
}; };
final Store<AppState> store;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final StatefulWidget home = MaterialAppWithIntroHome( final StatefulWidget home = MaterialAppWithIntroHome(
@ -61,7 +65,7 @@ class _FiresAppState extends State<FiresApp> {
store: store, store: store,
child: MaterialApp( child: MaterialApp(
navigatorKey: navigatorKey, navigatorKey: navigatorKey,
localizationsDelegates: const <LocalizationsDelegate<dynamic>> [ localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
S.delegate, S.delegate,
GlobalMaterialLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, GlobalWidgetsLocalizations.delegate,

View file

@ -19,15 +19,19 @@ class GlobalFiresBottomStats extends StatefulWidget {
class _GlobalFiresBottomStatsState extends State<GlobalFiresBottomStats> { class _GlobalFiresBottomStatsState extends State<GlobalFiresBottomStats> {
late String lastCheck; late String lastCheck;
int activeFires = 0; int activeFires = 0;
final String firesApiUrl = GetIt.instance<String>(instanceName: 'firesApiUrl'); final String firesApiUrl =
GetIt.instance<String>(instanceName: 'firesApiUrl');
@override @override
void initState() { void initState() {
super.initState(); super.initState();
http.read(Uri.parse('${firesApiUrl}status/last-fire-check')).then((String result) { http
.read(Uri.parse('${firesApiUrl}status/last-fire-check'))
.then((String result) {
try { try {
final Moment now = Moment.now(); final Moment now = Moment.now();
final DateTime last = DateTime.parse(json.decode(result)['value'] as String); final DateTime last =
DateTime.parse(json.decode(result)['value'] as String);
http http
.read(Uri.parse('${firesApiUrl}status/active-fires-count')) .read(Uri.parse('${firesApiUrl}status/active-fires-count'))
.then((String result) { .then((String result) {
@ -37,10 +41,12 @@ class _GlobalFiresBottomStatsState extends State<GlobalFiresBottomStats> {
lastCheck = now.from(context, last); lastCheck = now.from(context, last);
activeFires = count; activeFires = count;
}); });
} catch (e) { } catch (_) {
// Ignore JSON parse errors
} }
}); });
} catch (e) { } catch (_) {
// Ignore storage read errors
} }
}); });
} }
@ -49,13 +55,11 @@ class _GlobalFiresBottomStatsState extends State<GlobalFiresBottomStats> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<Widget> actionWidgets = <Widget>[]; final List<Widget> actionWidgets = <Widget>[];
if (activeFires > 0) { if (activeFires > 0) {
actionWidgets.add(Column( actionWidgets
mainAxisSize: MainAxisSize.min, .add(Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
children: <Widget>[ Text(S.of(context).activeFiresWorldWide(activeFires.toString())),
Text( Text(S.of(context).updatedLastCheck(lastCheck))
S.of(context).activeFiresWorldWide(activeFires.toString())), ]));
Text(S.of(context).updatedLastCheck(lastCheck))
]));
} }
return CustomBottomAppBar( return CustomBottomAppBar(

View file

@ -29,7 +29,8 @@ Future<YourLocation> getUserLocation(
address = address =
await getReverseLocation(lat: yl.lat, lon: yl.lon, external: true); await getReverseLocation(lat: yl.lat, lon: yl.lon, external: true);
yl.description = address; yl.description = address;
} catch (e) { } catch (_) {
// Ignore - fallback already attempted
} }
} }
return yl; return yl;
@ -40,7 +41,9 @@ Future<YourLocation> getUserLocation(
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(S.of(context).notPermsUbication), content: Text(S.of(context).notPermsUbication),
)); ));
} else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {} } else if (e.code == 'PERMISSION_DENIED_NEVER_ASK') {
// User selected "Don't ask again" - show settings prompt
}
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(S.of(context).isYourUbicationEnabled), content: Text(S.of(context).isYourUbicationEnabled),
)); ));

View file

@ -18,18 +18,24 @@ abstract class MarkdownPage extends StatefulWidget {
final String route; final String route;
@override @override
_MarkdownPageState createState() => _MarkdownPageState createState() => _MarkdownPageState();
_MarkdownPageState(title: title, file: file, route: route);
} }
class _MarkdownPageState extends State<MarkdownPage> { class _MarkdownPageState extends State<MarkdownPage> {
_MarkdownPageState( _MarkdownPageState();
{required this.title, required this.file, required this.route}); late final String title;
final String title; late final String route;
final String route; late final Future<String> file;
final Future<String> file;
String pageData = ''; String pageData = '';
@override
void initState() {
super.initState();
title = widget.title;
route = widget.route;
file = widget.file;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
file.then((String fileSync) { file.then((String fileSync) {

View file

@ -17,7 +17,7 @@ export 'fireMapState.dart';
part 'appState.g.dart'; part 'appState.g.dart';
@immutable @immutable
@JsonSerializable(nullable: false) @JsonSerializable()
class AppState { class AppState {
const AppState( const AppState(
{this.yourLocations = const <YourLocation>[], {this.yourLocations = const <YourLocation>[],
@ -37,27 +37,27 @@ class AppState {
factory AppState.fromJson(Map<String, dynamic> json) => factory AppState.fromJson(Map<String, dynamic> json) =>
_$AppStateFromJson(json); _$AppStateFromJson(json);
final bool isLoading; final bool isLoading;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final bool isLoaded; final bool isLoaded;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final String error; final String error;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final User user; final User user;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final String gmapKey; final String gmapKey;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final String serverUrl; final String serverUrl;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final String firesApiKey; final String firesApiKey;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final String firesApiUrl; final String firesApiUrl;
final List<YourLocation> yourLocations; final List<YourLocation> yourLocations;
final List<FireNotification> fireNotifications; final List<FireNotification> fireNotifications;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final List<Polyline> monitoredAreas; final List<Polyline> monitoredAreas;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final int fireNotificationsUnread; final int fireNotificationsUnread;
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final FireMapState fireMapState; final FireMapState fireMapState;
AppState copyWith( AppState copyWith(

View file

@ -1,4 +1,5 @@
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
part of 'appState.dart'; part of 'appState.dart';

View file

@ -1,4 +1,5 @@
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
part of 'fireNotification.dart'; part of 'fireNotification.dart';

View file

@ -32,10 +32,10 @@ class FiresApi {
if (response.statusCode == 200) { if (response.statusCode == 200) {
return response.data['data']['userId'] as String; return response.data['data']['userId'] as String;
} else { } else {
throw 'Unexpected error on create user'; throw Exception('Unexpected error on create user');
} }
} catch (e) { } catch (e) {
throw 'Error creating user: $e'; throw Exception('Error creating user: $e');
} }
} }
@ -64,10 +64,10 @@ class FiresApi {
} }
return subscribed; return subscribed;
} else { } else {
throw 'Unexpected error fetching your locations'; throw Exception('Unexpected error fetching your locations');
} }
} catch (e) { } catch (e) {
throw 'Error fetching locations: $e'; throw Exception('Error fetching locations: $e');
} }
} }
@ -86,10 +86,10 @@ class FiresApi {
if (response.statusCode == 200) { if (response.statusCode == 200) {
return response.data['data']['subsId'] as String; return response.data['data']['subsId'] as String;
} else { } else {
throw 'Unexpected error on subscribe'; throw Exception('Unexpected error on subscribe');
} }
} catch (e) { } catch (e) {
throw 'Error subscribing: $e'; throw Exception('Error subscribing: $e');
} }
} }
@ -103,10 +103,10 @@ class FiresApi {
if (response.statusCode == 200) { if (response.statusCode == 200) {
return true; return true;
} else { } else {
throw 'Unexpected error on unsubscribe'; throw Exception('Unexpected error on unsubscribe');
} }
} catch (e) { } catch (e) {
throw 'Error unsubscribing: $e'; throw Exception('Error unsubscribing: $e');
} }
} }

View file

@ -5,7 +5,7 @@ import '../objectIdUtils.dart';
part 'yourLocation.g.dart'; part 'yourLocation.g.dart';
@JsonSerializable(nullable: false) @JsonSerializable()
class YourLocation { class YourLocation {
YourLocation( YourLocation(
{required this.id, {required this.id,

View file

@ -1,4 +1,5 @@
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
part of 'yourLocation.dart'; part of 'yourLocation.dart';

View file

@ -7,27 +7,30 @@ import 'generated/i18n.dart';
typedef SlideCallback = void Function(int distance); typedef SlideCallback = void Function(int distance);
class FireDistanceSlider extends StatefulWidget { class FireDistanceSlider extends StatefulWidget {
const FireDistanceSlider(
const FireDistanceSlider({super.key, required this.initialValue, required this.onSlide}); {super.key, required this.initialValue, required this.onSlide});
final int initialValue; final int initialValue;
final SlideCallback onSlide; final SlideCallback onSlide;
@override @override
_FireDistanceSliderState createState() => _FireDistanceSliderState( _FireDistanceSliderState createState() => _FireDistanceSliderState();
initialValue: initialValue, onSlide: onSlide);
} }
class _FireDistanceSliderState extends State<FireDistanceSlider> { class _FireDistanceSliderState extends State<FireDistanceSlider> {
_FireDistanceSliderState();
_FireDistanceSliderState({int initialValue = 10, required this.onSlide}) {
_sliderValue = initialValue;
}
late int _sliderValue; late int _sliderValue;
final SlideCallback onSlide; late final SlideCallback onSlide;
Widget sizeText(int sliderValue) => Text( @override
S.of(context).subscribeToValueAroundThisArea(sliderValue.toString()), void initState() {
style: const TextStyle(color: Colors.black87)); super.initState();
_sliderValue = widget.initialValue;
onSlide = widget.onSlide;
}
Widget sizeText(int sliderValue) =>
Text(S.of(context).subscribeToValueAroundThisArea(sliderValue.toString()),
style: const TextStyle(color: Colors.black87));
Widget warningText(int sliderValue) => _sliderValue >= 50 Widget warningText(int sliderValue) => _sliderValue >= 50
? Text(S.of(context).warningThisIsAVeryLargeArea, ? Text(S.of(context).warningThisIsAVeryLargeArea,