feat: Enhance CLI and GUI to support configurable game data directory persistence
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
library;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
/// Whether desktop window-management APIs are expected to work on this host.
|
||||
bool get supportsDesktopWindowing {
|
||||
@@ -15,3 +17,21 @@ bool get supportsDesktopWindowing {
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// Ensures desktop windowing plugin state is initialized when supported.
|
||||
///
|
||||
/// This safely no-ops on non-desktop targets and in hosts where the plugin is
|
||||
/// not registered.
|
||||
Future<void> ensureDesktopWindowingInitialized({
|
||||
WindowManager? windowing,
|
||||
}) async {
|
||||
if (!supportsDesktopWindowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await (windowing ?? windowManager).ensureInitialized();
|
||||
} on MissingPluginException {
|
||||
// No-op on hosts where the window manager plugin is unavailable.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
library;
|
||||
|
||||
export 'game_data_directory_persistence_stub.dart'
|
||||
if (dart.library.io) 'game_data_directory_persistence_io.dart';
|
||||
@@ -0,0 +1,99 @@
|
||||
library;
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
/// Persists the configured game-data directory path as JSON.
|
||||
class DefaultGameDataDirectoryPersistence {
|
||||
DefaultGameDataDirectoryPersistence({String? filePath})
|
||||
: _filePath = filePath;
|
||||
|
||||
final String? _filePath;
|
||||
String? _resolvedPath;
|
||||
|
||||
/// Absolute JSON file path used for persistence.
|
||||
String get filePath {
|
||||
if (_resolvedPath != null) {
|
||||
return _resolvedPath!;
|
||||
}
|
||||
|
||||
if (_filePath != null && _filePath.isNotEmpty) {
|
||||
_resolvedPath = _filePath;
|
||||
return _resolvedPath!;
|
||||
}
|
||||
|
||||
_resolvedPath = '$platformConfigDir/data_source.json';
|
||||
return _resolvedPath!;
|
||||
}
|
||||
|
||||
/// Loads a previously persisted data-directory path.
|
||||
Future<String?> loadDataDirectory() async {
|
||||
try {
|
||||
final file = File(filePath);
|
||||
if (!await file.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final raw = await file.readAsString();
|
||||
if (raw.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final decoded = jsonDecode(raw);
|
||||
if (decoded is! Map<String, Object?>) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Object? value = decoded['dataDirectory'];
|
||||
if (value is! String) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final normalized = value.trim();
|
||||
return normalized.isEmpty ? null : normalized;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Persists [directoryPath] for future startups.
|
||||
Future<void> saveDataDirectory(String? directoryPath) async {
|
||||
try {
|
||||
final normalized = directoryPath?.trim();
|
||||
final file = File(filePath);
|
||||
|
||||
await file.parent.create(recursive: true);
|
||||
if (normalized == null || normalized.isEmpty) {
|
||||
if (await file.exists()) {
|
||||
await file.delete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final payload = jsonEncode(<String, Object>{
|
||||
'dataDirectory': normalized,
|
||||
});
|
||||
await file.writeAsString(payload, flush: true);
|
||||
} catch (_) {
|
||||
// Best-effort only.
|
||||
}
|
||||
}
|
||||
|
||||
String get platformConfigDir {
|
||||
if (Platform.isLinux) {
|
||||
final String xdg = Platform.environment['XDG_CONFIG_HOME'] ?? '';
|
||||
final String home = Platform.environment['HOME'] ?? '.';
|
||||
return xdg.isNotEmpty ? '$xdg/wolf3d' : '$home/.config/wolf3d';
|
||||
}
|
||||
if (Platform.isMacOS) {
|
||||
final String home = Platform.environment['HOME'] ?? '.';
|
||||
return '$home/Library/Application Support/wolf3d';
|
||||
}
|
||||
if (Platform.isWindows) {
|
||||
final String appData = Platform.environment['APPDATA'] ?? '.';
|
||||
return '$appData/wolf3d';
|
||||
}
|
||||
final String home = Platform.environment['HOME'] ?? '.';
|
||||
return '$home/.config/wolf3d';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
library;
|
||||
|
||||
/// No-op persistence used on platforms without `dart:io` support.
|
||||
class DefaultGameDataDirectoryPersistence {
|
||||
DefaultGameDataDirectoryPersistence({String? filePath});
|
||||
|
||||
/// Loads a previously persisted data-directory path.
|
||||
Future<String?> loadDataDirectory() async {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Persists [directoryPath] for future startups.
|
||||
Future<void> saveDataDirectory(String? directoryPath) async {}
|
||||
}
|
||||
Reference in New Issue
Block a user