import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:invoiceninja_flutter/redux/app/app_middleware.dart'; import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart'; import 'package:invoiceninja_flutter/redux/document/document_actions.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; import 'package:redux/redux.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_actions.dart'; import 'package:invoiceninja_flutter/ui/expense/expense_screen.dart'; import 'package:invoiceninja_flutter/ui/expense/edit/expense_edit_vm.dart'; import 'package:invoiceninja_flutter/ui/expense/view/expense_view_vm.dart'; import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/data/repositories/expense_repository.dart'; List> createStoreExpensesMiddleware([ ExpenseRepository repository = const ExpenseRepository(), ]) { final viewExpenseList = _viewExpenseList(); final viewExpense = _viewExpense(); final editExpense = _editExpense(); final loadExpenses = _loadExpenses(repository); final loadExpense = _loadExpense(repository); final saveExpense = _saveExpense(repository); final archiveExpense = _archiveExpense(repository); final deleteExpense = _deleteExpense(repository); final restoreExpense = _restoreExpense(repository); return [ TypedMiddleware(viewExpenseList), TypedMiddleware(viewExpense), TypedMiddleware(editExpense), TypedMiddleware(loadExpenses), TypedMiddleware(loadExpense), TypedMiddleware(saveExpense), TypedMiddleware(archiveExpense), TypedMiddleware(deleteExpense), TypedMiddleware(restoreExpense), ]; } Middleware _editExpense() { return (Store store, dynamic dynamicAction, NextDispatcher next) async { final action = dynamicAction as EditExpense; if (!action.force && hasChanges( store: store, context: action.context, action: action)) { return; } next(action); store.dispatch(UpdateCurrentRoute(ExpenseEditScreen.route)); if (isMobile(action.context)) { final expense = await Navigator.of(action.context).pushNamed(ExpenseEditScreen.route); if (action.completer != null && expense != null) { action.completer.complete(expense); } } }; } Middleware _viewExpense() { return (Store store, dynamic dynamicAction, NextDispatcher next) async { final action = dynamicAction as ViewExpense; if (!action.force && hasChanges( store: store, context: action.context, action: action)) { return; } next(action); store.dispatch(UpdateCurrentRoute(ExpenseViewScreen.route)); if (isMobile(action.context)) { Navigator.of(action.context).pushNamed(ExpenseViewScreen.route); } }; } Middleware _viewExpenseList() { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as ViewExpenseList; if (!action.force && hasChanges( store: store, context: action.context, action: action)) { return; } next(action); if (store.state.expenseState.isStale) { store.dispatch(LoadExpenses()); } store.dispatch(UpdateCurrentRoute(ExpenseScreen.route)); if (isMobile(action.context)) { Navigator.of(action.context).pushNamedAndRemoveUntil( ExpenseScreen.route, (Route route) => false); } }; } Middleware _archiveExpense(ExpenseRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as ArchiveExpenseRequest; final origExpense = store.state.expenseState.map[action.expenseId]; repository .saveData(store.state.credentials, origExpense, EntityAction.archive) .then((ExpenseEntity expense) { store.dispatch(ArchiveExpenseSuccess(expense)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(ArchiveExpenseFailure(origExpense)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _deleteExpense(ExpenseRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as DeleteExpenseRequest; final origExpense = store.state.expenseState.map[action.expenseId]; repository .saveData(store.state.credentials, origExpense, EntityAction.delete) .then((ExpenseEntity expense) { store.dispatch(DeleteExpenseSuccess(expense)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(DeleteExpenseFailure(origExpense)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _restoreExpense(ExpenseRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as RestoreExpenseRequest; final origExpense = store.state.expenseState.map[action.expenseId]; repository .saveData(store.state.credentials, origExpense, EntityAction.restore) .then((ExpenseEntity expense) { store.dispatch(RestoreExpenseSuccess(expense)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(RestoreExpenseFailure(origExpense)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _saveExpense(ExpenseRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as SaveExpenseRequest; repository .saveData(store.state.credentials, action.expense) .then((ExpenseEntity expense) { if (action.expense.isNew) { store.dispatch(AddExpenseSuccess(expense)); } else { store.dispatch(SaveExpenseSuccess(expense)); } action.completer.complete(expense); }).catchError((Object error) { print(error); store.dispatch(SaveExpenseFailure(error)); action.completer.completeError(error); }); next(action); }; } Middleware _loadExpense(ExpenseRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as LoadExpense; final AppState state = store.state; if (state.isLoading) { next(action); return; } store.dispatch(LoadExpenseRequest()); repository .loadItem(store.state.credentials, action.expenseId) .then((expense) { store.dispatch(LoadExpenseSuccess(expense)); if (action.completer != null) { action.completer.complete(null); } }).catchError((Object error) { print(error); store.dispatch(LoadExpenseFailure(error)); if (action.completer != null) { action.completer.completeError(error); } }); next(action); }; } Middleware _loadExpenses(ExpenseRepository repository) { return (Store store, dynamic dynamicAction, NextDispatcher next) { final action = dynamicAction as LoadExpenses; final AppState state = store.state; if (!state.expenseState.isStale && !action.force) { next(action); return; } if (state.isLoading) { next(action); return; } final int updatedAt = (state.expenseState.lastUpdated / 1000).round(); store.dispatch(LoadExpensesRequest()); repository.loadList(store.state.credentials, updatedAt).then((data) { store.dispatch(LoadExpensesSuccess(data)); if (action.completer != null) { action.completer.complete(null); } if (state.selectedCompany.isEnterprisePlan) { if (state.documentState.isStale) { store.dispatch(LoadDocuments()); } } else { if (state.dashboardState.isStale) { store.dispatch(LoadDashboard()); } } }).catchError((Object error) { print(error); store.dispatch(LoadExpensesFailure(error)); if (action.completer != null) { action.completer.completeError(error); } // Support selfhost users with older versions // TODO remove this in v2 if (state.dashboardState.isStale) { store.dispatch(LoadDashboard()); } }); next(action); }; }