Getting close to initial release

This commit is contained in:
Yannick Mauray 2021-10-16 14:58:06 +02:00
parent 09104a1f9c
commit 9c564d7e8c
No known key found for this signature in database
GPG Key ID: 67C4AAC5E99CB909
24 changed files with 339 additions and 37 deletions

BIN
assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -4,7 +4,7 @@ import 'package:window_size/window_size.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
setWindowTitle('QuickUI : a flutter frontend for Quickget and Quickemu');
setWindowTitle('Quickgui : a flutter frontend for Quickget and Quickemu');
setWindowMinSize(const Size(692, 580));
setWindowMaxSize(const Size(692, 580));
runApp(const App());

View File

@ -7,11 +7,10 @@ class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.pink,
),
home: const MainPage(title: 'QuickUI - A Flutter frontend for Quickget and Quickemu'),
home: const MainPage(title: 'Quickgui - A Flutter frontend for Quickget and Quickemu'),
);
}
}

View File

@ -0,0 +1,7 @@
class OperatingSystem {
OperatingSystem({required this.name, this.code, this.hasMore = false});
final String name;
final String? code;
final bool hasMore;
}

View File

@ -0,0 +1,6 @@
class Version {
Version({required this.name, this.code});
final String name;
final String? code;
}

View File

@ -1,5 +1,11 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:quickgui/src/model/operating_system.dart';
import 'package:quickgui/src/model/version.dart';
import 'package:quickgui/src/pages/operating_system_page.dart';
import 'package:quickgui/src/pages/operating_system_selection.dart';
import 'package:quickgui/src/pages/version_selection.dart';
import 'package:quickgui/src/widgets/home_page_button.dart';
class MainPage extends StatefulWidget {
@ -12,6 +18,9 @@ class MainPage extends StatefulWidget {
}
class _MainPageState extends State<MainPage> {
OperatingSystem? _selectedOperatingSystem;
Version? _selectedVersion;
@override
Widget build(BuildContext context) {
return Scaffold(
@ -21,10 +30,13 @@ class _MainPageState extends State<MainPage> {
height: 250,
child: Flex(
direction: Axis.vertical,
children: const [
children: [
Expanded(
child: Center(
child: Text("QuickGui"),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset('assets/images/logo.png'),
),
),
),
],
@ -36,23 +48,60 @@ class _MainPageState extends State<MainPage> {
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
HomePageButton(
text: "Operating system",
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => const OperatingSystemPpage()));
},
),
const HomePageButton(
text: "Version",
onPressed: null,
),
const HomePageButton(
text: "Download",
onPressed: null,
),
],
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
children: [
HomePageButton(
label: "Operating system",
text: _selectedOperatingSystem?.name ?? 'Select...',
onPressed: () {
Navigator.of(context)
.push<OperatingSystem>(MaterialPageRoute(fullscreenDialog: true, builder: (context) => const OperatingSystemSelection()))
.then((selection) {
if (selection != null) {
setState(() {
_selectedOperatingSystem = selection;
_selectedVersion = null;
});
}
});
},
),
HomePageButton(
label: "Version",
text: _selectedVersion?.name ?? 'Select...',
onPressed: (_selectedOperatingSystem != null)
? () {
Navigator.of(context)
.push<Version>(MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => VersionSelection(operatingSystem: _selectedOperatingSystem!),
))
.then((selection) {
if (selection != null) {
setState(() {
_selectedVersion = selection;
});
}
});
}
: null,
),
HomePageButton(
text: 'Download',
onPressed: (_selectedVersion == null)
? null
: () async {
showLoadingIndicator(text: 'Downloading');
await Process.run('quickget', [_selectedOperatingSystem!.code!, _selectedVersion!.code!]);
print('Finished !');
hideOpenDialog();
Navigator.of(context).pop();
},
),
],
),
)
],
),
@ -62,4 +111,44 @@ class _MainPageState extends State<MainPage> {
),
);
}
void showLoadingIndicator({String text = ''}) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => WillPopScope(
onWillPop: () async => false,
child: AlertDialog(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
backgroundColor: Colors.black87,
content: SizedBox(
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 32),
child: Text('Downloading...', style: Theme.of(context).textTheme.bodyText1?.copyWith(color: Colors.white)),
),
const CircularProgressIndicator(),
Padding(
padding: const EdgeInsets.symmetric(vertical: 32),
child: Text(
'Target : ${Directory.current.absolute.path}',
style: Theme.of(context).textTheme.bodyText1?.copyWith(color: Colors.white),
),
),
],
),
),
),
),
);
}
void hideOpenDialog() {
Navigator.of(context).pop();
}
}

View File

@ -0,0 +1,94 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:quickgui/src/model/operating_system.dart';
import 'package:quiver/iterables.dart';
class OperatingSystemSelection extends StatefulWidget {
const OperatingSystemSelection({Key? key, this.showUbuntus = false}) : super(key: key);
final bool showUbuntus;
@override
State<OperatingSystemSelection> createState() => _OperatingSystemSelectionState();
}
class _OperatingSystemSelectionState extends State<OperatingSystemSelection> {
late Future<List<OperatingSystem>> _future;
@override
void initState() {
_future = loadOperatingSystems(widget.showUbuntus);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Select operating system'),
),
body: FutureBuilder<List<OperatingSystem>>(
future: _future,
builder: (context, snapshot) {
if (snapshot.hasData) {
return SingleChildScrollView(
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
var item = snapshot.data![index];
return Card(
child: ListTile(
title: Text(item.name),
trailing: item.hasMore ? const Icon(Icons.chevron_right) : null,
onTap: () {
if (!item.hasMore) {
Navigator.of(context).pop(item);
} else {
Navigator.of(context)
.push(MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => const OperatingSystemSelection(
showUbuntus: true,
)))
.then((selection) {
if (selection != null) {
Navigator.of(context).pop(selection);
}
});
}
},
),
);
},
),
],
),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Future<List<OperatingSystem>> loadOperatingSystems(bool showUbuntus) async {
return Process.run('quickget', []).then<List<OperatingSystem>>((process) {
var stdout = process.stdout as String;
var codes = stdout.split('\n')[1].split(' ').where((element) => showUbuntus ? element.contains('buntu') : !element.contains('buntu'));
var names = codes.map((code) => code.toLowerCase().split('-').map((e) => e[0].toUpperCase() + e.substring(1)).join(' '));
List<OperatingSystem> items = [];
if (!showUbuntus) items.add(OperatingSystem(name: 'Ubuntu', hasMore: true));
items.addAll(zip([codes, names]).map((item) => OperatingSystem(code: item[0], name: item[1])).toList());
items.sort((a, b) => a.name.compareTo(b.name));
return items;
});
}
}

View File

@ -0,0 +1,79 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:quickgui/src/model/operating_system.dart';
import 'package:quickgui/src/model/version.dart';
import 'package:quiver/iterables.dart';
class VersionSelection extends StatefulWidget {
const VersionSelection({Key? key, required this.operatingSystem}) : super(key: key);
final OperatingSystem operatingSystem;
@override
_VersionSelectionState createState() => _VersionSelectionState();
}
class _VersionSelectionState extends State<VersionSelection> {
late Future<List<Version>> _future;
@override
void initState() {
_future = loadOperatingSystemVersions();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Select version for ${widget.operatingSystem.name}'),
),
body: FutureBuilder<List<Version>>(
future: _future,
builder: (context, snapshot) {
if (snapshot.hasData) {
return SingleChildScrollView(
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
var item = snapshot.data![index];
return Card(
child: ListTile(
title: Text(item.name),
onTap: () {
Navigator.of(context).pop(item);
},
),
);
},
),
],
),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
Future<List<Version>> loadOperatingSystemVersions() async {
return Process.run('quickget', [widget.operatingSystem.code!, 'dummy']).then<List<Version>>((process) {
var stdout = process.stdout as String;
var versions = stdout.split('\n')[1].split(' ');
var names =
versions.map((version) => version.toLowerCase().split('-').map((e) => e[0].toUpperCase() + e.substring(1)).join(' ').split('_').join('.')).toList();
List<Version> items = [];
items.addAll(zip([versions, names]).map((e) => Version(code: e[0], name: e[1])));
return items;
});
}
}

View File

@ -1,33 +1,47 @@
import 'package:flutter/material.dart';
class HomePageButton extends StatelessWidget {
final String text;
final VoidCallback? onPressed;
const HomePageButton({
Key? key,
this.label,
required this.text,
this.onPressed,
}) : super(key: key);
final String? label;
final String text;
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
return Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white,
onPrimary: Colors.pink,
),
onPressed: onPressed,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 16, 0, 16),
child: Text(
text.toUpperCase(),
padding: const EdgeInsets.fromLTRB(12, 24, 12, 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 24),
child: Center(
child: Text(
label?.toUpperCase() ?? '',
style: Theme.of(context).textTheme.subtitle2?.copyWith(color: Colors.white),
),
),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white,
onPrimary: Colors.pink,
),
onPressed: onPressed,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 16, 0, 16),
child: Text(text),
),
),
],
),
),
);

Binary file not shown.

View File

@ -0,0 +1,8 @@
Package: quickgui
Version: 1.0.0-1
Section: base
Priority: optional
Architecture: amd64
Maintainer: Yannick Mauray <yannick@frenchguy.ch>
Description: Flutter frontend for Quickget

Binary file not shown.

View File

@ -0,0 +1 @@
{"assets/images/logo.png":["assets/images/logo.png"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}

View File

@ -0,0 +1 @@
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}]

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1 @@
{"app_name":"quickgui","version":"1.0.0","build_number":"1"}

Binary file not shown.

Binary file not shown.

View File

@ -38,6 +38,7 @@ dependencies:
git:
url: git://github.com/google/flutter-desktop-embedding.git
path: plugins/window_size
quiver: ^3.0.1+1
dev_dependencies:
flutter_test:
@ -65,6 +66,8 @@ flutter:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
assets:
- assets/images/logo.png
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.