Files
inventree-app/lib/preferences.dart
T
Reza Fouladian ca655f36fe Add intent wedge scanner, MDM support for Android (#863)
Add Android intent wedge scanner support with auto configuration for supported Zebra and Datalogic devices.
Intent wedge scans can be done without pressing the scan button first.

Adds the ability for an MDM server to push settings on Android.
2026-08-16 13:59:20 +10:00

193 lines
5.7 KiB
Dart

import "dart:async";
import "dart:ui";
import "package:inventree/l10n/supported_locales.dart";
import "package:path_provider/path_provider.dart";
import "package:sembast/sembast_io.dart";
import "package:path/path.dart";
// Settings key values
const String INV_HOME_SHOW_SUBSCRIBED = "homeShowSubscribed";
const String INV_HOME_SHOW_PO = "homeShowPo";
const String INV_HOME_SHOW_SO = "homeShowSo";
const String INV_HOME_SHOW_SHIPMENTS = "homeShowShipments";
const String INV_HOME_SHOW_BUILD = "homeShowBuild";
const String INV_HOME_SHOW_MANUFACTURERS = "homeShowManufacturers";
const String INV_HOME_SHOW_CUSTOMERS = "homeShowCustomers";
const String INV_HOME_SHOW_SUPPLIERS = "homeShowSuppliers";
const String INV_HOME_SHOW_TRANSFER = "homeShowTransfer";
const String INV_SCREEN_ORIENTATION = "appScreenOrientation";
const String INV_SHOW_PK = "showPk";
// 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";
// Label printing settings
const String INV_ENABLE_LABEL_PRINTING = "enableLabelPrinting";
const String INV_LABEL_DEFAULT_TEMPLATES = "defaultLabelTemplates";
const String INV_LABEL_DEFAULT_PRINTER = "defaultLabelPrinter";
const String INV_LABEL_DEFAULT_PLUGIN = "defaultLabelPlugin";
// Part settings
const String INV_PART_SHOW_BOM = "partShowBom";
const String INV_PART_SHOW_PRICING = "partShowPricing";
const String INV_PART_SHOW_REQUIREMENTS = "partShowRequirements";
// Stock settings
const String INV_STOCK_SHOW_HISTORY = "stockShowHistory";
const String INV_STOCK_SHOW_TESTS = "stockShowTests";
const String INV_STOCK_CONFIRM_SCAN = "stockConfirmScan";
// Purchase order settings
const String INV_PO_ENABLE = "poEnable";
const String INV_PO_SHOW_CAMERA = "poShowCamera";
const String INV_PO_CONFIRM_SCAN = "poConfirmScan";
// Sales order settings
const String INV_SO_ENABLE = "soEnable";
const String INV_SO_SHOW_CAMERA = "soShowCamera";
const String INV_REPORT_ERRORS = "reportErrors";
const String INV_STRICT_HTTPS = "strictHttps";
// Barcode settings
const String INV_BARCODE_SCAN_DELAY = "barcodeScanDelay";
const String INV_BARCODE_SCAN_TYPE = "barcodeScanType";
const String INV_BARCODE_SCAN_SINGLE = "barcodeScanSingle";
// Barcode scanner types
const int BARCODE_CONTROLLER_CAMERA = 0;
const int BARCODE_CONTROLLER_WEDGE = 1;
const int BARCODE_CONTROLLER_INTENT = 2;
// Whether one-time intent wedge detection has run
const String INV_BARCODE_WEDGE_DETECTED = "barcodeWedgeDetected";
/*
* Class for storing InvenTree preferences in a NoSql DB
*/
class InvenTreePreferencesDB {
InvenTreePreferencesDB._();
static final InvenTreePreferencesDB _singleton = InvenTreePreferencesDB._();
static InvenTreePreferencesDB get instance => _singleton;
Completer<Database> _dbOpenCompleter = Completer();
bool isOpen = false;
Future<Database> get database async {
if (!isOpen) {
// Calling _openDatabase will also complete the completer with database instance
_openDatabase();
isOpen = true;
}
// If the database is already opened, awaiting the future will happen instantly.
// Otherwise, awaiting the returned future will take some time - until complete() is called
// on the Completer in _openDatabase() below.
return _dbOpenCompleter.future;
}
Future<void> _openDatabase() async {
// Get a platform-specific directory where persistent app data can be stored
final appDocumentDir = await getApplicationDocumentsDirectory();
// Path with the form: /platform-specific-directory/demo.db
final dbPath = join(appDocumentDir.path, "InvenTreeSettings.db");
final database = await databaseFactoryIo.openDatabase(dbPath);
_dbOpenCompleter.complete(database);
}
}
/*
* InvenTree setings manager class.
* Provides functions for loading and saving settings, with provision for default values
*/
class InvenTreeSettingsManager {
factory InvenTreeSettingsManager() {
return _manager;
}
InvenTreeSettingsManager._internal();
final store = StoreRef("settings");
Future<Database> get _db async => InvenTreePreferencesDB.instance.database;
Future<Locale?> getSelectedLocale() async {
final String locale_name = await getValue("customLocale", "") as String;
if (locale_name.isEmpty) {
return null;
}
for (var locale in supported_locales) {
if (locale.toString() == locale_name) {
return locale;
}
}
// No matching locale found
return null;
}
Future<void> setSelectedLocale(Locale? locale) async {
await setValue("customLocale", locale?.toString() ?? "");
}
Future<void> removeValue(String key) async {
await store.record(key).delete(await _db);
}
Future<dynamic> getValue(String key, dynamic backup) async {
dynamic value = await store.record(key).get(await _db);
// Retrieve value
if (value == "__null__") {
value = null;
}
if (value == null) {
return backup;
}
return value;
}
// Load a boolean setting
Future<bool> getBool(String key, bool backup) async {
final dynamic value = await getValue(key, backup);
if (value is bool) {
return value;
} else if (value is String) {
return value.toLowerCase().contains("t");
} else {
return false;
}
}
// Store a key:value pair in the database
Future<void> setValue(String key, dynamic value) async {
// Encode null values as strings
value ??= "__null__";
await store.record(key).put(await _db, value);
}
// Ensure we only ever create a single instance of this class
static final InvenTreeSettingsManager _manager =
InvenTreeSettingsManager._internal();
}