mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-29 18:38:36 +08:00
PurchaseScreen: Move to purchasing code to its own widget
All of this is way too complicated
This commit is contained in:
@ -12,84 +12,8 @@ import 'package:gitjournal/settings.dart';
|
|||||||
|
|
||||||
import 'package:purchases_flutter/purchases_flutter.dart';
|
import 'package:purchases_flutter/purchases_flutter.dart';
|
||||||
|
|
||||||
class PurchaseScreen extends StatefulWidget {
|
class PurchaseScreen extends StatelessWidget {
|
||||||
@override
|
final _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
_PurchaseScreenState createState() => _PurchaseScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PurchaseScreenState extends State<PurchaseScreen> {
|
|
||||||
List<Offering> _offerings;
|
|
||||||
Offering _selectedOffering;
|
|
||||||
var _scaffoldKey = GlobalKey<ScaffoldState>();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
initPlatformState();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> initPlatformState() async {
|
|
||||||
await InAppPurchases.confirmProPurchase();
|
|
||||||
if (Settings.instance.proMode) {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
await Purchases.setup(
|
|
||||||
environment['revenueCat'],
|
|
||||||
appUserId: Settings.instance.pseudoId,
|
|
||||||
);
|
|
||||||
|
|
||||||
Offerings offerings;
|
|
||||||
try {
|
|
||||||
offerings = await Purchases.getOfferings();
|
|
||||||
} catch (e) {
|
|
||||||
if (e is PlatformException) {
|
|
||||||
var snackBar = SnackBar(content: Text(e.message));
|
|
||||||
_scaffoldKey.currentState
|
|
||||||
..removeCurrentSnackBar()
|
|
||||||
..showSnackBar(snackBar);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var offeringList = offerings.all.values.toList();
|
|
||||||
offeringList.retainWhere((Offering o) => o.identifier.contains("monthly"));
|
|
||||||
offeringList.sort((Offering a, Offering b) =>
|
|
||||||
a.monthly.product.price.compareTo(b.monthly.product.price));
|
|
||||||
print("Offerings: $offeringList");
|
|
||||||
|
|
||||||
// If the widget was removed from the tree while the asynchronous platform
|
|
||||||
// message was in flight, we want to discard the reply rather than calling
|
|
||||||
// setState to update our non-existent appearance.
|
|
||||||
if (!mounted) return;
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_offerings = offeringList;
|
|
||||||
_selectedOffering = _offerings.isNotEmpty ? _offerings.first : null;
|
|
||||||
|
|
||||||
if (_offerings.length > 1) {
|
|
||||||
_selectedOffering = _offerings[1];
|
|
||||||
} else {
|
|
||||||
var fakePackageJson = {
|
|
||||||
'identifier': 'monthly_fake',
|
|
||||||
'product': {
|
|
||||||
'identifier': 'fake_product',
|
|
||||||
'title': 'Fake Product',
|
|
||||||
'priceString': '0 Fake',
|
|
||||||
'price': 0.0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var fakeOffer = Offering.fromJson(<String, dynamic>{
|
|
||||||
'identifier': 'monthly_fake_offering',
|
|
||||||
'monthly': fakePackageJson,
|
|
||||||
'availablePackages': [fakePackageJson],
|
|
||||||
});
|
|
||||||
|
|
||||||
_offerings = [fakeOffer];
|
|
||||||
_selectedOffering = _offerings[0];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -97,7 +21,7 @@ class _PurchaseScreenState extends State<PurchaseScreen> {
|
|||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
key: _scaffoldKey,
|
key: _scaffoldKey,
|
||||||
appBar: EmptyAppBar(),
|
appBar: EmptyAppBar(),
|
||||||
body: _offerings == null ? const LoadingWidget() : buildBody(context),
|
body: buildBody(context),
|
||||||
),
|
),
|
||||||
onWillPop: _onWillPop,
|
onWillPop: _onWillPop,
|
||||||
);
|
);
|
||||||
@ -150,36 +74,6 @@ class _PurchaseScreenState extends State<PurchaseScreen> {
|
|||||||
|
|
||||||
var titleStyle =
|
var titleStyle =
|
||||||
textTheme.headline3.copyWith(color: textTheme.headline6.color);
|
textTheme.headline3.copyWith(color: textTheme.headline6.color);
|
||||||
var slider = Slider(
|
|
||||||
min: _offerings.first.monthly.product.price,
|
|
||||||
max: _offerings.last.monthly.product.price + 0.50,
|
|
||||||
value: _selectedOffering.monthly.product.price,
|
|
||||||
onChanged: (double val) {
|
|
||||||
int i = -1;
|
|
||||||
for (i = 1; i < _offerings.length; i++) {
|
|
||||||
var prev = _offerings[i - 1].monthly.product;
|
|
||||||
var cur = _offerings[i].monthly.product;
|
|
||||||
|
|
||||||
if (prev.price < val && val <= cur.price) {
|
|
||||||
i--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (val == _offerings.first.monthly.product.price) {
|
|
||||||
i = 0;
|
|
||||||
} else if (val >= _offerings.last.monthly.product.price) {
|
|
||||||
i = _offerings.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i != -1) {
|
|
||||||
setState(() {
|
|
||||||
_selectedOffering = _offerings[i];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
label: _selectedOffering.monthly.product.priceString,
|
|
||||||
divisions: _offerings.length,
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget w = Column(
|
Widget w = Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
@ -189,8 +83,7 @@ class _PurchaseScreenState extends State<PurchaseScreen> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
body,
|
body,
|
||||||
slider,
|
PurchaseWidget(),
|
||||||
PurchaseButton(_selectedOffering?.monthly),
|
|
||||||
],
|
],
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
);
|
);
|
||||||
@ -373,3 +266,130 @@ class _SingleChildScrollViewExpanded extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PurchaseWidget extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_PurchaseWidgetState createState() => _PurchaseWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PurchaseWidgetState extends State<PurchaseWidget> {
|
||||||
|
List<Offering> _offerings;
|
||||||
|
Offering _selectedOffering;
|
||||||
|
var _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
initPlatformState();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> initPlatformState() async {
|
||||||
|
await InAppPurchases.confirmProPurchase();
|
||||||
|
if (Settings.instance.proMode) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
await Purchases.setup(
|
||||||
|
environment['revenueCat'],
|
||||||
|
appUserId: Settings.instance.pseudoId,
|
||||||
|
);
|
||||||
|
|
||||||
|
Offerings offerings;
|
||||||
|
try {
|
||||||
|
offerings = await Purchases.getOfferings();
|
||||||
|
} catch (e) {
|
||||||
|
if (e is PlatformException) {
|
||||||
|
var snackBar = SnackBar(content: Text(e.message));
|
||||||
|
_scaffoldKey.currentState
|
||||||
|
..removeCurrentSnackBar()
|
||||||
|
..showSnackBar(snackBar);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var offeringList = offerings.all.values.toList();
|
||||||
|
offeringList.retainWhere((Offering o) => o.identifier.contains("monthly"));
|
||||||
|
offeringList.sort((Offering a, Offering b) =>
|
||||||
|
a.monthly.product.price.compareTo(b.monthly.product.price));
|
||||||
|
print("Offerings: $offeringList");
|
||||||
|
|
||||||
|
// If the widget was removed from the tree while the asynchronous platform
|
||||||
|
// message was in flight, we want to discard the reply rather than calling
|
||||||
|
// setState to update our non-existent appearance.
|
||||||
|
if (!mounted) return;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_offerings = offeringList;
|
||||||
|
_selectedOffering = _offerings.isNotEmpty ? _offerings.first : null;
|
||||||
|
|
||||||
|
if (_offerings.length > 1) {
|
||||||
|
_selectedOffering = _offerings[1];
|
||||||
|
} else {
|
||||||
|
var fakePackageJson = {
|
||||||
|
'identifier': 'monthly_fake',
|
||||||
|
'product': {
|
||||||
|
'identifier': 'fake_product',
|
||||||
|
'title': 'Fake Product',
|
||||||
|
'priceString': '0 Fake',
|
||||||
|
'price': 0.0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var fakeOffer = Offering.fromJson(<String, dynamic>{
|
||||||
|
'identifier': 'monthly_fake_offering',
|
||||||
|
'monthly': fakePackageJson,
|
||||||
|
'availablePackages': [fakePackageJson],
|
||||||
|
});
|
||||||
|
|
||||||
|
_offerings = [fakeOffer];
|
||||||
|
_selectedOffering = _offerings[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return _offerings == null ? const LoadingWidget() : buildBody(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildBody(BuildContext context) {
|
||||||
|
var slider = Slider(
|
||||||
|
min: _offerings.first.monthly.product.price,
|
||||||
|
max: _offerings.last.monthly.product.price + 0.50,
|
||||||
|
value: _selectedOffering.monthly.product.price,
|
||||||
|
onChanged: (double val) {
|
||||||
|
int i = -1;
|
||||||
|
for (i = 1; i < _offerings.length; i++) {
|
||||||
|
var prev = _offerings[i - 1].monthly.product;
|
||||||
|
var cur = _offerings[i].monthly.product;
|
||||||
|
|
||||||
|
if (prev.price < val && val <= cur.price) {
|
||||||
|
i--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (val == _offerings.first.monthly.product.price) {
|
||||||
|
i = 0;
|
||||||
|
} else if (val >= _offerings.last.monthly.product.price) {
|
||||||
|
i = _offerings.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != -1) {
|
||||||
|
setState(() {
|
||||||
|
_selectedOffering = _offerings[i];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label: _selectedOffering.monthly.product.priceString,
|
||||||
|
divisions: _offerings.length,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
slider,
|
||||||
|
const SizedBox(height: 16.0),
|
||||||
|
PurchaseButton(_selectedOffering?.monthly),
|
||||||
|
],
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user