diff --git a/lib/redux/ui/pref_state.dart b/lib/redux/ui/pref_state.dart index 6f8208921..9fbda1b6b 100644 --- a/lib/redux/ui/pref_state.dart +++ b/lib/redux/ui/pref_state.dart @@ -59,7 +59,7 @@ abstract class PrefState implements Built { bool get isTablet => appLayout != AppLayout.mobile; - bool get isMobile => layout == AppLayout.mobile; + bool get isMobile => appLayout == AppLayout.mobile; bool get isMenuFloated => appLayout == AppLayout.mobile || menuSidebarMode == AppSidebarMode.float; diff --git a/lib/ui/product/product_list.dart b/lib/ui/product/product_list.dart index 13ff03d63..b366da670 100644 --- a/lib/ui/product/product_list.dart +++ b/lib/ui/product/product_list.dart @@ -4,6 +4,7 @@ import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/product/product_actions.dart'; +import 'package:invoiceninja_flutter/redux/ui/pref_state.dart'; import 'package:invoiceninja_flutter/ui/app/entities/entity_actions_dialog.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart'; import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart'; @@ -35,46 +36,83 @@ class ProductList extends StatelessWidget { final store = StoreProvider.of(context); final listUIState = store.state.uiState.productUIState.listUIState; final isInMultiselect = listUIState.isInMultiselect(); + final isList = store.state.prefState.moduleLayout == ModuleLayout.list; + final localization = AppLocalization.of(context); + + final listView = ListView.separated( + separatorBuilder: (context, index) => ListDivider(), + itemCount: viewModel.productList.length, + itemBuilder: (BuildContext context, index) { + final productId = viewModel.productList[index]; + final product = viewModel.productMap[productId]; + + void showDialog() => showEntityActionsDialog( + entities: [product], + context: context, + ); + + return ProductListItem( + userCompany: viewModel.state.userCompany, + filter: viewModel.filter, + product: product, + onEntityAction: (EntityAction action) { + if (action == EntityAction.more) { + showDialog(); + } else { + handleProductAction(context, [product], action); + } + }, + onTap: () => viewModel.onProductTap(context, product), + onLongPress: () async { + final longPressIsSelection = + store.state.prefState.longPressSelectionIsDefault ?? true; + if (longPressIsSelection && !isInMultiselect) { + handleProductAction( + context, [product], EntityAction.toggleMultiselect); + } else { + showDialog(); + } + }, + isChecked: isInMultiselect && listUIState.isSelected(product.id), + ); + }); + + final dataTableView = SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: DataTable( + columns: [ + DataColumn( + label: Text(localization.name), + ), + DataColumn(label: Text(localization.price), numeric: true), + DataColumn(label: Text(localization.cost), numeric: true), + DataColumn(label: Text(localization.quantity), numeric: true), + ], + rows: getDataTableRows(viewModel), + ))); return RefreshIndicator( onRefresh: () => viewModel.onRefreshed(context), - child: ListView.separated( - separatorBuilder: (context, index) => ListDivider(), - itemCount: viewModel.productList.length, - itemBuilder: (BuildContext context, index) { - final productId = viewModel.productList[index]; - final product = viewModel.productMap[productId]; - - void showDialog() => showEntityActionsDialog( - entities: [product], - context: context, - ); - - return ProductListItem( - userCompany: viewModel.state.userCompany, - filter: viewModel.filter, - product: product, - onEntityAction: (EntityAction action) { - if (action == EntityAction.more) { - showDialog(); - } else { - handleProductAction(context, [product], action); - } - }, - onTap: () => viewModel.onProductTap(context, product), - onLongPress: () async { - final longPressIsSelection = - store.state.prefState.longPressSelectionIsDefault ?? true; - if (longPressIsSelection && !isInMultiselect) { - handleProductAction( - context, [product], EntityAction.toggleMultiselect); - } else { - showDialog(); - } - }, - isChecked: isInMultiselect && listUIState.isSelected(product.id), - ); - }), + child: isList ? listView : dataTableView, ); } + + List getDataTableRows(ProductListVM viewModel) { + final products = viewModel.productList + .map((productId) => viewModel.productMap[productId]) + .toList(); + + return products.map((product) { + return DataRow( + cells: [ + DataCell(Text(product.productKey)), + DataCell(Text(product.price.toString())), + DataCell(Text(product.cost.toString())), + DataCell(Text(product.quantity.toString())), + ] + ); + }).toList(); + } } diff --git a/pubspec.lock b/pubspec.lock index d0cd4fbae..31672d56f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,6 +15,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.1" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" args: dependency: transitive description: @@ -28,7 +35,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.3.0" + version: "2.4.0" boolean_selector: dependency: transitive description: @@ -105,7 +112,7 @@ packages: name: cached_network_image url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "2.0.0-rc.1" charcode: dependency: transitive description: @@ -155,13 +162,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.3+1" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.1+1" + version: "2.1.3" csslib: dependency: transitive description: @@ -189,7 +203,7 @@ packages: name: file url: "https://pub.dartlang.org" source: hosted - version: "5.0.8+1" + version: "5.1.0" firebase_auth: dependency: "direct main" description: @@ -341,6 +355,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.3" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" image_picker: dependency: "direct main" description: @@ -361,7 +382,7 @@ packages: name: intl url: "https://pub.dartlang.org" source: hosted - version: "0.15.8" + version: "0.16.0" io: dependency: transitive description: @@ -417,7 +438,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.5" + version: "0.12.6" memoize: dependency: "direct main" description: @@ -431,7 +452,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.7" + version: "1.1.8" mime: dependency: transitive description: @@ -509,6 +530,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0+1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" platform: dependency: transitive description: @@ -529,7 +557,7 @@ packages: name: process url: "https://pub.dartlang.org" source: hosted - version: "3.0.11" + version: "3.0.12" pub_semver: dependency: transitive description: @@ -716,21 +744,21 @@ packages: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.6.3" + version: "1.9.4" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.5" + version: "0.2.11" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.2.5" + version: "0.2.15" timeago: dependency: "direct main" description: @@ -787,6 +815,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.8" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" vm_service_client: dependency: transitive description: @@ -807,7 +842,7 @@ packages: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "1.0.15" + version: "1.1.0" webview_flutter: dependency: "direct main" description: @@ -815,6 +850,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.3.15+1" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "3.5.0" yaml: dependency: transitive description: @@ -831,4 +873,4 @@ packages: version: "0.8.0" sdks: dart: ">=2.5.0 <3.0.0" - flutter: ">=1.9.1+hotfix.5 <2.0.0" + flutter: ">=1.10.15-pre.148 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index d36ec07d8..d77459544 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,8 +23,8 @@ dependencies: built_value: ^6.7.1 built_collection: ^4.2.2 memoize: ^2.0.0 - #cached_network_image: ^2.0.0-rc.1 - cached_network_image: any + cached_network_image: ^2.0.0-rc.1 + #cached_network_image: any url_launcher: ^5.1.2 share: ^0.6.2+1 intl: any