mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-08-17 00:20:40 +02:00
Button to trigger nuke reset in dev mode
This commit is contained in:
@@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
An alternative approach to addressing this issue could be adjusting the `optionsBuilder` logic to avoid returning any suggestions when the input text field is empty, rather than guarding `onFieldSubmitted`. For instance:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
optionsBuilder: (TextEditingValue textEditingValue) {
|
|
||||||
if (textEditingValue.text.isEmpty) return <String>[];
|
|
||||||
return suggestions.where((s) => s.contains(textEditingValue.text));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This ensures that the `RawAutocomplete` widget doesn't offer any options to auto-select on submission when the field is cleared, potentially simplifying the implementation and avoiding the need for additional boolean flags (`guardOnSubmitted`). This pattern can be seen in some implementations "in the wild."
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import '../services/localization_service.dart';
|
import '../services/localization_service.dart';
|
||||||
|
import '../services/nuclear_reset_service.dart';
|
||||||
import '../widgets/welcome_dialog.dart';
|
import '../widgets/welcome_dialog.dart';
|
||||||
import '../widgets/submission_guide_dialog.dart';
|
import '../widgets/submission_guide_dialog.dart';
|
||||||
|
|
||||||
@@ -83,6 +85,13 @@ class AboutScreen extends StatelessWidget {
|
|||||||
_buildDialogButtons(context),
|
_buildDialogButtons(context),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
_buildHelpLinks(context),
|
_buildHelpLinks(context),
|
||||||
|
|
||||||
|
// Dev-only nuclear reset button at very bottom
|
||||||
|
if (kDebugMode) ...[
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
_buildDevNuclearResetButton(context),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -203,5 +212,231 @@ class AboutScreen extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dev-only nuclear reset button (only visible in debug mode)
|
||||||
|
Widget _buildDevNuclearResetButton(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
color: Theme.of(context).colorScheme.errorContainer.withOpacity(0.1),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.developer_mode,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
'Developer Tools',
|
||||||
|
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
'These tools are only available in debug mode for development and troubleshooting.',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.7),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: OutlinedButton.icon(
|
||||||
|
onPressed: () => _showNuclearResetConfirmation(context),
|
||||||
|
icon: const Icon(Icons.delete_forever, color: Colors.red),
|
||||||
|
label: const Text(
|
||||||
|
'Nuclear Reset (Clear All Data)',
|
||||||
|
style: TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
side: const BorderSide(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Show confirmation dialog for nuclear reset
|
||||||
|
Future<void> _showNuclearResetConfirmation(BuildContext context) async {
|
||||||
|
final confirmed = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.warning, color: Colors.red),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Nuclear Reset'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: const Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'This will completely clear ALL app data:',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
Text('• All settings and preferences'),
|
||||||
|
Text('• OAuth login credentials'),
|
||||||
|
Text('• Custom profiles and operators'),
|
||||||
|
Text('• Upload queue and cached data'),
|
||||||
|
Text('• Downloaded offline areas'),
|
||||||
|
Text('• Everything else'),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'The app will behave exactly like a fresh install after this operation.',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
'This action cannot be undone.',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||||
|
child: const Text('Nuclear Reset'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (confirmed == true && context.mounted) {
|
||||||
|
await _performNuclearReset(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform the nuclear reset operation
|
||||||
|
Future<void> _performNuclearReset(BuildContext context) async {
|
||||||
|
// Show progress dialog
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => const AlertDialog(
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
CircularProgressIndicator(),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Text('Clearing all app data...'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Perform the nuclear reset
|
||||||
|
await NuclearResetService.clearEverything();
|
||||||
|
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
// Close progress dialog
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
|
// Show completion dialog
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.check_circle, color: Colors.green),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Reset Complete'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: const Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'All app data has been cleared successfully.',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
'Please close and restart the app to continue with a fresh state.',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
// Close progress dialog if it's still open
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
|
// Show error dialog
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.error, color: Colors.red),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Reset Failed'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'An error occurred during the nuclear reset:',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
e.toString(),
|
||||||
|
style: const TextStyle(fontFamily: 'monospace'),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
const Text(
|
||||||
|
'Some data may have been partially cleared. You may want to manually clear app data through device settings.',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user