diff --git a/.github/labeler.yml b/.github/labeler.yml index 669881944..342736ee7 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -153,10 +153,6 @@ - "**/comments/**" - "**/**comment**" -"feature: donation": - - "**/donate/**" - - "**/donate**" - "feature: feedback": - "**/feedback/**" - "**/**feedback**" diff --git a/app/assets/icons/backpack.svg b/app/assets/icons/backpack.svg deleted file mode 100644 index fdbf0beed..000000000 --- a/app/assets/icons/backpack.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/icons/book.svg b/app/assets/icons/book.svg deleted file mode 100644 index df9903272..000000000 --- a/app/assets/icons/book.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/icons/chocolate.svg b/app/assets/icons/chocolate.svg deleted file mode 100644 index 4832943f0..000000000 --- a/app/assets/icons/chocolate.svg +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/assets/icons/pizza.svg b/app/assets/icons/pizza.svg deleted file mode 100644 index e831a80e7..000000000 --- a/app/assets/icons/pizza.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/assets/icons/sandwich.svg b/app/assets/icons/sandwich.svg deleted file mode 100644 index ca55171c1..000000000 --- a/app/assets/icons/sandwich.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/lib/account/features/feature_gateway.dart b/app/lib/account/features/feature_gateway.dart index 56bc8bdb5..9ff42015e 100644 --- a/app/lib/account/features/feature_gateway.dart +++ b/app/lib/account/features/feature_gateway.dart @@ -10,7 +10,6 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:rxdart/subjects.dart'; import 'package:sharezone/account/features/objects/all_colors.dart'; import 'package:sharezone/account/features/objects/feature.dart'; -import 'package:sharezone/account/features/objects/hide_donations.dart'; import 'package:user/user.dart'; class FeatureGateway { @@ -32,7 +31,6 @@ class FeatureGateway { Features.fromJson(doc?.data()['features'] as Map); if (features != null) { if (features.allColors) featureSet.add(AllColors()); - if (features.hideDonations) featureSet.add(HideDonations()); } _unlockedFeaturesSubject.sink.add(featureSet); diff --git a/app/lib/account/features/features_bloc.dart b/app/lib/account/features/features_bloc.dart index 8850f51bb..2711c0039 100644 --- a/app/lib/account/features/features_bloc.dart +++ b/app/lib/account/features/features_bloc.dart @@ -12,15 +12,11 @@ import 'package:bloc_base/bloc_base.dart'; import 'package:rxdart/rxdart.dart'; import 'package:sharezone/account/features/feature_gateway.dart'; import 'package:sharezone/account/features/objects/all_colors.dart'; -import 'package:sharezone/account/features/objects/hide_donations.dart'; class FeatureBloc extends BlocBase { final _isAllColorsUnlockedSubject = BehaviorSubject(); Stream get isAllColorsUnlocked => _isAllColorsUnlockedSubject; - final _hideDonationsSubject = BehaviorSubject(); - Stream get hideDonations => _hideDonationsSubject; - StreamSubscription _unlockedFeaturesSubscription; FeatureBloc(FeatureGateway featureGateway) { @@ -31,16 +27,13 @@ class FeatureBloc extends BlocBase { _unlockedFeaturesSubscription = featureGateway.unlockedFeatures.listen((featureSet) { final isAllColorsUnlocked = featureSet.contains(AllColors()); - final hideDonations = featureSet.contains(HideDonations()); _isAllColorsUnlockedSubject.sink.add(isAllColorsUnlocked); - _hideDonationsSubject.sink.add(hideDonations); }); } @override void dispose() { - _hideDonationsSubject.close(); _isAllColorsUnlockedSubject.close(); _unlockedFeaturesSubscription.cancel(); } diff --git a/app/lib/account/features/objects/hide_donations.dart b/app/lib/account/features/objects/hide_donations.dart deleted file mode 100644 index bd43b9158..000000000 --- a/app/lib/account/features/objects/hide_donations.dart +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:sharezone/account/features/objects/feature.dart'; - -/// Wie kann der Donate-Button aus dem Drawer ausgeblendet werden? Im -/// User-Dokument muss das Attribut 'features' als Map hinzugefügt werden. -/// Danach muss zu dieser Map der Schlüssel "hideDonations" mit dem Wert "true" -/// hinzugefügt werden. -class HideDonations extends Feature { - HideDonations() : super("hideDonations"); -} diff --git a/app/lib/blocs/sharezone_bloc_providers.dart b/app/lib/blocs/sharezone_bloc_providers.dart index 29040f9ad..8c5ca3507 100644 --- a/app/lib/blocs/sharezone_bloc_providers.dart +++ b/app/lib/blocs/sharezone_bloc_providers.dart @@ -46,9 +46,6 @@ import 'package:sharezone/dashboard/gateway/dashboard_gateway.dart'; import 'package:sharezone/dashboard/tips/cache/dashboard_tip_cache.dart'; import 'package:sharezone/dashboard/tips/dashboard_tip_system.dart'; import 'package:sharezone/dashboard/update_reminder/update_reminder_bloc.dart'; -import 'package:sharezone/donate/analytics/donation_analytics.dart'; -import 'package:sharezone/donate/bloc/donation_bloc.dart'; -import 'package:sharezone/donate/donation_service/donation_service.dart'; import 'package:sharezone/download_app_tip/analytics/download_app_tip_analytics.dart'; import 'package:sharezone/download_app_tip/bloc/download_app_tip_bloc.dart'; import 'package:sharezone/download_app_tip/cache/download_app_tip_cache.dart'; @@ -65,7 +62,6 @@ import 'package:sharezone/homework/analytics/homework_analytics.dart'; import 'package:sharezone/homework/student/src/mark_overdue_homework_prompt.dart'; import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart'; import 'package:sharezone/main/onboarding/onboarding_navigator.dart'; -import 'package:sharezone/main/plugin_initializations.dart'; import 'package:sharezone/markdown/markdown_analytics.dart'; import 'package:sharezone/navigation/analytics/navigation_analytics.dart'; import 'package:sharezone/navigation/logic/navigation_bloc.dart'; @@ -154,12 +150,6 @@ class _SharezoneBlocProvidersState extends State { FeedbackAnalytics(analytics), ); - PluginInitializations.tryInitializeRevenueCat( - apiKey: widget.blocDependencies.remoteConfiguration - .getString('revenuecat_api_key'), - uid: widget.blocDependencies.authUser.uid, - ); - super.initState(); } @@ -443,17 +433,6 @@ class _SharezoneBlocProvidersState extends State { bloc: ReportGateway(widget.blocDependencies.firestore)), BlocProvider(bloc: feedbackBloc), BlocProvider(bloc: markdownAnalytics), - BlocProvider( - bloc: DonationBloc( - userId: UserId(api.uID), - donationService: DonationService( - crashAnalytics: getCrashAnalytics(), - analytics: analytics, - appFunctions: widget.blocDependencies.appFunctions, - ), - analytics: DonationAnalytics(analytics), - ), - ), BlocProvider( bloc: CommentsBlocFactory( CommentsGateway(api.references.firestore), diff --git a/app/lib/donate/README.md b/app/lib/donate/README.md deleted file mode 100644 index 1bc4fbb04..000000000 --- a/app/lib/donate/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Donation-Flow - -```mermaid -graph TB - - InAppPurchase[In-App-Kauf wird getätigt]--> - DonationDocument[OnCall-CF wird aufgerufen]--> - Validation[CF validiert über RevenueCat REST API, ob Donation gültig war] - Validation -- gültig --> Notification[Client zeigt erfolgreiche Donation an.] - Validation -- ungültig --> DeleteDonation[Sende ungültige Donation] - -``` \ No newline at end of file diff --git a/app/lib/donate/analytics/donation_analytics.dart b/app/lib/donate/analytics/donation_analytics.dart deleted file mode 100644 index e442bb546..000000000 --- a/app/lib/donate/analytics/donation_analytics.dart +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:analytics/analytics.dart'; -import 'package:meta/meta.dart'; -import 'package:sharezone/donate/donation_service/donation_service.dart'; -import 'package:sharezone_utils/platform.dart'; - -class DonationAnalytics { - final Analytics _analytics; - - DonationAnalytics(this._analytics); - - void logDonation(DonationItemId id) { - _analytics.log(DonatedEvent(id: id)); - } - - void logDonationPageOpened(Platform platform) { - _analytics.log( - AnalyticsEvent( - 'donation_page_opened', - data: {'platform': platform.toString().toLowerCase()}, - ), - ); - } - - void logPressedDonationButtonOnMacOs() { - _analytics.log(NamedAnalyticsEvent(name: 'donation_pressed_button_macos')); - } -} - -class DonatedEvent extends AnalyticsEvent { - DonatedEvent({ - @required this.id, - }) : super('donated_$id'); - - final DonationItemId id; -} diff --git a/app/lib/donate/bloc/donation_bloc.dart b/app/lib/donate/bloc/donation_bloc.dart deleted file mode 100644 index a9428a5da..000000000 --- a/app/lib/donate/bloc/donation_bloc.dart +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:bloc_base/bloc_base.dart'; -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:crash_analytics/crash_analytics.dart'; -import 'package:flutter/services.dart'; -import 'package:meta/meta.dart'; -import 'package:optional/optional.dart'; -import 'package:purchases_flutter/errors.dart'; -import 'package:sharezone/donate/analytics/donation_analytics.dart'; -import 'package:sharezone/donate/donation_service/donation_service.dart'; -import 'package:sharezone/donate/page/donation_item_view.dart'; -import 'package:sharezone_utils/platform.dart'; -import '../donation_service/src/should_be_reported_extension.dart'; - -class DonationBloc extends BlocBase { - final UserId userId; - final DonationService donationService; - final DonationAnalytics analytics; - - DonationBloc({ - @required this.userId, - @required this.donationService, - @required this.analytics, - }); - - Future> getProductViews() async { - final items = await donationService.loadDonationItems(); - items.sortById(); - return items.toViews(); - } - - Future spende(DonationItemId id) async { - try { - await donationService.purchase(id); - } on PlatformException catch (e, s) { - final purchaseError = PurchasesErrorHelper.getErrorCode(e); - if (purchaseError != PurchasesErrorCode.purchaseCancelledError) { - if (purchaseError.shouldErrorBeReported()) { - getCrashAnalytics().recordError(purchaseError, s); - } - } - - rethrow; - } - } - - void logDonationPageOpened() { - analytics.logDonationPageOpened(getPlatform()); - } - - // Donations sind aktuell noch nich für macOS verfügbar. Trotzdem soll - // getrackt werden, wie viele Nutzer über macOS gespendet hätten. - void logPressedDonationButtonOnMacOs() { - analytics.logPressedDonationButtonOnMacOs(); - } - - @override - void dispose() {} -} - -extension on List { - List toViews() { - return map((p) => p.toView()).toList(); - } - - void sortById() { - sort((a, b) => a.id.id.compareTo(b.id.id)); - } -} - -extension on DonationItem { - DonationItemView toView() { - return DonationItemView( - id: id, - iconPath: Optional.ofNullable(_getIconPath()), - title: title, - price: formattedPrice, - ); - } - - String _getIconPath() { - const basepath = 'assets/icons'; - if (title.contains('Schokoriegel')) { - return '$basepath/chocolate.svg'; - } else if (title.contains('Pausenbrot')) { - return '$basepath/sandwich.svg'; - } else if (title.contains('Mittagessen')) { - return '$basepath/pizza.svg'; - } else if (title.contains('Neue Hefter')) { - return '$basepath/book.svg'; - } else if (title.contains('Neuer Schulranzen')) { - return '$basepath/backpack.svg'; - } - return null; - } -} diff --git a/app/lib/donate/donation_service/donation_item.dart b/app/lib/donate/donation_service/donation_item.dart deleted file mode 100644 index c551073e8..000000000 --- a/app/lib/donate/donation_service/donation_item.dart +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:meta/meta.dart'; - -class DonationItemId extends Id { - DonationItemId(String id) : super(id, 'DonationItemId'); -} - -class DonationItem { - final DonationItemId id; - final String title; - final String formattedPrice; - - DonationItem({ - @required this.id, - @required this.title, - @required this.formattedPrice, - }); -} diff --git a/app/lib/donate/donation_service/donation_service.dart b/app/lib/donate/donation_service/donation_service.dart deleted file mode 100644 index 53449d92c..000000000 --- a/app/lib/donate/donation_service/donation_service.dart +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:analytics/analytics.dart'; -import 'package:app_functions/app_functions.dart'; -import 'package:crash_analytics/crash_analytics.dart'; -import 'package:meta/meta.dart'; -import 'package:purchases_flutter/purchases_flutter.dart'; -import 'package:sharezone/donate/analytics/donation_analytics.dart'; -import 'package:sharezone/donate/donation_service/src/revenue_cat_donation_service.dart'; - -import 'donation_item.dart'; -import 'src/purchase_service.dart'; -import 'src/sharezone_donation_backend.dart'; - -export 'donation_item.dart'; - -class DonationService { - final PurchaseService purchaseService; - final SharezoneDonationBackend sharezoneDonationBackend; - final DonationAnalytics donateAnalytics; - - factory DonationService({ - @required CrashAnalytics crashAnalytics, - @required Analytics analytics, - @required AppFunctions appFunctions, - }) { - return DonationService.internal( - purchaseService: RevenueCatPurchaseService(), - sharezoneDonationBackend: AppFunctionSharezoneDonationBackend( - crashAnalytics: crashAnalytics, - appFunctions: appFunctions, - ), - donateAnalytics: DonationAnalytics(analytics), - ); - } - - @visibleForTesting - DonationService.internal({ - @required this.purchaseService, - @required this.sharezoneDonationBackend, - @required this.donateAnalytics, - }); - - Future purchase(DonationItemId id) async { - await purchaseService.purchase(ProductId.fromDonationItemId(id)); - await sharezoneDonationBackend.notifyUserDonated(id); - donateAnalytics.logDonation(id); - } - - Future> loadDonationItems() async { - final products = await purchaseService.getProducts(); - return [ - for (final product in products) product.toDonationItem(), - ]; - } -} - -extension on StoreProduct { - DonationItem toDonationItem() { - return DonationItem( - id: DonationItemId(identifier), - title: _getTitle(), - formattedPrice: priceString, - ); - } - - /// Der Title, den RevenueCat zurückgibt, enthalt am Ende - /// den App-Titel aus dem jeweiligen noch. Bei Android wäre - /// dies z.B. "Schokoriegel (Schulplaner, Hausaufgaben, - /// Stundenplan: Sharezone)". Diese Methode gibt den Titel - /// des Produktes ohne den App-Titel zurück. - String _getTitle() { - return title.replaceAll(RegExp(r"\(.+?\)$"), "").trim(); - } -} diff --git a/app/lib/donate/donation_service/src/purchase_service.dart b/app/lib/donate/donation_service/src/purchase_service.dart deleted file mode 100644 index 0d66c7745..000000000 --- a/app/lib/donate/donation_service/src/purchase_service.dart +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:purchases_flutter/purchases_flutter.dart'; - -import '../donation_item.dart'; - -class ProductId extends Id { - ProductId._(String id) : super(id, 'productId'); - - /// 'donation_1_play_store' --> '1' - factory ProductId.fromDonationItemId(DonationItemId id) { - return ProductId._(id.toString().substring(9, 10)); - } -} - -abstract class PurchaseService { - Future purchase(ProductId id); - Future> getProducts(); -} diff --git a/app/lib/donate/donation_service/src/revenue_cat_donation_service.dart b/app/lib/donate/donation_service/src/revenue_cat_donation_service.dart deleted file mode 100644 index 4a62db89e..000000000 --- a/app/lib/donate/donation_service/src/revenue_cat_donation_service.dart +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:purchases_flutter/purchases_flutter.dart'; - -import 'purchase_service.dart'; - -class RevenueCatPurchaseService implements PurchaseService { - @override - Future purchase(ProductId id) async { - final offerings = await Purchases.getOfferings(); - final availablePackages = - offerings.getOffering('default-donate').availablePackages; - final packageToPurchase = availablePackages - .singleWhere((package) => package.identifier == id.toString()); - await Purchases.purchasePackage(packageToPurchase); - } - - @override - Future> getProducts() async { - final offerings = await Purchases.getOfferings(); - - final availablePackages = - offerings.getOffering('default-donate').availablePackages; - final identifiers = availablePackages - .map((package) => package.storeProduct.identifier) - .toList(); - - final products = await Purchases.getProducts( - identifiers, - type: PurchaseType.inapp, - ); - - return products; - } -} diff --git a/app/lib/donate/donation_service/src/sharezone_donation_backend.dart b/app/lib/donate/donation_service/src/sharezone_donation_backend.dart deleted file mode 100644 index 67025d6b9..000000000 --- a/app/lib/donate/donation_service/src/sharezone_donation_backend.dart +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:app_functions/app_functions.dart'; -import 'package:crash_analytics/crash_analytics.dart'; -import 'package:meta/meta.dart'; -import 'package:sharezone/donate/donation_service/donation_item.dart'; - -import '../donation_service.dart'; - -abstract class SharezoneDonationBackend { - Future notifyUserDonated(DonationItemId productId); -} - -class AppFunctionSharezoneDonationBackend extends SharezoneDonationBackend { - final AppFunctions appFunctions; - final CrashAnalytics crashAnalytics; - - AppFunctionSharezoneDonationBackend({ - @required this.appFunctions, - @required this.crashAnalytics, - }); - - @override - Future notifyUserDonated(DonationItemId productId) async { - await _callOnDonationFunction(productId); - } - - Future> _callOnDonationFunction( - DonationItemId donationItemId) async { - final res = await appFunctions.callCloudFunction( - functionName: 'onDonationCreated', - parameters: {'donationItemId': '$donationItemId'}, - ); - if (res.hasException) { - throw res.exception; - } - return res.data as Map; - } -} diff --git a/app/lib/donate/donation_service/src/should_be_reported_extension.dart b/app/lib/donate/donation_service/src/should_be_reported_extension.dart deleted file mode 100644 index 5ffaabc1e..000000000 --- a/app/lib/donate/donation_service/src/should_be_reported_extension.dart +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:purchases_flutter/errors.dart'; - -extension ShouldBeReportedExtension on PurchasesErrorCode { - /// Diese Errors sollten niemals auftreten. Sollte es doch zu diesem Fall - /// kommen, sollten diese Error an uns reported werden, damit diese behoben - /// werden können. - bool shouldErrorBeReported() { - return [ - PurchasesErrorCode.unknownError, - PurchasesErrorCode.unknownBackendError, - PurchasesErrorCode.unexpectedBackendResponseError, - PurchasesErrorCode.invalidCredentialsError, - PurchasesErrorCode.invalidAppUserIdError, - PurchasesErrorCode.invalidReceiptError, - PurchasesErrorCode.receiptAlreadyInUseError, - ].contains(this); - } -} diff --git a/app/lib/donate/page/donate_page.dart b/app/lib/donate/page/donate_page.dart deleted file mode 100644 index 737f9167f..000000000 --- a/app/lib/donate/page/donate_page.dart +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:bloc_provider/bloc_provider.dart'; -import 'package:build_context/build_context.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; -import 'package:optional/optional.dart'; -import 'package:purchases_flutter/purchases_flutter.dart'; -import 'package:sharezone/donate/bloc/donation_bloc.dart'; -import 'package:sharezone/navigation/logic/navigation_bloc.dart'; -import 'package:sharezone/navigation/models/navigation_item.dart'; -import 'package:sharezone/navigation/scaffold/app_bar_configuration.dart'; -import 'package:sharezone/navigation/scaffold/sharezone_main_scaffold.dart'; -import 'package:sharezone/pages/settings/src/subpages/about/widgets/team.dart'; -import 'package:sharezone/pages/settings/support_page.dart'; -import 'package:sharezone/util/launch_link.dart'; -import 'package:sharezone_utils/dimensions.dart'; -import 'package:sharezone_utils/platform.dart'; -import 'package:sharezone_widgets/adaptive_dialog.dart'; -import 'package:sharezone_widgets/snackbars.dart'; -import 'package:sharezone_widgets/svg.dart'; -import 'package:sharezone_widgets/theme.dart'; -import 'package:sharezone_widgets/widgets.dart'; -import 'package:sharezone_widgets/wrapper.dart'; - -import 'donation_item_view.dart'; -import 'translate_purchases_error_code.dart'; - -class DonatePage extends StatefulWidget { - static const tag = 'donate-page'; - - @override - _DonatePageState createState() => _DonatePageState(); -} - -class _DonatePageState extends State { - @override - void initState() { - super.initState(); - logPageOpened(); - } - - void logPageOpened() { - final bloc = BlocProvider.of(context); - bloc.logDonationPageOpened(); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () => popToOverview(context), - child: SharezoneMainScaffold( - appBarConfiguration: AppBarConfiguration(title: 'Spenden'), - navigationItem: NavigationItem.donate, - body: Center( - child: SingleChildScrollView( - padding: EdgeInsets.symmetric(vertical: 12), - child: MaxWidthConstraintBox( - child: SafeArea( - child: Column( - children: const [ - SizedBox(height: 8), - _Team(), - SizedBox(height: 20), - _Title(), - SizedBox(height: 20), - _BeggingForMoneyText(), - SizedBox(height: 18), - _DonationOptions(), - ], - ), - ), - ), - ), - ), - ), - ); - } -} - -class _Title extends StatelessWidget { - const _Title({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Text( - 'Unterstütze Sharezone 💙', - style: Theme.of(context).textTheme.headlineSmall, - textAlign: TextAlign.center, - ); - } -} - -class _Team extends StatelessWidget { - const _Team({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - final sizedBoxWidth = - Dimensions.fromMediaQuery(context).isDesktopModus ? 50.0 : 12.0; - return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _TeamMember( - imagePath: TeamImagePath.nils, - name: 'Nils Reichardt', - ), - SizedBox(width: sizedBoxWidth), - _TeamMember( - imagePath: TeamImagePath.jonas, - name: 'Jonas Sander', - ), - SizedBox(width: sizedBoxWidth), - ], - ), - ); - } -} - -class _TeamMember extends StatelessWidget { - const _TeamMember({ - Key key, - @required this.imagePath, - @required this.name, - }) : super(key: key); - - final String imagePath; - final String name; - - @override - Widget build(BuildContext context) { - final imageSize = - (MediaQuery.of(context).size.width * 0.25).clamp(0.0, 100.0).toDouble(); - return Tooltip( - message: name, - child: Image( - width: imageSize, - height: imageSize, - image: AssetImage(imagePath), - ), - ); - } -} - -class _BeggingForMoneyText extends StatelessWidget { - const _BeggingForMoneyText({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: MarkdownBody( - data: - // Umbrüche müssen mit \n gemacht werden, da ansonsten bei ''' ''' - // das Markdown-Plugin den Text nicht korrekt anzeigt, wenn dort ein - // Emoji enthalten ist. - 'Wir sind 2 Jungs, die aus der Schule heraus mit Sharezone den Schulalltag revolutionieren wollen!\n\nWir sind für jede Spende dankbar, die es uns ermöglicht noch weiter Zeit und Energie in Sharezone zu stecken ❤️\n\nJeder Spender enthält zudem den Unterstützer-Rang auf unserem [Discord-Server](https://sharezone.net/discord) 💪', - styleSheet: MarkdownStyleSheet( - textAlign: WrapAlignment.center, - p: Theme.of(context) - .textTheme - .bodyMedium - .copyWith(fontSize: 16, height: 1.3), - a: linkStyle(context), - ), - onTapLink: (url, _, __) => launchURL(url, context: context), - ), - ); - } -} - -class _DonationOptions extends StatelessWidget { - const _DonationOptions({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - // Im Web laufen die Donations über einen PayPal-Link, weil ein - // Bezahlservice, wie z.B. Stripe noch nicht implementiert ist. - if (PlatformCheck.isWeb) return _PayPalDonateButton(); - - // Das RevenueCat-Plugin unterstützt momentan noch keine In-App-Käufe für - // Flutter macOS. Sobald dies möglich ist, kann auch über die macOS-App - // gespendet werden. - // - // Ticket: https://github.com/RevenueCat/purchases-flutter/issues/26 - if (PlatformCheck.isMacOS) return _DonationsNotSupportedOnMacOsButton(); - - final bloc = BlocProvider.of(context); - return FutureBuilder>( - future: bloc.getProductViews(), - builder: (context, snapshot) { - if (!snapshot.hasData) return AccentColorCircularProgressIndicator(); - final products = snapshot.data; - return Column( - children: [ - for (final product in products) - _DonationOptionTile( - leadingSvgPath: product.iconPath, - product: product, - ) - ], - ); - }, - ); - } -} - -class _PayPalDonateButton extends StatelessWidget { - @override - Widget build(BuildContext context) { - return ElevatedButton.icon( - onPressed: () => launchURL("https://paypal.me/sharezone"), - label: const Text("Spenden via PayPal"), - icon: Icon(Icons.favorite), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, backgroundColor: Theme.of(context).primaryColor, - ), - ); - } -} - -class _DonationsNotSupportedOnMacOsButton extends StatelessWidget { - @override - Widget build(BuildContext context) { - return ElevatedButton.icon( - onPressed: () { - _noMacOsSupportDialog(context); - _logPressedDonationButton(context); - }, - label: const Text("Spenden"), - icon: Icon(Icons.favorite), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, backgroundColor: Theme.of(context).primaryColor, - ), - ); - } - - void _logPressedDonationButton(BuildContext context) { - final bloc = BlocProvider.of(context); - bloc.logPressedDonationButtonOnMacOs(); - } - - void _noMacOsSupportDialog(BuildContext context) { - showLeftRightAdaptiveDialog( - context: context, - title: 'Spenden über macOS nicht möglich', - left: AdaptiveDialogAction.ok, - content: Text( - "Aktuell kann leider nicht über die macOS-App gespendet werden. Dies ist nur über die Android-, iOS- oder Web-App möglich."), - ); - } -} - -class _DonationOptionTile extends StatelessWidget { - const _DonationOptionTile({ - Key key, - @required this.leadingSvgPath, - this.product, - }) : super(key: key); - - final Optional leadingSvgPath; - final DonationItemView product; - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(bottom: 10), - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 400), - child: ListTile( - leading: CircleAvatar( - backgroundColor: isDarkThemeEnabled(context) - ? Colors.grey[700] - : Colors.grey[300], - child: leadingSvgPath.isPresent - ? PlatformSvg.asset( - leadingSvgPath.value, - width: 27.5, - height: 27.5, - ) - : null, - ), - title: Text(product.title), - trailing: Text(product.price), - onTap: () => donate(context), - ), - ), - ); - } - - Future donate(BuildContext context) async { - final bloc = BlocProvider.of(context); - try { - // Snackbar wird verzögert angezeigt, damit erst der Kaufdialog angezeigt - // wird und danach erst die Lade-Snackbar. - Future.delayed(const Duration(milliseconds: 600)).then( - (value) => showSnackSec( - context: context, - text: 'Spende wird übermittelt', - seconds: 60, - withLoadingCircle: true, - ), - ); - await bloc.spende(product.id); - context.hideCurrentSnackBar(); - showThanksDialog(context); - } on PlatformException catch (e) { - context.hideCurrentSnackBar(); - final purchaseError = PurchasesErrorHelper.getErrorCode(e); - if (purchaseError != PurchasesErrorCode.purchaseCancelledError) { - showErrorDialog(context, - PurchasesErrorTranslator.getTranslatedMessage(purchaseError)); - } - } on Exception catch (e) { - context.hideCurrentSnackBar(); - showErrorDialog(context, 'Es gab einen Fehler: ${e.toString()}'); - } - } - - Future showErrorDialog(BuildContext context, String errorMsg) async { - final contactSupport = await showLeftRightAdaptiveDialog( - context: context, - defaultValue: false, - content: Text(errorMsg), - title: 'Fehler', - left: AdaptiveDialogAction( - title: 'Support kontakieren', - popResult: true, - ), - right: AdaptiveDialogAction.ok, - ); - if (contactSupport) { - Navigator.pushNamed(context, SupportPage.tag); - } - } - - void showThanksDialog(BuildContext context) { - showLeftRightAdaptiveDialog( - context: context, - title: "Danke!", - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - PlatformSvg.asset('assets/icons/gift.svg', width: 125, height: 125), - const SizedBox(height: 28), - Text( - "Vielen Dank für deine Spende!\n\nFalls du den Unterstützer-Rang auf unserem Discord-Server erhalten möchtest, dann melde dich dort bei einem Admin 👍", - textAlign: TextAlign.center, - ) - ], - ), - left: AdaptiveDialogAction.ok, - ); - } -} diff --git a/app/lib/donate/page/donation_item_view.dart b/app/lib/donate/page/donation_item_view.dart deleted file mode 100644 index 2fc6c77cf..000000000 --- a/app/lib/donate/page/donation_item_view.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:meta/meta.dart'; -import 'package:optional/optional.dart'; -import 'package:sharezone/donate/donation_service/donation_item.dart'; - -class DonationItemView { - final DonationItemId id; - final Optional iconPath; - final String title; - final String price; - - DonationItemView({ - @required this.id, - @required this.iconPath, - @required this.title, - @required this.price, - }); - - @override - // ignore: avoid_renaming_method_parameters - bool operator ==(Object o) { - if (identical(this, o)) return true; - - return o is DonationItemView && - o.id == id && - o.iconPath == iconPath && - o.title == title && - o.price == price; - } - - @override - int get hashCode { - return id.hashCode ^ iconPath.hashCode ^ title.hashCode ^ price.hashCode; - } -} diff --git a/app/lib/donate/page/translate_purchases_error_code.dart b/app/lib/donate/page/translate_purchases_error_code.dart deleted file mode 100644 index 1a3c145b8..000000000 --- a/app/lib/donate/page/translate_purchases_error_code.dart +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:purchases_flutter/object_wrappers.dart'; - -class PurchasesErrorTranslator { - static String getTranslatedMessage(PurchasesErrorCode error) { - const tryItAgain = 'Versuche es einfach nochmal 👍'; - const plsContactSupport = 'Bitte kontaktiere den Support.'; - - if (error == PurchasesErrorCode.networkError) { - return 'Es gab einen Fehler mit deiner Internetverbindung! $tryItAgain'; - } - if (error == PurchasesErrorCode.operationAlreadyInProgressError) { - return 'Es scheint so, dass ein bereits getätigter Kauf noch verarbeitet wird. Warte einfach einen kurzen Moment, bis dieser verarbeitet wurde.'; - } - if (error == PurchasesErrorCode.invalidCredentialsError) { - return 'Der API-Key wurde falsch konfiguriert. $plsContactSupport'; - } - if (error == PurchasesErrorCode.invalidAppUserIdError) { - return 'Deine User-Id ist ungültig. $plsContactSupport'; - } - if (error == PurchasesErrorCode.purchaseCancelledError) { - return 'Der Kauf wurde abgebrochen.'; - } - if (error == PurchasesErrorCode.invalidReceiptError) { - return 'Es gab einen Fehler bei der Rechnung. $plsContactSupport'; - } - if (error == PurchasesErrorCode.productNotAvailableForPurchaseError) { - return 'Dieses Produkt ist nicht mehr verfügbar.'; - } - if (error == PurchasesErrorCode.receiptAlreadyInUseError) { - return 'Die Rechnung wird bereits von einem anderen User verwendet. $plsContactSupport'; - } - if (error == PurchasesErrorCode.missingReceiptFileError) { - // Dieser Fehler tritt bei Sandbox-Testing häufiger auf. - return 'Es ist kein Rechnung vorhanden... $plsContactSupport'; - } - if (error == PurchasesErrorCode.purchaseNotAllowedError) { - return 'Dieses Gerät darf keine Käufe tätigen 🙁'; - } - if (error == PurchasesErrorCode.paymentPendingError) { - return 'Es ist ein weiterer Schritt bei der Bezahlung notwenig. Bitte beende diesen Schritt.'; - } - if (error == PurchasesErrorCode.purchaseInvalidError) { - return 'Es gab einen Fehler beim Kauf. Bitte überprüfe, ob die Zahlungsmethode gültig ist.'; - } - if (error == PurchasesErrorCode.productAlreadyPurchasedError) { - return 'Das Produkt wurde bereits gekauft.'; - } - if (error == PurchasesErrorCode.storeProblemError) { - return 'Es gab einen Fehler beim App- oder PlayStore. $tryItAgain'; - } - if (error == PurchasesErrorCode.unexpectedBackendResponseError) { - return 'Es gab eine unerwartete Fehlermeldung vom Server. $plsContactSupport'; - } - if (error == PurchasesErrorCode.unknownBackendError) { - return 'Es gab einen Fehler beim Server. $plsContactSupport'; - } - return 'Es gab beim Kauf einen unbekannten Fehler. $plsContactSupport'; - } -} diff --git a/app/lib/main/plugin_initializations.dart b/app/lib/main/plugin_initializations.dart index 0c0b24b36..34ec71949 100644 --- a/app/lib/main/plugin_initializations.dart +++ b/app/lib/main/plugin_initializations.dart @@ -6,15 +6,10 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'dart:developer'; - import 'package:crash_analytics/crash_analytics.dart'; import 'package:dynamic_links/dynamic_links.dart'; -import 'package:flutter/foundation.dart'; -import 'package:purchases_flutter/purchases_flutter.dart'; import 'package:remote_configuration/remote_configuration.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:sharezone_utils/platform.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; class PluginInitializations { @@ -37,23 +32,6 @@ class PluginInitializations { return crashAnalytics; } - /// Unter der User-ID "$RCAnonymousID:7689187fe95f4116bd0239217a211465" wurde - /// bereits ein In-App-Kauf getätigt (donation_1_play_store). Diese User-ID - /// kann beim Debuggen genutzt werden, um Daten von Käufern abzufragen. - static Future tryInitializeRevenueCat( - {@required String apiKey, @required String uid}) async { - // Web wird vom RevenueCat-Package nicht unterstützt - if (!PlatformCheck.isWeb) { - try { - if (!kReleaseMode) await Purchases.setLogLevel(LogLevel.debug); - await Purchases.configure( - PurchasesConfiguration(apiKey)..appUserID = uid); - } catch (e) { - log('RevenueCat konnte nicht inizialisiert werden: $e', error: e); - } - } - } - static Future initializeDynamicLinks() async { final dynamicLinks = getDynamicLinks(); return dynamicLinks; diff --git a/app/lib/navigation/drawer/drawer.dart b/app/lib/navigation/drawer/drawer.dart index def9acbdf..0fcdaa33d 100644 --- a/app/lib/navigation/drawer/drawer.dart +++ b/app/lib/navigation/drawer/drawer.dart @@ -84,7 +84,6 @@ class _DrawerItems extends StatelessWidget { ...functionTiles, const Divider(), feedbackBoxtile, - donatePageTile, settingsPageTile, ], ), diff --git a/app/lib/navigation/drawer/tiles/drawer_tiles.dart b/app/lib/navigation/drawer/tiles/drawer_tiles.dart index 99e84f8db..20c14b77c 100644 --- a/app/lib/navigation/drawer/tiles/drawer_tiles.dart +++ b/app/lib/navigation/drawer/tiles/drawer_tiles.dart @@ -6,25 +6,13 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:bloc_provider/bloc_provider.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:sharezone/account/features/features_bloc.dart'; import 'package:sharezone/navigation/models/navigation_item.dart'; import 'drawer_tile.dart'; const settingsPageTile = DrawerTile(NavigationItem.settings); const feedbackBoxtile = DrawerTile(NavigationItem.feedbackBox); -final donatePageTile = Builder( - builder: (context) => StreamBuilder( - stream: BlocProvider.of(context).hideDonations, - builder: (context, snapshot) { - final hideDonations = snapshot.data ?? false; - if (hideDonations) return Container(); - return DrawerTile(NavigationItem.donate); - }, - ), -); const onlyDesktopTiles = [ DrawerTile(NavigationItem.overview), DrawerTile(NavigationItem.group), diff --git a/app/lib/navigation/models/navigation_item.dart b/app/lib/navigation/models/navigation_item.dart index c39219378..7ce721ca3 100644 --- a/app/lib/navigation/models/navigation_item.dart +++ b/app/lib/navigation/models/navigation_item.dart @@ -12,7 +12,6 @@ import 'package:sharezone/account/account_page.dart'; import 'package:sharezone/blackboard/blackboard_page.dart'; import 'package:sharezone/calendrical_events/page/calendrical_events_page.dart'; import 'package:sharezone/dashboard/dashboard_page.dart'; -import 'package:sharezone/donate/page/donate_page.dart'; import 'package:sharezone/feedback/feedback_box_page.dart'; import 'package:sharezone/filesharing/file_sharing_page.dart'; import 'package:sharezone/groups/src/pages/course/group_page.dart'; @@ -30,7 +29,6 @@ enum NavigationItem { filesharing, events, feedbackBox, - donate, settings, accountPage, more, @@ -71,8 +69,6 @@ extension NavigationItemExtension on NavigationItem { return 'feedback'; case NavigationItem.accountPage: return 'profile'; - case NavigationItem.donate: - return 'donate'; case NavigationItem.more: return 'more'; } @@ -111,9 +107,6 @@ extension NavigationItemExtension on NavigationItem { case NavigationItem.accountPage: return Icon( themeIconData(Icons.person, cupertinoIcon: SFSymbols.person_fill)); - case NavigationItem.donate: - return Icon( - themeIconData(Icons.favorite, cupertinoIcon: SFSymbols.heart_fill)); case NavigationItem.more: return Icon( themeIconData(Icons.more_horiz, cupertinoIcon: SFSymbols.ellipsis)); @@ -143,8 +136,6 @@ extension NavigationItemExtension on NavigationItem { return 'Feedback'; case NavigationItem.accountPage: return 'Profil'; - case NavigationItem.donate: - return 'Spenden'; case NavigationItem.more: return 'Mehr'; } @@ -173,8 +164,6 @@ extension NavigationItemExtension on NavigationItem { return FeedbackPage(); case NavigationItem.accountPage: return AccountPage(); - case NavigationItem.donate: - return DonatePage(); case NavigationItem.more: // [NavigationItem.more] is not a spefic page. It's a navigation element // in the [ExtendableBottomNavigationBar] @@ -205,8 +194,6 @@ extension NavigationItemExtension on NavigationItem { return FeedbackPage.tag; case NavigationItem.accountPage: return AccountPage.tag; - case NavigationItem.donate: - return DonatePage.tag; case NavigationItem.more: // [NavigationItem.more] is not a spefic page. It's a navigation element // in the [ExtendableBottomNavigationBar] diff --git a/app/macos/Flutter/GeneratedPluginRegistrant.swift b/app/macos/Flutter/GeneratedPluginRegistrant.swift index 04c1c0f0f..2a4ed4428 100644 --- a/app/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/app/macos/Flutter/GeneratedPluginRegistrant.swift @@ -21,7 +21,6 @@ import package_info import package_info_plus import path_provider_foundation import pdfx -import purchases_flutter import shared_preferences_foundation import sign_in_with_apple import sqflite @@ -45,7 +44,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PdfxPlugin.register(with: registry.registrar(forPlugin: "PdfxPlugin")) - PurchasesFlutterPlugin.register(with: registry.registrar(forPlugin: "PurchasesFlutterPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SignInWithApplePlugin.register(with: registry.registrar(forPlugin: "SignInWithApplePlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/app/pubspec.lock b/app/pubspec.lock index ad4264e16..15b5112da 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -880,6 +880,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.3" + flutter_lints: + dependency: transitive + description: + name: flutter_lints + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" + source: hosted + version: "2.0.1" flutter_localizations: dependency: "direct main" description: flutter @@ -967,14 +975,6 @@ packages: url: "https://pub.dev" source: hosted version: "10.4.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - sha256: aeac15850ef1b38ee368d4c53ba9a847e900bb2c53a4db3f6881cbb3cb684338 - url: "https://pub.dev" - source: hosted - version: "2.2.0" frontend_server_client: dependency: transitive description: @@ -1251,6 +1251,14 @@ packages: relative: true source: path version: "0.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" + source: hosted + version: "2.0.1" logging: dependency: transitive description: @@ -1612,14 +1620,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" - purchases_flutter: - dependency: "direct main" - description: - name: purchases_flutter - sha256: bf54c32a02991398d1f5cd6fd4482be91fef89ffe4b0929a33d592bf1fa26e66 - url: "https://pub.dev" - source: hosted - version: "4.10.1" qr: dependency: transitive description: @@ -1753,6 +1753,13 @@ packages: relative: true source: path version: "0.0.1" + sharezone_lints: + dependency: transitive + description: + path: "../lib/sharezone_lints" + relative: true + source: path + version: "1.0.0" sharezone_utils: dependency: "direct main" description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 26ce25198..9b1399976 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -114,7 +114,6 @@ dependencies: permission_handler: ^10.2.0 photo_view: ^0.14.0 provider: ^6.0.3 - purchases_flutter: ^4.10.1 qr_flutter: ^4.0.0 quiver: ^3.0.1 remote_configuration: diff --git a/app/test/donate/donation_service_test.dart b/app/test/donate/donation_service_test.dart deleted file mode 100644 index 5a2cd6f4d..000000000 --- a/app/test/donate/donation_service_test.dart +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:flutter_test/flutter_test.dart'; -import 'package:purchases_flutter/models/introductory_price.dart'; -import 'package:purchases_flutter/models/store_product_discount.dart'; -import 'package:purchases_flutter/models/store_product_wrapper.dart'; -import 'package:random_string/random_string.dart'; -import 'package:sharezone/donate/donation_service/donation_service.dart'; -import 'package:sharezone/donate/donation_service/src/purchase_service.dart'; -import 'package:sharezone/donate/donation_service/src/sharezone_donation_backend.dart'; - -import 'mock_donate_analytics.dart'; - -void main() { - group('DonationService', () { - DonationService donationService; - MockPurchasingService purchasingService; - MockDonateAnalytics donateAnalytics; - MockSharezoneDonationBackend sharezoneDonationBackend; - - setUp(() { - purchasingService = MockPurchasingService(); - donateAnalytics = MockDonateAnalytics(); - sharezoneDonationBackend = MockSharezoneDonationBackend(); - - donationService = DonationService.internal( - sharezoneDonationBackend: sharezoneDonationBackend, - donateAnalytics: donateAnalytics, - purchaseService: purchasingService, - ); - }); - - TestProduct _productWith({String id, String title}) { - return TestProduct( - identifier: id, - price: 3, - currencyCode: 'EUR', // ? - description: 'Schönes Ding', - title: title ?? - 'Schokoriegel (Schulplaner, Hausaufgaben, Stundenplan: Sharezone)', - priceString: '3€'); - } - - Future expectTitle( - {String fromPurchaseTitle, String isFormattedTo}) async { - var id = randomAlpha(9); - final productAtOffer = _productWith(id: id, title: fromPurchaseTitle); - purchasingService.add(productAtOffer); - - final item = await donationService.loadDonationWithId(id); - - expect(item.title, isFormattedTo); - } - - test('loggt Analytics, wenn gespendet wurde.', () async { - final productAtOffer = _productWith(id: '1'); - purchasingService.add(productAtOffer); - - await donationService.purchase(DonationItemId('donation_1_play_store')); - - expect(donateAnalytics.donationLogged, true); - }); - - test('formats title form purchase to donation item correctly', () async { - await expectTitle( - fromPurchaseTitle: - 'Schokoriegel (Schulplaner, Hausaufgaben, Stundenplan: Sharezone)', - isFormattedTo: 'Schokoriegel', - ); - await expectTitle( - fromPurchaseTitle: - 'Neuer Schulranzen (Schulplaner, Hausaufgaben, Stundenplan: Sharezone)', - isFormattedTo: 'Neuer Schulranzen', - ); - await expectTitle( - fromPurchaseTitle: 'Neuer Schulranzen (Irgendein Title)', - isFormattedTo: 'Neuer Schulranzen', - ); - await expectTitle( - fromPurchaseTitle: 'Neuer Schulranzen', - isFormattedTo: 'Neuer Schulranzen', - ); - }); - }); -} - -class TestProduct implements StoreProduct { - /// StoreProduct Id. - @override - final String identifier; - - /// Description of the product. - @override - final String description; - - /// Title of the product. - @override - final String title; - - /// Price of the product in the local currency. - @override - final double price; - - /// Formatted price of the item, including its currency sign. - @override - final String priceString; - - /// Currency code for price and original price. - @override - final String currencyCode; - - /// For Testing - bool wasBought = false; - - TestProduct({ - this.identifier, - this.description, - this.title, - this.price, - this.priceString, - this.currencyCode, - }); - - @override - $StoreProductCopyWith get copyWith => - throw UnimplementedError(); - - @override - String get subscriptionPeriod => throw UnimplementedError(); - - @override - Map toJson() { - throw UnimplementedError(); - } - - @override - List get discounts => throw UnimplementedError(); - - @override - IntroductoryPrice get introductoryPrice => throw UnimplementedError(); -} - -class MockPurchasingService extends PurchaseService { - final _products = []; - - void add(TestProduct product) { - _products.add(product); - } - - @override - Future> getProducts() async { - return _products; - } - - @override - Future purchase(ProductId id) async { - getProduct(id).wasBought = true; - } - - TestProduct getProduct(ProductId id) { - return _products.singleWhere((p) => p.identifier == '$id'); - } - - bool wasProductBought(String id) { - return _products.singleWhere((p) => p.identifier == id).wasBought; - } -} - -extension on DonationService { - Future loadDonationWithId(String id) async { - return (await loadDonationItems()).singleWhere((p) => '${p.id}' == id); - } -} - -class MockSharezoneDonationBackend extends SharezoneDonationBackend { - @override - Future notifyUserDonated(DonationItemId productId) async {} -} diff --git a/app/test/donate/mock_donate_analytics.dart b/app/test/donate/mock_donate_analytics.dart deleted file mode 100644 index 3800d12a6..000000000 --- a/app/test/donate/mock_donate_analytics.dart +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:sharezone/donate/analytics/donation_analytics.dart'; -import 'package:sharezone/donate/donation_service/donation_service.dart'; -import 'package:sharezone_utils/src/platform/models/platform.dart'; - -class MockDonateAnalytics implements DonationAnalytics { - bool donationLogged = false; - bool donationPageOpenedLogged = false; - bool donationViaMacOsLogged = false; - - @override - void logDonation(DonationItemId id) { - donationLogged = true; - } - - @override - void logDonationPageOpened(Platform platform) { - donationPageOpenedLogged = true; - } - - @override - void logPressedDonationButtonOnMacOs() { - donationViaMacOsLogged = true; - } -} diff --git a/lib/user/lib/src/models/features.dart b/lib/user/lib/src/models/features.dart index b52c978c8..09ef80ab8 100644 --- a/lib/user/lib/src/models/features.dart +++ b/lib/user/lib/src/models/features.dart @@ -8,24 +8,20 @@ class Features { final bool allColors; - final bool hideDonations; Features({ required this.allColors, - required this.hideDonations, }); Map toJson() { return { 'allColors': allColors, - 'hide-donations': hideDonations, }; } factory Features.fromJson(Map? map) { return Features( allColors: map == null ? true : map['allColors'] ?? true, - hideDonations: map == null ? false : map['hideDonations'] ?? false, ); } @@ -33,15 +29,12 @@ class Features { bool operator ==(Object other) { if (identical(this, other)) return true; - return other is Features && - other.allColors == allColors && - other.hideDonations == hideDonations; + return other is Features && other.allColors == allColors; } @override - int get hashCode => allColors.hashCode ^ hideDonations.hashCode; + int get hashCode => allColors.hashCode; @override - String toString() => - 'Features(allColors: $allColors, hideDonations: $hideDonations)'; + String toString() => 'Features(allColors: $allColors)'; }