260 lines
10 KiB
Dart
260 lines
10 KiB
Dart
// lib/services/user_preferences_service.dart
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:environment_monitoring_app/services/api_service.dart'; // Contains DatabaseHelper
|
|
|
|
/// A dedicated service to manage the user's local preferences for
|
|
/// module-specific submission destinations.
|
|
class UserPreferencesService {
|
|
final DatabaseHelper _dbHelper = DatabaseHelper();
|
|
static const _defaultPrefsSavedKey = 'default_preferences_saved';
|
|
|
|
// Moved from settings.dart for central access
|
|
// This list now includes all your modules
|
|
final List<Map<String, String>> _configurableModules = [
|
|
{'key': 'marine_tarball', 'name': 'Marine Tarball'},
|
|
{'key': 'marine_in_situ', 'name': 'Marine In-Situ'},
|
|
{'key': 'marine_investigative', 'name': 'Marine Investigative'},
|
|
{'key': 'river_in_situ', 'name': 'River In-Situ'},
|
|
{'key': 'river_triennial', 'name': 'River Triennial'},
|
|
{'key': 'river_investigative', 'name': 'River Investigative'},
|
|
{'key': 'air_installation', 'name': 'Air Installation'},
|
|
{'key': 'air_collection', 'name': 'Air Collection'},
|
|
];
|
|
|
|
/// Checks if default preferences have been set. If not, it applies
|
|
/// and saves the default submission destinations for all modules.
|
|
/// This ensures the app is ready for submissions immediately after the first login.
|
|
Future<void> applyAndSaveDefaultPreferencesIfNeeded() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
if (prefs.getBool(_defaultPrefsSavedKey) ?? false) {
|
|
// Defaults have already been saved for this session, do nothing.
|
|
return;
|
|
}
|
|
|
|
debugPrint("Applying and auto-saving default submission preferences for the first time.");
|
|
|
|
try {
|
|
// Get all possible configs from the database just once
|
|
final allApiConfigs = await _dbHelper.loadApiConfigs() ?? [];
|
|
final allFtpConfigs = await _dbHelper.loadFtpConfigs() ?? [];
|
|
|
|
for (var module in _configurableModules) {
|
|
final moduleKey = module['key']!;
|
|
|
|
// 1. Save master switches to enable API and FTP for the module.
|
|
await saveModulePreference(
|
|
moduleName: moduleKey,
|
|
isApiEnabled: true,
|
|
isFtpEnabled: true,
|
|
);
|
|
|
|
// 2. Determine default API links
|
|
// This is correct: Tick any API server marked as 'is_active' by default.
|
|
final defaultApiLinks = allApiConfigs.map((config) {
|
|
bool isEnabled = (config['is_active'] == 1 || config['is_active'] == true);
|
|
return {...config, 'is_enabled': isEnabled};
|
|
}).toList();
|
|
|
|
// 3. Determine default FTP links
|
|
// Handle mapping 'marine_in_situ' -> 'marine_manual'
|
|
String expectedFtpModuleKey = moduleKey;
|
|
if (moduleKey == 'marine_in_situ') {
|
|
expectedFtpModuleKey = 'marine_manual';
|
|
} else if (moduleKey == 'river_in_situ') {
|
|
expectedFtpModuleKey = 'river_manual';
|
|
}
|
|
|
|
final defaultFtpLinks = allFtpConfigs.map((config) {
|
|
final String configModule = config['ftp_module'] ?? '';
|
|
final bool isActive = (config['is_active'] == 1 || config['is_active'] == true);
|
|
|
|
// Enable if the config's module matches the current moduleKey AND it's active
|
|
bool isEnabled = (configModule == expectedFtpModuleKey) && isActive;
|
|
|
|
return {...config, 'is_enabled': isEnabled};
|
|
}).toList();
|
|
// --- END MODIFICATION ---
|
|
|
|
// 4. Save the default links to the database.
|
|
await saveApiLinksForModule(moduleKey, defaultApiLinks);
|
|
await saveFtpLinksForModule(moduleKey, defaultFtpLinks);
|
|
}
|
|
|
|
// 5. Set the flag to prevent this from running again until next login.
|
|
await prefs.setBool(_defaultPrefsSavedKey, true);
|
|
debugPrint("Default submission preferences have been auto-saved.");
|
|
|
|
} catch (e) {
|
|
debugPrint("Error auto-saving default preferences: $e");
|
|
}
|
|
}
|
|
|
|
|
|
/// Retrieves a module's master submission preferences.
|
|
/// This method now returns null if no preference is found.
|
|
Future<Map<String, dynamic>?> getModulePreference(String moduleName) async {
|
|
final preference = await _dbHelper.getModulePreference(moduleName);
|
|
if (preference != null) {
|
|
return preference;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// Saves or updates a module's master on/off switches for API and FTP submissions.
|
|
Future<void> saveModulePreference({
|
|
required String moduleName,
|
|
required bool isApiEnabled,
|
|
required bool isFtpEnabled,
|
|
}) async {
|
|
await _dbHelper.saveModulePreference(
|
|
moduleName: moduleName,
|
|
isApiEnabled: isApiEnabled,
|
|
isFtpEnabled: isFtpEnabled,
|
|
);
|
|
}
|
|
|
|
/// Retrieves all available API configurations and merges them with the user's
|
|
/// saved preferences for a specific module.
|
|
///
|
|
/// This is primarily for the Settings UI to display all possible destinations
|
|
/// with their current enabled/disabled state (e.g., checkboxes).
|
|
Future<List<Map<String, dynamic>>> getAllApiConfigsWithModulePreferences(String moduleName) async {
|
|
// 1. Get all possible API destinations that have been synced to the device.
|
|
final allApiConfigs = await _dbHelper.loadApiConfigs() ?? [];
|
|
if (allApiConfigs.isEmpty) return [];
|
|
|
|
// 2. Get the specific links the user has previously saved for this module.
|
|
final savedLinks = await _dbHelper.getAllApiLinksForModule(moduleName);
|
|
|
|
// 3. Merge the two lists.
|
|
return allApiConfigs.map((config) {
|
|
final configId = config['api_config_id'];
|
|
bool isEnabled;
|
|
|
|
// --- START MODIFICATION: Corrected Merge Logic ---
|
|
Map<String, dynamic>? matchingLink;
|
|
try {
|
|
matchingLink = savedLinks.firstWhere(
|
|
(link) => link['api_config_id'] == configId,
|
|
);
|
|
} catch (e) {
|
|
matchingLink = null; // No match found
|
|
}
|
|
|
|
if (matchingLink != null) {
|
|
// A preference exists. Use the saved value.
|
|
isEnabled = matchingLink['is_enabled'] as bool? ?? false;
|
|
} else {
|
|
// No preference saved for this config. Apply default logic.
|
|
// (This handles newly synced configs automatically)
|
|
isEnabled = (config['is_active'] == 1 || config['is_active'] == true);
|
|
}
|
|
// --- END MODIFICATION ---
|
|
|
|
// Return a new map containing the original config details plus the 'is_enabled' flag.
|
|
return {
|
|
...config,
|
|
'is_enabled': isEnabled,
|
|
};
|
|
}).toList();
|
|
}
|
|
|
|
/// Retrieves all available FTP configurations and merges them with the user's
|
|
/// saved preferences for a specific module. (For the Settings UI).
|
|
Future<List<Map<String, dynamic>>> getAllFtpConfigsWithModulePreferences(String moduleName) async {
|
|
final allFtpConfigs = await _dbHelper.loadFtpConfigs() ?? [];
|
|
if (allFtpConfigs.isEmpty) return [];
|
|
|
|
final savedLinks = await _dbHelper.getAllFtpLinksForModule(moduleName);
|
|
|
|
// Handle mapping 'marine_in_situ' -> 'marine_manual'
|
|
String expectedFtpModuleKey = moduleName;
|
|
if (moduleName == 'marine_in_situ') {
|
|
expectedFtpModuleKey = 'marine_manual';
|
|
} else if (moduleName == 'river_in_situ') {
|
|
expectedFtpModuleKey = 'river_manual';
|
|
}
|
|
|
|
return allFtpConfigs.map((config) {
|
|
final configId = config['ftp_config_id'];
|
|
bool isEnabled;
|
|
|
|
// --- START MODIFICATION: Corrected Merge Logic ---
|
|
Map<String, dynamic>? matchingLink;
|
|
try {
|
|
matchingLink = savedLinks.firstWhere(
|
|
(link) => link['ftp_config_id'] == configId,
|
|
);
|
|
} catch (e) {
|
|
matchingLink = null; // No match found
|
|
}
|
|
|
|
if (matchingLink != null) {
|
|
// A preference exists. Use the saved value.
|
|
isEnabled = matchingLink['is_enabled'] as bool? ?? false;
|
|
} else {
|
|
// No preference saved for this config. Apply default logic.
|
|
final String configModule = config['ftp_module'] ?? '';
|
|
final bool isActive = (config['is_active'] == 1 || config['is_active'] == true);
|
|
// Use the mapped key for comparison
|
|
isEnabled = (configModule == expectedFtpModuleKey) && isActive;
|
|
}
|
|
// --- END MODIFICATION ---
|
|
|
|
return {
|
|
...config,
|
|
'is_enabled': isEnabled,
|
|
};
|
|
}).toList();
|
|
}
|
|
|
|
/// Saves the complete set of enabled/disabled API links for a specific module.
|
|
/// This will replace all previous links for that module.
|
|
Future<void> saveApiLinksForModule(String moduleName, List<Map<String, dynamic>> links) async {
|
|
await _dbHelper.saveApiLinksForModule(moduleName, links);
|
|
}
|
|
|
|
/// Saves the complete set of enabled/disabled FTP links for a specific module.
|
|
Future<void> saveFtpLinksForModule(String moduleName, List<Map<String, dynamic>> links) async {
|
|
await _dbHelper.saveFtpLinksForModule(moduleName, links);
|
|
}
|
|
|
|
/// Retrieves only the API configurations that are actively enabled for a given module.
|
|
///
|
|
/// This is primarily for the submission services to know exactly which
|
|
/// destinations to send data to.
|
|
Future<List<Map<String, dynamic>>> getEnabledApiConfigsForModule(String moduleName) async {
|
|
// 1. Check the master switch for the module.
|
|
final pref = await _dbHelper.getModulePreference(moduleName); // Use direct DB call
|
|
if (pref == null || !(pref['is_api_enabled'] as bool)) {
|
|
debugPrint("API submissions are disabled for module '$moduleName'.");
|
|
return []; // Return empty list if API is disabled or not set.
|
|
}
|
|
|
|
// 2. Get all configs with their preference flags.
|
|
final allConfigsWithPrefs = await getAllApiConfigsWithModulePreferences(moduleName);
|
|
|
|
// 3. Filter for only those that are enabled.
|
|
final enabledConfigs = allConfigsWithPrefs.where((config) => config['is_enabled'] == true).toList();
|
|
|
|
debugPrint("Found ${enabledConfigs.length} enabled API destinations for module '$moduleName'.");
|
|
return enabledConfigs;
|
|
}
|
|
|
|
/// Retrieves only the FTP configurations that are actively enabled for a given module.
|
|
Future<List<Map<String, dynamic>>> getEnabledFtpConfigsForModule(String moduleName) async {
|
|
final pref = await _dbHelper.getModulePreference(moduleName); // Use direct DB call
|
|
if (pref == null || !(pref['is_ftp_enabled'] as bool)) {
|
|
debugPrint("FTP submissions are disabled for module '$moduleName'.");
|
|
return [];
|
|
}
|
|
|
|
final allConfigsWithPrefs = await getAllFtpConfigsWithModulePreferences(moduleName);
|
|
final enabledConfigs = allConfigsWithPrefs.where((config) => config['is_enabled'] == true).toList();
|
|
|
|
debugPrint("Found ${enabledConfigs.length} enabled FTP destinations for module '$moduleName'.");
|
|
return enabledConfigs;
|
|
}
|
|
} |