Remove unused widgets
This commit is contained in:
parent
c10655e353
commit
33b141916f
5 changed files with 0 additions and 789 deletions
|
@ -1,153 +0,0 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:ente_auth/core/network.dart';
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
import 'package:ente_auth/ui/common/loading_widget.dart';
|
||||
import 'package:expansion_tile_card/expansion_tile_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BillingQuestionsWidget extends StatelessWidget {
|
||||
const BillingQuestionsWidget({
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: Network.instance
|
||||
.getDio()
|
||||
.get("https://static.ente.io/faq.json")
|
||||
.then((response) {
|
||||
final faqItems = <FaqItem>[];
|
||||
for (final item in response.data as List) {
|
||||
faqItems.add(FaqItem.fromMap(item));
|
||||
}
|
||||
return faqItems;
|
||||
}),
|
||||
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final faqs = <Widget>[];
|
||||
faqs.add(
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Text(
|
||||
"FAQs",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
for (final faq in snapshot.data) {
|
||||
faqs.add(FaqWidget(faq: faq));
|
||||
}
|
||||
faqs.add(
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
),
|
||||
);
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: faqs,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const EnteLoadingWidget();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FaqWidget extends StatelessWidget {
|
||||
const FaqWidget({
|
||||
Key key,
|
||||
@required this.faq,
|
||||
}) : super(key: key);
|
||||
|
||||
final FaqItem faq;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: ExpansionTileCard(
|
||||
elevation: 0,
|
||||
title: Text(faq.q),
|
||||
expandedTextColor: Theme.of(context).colorScheme.alternativeColor,
|
||||
baseColor: Theme.of(context).cardColor,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 12,
|
||||
),
|
||||
child: Text(
|
||||
faq.a,
|
||||
style: const TextStyle(
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FaqItem {
|
||||
final String q;
|
||||
final String a;
|
||||
FaqItem({
|
||||
this.q,
|
||||
this.a,
|
||||
});
|
||||
|
||||
FaqItem copyWith({
|
||||
String q,
|
||||
String a,
|
||||
}) {
|
||||
return FaqItem(
|
||||
q: q ?? this.q,
|
||||
a: a ?? this.a,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'q': q,
|
||||
'a': a,
|
||||
};
|
||||
}
|
||||
|
||||
factory FaqItem.fromMap(Map<String, dynamic> map) {
|
||||
if (map == null) return null;
|
||||
|
||||
return FaqItem(
|
||||
q: map['q'],
|
||||
a: map['a'],
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory FaqItem.fromJson(String source) =>
|
||||
FaqItem.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() => 'FaqItem(q: $q, a: $a)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object o) {
|
||||
if (identical(this, o)) return true;
|
||||
|
||||
return o is FaqItem && o.q == q && o.a == a;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => q.hashCode ^ a.hashCode;
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
import 'package:ente_auth/l10n/l10n.dart';
|
||||
import 'package:ente_auth/models/user_details.dart';
|
||||
import 'package:ente_auth/services/user_service.dart';
|
||||
import 'package:ente_auth/ui/common/dialogs.dart';
|
||||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ChildSubscriptionWidget extends StatelessWidget {
|
||||
const ChildSubscriptionWidget({
|
||||
Key key,
|
||||
@required this.userDetails,
|
||||
}) : super(key: key);
|
||||
|
||||
final UserDetails userDetails;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
final String familyAdmin = userDetails.familyData.members
|
||||
.firstWhere((element) => element.isAdmin)
|
||||
.email;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
l10n.inFamilyPlanMessage,
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: "Please contact ",
|
||||
),
|
||||
TextSpan(
|
||||
text: familyAdmin,
|
||||
style:
|
||||
const TextStyle(color: Color.fromRGBO(29, 185, 84, 1)),
|
||||
),
|
||||
const TextSpan(
|
||||
text: " to manage your subscription",
|
||||
),
|
||||
],
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
),
|
||||
Image.asset(
|
||||
"assets/family_plan_leave.png",
|
||||
height: 256,
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 0),
|
||||
),
|
||||
InkWell(
|
||||
child: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 18, horizontal: 100),
|
||||
backgroundColor: Colors.red[500],
|
||||
),
|
||||
child: Text(
|
||||
l10n.leaveFamily,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
color: Colors.white, // same for both themes
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
onPressed: () async => {await _leaveFamilyPlan(context)},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "Please contact ",
|
||||
style: Theme.of(context).textTheme.bodyText2,
|
||||
),
|
||||
TextSpan(
|
||||
text: "support@ente.io",
|
||||
style: Theme.of(context).textTheme.bodyText2.copyWith(
|
||||
color: const Color.fromRGBO(29, 185, 84, 1),
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " for help",
|
||||
style: Theme.of(context).textTheme.bodyText2,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _leaveFamilyPlan(BuildContext context) async {
|
||||
final l10n = context.l10n;
|
||||
final choice = await showChoiceDialog(
|
||||
context,
|
||||
l10n.leaveFamily,
|
||||
l10n.leaveFamilyMessage,
|
||||
firstAction: l10n.no,
|
||||
secondAction: l10n.yes,
|
||||
firstActionColor: Theme.of(context).colorScheme.alternativeColor,
|
||||
secondActionColor: Theme.of(context).colorScheme.onSurface,
|
||||
);
|
||||
if (choice != DialogUserChoice.secondChoice) {
|
||||
return;
|
||||
}
|
||||
final dialog = createProgressDialog(context, l10n.pleaseWaitTitle);
|
||||
await dialog.show();
|
||||
try {
|
||||
await UserService.instance.leaveFamilyPlan();
|
||||
dialog.hide();
|
||||
Navigator.of(context).pop('');
|
||||
} catch (e) {
|
||||
dialog.hide();
|
||||
showGenericErrorDialog(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
import 'package:ente_auth/l10n/l10n.dart';
|
||||
import 'package:ente_auth/models/subscription.dart';
|
||||
import 'package:ente_auth/services/billing_service.dart';
|
||||
import 'package:ente_auth/services/user_service.dart';
|
||||
import 'package:ente_auth/ui/common/loading_widget.dart';
|
||||
import 'package:ente_auth/ui/common/progress_dialog.dart';
|
||||
import 'package:ente_auth/utils/dialog_util.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class PaymentWebPage extends StatefulWidget {
|
||||
final String planId;
|
||||
final String actionType;
|
||||
|
||||
const PaymentWebPage({Key key, this.planId, this.actionType})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _PaymentWebPageState();
|
||||
}
|
||||
|
||||
class _PaymentWebPageState extends State<PaymentWebPage> {
|
||||
final _logger = Logger("PaymentWebPageState");
|
||||
final UserService userService = UserService.instance;
|
||||
final BillingService billingService = BillingService.instance;
|
||||
final String basePaymentUrl = kWebPaymentBaseEndpoint;
|
||||
ProgressDialog _dialog;
|
||||
InAppWebViewController webView;
|
||||
double progress = 0;
|
||||
Uri initPaymentUrl;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
userService.getPaymentToken().then((token) {
|
||||
initPaymentUrl = _getPaymentUrl(token);
|
||||
setState(() {});
|
||||
});
|
||||
if (Platform.isAndroid && kDebugMode) {
|
||||
AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
_dialog = createProgressDialog(context, l10n.pleaseWaitTitle);
|
||||
if (initPaymentUrl == null) {
|
||||
return const EnteLoadingWidget();
|
||||
}
|
||||
return WillPopScope(
|
||||
onWillPop: () async => _buildPageExitWidget(context),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Subscription'),
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
(progress != 1.0)
|
||||
? LinearProgressIndicator(value: progress)
|
||||
: Container(),
|
||||
Expanded(
|
||||
child: InAppWebView(
|
||||
initialUrlRequest: URLRequest(url: initPaymentUrl),
|
||||
onProgressChanged:
|
||||
(InAppWebViewController controller, int progress) {
|
||||
setState(() {
|
||||
this.progress = progress / 100;
|
||||
});
|
||||
},
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
useShouldOverrideUrlLoading: true,
|
||||
),
|
||||
),
|
||||
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
||||
final loadingUri = navigationAction.request.url;
|
||||
_logger.info("Loading url $loadingUri");
|
||||
// handle the payment response
|
||||
if (_isPaymentActionComplete(loadingUri)) {
|
||||
await _handlePaymentResponse(loadingUri);
|
||||
return NavigationActionPolicy.CANCEL;
|
||||
}
|
||||
return NavigationActionPolicy.ALLOW;
|
||||
},
|
||||
onConsoleMessage: (controller, consoleMessage) {
|
||||
_logger.info(consoleMessage);
|
||||
},
|
||||
onLoadStart: (controller, navigationAction) async {
|
||||
if (!_dialog.isShowing()) {
|
||||
await _dialog.show();
|
||||
}
|
||||
},
|
||||
onLoadError: (controller, navigationAction, code, msg) async {
|
||||
if (_dialog.isShowing()) {
|
||||
await _dialog.hide();
|
||||
}
|
||||
},
|
||||
onLoadHttpError:
|
||||
(controller, navigationAction, code, msg) async {
|
||||
_logger.info("onHttpError with $code and msg = $msg");
|
||||
},
|
||||
onLoadStop: (controller, navigationAction) async {
|
||||
_logger.info("loadStart" + navigationAction.toString());
|
||||
if (_dialog.isShowing()) {
|
||||
await _dialog.hide();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
].where((Object o) => o != null).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_dialog.hide();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Uri _getPaymentUrl(String paymentToken) {
|
||||
final queryParameters = {
|
||||
'productID': widget.planId,
|
||||
'paymentToken': paymentToken,
|
||||
'action': widget.actionType,
|
||||
'redirectURL': kWebPaymentRedirectUrl,
|
||||
};
|
||||
final tryParse = Uri.tryParse(kWebPaymentBaseEndpoint);
|
||||
if (kDebugMode && kWebPaymentBaseEndpoint.startsWith("http://")) {
|
||||
return Uri.http(tryParse.authority, tryParse.path, queryParameters);
|
||||
} else {
|
||||
return Uri.https(tryParse.authority, tryParse.path, queryParameters);
|
||||
}
|
||||
}
|
||||
|
||||
// show dialog to handle accidental back press.
|
||||
Future<bool> _buildPageExitWidget(BuildContext context) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Are you sure you want to exit?'),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text(
|
||||
'Yes',
|
||||
style: TextStyle(
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
'No',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.alternativeColor,
|
||||
),
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool _isPaymentActionComplete(Uri loadingUri) {
|
||||
return loadingUri.toString().startsWith(kWebPaymentRedirectUrl);
|
||||
}
|
||||
|
||||
Future<void> _handlePaymentResponse(Uri uri) async {
|
||||
final queryParams = uri.queryParameters;
|
||||
final paymentStatus = uri.queryParameters['status'] ?? '';
|
||||
_logger.fine('handle payment response with status $paymentStatus');
|
||||
if (paymentStatus == 'success') {
|
||||
await _handlePaymentSuccess(queryParams);
|
||||
} else if (paymentStatus == 'fail') {
|
||||
final reason = queryParams['reason'] ?? '';
|
||||
await _handlePaymentFailure(reason);
|
||||
} else {
|
||||
// should never reach here
|
||||
_logger.severe("unexpected status", uri.toString());
|
||||
showGenericErrorDialog(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handlePaymentFailure(String reason) async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Payment failed'),
|
||||
content: Text("Unfortunately your payment failed due to $reason"),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('Ok'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop('dialog');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
|
||||
// return true if verifySubscription didn't throw any exceptions
|
||||
Future<void> _handlePaymentSuccess(Map<String, String> queryParams) async {
|
||||
final checkoutSessionID = queryParams['session_id'] ?? '';
|
||||
await _dialog.show();
|
||||
try {
|
||||
final response = await billingService.verifySubscription(
|
||||
widget.planId,
|
||||
checkoutSessionID,
|
||||
paymentProvider: stripe,
|
||||
);
|
||||
await _dialog.hide();
|
||||
if (response != null) {
|
||||
final content = widget.actionType == 'buy'
|
||||
? 'Your purchase was successful'
|
||||
: 'Your subscription was updated successfully';
|
||||
await _showExitPageDialog(title: 'Thank you', content: content);
|
||||
} else {
|
||||
throw Exception("verifySubscription api failed");
|
||||
}
|
||||
} catch (error) {
|
||||
_logger.severe(error);
|
||||
await _dialog.hide();
|
||||
await _showExitPageDialog(
|
||||
title: 'Failed to verify payment status',
|
||||
content: 'Please wait for sometime before retrying',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// warn the user to wait for sometime before trying another payment
|
||||
Future<dynamic> _showExitPageDialog({String title, String content}) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(content),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(
|
||||
'Ok',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.alternativeColor,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop('dialog');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
).then((val) => Navigator.pop(context, true));
|
||||
}
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
import 'package:ente_auth/models/subscription.dart';
|
||||
import 'package:ente_auth/ui/payment/billing_questions_widget.dart';
|
||||
import 'package:ente_auth/utils/data_util.dart';
|
||||
import 'package:ente_auth/utils/date_time_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SubscriptionHeaderWidget extends StatefulWidget {
|
||||
final bool isOnboarding;
|
||||
final int currentUsage;
|
||||
|
||||
const SubscriptionHeaderWidget({
|
||||
Key key,
|
||||
this.isOnboarding,
|
||||
this.currentUsage,
|
||||
}) : 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: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"Select your plan",
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
"Ente preserves your memories, so they're always available to you, even if you lose your device ",
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SizedBox(
|
||||
height: 72,
|
||||
width: double.infinity,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "Current usage is ",
|
||||
style: Theme.of(context).textTheme.subtitle1,
|
||||
),
|
||||
TextSpan(
|
||||
text: formatBytes(widget.currentUsage),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.subtitle1
|
||||
.copyWith(fontWeight: FontWeight.bold),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 const SizedBox.shrink();
|
||||
}
|
||||
final endDate = getDateAndMonthAndYear(
|
||||
DateTime.fromMicrosecondsSinceEpoch(currentSubscription.expiryTime),
|
||||
);
|
||||
var message = "Renews on $endDate";
|
||||
if (currentSubscription.productID == freeProductID) {
|
||||
message = "Free plan valid till $endDate";
|
||||
} else if (currentSubscription.attributes?.isCancelled ?? false) {
|
||||
message = "Your subscription will be cancelled on $endDate";
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Text(
|
||||
message,
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SubFaqWidget extends StatelessWidget {
|
||||
const SubFaqWidget({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () {
|
||||
showModalBottomSheet<void>(
|
||||
backgroundColor: Theme.of(context).colorScheme.bgColorForQuestions,
|
||||
barrierColor: Colors.black87,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const BillingQuestionsWidget();
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(40),
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
text: "Questions?",
|
||||
style: Theme.of(context).textTheme.overline,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'package:ente_auth/utils/data_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SubscriptionPlanWidget extends StatelessWidget {
|
||||
const SubscriptionPlanWidget({
|
||||
Key key,
|
||||
@required this.storage,
|
||||
@required this.price,
|
||||
@required this.period,
|
||||
this.isActive = false,
|
||||
}) : super(key: key);
|
||||
|
||||
final int storage;
|
||||
final String price;
|
||||
final String period;
|
||||
final bool isActive;
|
||||
|
||||
String _displayPrice() {
|
||||
final result = price + (period.isNotEmpty ? " / " + period : "");
|
||||
return result.isNotEmpty ? result : "Trial plan";
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Color textColor = isActive ? Colors.white : Colors.black;
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: Theme.of(context).colorScheme.onPrimary,
|
||||
padding: EdgeInsets.symmetric(horizontal: isActive ? 8 : 16, vertical: 4),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isActive
|
||||
? const Color(0xFF22763F)
|
||||
: const Color.fromRGBO(240, 240, 240, 1.0),
|
||||
gradient: isActive
|
||||
? const LinearGradient(
|
||||
begin: Alignment.centerLeft,
|
||||
end: Alignment.centerRight,
|
||||
colors: [
|
||||
Color(0xFF2CD267),
|
||||
Color(0xFF1DB954),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
),
|
||||
// color: Colors.yellow,
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: isActive ? 22 : 20, vertical: 18),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
convertBytesToReadableFormat(storage),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headline6
|
||||
.copyWith(color: textColor),
|
||||
),
|
||||
Text(
|
||||
_displayPrice(),
|
||||
style: Theme.of(context).textTheme.headline6.copyWith(
|
||||
color: textColor,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue