Mixin preferences: Refactored shared preferences functions to be generic setters/getters used as a mixin (#2)

* Refactored shared preferences functions to be generic setters/getters using key/values to allow for multiple preferences to be stored. Refactored the shared preferences functions as a mixin for ease of use. Directory change is now remembered across the app pages.

* Added initState() to downloader_menu.dart to fetch prefWorkingDirectory

Co-authored-by: ElanMan <ben@elanman.com>
This commit is contained in:
Ben Hall 2021-11-05 00:52:58 +00:00 committed by GitHub
parent 7124b6fc35
commit a9ae0e28fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 43 deletions

View File

@ -1,8 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:quickgui/src/app.dart'; import 'package:quickgui/src/app.dart';
import 'package:quickgui/src/globals.dart';
import 'package:quickgui/src/model/operating_system.dart'; import 'package:quickgui/src/model/operating_system.dart';
import 'package:quickgui/src/model/option.dart'; import 'package:quickgui/src/model/option.dart';
import 'package:quickgui/src/model/version.dart'; import 'package:quickgui/src/model/version.dart';
@ -44,7 +42,6 @@ Future<List<OperatingSystem>> loadOperatingSystems(bool showUbuntus) async {
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
Directory.current = gCurrentDirectoy;
setWindowTitle('Quickgui : a flutter frontend for Quickget and Quickemu'); setWindowTitle('Quickgui : a flutter frontend for Quickget and Quickemu');
setWindowMinSize(const Size(692, 580)); setWindowMinSize(const Size(692, 580));
setWindowMaxSize(const Size(692, 580)); setWindowMaxSize(const Size(692, 580));

View File

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

View File

@ -1,6 +1,4 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart';
var gIsSnap = Platform.environment['SNAP']?.isNotEmpty ?? false; var gIsSnap = Platform.environment['SNAP']?.isNotEmpty ?? false;
var gCurrentDirectoy = Directory(Platform.environment['HOME'] ?? Directory.current.absolute.path); const String prefWorkingDirectory = 'workingDirectory';

View File

@ -0,0 +1,16 @@
import 'package:shared_preferences/shared_preferences.dart';
mixin PreferencesMixin {
void savePreference(key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, value);
}
Future getPreference(key) async {
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey(key)) {
final preference = prefs.getString(key);
return preference ?? false;
}
}
}

View File

@ -3,7 +3,6 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:quickgui/src/globals.dart';
import 'package:quickgui/src/model/operating_system.dart'; import 'package:quickgui/src/model/operating_system.dart';
import 'package:quickgui/src/model/option.dart'; import 'package:quickgui/src/model/option.dart';
import 'package:quickgui/src/model/version.dart'; import 'package:quickgui/src/model/version.dart';
@ -37,7 +36,6 @@ class _DownloaderState extends State<Downloader> {
@override @override
void initState() { void initState() {
Directory.current = gCurrentDirectoy;
_progressStream = progressStream(); _progressStream = progressStream();
super.initState(); super.initState();
} }
@ -122,7 +120,7 @@ class _DownloaderState extends State<Downloader> {
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 32), padding: const EdgeInsets.only(top: 32),
child: Text("Target folder : $gCurrentDirectoy"), child: Text("Target folder : ${Directory.current}"),
), ),
], ],
); );

View File

