Rework saving to config
This commit is contained in:
@@ -1325,47 +1325,7 @@ class _ModManagerPageState extends State<ModManagerPage> {
|
||||
'Saving mod load order for ${_activeMods.length} active mods to $configPath',
|
||||
);
|
||||
|
||||
// Save the mod list to the XML config file
|
||||
final file = File(configPath);
|
||||
final buffer = StringBuffer();
|
||||
|
||||
buffer.writeln('<?xml version="1.0" encoding="utf-8"?>');
|
||||
buffer.writeln('<ModsConfigData>');
|
||||
buffer.writeln(' <version>1</version>');
|
||||
|
||||
// Write active mods
|
||||
buffer.writeln(' <activeMods>');
|
||||
for (final mod in _activeMods) {
|
||||
buffer.writeln(' <li>${mod.id}</li>');
|
||||
logger.info(' - Adding mod to config: ${mod.name} (${mod.id})');
|
||||
}
|
||||
buffer.writeln(' </activeMods>');
|
||||
|
||||
// Count expansions
|
||||
final expansions = _availableMods.where((m) => m.isExpansion).toList();
|
||||
logger.info('Found ${expansions.length} expansions to include in config');
|
||||
|
||||
// Add known expansions
|
||||
buffer.writeln(' <knownExpansions>');
|
||||
for (final mod in expansions) {
|
||||
buffer.writeln(' <li>${mod.id}</li>');
|
||||
logger.info(' - Adding expansion to config: ${mod.name} (${mod.id})');
|
||||
}
|
||||
buffer.writeln(' </knownExpansions>');
|
||||
|
||||
buffer.writeln('</ModsConfigData>');
|
||||
|
||||
// Ensure directory exists
|
||||
final directory = Directory(configRoot);
|
||||
if (!directory.existsSync()) {
|
||||
logger.info('Creating config directory: $configRoot');
|
||||
directory.createSync(recursive: true);
|
||||
}
|
||||
|
||||
// Write to file
|
||||
logger.info('Writing config file to $configPath');
|
||||
await file.writeAsString(buffer.toString());
|
||||
logger.info('Successfully saved mod configuration');
|
||||
modManager.saveToConfig(LoadOrder(_activeMods));
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
@@ -13,7 +13,9 @@ class LoadOrder {
|
||||
return order.map((mod) => mod.id).toList();
|
||||
}
|
||||
|
||||
LoadOrder();
|
||||
LoadOrder([List<Mod>? order]) {
|
||||
this.order = order ?? [];
|
||||
}
|
||||
|
||||
bool get hasErrors => errors.isNotEmpty;
|
||||
}
|
||||
@@ -204,6 +206,66 @@ class ModList {
|
||||
}
|
||||
}
|
||||
|
||||
void saveToConfig(LoadOrder loadOrder) {
|
||||
final file = File(configPath);
|
||||
final logger = Logger.instance;
|
||||
|
||||
try {
|
||||
// Create XML builder
|
||||
final builder = XmlBuilder();
|
||||
|
||||
// Add XML declaration
|
||||
builder.declaration(encoding: 'utf-8');
|
||||
|
||||
// Add root element
|
||||
builder.element(
|
||||
'ModsConfigData',
|
||||
nest: () {
|
||||
// Add version element
|
||||
builder.element('version', nest: '1.5.4297 rev994');
|
||||
|
||||
// Add active mods element
|
||||
builder.element(
|
||||
'activeMods',
|
||||
nest: () {
|
||||
// Add each mod as a list item
|
||||
for (final mod in loadOrder.order) {
|
||||
builder.element('li', nest: mod.id);
|
||||
logger.info('Adding mod to config: ${mod.name} (${mod.id})');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Add known expansions element
|
||||
final expansions = mods.values.where((m) => m.isExpansion).toList();
|
||||
if (expansions.isNotEmpty) {
|
||||
builder.element(
|
||||
'knownExpansions',
|
||||
nest: () {
|
||||
for (final mod in expansions) {
|
||||
builder.element('li', nest: mod.id);
|
||||
logger.info(
|
||||
'Adding expansion to config: ${mod.name} (${mod.id})',
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Build the XML document
|
||||
final xmlDocument = builder.buildDocument();
|
||||
|
||||
// Write the XML document to file
|
||||
file.writeAsStringSync(xmlDocument.toString());
|
||||
logger.info('Successfully saved mod configuration to: $configPath');
|
||||
} catch (e) {
|
||||
logger.error('Error saving configuration file: $e');
|
||||
throw Exception('Failed to save config file: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void setEnabled(String modId, bool enabled) {
|
||||
if (mods.containsKey(modId)) {
|
||||
final mod = mods[modId]!;
|
||||
|
@@ -34,7 +34,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
final Set<String> _problemMods = {};
|
||||
|
||||
// The currently selected mod IDs (for highlighting)
|
||||
List<String> _selectedMods = [];
|
||||
LoadOrder _loadOrder = LoadOrder();
|
||||
|
||||
// The next potential set of mods (from move calculation)
|
||||
Move? _nextForwardMove;
|
||||
@@ -64,7 +64,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
// Set initial active mods for highlighting
|
||||
if (modManager.activeMods.isNotEmpty) {
|
||||
// Initially select all active mods
|
||||
_selectedMods = List.from(modManager.activeMods.keys);
|
||||
_loadOrder = LoadOrder(modManager.activeMods.values.toList());
|
||||
}
|
||||
|
||||
// Calculate initial moves
|
||||
@@ -100,7 +100,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
|
||||
// Use the mods from the load order result
|
||||
setState(() {
|
||||
_selectedMods = loadOrder.loadOrder;
|
||||
_loadOrder = loadOrder;
|
||||
_updateNextMoves();
|
||||
});
|
||||
}
|
||||
@@ -118,7 +118,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
|
||||
// Use the mods from the load order result
|
||||
setState(() {
|
||||
_selectedMods = loadOrder.loadOrder;
|
||||
_loadOrder = loadOrder;
|
||||
_updateNextMoves();
|
||||
});
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
|
||||
void _saveTroubleshootingConfig() {
|
||||
// Only save if we have a valid selection
|
||||
if (_selectedMods.isEmpty) {
|
||||
if (_loadOrder.order.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('No mods selected to save'),
|
||||
@@ -165,17 +165,13 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
return;
|
||||
}
|
||||
|
||||
// First disable all mods
|
||||
modManager.disableAll();
|
||||
|
||||
// Then enable only the selected mods
|
||||
modManager.enableMods(_selectedMods);
|
||||
modManager.saveToConfig(_loadOrder);
|
||||
|
||||
// Save the configuration (we don't have direct access to save method, so show a message)
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'${_selectedMods.length} mods prepared for testing. Please use Save button in the Mods tab to save config.',
|
||||
'${_loadOrder.order.length} mods prepared for testing. Please use Save button in the Mods tab to save config.',
|
||||
),
|
||||
backgroundColor: Colors.orange,
|
||||
duration: const Duration(seconds: 4),
|
||||
@@ -184,7 +180,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
}
|
||||
|
||||
void _markSelectedAsGood() {
|
||||
if (_selectedMods.isEmpty) {
|
||||
if (_loadOrder.order.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('No mods selected to mark'),
|
||||
@@ -195,15 +191,15 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
for (final modId in _selectedMods) {
|
||||
_checkedMods.add(modId);
|
||||
_problemMods.remove(modId);
|
||||
for (final mod in _loadOrder.order) {
|
||||
_checkedMods.add(mod.id);
|
||||
_problemMods.remove(mod.id);
|
||||
}
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Marked ${_selectedMods.length} mods as good'),
|
||||
content: Text('Marked ${_loadOrder.order.length} mods as good'),
|
||||
backgroundColor: Colors.green,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
@@ -211,7 +207,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
}
|
||||
|
||||
void _markSelectedAsProblem() {
|
||||
if (_selectedMods.isEmpty) {
|
||||
if (_loadOrder.order.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('No mods selected to mark'),
|
||||
@@ -222,15 +218,15 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
for (final modId in _selectedMods) {
|
||||
_problemMods.add(modId);
|
||||
_checkedMods.remove(modId);
|
||||
for (final mod in _loadOrder.order) {
|
||||
_problemMods.add(mod.id);
|
||||
_checkedMods.remove(mod.id);
|
||||
}
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Marked ${_selectedMods.length} mods as problematic'),
|
||||
content: Text('Marked ${_loadOrder.order.length} mods as problematic'),
|
||||
backgroundColor: Colors.orange,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
@@ -307,8 +303,8 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
// Compact instruction
|
||||
Expanded(
|
||||
child: Text(
|
||||
_selectedMods.isNotEmpty
|
||||
? 'Testing ${_selectedMods.length} mods. Tap highlighted mods to navigate. Mark results below:'
|
||||
_loadOrder.order.isNotEmpty
|
||||
? 'Testing ${_loadOrder.order.length} mods. Tap highlighted mods to navigate. Mark results below:'
|
||||
: 'Click highlighted mods to begin testing. Blue→forward, purple←backward.',
|
||||
style: TextStyle(
|
||||
fontSize: AppThemeExtension.of(context).textSizeRegular,
|
||||
@@ -379,7 +375,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
const Spacer(),
|
||||
|
||||
// Buttons to mark selected mods
|
||||
if (_selectedMods.isNotEmpty) ...[
|
||||
if (_loadOrder.order.isNotEmpty) ...[
|
||||
OutlinedButton.icon(
|
||||
icon: Icon(
|
||||
Icons.error,
|
||||
@@ -427,7 +423,7 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
onPressed: _resetTroubleshooter,
|
||||
),
|
||||
|
||||
if (_selectedMods.isNotEmpty) ...[
|
||||
if (_loadOrder.order.isNotEmpty) ...[
|
||||
const SizedBox(width: 4),
|
||||
// Save config button
|
||||
OutlinedButton.icon(
|
||||
@@ -492,7 +488,9 @@ class _ModTroubleshooterWidgetState extends State<ModTroubleshooterWidget> {
|
||||
if (mod == null) return const SizedBox.shrink();
|
||||
|
||||
// Determine if this mod is in the selection range for highlighted navigation
|
||||
final bool isSelected = _selectedMods.contains(modId);
|
||||
final bool isSelected = _loadOrder.order.any(
|
||||
(m) => m.id == modId,
|
||||
);
|
||||
|
||||
// Check if this mod would be included in the next Forward/Backward move
|
||||
bool isInNextForward = false;
|
||||
|
Reference in New Issue
Block a user