diff --git a/app/assets/icons/graduation-cap.svg b/app/assets/icons/graduation-cap.svg
deleted file mode 100644
index a7dc456ab..000000000
--- a/app/assets/icons/graduation-cap.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock
index fdbc037a0..d2259ba2b 100644
--- a/app/ios/Podfile.lock
+++ b/app/ios/Podfile.lock
@@ -684,7 +684,7 @@ SPEC CHECKSUMS:
GTMSessionFetcher: 8000756fc1c19d2e5697b90311f7832d2e33f6cd
image_picker_ios: b545a5f16c0fa88e3ecbbce3ed4de45567a8ec18
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
- integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4
+ integration_test: 13825b8a9334a850581300559b8839134b124670
leveldb-library: e8eadf9008a61f9e1dde3978c086d2b6d9b9dc28
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
diff --git a/app/lib/dashboard/tips/dashboard_tip_system.dart b/app/lib/dashboard/tips/dashboard_tip_system.dart
index 012426af4..7934119d8 100644
--- a/app/lib/dashboard/tips/dashboard_tip_system.dart
+++ b/app/lib/dashboard/tips/dashboard_tip_system.dart
@@ -10,7 +10,6 @@ import 'package:bloc_base/bloc_base.dart';
import 'package:rxdart/rxdart.dart';
import 'package:sharezone/dashboard/tips/cache/dashboard_tip_cache.dart';
import 'package:sharezone/dashboard/tips/models/rate_our_app_tip.dart';
-import 'package:sharezone/dashboard/tips/models/wrapped_tip.dart';
import 'package:sharezone/navigation/logic/navigation_bloc.dart';
import 'package:sharezone/settings/src/bloc/user_tips_bloc.dart';
@@ -37,16 +36,12 @@ class DashboardTipSystem extends BlocBase {
UserTipsBloc userTipsBloc,
) {
final rateOurAppTip = RateOurAppTip(cache);
- final wrappedTip =
- SharezoneWrappedTip(cache, userTipsBloc.streamAccountCreatedOn());
- final tips = [rateOurAppTip, wrappedTip];
+ final tips = [rateOurAppTip];
return CombineLatestStream(tips.map((tip) => tip.shouldShown()).toList(),
(streamValues) {
final showRateOurAppCard = streamValues[0];
- final showWrappedTip = streamValues[1];
- if (showWrappedTip) return wrappedTip;
if (showRateOurAppCard) return rateOurAppTip;
return null;
});
diff --git a/app/lib/dashboard/tips/models/wrapped_tip.dart b/app/lib/dashboard/tips/models/wrapped_tip.dart
deleted file mode 100644
index bb61781fb..000000000
--- a/app/lib/dashboard/tips/models/wrapped_tip.dart
+++ /dev/null
@@ -1,57 +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/material.dart' hide Action;
-import 'package:rxdart/rxdart.dart';
-import 'package:sharezone/dashboard/tips/cache/dashboard_tip_cache.dart';
-import 'package:sharezone/dashboard/tips/models/action.dart';
-import 'package:sharezone/dashboard/tips/models/dashboard_tip.dart';
-import 'package:sharezone/sharezone_wrapped/sharezone_wrapped_page.dart';
-
-class SharezoneWrappedTip implements DashboardTip {
- static const _showedDashboardRatingCardKey =
- "dashboard-showed-wrapped-23-24-tip";
-
- final DashboardTipCache cache;
- final Stream accountCreatedOn;
-
- SharezoneWrappedTip(this.cache, this.accountCreatedOn);
-
- @override
- Action get action => Action(
- title: "Ansehen",
- onTap: (context) =>
- Navigator.pushNamed(context, SharezoneWrappedPage.tag));
-
- @override
- String get text =>
- "Das Schuljahr ist vorbei! Sieh dir dein Sharezone Wrapped 23/24 (dein Schuljahr in Zahlen) an 🎉";
-
- @override
- String get title => "Sharezone Wrapped 23/24";
-
- @override
- Stream shouldShown() {
- return CombineLatestStream([
- cache.showedTip(_showedDashboardRatingCardKey),
- accountCreatedOn,
- ], (streamValues) {
- final showedDashboardCounterCard = streamValues[0] as bool? ?? false;
- final createdOn = streamValues[1] as DateTime?;
-
- // New user shouldn't see the Sharezone Wrapped tip because their Wrapped
- // will be mostly empty.
- final isOldUser = createdOn?.isBefore(DateTime(2024, 5, 1)) == true;
-
- return !showedDashboardCounterCard && isOldUser;
- });
- }
-
- @override
- void markAsShown() => cache.markTipAsShown(_showedDashboardRatingCardKey);
-}
diff --git a/app/lib/main/plugin_initializations.dart b/app/lib/main/plugin_initializations.dart
index dc5cdc682..524b6b939 100644
--- a/app/lib/main/plugin_initializations.dart
+++ b/app/lib/main/plugin_initializations.dart
@@ -81,8 +81,7 @@ class PluginInitializations {
'firebase_messaging_vapid_key':
'BNT7Da6B6wi-mUBcGrt-9HxeIJZsPTsPpmR8cae_LhgJPcSFb5j0T8o-r-oFV1xAtXVXfRPIZlgUJR3tx8mLbbA',
'stripe_checkout_session_function_url':
- 'https://europe-west1-sharezone-c2bd8.cloudfunctions.net/createStripeCheckoutSession',
- 'show_sz_wrapped_23_24': true,
+ 'https://europe-west1-sharezone-c2bd8.cloudfunctions.net/createStripeCheckoutSession'
});
try {
diff --git a/app/lib/main/sharezone_app.dart b/app/lib/main/sharezone_app.dart
index 5f80e19c3..e64a7e91f 100644
--- a/app/lib/main/sharezone_app.dart
+++ b/app/lib/main/sharezone_app.dart
@@ -55,7 +55,6 @@ import 'package:sharezone/settings/src/subpages/notification.dart';
import 'package:sharezone/settings/src/subpages/theme/theme_page.dart';
import 'package:sharezone/settings/src/subpages/timetable/timetable_settings_page.dart';
import 'package:sharezone/settings/src/subpages/web_app.dart';
-import 'package:sharezone/sharezone_wrapped/sharezone_wrapped_page.dart';
import 'package:sharezone/sharezone_v2/sz_v2_announcement_dialog.dart';
import 'package:sharezone/support/support_page.dart';
import 'package:sharezone/timetable/timetable_add/timetable_add_page.dart';
@@ -205,8 +204,6 @@ class _SharezoneAppState extends State
ICalLinksDialog.tag: (context) => const ICalLinksDialog(),
CreateTermPage.tag: (context) => const CreateTermPage(),
GradesDialog.tag: (context) => const GradesDialog(),
- SharezoneWrappedPage.tag: (context) =>
- const SharezoneWrappedPage(),
},
navigatorKey: navigationService.navigatorKey,
),
diff --git a/app/lib/main/sharezone_bloc_providers.dart b/app/lib/main/sharezone_bloc_providers.dart
index 48e58ccea..467a5f53a 100644
--- a/app/lib/main/sharezone_bloc_providers.dart
+++ b/app/lib/main/sharezone_bloc_providers.dart
@@ -33,7 +33,6 @@ import 'package:http/http.dart' as http;
import 'package:key_value_store/in_memory_key_value_store.dart';
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
-import 'package:remote_configuration/remote_configuration.dart';
import 'package:sharezone/account/account_page_bloc_factory.dart';
import 'package:sharezone/account/change_data_bloc.dart';
import 'package:sharezone/account/type_of_user_bloc.dart';
@@ -116,8 +115,6 @@ import 'package:sharezone/sharezone_plus/page/sharezone_plus_page_controller.dar
import 'package:sharezone/sharezone_plus/subscription_service/is_buying_enabled.dart';
import 'package:sharezone/sharezone_plus/subscription_service/revenue_cat_sharezone_plus_service.dart';
import 'package:sharezone/sharezone_plus/subscription_service/subscription_service.dart';
-import 'package:sharezone/sharezone_wrapped/sharezone_wrapped_controller.dart';
-import 'package:sharezone/sharezone_wrapped/sharezone_wrapped_repository.dart';
import 'package:sharezone/support/support_page_controller.dart';
import 'package:sharezone/timetable/src/bloc/timetable_bloc.dart';
import 'package:sharezone/timetable/src/models/lesson_length/lesson_length_cache.dart';
@@ -351,9 +348,6 @@ class _SharezoneBlocProvidersState extends State {
create: (context) => api.user.authUserStream,
initialData: null,
),
- Provider(
- create: (context) => widget.blocDependencies.remoteConfiguration,
- ),
ChangeNotifierProvider(
create: (context) => SharezonePlusPageController(
buyingFlagApi: BuyingEnabledApi(client: http.Client()),
@@ -487,19 +481,7 @@ class _SharezoneBlocProvidersState extends State {
courseMemberAccessor:
FirestoreCourseMemberAccessor(api.references.firestore),
),
- ),
- Provider(
- create: (context) => SharezoneWrappedController(
- repository: SharezoneWrappedRepository(
- firestore: firestore,
- userId: api.userId,
- connectionsGateway: api.connectionsGateway,
- clock: clock,
- ),
- crashAnalytics: crashAnalytics,
- analytics: analytics,
- ),
- ),
+ )
];
mainBlocProviders = [
diff --git a/app/lib/settings/settings_page.dart b/app/lib/settings/settings_page.dart
index 41ebaf819..aa6acb12c 100644
--- a/app/lib/settings/settings_page.dart
+++ b/app/lib/settings/settings_page.dart
@@ -10,8 +10,6 @@ import 'package:analytics/analytics.dart';
import 'package:bloc_provider/bloc_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
-import 'package:provider/provider.dart';
-import 'package:remote_configuration/remote_configuration.dart';
import 'package:sharezone/legal/terms_of_service/terms_of_service_page.dart';
import 'package:sharezone/main/application_bloc.dart';
import 'package:sharezone/navigation/logic/navigation_bloc.dart';
@@ -21,13 +19,11 @@ import 'package:sharezone/settings/src/subpages/changelog_page.dart';
import 'package:sharezone/settings/src/subpages/notification.dart';
import 'package:sharezone/settings/src/subpages/about/about_page.dart';
import 'package:sharezone/settings/src/subpages/theme/theme_page.dart';
-import 'package:sharezone/sharezone_wrapped/sharezone_wrapped_page.dart';
import 'package:sharezone/support/support_page.dart';
import 'package:sharezone/settings/src/subpages/timetable/timetable_settings_page.dart';
import 'package:sharezone/settings/src/subpages/web_app.dart';
import 'package:sharezone/legal/privacy_policy/privacy_policy_page.dart';
import 'package:platform_check/platform_check.dart';
-import 'package:sharezone/widgets/limited_chip.dart';
import 'package:sharezone_utils/launch_link.dart';
import 'package:sharezone_widgets/sharezone_widgets.dart';
@@ -149,38 +145,29 @@ class _LegalSection extends StatelessWidget {
class _AppSettingsSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
- final remoteConfig = context.read();
- final showWrapped = remoteConfig.getBool('show_sz_wrapped_23_24');
- return _SettingsSection(
+ return const _SettingsSection(
title: 'App-Einstellungen',
children: [
- const _SettingsOption(
+ _SettingsOption(
title: "Mein Konto",
icon: Icon(Icons.account_circle),
tag: MyProfilePage.tag,
),
- const _SettingsOption(
+ _SettingsOption(
title: "Benachrichtigungen",
icon: Icon(Icons.notifications_active),
tag: NotificationPage.tag,
),
- const _SettingsOption(
+ _SettingsOption(
title: "Erscheinungsbild",
icon: Icon(Icons.color_lens),
tag: ThemePage.tag,
),
- const _SettingsOption(
+ _SettingsOption(
title: "Stundenplan",
icon: Icon(Icons.access_time),
tag: TimetableSettingsPage.tag,
- ),
- if (showWrapped)
- const _SettingsOption(
- title: "Schuljahr 23/24 Sharezone Wrapped",
- icon: Icon(Icons.fast_rewind),
- tag: SharezoneWrappedPage.tag,
- trailing: LimitedChip(),
- )
+ )
],
);
}
@@ -262,13 +249,11 @@ class _SettingsOption extends StatelessWidget {
this.icon,
this.onTap,
this.tag,
- this.trailing,
});
final String? title;
final Widget? icon;
final GestureTapCallback? onTap;
- final Widget? trailing;
final String? tag;
@override
@@ -277,7 +262,6 @@ class _SettingsOption extends StatelessWidget {
title: Text(title!),
leading: icon,
onTap: onTap ?? () => Navigator.pushNamed(context, tag!),
- trailing: trailing,
);
}
}
diff --git a/app/lib/settings/src/bloc/user_tips_bloc.dart b/app/lib/settings/src/bloc/user_tips_bloc.dart
index 02e553271..60a23df0d 100644
--- a/app/lib/settings/src/bloc/user_tips_bloc.dart
+++ b/app/lib/settings/src/bloc/user_tips_bloc.dart
@@ -19,10 +19,6 @@ class UserTipsBloc extends BlocBase {
return _userGateway.userStream.map((user) => user?.userTipData);
}
- Stream streamAccountCreatedOn() {
- return _userGateway.userStream.map((user) => user?.createdOn);
- }
-
void enableUserTip(UserTipKey tipKey) {
_updateUserTip(tipKey, true);
}
diff --git a/app/lib/sharezone_wrapped/sharezone_wrapped_controller.dart b/app/lib/sharezone_wrapped/sharezone_wrapped_controller.dart
deleted file mode 100644
index 3d0f25739..000000000
--- a/app/lib/sharezone_wrapped/sharezone_wrapped_controller.dart
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright (c) 2024 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:collection/collection.dart';
-import 'package:common_domain_models/common_domain_models.dart';
-import 'package:crash_analytics/crash_analytics.dart';
-import 'package:date/weektype.dart';
-import 'package:equatable/equatable.dart';
-import 'package:group_domain_models/group_domain_models.dart';
-import 'package:sharezone/sharezone_wrapped/sharezone_wrapped_repository.dart';
-import 'package:sharezone/timetable/src/models/lesson.dart';
-
-class SharezoneWrappedController {
- final CrashAnalytics crashAnalytics;
- final Analytics analytics;
- final SharezoneWrappedRepository repository;
-
- const SharezoneWrappedController({
- required this.repository,
- required this.crashAnalytics,
- required this.analytics,
- });
-
- Future getValues() async {
- try {
- final courses = repository.getCourses();
- final courseIds = courses.map((course) => CourseId(course.id)).toList();
-
- final (
- lessons,
- totalAmountOfHomeworks,
- totalAmountOfExams,
- homeworkTopThreeCourses,
- examTopThreeCourses,
- ) = await (
- repository.getLessons(),
- repository.getTotalAmountOfHomeworks(),
- repository.getTotalAmountOfExams(),
- _getHomeworkTopThreeCourses(courseIds),
- _getExamTopThreeCourses(courseIds),
- ).wait;
-
- final totalAmountOfLessonHours = _getTotalAmountOfLessonHours(lessons);
- final lessonHoursTopThreeCourses =
- _getLessonHoursTopThreeCourses(courseIds, lessons);
-
- _logGenerationAnalytics();
-
- return SharezoneWrappedValues(
- totalAmountOfLessonHours: totalAmountOfLessonHours,
- amountOfLessonHoursTopThreeCourses:
- lessonHoursTopThreeCourses.withCourseName(courses),
- totalAmountOfHomeworks: totalAmountOfHomeworks ?? 0,
- amountOfHomeworksTopThreeCourses:
- homeworkTopThreeCourses.withCourseName(courses),
- totalAmountOfExams: totalAmountOfExams ?? 0,
- amountOfExamsTopThreeCourses:
- examTopThreeCourses.withCourseName(courses),
- );
- } catch (e, s) {
- crashAnalytics.recordError(
- 'Failed to get values for SharezoneWrapped: $e', s);
- rethrow;
- }
- }
-
- void _logGenerationAnalytics() {
- analytics.log(NamedAnalyticsEvent(name: 'sz_wrapped_generated'));
- }
-
- /// Calculates the amount of lesson hours per course per school year.
- ///
- /// The amount of lesson hours is calculated by summing up the duration of all
- /// lessons per course.
- ///
- /// We assume that a student has 40 school weeks per year. Source:
- /// https://www.perplexity.ai/search/Wie-viele-Schulwochen-PKOcR28uRe2vga9SuurUcA#0
- List<(CourseId, int)> _getAmountOfLessonHoursPerCourse(List lessons) {
- final lessonMinutesPerCourse = {};
- for (final lesson in lessons) {
- final courseId = CourseId(lesson.groupID);
- int lessonMinutes = lesson.endTime.differenceInMinutes(lesson.startTime);
-
- if (lesson.weektype != WeekType.always) {
- // When the lesson is only every second week, we only count half of the
- // lesson minutes.
- //
- // This calculation will break if support a,b,c or a,b,c,d week types.
- lessonMinutes = lessonMinutes ~/ 2;
- }
-
- lessonMinutesPerCourse[courseId] =
- (lessonMinutesPerCourse[courseId] ?? 0) + lessonMinutes;
- }
-
- return lessonMinutesPerCourse.entries
- // Divide by 60 to get the amount of hours.
- .map((entry) => (entry.key, ((entry.value / 60) * 40).toInt()))
- .toList();
- }
-
- int _getTotalAmountOfLessonHours(List lessons) {
- final perCourses = _getAmountOfLessonHoursPerCourse(lessons);
- return perCourses.map((entry) => entry.$2).fold(0, (a, b) => a + b);
- }
-
- List<(CourseId, int)> _getLessonHoursTopThreeCourses(
- List courseIds, List lessons) {
- final perCourses = _getAmountOfLessonHoursPerCourse(lessons);
- final sorted = perCourses.toList()..sort((a, b) => b.$2.compareTo(a.$2));
- return sorted.take(3).toList();
- }
-
- Future> _getHomeworkTopThreeCourses(
- List courseIds) async {
- return _getTopThreeCourses(
- courseIds,
- (courseId) => repository.getAmountOfHomeworksFor(courseId: courseId),
- );
- }
-
- // get top exam courses
- Future> _getExamTopThreeCourses(
- List courseIds) async {
- return _getTopThreeCourses(
- courseIds,
- (courseId) => repository.getAmountOfExamsFor(courseId: courseId),
- );
- }
-
- Future> _getTopThreeCourses(
- List courseIds,
- Future Function(CourseId) getAmount,
- ) async {
- final amounts = await Future.wait(courseIds.map((courseId) {
- return getAmount(courseId);
- }));
- final amountsSorted = amounts
- .asMap()
- .entries
- .map((entry) => MapEntry(courseIds[entry.key], entry.value))
- .toList();
- amountsSorted.sort((a, b) => (b.value ?? 0).compareTo(a.value ?? 0));
- final topThreeCourses = amountsSorted.take(3).toList();
- return topThreeCourses
- .map((entry) => (entry.key, entry.value ?? 0))
- .toList();
- }
-}
-
-extension on List<(CourseId, int)> {
- List<(CourseId, CourseName, int)> withCourseName(List courses) {
- return map((entry) {
- final course =
- courses.firstWhereOrNull((course) => course.id == entry.$1.value);
- return (entry.$1, course?.name ?? '?', entry.$2);
- }).toList();
- }
-}
-
-class SharezoneWrappedValues extends Equatable {
- final int totalAmountOfLessonHours;
- final List<(CourseId, CourseName, int)> amountOfLessonHoursTopThreeCourses;
- final int totalAmountOfHomeworks;
- final List<(CourseId, CourseName, int)> amountOfHomeworksTopThreeCourses;
- final int totalAmountOfExams;
- final List<(CourseId, CourseName, int)> amountOfExamsTopThreeCourses;
-
- const SharezoneWrappedValues({
- required this.totalAmountOfLessonHours,
- required this.amountOfLessonHoursTopThreeCourses,
- required this.totalAmountOfHomeworks,
- required this.amountOfHomeworksTopThreeCourses,
- required this.totalAmountOfExams,
- required this.amountOfExamsTopThreeCourses,
- });
-
- @override
- List