Implement incremental loading via streaming
This commit is contained in:
143
lib/main.dart
143
lib/main.dart
@@ -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
|
||||
|
@@ -177,7 +177,7 @@ class ModList {
|
||||
|
||||
ModList({required this.path});
|
||||
|
||||
void load() {
|
||||
Stream<Mod> load() async* {
|
||||
final directory = Directory(path);
|
||||
print('Loading configuration from: $path');
|
||||
|
||||
@@ -187,8 +187,12 @@ class ModList {
|
||||
entities.whereType<Directory>().map((dir) => dir.path).toList();
|
||||
|
||||
print('Found ${modDirectories.length} mod directories:');
|
||||
|
||||
for (final modDir in modDirectories) {
|
||||
try {
|
||||
// Add a small delay to prevent UI freezing and give time for rendering
|
||||
await Future.delayed(const Duration(milliseconds: 5));
|
||||
|
||||
final mod = Mod.fromDirectory(modDir);
|
||||
mods[mod.id] = mod;
|
||||
print(
|
||||
@@ -198,6 +202,8 @@ class ModList {
|
||||
'Soft Dependencies: ${mod.softDependencies.join(', ')}, '
|
||||
'Incompatibilities: ${mod.incompatabilities.join(', ')}',
|
||||
);
|
||||
|
||||
yield mod;
|
||||
print('Current total mods loaded: ${mods.length}');
|
||||
} catch (e) {
|
||||
print('Error loading mod from directory: $modDir');
|
||||
|
Reference in New Issue
Block a user