From 25c378a9b419f0183c3346926ed3b61d68bc3dab Mon Sep 17 00:00:00 2001 From: Sigve Hansen Date: Tue, 8 Sep 2026 15:15:49 +0200 Subject: [PATCH] refactor(freezed): declare freezed classes abstract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converts all 41 `@freezed` classes in bccm_core from `class X with _$X` to `abstract class X with _$X`. freezed 3.0.0 made this mandatory — classes must be `abstract`, `sealed`, or manually implement `_$X` — and freezed 4 is required by the codegen cluster (it is the only freezed supporting analyzer 13, which is in turn the only analyzer that parses Dart 3.13). Landing the syntax change on its own keeps it out of that cutover PR. No regeneration needed: the generated mixin does not depend on the declaration keyword, so the committed .freezed.dart files stay valid. This was verified on freezed 2.5.8 in a clean pure-Dart harness, which matters because codegen currently cannot run on Flutter 3.47 at all. None of the 41 are unions (each has one public factory, plus fromJson where serialized), so `abstract` is correct throughout and no class needs `sealed`. No @unfreezed anywhere, so the freezed 4 removal of `final` in constructor parameters does not apply. Verified: bccm_core analyze clean + 68/68 tests; brunstadtv_app 132 issues (unchanged baseline, 0 errors) + 113/113 tests; kids 10 issues, 0 errors. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/models/analytics/achievement_clicked.dart | 2 +- .../lib/src/models/analytics/achievement_shared.dart | 2 +- .../lib/src/models/analytics/audio_only_clicked.dart | 2 +- .../src/models/analytics/calendar_day_clicked.dart | 2 +- .../lib/src/models/analytics/chapter_clicked.dart | 2 +- .../lib/src/models/analytics/content_shared.dart | 2 +- .../lib/src/models/analytics/deep_link_opened.dart | 2 +- bccm_core/lib/src/models/analytics/downloads.dart | 6 +++--- bccm_core/lib/src/models/analytics/game_closed.dart | 2 +- .../lib/src/models/analytics/language_changed.dart | 2 +- bccm_core/lib/src/models/analytics/misc.dart | 12 ++++++------ .../src/models/analytics/notification_prompt.dart | 10 +++++----- .../lib/src/models/analytics/notifications.dart | 8 ++++---- .../lib/src/models/analytics/search_performed.dart | 2 +- .../src/models/analytics/search_result_clicked.dart | 6 +++--- bccm_core/lib/src/models/analytics/sections.dart | 6 +++--- bccm_core/lib/src/models/analytics/shorts.dart | 4 ++-- bccm_core/lib/src/models/auth0/auth0_api.dart | 6 +++--- bccm_core/lib/src/models/auth_state.dart | 2 +- bccm_core/lib/src/models/user_profile.dart | 2 +- 20 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bccm_core/lib/src/models/analytics/achievement_clicked.dart b/bccm_core/lib/src/models/analytics/achievement_clicked.dart index b88cc11..a4c2626 100644 --- a/bccm_core/lib/src/models/analytics/achievement_clicked.dart +++ b/bccm_core/lib/src/models/analytics/achievement_clicked.dart @@ -4,7 +4,7 @@ part 'achievement_clicked.freezed.dart'; part 'achievement_clicked.g.dart'; @freezed -class AchievementClickedEvent with _$AchievementClickedEvent { +abstract class AchievementClickedEvent with _$AchievementClickedEvent { const factory AchievementClickedEvent({ required int elementPosition, required String elementTitle, diff --git a/bccm_core/lib/src/models/analytics/achievement_shared.dart b/bccm_core/lib/src/models/analytics/achievement_shared.dart index dc7697e..e965956 100644 --- a/bccm_core/lib/src/models/analytics/achievement_shared.dart +++ b/bccm_core/lib/src/models/analytics/achievement_shared.dart @@ -4,7 +4,7 @@ part 'achievement_shared.freezed.dart'; part 'achievement_shared.g.dart'; @freezed -class AchievementSharedEvent with _$AchievementSharedEvent { +abstract class AchievementSharedEvent with _$AchievementSharedEvent { const factory AchievementSharedEvent({required String elementTitle}) = _AchievementSharedEvent; factory AchievementSharedEvent.fromJson(Map json) => _$AchievementSharedEventFromJson(json); diff --git a/bccm_core/lib/src/models/analytics/audio_only_clicked.dart b/bccm_core/lib/src/models/analytics/audio_only_clicked.dart index 1b44ff9..27cc934 100644 --- a/bccm_core/lib/src/models/analytics/audio_only_clicked.dart +++ b/bccm_core/lib/src/models/analytics/audio_only_clicked.dart @@ -4,7 +4,7 @@ part 'audio_only_clicked.freezed.dart'; part 'audio_only_clicked.g.dart'; @freezed -class AudioOnlyClickedEvent with _$AudioOnlyClickedEvent { +abstract class AudioOnlyClickedEvent with _$AudioOnlyClickedEvent { const factory AudioOnlyClickedEvent({ required bool audioOnly, }) = _AudioOnlyClickedEvent; diff --git a/bccm_core/lib/src/models/analytics/calendar_day_clicked.dart b/bccm_core/lib/src/models/analytics/calendar_day_clicked.dart index 5d7ea4e..05dbb29 100644 --- a/bccm_core/lib/src/models/analytics/calendar_day_clicked.dart +++ b/bccm_core/lib/src/models/analytics/calendar_day_clicked.dart @@ -4,7 +4,7 @@ part 'calendar_day_clicked.freezed.dart'; part 'calendar_day_clicked.g.dart'; @freezed -class CalendarDayClickedEvent with _$CalendarDayClickedEvent { +abstract class CalendarDayClickedEvent with _$CalendarDayClickedEvent { const factory CalendarDayClickedEvent({ required String pageCode, required String calendarView, diff --git a/bccm_core/lib/src/models/analytics/chapter_clicked.dart b/bccm_core/lib/src/models/analytics/chapter_clicked.dart index 9b707ef..ab4967b 100644 --- a/bccm_core/lib/src/models/analytics/chapter_clicked.dart +++ b/bccm_core/lib/src/models/analytics/chapter_clicked.dart @@ -4,7 +4,7 @@ part 'chapter_clicked.freezed.dart'; part 'chapter_clicked.g.dart'; @freezed -class ChapterClickedEvent with _$ChapterClickedEvent { +abstract class ChapterClickedEvent with _$ChapterClickedEvent { const factory ChapterClickedEvent({ required String elementType, required String elementId, diff --git a/bccm_core/lib/src/models/analytics/content_shared.dart b/bccm_core/lib/src/models/analytics/content_shared.dart index 6aeb666..a6c496c 100644 --- a/bccm_core/lib/src/models/analytics/content_shared.dart +++ b/bccm_core/lib/src/models/analytics/content_shared.dart @@ -4,7 +4,7 @@ part 'content_shared.freezed.dart'; part 'content_shared.g.dart'; @freezed -class ContentSharedEvent with _$ContentSharedEvent { +abstract class ContentSharedEvent with _$ContentSharedEvent { const factory ContentSharedEvent({ required String pageCode, required String elementType, diff --git a/bccm_core/lib/src/models/analytics/deep_link_opened.dart b/bccm_core/lib/src/models/analytics/deep_link_opened.dart index e611075..8c13fb4 100644 --- a/bccm_core/lib/src/models/analytics/deep_link_opened.dart +++ b/bccm_core/lib/src/models/analytics/deep_link_opened.dart @@ -4,7 +4,7 @@ part 'deep_link_opened.freezed.dart'; part 'deep_link_opened.g.dart'; @freezed -class DeepLinkOpenedEvent with _$DeepLinkOpenedEvent { +abstract class DeepLinkOpenedEvent with _$DeepLinkOpenedEvent { const factory DeepLinkOpenedEvent({ required String url, required String source, diff --git a/bccm_core/lib/src/models/analytics/downloads.dart b/bccm_core/lib/src/models/analytics/downloads.dart index 074b8ad..fec05aa 100644 --- a/bccm_core/lib/src/models/analytics/downloads.dart +++ b/bccm_core/lib/src/models/analytics/downloads.dart @@ -4,7 +4,7 @@ part 'downloads.freezed.dart'; part 'downloads.g.dart'; @freezed -class VideoDownloadStartedEvent with _$VideoDownloadStartedEvent { +abstract class VideoDownloadStartedEvent with _$VideoDownloadStartedEvent { const factory VideoDownloadStartedEvent({ required String downloadId, required String episodeId, @@ -16,7 +16,7 @@ class VideoDownloadStartedEvent with _$VideoDownloadStartedEvent { } @freezed -class VideoDownloadRemovedEvent with _$VideoDownloadRemovedEvent { +abstract class VideoDownloadRemovedEvent with _$VideoDownloadRemovedEvent { const factory VideoDownloadRemovedEvent({ required String downloadId, required String? episodeId, @@ -26,7 +26,7 @@ class VideoDownloadRemovedEvent with _$VideoDownloadRemovedEvent { } @freezed -class VideoDownloadPlayedEvent with _$VideoDownloadPlayedEvent { +abstract class VideoDownloadPlayedEvent with _$VideoDownloadPlayedEvent { const factory VideoDownloadPlayedEvent({ required String downloadId, required String? episodeId, diff --git a/bccm_core/lib/src/models/analytics/game_closed.dart b/bccm_core/lib/src/models/analytics/game_closed.dart index 2f51339..f724bae 100644 --- a/bccm_core/lib/src/models/analytics/game_closed.dart +++ b/bccm_core/lib/src/models/analytics/game_closed.dart @@ -4,7 +4,7 @@ part 'game_closed.freezed.dart'; part 'game_closed.g.dart'; @freezed -class GameClosedEvent with _$GameClosedEvent { +abstract class GameClosedEvent with _$GameClosedEvent { const factory GameClosedEvent({ required String gameId, required int timeSpent, diff --git a/bccm_core/lib/src/models/analytics/language_changed.dart b/bccm_core/lib/src/models/analytics/language_changed.dart index e2fb3f1..46edfd7 100644 --- a/bccm_core/lib/src/models/analytics/language_changed.dart +++ b/bccm_core/lib/src/models/analytics/language_changed.dart @@ -4,7 +4,7 @@ part 'language_changed.freezed.dart'; part 'language_changed.g.dart'; @freezed -class LanguageChangedEvent with _$LanguageChangedEvent { +abstract class LanguageChangedEvent with _$LanguageChangedEvent { const factory LanguageChangedEvent({ required String? languageFrom, required String languageTo, diff --git a/bccm_core/lib/src/models/analytics/misc.dart b/bccm_core/lib/src/models/analytics/misc.dart index dbda0b8..921b5a9 100644 --- a/bccm_core/lib/src/models/analytics/misc.dart +++ b/bccm_core/lib/src/models/analytics/misc.dart @@ -4,7 +4,7 @@ part 'misc.freezed.dart'; part 'misc.g.dart'; @freezed -class InteractionEvent with _$InteractionEvent { +abstract class InteractionEvent with _$InteractionEvent { const factory InteractionEvent({ String? interaction, String? pageCode, @@ -17,7 +17,7 @@ class InteractionEvent with _$InteractionEvent { } @freezed -class ImpressionEvent with _$ImpressionEvent { +abstract class ImpressionEvent with _$ImpressionEvent { const factory ImpressionEvent({ String? name, String? pageCode, @@ -30,7 +30,7 @@ class ImpressionEvent with _$ImpressionEvent { } @freezed -class GuideShownEvent with _$GuideShownEvent { +abstract class GuideShownEvent with _$GuideShownEvent { const factory GuideShownEvent({ String? guide, Map? meta, @@ -40,7 +40,7 @@ class GuideShownEvent with _$GuideShownEvent { } @freezed -class TimeMeasurementEvent with _$TimeMeasurementEvent { +abstract class TimeMeasurementEvent with _$TimeMeasurementEvent { const factory TimeMeasurementEvent({ String? key, double? seconds, @@ -51,7 +51,7 @@ class TimeMeasurementEvent with _$TimeMeasurementEvent { } @freezed -class LogEvent with _$LogEvent { +abstract class LogEvent with _$LogEvent { const factory LogEvent({ String? name, String? message, @@ -63,7 +63,7 @@ class LogEvent with _$LogEvent { } @freezed -class VideoPlayedEvent with _$VideoPlayedEvent { +abstract class VideoPlayedEvent with _$VideoPlayedEvent { const factory VideoPlayedEvent({ String? videoId, String? referenceId, diff --git a/bccm_core/lib/src/models/analytics/notification_prompt.dart b/bccm_core/lib/src/models/analytics/notification_prompt.dart index a6946b7..2817714 100644 --- a/bccm_core/lib/src/models/analytics/notification_prompt.dart +++ b/bccm_core/lib/src/models/analytics/notification_prompt.dart @@ -4,7 +4,7 @@ part 'notification_prompt.freezed.dart'; part 'notification_prompt.g.dart'; @freezed -class NotificationPromptDismissedEvent with _$NotificationPromptDismissedEvent { +abstract class NotificationPromptDismissedEvent with _$NotificationPromptDismissedEvent { const factory NotificationPromptDismissedEvent({ required int timesDismissed, }) = _NotificationPromptDismissedEvent; @@ -13,25 +13,25 @@ class NotificationPromptDismissedEvent with _$NotificationPromptDismissedEvent { } @freezed -class NotificationPromptClickedEvent with _$NotificationPromptClickedEvent { +abstract class NotificationPromptClickedEvent with _$NotificationPromptClickedEvent { const factory NotificationPromptClickedEvent() = _NotificationPromptClickedEvent; factory NotificationPromptClickedEvent.fromJson(Map json) => _$NotificationPromptClickedEventFromJson(json); } @freezed -class NotificationPromptDeniedEvent with _$NotificationPromptDeniedEvent { +abstract class NotificationPromptDeniedEvent with _$NotificationPromptDeniedEvent { const factory NotificationPromptDeniedEvent() = _NotificationPromptDeniedEvent; factory NotificationPromptDeniedEvent.fromJson(Map json) => _$NotificationPromptDeniedEventFromJson(json); } @freezed -class NotificationPromptAcceptedEvent with _$NotificationPromptAcceptedEvent { +abstract class NotificationPromptAcceptedEvent with _$NotificationPromptAcceptedEvent { const factory NotificationPromptAcceptedEvent() = _NotificationPromptAcceptedEvent; factory NotificationPromptAcceptedEvent.fromJson(Map json) => _$NotificationPromptAcceptedEventFromJson(json); } @freezed -class NotificationsSettingToggledEvent with _$NotificationsSettingToggledEvent { +abstract class NotificationsSettingToggledEvent with _$NotificationsSettingToggledEvent { const factory NotificationsSettingToggledEvent({ required bool enabled, }) = _NotificationsSettingToggledEvent; diff --git a/bccm_core/lib/src/models/analytics/notifications.dart b/bccm_core/lib/src/models/analytics/notifications.dart index 9bdc833..f796a38 100644 --- a/bccm_core/lib/src/models/analytics/notifications.dart +++ b/bccm_core/lib/src/models/analytics/notifications.dart @@ -4,7 +4,7 @@ part 'notifications.freezed.dart'; part 'notifications.g.dart'; @freezed -class NotificationReceivedEvent with _$NotificationReceivedEvent { +abstract class NotificationReceivedEvent with _$NotificationReceivedEvent { const factory NotificationReceivedEvent({ String? notificationId, String? action, @@ -15,7 +15,7 @@ class NotificationReceivedEvent with _$NotificationReceivedEvent { } @freezed -class NotificationOpenedEvent with _$NotificationOpenedEvent { +abstract class NotificationOpenedEvent with _$NotificationOpenedEvent { const factory NotificationOpenedEvent({ String? notificationId, }) = _NotificationOpenedEvent; @@ -24,13 +24,13 @@ class NotificationOpenedEvent with _$NotificationOpenedEvent { } @freezed -class NotificationDeviceTokenUpdatedEvent with _$NotificationDeviceTokenUpdatedEvent { +abstract class NotificationDeviceTokenUpdatedEvent with _$NotificationDeviceTokenUpdatedEvent { const factory NotificationDeviceTokenUpdatedEvent() = _NotificationDeviceTokenUpdatedEvent; factory NotificationDeviceTokenUpdatedEvent.fromJson(Map json) => _$NotificationDeviceTokenUpdatedEventFromJson(json); } @freezed -class NotificationsStatusEvent with _$NotificationsStatusEvent { +abstract class NotificationsStatusEvent with _$NotificationsStatusEvent { const factory NotificationsStatusEvent({ String? recipientId, bool? enabled, diff --git a/bccm_core/lib/src/models/analytics/search_performed.dart b/bccm_core/lib/src/models/analytics/search_performed.dart index 3a5274e..285c4f6 100644 --- a/bccm_core/lib/src/models/analytics/search_performed.dart +++ b/bccm_core/lib/src/models/analytics/search_performed.dart @@ -4,7 +4,7 @@ part 'search_performed.freezed.dart'; part 'search_performed.g.dart'; @freezed -class SearchPerformedEvent with _$SearchPerformedEvent { +abstract class SearchPerformedEvent with _$SearchPerformedEvent { const factory SearchPerformedEvent({ required String searchText, required int searchLatency, diff --git a/bccm_core/lib/src/models/analytics/search_result_clicked.dart b/bccm_core/lib/src/models/analytics/search_result_clicked.dart index 3d63c98..6d32122 100644 --- a/bccm_core/lib/src/models/analytics/search_result_clicked.dart +++ b/bccm_core/lib/src/models/analytics/search_result_clicked.dart @@ -4,7 +4,7 @@ part 'search_result_clicked.freezed.dart'; part 'search_result_clicked.g.dart'; @freezed -class SearchResultClickedEvent with _$SearchResultClickedEvent { +abstract class SearchResultClickedEvent with _$SearchResultClickedEvent { const factory SearchResultClickedEvent({ required String searchText, required int elementPosition, @@ -17,14 +17,14 @@ class SearchResultClickedEvent with _$SearchResultClickedEvent { } @freezed -class SearchAnalytics with _$SearchAnalytics { +abstract class SearchAnalytics with _$SearchAnalytics { const factory SearchAnalytics({ required String searchText, }) = _SearchAnalytics; } @freezed -class SearchItemAnalytics with _$SearchItemAnalytics { +abstract class SearchItemAnalytics with _$SearchItemAnalytics { const factory SearchItemAnalytics({ required int position, required String type, diff --git a/bccm_core/lib/src/models/analytics/sections.dart b/bccm_core/lib/src/models/analytics/sections.dart index cd3916f..93196a2 100644 --- a/bccm_core/lib/src/models/analytics/sections.dart +++ b/bccm_core/lib/src/models/analytics/sections.dart @@ -6,7 +6,7 @@ part 'sections.freezed.dart'; part 'sections.g.dart'; @freezed -class SectionClickedEvent with _$SectionClickedEvent { +abstract class SectionClickedEvent with _$SectionClickedEvent { const factory SectionClickedEvent({ required String sectionId, String? sectionName, @@ -24,7 +24,7 @@ class SectionClickedEvent with _$SectionClickedEvent { } @freezed -class SectionAnalyticsData with _$SectionAnalyticsData { +abstract class SectionAnalyticsData with _$SectionAnalyticsData { const factory SectionAnalyticsData({ String? pageCode, required String id, @@ -36,7 +36,7 @@ class SectionAnalyticsData with _$SectionAnalyticsData { } @freezed -class SectionItemAnalyticsData with _$SectionItemAnalyticsData { +abstract class SectionItemAnalyticsData with _$SectionItemAnalyticsData { const factory SectionItemAnalyticsData({ required int position, required String type, diff --git a/bccm_core/lib/src/models/analytics/shorts.dart b/bccm_core/lib/src/models/analytics/shorts.dart index 270db86..c589014 100644 --- a/bccm_core/lib/src/models/analytics/shorts.dart +++ b/bccm_core/lib/src/models/analytics/shorts.dart @@ -4,7 +4,7 @@ part 'shorts.freezed.dart'; part 'shorts.g.dart'; @freezed -class ShortStartedEvent with _$ShortStartedEvent { +abstract class ShortStartedEvent with _$ShortStartedEvent { const factory ShortStartedEvent({ required String shortId, required String shortTitle, @@ -18,7 +18,7 @@ class ShortStartedEvent with _$ShortStartedEvent { } @freezed -class ShortStoppedEvent with _$ShortStoppedEvent { +abstract class ShortStoppedEvent with _$ShortStoppedEvent { const factory ShortStoppedEvent({ required String shortId, required String? shortTitle, diff --git a/bccm_core/lib/src/models/auth0/auth0_api.dart b/bccm_core/lib/src/models/auth0/auth0_api.dart index d68d0a8..1201bd7 100644 --- a/bccm_core/lib/src/models/auth0/auth0_api.dart +++ b/bccm_core/lib/src/models/auth0/auth0_api.dart @@ -6,7 +6,7 @@ part 'auth0_api.freezed.dart'; part 'auth0_api.g.dart'; @freezed -class Auth0SignupRequestBody with _$Auth0SignupRequestBody { +abstract class Auth0SignupRequestBody with _$Auth0SignupRequestBody { @JsonSerializable(includeIfNull: false, fieldRename: FieldRename.snake) factory Auth0SignupRequestBody({ required String clientId, @@ -26,7 +26,7 @@ class Auth0SignupRequestBody with _$Auth0SignupRequestBody { } @freezed -class Auth0SignupResponse with _$Auth0SignupResponse { +abstract class Auth0SignupResponse with _$Auth0SignupResponse { const factory Auth0SignupResponse({ // Named after the wire format on purpose. Renaming it to userId is a // one-line change here but forces every generated file in the package to be @@ -41,7 +41,7 @@ class Auth0SignupResponse with _$Auth0SignupResponse { } @freezed -class Auth0ApiException with _$Auth0ApiException implements Exception { +abstract class Auth0ApiException with _$Auth0ApiException implements Exception { const factory Auth0ApiException({ String? name, String? code, diff --git a/bccm_core/lib/src/models/auth_state.dart b/bccm_core/lib/src/models/auth_state.dart index cc45614..dd65ed3 100644 --- a/bccm_core/lib/src/models/auth_state.dart +++ b/bccm_core/lib/src/models/auth_state.dart @@ -4,7 +4,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'auth_state.freezed.dart'; @freezed -class AuthState with _$AuthState { +abstract class AuthState with _$AuthState { const AuthState._(); const factory AuthState({ diff --git a/bccm_core/lib/src/models/user_profile.dart b/bccm_core/lib/src/models/user_profile.dart index 991a8d2..c393f09 100644 --- a/bccm_core/lib/src/models/user_profile.dart +++ b/bccm_core/lib/src/models/user_profile.dart @@ -5,7 +5,7 @@ part 'user_profile.freezed.dart'; part 'user_profile.g.dart'; @freezed -class UserProfile with _$UserProfile { +abstract class UserProfile with _$UserProfile { const UserProfile._(); const factory UserProfile({ required String id,