feat: track newly installed VMs in prefs

This commit is contained in:
ivo 2025-05-13 20:07:09 +02:00
parent fd2ccebafe
commit 94dcd6c138
5 changed files with 58 additions and 40 deletions

View File

@ -4,6 +4,7 @@ var gIsSnap = Platform.environment['SNAP']?.isNotEmpty ?? false;
const String prefWorkingDirectory = 'workingDirectory'; const String prefWorkingDirectory = 'workingDirectory';
const String prefThemeMode = 'themeMode'; const String prefThemeMode = 'themeMode';
const String prefCurrentLocale = 'currentLocale'; const String prefCurrentLocale = 'currentLocale';
const String prefNewlyInstalledVms = 'newlyInstalledVms';
Future<String> fetchQuickemuVersion() async { Future<String> fetchQuickemuVersion() async {
// Get the version of quickemu // Get the version of quickemu

View File

@ -27,7 +27,7 @@ mixin PreferencesMixin {
return prefs.getInt(key) as T; return prefs.getInt(key) as T;
} else if (T == String) { } else if (T == String) {
return prefs.getString(key) as T; return prefs.getString(key) as T;
} else if (T == List) { } else if (T == List<String>) {
return prefs.getStringList(key) as T; return prefs.getStringList(key) as T;
} }
} }

View File

