Add drawer animation
This commit is contained in:
parent
26e595755d
commit
6f855ee121
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class HistoryDrawer extends StatelessWidget {
|
|||
),
|
||||
onPressed: () {
|
||||
store.dispatch(
|
||||
UserSettingsChanged(sidebar: AppSidebar.history));
|
||||
UserPreferencesChanged(sidebar: AppSidebar.history));
|
||||
},
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class ListScaffold extends StatelessWidget {
|
|||
Scaffold.of(context).openEndDrawer();
|
||||
} else {
|
||||
store.dispatch(
|
||||
UserSettingsChanged(sidebar: AppSidebar.history));
|
||||
UserPreferencesChanged(sidebar: AppSidebar.history));
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class _DashboardScreenState extends State<DashboardScreen>
|
|||
Scaffold.of(context).openEndDrawer();
|
||||
} else {
|
||||
store.dispatch(
|
||||
UserSettingsChanged(sidebar: AppSidebar.history));
|
||||
UserPreferencesChanged(sidebar: AppSidebar.history));
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class ReportsScreen extends StatelessWidget {
|
|||
Scaffold.of(context).openEndDrawer();
|
||||
} else {
|
||||
store.dispatch(
|
||||
UserSettingsChanged(sidebar: AppSidebar.history));
|
||||
UserPreferencesChanged(sidebar: AppSidebar.history));
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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] ??
|
||||
|
|
|
|||
Loading…
Reference in New Issue