Files
hans ce4dd8d61d feat: Add tests for Wolf3dGuiApp and refactor game data picker management
- Introduced unit tests for the Wolf3dGuiApp to ensure proper directory configuration and audio management.
- Refactored the GameDataPickerManager to streamline directory and file selection processes.
- Removed obsolete GameDataPickerManager and Wolf3dAppManager classes to simplify the architecture.
- Enhanced the Wolf3dFlutterEngine to improve game version handling during save loading.
- Updated existing tests to reflect changes in the game data management structure.
- Removed unnecessary dependencies and cleaned up the codebase for better maintainability.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
2026-03-24 14:35:20 +01:00

157 lines
4.0 KiB
Dart

library;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:wolf_3d_flutter/wolf_3d_flutter.dart';
import 'game_data_picker_manager.dart';
import 'no_game_data_screen.dart';
/// GUI-host application shell that owns setup/import UX.
class Wolf3dGuiApp extends StatefulWidget {
/// Creates the GUI host shell for a prepared engine facade.
const Wolf3dGuiApp({
super.key,
required this.engine,
this.pickerManager,
});
/// Shared initialized facade that owns game data, input, and audio services.
final Wolf3dFlutterEngine engine;
/// Optional injected picker manager used by tests.
final GameDataPickerManager? pickerManager;
@override
State<Wolf3dGuiApp> createState() => _Wolf3dGuiAppState();
}
class _Wolf3dGuiAppState extends State<Wolf3dGuiApp>
with WidgetsBindingObserver {
late final GameDataPickerManager _pickerManager;
Future<void>? _shutdownFuture;
@override
void initState() {
super.initState();
_pickerManager =
widget.pickerManager ?? GameDataPickerManager(engine: widget.engine);
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
unawaited(_ensureAudioShutdown());
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
unawaited(_ensureAudioShutdown());
}
}
Future<void> _ensureAudioShutdown() {
final Future<void>? existing = _shutdownFuture;
if (existing != null) {
return existing;
}
final Future<void> shutdown = widget.engine.shutdownAudio();
_shutdownFuture = shutdown;
return shutdown;
}
Future<void> _pickGameDataDirectory() {
return _runPickerAction(
() => _pickerManager.pickGameDataDirectory(
notifyChanged: () {
if (mounted) {
setState(() {});
}
},
),
);
}
Future<void> _pickGameDataFiles() {
return _runPickerAction(
() => _pickerManager.pickGameDataFiles(
notifyChanged: () {
if (mounted) {
setState(() {});
}
},
),
);
}
Future<void> _runPickerAction(Future<void> Function() action) async {
await action();
final GameDataVersionAnalysis? soleReadyVersion =
_pickerManager.scanResult?.soleReadyVersion;
if (soleReadyVersion == null ||
!mounted ||
widget.engine.availableGames.isNotEmpty) {
return;
}
if (_pickerManager.selectedReadyVersion != soleReadyVersion.version) {
setState(() {
_pickerManager.selectReadyVersion(soleReadyVersion.version);
});
}
await _useSelectedData();
}
Future<void> _useSelectedData() {
return _pickerManager.useSelectedData(
notifyChanged: () {
if (mounted) {
setState(() {});
}
},
);
}
Future<void> _importSelectedData() {
return _pickerManager.importSelectedData(
notifyChanged: () {
if (mounted) {
setState(() {});
}
},
);
}
@override
Widget build(BuildContext context) {
return widget.engine.availableGames.isEmpty
? NoGameDataScreen(
configuredDataDirectory: widget.engine.configuredDataDirectory,
onPickGameDataDirectory: _pickGameDataDirectory,
onPickGameDataFiles: _pickGameDataFiles,
onUseSelectedData: _useSelectedData,
onImportSelectedData: _importSelectedData,
onSelectReadyVersion: (version) {
if (version == null) {
return;
}
setState(() {
_pickerManager.selectReadyVersion(version);
});
},
isLoadingGameData: _pickerManager.isLoadingGameData,
pickerError: _pickerManager.pickerError,
scanResult: _pickerManager.scanResult,
selectedReadyVersion: _pickerManager.selectedReadyVersion,
)
: GameScreen(wolf3d: widget.engine);
}
}