@ -5,8 +5,10 @@ import 'dart:io';
import 'package:desktop_notifications/desktop_notifications.dart'; import 'package:desktop_notifications/desktop_notifications.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gettext_i18n/gettext_i18n.dart'; import 'package:gettext_i18n/gettext_i18n.dart';
import 'package:quickgui/src/widgets/downloader/run_image_button.dart'; import 'package:quickgui/src/globals.dart';
import 'package:quickgui/src/widgets/downloader/manage_machines_after_download_button.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'package:quickgui/src/mixins/preferences_mixin.dart';
import '../model/operating_system.dart'; import '../model/operating_system.dart';
import '../model/option.dart'; import '../model/option.dart';
@ -31,14 +33,13 @@ class Downloader extends StatefulWidget {
_DownloaderState createState() => _DownloaderState(); _DownloaderState createState() => _DownloaderState();
} }
class _DownloaderState extends State<Downloader> { class _DownloaderState extends State<Downloader> with PreferencesMixin {
final notificationsClient = Platform.isMacOS ? null : NotificationsClient(); final notificationsClient = Platform.isMacOS ? null : NotificationsClient();
final curlPattern = RegExp("( [0-9.]+%)"); final curlPattern = RegExp("( [0-9.]+%)");
late final Stream<double> _progressStream; late final Stream<double> _progressStream;
bool _downloadFinished = false; bool _downloadFinished = false;
var controller = StreamController<double>(); var controller = StreamController<double>();
Process? _process; Process? _process;
String? _newestVmFolderName;
@override @override
void initState() { void initState() {
@ -57,7 +58,7 @@ class _DownloaderState extends State<Downloader> {
} }
} }
Future<String?> findNewestFolder() async { Future<void> addNewestVmToPrefs() async {
final dir = Directory.current; final dir = Directory.current;
final folders = await dir final folders = await dir
.list() .list()
@ -68,7 +69,18 @@ class _DownloaderState extends State<Downloader> {
folders folders
.sort((a, b) => b.statSync().modified.compareTo(a.statSync().modified)); .sort((a, b) => b.statSync().modified.compareTo(a.statSync().modified));
return folders.isNotEmpty ? p.basename(folders.first.path) : null; // Update the prefNewlyInstalledVms with the newest folder
if (folders.isNotEmpty) {
String newestFolder = p.basename(folders.first.path);
final List<String> newVmNames =
await getPreference<List<String>>(prefNewlyInstalledVms) ??
<String>[];
newVmNames.add(newestFolder);
savePreference(prefNewlyInstalledVms, newVmNames);
}
} }
Stream<double> progressStream() { Stream<double> progressStream() {
@ -86,31 +98,29 @@ class _DownloaderState extends State<Downloader> {
process.exitCode.then((value) { process.exitCode.then((value) {
bool _cancelled = value.isNegative; bool _cancelled = value.isNegative;
controller.close(); controller.close();
findNewestFolder().then( addNewestVmToPrefs();
(path) { setState(() {
setState(() { _downloadFinished = true;
_downloadFinished = true;
_newestVmFolderName = path; notificationsClient?.notify(
notificationsClient?.notify( _cancelled
_cancelled ? context.t('Download cancelled')
? context.t('Download cancelled') : context.t('Download complete'),
: context.t('Download complete'), body: _cancelled
body: _cancelled ? context.t(
? context.t( 'Download of {0} has been canceled.',
'Download of {0} has been canceled.', args: [widget.operatingSystem.name],
args: [widget.operatingSystem.name], )
) : context.t(
: context.t( 'Download of {0} has completed.',
'Download of {0} has completed.', args: [widget.operatingSystem.name],
args: [widget.operatingSystem.name], ),
), appName: 'Quickgui',
appName: 'Quickgui', expireTimeoutMs: 10000, /* 10 seconds */
expireTimeoutMs: 10000, /* 10 seconds */ );
); });
});
},
);
}); });
setState(() { setState(() {
@ -165,7 +175,6 @@ class _DownloaderState extends State<Downloader> {
), ),
ManageMachinesAfterDownloadButton( ManageMachinesAfterDownloadButton(
downloadFinished: _downloadFinished, downloadFinished: _downloadFinished,
vmName: _newestVmFolderName ?? '',
), ),
CancelDismissButton( CancelDismissButton(
onCancel: () { onCancel: () {

View File

@ -21,9 +21,7 @@ import '../model/vminfo.dart';
/// Displays a list of available VMs, running state and connection info, /// Displays a list of available VMs, running state and connection info,
/// with buttons to start and stop VMs. /// with buttons to start and stop VMs.
class Manager extends StatefulWidget { class Manager extends StatefulWidget {
const Manager({super.key, this.newVmName}); const Manager({super.key});
final String? newVmName;
@override @override
State<Manager> createState() => _ManagerState(); State<Manager> createState() => _ManagerState();
@ -56,12 +54,14 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
'xterm', 'xterm',
]; ];
Timer? refreshTimer; Timer? refreshTimer;
List<String> newVmNames = <String>[];
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_getTerminalEmulator(); _getTerminalEmulator();
_detectSpice(); _detectSpice();
_setNewVmName();
getPreference<String>(prefWorkingDirectory).then((pref) { getPreference<String>(prefWorkingDirectory).then((pref) {
setState(() { setState(() {
if (pref == null) { if (pref == null) {
@ -83,6 +83,13 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
super.dispose(); super.dispose();
} }
Future<void> _setNewVmName() async {
newVmNames =
await getPreference<List<String>>(prefNewlyInstalledVms) ?? <String>[];
// Delete prefNewlyInstalledVms to only display once
savePreference(prefNewlyInstalledVms, <String>[]);
}
void _getTerminalEmulator() async { void _getTerminalEmulator() async {
// Find out which terminal emulator we have set as the default. // Find out which terminal emulator we have set as the default.
String result = whichSync('x-terminal-emulator') ?? ''; String result = whichSync('x-terminal-emulator') ?? '';
@ -253,7 +260,12 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
final bool active = _activeVms.containsKey(currentVm); final bool active = _activeVms.containsKey(currentVm);
final bool sshy = _sshVms.contains(currentVm); final bool sshy = _sshVms.contains(currentVm);
final bool newVM = widget.newVmName == currentVm; print('currentVm: $currentVm');
print('newVmNames: $newVmNames');
final bool newVM = newVmNames.contains(currentVm);
print('newVM $newVM');
VmInfo vmInfo = VmInfo(); VmInfo vmInfo = VmInfo();
String connectInfo = ''; String connectInfo = '';

View File

@ -5,12 +5,10 @@ import 'package:quickgui/src/pages/manager.dart';
class ManageMachinesAfterDownloadButton extends StatelessWidget { class ManageMachinesAfterDownloadButton extends StatelessWidget {
const ManageMachinesAfterDownloadButton({ const ManageMachinesAfterDownloadButton({
required this.downloadFinished, required this.downloadFinished,
required this.vmName,
super.key, super.key,
}); });
final bool downloadFinished; final bool downloadFinished;
final String vmName;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -30,9 +28,7 @@ class ManageMachinesAfterDownloadButton extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Manager( builder: (context) => const Manager(),
newVmName: vmName,
),
), ),
); );
}, },