@ -4,8 +4,9 @@ import 'package:flutter/material.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'dart:io'; import 'dart:io';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:quickgui/src/globals.dart';
import 'package:quickgui/src/model/vminfo.dart'; import 'package:quickgui/src/model/vminfo.dart';
import 'package:quickgui/src/mixins/preferences_mixin.dart';
/// VM manager page. /// VM manager page.
/// Displays a list of available VMs, running state and connection info, /// Displays a list of available VMs, running state and connection info,
@ -17,18 +18,24 @@ class Manager extends StatefulWidget {
State<Manager> createState() => _ManagerState(); State<Manager> createState() => _ManagerState();
} }
class _ManagerState extends State<Manager> { class _ManagerState extends State<Manager> with PreferencesMixin {
List<String> _currentVms = []; List<String> _currentVms = [];
Map<String, VmInfo> _activeVms = {}; Map<String, VmInfo> _activeVms = {};
final List<String> _spicyVms = []; final List<String> _spicyVms = [];
Timer? refreshTimer; Timer? refreshTimer;
static const String prefsWorkingDirectory = 'workingDirectory';
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_getCurrentDirectory(); getPreference(prefWorkingDirectory).then((pref) {
Future.delayed(Duration.zero, () => _getVms(context)); // Reload VM list when we enter the page. if (pref is String) {
setState(() {
Directory.current = pref;
});
Future.delayed(Duration.zero, () => _getVms(context)); // Reload VM list when we enter the page.
}
});
refreshTimer = Timer.periodic(const Duration(seconds: 5), (Timer t) { refreshTimer = Timer.periodic(const Duration(seconds: 5), (Timer t) {
_getVms(context); _getVms(context);
}); // Reload VM list every 5 seconds. }); // Reload VM list every 5 seconds.
@ -40,23 +47,6 @@ class _ManagerState extends State<Manager> {
super.dispose(); super.dispose();
} }
void _saveCurrentDirectory() async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(prefsWorkingDirectory, Directory.current.path);
}
void _getCurrentDirectory() async {
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey(prefsWorkingDirectory)) {
setState(() {
final directory = prefs.getString(prefsWorkingDirectory);
if (directory != null) {
Directory.current = directory;
}
});
}
}
VmInfo _parseVmInfo(name) { VmInfo _parseVmInfo(name) {
VmInfo info = VmInfo(); VmInfo info = VmInfo();
List<String> lines = File(name + '/' + name + '.ports').readAsLinesSync(); List<String> lines = File(name + '/' + name + '.ports').readAsLinesSync();
@ -109,8 +99,11 @@ class _ManagerState extends State<Manager> {
onPressed: () async { onPressed: () async {
String? result = await FilePicker.platform.getDirectoryPath(); String? result = await FilePicker.platform.getDirectoryPath();
if (result != null) { if (result != null) {
Directory.current = result; setState(() {
_saveCurrentDirectory(); Directory.current = result;
});
savePreference(prefWorkingDirectory, Directory.current.path);
_getVms(context); _getVms(context);
} }
}, },

View File

@ -1,8 +1,8 @@
import 'dart:io'; import 'dart:io';
import 'package:quickgui/src/globals.dart';
import 'package:quickgui/src/mixins/preferences_mixin.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:quickgui/src/globals.dart';
import 'package:quickgui/src/widgets/home_page/home_page_button_group.dart'; import 'package:quickgui/src/widgets/home_page/home_page_button_group.dart';
class DownloaderMenu extends StatefulWidget { class DownloaderMenu extends StatefulWidget {
@ -12,7 +12,19 @@ class DownloaderMenu extends StatefulWidget {
State<DownloaderMenu> createState() => _DownloaderMenuState(); State<DownloaderMenu> createState() => _DownloaderMenuState();
} }
class _DownloaderMenuState extends State<DownloaderMenu> { class _DownloaderMenuState extends State<DownloaderMenu> with PreferencesMixin {
@override
void initState() {
super.initState();
getPreference(prefWorkingDirectory).then((pref) {
if (pref is String) {
setState(() {
Directory.current = pref;
});
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Expanded( return Expanded(
@ -40,12 +52,13 @@ class _DownloaderMenuState extends State<DownloaderMenu> {
var folder = await FilePicker.platform.getDirectoryPath(dialogTitle: "Pick a folder"); var folder = await FilePicker.platform.getDirectoryPath(dialogTitle: "Pick a folder");
if (folder != null) { if (folder != null) {
setState(() { setState(() {
gCurrentDirectoy = Directory(folder); Directory.current = folder;
}); });
savePreference(prefWorkingDirectory, Directory.current.path);
} }
}, },
child: Text( child: Text(
"Working directory : ${gCurrentDirectoy.path}", "Working directory : ${Directory.current.path}",
style: Theme.of(context).textTheme.subtitle1!.copyWith(color: Colors.white), style: Theme.of(context).textTheme.subtitle1!.copyWith(color: Colors.white),
), ),
), ),