From 89f3f314a5d29bce6788d95a761dff79359fbeea Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Thu, 29 Aug 2019 10:38:34 +0300 Subject: [PATCH] IAP --- lib/data/models/company_model.dart | 11 ++++- lib/main.dart | 6 ++- lib/redux/app/app_state.dart | 4 ++ lib/redux/auth/auth_state.dart | 12 +++++ lib/redux/company/company_selectors.dart | 2 +- lib/ui/app/app_drawer.dart | 2 +- lib/utils/platforms.dart | 59 ++++++++---------------- 7 files changed, 51 insertions(+), 45 deletions(-) diff --git a/lib/data/models/company_model.dart b/lib/data/models/company_model.dart index 64f6d5c14..716cd76f7 100644 --- a/lib/data/models/company_model.dart +++ b/lib/data/models/company_model.dart @@ -197,15 +197,18 @@ abstract class CompanyEntity @nullable @BuiltValueField(wireName: 'task_statuses') BuiltList get taskStatuses; + BuiltMap get taskStatusMap; @nullable @BuiltValueField(wireName: 'expense_categories') BuiltList get expenseCategories; + BuiltMap get expenseCategoryMap; @BuiltValueField(wireName: 'users') BuiltList get users; + BuiltMap get userMap; UserEntity get user; @@ -316,9 +319,13 @@ abstract class CompanyEntity } } - bool get isSelfHost => appUrl != kAppUrl; + bool get isSelfHost => + appUrl != null && appUrl.isNotEmpty && appUrl != kAppUrl; - bool get isProPlan => isSelfHost || plan == kPlanPro; + bool get isHosted => !isSelfHost; + + bool get isProPlan => + isSelfHost || plan == kPlanPro; bool get isEnterprisePlan => isProPlan || plan == kPlanEnterprise; diff --git a/lib/main.dart b/lib/main.dart index 80245a29c..e26a2b751 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -113,12 +113,14 @@ void main({bool isTesting = false}) async { runZoned>(() async { runApp(InvoiceNinjaApp(store: store)); }, onError: (dynamic error, dynamic stackTrace) { - _reportError(error, stackTrace); + if (store.state.isHosted) { + _reportError(error, stackTrace); + } }); } FlutterError.onError = (FlutterErrorDetails details) { - if (isInDebugMode) { + if (isInDebugMode || store.state.isSelfHosted) { FlutterError.dumpErrorToConsole(details); } else { Zone.current.handleUncaughtError(details.exception, details.stack); diff --git a/lib/redux/app/app_state.dart b/lib/redux/app/app_state.dart index 2fd842c50..5c308a204 100644 --- a/lib/redux/app/app_state.dart +++ b/lib/redux/app/app_state.dart @@ -264,6 +264,10 @@ abstract class AppState implements Built { } } + bool get isHosted => authState.isHosted ?? false; + + bool get isSelfHosted => !isHosted; + @override String toString() { return 'URL: ${authState.url}'; diff --git a/lib/redux/auth/auth_state.dart b/lib/redux/auth/auth_state.dart index 7c4a787b5..37564f4a6 100644 --- a/lib/redux/auth/auth_state.dart +++ b/lib/redux/auth/auth_state.dart @@ -1,5 +1,6 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; +import 'package:invoiceninja_flutter/constants.dart'; part 'auth_state.g.dart'; @@ -14,18 +15,29 @@ abstract class AuthState implements Built { isInitialized: false, ); } + AuthState._(); String get email; + String get password; + String get url; + String get secret; + bool get isInitialized; + bool get isAuthenticated; @nullable String get error; + bool get isHosted => + isAuthenticated && (url == null || url.isEmpty || url == kAppUrl); + + bool get isSelfHost => isAuthenticated && !isHosted; + //factory AuthState([void updates(AuthStateBuilder b)]) = _$AuthState; static Serializer get serializer => _$authStateSerializer; } diff --git a/lib/redux/company/company_selectors.dart b/lib/redux/company/company_selectors.dart index bbe85a33e..b052a2670 100644 --- a/lib/redux/company/company_selectors.dart +++ b/lib/redux/company/company_selectors.dart @@ -135,7 +135,7 @@ String localeSelector(AppState state) { 'en'; // https://github.com/flutter/flutter/issues/32090 - if (locale == 'mk_MK') { + if (locale == 'mk_MK' || locale == 'sq') { return 'en'; } else { return locale; diff --git a/lib/ui/app/app_drawer.dart b/lib/ui/app/app_drawer.dart index 796e41246..6e9c4805c 100644 --- a/lib/ui/app/app_drawer.dart +++ b/lib/ui/app/app_drawer.dart @@ -482,7 +482,7 @@ class SidebarFooter extends StatelessWidget { icon: Icon(Icons.info_outline), onPressed: () => showAbout(), ), - if (isHosted(context) && !isProAccount(context)) ...[ + if (isHosted(context) && !isPaidAccount(context)) ...[ Spacer(), FlatButton( child: Text(localization.upgrade), diff --git a/lib/utils/platforms.dart b/lib/utils/platforms.dart index 4ca2f1196..3c53f2574 100644 --- a/lib/utils/platforms.dart +++ b/lib/utils/platforms.dart @@ -5,33 +5,24 @@ import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/ui/ui_state.dart'; bool isAndroid(BuildContext context) => - Theme - .of(context) - .platform == TargetPlatform.android; + Theme.of(context).platform == TargetPlatform.android; -String getMapURL(BuildContext context) => - isAndroid(context) - ? 'https://maps.google.com/?q=' - : 'http://maps.apple.com/?address='; +String getMapURL(BuildContext context) => isAndroid(context) + ? 'https://maps.google.com/?q=' + : 'http://maps.apple.com/?address='; -String getLegacyAppURL(BuildContext context) => - isAndroid(context) - ? 'https://play.google.com/store/apps/details?id=com.invoiceninja.invoiceninja' - : 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1220337560&mt=8'; +String getLegacyAppURL(BuildContext context) => isAndroid(context) + ? 'https://play.google.com/store/apps/details?id=com.invoiceninja.invoiceninja' + : 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1220337560&mt=8'; String getPlatform(BuildContext context) => - Theme - .of(context) - .platform == TargetPlatform.iOS ? 'ios' : 'android'; + Theme.of(context).platform == TargetPlatform.iOS ? 'ios' : 'android'; String getAppURL(BuildContext context) => isAndroid(context) ? kGoogleStoreUrl : kAppleStoreUrl; AppLayout calculateLayout(BuildContext context) { - final size = MediaQuery - .of(context) - .size - .shortestSide; + final size = MediaQuery.of(context).size.shortestSide; if (size < kMobileLayoutWidth) { return AppLayout.mobile; } else if (size > kTabletLayoutWidth) { @@ -42,12 +33,8 @@ AppLayout calculateLayout(BuildContext context) { } AppLayout getLayout(BuildContext context) => - StoreProvider - .of(context) - .state - .uiState - .layout ?? - AppLayout.mobile; + StoreProvider.of(context).state.uiState.layout ?? + AppLayout.mobile; bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile; @@ -56,22 +43,16 @@ bool isTablet(BuildContext context) => getLayout(context) == AppLayout.tablet; bool isDesktop(BuildContext context) => getLayout(context) == AppLayout.desktop; bool isDarkMode(BuildContext context) => - StoreProvider - .of(context) - .state - .uiState - .enableDarkMode; + StoreProvider.of(context).state.uiState.enableDarkMode; bool isSelfHosted(BuildContext context) => - StoreProvider - .of(context) - .state.selectedCompany.isSelfHost; + StoreProvider.of(context).state.isSelfHosted; -bool isHosted(BuildContext context) => !isSelfHosted(context); +bool isHosted(BuildContext context) => + StoreProvider.of(context).state.isHosted; -bool isProAccount(BuildContext context) => - isSelfHosted(context) || StoreProvider - .of(context) - .state - .selectedCompany - .isProPlan; +bool isPaidAccount(BuildContext context) { + final company = StoreProvider.of(context).state.selectedCompany; + + return isSelfHosted(context) || company.isProPlan || company.isEnterprisePlan; +}