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:
parent
ba409660f4
commit
71bf3ad049
@ -1,5 +1,7 @@
|
|||||||
### -
|
### -
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- Adds options for configuring screen orientation
|
||||||
- Improvements to barcode scanning
|
- Improvements to barcode scanning
|
||||||
- Translation updates
|
- Translation updates
|
||||||
|
|
||||||
|
@ -627,6 +627,21 @@
|
|||||||
"onOrderDetails": "Items currently on order",
|
"onOrderDetails": "Items currently on order",
|
||||||
"@onOrderDetails": {},
|
"@onOrderDetails": {},
|
||||||
|
|
||||||
|
"orientation": "Screen Orientation",
|
||||||
|
"@orientation": {},
|
||||||
|
|
||||||
|
"orientationDetail": "Screen orientation (requires restart)",
|
||||||
|
"@orientationDetail": {},
|
||||||
|
|
||||||
|
"orientationLandscape": "Landscape",
|
||||||
|
"@orientationLandscape": {},
|
||||||
|
|
||||||
|
"orientationPortrait": "Portrait",
|
||||||
|
"@orientationPortrait": {},
|
||||||
|
|
||||||
|
"orientationSystem": "System",
|
||||||
|
"@orientationSystem": {},
|
||||||
|
|
||||||
"outstanding": "Outstanding",
|
"outstanding": "Outstanding",
|
||||||
"@outstanding": {},
|
"@outstanding": {},
|
||||||
|
|
||||||
|
@ -55,9 +55,29 @@ Future<void> main() async {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
runApp(
|
final int orientation = await InvenTreeSettingsManager().getValue(INV_SCREEN_ORIENTATION, SCREEN_ORIENTATION_SYSTEM) as int;
|
||||||
InvenTreeApp(savedThemeMode)
|
|
||||||
);
|
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 {
|
}, (Object error, StackTrace stackTrace) async {
|
||||||
sentryReportError("main.runZonedGuarded", error, stackTrace);
|
sentryReportError("main.runZonedGuarded", error, stackTrace);
|
||||||
|
@ -15,6 +15,13 @@ const String INV_HOME_SHOW_MANUFACTURERS = "homeShowManufacturers";
|
|||||||
const String INV_HOME_SHOW_CUSTOMERS = "homeShowCustomers";
|
const String INV_HOME_SHOW_CUSTOMERS = "homeShowCustomers";
|
||||||
const String INV_HOME_SHOW_SUPPLIERS = "homeShowSuppliers";
|
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_BARCODE = "barcodeSounds";
|
||||||
const String INV_SOUNDS_SERVER = "serverSounds";
|
const String INV_SOUNDS_SERVER = "serverSounds";
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ import "package:flutter/material.dart";
|
|||||||
import "package:adaptive_theme/adaptive_theme.dart";
|
import "package:adaptive_theme/adaptive_theme.dart";
|
||||||
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
||||||
import "package:flutter_localized_locales/flutter_localized_locales.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:one_context/one_context.dart";
|
||||||
|
|
||||||
import "package:inventree/api_form.dart";
|
import "package:inventree/api_form.dart";
|
||||||
@ -34,6 +36,8 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
|
|
||||||
bool darkMode = false;
|
bool darkMode = false;
|
||||||
|
|
||||||
|
int screenOrientation = SCREEN_ORIENTATION_SYSTEM;
|
||||||
|
|
||||||
Locale? locale;
|
Locale? locale;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -51,6 +55,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
|
serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
|
||||||
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
|
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
|
||||||
strictHttps = await InvenTreeSettingsManager().getValue(INV_STRICT_HTTPS, false) 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;
|
darkMode = AdaptiveTheme.of(context).mode.isDark;
|
||||||
|
|
||||||
@ -116,9 +121,9 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
InvenTreeApp.of(context)?.setLocale(locale);
|
InvenTreeApp.of(context)?.setLocale(locale);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
@ -128,6 +133,21 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
languageName = LocaleNames.of(context)!.nameOf(locale.toString()) ?? L10().languageDefault;
|
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(
|
return Scaffold(
|
||||||
key: _settingsKey,
|
key: _settingsKey,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -138,42 +158,6 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
|||||||
children: [
|
children: [
|
||||||
/* Sound Settings */
|
/* Sound Settings */
|
||||||
Divider(height: 3),
|
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(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
L10().appSettings,
|
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(
|
ListTile(
|
||||||
title: Text(L10().strictHttps),
|
title: Text(L10().strictHttps),
|
||||||
subtitle: Text(L10().strictHttpsDetails),
|
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),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -10,6 +10,51 @@ import "package:inventree/preferences.dart";
|
|||||||
import "package:inventree/widget/snacks.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
|
* Display a "confirmation" dialog allowing the user to accept or reject an action
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user