diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 65034ea..651fab9 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,5 +1,8 @@
+
+
+
@@ -69,4 +72,3 @@
-
diff --git a/lib/app_state.dart b/lib/app_state.dart
index 8053745..448ef41 100644
--- a/lib/app_state.dart
+++ b/lib/app_state.dart
@@ -141,6 +141,16 @@ class AppState extends ChangeNotifier {
notifyListeners();
}
+ // Validate current token/credentials
+ Future validateToken() async {
+ try {
+ return await _auth.isLoggedIn();
+ } catch (e) {
+ print('AppState: Token validation error: $e');
+ return false;
+ }
+ }
+
// ---------- Profiles ----------
List get profiles => List.unmodifiable(_profiles);
bool isEnabled(CameraProfile p) => _enabled.contains(p);
@@ -216,6 +226,10 @@ class AppState extends ChangeNotifier {
);
_saveQueue();
_session = null;
+
+ // Restart uploader when new items are added
+ _startUploader();
+
notifyListeners();
}
@@ -305,4 +319,3 @@ class AppState extends ChangeNotifier {
notifyListeners();
}
}
-
diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart
index 8ea5d40..80147e7 100644
--- a/lib/screens/settings_screen.dart
+++ b/lib/screens/settings_screen.dart
@@ -18,6 +18,7 @@ class SettingsScreen extends StatelessWidget {
body: ListView(
padding: const EdgeInsets.all(16),
children: [
+ // Authentication section
ListTile(
leading: Icon(
appState.isLoggedIn ? Icons.person : Icons.login,
@@ -28,57 +29,48 @@ class SettingsScreen extends StatelessWidget {
: 'Log in to OpenStreetMap'),
subtitle: appState.isLoggedIn
? const Text('Tap to logout')
- : const Text('Tap to login'),
+ : const Text('Required to submit camera data'),
onTap: () async {
if (appState.isLoggedIn) {
await appState.logout();
} else {
- await appState.login();
+ await appState.forceLogin(); // Use force login as the primary method
}
- },
- ),
- ListTile(
- leading: const Icon(Icons.refresh),
- title: const Text('Refresh Login Status'),
- subtitle: const Text('Check if you\'re already logged in'),
- onTap: () async {
- await appState.refreshAuthState();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(appState.isLoggedIn
? 'Logged in as ${appState.username}'
- : 'Not logged in'),
- ),
- );
- }
- },
- ),
- ListTile(
- leading: const Icon(Icons.login_outlined),
- title: const Text('Force Fresh Login'),
- subtitle: const Text('Clear stored tokens and login again'),
- onTap: () async {
- await appState.forceLogin();
- if (context.mounted) {
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(appState.isLoggedIn
- ? 'Fresh login successful: ${appState.username}'
- : 'Fresh login failed'),
- backgroundColor: appState.isLoggedIn ? Colors.green : Colors.red,
+ : 'Logged out'),
+ backgroundColor: appState.isLoggedIn ? Colors.green : Colors.grey,
),
);
}
},
),
+ // Test connection (only when logged in)
if (appState.isLoggedIn)
ListTile(
- leading: const Icon(Icons.cloud_upload),
- title: const Text('Test upload'),
- onTap: () => ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(content: Text('Upload will run soon...')),
- ),
+ leading: const Icon(Icons.wifi_protected_setup),
+ title: const Text('Test Connection'),
+ subtitle: const Text('Verify OSM credentials are working'),
+ onTap: () async {
+ final isValid = await appState.validateToken();
+ if (context.mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(isValid
+ ? 'Connection OK - credentials are valid'
+ : 'Connection failed - please re-login'),
+ backgroundColor: isValid ? Colors.green : Colors.red,
+ ),
+ );
+ }
+ if (!isValid) {
+ // Auto-logout if token is invalid
+ await appState.logout();
+ }
+ },
),
const Divider(),
Row(
@@ -289,4 +281,3 @@ class SettingsScreen extends StatelessWidget {
);
}
}
-