Resolves #412 Add 'Support app development' option
This commit is contained in:
107
lib/pages/purchase.page.dart
Normal file
107
lib/pages/purchase.page.dart
Normal file
@ -0,0 +1,107 @@
|
||||
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 = {'just_few_bucks', 'flat_white_a_month', 'lunch_a_year', 'lunch_a_month'};
|
||||
final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(_kIds);
|
||||
if (!response.notFoundIDs.isEmpty) {
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildProducts() {
|
||||
List<Widget> productWidgets = [];
|
||||
for (ProductDetails product in _products) {
|
||||
productWidgets.add(
|
||||
ProductPurchase(
|
||||
product: product,
|
||||
onBuy: (product) => _buyProduct(product),
|
||||
purchased: _purchases.any((purchase) { return purchase.productID == product.id;}),)
|
||||
);
|
||||
}
|
||||
return ListView(
|
||||
scrollDirection: Axis.vertical,
|
||||
children: 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) {
|
||||
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: body,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
32
lib/pages/widgets/page_loading_error.dart
Normal file
32
lib/pages/widgets/page_loading_error.dart
Normal file
@ -0,0 +1,32 @@
|
||||
part of '../../main.dart';
|
||||
|
||||
class PageLoadingError extends StatelessWidget {
|
||||
|
||||
final String errorText;
|
||||
|
||||
const PageLoadingError({Key key, this.errorText: "Error"}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40.0, bottom: 20.0),
|
||||
child: Icon(
|
||||
Icons.error,
|
||||
color: Colors.redAccent,
|
||||
size: 48.0
|
||||
)
|
||||
),
|
||||
Text(this.errorText, style: TextStyle(color: Colors.black45))
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
23
lib/pages/widgets/page_loading_indicator.dart
Normal file
23
lib/pages/widgets/page_loading_indicator.dart
Normal file
@ -0,0 +1,23 @@
|
||||
part of '../../main.dart';
|
||||
|
||||
class PageLoadingIndicator extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40.0, bottom: 20.0),
|
||||
child: CircularProgressIndicator()
|
||||
),
|
||||
Text("Loading...", style: TextStyle(color: Colors.black45))
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
68
lib/pages/widgets/product_purchase.widget.dart
Normal file
68
lib/pages/widgets/product_purchase.widget.dart
Normal file
@ -0,0 +1,68 @@
|
||||
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;
|
||||
if (product.id.contains("month")) {
|
||||
period += "month";
|
||||
priceColor = Colors.deepOrangeAccent;
|
||||
} else {
|
||||
period += "year";
|
||||
priceColor = Colors.amber;
|
||||
}
|
||||
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: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16.0
|
||||
),
|
||||
),
|
||||
Container(height: Sizes.rowPadding,),
|
||||
Text(
|
||||
"${product.description}",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 4,
|
||||
softWrap: true,
|
||||
),
|
||||
Container(height: Sizes.rowPadding,),
|
||||
Text("${product.price} $period", style: TextStyle(color: priceColor)),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: RaisedButton(
|
||||
child: Text(this.purchased ? "Bought" : "Buy", style: TextStyle(color: Colors.white)),
|
||||
color: Colors.blue,
|
||||
onPressed: this.purchased ? null : () => this.onBuy(this.product),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user