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/**'
- 'lib/generated/**'
- 'lib/data/models/*g.dart'
- 'lib/models/*.g.dart'
- '.dart_tool/**'
linter:

View file

@ -24,13 +24,15 @@ class _CompassMapPluginWidgetState extends State<CompassMapPluginWidget> {
try {
_mapController = MapController.of(context);
_initRotationMonitoring();
} catch (e) {
} catch (_) {
// Ignore - MapController may not be available yet
}
}
void _initRotationMonitoring() {
// Check rotation periodically (every 100ms) to detect changes
_rotationCheckTimer = Timer.periodic(const Duration(milliseconds: 100), (_) {
_rotationCheckTimer =
Timer.periodic(const Duration(milliseconds: 100), (_) {
_checkRotation();
});
@ -59,7 +61,8 @@ class _CompassMapPluginWidgetState extends State<CompassMapPluginWidget> {
try {
final MapController controller = MapController.of(context);
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() {
final strings = S.of(context);
return Align(
alignment: const Alignment(0.0, -0.2),
child: FloatingActionButton(
@ -64,13 +65,12 @@ class _FireAlertState extends State<FireAlert> {
openPlacesDialog(_scaffoldKey).then((YourLocation yourLocation) {
final String where =
yourLocation.description.replaceAll(' ', '').split(',')[0];
Share.shareWithResult(S
.of(context)
.tweetAboutSelf(yourLocation.description, '#IF$where'));
Share.shareWithResult(
strings.tweetAboutSelf(yourLocation.description, '#IF$where'));
}).catchError((Object onError) {
if (mounted) {
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;
@override
_FiresAppState createState() => _FiresAppState(store);
_FiresAppState createState() => _FiresAppState();
}
class _FiresAppState extends State<FiresApp> {
// globals.getIt.registerSingleton
_FiresAppState(this.store);
final GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>();
_FiresAppState();
late final Store<AppState> store;
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
static Widget introWidget(BuildContext context) => IntroPage();
static Widget continueWidget(BuildContext context) => const HomePage();
@override
void initState() {
super.initState();
store = widget.store;
}
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
IntroPage.routeName: introWidget,
HomePage.routeName: continueWidget,
PrivacyPage.routeName: (BuildContext context) => PrivacyPage(context),
ActiveFiresPage.routeName: (BuildContext context) => const ActiveFiresPage(),
ActiveFiresPage.routeName: (BuildContext context) =>
const ActiveFiresPage(),
Sandbox.routeName: (BuildContext context) => const Sandbox(),
FireAlert.routeName: (BuildContext context) => const FireAlert(),
SupportPage.routeName: (BuildContext context) => const SupportPage(),
@ -51,8 +57,6 @@ class _FiresAppState extends State<FiresApp> {
const MonitoredAreasPage()
};
final Store<AppState> store;
@override
Widget build(BuildContext context) {
final StatefulWidget home = MaterialAppWithIntroHome(
@ -61,7 +65,7 @@ class _FiresAppState extends State<FiresApp> {
store: store,
child: MaterialApp(
navigatorKey: navigatorKey,
localizationsDelegates: const <LocalizationsDelegate<dynamic>> [
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
S.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,

View file

@ -19,15 +19,19 @@ class GlobalFiresBottomStats extends StatefulWidget {
class _GlobalFiresBottomStatsState extends State<GlobalFiresBottomStats> {
late String lastCheck;
int activeFires = 0;
final String firesApiUrl = GetIt.instance<String>(instanceName: 'firesApiUrl');
final String firesApiUrl =
GetIt.instance<String>(instanceName: 'firesApiUrl');
@override
void 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 {
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
.read(Uri.parse('${firesApiUrl}status/active-fires-count'))
.then((String result) {
@ -37,10 +41,12 @@ class _GlobalFiresBottomStatsState extends State<GlobalFiresBottomStats> {
lastCheck = now.from(context, last);
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) {
final List<Widget> actionWidgets = <Widget>[];
if (activeFires > 0) {
actionWidgets.add(Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
S.of(context).activeFiresWorldWide(activeFires.toString())),
Text(S.of(context).updatedLastCheck(lastCheck))
]));
actionWidgets
.add(Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Text(S.of(context).activeFiresWorldWide(activeFires.toString())),
Text(S.of(context).updatedLastCheck(lastCheck))
]));
}
return CustomBottomAppBar(

View file

@ -29,7 +29,8 @@ Future<YourLocation> getUserLocation(
address =
await getReverseLocation(lat: yl.lat, lon: yl.lon, external: true);
yl.description = address;
} catch (e) {
} catch (_) {
// Ignore - fallback already attempted
}
}
return yl;
@ -40,7 +41,9 @@ Future<YourLocation> getUserLocation(
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
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(
content: Text(S.of(context).isYourUbicationEnabled),
));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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