Added redux logic for Table/List

This commit is contained in:
Gianfranco Gasbarri 2019-11-17 13:03:10 +00:00
parent 5f3501c3de
commit 2359b1b2f6
11 changed files with 136 additions and 28 deletions

View File

@ -91,6 +91,7 @@ Serializers _$serializers = (new Serializers().toBuilder()
..add(LanguageListResponse.serializer)
..add(ListUIState.serializer)
..add(LoginResponse.serializer)
..add(ModuleLayout.serializer)
..add(PaymentEntity.serializer)
..add(PaymentItemResponse.serializer)
..add(PaymentListResponse.serializer)

View File

@ -59,7 +59,7 @@ import 'package:invoiceninja_flutter/ui/company_gateway/view/company_gateway_vie
import 'package:invoiceninja_flutter/redux/company_gateway/company_gateway_middleware.dart';
void main({bool isTesting = false}) async {
//WidgetsFlutterBinding.ensureInitialized();
WidgetsFlutterBinding.ensureInitialized();
final SentryClient _sentry = Config.SENTRY_DNS.isEmpty
? null

View File

@ -36,6 +36,8 @@ class RefreshClient {
final String clientId;
}
class SwitchListTableLayout implements PersistUI, PersistPrefs {}
class ViewMainScreen {
ViewMainScreen(this.context);

View File

@ -217,7 +217,7 @@ Middleware<AppState> _createLoadState(
uiState.currentRoute.isNotEmpty) {
final NavigatorState navigator = Navigator.of(action.context);
final routes = _getRoutes(appState);
if (appState.prefState.layout == AppLayout.mobile) {
if (appState.prefState.appLayout == AppLayout.mobile) {
bool isFirst = true;
routes.forEach((route) {
if (isFirst) {
@ -250,7 +250,7 @@ Middleware<AppState> _createLoadState(
final Completer<Null> completer = Completer<Null>();
completer.future.then((_) {
final layout = calculateLayout(action.context);
if (store.state.prefState.layout == AppLayout.tablet &&
if (store.state.prefState.appLayout == AppLayout.tablet &&
layout == AppLayout.mobile) {
store.dispatch(UserSettingsChanged(layout: layout));
store.dispatch(

View File

@ -27,7 +27,8 @@ PrefState prefReducer(
return state.rebuild((b) => b
..companyPrefs[selectedCompanyIndex] =
companyPrefReducer(state.companyPrefs[selectedCompanyIndex], action)
..layout = layoutReducer(state.layout, action)
..appLayout = layoutReducer(state.appLayout, action)
..moduleLayout = moduleLayoutReducer(state.moduleLayout, action)
..menuSidebarMode = manuSidebarReducer(state.menuSidebarMode, action)
..historySidebarMode =
historySidebarReducer(state.historySidebarMode, action)
@ -92,6 +93,16 @@ Reducer<AppLayout> layoutReducer = combineReducers([
}),
]);
Reducer<ModuleLayout> moduleLayoutReducer = combineReducers([
TypedReducer<ModuleLayout, SwitchListTableLayout>((moduleLayout, action) {
if (moduleLayout == ModuleLayout.list) {
return ModuleLayout.table;
} else {
return ModuleLayout.list;
}
}),
]);
Reducer<AppSidebarMode> manuSidebarReducer = combineReducers([
TypedReducer<AppSidebarMode, UserSettingsChanged>((mode, action) {
return action.menuMode ?? mode;

View File

@ -10,7 +10,8 @@ part 'pref_state.g.dart';
abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
factory PrefState() {
return _$PrefState._(
layout: AppLayout.tablet,
appLayout: AppLayout.tablet,
moduleLayout: ModuleLayout.list,
menuSidebarMode: AppSidebarMode.collapse,
historySidebarMode: AppSidebarMode.visible,
isMenuVisible: false,
@ -30,7 +31,9 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
PrefState._();
AppLayout get layout;
AppLayout get appLayout;
ModuleLayout get moduleLayout;
AppSidebarMode get menuSidebarMode;
@ -59,10 +62,10 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
bool get isMobile => layout == AppLayout.mobile;
bool get isMenuFloated =>
layout == AppLayout.mobile || menuSidebarMode == AppSidebarMode.float;
appLayout == AppLayout.mobile || menuSidebarMode == AppSidebarMode.float;
bool get isHistoryFloated =>
layout == AppLayout.mobile || historySidebarMode == AppSidebarMode.float;
appLayout == AppLayout.mobile || historySidebarMode == AppSidebarMode.float;
bool get showMenu =>
(isMenuVisible && menuSidebarMode == AppSidebarMode.visible) ||
@ -112,6 +115,19 @@ class AppLayout extends EnumClass {
static AppLayout valueOf(String name) => _$valueOf(name);
}
class ModuleLayout extends EnumClass {
const ModuleLayout._(String name) : super(name);
static Serializer<ModuleLayout> get serializer => _$moduleLayoutSerializer;
static const ModuleLayout list = _$list;
static const ModuleLayout table = _$table;
static BuiltSet<ModuleLayout> get values => _$moduleLayoutValues;
static ModuleLayout valueOf(String name) => _$moduleLayoutValueOf(name);
}
class AppSidebar extends EnumClass {
const AppSidebar._(String name) : super(name);

View File

@ -29,6 +29,26 @@ final BuiltSet<AppLayout> _$values = new BuiltSet<AppLayout>(const <AppLayout>[
_$desktop,
]);
const ModuleLayout _$list = const ModuleLayout._('list');
const ModuleLayout _$table = const ModuleLayout._('table');
ModuleLayout _$moduleLayoutValueOf(String name) {
switch (name) {
case 'list':
return _$list;
case 'table':
return _$table;
default:
throw new ArgumentError(name);
}
}
final BuiltSet<ModuleLayout> _$moduleLayoutValues =
new BuiltSet<ModuleLayout>(const <ModuleLayout>[
_$list,
_$table,
]);
const AppSidebar _$menu = const AppSidebar._('menu');
const AppSidebar _$history = const AppSidebar._('history');
@ -77,6 +97,8 @@ Serializer<PrefState> _$prefStateSerializer = new _$PrefStateSerializer();
Serializer<CompanyPrefState> _$companyPrefStateSerializer =
new _$CompanyPrefStateSerializer();
Serializer<AppLayout> _$appLayoutSerializer = new _$AppLayoutSerializer();
Serializer<ModuleLayout> _$moduleLayoutSerializer =
new _$ModuleLayoutSerializer();
Serializer<AppSidebar> _$appSidebarSerializer = new _$AppSidebarSerializer();
Serializer<AppSidebarMode> _$appSidebarModeSerializer =
new _$AppSidebarModeSerializer();
@ -93,9 +115,12 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
Iterable<Object> serialize(Serializers serializers, PrefState object,
{FullType specifiedType = FullType.unspecified}) {
final result = <Object>[
'layout',
serializers.serialize(object.layout,
'appLayout',
serializers.serialize(object.appLayout,
specifiedType: const FullType(AppLayout)),
'moduleLayout',
serializers.serialize(object.moduleLayout,
specifiedType: const FullType(ModuleLayout)),
'menuSidebarMode',
serializers.serialize(object.menuSidebarMode,
specifiedType: const FullType(AppSidebarMode)),
@ -146,10 +171,14 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
iterator.moveNext();
final dynamic value = iterator.current;
switch (key) {
case 'layout':
result.layout = serializers.deserialize(value,
case 'appLayout':
result.appLayout = serializers.deserialize(value,
specifiedType: const FullType(AppLayout)) as AppLayout;
break;
case 'moduleLayout':
result.moduleLayout = serializers.deserialize(value,
specifiedType: const FullType(ModuleLayout)) as ModuleLayout;
break;
case 'menuSidebarMode':
result.menuSidebarMode = serializers.deserialize(value,
specifiedType: const FullType(AppSidebarMode)) as AppSidebarMode;
@ -272,6 +301,23 @@ class _$AppLayoutSerializer implements PrimitiveSerializer<AppLayout> {
AppLayout.valueOf(serialized as String);
}
class _$ModuleLayoutSerializer implements PrimitiveSerializer<ModuleLayout> {
@override
final Iterable<Type> types = const <Type>[ModuleLayout];
@override
final String wireName = 'ModuleLayout';
@override
Object serialize(Serializers serializers, ModuleLayout object,
{FullType specifiedType = FullType.unspecified}) =>
object.name;
@override
ModuleLayout deserialize(Serializers serializers, Object serialized,
{FullType specifiedType = FullType.unspecified}) =>
ModuleLayout.valueOf(serialized as String);
}
class _$AppSidebarSerializer implements PrimitiveSerializer<AppSidebar> {
@override
final Iterable<Type> types = const <Type>[AppSidebar];
@ -363,7 +409,9 @@ class _$HistoryRecordSerializer implements StructuredSerializer<HistoryRecord> {
class _$PrefState extends PrefState {
@override
final AppLayout layout;
final AppLayout appLayout;
@override
final ModuleLayout moduleLayout;
@override
final AppSidebarMode menuSidebarMode;
@override
@ -391,7 +439,8 @@ class _$PrefState extends PrefState {
(new PrefStateBuilder()..update(updates)).build();
_$PrefState._(
{this.layout,
{this.appLayout,
this.moduleLayout,
this.menuSidebarMode,
this.historySidebarMode,
this.isMenuVisible,
@ -404,8 +453,11 @@ class _$PrefState extends PrefState {
this.addDocumentsToInvoice,
this.companyPrefs})
: super._() {
if (layout == null) {
throw new BuiltValueNullFieldError('PrefState', 'layout');
if (appLayout == null) {
throw new BuiltValueNullFieldError('PrefState', 'appLayout');
}
if (moduleLayout == null) {
throw new BuiltValueNullFieldError('PrefState', 'moduleLayout');
}
if (menuSidebarMode == null) {
throw new BuiltValueNullFieldError('PrefState', 'menuSidebarMode');
@ -454,7 +506,8 @@ class _$PrefState extends PrefState {
bool operator ==(Object other) {
if (identical(other, this)) return true;
return other is PrefState &&
layout == other.layout &&
appLayout == other.appLayout &&
moduleLayout == other.moduleLayout &&
menuSidebarMode == other.menuSidebarMode &&
historySidebarMode == other.historySidebarMode &&
isMenuVisible == other.isMenuVisible &&
@ -480,7 +533,9 @@ class _$PrefState extends PrefState {
$jc(
$jc(
$jc(
$jc($jc(0, layout.hashCode),
$jc(
$jc($jc(0, appLayout.hashCode),
moduleLayout.hashCode),
menuSidebarMode.hashCode),
historySidebarMode.hashCode),
isMenuVisible.hashCode),
@ -497,7 +552,8 @@ class _$PrefState extends PrefState {
@override
String toString() {
return (newBuiltValueToStringHelper('PrefState')
..add('layout', layout)
..add('appLayout', appLayout)
..add('moduleLayout', moduleLayout)
..add('menuSidebarMode', menuSidebarMode)
..add('historySidebarMode', historySidebarMode)
..add('isMenuVisible', isMenuVisible)
@ -516,9 +572,14 @@ class _$PrefState extends PrefState {
class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
_$PrefState _$v;
AppLayout _layout;
AppLayout get layout => _$this._layout;
set layout(AppLayout layout) => _$this._layout = layout;
AppLayout _appLayout;
AppLayout get appLayout => _$this._appLayout;
set appLayout(AppLayout appLayout) => _$this._appLayout = appLayout;
ModuleLayout _moduleLayout;
ModuleLayout get moduleLayout => _$this._moduleLayout;
set moduleLayout(ModuleLayout moduleLayout) =>
_$this._moduleLayout = moduleLayout;
AppSidebarMode _menuSidebarMode;
AppSidebarMode get menuSidebarMode => _$this._menuSidebarMode;
@ -579,7 +640,8 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
PrefStateBuilder get _$this {
if (_$v != null) {
_layout = _$v.layout;
_appLayout = _$v.appLayout;
_moduleLayout = _$v.moduleLayout;
_menuSidebarMode = _$v.menuSidebarMode;
_historySidebarMode = _$v.historySidebarMode;
_isMenuVisible = _$v.isMenuVisible;
@ -615,7 +677,8 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
try {
_$result = _$v ??
new _$PrefState._(
layout: layout,
appLayout: appLayout,
moduleLayout: moduleLayout,
menuSidebarMode: menuSidebarMode,
historySidebarMode: historySidebarMode,
isMenuVisible: isMenuVisible,

View File

@ -1,8 +1,11 @@
import 'package:built_collection/built_collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/ui/list_ui_state.dart';
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/redux/ui/ui_state.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/data/models/models.dart';
import 'package:redux/redux.dart';
@ -260,11 +263,20 @@ class _AppBottomBarState extends State<AppBottomBar> {
return StoreBuilder(builder: (BuildContext context, Store<AppState> store) {
final localization = AppLocalization.of(context);
final prefState = store.state.prefState;
final isList = prefState.moduleLayout == ModuleLayout.list;
return BottomAppBar(
shape: CircularNotchedRectangle(),
child: Row(
children: <Widget>[
IconButton(
tooltip: AppLocalization.of(context).switchListTable,
icon: Icon(isList ? Icons.table_chart : Icons.view_list),
onPressed: () {
store.dispatch(SwitchListTableLayout());
},
),
if (widget.sortFields.isNotEmpty)
IconButton(
tooltip: AppLocalization.of(context).sort,

View File

@ -53,7 +53,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
children: <Widget>[
AppDropdownButton<AppLayout>(
labelText: localization.layout,
value: viewModel.state.prefState.layout,
value: viewModel.state.prefState.appLayout,
onChanged: (dynamic value) =>
viewModel.onLayoutChanged(context, value),
items: [
@ -67,7 +67,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
),
],
),
if (state.prefState.layout == AppLayout.tablet) ...[
if (state.prefState.appLayout == AppLayout.tablet) ...[
AppDropdownButton<AppSidebarMode>(
labelText: localization.menuSidebar,
value: state.prefState.menuSidebarMode,

View File

@ -814,7 +814,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
'default_tax_rate_3': 'Default Tax Rate 3',
'email_subject_invoice': 'Email Invoice Subject',
'email_subject_quote': 'Email Quote Subject',
'email_subject_payment': 'Email Payment Subject'
'email_subject_payment': 'Email Payment Subject',
'switch_list_table': 'Switch List Table'
},
'sq': {
'thank_you_for_your_purchase': 'Thank you for your purchase!',
@ -15766,6 +15767,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
String get newPayment => _localizedValues[localeCode]['new_payment'];
String get switchListTable => _localizedValues[localeCode]['switch_list_table'];
String lookup(String key) {
final lookupKey = toSnakeCase(key);
return _localizedValues[localeCode][lookupKey] ??

View File

@ -33,7 +33,7 @@ AppLayout calculateLayout(BuildContext context) {
}
AppLayout getLayout(BuildContext context) =>
StoreProvider.of<AppState>(context).state.prefState.layout ??
StoreProvider.of<AppState>(context).state.prefState.appLayout ??
AppLayout.mobile;
bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile;