import 'dart:convert'; import 'dart:io'; import 'ostree_service.dart'; class PendingConfirmation { final String packageName; final DeploymentInfo before; final DateTime installedAt; PendingConfirmation({ required this.packageName, required this.before, required this.installedAt, }); } class ConfirmationMarker { static String get _stateDir => '${Platform.environment['HOME']}/.local/state/layer_wizard'; static String get _markerPath => '$_stateDir/pending_confirmation.json'; static String get _autostartPath => '${Platform.environment['HOME']}/.config/autostart/com.ironmagma.layer_wizard.desktop'; static Future write(String packageName, DeploymentInfo before) async { final dir = Directory(_stateDir); if (!await dir.exists()) { await dir.create(recursive: true); } final json = jsonEncode({ 'packageName': packageName, 'before': before.toJson(), 'installedAt': DateTime.now().toIso8601String(), }); await File(_markerPath).writeAsString(json); } static Future read() async { final file = File(_markerPath); if (!await file.exists()) return null; try { final data = jsonDecode(await file.readAsString()) as Map; return PendingConfirmation( packageName: data['packageName'] as String, before: DeploymentInfo.fromJson(data['before'] as Map), installedAt: DateTime.parse(data['installedAt'] as String), ); } catch (_) { // Corrupt/unreadable marker — treat as if nothing is pending rather // than getting the user stuck on a confirmation screen we can't render. return null; } } static Future clear() async { final file = File(_markerPath); if (await file.exists()) { await file.delete(); } } /// Installs an autostart entry pointing at the currently-running binary, /// so the confirmation screen is shown automatically right after the next /// login. Idempotent. static Future installAutostart() async { final dir = Directory('${Platform.environment['HOME']}/.config/autostart'); if (!await dir.exists()) { await dir.create(recursive: true); } final exe = Platform.resolvedExecutable; final contents = ''' [Desktop Entry] Type=Application Name=Layer Wizard Confirmation Comment=Confirm a pending permanent package layer Exec=$exe X-GNOME-Autostart-enabled=true NoDisplay=true '''; await File(_autostartPath).writeAsString(contents); } static Future removeAutostart() async { final file = File(_autostartPath); if (await file.exists()) { await file.delete(); } } }