Add drawer animation

This commit is contained in:
Hillel Coren 2020-05-22 15:39:50 +03:00
parent 26e595755d
commit 6f855ee121
17 changed files with 95 additions and 45 deletions

View File

@ -79,8 +79,8 @@ class LoadStaticSuccess implements PersistStatic {
final StaticDataEntity data;
}
class UserSettingsChanged implements PersistPrefs {
UserSettingsChanged({
class UserPreferencesChanged implements PersistPrefs {
UserPreferencesChanged({
this.layout,
this.sidebar,
this.enableDarkMode,
@ -93,6 +93,8 @@ class UserSettingsChanged implements PersistPrefs {
this.accentColor,
this.menuMode,
this.historyMode,
this.fullHeightFilter,
this.fullWidthEditor,
});
final AppLayout layout;
@ -106,6 +108,8 @@ class UserSettingsChanged implements PersistPrefs {
final bool autoStartTasks;
final bool isPreviewVisible;
final bool addDocumentsToInvoice;
final bool fullWidthEditor;
final bool fullHeightFilter;
final String accentColor;
}
@ -350,7 +354,7 @@ void viewEntityById({
if (!state.prefState.isPreviewVisible &&
state.prefState.moduleLayout == ModuleLayout.table) {
store.dispatch(UserSettingsChanged(isPreviewVisible: true));
store.dispatch(UserPreferencesChanged(isPreviewVisible: true));
}
switch (entityType) {

View File

@ -261,7 +261,7 @@ Middleware<AppState> _createLoadState(
completer.future.then((_) {
final layout = calculateLayout(action.context);
if (store.state.prefState.isNotMobile && layout == AppLayout.mobile) {
store.dispatch(UserSettingsChanged(layout: layout));
store.dispatch(UserPreferencesChanged(layout: layout));
AppBuilder.of(action.context).rebuild();
WidgetsBinding.instance.addPostFrameCallback((duration) {
store.dispatch(

View File

@ -54,10 +54,10 @@ PrefState prefReducer(
}
Reducer<bool> menuVisibleReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((value, action) {
TypedReducer<bool, UserPreferencesChanged>((value, action) {
return action.sidebar == AppSidebar.menu ? !value : value;
}),
TypedReducer<bool, UserSettingsChanged>((value, action) {
TypedReducer<bool, UserPreferencesChanged>((value, action) {
switch (action.menuMode) {
case AppSidebarMode.visible:
return true;
@ -71,10 +71,10 @@ Reducer<bool> menuVisibleReducer = combineReducers([
]);
Reducer<bool> historyVisibleReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((value, action) {
TypedReducer<bool, UserPreferencesChanged>((value, action) {
return action.sidebar == AppSidebar.history ? !value : value;
}),
TypedReducer<bool, UserSettingsChanged>((value, action) {
TypedReducer<bool, UserPreferencesChanged>((value, action) {
return action.historyMode == AppSidebarMode.visible
? true
: action.historyMode == AppSidebarMode.float ? false : value;
@ -96,7 +96,7 @@ Reducer<int> filterClearedAtReducer = combineReducers([
]);
Reducer<AppLayout> layoutReducer = combineReducers([
TypedReducer<AppLayout, UserSettingsChanged>((layout, action) {
TypedReducer<AppLayout, UserPreferencesChanged>((layout, action) {
return action.layout ?? layout;
}),
]);
@ -112,56 +112,56 @@ Reducer<ModuleLayout> moduleLayoutReducer = combineReducers([
]);
Reducer<AppSidebarMode> manuSidebarReducer = combineReducers([
TypedReducer<AppSidebarMode, UserSettingsChanged>((mode, action) {
TypedReducer<AppSidebarMode, UserPreferencesChanged>((mode, action) {
return action.menuMode ?? mode;
}),
]);
Reducer<AppSidebarMode> historySidebarReducer = combineReducers([
TypedReducer<AppSidebarMode, UserSettingsChanged>((mode, action) {
TypedReducer<AppSidebarMode, UserPreferencesChanged>((mode, action) {
return action.historyMode ?? mode;
}),
]);
Reducer<bool> emailPaymentReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((emailPayment, action) {
TypedReducer<bool, UserPreferencesChanged>((emailPayment, action) {
return action.emailPayment ?? emailPayment;
}),
]);
Reducer<bool> darkModeReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((enableDarkMode, action) {
TypedReducer<bool, UserPreferencesChanged>((enableDarkMode, action) {
return action.enableDarkMode ?? enableDarkMode;
}),
]);
Reducer<bool> longPressReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>(
TypedReducer<bool, UserPreferencesChanged>(
(longPressSelectionIsDefault, action) {
return action.longPressSelectionIsDefault ?? longPressSelectionIsDefault;
}),
]);
Reducer<bool> autoStartTasksReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((autoStartTasks, action) {
TypedReducer<bool, UserPreferencesChanged>((autoStartTasks, action) {
return action.autoStartTasks ?? autoStartTasks;
}),
]);
Reducer<bool> isPreviewVisibleReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((isPreviewVisible, action) {
TypedReducer<bool, UserPreferencesChanged>((isPreviewVisible, action) {
return action.isPreviewVisible ?? isPreviewVisible;
}),
]);
Reducer<bool> addDocumentsToInvoiceReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((addDocumentsToInvoice, action) {
TypedReducer<bool, UserPreferencesChanged>((addDocumentsToInvoice, action) {
return action.addDocumentsToInvoice ?? addDocumentsToInvoice;
}),
]);
Reducer<bool> requireAuthenticationReducer = combineReducers([
TypedReducer<bool, UserSettingsChanged>((requireAuthentication, action) {
TypedReducer<bool, UserPreferencesChanged>((requireAuthentication, action) {
return action.requireAuthentication ?? requireAuthentication;
}),
]);

View File

@ -360,7 +360,7 @@ class _AppBottomBarState extends State<AppBottomBar> {
tooltip: localization.preview,
icon: Icon(Icons.chrome_reader_mode),
onPressed: () {
store.dispatch(UserSettingsChanged(
store.dispatch(UserPreferencesChanged(
isPreviewVisible: !state.prefState.isPreviewVisible));
},
),

View File

@ -67,7 +67,7 @@ class HistoryDrawer extends StatelessWidget {
),
onPressed: () {
store.dispatch(
UserSettingsChanged(sidebar: AppSidebar.history));
UserPreferencesChanged(sidebar: AppSidebar.history));
},
)
],

View File

@ -126,7 +126,7 @@ class ListScaffold extends StatelessWidget {
Scaffold.of(context).openEndDrawer();
} else {
store.dispatch(
UserSettingsChanged(sidebar: AppSidebar.history));
UserPreferencesChanged(sidebar: AppSidebar.history));
}
},
),

View File

@ -260,6 +260,8 @@ class MainScreen extends StatelessWidget {
child: FocusTraversalGroup(
policy: WidgetOrderTraversalPolicy(),
child: ChangeLayoutBanner(
key: ValueKey(prefState.appLayout),
appLayout: prefState.appLayout,
child: Row(children: <Widget>[
if (prefState.showMenu) ...[
MenuDrawerBuilder(),
@ -584,9 +586,14 @@ class _CustomDivider extends StatelessWidget {
}
class ChangeLayoutBanner extends StatefulWidget {
const ChangeLayoutBanner({this.child});
const ChangeLayoutBanner({
Key key,
@required this.child,
@required this.appLayout,
}) : super(key: key);
final Widget child;
final AppLayout appLayout;
@override
_ChangeLayoutBannerState createState() => _ChangeLayoutBannerState();
@ -600,14 +607,14 @@ class _ChangeLayoutBannerState extends State<ChangeLayoutBanner> {
final store = StoreProvider.of<AppState>(context);
final localization = AppLocalization.of(context);
final layout = store.state.prefState.appLayout;
final calculatedLayout = calculateLayout(context, breakOutTablet: true);
String message;
if (!_dismissedChange) {
if (layout == AppLayout.mobile && calculatedLayout == AppLayout.desktop) {
if (widget.appLayout == AppLayout.mobile &&
calculatedLayout == AppLayout.desktop) {
message = localization.changeToDekstopLayout;
} else if (layout == AppLayout.desktop &&
} else if (widget.appLayout == AppLayout.desktop &&
calculatedLayout == AppLayout.mobile) {
message = localization.changeToMobileLayout;
}
@ -635,7 +642,7 @@ class _ChangeLayoutBannerState extends State<ChangeLayoutBanner> {
child: Text(localization.change.toUpperCase()),
onPressed: () {
store.dispatch(
UserSettingsChanged(layout: AppLayout.mobile));
UserPreferencesChanged(layout: AppLayout.mobile));
AppBuilder.of(context).rebuild();
WidgetsBinding.instance.addPostFrameCallback((duration) {
store.dispatch(ViewDashboard(
@ -683,7 +690,7 @@ class _EntityFilter extends StatelessWidget {
color: Theme.of(context).cardColor,
child: AnimatedContainer(
height: show ? kTopBottomBarHeight : 0,
duration: Duration(milliseconds: kDefaultAnimationDuration ),
duration: Duration(milliseconds: kDefaultAnimationDuration),
curve: Curves.easeInOutCubic,
child: Row(
children: filterEntity == null

View File

@ -610,7 +610,7 @@ class SidebarFooter extends StatelessWidget {
icon: Icon(Icons.chevron_left),
onPressed: () {
store.dispatch(
UserSettingsChanged(sidebar: AppSidebar.menu));
UserPreferencesChanged(sidebar: AppSidebar.menu));
},
),
),
@ -696,7 +696,7 @@ class SidebarFooterCollapsed extends StatelessWidget {
icon: Icon(Icons.chevron_right),
tooltip: localization.showMenu,
onPressed: () {
store.dispatch(UserSettingsChanged(sidebar: AppSidebar.menu));
store.dispatch(UserPreferencesChanged(sidebar: AppSidebar.menu));
},
),
);

View File

@ -93,7 +93,7 @@ class LoginVM {
void _handleLogin(BuildContext context) {
final layout = calculateLayout(context);
store.dispatch(UserSettingsChanged(layout: layout));
store.dispatch(UserPreferencesChanged(layout: layout));
AppBuilder.of(context).rebuild();
WidgetsBinding.instance.addPostFrameCallback((duration) {

View File

@ -77,7 +77,7 @@ class _DashboardScreenState extends State<DashboardScreen>
Scaffold.of(context).openEndDrawer();
} else {
store.dispatch(
UserSettingsChanged(sidebar: AppSidebar.history));
UserPreferencesChanged(sidebar: AppSidebar.history));
}
},
),

View File

@ -133,7 +133,7 @@ class ExpenseEditVM {
}
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool(kSharedPrefEmailPayment, value);
store.dispatch(UserSettingsChanged(addDocumentsToInvoice: value));
store.dispatch(UserPreferencesChanged(addDocumentsToInvoice: value));
},
);
}

View File

@ -74,7 +74,7 @@ class PaymentEditVM {
}
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool(kSharedPrefEmailPayment, value);
store.dispatch(UserSettingsChanged(emailPayment: value));
store.dispatch(UserPreferencesChanged(emailPayment: value));
},
onCancelPressed: (BuildContext context) {
createEntity(context: context, entity: PaymentEntity(), force: true);

View File

@ -78,7 +78,7 @@ class PaymentRefundVM {
onEmailChanged: (value) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool(kSharedPrefEmailPayment, value);
store.dispatch(UserSettingsChanged(emailPayment: value));
store.dispatch(UserPreferencesChanged(emailPayment: value));
},
onCancelPressed: (BuildContext context) {
createEntity(context: context, entity: PaymentEntity(), force: true);

View File

@ -119,7 +119,7 @@ class ReportsScreen extends StatelessWidget {
Scaffold.of(context).openEndDrawer();
} else {
store.dispatch(
UserSettingsChanged(sidebar: AppSidebar.history));
UserPreferencesChanged(sidebar: AppSidebar.history));
}
},
),

View File

@ -7,6 +7,7 @@ import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/app/forms/app_dropdown_button.dart';
import 'package:invoiceninja_flutter/ui/settings/device_settings_list_vm.dart';
import 'package:invoiceninja_flutter/utils/icons.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
import 'package:invoiceninja_flutter/utils/platforms.dart';
@ -106,10 +107,30 @@ class _DeviceSettingsState extends State<DeviceSettings> {
],
],
),
FormCard(
children: [
SwitchListTile(
title: Text(localization.fullWidthEditor),
value: prefState.fullWidthEditor,
onChanged: (value) =>
viewModel.onFullWidthEditorChanged(context, value),
secondary: Icon(getEntityIcon(EntityType.invoice)),
activeColor: Theme.of(context).accentColor,
),
SwitchListTile(
title: Text(localization.fullHeightFilter),
value: prefState.fullHeightFilter,
onChanged: (value) =>
viewModel.onFullHeightFilterChanged(context, value),
secondary: Icon(Icons.filter_list),
activeColor: Theme.of(context).accentColor,
),
],
),
FormCard(
children: <Widget>[
SwitchListTile(
title: Text(AppLocalization.of(context).darkMode),
title: Text(localization.darkMode),
value: prefState.enableDarkMode,
onChanged: (value) =>
viewModel.onDarkModeChanged(context, value),
@ -119,8 +140,7 @@ class _DeviceSettingsState extends State<DeviceSettings> {
activeColor: Theme.of(context).accentColor,
),
SwitchListTile(
title: Text(AppLocalization.of(context)
.longPressSelectionIsDefault),
title: Text(localization.longPressSelectionIsDefault),
value: prefState.longPressSelectionIsDefault,
onChanged: (value) =>
viewModel.onLongPressSelectionIsDefault(context, value),

View File

@ -46,6 +46,8 @@ class DeviceSettingsVM {
@required this.authenticationSupported,
@required this.onMenuModeChanged,
@required this.onHistoryModeChanged,
@required this.onFullHeightFilterChanged,
@required this.onFullWidthEditorChanged,
});
static DeviceSettingsVM fromStore(Store<AppState> store) {
@ -76,26 +78,33 @@ class DeviceSettingsVM {
callback: () => store.dispatch(UserLogout(context))),
onRefreshTap: (BuildContext context) => _refreshData(context),
onDarkModeChanged: (BuildContext context, bool value) async {
store.dispatch(UserSettingsChanged(enableDarkMode: value));
store.dispatch(UserPreferencesChanged(enableDarkMode: value));
AppBuilder.of(context).rebuild();
},
onAutoStartTasksChanged: (BuildContext context, bool value) async {
store.dispatch(UserSettingsChanged(autoStartTasks: value));
store.dispatch(UserPreferencesChanged(autoStartTasks: value));
},
onLongPressSelectionIsDefault: (BuildContext context, bool value) async {
store.dispatch(UserSettingsChanged(longPressSelectionIsDefault: value));
store.dispatch(
UserPreferencesChanged(longPressSelectionIsDefault: value));
},
onMenuModeChanged: (context, value) async {
store.dispatch(UserSettingsChanged(menuMode: value));
store.dispatch(UserPreferencesChanged(menuMode: value));
},
onHistoryModeChanged: (context, value) async {
store.dispatch(UserSettingsChanged(historyMode: value));
store.dispatch(UserPreferencesChanged(historyMode: value));
},
onFullHeightFilterChanged: (context, value) async {
store.dispatch(UserPreferencesChanged(fullHeightFilter: value));
},
onFullWidthEditorChanged: (context, value) async {
store.dispatch(UserPreferencesChanged(fullWidthEditor: value));
},
onLayoutChanged: (BuildContext context, AppLayout value) async {
if (store.state.prefState.appLayout == value) {
return;
}
store.dispatch(UserSettingsChanged(layout: value));
store.dispatch(UserPreferencesChanged(layout: value));
AppBuilder.of(context).rebuild();
WidgetsBinding.instance.addPostFrameCallback((duration) {
if (value == AppLayout.mobile) {
@ -119,7 +128,7 @@ class DeviceSettingsVM {
print(e);
}
if (authenticated) {
store.dispatch(UserSettingsChanged(requireAuthentication: value));
store.dispatch(UserPreferencesChanged(requireAuthentication: value));
} else {}
},
//authenticationSupported: LocalAuthentication().canCheckBiometrics,
@ -140,6 +149,8 @@ class DeviceSettingsVM {
final AppState state;
final Function(BuildContext) onLogoutTap;
final Function(BuildContext) onRefreshTap;
final Function(BuildContext, bool) onFullHeightFilterChanged;
final Function(BuildContext, bool) onFullWidthEditorChanged;
final Function(BuildContext, bool) onDarkModeChanged;
final Function(BuildContext, AppLayout) onLayoutChanged;
final Function(BuildContext, AppSidebarMode) onMenuModeChanged;

View File

@ -15,6 +15,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = {
'en': {
// STARTER: lang key - do not remove comment
'full_width_editor': 'Full Width Editor',
'full_height_filter': 'Full Height Filter',
'email_sign_in': 'Sign in with email',
'change': 'Change',
'change_to_mobile_layout': 'Change to the mobile layout?',
@ -36534,6 +36536,12 @@ mixin LocalizationsProvider on LocaleCodeAware {
String get emailSignIn => _localizedValues[localeCode]['email_sign_in'] ?? '';
String get fullWidthEditor =>
_localizedValues[localeCode]['full_width_editor'] ?? '';
String get fullHeightFilter =>
_localizedValues[localeCode]['full_height_filter'] ?? '';
String lookup(String key) {
final lookupKey = toSnakeCase(key);
return _localizedValues[localeCode][lookupKey] ??