Tablet layout

This commit is contained in:
Hillel Coren 2019-08-14 16:39:37 +03:00
parent 6081af2314
commit c6096efb2f
9 changed files with 58 additions and 22 deletions

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:invoiceninja_flutter/constants.dart';
import 'package:invoiceninja_flutter/data/file_storage.dart';
@ -15,8 +16,10 @@ import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
import 'package:invoiceninja_flutter/redux/static/static_state.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/alert_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/main_screen.dart';
import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart';
import 'package:redux/redux.dart';
import 'package:path_provider/path_provider.dart';
@ -421,3 +424,16 @@ void _setLastLoadWasSuccesfull() async {
prefs.setBool('initialized', true);
}
*/
bool hasChanges(Store<AppState> store, dynamic action) {
if (store.state.hasChanges() && !isMobile(action.context) && !action.force) {
showDialog<MessageDialog>(
context: action.context,
builder: (BuildContext context) {
return MessageDialog(AppLocalization.of(context).errorUnsavedChanges);
});
return true;
} else {
return false;
}
}

View File

@ -12,23 +12,29 @@ import 'package:invoiceninja_flutter/utils/completers.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
class ViewClientList implements PersistUI {
ViewClientList(this.context);
ViewClientList({@required this.context, this.force = false});
final BuildContext context;
final bool force;
}
class ViewClient implements PersistUI {
ViewClient({this.clientId, this.context});
ViewClient({
@required this.clientId,
@required this.context,
this.force = false,
});
final int clientId;
final BuildContext context;
final bool force;
}
class EditClient implements PersistUI {
EditClient(
{this.client,
{@required this.client,
@required this.context,
this.contact,
this.context,
this.completer,
this.trackRoute = true});

View File

@ -1,13 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/app/app_middleware.dart';
import 'package:invoiceninja_flutter/redux/product/product_actions.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/alert_dialog.dart';
import 'package:invoiceninja_flutter/ui/client/client_screen.dart';
import 'package:invoiceninja_flutter/ui/client/edit/client_edit_vm.dart';
import 'package:invoiceninja_flutter/ui/client/view/client_view_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart';
import 'package:redux/redux.dart';
import 'package:invoiceninja_flutter/redux/client/client_actions.dart';
@ -42,13 +41,17 @@ List<Middleware<AppState>> createStoreClientsMiddleware([
Middleware<AppState> _editClient() {
return (Store<AppState> store, dynamic action, NextDispatcher next) async {
if (hasChanges(store, action)) {
return;
}
next(action);
if (action.trackRoute) {
store.dispatch(UpdateCurrentRoute(ClientEditScreen.route));
}
if (action.context != null && isMobile(action.context)) {
if (isMobile(action.context)) {
final client =
await Navigator.of(action.context).pushNamed(ClientEditScreen.route);
@ -61,17 +64,12 @@ Middleware<AppState> _editClient() {
Middleware<AppState> _viewClient() {
return (Store<AppState> store, dynamic action, NextDispatcher next) async {
next(action);
if (store.state.hasChanges() && !isMobile(action.context)) {
showDialog<AlertDialog>(
context: action.context,
builder: (BuildContext context) {
return MessageDialog(AppLocalization.of(context).errorUnsavedChanges);
});
if (hasChanges(store, action)) {
return;
}
next(action);
store.dispatch(UpdateCurrentRoute(ClientViewScreen.route));
if (isMobile(action.context)) {
@ -82,15 +80,15 @@ Middleware<AppState> _viewClient() {
Middleware<AppState> _viewClientList() {
return (Store<AppState> store, dynamic action, NextDispatcher next) {
next(action);
if (store.state.hasChanges()) {
if (hasChanges(store, action)) {
return;
}
next(action);
store.dispatch(UpdateCurrentRoute(ClientScreen.route));
if (action.context != null && isMobile(action.context)) {
if (isMobile(action.context)) {
Navigator.of(action.context).pushNamedAndRemoveUntil(
ClientScreen.route, (Route<dynamic> route) => false);
}

View File

@ -42,6 +42,8 @@ final editingReducer = combineReducers<ClientEntity>([
TypedReducer<ClientEntity, AddContact>(_addContact),
TypedReducer<ClientEntity, DeleteContact>(_removeContact),
TypedReducer<ClientEntity, UpdateContact>(_updateContact),
TypedReducer<ClientEntity, ViewClient>(_clearEditing),
TypedReducer<ClientEntity, ViewClientList>(_clearEditing),
TypedReducer<ClientEntity, SelectCompany>(_clearEditing),
]);

View File

@ -3,7 +3,6 @@ import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_actions.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/alert_dialog.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
import 'package:invoiceninja_flutter/ui/product/edit/product_edit_vm.dart';
import 'package:invoiceninja_flutter/ui/product/product_screen.dart';
import 'package:invoiceninja_flutter/ui/product/view/product_view_vm.dart';

View File

@ -2,7 +2,6 @@ import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:invoiceninja_flutter/data/models/company_model.dart';
import 'package:invoiceninja_flutter/data/models/entities.dart';
import 'package:invoiceninja_flutter/redux/client/client_state.dart';
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_state.dart';
import 'package:invoiceninja_flutter/redux/invoice/invoice_state.dart';

View File

@ -178,7 +178,7 @@ class AppDrawer extends StatelessWidget {
entityType: EntityType.client,
icon: getEntityIcon(EntityType.client),
title: localization.clients,
onTap: () => store.dispatch(ViewClientList(context)),
onTap: () => store.dispatch(ViewClientList(context: context)),
onCreateTap: () {
if (isMobile(context)) {
navigator.pop();

View File

@ -57,6 +57,11 @@ class _ClientEditState extends State<ClientEdit>
title: Text(
client.isNew ? localization.newClient : localization.editClient),
actions: <Widget>[
if (!isMobile(context))
FlatButton(
child: Text(localization.cancel),
onPressed: () => viewModel.onCancelPressed(context),
),
ActionIconButton(
icon: Icons.cloud_upload,
tooltip: localization.save,

View File

@ -48,6 +48,7 @@ class ClientEditVM {
@required this.onChanged,
@required this.onSavePressed,
@required this.onBackPressed,
@required this.onCancelPressed,
@required this.staticState,
@required this.copyBillingAddress,
@required this.copyShippingAddress,
@ -87,6 +88,15 @@ class ClientEditVM {
..state = client.shippingState
..postalCode = client.shippingPostalCode
..countryId = client.shippingCountryId))),
onCancelPressed: (BuildContext context) {
store.dispatch(EditClient(client: ClientEntity(), context: context));
if (client.isNew) {
store.dispatch(ViewClientList(context: context, force: true));
} else {
store.dispatch(
ViewClient(context: context, clientId: client.id, force: true));
}
},
onSavePressed: (BuildContext context) {
if (!client.hasNameSet) {
showDialog<ErrorDialog>(
@ -138,6 +148,7 @@ class ClientEditVM {
final Function(ClientEntity) onChanged;
final Function(BuildContext) onSavePressed;
final Function onBackPressed;
final Function(BuildContext) onCancelPressed;
final StaticState staticState;
final Function() copyShippingAddress;
final Function() copyBillingAddress;