From 2788ed5bd7072d305fa7d432b83b3c721efbcd74 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 5 Jan 2022 14:00:38 +1100 Subject: [PATCH] User configurable home screen actions --- assets/release_notes.md | 3 +- lib/api.dart | 4 +- lib/app_settings.dart | 15 +++ lib/helpers.dart | 4 +- lib/l10n | 2 +- lib/settings/app_settings.dart | 167 +++++++++++++++++++++++++-------- lib/widget/dialogs.dart | 2 +- lib/widget/home.dart | 161 ++++++++++++++++++++----------- 8 files changed, 256 insertions(+), 102 deletions(-) diff --git a/assets/release_notes.md b/assets/release_notes.md index e57c1795..f8de631c 100644 --- a/assets/release_notes.md +++ b/assets/release_notes.md @@ -1,11 +1,12 @@ ## InvenTree App Release Notes --- -### 0.x.x - January 2022 +### 0.5.4 - January 2022 --- - Enable usage of camera flash when scanning barcodes - Enable camera toggle when scanning barcodes +- Configurable home screen actions - Updated icon set - Removed "upload error report" functionality (instead link to GitHub issues) - Updated multiple language translations diff --git a/lib/api.dart b/lib/api.dart index b58b620f..5343937e 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -488,9 +488,7 @@ class InvenTreeAPI { List perms = List.from(roles[role] as List); return perms.contains(permission); } catch (error, stackTrace) { - if (error is CastError) { - // Ignore CastError - } else if (error is TypeError) { + if (error is TypeError) { // Ignore TypeError } else { // Unknown error - report it! diff --git a/lib/app_settings.dart b/lib/app_settings.dart index f47b41d3..8a705293 100644 --- a/lib/app_settings.dart +++ b/lib/app_settings.dart @@ -5,6 +5,21 @@ import "package:sembast/sembast.dart"; import "package:inventree/preferences.dart"; +// Settings key values +const String INV_HOME_SHOW_SUBSCRIBED = "homeShowSubscribed"; +const String INV_HOME_SHOW_PO = "homeShowPo"; +const String INV_HOME_SHOW_MANUFACTURERS = "homeShowManufacturers"; +const String INV_HOME_SHOW_CUSTOMERS = "homeShowCustomers"; +const String INV_HOME_SHOW_SUPPLIERS = "homeShowSuppliers"; + +const String INV_SOUNDS_BARCODE = "barcodeSounds"; +const String INV_SOUNDS_SERVER = "serverSounds"; + +const String INV_PART_SUBCATEGORY = "partSubcategory"; + +const String INV_STOCK_SUBLOCATION = "stockSublocation"; + + class InvenTreeSettingsManager { factory InvenTreeSettingsManager() { diff --git a/lib/helpers.dart b/lib/helpers.dart index 8b3e1764..524cd92a 100644 --- a/lib/helpers.dart +++ b/lib/helpers.dart @@ -18,7 +18,7 @@ String simpleNumberString(double number) { Future successTone() async { - final bool en = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; + final bool en = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool; if (en) { final player = AudioCache(); @@ -28,7 +28,7 @@ Future successTone() async { Future failureTone() async { - final bool en = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; + final bool en = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool; if (en) { final player = AudioCache(); diff --git a/lib/l10n b/lib/l10n index 08bfb71d..feae1bee 160000 --- a/lib/l10n +++ b/lib/l10n @@ -1 +1 @@ -Subproject commit 08bfb71daa2f4cd0780708bf3553ff2b1e2adc50 +Subproject commit feae1bee4275544b1571a37273b0e8113622eb2c diff --git a/lib/settings/app_settings.dart b/lib/settings/app_settings.dart index 4a79dd93..6a120bb4 100644 --- a/lib/settings/app_settings.dart +++ b/lib/settings/app_settings.dart @@ -19,9 +19,21 @@ class _InvenTreeAppSettingsState extends State { final GlobalKey<_InvenTreeAppSettingsState> _settingsKey = GlobalKey<_InvenTreeAppSettingsState>(); + // Home screen settings + bool homeShowSubscribed = true; + bool homeShowPo = true; + bool homeShowSuppliers = true; + bool homeShowManufacturers = true; + bool homeShowCustomers = true; + + // Sound settings bool barcodeSounds = true; bool serverSounds = true; + + // Part settings bool partSubcategory = false; + + // Stock settings bool stockSublocation = false; @override @@ -32,45 +44,21 @@ class _InvenTreeAppSettingsState extends State { } Future loadSettings() async { - barcodeSounds = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; - serverSounds = await InvenTreeSettingsManager().getValue("serverSounds", true) as bool; - partSubcategory = await InvenTreeSettingsManager().getValue("partSubcategory", true) as bool; - stockSublocation = await InvenTreeSettingsManager().getValue("stockSublocation", true) as bool; + // Load initial settings - setState(() { - }); - } + homeShowSubscribed = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_SUBSCRIBED, true) as bool; + homeShowPo = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_PO, true) as bool; + homeShowManufacturers = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_MANUFACTURERS, true) as bool; + homeShowCustomers = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_CUSTOMERS, true) as bool; + homeShowSuppliers = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_SUPPLIERS, true) as bool; - Future setBarcodeSounds(bool en) async { + barcodeSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool; + serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool; - await InvenTreeSettingsManager().setValue("barcodeSounds", en); - barcodeSounds = await InvenTreeSettingsManager().getBool("barcodeSounds", true); + partSubcategory = await InvenTreeSettingsManager().getValue(INV_PART_SUBCATEGORY, true) as bool; - setState(() { - }); - } - - Future setServerSounds(bool en) async { - - await InvenTreeSettingsManager().setValue("serverSounds", en); - serverSounds = await InvenTreeSettingsManager().getBool("serverSounds", true); - - setState(() { - }); - } - - Future setPartSubcategory(bool en) async { - await InvenTreeSettingsManager().setValue("partSubcategory", en); - partSubcategory = await InvenTreeSettingsManager().getBool("partSubcategory", true); - - setState(() { - }); - } - - Future setStockSublocation(bool en) async { - await InvenTreeSettingsManager().setValue("stockSublocation", en); - stockSublocation = await InvenTreeSettingsManager().getBool("stockSublocation", true); + stockSublocation = await InvenTreeSettingsManager().getValue(INV_STOCK_SUBLOCATION, true) as bool; setState(() { }); @@ -87,12 +75,90 @@ class _InvenTreeAppSettingsState extends State { body: Container( child: ListView( children: [ + /* Home Screen Settings */ + ListTile( + title: Text( + L10().homeScreen, + style: TextStyle(fontWeight: FontWeight.bold) + ), + ), + ListTile( + title: Text(L10().homeShowSubscribed), + subtitle: Text(L10().homeShowSubscribedDescription), + leading: FaIcon(FontAwesomeIcons.bell), + trailing: Switch( + value: homeShowSubscribed, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_HOME_SHOW_SUBSCRIBED, value); + setState(() { + homeShowSubscribed = value; + }); + }, + ) + ), + ListTile( + title: Text(L10().homeShowPo), + subtitle: Text(L10().homeShowPoDescription), + leading: FaIcon(FontAwesomeIcons.shoppingCart), + trailing: Switch( + value: homeShowPo, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_HOME_SHOW_PO, value); + setState(() { + homeShowPo = value; + }); + }, + ), + ), + ListTile( + title: Text(L10().homeShowSuppliers), + subtitle: Text(L10().homeShowSuppliersDescription), + leading: FaIcon(FontAwesomeIcons.building), + trailing: Switch( + value: homeShowSuppliers, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_HOME_SHOW_SUPPLIERS, value); + setState(() { + homeShowSuppliers = value; + }); + }, + ), + ), + ListTile( + title: Text(L10().homeShowManufacturers), + subtitle: Text(L10().homeShowManufacturersDescription), + leading: FaIcon(FontAwesomeIcons.industry), + trailing: Switch( + value: homeShowManufacturers, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_HOME_SHOW_MANUFACTURERS, value); + setState(() { + homeShowManufacturers = value; + }); + }, + ), + ), + ListTile( + title: Text(L10().homeShowCustomers), + subtitle: Text(L10().homeShowCustomersDescription), + leading: FaIcon(FontAwesomeIcons.userTie), + trailing: Switch( + value: homeShowCustomers, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_HOME_SHOW_CUSTOMERS, value); + setState(() { + homeShowCustomers = value; + }); + }, + ), + ), + /* Part Settings */ + Divider(height: 3), ListTile( title: Text( L10().parts, style: TextStyle(fontWeight: FontWeight.bold), ), - leading: FaIcon(FontAwesomeIcons.shapes), ), ListTile( title: Text(L10().includeSubcategories), @@ -100,15 +166,20 @@ class _InvenTreeAppSettingsState extends State { leading: FaIcon(FontAwesomeIcons.sitemap), trailing: Switch( value: partSubcategory, - onChanged: setPartSubcategory, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_PART_SUBCATEGORY, value); + setState(() { + partSubcategory = value; + }); + }, ), ), + /* Stock Settings */ Divider(height: 3), ListTile( title: Text(L10().stock, style: TextStyle(fontWeight: FontWeight.bold), ), - leading: FaIcon(FontAwesomeIcons.boxes), ), ListTile( title: Text(L10().includeSublocations), @@ -116,9 +187,15 @@ class _InvenTreeAppSettingsState extends State { leading: FaIcon(FontAwesomeIcons.sitemap), trailing: Switch( value: stockSublocation, - onChanged: setStockSublocation, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_STOCK_SUBLOCATION, value); + setState(() { + stockSublocation = value; + }); + }, ), ), + /* Sound Settings */ Divider(height: 3), ListTile( title: Text( @@ -133,7 +210,12 @@ class _InvenTreeAppSettingsState extends State { leading: FaIcon(FontAwesomeIcons.server), trailing: Switch( value: serverSounds, - onChanged: setServerSounds, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_SOUNDS_SERVER, value); + setState(() { + serverSounds = value; + }); + }, ), ), ListTile( @@ -142,7 +224,12 @@ class _InvenTreeAppSettingsState extends State { leading: Icon(Icons.qr_code), trailing: Switch( value: barcodeSounds, - onChanged: setBarcodeSounds, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_SOUNDS_BARCODE, value); + setState(() { + barcodeSounds = value; + }); + }, ), ), Divider(height: 1), diff --git a/lib/widget/dialogs.dart b/lib/widget/dialogs.dart index 2d80d650..6dca2ec5 100644 --- a/lib/widget/dialogs.dart +++ b/lib/widget/dialogs.dart @@ -106,7 +106,7 @@ Future showServerError(String title, String description) async { } // Play a sound - final bool tones = await InvenTreeSettingsManager().getValue("serverSounds", true) as bool; + final bool tones = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool; if (tones) { final player = AudioCache(); diff --git a/lib/widget/home.dart b/lib/widget/home.dart index 7a3f37e7..07ac9733 100644 --- a/lib/widget/home.dart +++ b/lib/widget/home.dart @@ -19,6 +19,8 @@ import "package:inventree/widget/search.dart"; import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/drawer.dart"; +import "../app_settings.dart"; + class InvenTreeHomePage extends StatefulWidget { @@ -32,10 +34,20 @@ class _InvenTreeHomePageState extends State { _InvenTreeHomePageState() : super() { + // Load display settings + _loadSettings(); + // Initially load the profile and attempt server connection _loadProfile(); + } + bool homeShowPo = true; + bool homeShowSubscribed = true; + bool homeShowManufacturers = true; + bool homeShowCustomers = true; + bool homeShowSuppliers = true; + final GlobalKey<_InvenTreeHomePageState> _homeKey = GlobalKey<_InvenTreeHomePageState>(); // Selected user profile @@ -127,6 +139,22 @@ class _InvenTreeHomePageState extends State { }); } + Future _loadSettings() async { + + print("_loadSettings"); + + homeShowSubscribed = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_SUBSCRIBED, true) as bool; + homeShowPo = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_PO, true) as bool; + homeShowManufacturers = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_MANUFACTURERS, true) as bool; + homeShowCustomers = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_CUSTOMERS, true) as bool; + homeShowSuppliers = await InvenTreeSettingsManager().getValue(INV_HOME_SHOW_SUPPLIERS, true) as bool; + + print("suppliers: ${homeShowSuppliers}"); + + setState(() { + }); + } + Future _loadProfile() async { _profile = await UserProfileDBManager().getSelectedProfile(); @@ -201,95 +229,120 @@ class _InvenTreeHomePageState extends State { } List getGridTiles(BuildContext context) { - return [ - _iconButton( - context, - L10().scanBarcode, - Icons.qr_code_scanner, - callback: () { - _scan(context); - } - ), - _iconButton( - context, - L10().search, - FontAwesomeIcons.search, - callback: () { - _search(context); - } - ), - _iconButton( - context, - L10().parts, - FontAwesomeIcons.shapes, - callback: () { - _showParts(context); - } - ), - _iconButton( + + List tiles = []; + + // Barcode scanner + tiles.add(_iconButton( + context, + L10().scanBarcode, + Icons.qr_code_scanner, + callback: () { + _scan(context); + } + )); + + // Search widget + tiles.add(_iconButton( + context, + L10().search, + FontAwesomeIcons.search, + callback: () { + _search(context); + } + )); + + // Parts + tiles.add(_iconButton( + context, + L10().parts, + FontAwesomeIcons.shapes, + callback: () { + _showParts(context); + } + )); + + // Starred parts + if (homeShowSubscribed) { + tiles.add(_iconButton( context, L10().partsStarred, - FontAwesomeIcons.solidStar, + FontAwesomeIcons.bell, callback: () { _showStarredParts(context); } - ), - _iconButton( - context, - L10().stock, - FontAwesomeIcons.boxes, - callback: () { - _showStock(context); - } - ), - _iconButton( + )); + } + + // Stock button + tiles.add(_iconButton( + context, + L10().stock, + FontAwesomeIcons.boxes, + callback: () { + _showStock(context); + } + )); + + // Purchase orderes + if (homeShowPo) { + tiles.add(_iconButton( context, L10().purchaseOrders, FontAwesomeIcons.shoppingCart, callback: () { _showPurchaseOrders(context); } - ), - /* - _iconButton( - context, - L10().salesOrders, - FontAwesomeIcons.truck, - ), - */ - _iconButton( + )); + } + + // Suppliers + if (homeShowSuppliers) { + tiles.add(_iconButton( context, L10().suppliers, FontAwesomeIcons.building, callback: () { _showSuppliers(context); } - ), - _iconButton( + )); + } + + // Manufacturers + if (homeShowManufacturers) { + tiles.add(_iconButton( context, L10().manufacturers, FontAwesomeIcons.industry, callback: () { _showManufacturers(context); } - ), - _iconButton( + )); + } + + // Customers + if (homeShowCustomers) { + tiles.add(_iconButton( context, L10().customers, FontAwesomeIcons.userTie, callback: () { _showCustomers(context); } - ), - _iconButton( + )); + } + + // Settings + tiles.add(_iconButton( context, L10().settings, FontAwesomeIcons.cogs, callback: () { _showSettings(context); } - ) - ]; + )); + + return tiles; } @override