feat: add label for newly installed vms
This commit is contained in:
parent
18e0c20ccb
commit
fd2ccebafe
|
|
@ -5,6 +5,8 @@ import 'dart:io';
|
|||
import 'package:desktop_notifications/desktop_notifications.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gettext_i18n/gettext_i18n.dart';
|
||||
import 'package:quickgui/src/widgets/downloader/run_image_button.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import '../model/operating_system.dart';
|
||||
import '../model/option.dart';
|
||||
|
|
@ -36,6 +38,7 @@ class _DownloaderState extends State<Downloader> {
|
|||
bool _downloadFinished = false;
|
||||
var controller = StreamController<double>();
|
||||
Process? _process;
|
||||
String? _newestVmFolderName;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -54,11 +57,26 @@ class _DownloaderState extends State<Downloader> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<String?> findNewestFolder() async {
|
||||
final dir = Directory.current;
|
||||
final folders = await dir
|
||||
.list()
|
||||
.where((entity) => entity is Directory)
|
||||
.cast<Directory>()
|
||||
.toList();
|
||||
|
||||
folders
|
||||
.sort((a, b) => b.statSync().modified.compareTo(a.statSync().modified));
|
||||
|
||||
return folders.isNotEmpty ? p.basename(folders.first.path) : null;
|
||||
}
|
||||
|
||||
Stream<double> progressStream() {
|
||||
var options = [widget.operatingSystem.code, widget.version.version];
|
||||
if (widget.option != null) {
|
||||
options.add(widget.option!.option);
|
||||
}
|
||||
|
||||
Process.start('quickget', options).then((process) {
|
||||
if (widget.option!.downloader != 'zsync') {
|
||||
process.stderr.transform(utf8.decoder).forEach(parseCurlProgress);
|
||||
|
|
@ -69,25 +87,30 @@ class _DownloaderState extends State<Downloader> {
|
|||
process.exitCode.then((value) {
|
||||
bool _cancelled = value.isNegative;
|
||||
controller.close();
|
||||
setState(() {
|
||||
_downloadFinished = true;
|
||||
notificationsClient?.notify(
|
||||
_cancelled
|
||||
? context.t('Download cancelled')
|
||||
: context.t('Download complete'),
|
||||
body: _cancelled
|
||||
? context.t(
|
||||
'Download of {0} has been canceled.',
|
||||
args: [widget.operatingSystem.name],
|
||||
)
|
||||
: context.t(
|
||||
'Download of {0} has completed.',
|
||||
args: [widget.operatingSystem.name],
|
||||
),
|
||||
appName: 'Quickgui',
|
||||
expireTimeoutMs: 10000, /* 10 seconds */
|
||||
);
|
||||
});
|
||||
findNewestFolder().then(
|
||||
(path) {
|
||||
setState(() {
|
||||
_downloadFinished = true;
|
||||
_newestVmFolderName = path;
|
||||
notificationsClient?.notify(
|
||||
_cancelled
|
||||
? context.t('Download cancelled')
|
||||
: context.t('Download complete'),
|
||||
body: _cancelled
|
||||
? context.t(
|
||||
'Download of {0} has been canceled.',
|
||||
args: [widget.operatingSystem.name],
|
||||
)
|
||||
: context.t(
|
||||
'Download of {0} has completed.',
|
||||
args: [widget.operatingSystem.name],
|
||||
),
|
||||
appName: 'Quickgui',
|
||||
expireTimeoutMs: 10000, /* 10 seconds */
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
setState(() {
|
||||
|
|
@ -103,10 +126,7 @@ class _DownloaderState extends State<Downloader> {
|
|||
appBar: AppBar(
|
||||
title: Text(
|
||||
context.t('Downloading {0}', args: [
|
||||
'${widget.operatingSystem.name} ${widget.version.version}' +
|
||||
(widget.option!.option.isNotEmpty
|
||||
? ' (${widget.option!.option})'
|
||||
: '')
|
||||
'${widget.operatingSystem.name} ${widget.version.version}${widget.option!.option.isNotEmpty ? ' (${widget.option!.option})' : ''}'
|
||||
]),
|
||||
),
|
||||
automaticallyImplyLeading: false,
|
||||
|
|
@ -117,10 +137,10 @@ class _DownloaderState extends State<Downloader> {
|
|||
child: StreamBuilder(
|
||||
stream: _progressStream,
|
||||
builder: (context, AsyncSnapshot<double> snapshot) {
|
||||
var data = !snapshot.hasData ||
|
||||
widget.option!.downloader != 'curl'
|
||||
? null
|
||||
: snapshot.data;
|
||||
var data =
|
||||
!snapshot.hasData || widget.option!.downloader != 'curl'
|
||||
? null
|
||||
: snapshot.data;
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
|
|
@ -143,6 +163,10 @@ class _DownloaderState extends State<Downloader> {
|
|||
},
|
||||
),
|
||||
),
|
||||
ManageMachinesAfterDownloadButton(
|
||||
downloadFinished: _downloadFinished,
|
||||
vmName: _newestVmFolderName ?? '',
|
||||
),
|
||||
CancelDismissButton(
|
||||
onCancel: () {
|
||||
_process?.kill();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||
import 'package:gettext_i18n/gettext_i18n.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:process_run/shell.dart';
|
||||
import 'package:quickgui/src/widgets/manager/new_vm_tag.dart';
|
||||
import 'package:version/version.dart';
|
||||
|
||||
import '../globals.dart';
|
||||
|
|
@ -20,7 +21,9 @@ import '../model/vminfo.dart';
|
|||
/// Displays a list of available VMs, running state and connection info,
|
||||
/// with buttons to start and stop VMs.
|
||||
class Manager extends StatefulWidget {
|
||||
const Manager({super.key});
|
||||
const Manager({super.key, this.newVmName});
|
||||
|
||||
final String? newVmName;
|
||||
|
||||
@override
|
||||
State<Manager> createState() => _ManagerState();
|
||||
|
|
@ -249,6 +252,9 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
|
|||
List<Widget> _buildRow(String currentVm, Color buttonColor) {
|
||||
final bool active = _activeVms.containsKey(currentVm);
|
||||
final bool sshy = _sshVms.contains(currentVm);
|
||||
|
||||
final bool newVM = widget.newVmName == currentVm;
|
||||
|
||||
VmInfo vmInfo = VmInfo();
|
||||
String connectInfo = '';
|
||||
if (active) {
|
||||
|
|
@ -287,7 +293,12 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
|
|||
return <Widget>[
|
||||
ListTile(
|
||||
leading: osIcon ?? const Icon(Icons.computer, size: 32),
|
||||
title: Text(currentVm),
|
||||
title: Row(
|
||||
children: [
|
||||
Text(currentVm),
|
||||
newVM ? const NewVmTag() : const SizedBox.shrink()
|
||||
],
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:gettext_i18n/gettext_i18n.dart';
|
||||
import 'package:quickgui/src/pages/manager.dart';
|
||||
|
||||
class ManageMachinesAfterDownloadButton extends StatelessWidget {
|
||||
const ManageMachinesAfterDownloadButton({
|
||||
required this.downloadFinished,
|
||||
required this.vmName,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final bool downloadFinished;
|
||||
final String vmName;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
downloadFinished
|
||||
? ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
foregroundColor: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Manager(
|
||||
newVmName: vmName,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(context.t('Manage existing machines')),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class NewVmTag extends StatelessWidget {
|
||||
const NewVmTag({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.new_releases,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 4.0),
|
||||
child: Text(
|
||||
'new',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
name: quickgui
|
||||
description: An elegant virtual machine manager for the desktop
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.2.10+1
|
||||
|
||||
environment:
|
||||
|
|
@ -15,6 +15,7 @@ dependencies:
|
|||
cupertino_icons: ^1.0.8
|
||||
desktop_notifications: ^0.6.3
|
||||
file_picker: ^8.0.6
|
||||
path: ^1.9.1
|
||||
flutter_svg: ^2.0.17
|
||||
gettext: ^1.2.0
|
||||
gettext_i18n: ^1.0.7
|
||||
|
|
|
|||
Loading…
Reference in New Issue