2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 05:26:47 +00:00

App orientation (#369)

* Configurable screen orientation

- Follow system (default)
- Fixed in portrait
- Fixed in landscape

* Fix for dialog
This commit is contained in:
Oliver 2023-06-13 19:53:50 +10:00 committed by GitHub
parent ba409660f4
commit 71bf3ad049
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 185 additions and 40 deletions

View File

@ -1,5 +1,7 @@
### -
---
- Adds options for configuring screen orientation
- Improvements to barcode scanning
- Translation updates

View File

@ -627,6 +627,21 @@
"onOrderDetails": "Items currently on order",
"@onOrderDetails": {},
"orientation": "Screen Orientation",
"@orientation": {},
"orientationDetail": "Screen orientation (requires restart)",
"@orientationDetail": {},
"orientationLandscape": "Landscape",
"@orientationLandscape": {},
"orientationPortrait": "Portrait",
"@orientationPortrait": {},
"orientationSystem": "System",
"@orientationSystem": {},
"outstanding": "Outstanding",
"@outstanding": {},

View File

@ -55,9 +55,29 @@ Future<void> main() async {
);
};
runApp(
InvenTreeApp(savedThemeMode)
);
final int orientation = await InvenTreeSettingsManager().getValue(INV_SCREEN_ORIENTATION, SCREEN_ORIENTATION_SYSTEM) as int;
List<DeviceOrientation> orientations = [];
switch (orientation) {
case SCREEN_ORIENTATION_PORTRAIT:
orientations.add(DeviceOrientation.portraitUp);
break;
case SCREEN_ORIENTATION_LANDSCAPE:
orientations.add(DeviceOrientation.landscapeLeft);
break;
default:
orientations.add(DeviceOrientation.portraitUp);
orientations.add(DeviceOrientation.landscapeLeft);
orientations.add(DeviceOrientation.landscapeRight);
break;
}
SystemChrome.setPreferredOrientations(orientations).then((_) {
runApp(
InvenTreeApp(savedThemeMode)
);
});
}, (Object error, StackTrace stackTrace) async {
sentryReportError("main.runZonedGuarded", error, stackTrace);

View File

@ -15,6 +15,13 @@ const String INV_HOME_SHOW_MANUFACTURERS = "homeShowManufacturers";
const String INV_HOME_SHOW_CUSTOMERS = "homeShowCustomers";
const String INV_HOME_SHOW_SUPPLIERS = "homeShowSuppliers";
const String INV_SCREEN_ORIENTATION = "appScreenOrientation";
// Available screen orientation values
const int SCREEN_ORIENTATION_SYSTEM = 0;
const int SCREEN_ORIENTATION_PORTRAIT = 1;
const int SCREEN_ORIENTATION_LANDSCAPE = 2;
const String INV_SOUNDS_BARCODE = "barcodeSounds";
const String INV_SOUNDS_SERVER = "serverSounds";

View File

@ -3,6 +3,8 @@ import "package:flutter/material.dart";
import "package:adaptive_theme/adaptive_theme.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart";
import "package:flutter_localized_locales/flutter_localized_locales.dart";
import "package:inventree/app_colors.dart";
import "package:inventree/widget/dialogs.dart";
import "package:one_context/one_context.dart";
import "package:inventree/api_form.dart";
@ -34,6 +36,8 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
bool darkMode = false;
int screenOrientation = SCREEN_ORIENTATION_SYSTEM;
Locale? locale;
@override
@ -51,6 +55,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) as bool;
screenOrientation = await InvenTreeSettingsManager().getValue(INV_SCREEN_ORIENTATION, SCREEN_ORIENTATION_SYSTEM) as int;
darkMode = AdaptiveTheme.of(context).mode.isDark;
@ -116,9 +121,9 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
InvenTreeApp.of(context)?.setLocale(locale);
}
);
}
@override
Widget build(BuildContext context) {
@ -128,6 +133,21 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
languageName = LocaleNames.of(context)!.nameOf(locale.toString()) ?? L10().languageDefault;
}
IconData orientationIcon = Icons.screen_rotation;
switch (screenOrientation) {
case SCREEN_ORIENTATION_PORTRAIT:
orientationIcon = Icons.screen_lock_portrait;
break;
case SCREEN_ORIENTATION_LANDSCAPE:
orientationIcon = Icons.screen_lock_landscape;
break;
case SCREEN_ORIENTATION_SYSTEM:
default:
orientationIcon = Icons.screen_rotation;
break;
}
return Scaffold(
key: _settingsKey,
appBar: AppBar(
@ -138,42 +158,6 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
children: [
/* Sound Settings */
Divider(height: 3),
ListTile(
title: Text(
L10().sounds,
style: TextStyle(fontWeight: FontWeight.bold),
),
leading: FaIcon(FontAwesomeIcons.volumeHigh),
),
ListTile(
title: Text(L10().serverError),
subtitle: Text(L10().soundOnServerError),
leading: FaIcon(FontAwesomeIcons.server),
trailing: Switch(
value: serverSounds,
onChanged: (bool value) {
InvenTreeSettingsManager().setValue(INV_SOUNDS_SERVER, value);
setState(() {
serverSounds = value;
});
},
),
),
ListTile(
title: Text(L10().barcodeTones),
subtitle: Text(L10().soundOnBarcodeAction),
leading: Icon(Icons.qr_code),
trailing: Switch(
value: barcodeSounds,
onChanged: (bool value) {
InvenTreeSettingsManager().setValue(INV_SOUNDS_BARCODE, value);
setState(() {
barcodeSounds = value;
});
},
),
),
Divider(height: 1),
ListTile(
title: Text(
L10().appSettings,
@ -199,6 +183,41 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
}
)
),
GestureDetector(
child: ListTile(
title: Text(L10().orientation),
subtitle: Text(L10().orientationDetail),
leading: Icon(Icons.screen_rotation_alt),
trailing: Icon(orientationIcon),
),
onTap: () async {
choiceDialog(
L10().orientation,
[
ListTile(
leading: Icon(Icons.screen_rotation, color: screenOrientation == SCREEN_ORIENTATION_SYSTEM ? COLOR_ACTION : null),
title: Text(L10().orientationSystem),
),
ListTile(
leading: Icon(Icons.screen_lock_portrait, color: screenOrientation == SCREEN_ORIENTATION_PORTRAIT ? COLOR_ACTION : null),
title: Text(L10().orientationPortrait),
),
ListTile(
leading: Icon(Icons.screen_lock_landscape, color: screenOrientation == SCREEN_ORIENTATION_LANDSCAPE ? COLOR_ACTION : null),
title: Text(L10().orientationLandscape),
)
],
onSelected: (idx) async {
screenOrientation = idx as int;
InvenTreeSettingsManager().setValue(INV_SCREEN_ORIENTATION, screenOrientation);
setState(() {
});
}
);
},
),
ListTile(
title: Text(L10().strictHttps),
subtitle: Text(L10().strictHttpsDetails),
@ -235,6 +254,43 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
},
),
),
ListTile(
title: Text(
L10().sounds,
style: TextStyle(fontWeight: FontWeight.bold),
),
leading: FaIcon(FontAwesomeIcons.volumeHigh),
),
Divider(),
ListTile(
title: Text(L10().serverError),
subtitle: Text(L10().soundOnServerError),
leading: FaIcon(FontAwesomeIcons.server),
trailing: Switch(
value: serverSounds,
onChanged: (bool value) {
InvenTreeSettingsManager().setValue(INV_SOUNDS_SERVER, value);
setState(() {
serverSounds = value;
});
},
),
),
ListTile(
title: Text(L10().barcodeTones),
subtitle: Text(L10().soundOnBarcodeAction),
leading: Icon(Icons.qr_code),
trailing: Switch(
value: barcodeSounds,
onChanged: (bool value) {
InvenTreeSettingsManager().setValue(INV_SOUNDS_BARCODE, value);
setState(() {
barcodeSounds = value;
});
},
),
),
Divider(height: 1),
]
)
)

View File

@ -10,6 +10,51 @@ import "package:inventree/preferences.dart";
import "package:inventree/widget/snacks.dart";
/*
* Launch a dialog allowing the user to select from a list of options
*/
Future<void> choiceDialog(String title, List<Widget> items, {Function? onSelected}) async {
List<Widget> choices = [];
for (int idx = 0; idx < items.length; idx++) {
choices.add(
GestureDetector(
child: items[idx],
onTap: () {
Navigator.pop(OneContext().context!);
if (onSelected != null) {
onSelected(idx);
}
},
)
);
}
OneContext().showDialog(
builder: (BuildContext context) {
return AlertDialog(
title: Text(title),
content: SingleChildScrollView(
child: Column(
children: choices,
)
),
actions: [
TextButton(
child: Text(L10().cancel),
onPressed: () {
Navigator.pop(OneContext().context!);
},
)
],
);
}
);
}
/*
* Display a "confirmation" dialog allowing the user to accept or reject an action
*/