diff --git a/l10n.yaml b/l10n.yaml index b2fcf348..1baa7ccc 100644 --- a/l10n.yaml +++ b/l10n.yaml @@ -1,3 +1,4 @@ arb-dir: lib/i18n template-arb-file: app_en.arb -output-localization-file: app_localizations.dart \ No newline at end of file +output-localization-file: app_localizations.dart +output-class: I18N \ No newline at end of file diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart index 2dcf8369..db983ef0 100644 --- a/lib/generated/i18n.dart +++ b/lib/generated/i18n.dart @@ -1,122 +1,78 @@ + import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; - // ignore_for_file: non_constant_identifier_names // ignore_for_file: camel_case_types // ignore_for_file: prefer_single_quotes -// This file is automatically generated. DO NOT EDIT, all your changes would be lost. +//This file is automatically generated. DO NOT EDIT, all your changes would be lost. + class S implements WidgetsLocalizations { const S(); static const GeneratedLocalizationsDelegate delegate = - GeneratedLocalizationsDelegate(); + const GeneratedLocalizationsDelegate(); - static S of(BuildContext context) => Localizations.of(context, S); + static S of(BuildContext context) => + Localizations.of(context, WidgetsLocalizations); @override TextDirection get textDirection => TextDirection.ltr; } -class $en extends S { - const $en(); +class en extends S { + const en(); } -class GeneratedLocalizationsDelegate extends LocalizationsDelegate { + +class GeneratedLocalizationsDelegate extends LocalizationsDelegate { const GeneratedLocalizationsDelegate(); List get supportedLocales { return const [ - Locale("en", ""), + + const Locale("en", ""), + ]; } - LocaleListResolutionCallback listResolution({Locale fallback, bool withCountry = true}) { - return (List locales, Iterable supported) { - if (locales == null || locales.isEmpty) { - return fallback ?? supported.first; - } else { - return _resolve(locales.first, fallback, supported, withCountry); - } - }; - } - - LocaleResolutionCallback resolution({Locale fallback, bool withCountry = true}) { + LocaleResolutionCallback resolution({Locale fallback}) { return (Locale locale, Iterable supported) { - return _resolve(locale, fallback, supported, withCountry); + final Locale languageLocale = new Locale(locale.languageCode, ""); + if (supported.contains(locale)) + return locale; + else if (supported.contains(languageLocale)) + return languageLocale; + else { + final Locale fallbackLocale = fallback ?? supported.first; + return fallbackLocale; + } }; } @override - Future load(Locale locale) { + Future load(Locale locale) { final String lang = getLang(locale); - if (lang != null) { - switch (lang) { - case "en": - return SynchronousFuture(const $en()); - default: - // NO-OP. - } + switch (lang) { + + case "en": + return new SynchronousFuture(const en()); + + default: + return new SynchronousFuture(const S()); } - return SynchronousFuture(const S()); } @override - bool isSupported(Locale locale) => _isSupported(locale, true); + bool isSupported(Locale locale) => supportedLocales.contains(locale); @override bool shouldReload(GeneratedLocalizationsDelegate old) => false; - - /// - /// Internal method to resolve a locale from a list of locales. - /// - Locale _resolve(Locale locale, Locale fallback, Iterable supported, bool withCountry) { - if (locale == null || !_isSupported(locale, withCountry)) { - return fallback ?? supported.first; - } - - final Locale languageLocale = Locale(locale.languageCode, ""); - if (supported.contains(locale)) { - return locale; - } else if (supported.contains(languageLocale)) { - return languageLocale; - } else { - final Locale fallbackLocale = fallback ?? supported.first; - return fallbackLocale; - } - } - - /// - /// Returns true if the specified locale is supported, false otherwise. - /// - bool _isSupported(Locale locale, bool withCountry) { - if (locale != null) { - for (Locale supportedLocale in supportedLocales) { - // Language must always match both locales. - if (supportedLocale.languageCode != locale.languageCode) { - continue; - } - - // If country code matches, return this locale. - if (supportedLocale.countryCode == locale.countryCode) { - return true; - } - - // If no country requirement is requested, check if this locale has no country. - if (true != withCountry && (supportedLocale.countryCode == null || supportedLocale.countryCode.isEmpty)) { - return true; - } - } - } - return false; - } } -String getLang(Locale l) => l == null - ? null - : l.countryCode != null && l.countryCode.isEmpty +String getLang(Locale l) => l.countryCode != null && l.countryCode.isEmpty ? l.languageCode : l.toString(); diff --git a/lib/main.dart b/lib/main.dart index ff94b80f..46b31b85 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,21 +1,12 @@ import 'dart:async'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:InvenTree/widget/category_display.dart'; -import 'package:InvenTree/widget/company_list.dart'; -import 'package:InvenTree/widget/location_display.dart'; -import 'package:InvenTree/widget/search.dart'; -import 'package:InvenTree/widget/drawer.dart'; +import 'package:InvenTree/widget/home.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; - -import 'barcode.dart'; - -import 'api.dart'; import 'dsn.dart'; import 'preferences.dart'; @@ -73,16 +64,14 @@ class InvenTreeApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'InvenTree', + onGenerateTitle: (BuildContext context) => I18N.of(context).appTitle, theme: ThemeData( primarySwatch: Colors.lightBlue, secondaryHeaderColor: Colors.blueGrey, ), - home: MyHomePage(title: 'InvenTree'), + home: InvenTreeHomePage(), localizationsDelegates: [ - // ... app-specific localization delegate[s] here - // TODO: uncomment the line below after codegen - // AppLocalizations.delegate, + I18N.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, @@ -95,340 +84,4 @@ class InvenTreeApp extends StatelessWidget { ], ); } -} - - -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - - _MyHomePageState() : super() { - _checkServerConnection(); - } - - String _serverAddress = ""; - - String _serverStatus = "Connecting to server"; - - String _serverMessage = ""; - - bool _serverConnection = false; - - FaIcon _serverIcon = new FaIcon(FontAwesomeIcons.spinner); - - Color _serverStatusColor = Color.fromARGB(255, 50, 50, 250); - - void onConnectSuccess(String msg) { - _serverConnection = true; - _serverMessage = msg; - _serverStatus = "Connected to $_serverAddress"; - _serverStatusColor = Color.fromARGB(255, 50, 250, 50); - _serverIcon = new FaIcon(FontAwesomeIcons.checkCircle, color: _serverStatusColor); - - setState(() {}); - } - - void onConnectFailure(String msg) { - _serverConnection = false; - _serverMessage = msg; - _serverStatus = "Could not connect to $_serverAddress"; - _serverStatusColor = Color.fromARGB(255, 250, 50, 50); - _serverIcon = new FaIcon(FontAwesomeIcons.timesCircle, color: _serverStatusColor); - - setState(() {}); - } - - /* - * Test the server connection - */ - void _checkServerConnection() async { - - var prefs = await SharedPreferences.getInstance(); - - _serverAddress = prefs.getString("server"); - - // Reset the connection status variables - _serverStatus = "Connecting to server"; - _serverMessage = ""; - _serverConnection = false; - _serverIcon = new FaIcon(FontAwesomeIcons.spinner); - _serverStatusColor = Color.fromARGB(255, 50, 50, 250); - - InvenTreeAPI().connect().then((bool result) { - - if (result) { - onConnectSuccess(""); - } else { - onConnectFailure("Could not connect to server"); - } - - }); - - // Update widget state - setState(() {}); - } - - void _search() { - if (!InvenTreeAPI().checkConnection(context)) return; - - Navigator.push(context, MaterialPageRoute(builder: (context) => SearchWidget())); - - } - - void _scan() { - if (!InvenTreeAPI().checkConnection(context)) return; - - scanQrCode(context); - } - - void _parts() { - if (!InvenTreeAPI().checkConnection(context)) return; - - Navigator.push(context, MaterialPageRoute(builder: (context) => CategoryDisplayWidget(null))); - } - - void _stock() { - if (!InvenTreeAPI().checkConnection(context)) return; - - Navigator.push(context, MaterialPageRoute(builder: (context) => LocationDisplayWidget(null))); - } - - void _suppliers() { - if (!InvenTreeAPI().checkConnection(context)) return; - - Navigator.push(context, MaterialPageRoute(builder: (context) => SupplierListWidget())); - } - - void _manufacturers() { - if (!InvenTreeAPI().checkConnection(context)) return; - - Navigator.push(context, MaterialPageRoute(builder: (context) => ManufacturerListWidget())); - } - - void _customers() { - if (!InvenTreeAPI().checkConnection(context)) return; - - Navigator.push(context, MaterialPageRoute(builder: (context) => CustomerListWidget())); - } - - void _unsupported() { - showDialog( - context: context, - child: new SimpleDialog( - title: new Text("Unsupported"), - children: [ - ListTile( - title: Text("This feature is not yet supported"), - subtitle: Text("It will be supported in an upcoming release"), - ) - ], - ) - ); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - actions: [ - /* - IconButton( - icon: FaIcon(FontAwesomeIcons.search), - tooltip: 'Search', - onPressed: _search, - ), - */ - ], - ), - drawer: new InvenTreeDrawer(context), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: ([ - Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - /* - Column( - children: [ - - IconButton( - icon: new FaIcon(FontAwesomeIcons.search), - tooltip: 'Search', - onPressed: _search, - ), - Text("Search"), - ], - ), - */ - Column( - children: [ - IconButton( - icon: new FaIcon(FontAwesomeIcons.barcode), - tooltip: 'Scan Barcode', - onPressed: _scan, - ), - Text("Scan Barcode"), - ], - ), - ], - ), - Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - IconButton( - icon: new FaIcon(FontAwesomeIcons.shapes), - tooltip: 'Parts', - onPressed: _parts, - ), - Text("Parts"), - ], - ), - Column( - children: [ - IconButton( - icon: new FaIcon(FontAwesomeIcons.boxes), - tooltip: 'Stock', - onPressed: _stock, - ), - Text('Stock'), - ], - ), - ], - ), - Spacer(), - // TODO - Re-add these when the features actually do something.. - /* - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - IconButton( - icon: new FaIcon(FontAwesomeIcons.building), - tooltip: "Suppliers", - onPressed: _suppliers, - ), - Text("Suppliers"), - ], - ), - Column( - children: [ - IconButton( - icon: FaIcon(FontAwesomeIcons.industry), - tooltip: "Manufacturers", - onPressed: _manufacturers, - ), - Text("Manufacturers") - ], - ), - Column( - children: [ - IconButton( - icon: FaIcon(FontAwesomeIcons.userTie), - tooltip: "Customers", - onPressed: _customers, - ), - Text("Customers"), - ] - ) - ], - ), - Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - children: [ - IconButton( - icon: new FaIcon(FontAwesomeIcons.tools), - tooltip: "Build", - onPressed: _unsupported, - ), - Text("Build"), - ], - ), - Column( - children: [ - IconButton( - icon: new FaIcon(FontAwesomeIcons.shoppingCart), - tooltip: "Order", - onPressed: _unsupported, - ), - Text("Order"), - ] - ), - Column( - children: [ - IconButton( - icon: new FaIcon(FontAwesomeIcons.truck), - tooltip: "Ship", - onPressed: _unsupported, - ), - Text("Ship"), - ] - ) - ], - ), - Spacer(), - */ - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: ListTile( - title: Text("$_serverStatus", - style: TextStyle(color: _serverStatusColor), - ), - subtitle: Text("$_serverMessage", - style: TextStyle(color: _serverStatusColor), - ), - leading: _serverIcon, - onTap: () { - if (!_serverConnection) { - _checkServerConnection(); - } - }, - ), - ), - ], - ), - ]), - ), - ), - ); - } -} +} \ No newline at end of file diff --git a/lib/widget/home.dart b/lib/widget/home.dart new file mode 100644 index 00000000..b2d99479 --- /dev/null +++ b/lib/widget/home.dart @@ -0,0 +1,337 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'package:InvenTree/barcode.dart'; +import 'package:InvenTree/api.dart'; + +import 'package:InvenTree/widget/category_display.dart'; +import 'package:InvenTree/widget/company_list.dart'; +import 'package:InvenTree/widget/location_display.dart'; +import 'package:InvenTree/widget/search.dart'; +import 'package:InvenTree/widget/drawer.dart'; + +class InvenTreeHomePage extends StatefulWidget { + InvenTreeHomePage({Key key}) : super(key: key); + + @override + _InvenTreeHomePageState createState() => _InvenTreeHomePageState(); +} + +class _InvenTreeHomePageState extends State { + + _InvenTreeHomePageState() : super() { + _checkServerConnection(); + } + + String _serverAddress = ""; + + String _serverStatus = "Connecting to server"; + + String _serverMessage = ""; + + bool _serverConnection = false; + + FaIcon _serverIcon = new FaIcon(FontAwesomeIcons.spinner); + + Color _serverStatusColor = Color.fromARGB(255, 50, 50, 250); + + void onConnectSuccess(String msg) { + _serverConnection = true; + _serverMessage = msg; + _serverStatus = "Connected to $_serverAddress"; + _serverStatusColor = Color.fromARGB(255, 50, 250, 50); + _serverIcon = new FaIcon(FontAwesomeIcons.checkCircle, color: _serverStatusColor); + + setState(() {}); + } + + void onConnectFailure(String msg) { + _serverConnection = false; + _serverMessage = msg; + _serverStatus = "Could not connect to $_serverAddress"; + _serverStatusColor = Color.fromARGB(255, 250, 50, 50); + _serverIcon = new FaIcon(FontAwesomeIcons.timesCircle, color: _serverStatusColor); + + setState(() {}); + } + + /* + * Test the server connection + */ + void _checkServerConnection() async { + + var prefs = await SharedPreferences.getInstance(); + + _serverAddress = prefs.getString("server"); + + // Reset the connection status variables + _serverStatus = "Connecting to server"; + _serverMessage = ""; + _serverConnection = false; + _serverIcon = new FaIcon(FontAwesomeIcons.spinner); + _serverStatusColor = Color.fromARGB(255, 50, 50, 250); + + InvenTreeAPI().connect().then((bool result) { + + if (result) { + onConnectSuccess(""); + } else { + onConnectFailure("Could not connect to server"); + } + + }); + + // Update widget state + setState(() {}); + } + + void _search() { + if (!InvenTreeAPI().checkConnection(context)) return; + + Navigator.push(context, MaterialPageRoute(builder: (context) => SearchWidget())); + + } + + void _scan() { + if (!InvenTreeAPI().checkConnection(context)) return; + + scanQrCode(context); + } + + void _parts() { + if (!InvenTreeAPI().checkConnection(context)) return; + + Navigator.push(context, MaterialPageRoute(builder: (context) => CategoryDisplayWidget(null))); + } + + void _stock() { + if (!InvenTreeAPI().checkConnection(context)) return; + + Navigator.push(context, MaterialPageRoute(builder: (context) => LocationDisplayWidget(null))); + } + + void _suppliers() { + if (!InvenTreeAPI().checkConnection(context)) return; + + Navigator.push(context, MaterialPageRoute(builder: (context) => SupplierListWidget())); + } + + void _manufacturers() { + if (!InvenTreeAPI().checkConnection(context)) return; + + Navigator.push(context, MaterialPageRoute(builder: (context) => ManufacturerListWidget())); + } + + void _customers() { + if (!InvenTreeAPI().checkConnection(context)) return; + + Navigator.push(context, MaterialPageRoute(builder: (context) => CustomerListWidget())); + } + + void _unsupported() { + showDialog( + context: context, + child: new SimpleDialog( + title: new Text("Unsupported"), + children: [ + ListTile( + title: Text("This feature is not yet supported"), + subtitle: Text("It will be supported in an upcoming release"), + ) + ], + ) + ); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + appBar: AppBar( + title: Text(I18N.of(context).appTitle), + actions: [ + /* + IconButton( + icon: FaIcon(FontAwesomeIcons.search), + tooltip: 'Search', + onPressed: _search, + ), + */ + ], + ), + drawer: new InvenTreeDrawer(context), + body: Center( + // Center is a layout widget. It takes a single child and positions it + // in the middle of the parent. + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: ([ + Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + /* + Column( + children: [ + + IconButton( + icon: new FaIcon(FontAwesomeIcons.search), + tooltip: 'Search', + onPressed: _search, + ), + Text("Search"), + ], + ), + */ + Column( + children: [ + IconButton( + icon: new FaIcon(FontAwesomeIcons.barcode), + tooltip: 'Scan Barcode', + onPressed: _scan, + ), + Text("Scan Barcode"), + ], + ), + ], + ), + Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + IconButton( + icon: new FaIcon(FontAwesomeIcons.shapes), + tooltip: 'Parts', + onPressed: _parts, + ), + Text("Parts"), + ], + ), + Column( + children: [ + IconButton( + icon: new FaIcon(FontAwesomeIcons.boxes), + tooltip: 'Stock', + onPressed: _stock, + ), + Text('Stock'), + ], + ), + ], + ), + Spacer(), + // TODO - Re-add these when the features actually do something.. + /* + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + IconButton( + icon: new FaIcon(FontAwesomeIcons.building), + tooltip: "Suppliers", + onPressed: _suppliers, + ), + Text("Suppliers"), + ], + ), + Column( + children: [ + IconButton( + icon: FaIcon(FontAwesomeIcons.industry), + tooltip: "Manufacturers", + onPressed: _manufacturers, + ), + Text("Manufacturers") + ], + ), + Column( + children: [ + IconButton( + icon: FaIcon(FontAwesomeIcons.userTie), + tooltip: "Customers", + onPressed: _customers, + ), + Text("Customers"), + ] + ) + ], + ), + Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + IconButton( + icon: new FaIcon(FontAwesomeIcons.tools), + tooltip: "Build", + onPressed: _unsupported, + ), + Text("Build"), + ], + ), + Column( + children: [ + IconButton( + icon: new FaIcon(FontAwesomeIcons.shoppingCart), + tooltip: "Order", + onPressed: _unsupported, + ), + Text("Order"), + ] + ), + Column( + children: [ + IconButton( + icon: new FaIcon(FontAwesomeIcons.truck), + tooltip: "Ship", + onPressed: _unsupported, + ), + Text("Ship"), + ] + ) + ], + ), + Spacer(), + */ + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: ListTile( + title: Text("$_serverStatus", + style: TextStyle(color: _serverStatusColor), + ), + subtitle: Text("$_serverMessage", + style: TextStyle(color: _serverStatusColor), + ), + leading: _serverIcon, + onTap: () { + if (!_serverConnection) { + _checkServerConnection(); + } + }, + ), + ), + ], + ), + ]), + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 389e467d..6569a05d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -253,7 +253,7 @@ packages: source: hosted version: "1.1.1" intl: - dependency: transitive + dependency: "direct main" description: name: intl url: "https://pub.dartlang.org"