Remove in-app purchase

This commit is contained in:
estevez-dev 2020-09-09 15:04:20 +03:00
parent 18c48ad067
commit e633449578
6 changed files with 1 additions and 268 deletions

View File

@ -19,7 +19,6 @@ import 'package:flutter_custom_tabs/flutter_custom_tabs.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:device_info/device_info.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'plugins/dynamic_multi_column_layout.dart';
import 'plugins/spoiler_card.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
@ -103,8 +102,6 @@ part 'entities/vacuum/widgets/vacuum_controls.dart';
part 'entities/vacuum/widgets/vacuum_state_button.dart';
part 'entities/error_entity_widget.dart';
part 'pages/settings/connection_settings.part.dart';
part 'pages/purchase.page.dart';
part 'pages/widgets/product_purchase.widget.dart';
part 'pages/widgets/page_loading_indicator.dart';
part 'pages/widgets/bottom_info_bar.dart';
part 'pages/widgets/page_loading_error.dart';
@ -214,18 +211,11 @@ class HAClientApp extends StatefulWidget {
}
class _HAClientAppState extends State<HAClientApp> {
StreamSubscription<List<PurchaseDetails>> _purchaseUpdateSubscription;
StreamSubscription _themeChangeSubscription;
AppTheme _currentTheme = AppTheme.defaultTheme;
@override
void initState() {
InAppPurchaseConnection.enablePendingPurchases();
final Stream purchaseUpdates =
InAppPurchaseConnection.instance.purchaseUpdatedStream;
_purchaseUpdateSubscription = purchaseUpdates.listen((purchases) {
_handlePurchaseUpdates(purchases);
});
_currentTheme = widget.theme;
_themeChangeSubscription = eventBus.on<ChangeThemeEvent>().listen((event){
setState(() {
@ -235,25 +225,6 @@ class _HAClientAppState extends State<HAClientApp> {
super.initState();
}
void _handlePurchaseUpdates(purchase) {
if (purchase is List<PurchaseDetails>) {
if (purchase[0].status == PurchaseStatus.purchased) {
eventBus.fire(ShowPopupEvent(
popup: Popup(
title: "Thanks a lot!",
body: "Thank you for supporting HA Client development!",
positiveText: "Ok"
)
));
InAppPurchaseConnection.instance.completePurchase(purchase[0]);
} else {
Logger.d("Purchase change handler: ${purchase[0].status}");
}
} else {
Logger.e("Something wrong with purchase handling. Got: $purchase");
}
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
@ -267,7 +238,6 @@ class _HAClientAppState extends State<HAClientApp> {
"/app-settings": (context) => AppSettingsPage(),
"/connection-settings": (context) => AppSettingsPage(showSection: AppSettingsSection.connectionSettings),
"/integration-settings": (context) => AppSettingsPage(showSection: AppSettingsSection.integrationSettings),
"/putchase": (context) => PurchasePage(title: "Support app development"),
"/play-media": (context) => PlayMediaPage(
mediaUrl: "${ModalRoute.of(context).settings.arguments != null ? (ModalRoute.of(context).settings.arguments as Map)['url'] : ''}",
mediaType: "${ModalRoute.of(context).settings.arguments != null ? (ModalRoute.of(context).settings.arguments as Map)['type'] ?? '' : ''}",
@ -314,7 +284,6 @@ class _HAClientAppState extends State<HAClientApp> {
@override
void dispose() {
_purchaseUpdateSubscription.cancel();
_themeChangeSubscription.cancel();
super.dispose();
}

View File

@ -11,53 +11,18 @@ class StartupUserMessagesManager {
StartupUserMessagesManager._internal();
bool _needToshowDonateMessage;
bool _whatsNewMessageShown;
static final _donateMsgTimerKey = "user-msg-donate-timer";
static final _donateMsgShownKey = "user-msg-donate-shpown";
static final _whatsNewMessageKey = "user-msg-whats-new-url";
void checkMessagesToShow() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.reload();
var tInt = prefs.getInt(_donateMsgTimerKey);
if (tInt == null) {
prefs.setInt(_donateMsgTimerKey, DateTime.now().millisecondsSinceEpoch);
_needToshowDonateMessage = false;
} else {
bool wasShown = prefs.getBool(_donateMsgShownKey) ?? false;
_needToshowDonateMessage = (Duration(milliseconds: DateTime.now().millisecondsSinceEpoch - tInt).inDays >= 14) && !wasShown;
}
_whatsNewMessageShown = '${prefs.getString(_whatsNewMessageKey)}' == whatsNewUrl;
if (!_whatsNewMessageShown) {
_showWhatsNewMessage();
} else if (_needToshowDonateMessage) {
_showSupportAppDevelopmentMessage();
}
}
void _showSupportAppDevelopmentMessage() {
eventBus.fire(ShowPopupEvent(
popup: Popup(
title: "Hi!",
body: "As you may have noticed this app contains no ads. Also all app features are available for you for free. I'm not planning to change this in nearest future, but still you can support this application development materially. There is one-time payment available as well as several subscription options. Thanks.",
positiveText: "Show options",
negativeText: "Later",
onPositive: () {
SharedPreferences.getInstance().then((prefs) {
prefs.setBool(_donateMsgShownKey, true);
eventBus.fire(ShowPageEvent(path: "/putchase"));
});
},
onNegative: () {
SharedPreferences.getInstance().then((prefs) {
prefs.setInt(_donateMsgTimerKey, DateTime.now().millisecondsSinceEpoch);
});
}
)
));
}
void _showWhatsNewMessage() {
SharedPreferences.getInstance().then((prefs) {
prefs.setString(_whatsNewMessageKey, whatsNewUrl);

View File

@ -304,15 +304,6 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
},
),
Divider(),
new ListTile(
leading: Icon(MaterialDesignIcons.getIconDataFromIconName("mdi:food")),
title: Text("Support app development"),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).pushNamed('/putchase');
},
),
Divider(),
new ListTile(
leading: Icon(Icons.help),
title: Text("Help"),

View File

@ -1,118 +0,0 @@
part of '../main.dart';
class PurchasePage extends StatefulWidget {
PurchasePage({Key key, this.title}) : super(key: key);
final String title;
@override
_PurchasePageState createState() => new _PurchasePageState();
}
class _PurchasePageState extends State<PurchasePage> {
bool _loaded = false;
String _error = "";
List<ProductDetails> _products;
List<PurchaseDetails> _purchases;
@override
void initState() {
super.initState();
_loadProducts();
}
_loadProducts() async {
final bool available = await InAppPurchaseConnection.instance.isAvailable();
if (!available) {
setState(() {
_error = "Error connecting to store";
});
} else {
const Set<String> _kIds = {'one_time_support','just_few_bucks_per_year', 'app_fan_support_per_year', 'grateful_user_support_per_year'};
final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(_kIds);
if (response.notFoundIDs.isNotEmpty) {
Logger.d("Products not found: ${response.notFoundIDs}");
}
_products = response.productDetails;
_loadPreviousPurchases();
}
}
_loadPreviousPurchases() async {
final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
if (response.error != null) {
setState(() {
_error = "Error loading previous purchases";
});
} else {
_purchases = response.pastPurchases;
for (PurchaseDetails purchase in _purchases) {
Logger.d("Previous purchase: ${purchase.status}");
}
if (_products.isEmpty) {
setState(() {
_error = "No data found in store";
});
} else {
setState(() {
_loaded = true;
});
}
}
}
List<Widget> _buildProducts() {
List<Widget> productWidgets = [
Card(
child: Padding(
padding: EdgeInsets.all(15),
child: Text(
'This will not unlock any additional functionality. This is only a donation to the HA Client open source project.',
style: Theme.of(context).textTheme.headline5,
textAlign: TextAlign.center,
)
)
)
];
for (ProductDetails product in _products) {
productWidgets.add(
ProductPurchase(
product: product,
onBuy: (product) => _buyProduct(product),
purchased: _purchases.any((purchase) { return purchase.productID == product.id;}),)
);
}
return productWidgets;
}
void _buyProduct(ProductDetails product) {
Logger.d("Starting purchase of ${product.id}");
final PurchaseParam purchaseParam = PurchaseParam(productDetails: product);
InAppPurchaseConnection.instance.buyNonConsumable(purchaseParam: purchaseParam);
Navigator.of(context).pop();
}
@override
Widget build(BuildContext context) {
List<Widget> body;
if (!_loaded) {
body = [_error.isEmpty ? PageLoadingIndicator() : PageLoadingError(errorText: _error)];
} else {
body = _buildProducts();
}
return new Scaffold(
appBar: new AppBar(
leading: IconButton(icon: Icon(Icons.arrow_back), onPressed: (){
Navigator.pop(context);
}),
title: new Text(widget.title),
),
body: ListView(
scrollDirection: Axis.vertical,
children: body
),
);
}
}

View File

@ -1,73 +0,0 @@
part of '../../main.dart';
class ProductPurchase extends StatelessWidget {
final ProductDetails product;
final onBuy;
final purchased;
const ProductPurchase({Key key, @required this.product, @required this.onBuy, this.purchased}) : super(key: key);
@override
Widget build(BuildContext context) {
String period = "";
Color priceColor;
String buttonText = '';
String buttonTextInactive = '';
if (product.id.contains("year")) {
period += "once a year";
buttonText = "Subscribe";
buttonTextInactive = "Already";
priceColor = Colors.amber;
} else {
period += "";
buttonText = "Pay";
buttonTextInactive = "Paid";
priceColor = Colors.deepOrangeAccent;
}
return Card(
child: Padding(
padding: EdgeInsets.all(Sizes.leftWidgetPadding),
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(
flex: 5,
child: Padding(
padding: EdgeInsets.only(right: Sizes.rightWidgetPadding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"${product.title}",
style: Theme.of(context).textTheme.body2,
),
Container(height: Sizes.rowPadding,),
Text(
"${product.description}",
overflow: TextOverflow.ellipsis,
maxLines: 4,
softWrap: true,
),
Container(height: Sizes.rowPadding,),
Text("${product.price} $period", style: Theme.of(context).textTheme.body1.copyWith(
color: priceColor
)),
],
)
),
),
Expanded(
flex: 2,
child: RaisedButton(
child: Text(this.purchased ? buttonTextInactive : buttonText, style: Theme.of(context).textTheme.button),
color: Colors.blue,
onPressed: this.purchased ? null : () => this.onBuy(this.product),
),
)
],
),
)
);
}
}

View File

@ -1,7 +1,7 @@
name: hass_client
description: Home Assistant Android Client
version: 1.3.0+1310
version: 1.3.1+1311
environment:
@ -19,7 +19,6 @@ dependencies:
date_format: ^1.0.8
charts_flutter: ^0.8.1
flutter_markdown: ^0.3.3
in_app_purchase: ^0.3.4
flutter_custom_tabs: ^0.6.0
flutter_webview_plugin: ^0.3.10+1
webview_flutter: ^0.3.19+7