diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 85d87c3ca..94cb007f0 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -61,6 +61,8 @@ PODS: - TOCropViewController (~> 2.6.1) - image_picker_ios (0.0.1): - Flutter + - in_app_purchase_storekit (0.0.1): + - Flutter - in_app_review (0.2.0): - Flutter - local_auth (0.0.1): @@ -108,6 +110,7 @@ DEPENDENCIES: - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`) - image_cropper (from `.symlinks/plugins/image_cropper/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - local_auth (from `.symlinks/plugins/local_auth/ios`) - package_info (from `.symlinks/plugins/package_info/ios`) @@ -150,6 +153,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/image_cropper/ios" image_picker_ios: :path: ".symlinks/plugins/image_picker_ios/ios" + in_app_purchase_storekit: + :path: ".symlinks/plugins/in_app_purchase_storekit/ios" in_app_review: :path: ".symlinks/plugins/in_app_review/ios" local_auth: @@ -193,6 +198,7 @@ SPEC CHECKSUMS: GTMSessionFetcher: 5595ec75acf5be50814f81e9189490412bad82ba image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98 image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb + in_app_purchase_storekit: d7fcf4646136ec258e237872755da8ea6c1b6096 in_app_review: 4a97249f7a2f539a0f294c2d9196b7fe35e49541 local_auth: 1740f55d7af0a2e2a8684ce225fe79d8931e808c package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 diff --git a/lib/ui/app/menu_drawer.dart b/lib/ui/app/menu_drawer.dart index ee19d005c..e6affa772 100644 --- a/lib/ui/app/menu_drawer.dart +++ b/lib/ui/app/menu_drawer.dart @@ -11,6 +11,7 @@ import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_styled_toast/flutter_styled_toast.dart'; import 'package:invoiceninja_flutter/redux/auth/auth_actions.dart'; import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart'; +import 'package:invoiceninja_flutter/ui/app/upgrade_dialog.dart'; import 'package:invoiceninja_flutter/utils/app_review.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; @@ -383,7 +384,7 @@ class MenuDrawer extends StatelessWidget { }, ), ), - if (state.userCompany.isOwner && + if (true || state.userCompany.isOwner && state.isHosted && !isPaidAccount(context) && !isApple() && @@ -397,15 +398,14 @@ class MenuDrawer extends StatelessWidget { dense: true, tileColor: Colors.green, leading: Padding( - padding: const EdgeInsets.only(left: 9), + padding: const EdgeInsets.only(left: 6), child: Icon( Icons.arrow_circle_up, size: 22, color: Colors.white, ), ), - contentPadding: - const EdgeInsets.only(left: 12), + contentPadding: const EdgeInsets.only(left: 20), title: state.isMenuCollapsed ? SizedBox() : Text( @@ -419,11 +419,16 @@ class MenuDrawer extends StatelessWidget { ), ), onTap: () { + + showDialog(context: context, builder: (BuildContext context) => UpgradeDialog()); + + /* store.dispatch(ViewSettings( clearFilter: true, company: company, user: state.user, section: kSettingsAccountManagement)); + */ }, ), ), diff --git a/lib/ui/app/upgrade_dialog.dart b/lib/ui/app/upgrade_dialog.dart index 4724d2a20..df116e5c2 100644 --- a/lib/ui/app/upgrade_dialog.dart +++ b/lib/ui/app/upgrade_dialog.dart @@ -13,6 +13,7 @@ import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart'; import 'package:in_app_purchase_storekit/store_kit_wrappers.dart'; import 'package:invoiceninja_flutter/constants.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; +import 'package:invoiceninja_flutter/ui/dashboard/dashboard_chart.dart'; class UpgradeDialog extends StatefulWidget { @override @@ -22,7 +23,6 @@ class UpgradeDialog extends StatefulWidget { class _UpgradeDialogState extends State { final InAppPurchase _inAppPurchase = InAppPurchase.instance; StreamSubscription> _subscription; - List _notFoundIds = []; List _products = []; List _purchases = []; bool _isAvailable = false; @@ -53,7 +53,6 @@ class _UpgradeDialogState extends State { _isAvailable = isAvailable; _products = []; _purchases = []; - _notFoundIds = []; _purchasePending = false; _loading = false; }); @@ -75,7 +74,6 @@ class _UpgradeDialogState extends State { _isAvailable = isAvailable; _products = productDetailResponse.productDetails; _purchases = []; - _notFoundIds = productDetailResponse.notFoundIDs; _purchasePending = false; _loading = false; }); @@ -88,7 +86,6 @@ class _UpgradeDialogState extends State { _isAvailable = isAvailable; _products = productDetailResponse.productDetails; _purchases = []; - _notFoundIds = productDetailResponse.notFoundIDs; _purchasePending = false; _loading = false; }); @@ -98,7 +95,6 @@ class _UpgradeDialogState extends State { setState(() { _isAvailable = isAvailable; _products = productDetailResponse.productDetails; - _notFoundIds = productDetailResponse.notFoundIDs; _purchasePending = false; _loading = false; }); @@ -150,7 +146,7 @@ class _UpgradeDialogState extends State { ); } - return Stack(children: stack); + return AlertDialog(content: Stack(children: stack)); } Card _buildConnectionCheckTile() { @@ -194,13 +190,7 @@ class _UpgradeDialogState extends State { final store = StoreProvider.of(context); final account = store.state.account; - if (_notFoundIds.isNotEmpty) { - productList.add(ListTile( - title: Text('[${_notFoundIds.join(", ")}] not found', - style: TextStyle(color: ThemeData.light().errorColor)), - subtitle: const Text( - 'This app needs special configuration to run. Please see example/README.md for instructions.'))); - } + // This loading previous purchases code is just a demo. Please do not use this as it is. // In your app you should always verify the purchase data using the `verificationData` inside the [PurchaseDetails] object before trusting it. @@ -216,44 +206,61 @@ class _UpgradeDialogState extends State { productList.addAll(_products.map( (ProductDetails productDetails) { final PurchaseDetails previousPurchase = purchases[productDetails.id]; + + String title = productDetails.title; + String description = productDetails.description; + + // TODO remove this code + // Workaround for product in app store with blank values + if (title.isEmpty && productDetails.id == kProductEnterprisePlanMonth_10) { + title = 'Enterprise - Month (6-10)'; + description = 'One month of the Enterprise Plan (10 users)'; + } + return ListTile( title: Text( - productDetails.title, + title ), - subtitle: Text( - productDetails.description, - ), - trailing: previousPurchase != null - ? IconButton( + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + description + ), + previousPurchase != null + ? IconButton( onPressed: () => confirmPriceChange(context), icon: const Icon(Icons.upgrade)) - : TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.green[800], - // TODO(darrenaustin): Migrate to new API once it lands in stable: https://github.com/flutter/flutter/issues/105724 - // ignore: deprecated_member_use - primary: Colors.white, - ), - onPressed: () { - PurchaseParam purchaseParam; - - if (Platform.isAndroid) { - purchaseParam = GooglePlayPurchaseParam( - productDetails: productDetails, - applicationUserName: account.id); - } else { - purchaseParam = PurchaseParam( - productDetails: productDetails, - applicationUserName: account.id, - ); - } - - _inAppPurchase.buyNonConsumable( - purchaseParam: purchaseParam, - ); - }, - child: Text(productDetails.price), + : TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + // TODO(darrenaustin): Migrate to new API once it lands in stable: https://github.com/flutter/flutter/issues/105724 + // ignore: deprecated_member_use + primary: Colors.white, ), + onPressed: () { + PurchaseParam purchaseParam; + + if (Platform.isAndroid) { + purchaseParam = GooglePlayPurchaseParam( + productDetails: productDetails, + applicationUserName: account.id); + } else { + purchaseParam = PurchaseParam( + productDetails: productDetails, + applicationUserName: account.id, + ); + } + + _inAppPurchase.buyNonConsumable( + purchaseParam: purchaseParam, + ); + }, + child: Text(productDetails.price), + ), + SizedBox(height: 20), + ], + ), ); }, ));