Files
feeddeck/app/lib/widgets/settings/premium/settings_premium_stripe.dart
Rico Berger fb3bec623a [core] Add Missing SafeArea Widget (#124)
Several widgets which where rendered within a modal bottom sheet didn't
used a `SafeArea` widget in the body of the `Scaffold` widget, so that
the action buttons on the bottom of the widget where not rendered in the
correct position.
2024-01-31 20:54:50 +01:00

155 lines
5.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:supabase_flutter/supabase_flutter.dart' as supabase;
import 'package:feeddeck/utils/api_exception.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/utils/fd_icons.dart';
import 'package:feeddeck/utils/openurl.dart';
import 'package:feeddeck/widgets/general/elevated_button_progress_indicator.dart';
const _settingsPremiumStripeText = '''
You are currently using the free version of FeedDeck, which allows you to add up
to 10 sources for the first 7 days. After that trial period your sources will
not be updated anymore.
To use FeedDeck after the trial period with up to 1000 sources, you need to
upgrade to a premium account. The premium account costs 5€ per month and can be
canceled at any time.
''';
class SettingsPremiumStripe extends StatefulWidget {
const SettingsPremiumStripe({super.key});
@override
State<SettingsPremiumStripe> createState() => _SettingsPremiumStripeState();
}
class _SettingsPremiumStripeState extends State<SettingsPremiumStripe> {
late Future<String> _futureFetchCheckoutSessionLink;
/// [_fetchCheckoutSessionLink] is used to fetch the Stripe checkout session
/// link. For that we have to call the `stripe-create-checkout-session-v1`
/// Supabase edge function. If the link is generated successfully, the
/// function returns the url, which can then be opened by the user.
Future<String> _fetchCheckoutSessionLink() async {
final result = await supabase.Supabase.instance.client.functions.invoke(
'stripe-create-checkout-session-v1',
method: supabase.HttpMethod.get,
);
if (result.status != 200) {
throw ApiException(result.data['error'], result.status);
}
return result.data['url'];
}
/// [_openUrl] is used to open the [url] in a browser. If the link can not be
/// opened the error is ignored.
Future<void> _openUrl(String? url) async {
try {
if (url != null) {
await openUrl(url);
}
} catch (_) {}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
setState(() {
_futureFetchCheckoutSessionLink = _fetchCheckoutSessionLink();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
shape: const Border(
bottom: BorderSide(
color: Constants.dividerColor,
width: 1,
),
),
title: const Text('FeedDeck Premium'),
actions: [
IconButton(
icon: const Icon(
Icons.close,
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
body: SafeArea(
child: FutureBuilder(
future: _futureFetchCheckoutSessionLink,
builder: (
BuildContext context,
AsyncSnapshot<String> snapshot,
) {
return Column(
children: [
const Expanded(
child: Padding(
padding: EdgeInsets.all(Constants.spacingMiddle),
child: SingleChildScrollView(
child: MarkdownBody(
selectable: true,
data: _settingsPremiumStripeText,
),
),
),
),
const SizedBox(
height: Constants.spacingSmall,
),
const Divider(
color: Constants.dividerColor,
height: 1,
thickness: 1,
),
Padding(
padding: const EdgeInsets.all(Constants.spacingMiddle),
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: Constants.primary,
foregroundColor: Constants.onPrimary,
maximumSize: const Size.fromHeight(
Constants.elevatedButtonSize,
),
minimumSize: const Size.fromHeight(
Constants.elevatedButtonSize,
),
),
label: const Text('Subscribe to FeedDeck Premium'),
onPressed:
snapshot.connectionState == ConnectionState.none ||
snapshot.connectionState ==
ConnectionState.waiting ||
snapshot.hasError
? null
: () => _openUrl(snapshot.data),
icon: snapshot.connectionState == ConnectionState.none ||
snapshot.connectionState ==
ConnectionState.waiting ||
snapshot.hasError
? const ElevatedButtonProgressIndicator()
: const Icon(FDIcons.feeddeck),
),
),
],
);
},
),
),
);
}
}