diff --git a/lib/ui/app/menu_drawer.dart b/lib/ui/app/menu_drawer.dart index 8e63dc648..272d57cfe 100644 --- a/lib/ui/app/menu_drawer.dart +++ b/lib/ui/app/menu_drawer.dart @@ -36,7 +36,7 @@ import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:invoiceninja_flutter/utils/colors.dart'; -class MenuDrawer extends StatelessWidget { +class MenuDrawer extends StatefulWidget { const MenuDrawer({ Key key, @required this.viewModel, @@ -45,6 +45,26 @@ class MenuDrawer extends StatelessWidget { final MenuDrawerVM viewModel; static const LOGO_WIDTH = 38.0; + @override + _MenuDrawerState createState() => _MenuDrawerState(); +} + +class _MenuDrawerState extends State { + ScrollController _scrollController; + + @override + void initState() { + super.initState(); + + _scrollController = ScrollController(); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final Store store = StoreProvider.of(context); @@ -52,20 +72,21 @@ class MenuDrawer extends StatelessWidget { final enableDarkMode = state.prefState.enableDarkMode; final localization = AppLocalization.of(context); final account = state.account; - final company = viewModel.selectedCompany; + final company = widget.viewModel.selectedCompany; if (company == null) { return Container(); } - Widget _companyLogo(CompanyEntity company) => - company.settings.companyLogo != null && - company.settings.companyLogo.isNotEmpty - ? CachedImage( - width: LOGO_WIDTH, - url: account.defaultUrl + company.settings.companyLogo, - ) - : Image.asset('assets/images/logo.png', width: LOGO_WIDTH); + Widget _companyLogo(CompanyEntity company) => company + .settings.companyLogo != + null && + company.settings.companyLogo.isNotEmpty + ? CachedImage( + width: MenuDrawer.LOGO_WIDTH, + url: account.defaultUrl + company.settings.companyLogo, + ) + : Image.asset('assets/images/logo.png', width: MenuDrawer.LOGO_WIDTH); Widget _companyListItem(CompanyEntity company) { final userCompany = state.userCompanyStates @@ -107,12 +128,12 @@ class MenuDrawer extends StatelessWidget { tooltip: localization.selectCompany, child: SizedBox( height: 48, - width: LOGO_WIDTH, - child: _companyLogo(viewModel.selectedCompany), + width: MenuDrawer.LOGO_WIDTH, + child: _companyLogo(widget.viewModel.selectedCompany), ), color: Theme.of(context).cardColor, itemBuilder: (BuildContext context) => [ - ...viewModel.state.companies + ...widget.viewModel.state.companies .map((company) => PopupMenuItem( child: _companyListItem(company), value: company.id, @@ -144,14 +165,14 @@ class MenuDrawer extends StatelessWidget { ], onSelected: (String companyId) { if (companyId == 'company') { - viewModel.onAddCompany(context); + widget.viewModel.onAddCompany(context); } else if (companyId == 'logout') { - viewModel.onLogoutTap(context); + widget.viewModel.onLogoutTap(context); } else { final company = state.companies.firstWhere((company) => company.id == companyId); final index = state.companies.indexOf(company); - viewModel.onCompanyChanged(context, index, company); + widget.viewModel.onCompanyChanged(context, index, company); } }, ); @@ -159,7 +180,7 @@ class MenuDrawer extends StatelessWidget { final _expandedCompanySelector = state.companies.isEmpty ? SizedBox() : AppDropdownButton( - value: viewModel.selectedCompanyIndex, + value: widget.viewModel.selectedCompanyIndex, items: [ ...state.companies .map((CompanyEntity company) => DropdownMenuItem( @@ -192,13 +213,13 @@ class MenuDrawer extends StatelessWidget { ], onChanged: (dynamic value) { if (value == 'company') { - viewModel.onAddCompany(context); + widget.viewModel.onAddCompany(context); } else if (value == 'logout') { - viewModel.onLogoutTap(context); + widget.viewModel.onLogoutTap(context); } else { final index = int.parse(value); - viewModel.onCompanyChanged( - context, index, state.companies[index]); + widget.viewModel + .onCompanyChanged(context, index, state.companies[index]); } }, ); @@ -228,141 +249,147 @@ class MenuDrawer extends StatelessWidget { : Expanded( child: Container( color: Theme.of(context).cardColor, - child: ListView( - shrinkWrap: true, - children: [ - if (state.account.debugEnabled) - if (state.isMenuCollapsed) - Tooltip( - message: localization.debugModeIsEnabled, - child: ListTile( - onTap: () => launch(kDebugModeUrl), - leading: - Icon(Icons.warning, color: Colors.red), - ), - ) - else - ListTile( - tileColor: Colors.red.shade800, - title: Padding( - padding: const EdgeInsets.only(bottom: 6), - child: IconText( - icon: Icons.warning, - text: localization.debugModeIsEnabled, + child: Scrollbar( + controller: _scrollController, + isAlwaysShown: isDesktop(context), + child: ListView( + controller: _scrollController, + shrinkWrap: true, + children: [ + if (state.account.debugEnabled) + if (state.isMenuCollapsed) + Tooltip( + message: localization.debugModeIsEnabled, + child: ListTile( + onTap: () => launch(kDebugModeUrl), + leading: + Icon(Icons.warning, color: Colors.red), + ), + ) + else + ListTile( + tileColor: Colors.red.shade800, + title: Padding( + padding: const EdgeInsets.only(bottom: 6), + child: IconText( + icon: Icons.warning, + text: localization.debugModeIsEnabled, + style: TextStyle(color: Colors.white), + ), + ), + subtitle: Text( + localization.debugModeIsEnabledHelp, style: TextStyle(color: Colors.white), ), + onTap: () => launch(kDebugModeUrl), ), - subtitle: Text( - localization.debugModeIsEnabledHelp, - style: TextStyle(color: Colors.white), - ), - onTap: () => launch(kDebugModeUrl), - ), - DrawerTile( - company: company, - icon: getEntityIcon(EntityType.dashboard), - title: localization.dashboard, - onTap: () => viewEntitiesByType( - context: context, - entityType: EntityType.dashboard), - onLongPress: () => store.dispatch(ViewDashboard( - navigator: Navigator.of(context), filter: '')), - ), - DrawerTile( - company: company, - entityType: EntityType.client, - icon: getEntityIcon(EntityType.client), - title: localization.clients, - iconTooltip: localization.newClient, - ), - DrawerTile( - company: company, - entityType: EntityType.product, - icon: getEntityIcon(EntityType.product), - title: localization.products, - iconTooltip: localization.newProduct, - ), - DrawerTile( - company: company, - entityType: EntityType.invoice, - icon: getEntityIcon(EntityType.invoice), - title: localization.invoices, - iconTooltip: localization.newInvoice, - ), - DrawerTile( - company: company, - entityType: EntityType.payment, - icon: getEntityIcon(EntityType.payment), - title: localization.payments, - iconTooltip: localization.newPayment, - ), - DrawerTile( - company: company, - entityType: EntityType.recurringInvoice, - icon: getEntityIcon(EntityType.recurringInvoice), - title: localization.recurringInvoices, - iconTooltip: localization.newRecurringInvoice, - ), - DrawerTile( - company: company, - entityType: EntityType.quote, - icon: getEntityIcon(EntityType.quote), - title: localization.quotes, - iconTooltip: localization.newQuote, - ), - DrawerTile( - company: company, - entityType: EntityType.credit, - icon: getEntityIcon(EntityType.credit), - title: localization.credits, - iconTooltip: localization.newCredit, - ), - DrawerTile( - company: company, - entityType: EntityType.project, - icon: getEntityIcon(EntityType.project), - title: localization.projects, - iconTooltip: localization.newProject, - ), - DrawerTile( - company: company, - entityType: EntityType.task, - icon: getEntityIcon(EntityType.task), - title: localization.tasks, - iconTooltip: localization.newTask, - ), - DrawerTile( - company: company, - entityType: EntityType.vendor, - icon: getEntityIcon(EntityType.vendor), - title: localization.vendors, - iconTooltip: localization.newVendor, - ), - DrawerTile( - company: company, - entityType: EntityType.expense, - icon: getEntityIcon(EntityType.expense), - title: localization.expenses, - iconTooltip: localization.newExpense, - ), - // STARTER: menu - do not remove comment - DrawerTile( - company: company, - icon: getEntityIcon(EntityType.reports), - title: localization.reports, - onTap: () => viewEntitiesByType( - context: context, - entityType: EntityType.reports), - ), - DrawerTile( - company: company, - icon: getEntityIcon(EntityType.settings), - title: localization.settings, - onTap: () => viewEntitiesByType( - context: context, - entityType: EntityType.settings), - ), - ], + DrawerTile( + company: company, + icon: getEntityIcon(EntityType.dashboard), + title: localization.dashboard, + onTap: () => viewEntitiesByType( + context: context, + entityType: EntityType.dashboard), + onLongPress: () => store.dispatch(ViewDashboard( + navigator: Navigator.of(context), + filter: '')), + ), + DrawerTile( + company: company, + entityType: EntityType.client, + icon: getEntityIcon(EntityType.client), + title: localization.clients, + iconTooltip: localization.newClient, + ), + DrawerTile( + company: company, + entityType: EntityType.product, + icon: getEntityIcon(EntityType.product), + title: localization.products, + iconTooltip: localization.newProduct, + ), + DrawerTile( + company: company, + entityType: EntityType.invoice, + icon: getEntityIcon(EntityType.invoice), + title: localization.invoices, + iconTooltip: localization.newInvoice, + ), + DrawerTile( + company: company, + entityType: EntityType.payment, + icon: getEntityIcon(EntityType.payment), + title: localization.payments, + iconTooltip: localization.newPayment, + ), + DrawerTile( + company: company, + entityType: EntityType.recurringInvoice, + icon: getEntityIcon(EntityType.recurringInvoice), + title: localization.recurringInvoices, + iconTooltip: localization.newRecurringInvoice, + ), + DrawerTile( + company: company, + entityType: EntityType.quote, + icon: getEntityIcon(EntityType.quote), + title: localization.quotes, + iconTooltip: localization.newQuote, + ), + DrawerTile( + company: company, + entityType: EntityType.credit, + icon: getEntityIcon(EntityType.credit), + title: localization.credits, + iconTooltip: localization.newCredit, + ), + DrawerTile( + company: company, + entityType: EntityType.project, + icon: getEntityIcon(EntityType.project), + title: localization.projects, + iconTooltip: localization.newProject, + ), + DrawerTile( + company: company, + entityType: EntityType.task, + icon: getEntityIcon(EntityType.task), + title: localization.tasks, + iconTooltip: localization.newTask, + ), + DrawerTile( + company: company, + entityType: EntityType.vendor, + icon: getEntityIcon(EntityType.vendor), + title: localization.vendors, + iconTooltip: localization.newVendor, + ), + DrawerTile( + company: company, + entityType: EntityType.expense, + icon: getEntityIcon(EntityType.expense), + title: localization.expenses, + iconTooltip: localization.newExpense, + ), + // STARTER: menu - do not remove comment + DrawerTile( + company: company, + icon: getEntityIcon(EntityType.reports), + title: localization.reports, + onTap: () => viewEntitiesByType( + context: context, + entityType: EntityType.reports), + ), + DrawerTile( + company: company, + icon: getEntityIcon(EntityType.settings), + title: localization.settings, + onTap: () => viewEntitiesByType( + context: context, + entityType: EntityType.settings), + ), + ], + ), ), )), SizedBox( diff --git a/lib/ui/app/tables/entity_list.dart b/lib/ui/app/tables/entity_list.dart index 54db8914d..199a31f3d 100644 --- a/lib/ui/app/tables/entity_list.dart +++ b/lib/ui/app/tables/entity_list.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:draggable_scrollbar/draggable_scrollbar.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart' hide DataRow, DataCell, DataColumn; import 'package:flutter_redux/flutter_redux.dart'; @@ -157,7 +156,29 @@ class _EntityListState extends State { fit: FlexFit.loose, child: entityList.isEmpty ? HelpText(AppLocalization.of(context).noRecordsFound) - : DraggableScrollbar.semicircle( + : Scrollbar( + controller: _scrollController, + isAlwaysShown: isDesktop(context), + child: ListView.separated( + padding: const EdgeInsets.symmetric(vertical: 25), + controller: _scrollController, + separatorBuilder: (context, index) => + (index == 0 || index == entityList.length) + ? SizedBox() + : ListDivider(), + itemCount: entityList.length + 2, + itemBuilder: (BuildContext context, index) { + if (index == 0 || index == entityList.length + 1) { + return Container( + color: Theme.of(context).cardColor, + height: 25, + ); + } else { + return widget.itemBuilder(context, index - 1); + } + }, + ), + ) /*DraggableScrollbar.semicircle( backgroundColor: Theme.of(context).backgroundColor, scrollbarTimeToFade: Duration(seconds: 1), controller: _scrollController, @@ -180,7 +201,8 @@ class _EntityListState extends State { } }, ), - ), + )*/ + , ), ], ); diff --git a/lib/ui/dashboard/dashboard_panels.dart b/lib/ui/dashboard/dashboard_panels.dart index 49c8e4b14..038cf3574 100644 --- a/lib/ui/dashboard/dashboard_panels.dart +++ b/lib/ui/dashboard/dashboard_panels.dart @@ -1,7 +1,6 @@ import 'dart:math'; import 'package:charts_common/common.dart'; import 'package:charts_flutter/flutter.dart' as charts; -import 'package:draggable_scrollbar/draggable_scrollbar.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:invoiceninja_flutter/constants.dart'; @@ -402,10 +401,9 @@ class DashboardPanels extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.only(top: 74), - child: DraggableScrollbar.semicircle( - backgroundColor: Theme.of(context).backgroundColor, - scrollbarTimeToFade: Duration(seconds: 1), + child: Scrollbar( controller: scrollController, + isAlwaysShown: isDesktop(context), child: ListView( controller: scrollController, children: [ diff --git a/lib/ui/invoice/edit/invoice_edit_items.dart b/lib/ui/invoice/edit/invoice_edit_items.dart index 78870d581..d169ec133 100644 --- a/lib/ui/invoice/edit/invoice_edit_items.dart +++ b/lib/ui/invoice/edit/invoice_edit_items.dart @@ -1,4 +1,3 @@ -import 'package:draggable_scrollbar/draggable_scrollbar.dart'; import 'package:invoiceninja_flutter/ui/app/forms/custom_field.dart'; import 'package:invoiceninja_flutter/ui/app/forms/decorated_form_field.dart'; import 'package:invoiceninja_flutter/ui/app/help_text.dart'; @@ -12,6 +11,7 @@ import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:flutter/material.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; +import 'package:invoiceninja_flutter/utils/platforms.dart'; class InvoiceEditItems extends StatefulWidget { const InvoiceEditItems({ @@ -83,10 +83,8 @@ class _InvoiceEditItemsState extends State { return HelpText(localization.clickPlusToAddItem); } - return DraggableScrollbar.semicircle( - backgroundColor: Theme.of(context).backgroundColor, - scrollbarTimeToFade: Duration(seconds: 1), - controller: _scrollController, + return Scrollbar( + isAlwaysShown: isDesktop(context), child: ListView( controller: _scrollController, children: [ diff --git a/lib/ui/settings/settings_list.dart b/lib/ui/settings/settings_list.dart index 2e1d1b81a..507a0e6bb 100644 --- a/lib/ui/settings/settings_list.dart +++ b/lib/ui/settings/settings_list.dart @@ -1,4 +1,3 @@ -import 'package:draggable_scrollbar/draggable_scrollbar.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:invoiceninja_flutter/constants.dart'; @@ -68,10 +67,8 @@ class _SettingsListState extends State { filter: settingsUIState.filter, ); - return DraggableScrollbar.semicircle( - backgroundColor: Theme.of(context).backgroundColor, - scrollbarTimeToFade: Duration(seconds: 1), - controller: _scrollController, + return Scrollbar( + isAlwaysShown: isDesktop(context), child: ListView( controller: _scrollController, children: [ diff --git a/pubspec.foss.yaml b/pubspec.foss.yaml index 94bf6f9ca..8d2dbcfe6 100644 --- a/pubspec.foss.yaml +++ b/pubspec.foss.yaml @@ -60,7 +60,6 @@ dependencies: contacts_service: ^0.4.6 extended_image: 1.3.1-dev #TODO remove file_picker: ^2.1.1 - draggable_scrollbar: ^0.0.4 dependency_overrides: # https://github.com/flutter/flutter/issues/70433#issuecomment-727154345 diff --git a/pubspec.lock b/pubspec.lock index 9cf6c13ab..6c6fa03db 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -232,13 +232,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" - draggable_scrollbar: - dependency: "direct main" - description: - name: draggable_scrollbar - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.4" extended_image: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2bbfb5e2f..86353c0a9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,7 +74,6 @@ dependencies: contacts_service: ^0.4.6 extended_image: 1.3.1-dev #TODO remove file_picker: ^2.1.1 - draggable_scrollbar: ^0.0.4 dependency_overrides: # https://github.com/flutter/flutter/issues/70433#issuecomment-727154345