move common subscription widget in util

This commit is contained in:
Neeraj Gupta 2021-08-21 02:01:12 +05:30
parent 43f1ade544
commit 05e15bbf90
3 changed files with 120 additions and 131 deletions

View file

@ -17,6 +17,7 @@ import 'package:photos/ui/common/dialogs.dart';
import 'package:photos/ui/loading_widget.dart'; import 'package:photos/ui/loading_widget.dart';
import 'package:photos/ui/payment/payment_web_page.dart'; import 'package:photos/ui/payment/payment_web_page.dart';
import 'package:photos/ui/payment/skip_subscription_widget.dart'; import 'package:photos/ui/payment/skip_subscription_widget.dart';
import 'package:photos/ui/payment/subscription_common_widgets.dart';
import 'package:photos/ui/payment/subscription_plan_widget.dart'; import 'package:photos/ui/payment/subscription_plan_widget.dart';
import 'package:photos/ui/progress_dialog.dart'; import 'package:photos/ui/progress_dialog.dart';
import 'package:photos/utils/data_util.dart'; import 'package:photos/utils/data_util.dart';
@ -54,14 +55,11 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
bool _hasLoadedData = false; bool _hasLoadedData = false;
bool _isActiveStripeSubscriber; bool _isActiveStripeSubscriber;
// based on this flag, we would show ente payment page with stripe plans
bool _isIndependentApk;
bool _showYearlyPlan = false; bool _showYearlyPlan = false;
@override @override
void initState() { void initState() {
_billingService.setIsOnSubscriptionPage(true); _billingService.setIsOnSubscriptionPage(true);
_isIndependentApk = UpdateService.instance.isIndependentFlavor();
_fetchSub(); _fetchSub();
_dialog = createProgressDialog(context, "please wait..."); _dialog = createProgressDialog(context, "please wait...");
super.initState(); super.initState();
@ -119,10 +117,9 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
} }
bool _showStripePlans() { bool _showStripePlans() {
return _isActiveStripeSubscriber || _isIndependentApk; return _isActiveStripeSubscriber;
} }
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
@ -148,76 +145,28 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
Widget _buildPlans() { Widget _buildPlans() {
final widgets = <Widget>[]; final widgets = <Widget>[];
if (widget.isOnboarding) {
widgets.add(Padding( widgets.add(SubscriptionHeaderWidget(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 24), isOnboarding: widget.isOnboarding,
child: Text( usageFuture: _usageFuture,
"ente preserves your memories, so they're always available to you, even if you lose your device", ));
style: TextStyle(
color: Colors.white54,
height: 1.2,
),
),
));
} else {
widgets.add(
SizedBox(
height: 50,
child: FutureBuilder(
future: _usageFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text("current usage is " + formatBytes(snapshot.data)),
);
} else if (snapshot.hasError) {
return Container();
} else {
return Padding(
padding: const EdgeInsets.all(16.0),
child: loadWidget,
);
}
},
),
),
);
}
widgets.addAll([ widgets.addAll([
Column( Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children:_getStripePlanWidgets() children: _getStripePlanWidgets()),
),
Padding(padding: EdgeInsets.all(8)), Padding(padding: EdgeInsets.all(8)),
]); ]);
widgets.add(_showSubscriptionToggle()); widgets.add(_showSubscriptionToggle());
if (_hasActiveSubscription) { if (_hasActiveSubscription) {
var endDate = getDateAndMonthAndYear( widgets.add(ValidityWidget(currentSubscription: _currentSubscription));
DateTime.fromMicrosecondsSinceEpoch(_currentSubscription.expiryTime));
var message = "renews on $endDate";
if (_currentSubscription.productID == kFreeProductID) {
message = "free plan valid till $endDate";
} else if (_isAutoReviewCancelled) {
message = "your subscription will be cancelled on $endDate";
}
widgets.add(
Text(
message,
style: TextStyle(
color: Colors.white.withOpacity(0.6),
fontSize: 14,
),
),
);
} }
if (_isIndependentApk && if (_hasActiveSubscription &&
_hasActiveSubscription &&
_isActiveStripeSubscriber) { _isActiveStripeSubscriber) {
widgets.add(_stripeSubscriptionToggleButton(_isAutoReviewCancelled)); widgets.add(_stripeRenewOrCancelButton());
} }
if (_hasActiveSubscription && if (_hasActiveSubscription &&
@ -228,12 +177,8 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
child: GestureDetector( child: GestureDetector(
onTap: () async { onTap: () async {
if (_isActiveStripeSubscriber) { if (_isActiveStripeSubscriber) {
if (_isIndependentApk) {
await _launchStripePortal(); await _launchStripePortal();
return; return;
} else {
return;
}
} }
if (Platform.isAndroid) { if (Platform.isAndroid) {
launch( launch(
@ -250,7 +195,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
children: [ children: [
RichText( RichText(
text: TextSpan( text: TextSpan(
text: _isActiveStripeSubscriber && !_isIndependentApk text: _isActiveStripeSubscriber
? "visit web.ente.io to manage your subscription" ? "visit web.ente.io to manage your subscription"
: "payment details", : "payment details",
style: TextStyle( style: TextStyle(
@ -332,43 +277,45 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
await _dialog.hide(); await _dialog.hide();
} }
Widget _stripeSubscriptionToggleButton(bool isCurrentlyCancelled) { Widget _stripeRenewOrCancelButton() {
bool isRenewCancelled =
_currentSubscription.attributes?.isCancelled ?? false;
return TextButton( return TextButton(
child: Text( child: Text(
isCurrentlyCancelled ? "renew subscription" : "cancel subscription", isRenewCancelled ? "renew subscription" : "cancel subscription",
style: TextStyle( style: TextStyle(
color: isCurrentlyCancelled ? Colors.greenAccent : Colors.redAccent, color: isRenewCancelled ? Colors.greenAccent : Colors.redAccent,
), ),
), ),
onPressed: () async { onPressed: () async {
var result = await showChoiceDialog( var result = await showChoiceDialog(
context, context,
isCurrentlyCancelled isRenewCancelled
? 'subscription renewal' ? 'subscription renewal'
: 'subscription cancellation', : 'subscription cancellation',
isCurrentlyCancelled isRenewCancelled
? 'are you sure you want to renew?' ? 'are you sure you want to renew?'
: 'are you sure you want to cancel?', : 'are you sure you want to cancel?',
firstAction: 'yes', firstAction: 'yes',
secondAction: 'no'); secondAction: 'no');
if (result == DialogUserChoice.firstChoice) { if (result == DialogUserChoice.firstChoice) {
toggleStripeSubscription(isCurrentlyCancelled); toggleStripeSubscription(isRenewCancelled);
} }
}, },
); );
} }
Future<void> toggleStripeSubscription(bool isCurrentlyCancelled) async { Future<void> toggleStripeSubscription(bool isRenewCancelled) async {
await _dialog.show(); await _dialog.show();
try { try {
if (isCurrentlyCancelled) { if (isRenewCancelled) {
await _billingService.activateStripeSubscription(); await _billingService.activateStripeSubscription();
} else { } else {
await _billingService.cancelStripeSubscription(); await _billingService.cancelStripeSubscription();
} }
await _fetchSub(); await _fetchSub();
} catch (e) { } catch (e) {
showToast(isCurrentlyCancelled ? 'failed to renew' : 'failed to cancel'); showToast(isRenewCancelled ? 'failed to renew' : 'failed to cancel');
} }
await _dialog.hide(); await _dialog.hide();
} }
@ -393,9 +340,9 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
if (isActive) { if (isActive) {
return; return;
} }
if (_isActiveStripeSubscriber && !_isIndependentApk) { if (!_isActiveStripeSubscriber) {
showErrorDialog(context, "sorry", showErrorDialog(context, "sorry",
"please visit web.ente.io to manage your subscription"); "please cancel your existing subscription from ${_currentSubscription.paymentProvider} first");
return; return;
} }
await _dialog.show(); await _dialog.show();

View file

@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:photos/models/subscription.dart';
import 'package:photos/utils/data_util.dart';
import 'package:photos/ui/loading_widget.dart';
import 'package:photos/utils/date_time_util.dart';
class SubscriptionHeaderWidget extends StatefulWidget {
final bool isOnboarding;
final Future<int> usageFuture;
const SubscriptionHeaderWidget({Key key, this.isOnboarding, this.usageFuture})
: super(key: key);
@override
State<StatefulWidget> createState() {
return _SubscriptionHeaderWidgetState();
}
}
class _SubscriptionHeaderWidgetState extends State<SubscriptionHeaderWidget> {
@override
Widget build(BuildContext context) {
if (widget.isOnboarding) {
return Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 24),
child: Text(
"ente preserves your memories, so they're always available to you, even if you lose your device",
style: TextStyle(
color: Colors.white54,
height: 1.2,
),
),
);
} else {
return SizedBox(
height: 50,
child: FutureBuilder(
future: widget.usageFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text("current usage is " + formatBytes(snapshot.data)),
);
} else if (snapshot.hasError) {
return Container();
} else {
return Padding(
padding: const EdgeInsets.all(16.0),
child: loadWidget,
);
}
},
),
);
}
}
}
class ValidityWidget extends StatelessWidget {
final Subscription currentSubscription;
const ValidityWidget({Key key, this.currentSubscription}) : super(key: key);
@override
Widget build(BuildContext context) {
if (currentSubscription == null) {
return Container();
}
var endDate = getDateAndMonthAndYear(
DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime));
var message = "renews on $endDate";
if (currentSubscription.productID == kFreeProductID) {
message = "free plan valid till $endDate";
} else if (currentSubscription.attributes?.isCancelled ?? false) {
message = "your subscription will be cancelled on $endDate";
}
return Text(
message,
style: TextStyle(
color: Colors.white.withOpacity(0.6),
fontSize: 14,
),
);
}
}

View file

@ -12,13 +12,11 @@ import 'package:photos/models/billing_plan.dart';
import 'package:photos/models/subscription.dart'; import 'package:photos/models/subscription.dart';
import 'package:photos/services/billing_service.dart'; import 'package:photos/services/billing_service.dart';
import 'package:photos/ui/billing_questions_widget.dart'; import 'package:photos/ui/billing_questions_widget.dart';
import 'package:photos/ui/common_elements.dart';
import 'package:photos/ui/loading_widget.dart'; import 'package:photos/ui/loading_widget.dart';
import 'package:photos/ui/payment/skip_subscription_widget.dart'; import 'package:photos/ui/payment/skip_subscription_widget.dart';
import 'package:photos/ui/payment/subscription_common_widgets.dart';
import 'package:photos/ui/payment/subscription_plan_widget.dart'; import 'package:photos/ui/payment/subscription_plan_widget.dart';
import 'package:photos/ui/progress_dialog.dart'; import 'package:photos/ui/progress_dialog.dart';
import 'package:photos/utils/data_util.dart';
import 'package:photos/utils/date_time_util.dart';
import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/dialog_util.dart';
import 'package:photos/utils/toast_util.dart'; import 'package:photos/utils/toast_util.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -67,7 +65,6 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
return productID != null && productID.isNotEmpty; return productID != null && productID.isNotEmpty;
}).toList(); }).toList();
_freePlan = billingPlans.freePlan; _freePlan = billingPlans.freePlan;
_usageFuture = _billingService.fetchUsage(); _usageFuture = _billingService.fetchUsage();
_hasLoadedData = true; _hasLoadedData = true;
setState(() {}); setState(() {});
@ -162,42 +159,10 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
Widget _buildPlans() { Widget _buildPlans() {
final widgets = <Widget>[]; final widgets = <Widget>[];
if (widget.isOnboarding) { widgets.add(SubscriptionHeaderWidget(
widgets.add(Padding( isOnboarding: widget.isOnboarding,
padding: const EdgeInsets.fromLTRB(20, 20, 20, 24), usageFuture: _usageFuture,
child: Text( ));
"ente preserves your memories, so they're always available to you, even if you lose your device",
style: TextStyle(
color: Colors.white54,
height: 1.2,
),
),
));
} else {
widgets.add(
SizedBox(
height: 50,
child: FutureBuilder(
future: _usageFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text("current usage is " + formatBytes(snapshot.data)),
);
} else if (snapshot.hasError) {
return Container();
} else {
return Padding(
padding: const EdgeInsets.all(16.0),
child: loadWidget,
);
}
},
),
),
);
}
widgets.addAll([ widgets.addAll([
Column( Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -209,17 +174,7 @@ class _SubscriptionPageState extends State<SubscriptionPage> {
]); ]);
if (_hasActiveSubscription) { if (_hasActiveSubscription) {
widgets.add( widgets.add(ValidityWidget(currentSubscription: _currentSubscription));
Text(
"valid till " +
getDateAndMonthAndYear(DateTime.fromMicrosecondsSinceEpoch(
_currentSubscription.expiryTime)),
style: TextStyle(
color: Colors.white.withOpacity(0.6),
fontSize: 14,
),
),
);
} }
if (_hasActiveSubscription && if (_hasActiveSubscription &&