Add flutter_lints and fix analyzer errors, dead code, and unused imports

This commit is contained in:
Doug Borg committed 2026-02-08 14:23:06 -07:00
1 parent 498e36f69d
commit c712aba724
54 files changed
+107 -226

No files matched your search

+8 -26
View File
@@ -7,7 +7,6 @@ import 'package:flutter_map/flutter_map.dart';
import '../app_state.dart';
import '../dev_config.dart';
import '../models/node_profile.dart';
import '../models/operator_profile.dart';
import '../services/localization_service.dart';
import '../services/map_data_provider.dart';
import '../services/node_data_manager.dart';
@@ -59,23 +58,6 @@ class _AddNodeSheetState extends State<AddNodeSheet> {
}
}
/// Listen for tutorial completion from AppState
void _onTutorialCompleted() {
_hideTutorial();
}
/// Also check periodically if tutorial was completed by another sheet
void _recheckTutorialStatus() async {
if (_showTutorial) {
final hasCompleted = await ChangelogService().hasCompletedPositioningTutorial();
if (hasCompleted && mounted) {
setState(() {
_showTutorial = false;
});
}
}
}
void _hideTutorial() {
if (mounted && _showTutorial) {
setState(() {
@@ -402,11 +384,11 @@ class _AddNodeSheetState extends State<AddNodeSheet> {
final locService = LocalizationService.instance;
final appState = context.watch<AppState>();
void _commit() {
void commit() {
_checkProximityAndCommit(context, appState, locService);
}
void _cancel() {
void cancel() {
appState.cancelSession();
Navigator.pop(context);
}
@@ -442,11 +424,11 @@ class _AddNodeSheetState extends State<AddNodeSheet> {
session.profile!.isSubmittable &&
hasGoodCoverage;
void _navigateToLogin() {
void navigateToLogin() {
Navigator.pushNamed(context, '/settings/osm-account');
}
void _openRefineTags() async {
void openRefineTags() async {
final result = await Navigator.push<RefineTagsResult?>(
context,
MaterialPageRoute(
@@ -578,7 +560,7 @@ class _AddNodeSheetState extends State<AddNodeSheet> {
child: SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: session.profile != null ? _openRefineTags : null, // Disabled when no profile selected
onPressed: session.profile != null ? openRefineTags : null, // Disabled when no profile selected
icon: const Icon(Icons.tune),
label: Text(locService.t('addNode.refineTags')),
),
@@ -591,14 +573,14 @@ class _AddNodeSheetState extends State<AddNodeSheet> {
children: [
Expanded(
child: OutlinedButton(
onPressed: _cancel,
onPressed: cancel,
child: Text(locService.cancel),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: !appState.isLoggedIn ? _navigateToLogin : (allowSubmit ? _commit : null),
onPressed: !appState.isLoggedIn ? navigateToLogin : (allowSubmit ? commit : null),
child: Text(!appState.isLoggedIn ? locService.t('actions.logIn') : locService.t('actions.submit')),
),
),
-1
View File
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import '../services/changelog_service.dart';
import '../services/version_service.dart';
class ChangelogDialog extends StatelessWidget {
-1
View File
@@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_animations/flutter_map_animations.dart';
import 'package:provider/provider.dart';
+1 -3
View File
@@ -57,8 +57,7 @@ class _DownloadAreaDialogState extends State<DownloadAreaDialog> {
}
final minZoom = 1; // Always start from zoom 1 to show area overview when zoomed out
final maxZoom = _zoom.toInt();
// Calculate maximum possible zoom based on tile count limit and tile provider max zoom
final maxPossibleZoom = _calculateMaxZoomForTileLimit(bounds, minZoom);
@@ -124,7 +123,6 @@ class _DownloadAreaDialogState extends State<DownloadAreaDialog> {
final locService = LocalizationService.instance;
final appState = context.watch<AppState>();
final bounds = widget.controller.camera.visibleBounds;
final maxZoom = _zoom.toInt();
final isOfflineMode = appState.offlineMode;
// Use the calculated max possible zoom instead of fixed span
+9 -14
View File
@@ -7,14 +7,11 @@ import 'package:flutter_map/flutter_map.dart';
import '../app_state.dart';
import '../dev_config.dart';
import '../models/node_profile.dart';
import '../models/operator_profile.dart';
import '../models/pending_upload.dart';
import '../services/localization_service.dart';
import '../services/map_data_provider.dart';
import '../services/node_data_manager.dart';
import '../services/changelog_service.dart';
import '../state/settings_state.dart';
import '../state/session_state.dart';
import 'refine_tags_sheet.dart';
import 'advanced_edit_options_sheet.dart';
import 'proximity_warning_dialog.dart';
@@ -435,25 +432,23 @@ class _EditNodeSheetState extends State<EditNodeSheet> {
final locService = LocalizationService.instance;
final appState = context.watch<AppState>();
void _commit() {
void commit() {
// Check if there are any actual changes to submit
if (!_hasActualChanges(widget.session)) {
_showNoChangesDialog(context, locService);
return;
}
_checkProximityAndCommit(context, appState, locService);
}
void _cancel() {
void cancel() {
appState.cancelEditSession();
Navigator.pop(context);
}
final session = widget.session;
final submittableProfiles = appState.enabledProfiles.where((p) => p.isSubmittable).toList();
final isSandboxMode = appState.uploadMode == UploadMode.sandbox;
// Check if we have good cache coverage around the node position
bool hasGoodCoverage = true;
final nodeCoord = session.originalNode.coord;
@@ -481,11 +476,11 @@ class _EditNodeSheetState extends State<EditNodeSheet> {
session.profile!.isSubmittable &&
hasGoodCoverage;
void _navigateToLogin() {
void navigateToLogin() {
Navigator.pushNamed(context, '/settings/osm-account');
}
void _openRefineTags() async {
void openRefineTags() async {
final result = await Navigator.push<RefineTagsResult?>(
context,
MaterialPageRoute(
@@ -694,7 +689,7 @@ class _EditNodeSheetState extends State<EditNodeSheet> {
child: SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: session.profile != null ? _openRefineTags : null, // Disabled when no profile selected
onPressed: session.profile != null ? openRefineTags : null, // Disabled when no profile selected
icon: const Icon(Icons.tune),
label: Text(locService.t('editNode.refineTags')),
),
@@ -707,14 +702,14 @@ class _EditNodeSheetState extends State<EditNodeSheet> {
children: [
Expanded(
child: OutlinedButton(
onPressed: _cancel,
onPressed: cancel,
child: Text(locService.cancel),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: !appState.isLoggedIn ? _navigateToLogin : (allowSubmit ? _commit : null),
onPressed: !appState.isLoggedIn ? navigateToLogin : (allowSubmit ? commit : null),
child: Text(!appState.isLoggedIn ? locService.t('actions.logIn') : locService.t('actions.saveEdit')),
),
),
-28
View File
@@ -6,7 +6,6 @@ import 'package:latlong2/latlong.dart';
import '../../app_state.dart';
import '../../dev_config.dart';
import '../../models/osm_node.dart';
import '../../models/direction_fov.dart';
/// Helper class to build direction cone polygons for cameras
class DirectionConesBuilder {
@@ -113,11 +112,6 @@ class DirectionConesBuilder {
node.coord.longitude.abs() <= 180;
}
static bool _isPendingUpload(OsmNode node) {
return node.tags.containsKey('_pending_upload') &&
node.tags['_pending_upload'] == 'true';
}
/// Build cone with variable FOV width - new method for range notation support
static Polygon _buildConeWithFov(
LatLng origin,
@@ -141,28 +135,6 @@ class DirectionConesBuilder {
);
}
/// Legacy method for backward compatibility - uses dev_config FOV
static Polygon _buildCone(
LatLng origin,
double bearingDeg,
double zoom, {
required BuildContext context,
bool isPending = false,
bool isSession = false,
bool isActiveDirection = true,
}) {
return _buildConeInternal(
origin: origin,
bearingDeg: bearingDeg,
halfAngleDeg: kDirectionConeHalfAngle,
zoom: zoom,
context: context,
isPending: isPending,
isSession: isSession,
isActiveDirection: isActiveDirection,
);
}
/// Internal cone building method that handles the actual rendering
static Polygon _buildConeInternal({
required LatLng origin,
-1
View File
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_animations/flutter_map_animations.dart';
import 'package:latlong2/latlong.dart';
import '../../models/osm_node.dart';
-2
View File
@@ -1,12 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_animations/flutter_map_animations.dart';
import 'package:provider/provider.dart';
import '../../app_state.dart';
import '../../dev_config.dart';
import '../../services/localization_service.dart';
import '../camera_icon.dart';
import '../compass_indicator.dart';
import 'layer_selector_button.dart';
@@ -6,7 +6,6 @@ import 'package:latlong2/latlong.dart';
import '../../models/osm_node.dart';
import '../../models/suspected_location.dart';
import '../../app_state.dart';
import '../../state/session_state.dart';
import '../../dev_config.dart';
import '../camera_icon.dart';
import '../provisional_pin.dart';
+2 -2
View File
@@ -20,8 +20,8 @@ class NodeMapMarker extends StatefulWidget {
required this.mapController,
this.onNodeTap,
this.enabled = true,
Key? key,
}) : super(key: key);
super.key,
});
@override
State<NodeMapMarker> createState() => _NodeMapMarkerState();
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_map_animations/flutter_map_animations.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import '../../models/node_profile.dart';
import '../../app_state.dart' show UploadMode;
@@ -20,8 +20,8 @@ class SuspectedLocationMapMarker extends StatefulWidget {
required this.mapController,
this.onLocationTap,
this.enabled = true,
Key? key,
}) : super(key: key);
super.key,
});
@override
State<SuspectedLocationMapMarker> createState() => _SuspectedLocationMapMarkerState();
+1 -2
View File
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import '../../models/tile_provider.dart' as models;
import '../../services/deflock_tile_provider.dart';
@@ -93,7 +92,7 @@ class TileLayerManager {
return TileLayer(
urlTemplate: urlTemplate, // Critical for cache key generation
userAgentPackageName: 'me.deflock.deflockapp',
maxZoom: selectedTileType?.maxZoom?.toDouble() ?? 18.0,
maxZoom: selectedTileType?.maxZoom.toDouble() ?? 18.0,
tileProvider: _tileProvider!,
);
}
@@ -1,12 +1,9 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
import 'package:flutter_map/flutter_map.dart' show LatLngBounds;
import '../services/map_data_provider.dart';
import '../services/node_data_manager.dart';
import '../services/node_spatial_cache.dart';
import '../services/network_status.dart';
import '../models/node_profile.dart';
import '../models/osm_node.dart';
import '../app_state.dart';
+4 -4
View File
@@ -8,15 +8,15 @@ class NuclearResetDialog extends StatelessWidget {
final String errorReport;
const NuclearResetDialog({
Key? key,
super.key,
required this.errorReport,
}) : super(key: key);
});
@override
Widget build(BuildContext context) {
return WillPopScope(
return PopScope(
// Prevent back button from closing dialog
onWillPop: () async => false,
canPop: false,
child: AlertDialog(
title: const Row(
children: [
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
import '../models/osm_node.dart';
import '../services/localization_service.dart';
+3 -3
View File
@@ -107,7 +107,7 @@ class _LocationSearchBarState extends State<LocationSearchBar> {
borderRadius: const BorderRadius.vertical(bottom: Radius.circular(12)),
boxShadow: [
BoxShadow(
color: Theme.of(context).shadowColor.withOpacity(0.2),
color: Theme.of(context).shadowColor.withValues(alpha: 0.2),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -152,7 +152,7 @@ class _LocationSearchBarState extends State<LocationSearchBar> {
: null,
dense: true,
onTap: () => _onResultTap(result),
)).toList(),
)),
],
),
);
@@ -184,7 +184,7 @@ class _LocationSearchBarState extends State<LocationSearchBar> {
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Theme.of(context).shadowColor.withOpacity(0.2),
color: Theme.of(context).shadowColor.withValues(alpha: 0.2),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -1,9 +1,7 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../models/suspected_location.dart';
import '../app_state.dart';
import '../services/localization_service.dart';
import '../dev_config.dart';
@@ -17,7 +15,6 @@ class SuspectedLocationSheet extends StatelessWidget {
return AnimatedBuilder(
animation: LocalizationService.instance,
builder: (context, child) {
final appState = context.watch<AppState>();
final locService = LocalizationService.instance;
// Get all fields except location and ticket_no