Implement incremental loading via streaming

This commit is contained in:
2025-03-15 22:50:41 +01:00
parent b80959e58e
commit 2228aeeafa
2 changed files with 142 additions and 9 deletions

View File

@@ -1,9 +1,15 @@
import 'package:flutter/material.dart';
import 'package:rimworld_modman/modloader.dart';
// Global variable to store loaded mods for access across the app
late ModList modManager;
void main() {
ModList(path: modsRoot).load();
ConfigFile(path: configPath).load();
modManager = ModList(path: modsRoot);
modManager.load().listen((mod) {
print(mod);
});
// runApp(const RimWorldModManager());
}
@@ -61,7 +67,7 @@ class _ModManagerHomePageState extends State<ModManagerHomePage> {
});
},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.list), label: 'Mods'),
BottomNavigationBarItem(icon: Icon(Icons.extension), label: 'Mods'),
BottomNavigationBarItem(
icon: Icon(Icons.reorder),
label: 'Load Order',
@@ -77,11 +83,30 @@ class _ModManagerHomePageState extends State<ModManagerHomePage> {
}
// Page to display all installed mods with enable/disable toggles
class ModListPage extends StatelessWidget {
class ModListPage extends StatefulWidget {
const ModListPage({super.key});
@override
State<ModListPage> createState() => _ModListPageState();
}
class _ModListPageState extends State<ModListPage> {
final List<Mod> _loadedMods = [];
bool _isLoading = false;
String _loadingStatus = '';
int _totalModsFound = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body:
_loadedMods.isEmpty && !_isLoading
? _buildEmptyState()
: _buildModList(),
);
}
Widget _buildEmptyState() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@@ -91,20 +116,122 @@ class ModListPage extends StatelessWidget {
Text('Mod List', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 16),
Text(
'Here you\'ll see your installed mods.',
'Ready to scan for RimWorld mods.',
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () {
// TODO: Implement mod scanning functionality
},
onPressed: _startLoadingMods,
child: const Text('Scan for Mods'),
),
],
),
);
}
Widget _buildModList() {
return Column(
children: [
if (_isLoading)
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
LinearProgressIndicator(
value:
_totalModsFound > 0
? _loadedMods.length / _totalModsFound
: null,
),
const SizedBox(height: 8),
Text(
_loadingStatus,
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: _loadedMods.length,
itemBuilder: (context, index) {
final mod = _loadedMods[index];
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: ListTile(
title: Text(mod.name),
subtitle: Text(
'ID: ${mod.id}\nSize: ${mod.size} files',
style: Theme.of(context).textTheme.bodySmall,
),
trailing: Icon(
Icons.circle,
color:
mod.hardDependencies.isNotEmpty
? Colors.orange
: Colors.green,
size: 12,
),
onTap: () {
// TODO: Show mod details
},
),
);
},
),
),
if (!_isLoading && _loadedMods.isNotEmpty)
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('${_loadedMods.length} mods loaded'),
ElevatedButton(
onPressed: _startLoadingMods,
child: const Text('Reload'),
),
],
),
),
],
);
}
void _startLoadingMods() {
setState(() {
_loadedMods.clear();
_isLoading = true;
_loadingStatus = 'Scanning for mods...';
});
// Use batch loading for better performance
modManager
.load()
.listen(
(mod) {
setState(() {
_loadedMods.add(mod);
_loadingStatus = 'Loaded ${_loadedMods.length} mods...';
});
},
onError: (error) {
setState(() {
_isLoading = false;
_loadingStatus = 'Error loading mods: $error';
});
},
onDone: () {
setState(() {
_isLoading = false;
_loadingStatus = 'Completed! ${_loadedMods.length} mods loaded.';
// Sort mods by name for better display
_loadedMods.sort((a, b) => a.name.compareTo(b.name));
});
},
);
}
}
// Page to manage mod load order with dependency visualization