diff --git a/refilc/lib/api/client.dart b/refilc/lib/api/client.dart index ca5106a..2b153e2 100644 --- a/refilc/lib/api/client.dart +++ b/refilc/lib/api/client.dart @@ -50,6 +50,10 @@ class FilcAPI { static const allGradeColors = "$gradeColorsGet/all"; static const gradeColorsByID = "$gradeColorsGet/"; + // Payment API + static const payment = "$baseUrl/v3/payment"; + static const stripeSheet = "$payment/stripe-sheet"; + static Future checkConnectivity() async => (await Connectivity().checkConnectivity()) != ConnectivityResult.none; @@ -340,6 +344,35 @@ class FilcAPI { } return null; } + + // payment + static Future createPaymentSheet(String product) async { + try { + Map body = { + "product": product, + }; + + var client = http.Client(); + + http.Response res = await client.post( + Uri.parse(stripeSheet), + body: body, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + ); + + if (res.statusCode != 200) { + throw "HTTP ${res.statusCode}: ${res.body}"; + } + + return jsonDecode(res.body); + } on Exception catch (error, stacktrace) { + log("ERROR: FilcAPI.sendReport: $error $stacktrace"); + } + + return null; + } } class ErrorReport { diff --git a/refilc/lib/main.dart b/refilc/lib/main.dart index fe6a3ae..f33a476 100644 --- a/refilc/lib/main.dart +++ b/refilc/lib/main.dart @@ -35,7 +35,7 @@ void main() async { // initialize stripe key stripe.Stripe.publishableKey = - 'pk_live_51OWSV2HW2TAy5tA6EELuXtpG6ombCCrOFbvz2fDwZlqLT42Ql64CfxptWem8NjN1dhnE6jaI77TRsVZbF8gfd29Q00OGMQRGqm'; + 'pk_test_51Oo7iUBS0FxsTGxKjGZSQqzDKWHY5ZFYM9XeI0qSdIh2w8jWy6GhHlYpT7GLTzgpl1xhE5YP4BXpA4gMZqPmgMId00cGFYFzbh'; // Run App runApp(App( diff --git a/refilc/lib/models/settings.dart b/refilc/lib/models/settings.dart index 9560e0e..6441f9e 100644 --- a/refilc/lib/models/settings.dart +++ b/refilc/lib/models/settings.dart @@ -91,6 +91,7 @@ class SettingsProvider extends ChangeNotifier { // more bool _showBreaks; String _fontFamily; + String _plusSessionId; SettingsProvider({ DatabaseProvider? database, @@ -148,6 +149,7 @@ class SettingsProvider extends ChangeNotifier { required String pinSetNotify, required String pinSetExtras, required String fontFamily, + required String plusSessionId, }) : _database = database, _language = language, _startPage = startPage, @@ -202,7 +204,8 @@ class SettingsProvider extends ChangeNotifier { _pinSetPersonalize = pinSetPersonalize, _pinSetNotify = pinSetNotify, _pinSetExtras = pinSetExtras, - _fontFamily = fontFamily; + _fontFamily = fontFamily, + _plusSessionId = plusSessionId; factory SettingsProvider.fromMap(Map map, {required DatabaseProvider database}) { @@ -277,6 +280,7 @@ class SettingsProvider extends ChangeNotifier { pinSetNotify: map['notify_s_pin'], pinSetExtras: map['extras_s_pin'], fontFamily: map['font_family'], + plusSessionId: map['plus_session_id'], ); } @@ -339,6 +343,7 @@ class SettingsProvider extends ChangeNotifier { "notify_s_pin": _pinSetNotify, "extras_s_pin": _pinSetExtras, "font_family": _fontFamily, + "plus_session_id": _plusSessionId, }; } @@ -405,6 +410,7 @@ class SettingsProvider extends ChangeNotifier { pinSetNotify: '', pinSetExtras: '', fontFamily: '', + plusSessionId: '', ); } @@ -462,6 +468,7 @@ class SettingsProvider extends ChangeNotifier { String get currentThemeCreator => _currentThemeCreator; bool get showBreaks => _showBreaks; String get fontFamily => _fontFamily; + String get plusSessionId => _plusSessionId; Future update({ bool store = true, @@ -515,6 +522,7 @@ class SettingsProvider extends ChangeNotifier { String? currentThemeCreator, bool? showBreaks, String? fontFamily, + String? plusSessionId, }) async { if (language != null && language != _language) _language = language; if (startPage != null && startPage != _startPage) _startPage = startPage; @@ -662,6 +670,9 @@ class SettingsProvider extends ChangeNotifier { if (fontFamily != null && fontFamily != _fontFamily) { _fontFamily = fontFamily; } + if (plusSessionId != null && plusSessionId != _plusSessionId) { + _plusSessionId = plusSessionId; + } // store or not if (store) await _database?.store.storeSettings(this); notifyListeners(); diff --git a/refilc/lib/providers/third_party_provider.dart b/refilc/lib/providers/third_party_provider.dart index e01f6d3..4d4a0f4 100644 --- a/refilc/lib/providers/third_party_provider.dart +++ b/refilc/lib/providers/third_party_provider.dart @@ -11,8 +11,10 @@ import 'package:googleapis/calendar/v3.dart'; import 'package:google_sign_in/google_sign_in.dart'; class ThirdPartyProvider with ChangeNotifier { - late List? _googleEvents; late List _linkedAccounts; + // google specific + late List? _googleEvents; + late List? _googleCalendars; late BuildContext _context; @@ -21,9 +23,12 @@ class ThirdPartyProvider with ChangeNotifier { CalendarApi.calendarEventsScope, ]); - List get googleEvents => _googleEvents ?? []; + // public List get linkedAccounts => _linkedAccounts; + List get googleEvents => _googleEvents ?? []; + List get googleCalendars => _googleCalendars ?? []; + ThirdPartyProvider({ required BuildContext context, List? initialLinkedAccounts, @@ -64,6 +69,11 @@ class ThirdPartyProvider with ChangeNotifier { return null; } + Future signOutAll() async { + await _googleSignIn.signOut(); + _linkedAccounts.clear(); + } + // Future fetchGoogle() async { // try { // var httpClient = (await _googleSignIn.authenticatedClient())!; diff --git a/refilc_mobile_ui/lib/premium/components/github_button.dart b/refilc_mobile_ui/lib/premium/components/github_button.dart index 2a4b249..bffe147 100644 --- a/refilc_mobile_ui/lib/premium/components/github_button.dart +++ b/refilc_mobile_ui/lib/premium/components/github_button.dart @@ -1,4 +1,5 @@ import 'package:flutter_stripe/flutter_stripe.dart' as stripe; +import 'package:refilc/api/client.dart'; import 'package:refilc/theme/colors/colors.dart'; import 'package:refilc_plus/providers/premium_provider.dart'; import 'package:refilc_plus/ui/mobile/premium/activation_view/activation_view.dart'; @@ -6,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_feather_icons/flutter_feather_icons.dart'; import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; class GithubLoginButton extends StatelessWidget { const GithubLoginButton({super.key}); @@ -40,10 +42,21 @@ class GithubLoginButton extends StatelessWidget { // Navigator.of(context).push(MaterialPageRoute(builder: (context) { // return const PremiumActivationView(); // })); - bool initFinished = await initPaymentSheet(context); - if (initFinished) { - await stripe.Stripe.instance.presentPaymentSheet(); - } + // bool initFinished = await initPaymentSheet(context); + // if (initFinished) { + // stripe.PaymentSheetPaymentOption? result = + // await stripe.Stripe.instance.presentPaymentSheet(); + + // print(result == null); + + // print(result?.label ?? 'nem label'); + // } + + launchUrl( + Uri.parse( + 'https://api.refilc.hu/v3/payment/stripe-create-checkout?product=asdasd'), + mode: LaunchMode.inAppBrowserView, + ); }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 12.0), @@ -121,6 +134,10 @@ class GithubLoginButton extends StatelessWidget { // 1. create payment intent on the server final data = await _createPaymentSheet(); + if (data == null) { + throw "API error, can't create payment sheet!"; + } + // 2. initialize the payment sheet await stripe.Stripe.instance.initPaymentSheet( paymentSheetParameters: stripe.SetupPaymentSheetParameters( @@ -133,9 +150,9 @@ class GithubLoginButton extends StatelessWidget { customerEphemeralKeySecret: data['ephemeralKey'], customerId: data['customer'], // Extra options - applePay: const stripe.PaymentSheetApplePay( - merchantCountryCode: 'HU', - ), + // applePay: const stripe.PaymentSheetApplePay( + // merchantCountryCode: 'HU', + // ), googlePay: const stripe.PaymentSheetGooglePay( merchantCountryCode: 'HU', testEnv: true, @@ -145,6 +162,7 @@ class GithubLoginButton extends StatelessWidget { ); return true; } catch (e) { + // ignore: use_build_context_synchronously ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error: $e')), ); @@ -152,9 +170,8 @@ class GithubLoginButton extends StatelessWidget { } } - Future> _createPaymentSheet() async { - Map asdasd = {}; - - return asdasd; + Future _createPaymentSheet() async { + Map? data = await FilcAPI.createPaymentSheet("refilcplus"); + return data; } } diff --git a/refilc_mobile_ui/lib/screens/settings/settings_screen.i18n.dart b/refilc_mobile_ui/lib/screens/settings/settings_screen.i18n.dart index 9907cc4..2510749 100644 --- a/refilc_mobile_ui/lib/screens/settings/settings_screen.i18n.dart +++ b/refilc_mobile_ui/lib/screens/settings/settings_screen.i18n.dart @@ -100,6 +100,8 @@ extension SettingsLocalization on String { "fonts": "Fonts", "font_family": "Font Family", "calendar_sync": "Calendar Sync", + "choose_account": "Choose Account", + "your_account": "Your Account", }, "hu_hu": { "personal_details": "Személyes információk", @@ -198,6 +200,8 @@ extension SettingsLocalization on String { "fonts": "Betűk", "font_family": "Betűtípus", "calendar_sync": "Naptár szinkronizálás", + "choose_account": "Válassz fiókot", + "your_account": "Fiókod", }, "de_de": { "personal_details": "Persönliche Angaben", @@ -295,7 +299,9 @@ extension SettingsLocalization on String { "show_breaks": "Pausen anzeigen", "fonts": "Schriftarten", "font_family": "Schriftfamilie", - "calendar_sync": "heil hitler", + "calendar_sync": "Kalender-Synchronisation", + "choose_account": "Konto auswählen", + "your_account": "Ihr Konto", }, }; diff --git a/refilc_mobile_ui/lib/screens/settings/submenu/calendar_sync.dart b/refilc_mobile_ui/lib/screens/settings/submenu/calendar_sync.dart index d2737e7..382e6cd 100644 --- a/refilc_mobile_ui/lib/screens/settings/submenu/calendar_sync.dart +++ b/refilc_mobile_ui/lib/screens/settings/submenu/calendar_sync.dart @@ -70,6 +70,7 @@ class CalendarSyncScreenState extends State late SettingsProvider settingsProvider; late UserProvider user; late ShareProvider shareProvider; + late ThirdPartyProvider thirdPartyProvider; late AnimationController _hideContainersController; @@ -87,6 +88,7 @@ class CalendarSyncScreenState extends State Widget build(BuildContext context) { settingsProvider = Provider.of(context); user = Provider.of(context); + thirdPartyProvider = Provider.of(context); return AnimatedBuilder( animation: _hideContainersController, @@ -164,9 +166,7 @@ class CalendarSyncScreenState extends State height: 18.0, ), // choose account if not logged in - if (Provider.of(context) - .linkedAccounts - .isEmpty) + if (thirdPartyProvider.linkedAccounts.isEmpty) Column( children: [ SplittedPanel( @@ -180,6 +180,8 @@ class CalendarSyncScreenState extends State await Provider.of(context, listen: false) .googleSignIn(); + + setState(() {}); }, title: Text( 'Google', @@ -241,16 +243,121 @@ class CalendarSyncScreenState extends State ], ), - const SizedBox( - height: 18.0, - ), - // own paints - SplittedPanel( - title: Text('public_paint'.i18n), - padding: EdgeInsets.zero, - cardPadding: const EdgeInsets.all(4.0), - children: [], - ), + // show options if logged in + if (thirdPartyProvider.linkedAccounts.isNotEmpty) + Column( + children: [ + SplittedPanel( + title: Text('your_account'.i18n), + padding: EdgeInsets.zero, + cardPadding: const EdgeInsets.all(4.0), + children: [ + PanelButton( + onPressed: null, + title: Text( + thirdPartyProvider + .linkedAccounts.first.username, + style: TextStyle( + color: AppColors.of(context) + .text + .withOpacity(.95), + ), + ), + leading: Image.asset( + 'assets/images/ext_logo/${thirdPartyProvider.linkedAccounts.first.type == AccountType.google ? "google" : "apple"}.png', + width: 24.0, + height: 24.0, + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12), + bottom: Radius.circular(12), + ), + ), + PanelButton( + onPressed: () async { + await thirdPartyProvider.signOutAll(); + setState(() {}); + }, + title: Text( + 'change_account'.i18n, + style: TextStyle( + color: AppColors.of(context) + .text + .withOpacity(.95), + ), + ), + trailing: Icon( + FeatherIcons.chevronRight, + size: 22.0, + color: AppColors.of(context) + .text + .withOpacity(0.95), + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12), + bottom: Radius.circular(12), + ), + ), + ], + ), + const SizedBox( + height: 18.0, + ), + SplittedPanel( + title: Text('choose_calendar'.i18n), + padding: EdgeInsets.zero, + cardPadding: const EdgeInsets.all(4.0), + children: [ + PanelButton( + onPressed: null, + title: Text( + thirdPartyProvider + .linkedAccounts.first.username, + style: TextStyle( + color: AppColors.of(context) + .text + .withOpacity(.95), + ), + ), + leading: Image.asset( + 'assets/images/ext_logo/${thirdPartyProvider.linkedAccounts.first.type == AccountType.google ? "google" : "apple"}.png', + width: 24.0, + height: 24.0, + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12), + bottom: Radius.circular(12), + ), + ), + PanelButton( + onPressed: () async { + await thirdPartyProvider.signOutAll(); + setState(() {}); + }, + title: Text( + 'change_account'.i18n, + style: TextStyle( + color: AppColors.of(context) + .text + .withOpacity(.95), + ), + ), + trailing: Icon( + FeatherIcons.chevronRight, + size: 22.0, + color: AppColors.of(context) + .text + .withOpacity(0.95), + ), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(12), + bottom: Radius.circular(12), + ), + ), + ], + ), + ], + ), ], ), ), diff --git a/refilc_plus b/refilc_plus index c22b3e0..fea4d24 160000 --- a/refilc_plus +++ b/refilc_plus @@ -1 +1 @@ -Subproject commit c22b3e0de6042e09ef1d3693ef7b02fd73e778c3 +Subproject commit fea4d24e0727099654f3899f715c294af2eb72b5