diff --git a/lib/redux/app/app_state.dart b/lib/redux/app/app_state.dart index 25696535d..b0e5d0c01 100644 --- a/lib/redux/app/app_state.dart +++ b/lib/redux/app/app_state.dart @@ -714,6 +714,14 @@ abstract class AppState implements Built { bool get isProPlan => true; bool get isEnterprisePlan => true; + bool get isUserConfirmed { + if (isSelfHosted) { + return true; + } + + return (user.emailVerifiedAt ?? 0) > 0; + } + bool get canAddCompany => userCompany.isOwner && companies.length < 10; bool get isMenuCollapsed => diff --git a/lib/ui/app/confirm_email.dart b/lib/ui/app/confirm_email.dart new file mode 100644 index 000000000..2f602bab1 --- /dev/null +++ b/lib/ui/app/confirm_email.dart @@ -0,0 +1,54 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:invoiceninja_flutter/constants.dart'; +import 'package:invoiceninja_flutter/ui/app/buttons/elevated_button.dart'; +import 'package:invoiceninja_flutter/ui/app/confirm_email_vm.dart'; +import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; +import 'package:invoiceninja_flutter/utils/localization.dart'; + +class ConfirmEmail extends StatelessWidget { + const ConfirmEmail({ + Key key, + @required this.viewModel, + }) : super(key: key); + + final ConfirmEmailVM viewModel; + + @override + Widget build(BuildContext context) { + final localization = AppLocalization.of(context); + final state = viewModel.state; + + return Material( + color: Theme.of(context).cardColor, + child: state.isLoading + ? LoadingIndicator() + : Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + localization.confirmYourEmailAddress, + style: Theme.of(context).textTheme.headline6, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: viewModel.onResendPressed, + child: Text(localization.resendEmail), + ), + SizedBox( + width: kTableColumnGap, + ), + ElevatedButton( + onPressed: viewModel.onRefreshPressed, + child: Text(localization.refreshData), + ), + ], + ) + ], + ), + ); + } +} diff --git a/lib/ui/app/confirm_email_vm.dart b/lib/ui/app/confirm_email_vm.dart new file mode 100644 index 000000000..c6ee3c4a0 --- /dev/null +++ b/lib/ui/app/confirm_email_vm.dart @@ -0,0 +1,47 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; +import 'package:invoiceninja_flutter/ui/app/confirm_email.dart'; +import 'package:redux/redux.dart'; +import 'package:invoiceninja_flutter/redux/app/app_state.dart'; + +class ConfirmEmailBuilder extends StatelessWidget { + const ConfirmEmailBuilder({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return StoreConnector( + converter: ConfirmEmailVM.fromStore, + builder: (context, viewModel) { + return ConfirmEmail(viewModel: viewModel); + }, + ); + } +} + +class ConfirmEmailVM { + ConfirmEmailVM({ + this.state, + this.onRefreshPressed, + this.onResendPressed, + }); + + final AppState state; + final Function onResendPressed; + final Function onRefreshPressed; + + static ConfirmEmailVM fromStore(Store store) { + final AppState state = store.state; + + return ConfirmEmailVM( + state: state, + onRefreshPressed: () { + store.dispatch(RefreshData()); + }, + onResendPressed: () { + // + }, + ); + } +} diff --git a/lib/ui/app/main_screen.dart b/lib/ui/app/main_screen.dart index 83a1e316a..53c0f90f1 100644 --- a/lib/ui/app/main_screen.dart +++ b/lib/ui/app/main_screen.dart @@ -12,6 +12,7 @@ import 'package:invoiceninja_flutter/redux/ui/pref_state.dart'; import 'package:invoiceninja_flutter/ui/app/app_shortcuts.dart'; import 'package:invoiceninja_flutter/ui/app/blank_screen.dart'; import 'package:invoiceninja_flutter/ui/app/change_layout_banner.dart'; +import 'package:invoiceninja_flutter/ui/app/confirm_email_vm.dart'; import 'package:invoiceninja_flutter/ui/app/entity_top_filter.dart'; import 'package:invoiceninja_flutter/ui/app/history_drawer_vm.dart'; import 'package:invoiceninja_flutter/ui/app/loading_indicator.dart'; @@ -79,6 +80,8 @@ class MainScreen extends StatelessWidget { child: LoadingIndicator(), color: Theme.of(context).cardColor, ); + } else if (!state.isUserConfirmed) { + return ConfirmEmailBuilder(); } bool editingFilterEntity = false; diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 18f7325f1..1ae89ad87 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -15,6 +15,8 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'resend_email': 'Resend Email', + 'confirm_your_email_address': 'Please confirm your email address', 'refunded_payment': 'Successfully refunded payment', 'partially_unapplied': 'Partially Unapplied', 'select_a_gmail_user': 'Please select a user authenticated with Gmail', @@ -51595,7 +51597,8 @@ mixin LocalizationsProvider on LocaleCodeAware { String get uploadFile => _localizedValues[localeCode]['upload_file'] ?? ''; - String get requiredFilesMissing => _localizedValues[localeCode]['required_files_missing'] ?? ''; + String get requiredFilesMissing => + _localizedValues[localeCode]['required_files_missing'] ?? ''; String get download => _localizedValues[localeCode]['download'] ?? ''; @@ -54425,6 +54428,11 @@ mixin LocalizationsProvider on LocaleCodeAware { String get refundedPayment => _localizedValues[localeCode]['refunded_payment'] ?? ''; + String get confirmYourEmailAddress => + _localizedValues[localeCode]['confirm_your_email_address'] ?? ''; + + String get resendEmail => _localizedValues[localeCode]['resend_email'] ?? ''; + String lookup(String key) { final lookupKey = toSnakeCase(key);