Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Feat filter bookmarks saved entry handling #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
fulleni merged 8 commits into main from feat-filter-bookmarks-saved-entry-handling
Oct 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 1.0.0 - 2025εΉ΄10月13ζ—₯

* chore!: initial release under semantic versioning.
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter_news_app_api_server_full_source_code/src/database/migration.dart';
import 'package:logging/logging.dart';
import 'package:mongo_dart/mongo_dart.dart';

/// Migration to add the `savedFilters` field to existing
/// `user_content_preferences` documents.
class AddSavedFiltersToUserPreferences extends Migration {
/// {@macro add_saved_filters_to_user_preferences}
AddSavedFiltersToUserPreferences()
: super(
prDate: '20251013000056',
prId: '56',
prSummary: 'Add savedFilters field to user_content_preferences',
);

@override
Future<void> up(Db db, Logger log) async {
final collection = db.collection('user_content_preferences');
final result = await collection.updateMany(
// Filter for documents where 'savedFilters' does not exist.
where.notExists('savedFilters'),
// Set 'savedFilters' to an empty array.
modify.set('savedFilters', <dynamic>[]),
);
log.info(
'Updated ${result.nModified} documents in user_content_preferences.',
);
}

@override
Future<void> down(Db db, Logger log) async {
final collection = db.collection('user_content_preferences');
await collection.updateMany(
where.exists('savedFilters'),
modify.unset('savedFilters'),
);
log.info('Removed "savedFilters" field from user_content_preferences.');
}
}
6 changes: 4 additions & 2 deletions lib/src/database/migrations/all_migrations.dart
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import 'package:flutter_news_app_api_server_full_source_code/src/database/migration.dart';
import 'package:flutter_news_app_api_server_full_source_code/src/database/migrations/20250924084800__refactor_ad_config_to_role_based.dart';
import 'package:flutter_news_app_api_server_full_source_code/src/database/migrations/20251013000056_add_saved_filters_to_user_preferences.dart';
import 'package:flutter_news_app_api_server_full_source_code/src/services/database_migration_service.dart'
show DatabaseMigrationService;

/// A central list of all database migrations to be applied.
///
/// New migration classes should be added to this list. The
/// [DatabaseMigrationService] will automatically sort and apply them based on
/// their `prDate` property.
/// [DatabaseMigrationService] will automatically sort and apply them based
/// on their `prDate` property.
final List<Migration> allMigrations = [
RefactorAdConfigToRoleBased(),
AddSavedFiltersToUserPreferences(),
];
1 change: 1 addition & 0 deletions lib/src/services/auth_service.dart
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ class AuthService {
followedSources: const [],
followedTopics: const [],
savedHeadlines: const [],
savedFilters: const [],
);
await _userContentPreferencesRepository.create(
item: defaultUserPreferences,
Expand Down
1 change: 1 addition & 0 deletions lib/src/services/database_seeding_service.dart
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ class DatabaseSeedingService {
followedSources: const [],
followedTopics: const [],
savedHeadlines: const [],
savedFilters: const [],
);
await _db.collection('user_content_preferences').insertOne({
'_id': userId,
Expand Down
32 changes: 26 additions & 6 deletions lib/src/services/default_user_preference_limit_service.dart
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,28 @@ class DefaultUserPreferenceLimitService implements UserPreferenceLimitService {
// 2. Determine the limit based on the user's app role.
int limit;
String accountType;
final isFollowedItem =
itemType == 'country' || itemType == 'source' || itemType == 'topic';

switch (user.appRole) {
case AppUserRole.premiumUser:
accountType = 'premium';
limit = (itemType == 'headline')
? limits.premiumSavedHeadlinesLimit
: limits.premiumFollowedItemsLimit;
if (isFollowedItem) {
limit = limits.premiumFollowedItemsLimit;
} else if (itemType == 'headline') {
limit = limits.premiumSavedHeadlinesLimit;
} else {
limit = limits.premiumSavedFiltersLimit;
}
case AppUserRole.standardUser:
accountType = 'standard';
limit = (itemType == 'headline')
? limits.authenticatedSavedHeadlinesLimit
: limits.authenticatedFollowedItemsLimit;
if (isFollowedItem) {
limit = limits.authenticatedFollowedItemsLimit;
} else if (itemType == 'headline') {
limit = limits.authenticatedSavedHeadlinesLimit;
} else {
limit = limits.authenticatedSavedFiltersLimit;
}
case AppUserRole.guestUser:
accountType = 'guest';
limit = (itemType == 'headline')
Expand Down Expand Up @@ -113,21 +123,25 @@ class DefaultUserPreferenceLimitService implements UserPreferenceLimitService {
// 2. Determine limits based on the user's app role.
int followedItemsLimit;
int savedHeadlinesLimit;
int savedFiltersLimit;
String accountType;

switch (user.appRole) {
case AppUserRole.premiumUser:
accountType = 'premium';
followedItemsLimit = limits.premiumFollowedItemsLimit;
savedHeadlinesLimit = limits.premiumSavedHeadlinesLimit;
savedFiltersLimit = limits.premiumSavedFiltersLimit;
case AppUserRole.standardUser:
accountType = 'standard';
followedItemsLimit = limits.authenticatedFollowedItemsLimit;
savedHeadlinesLimit = limits.authenticatedSavedHeadlinesLimit;
savedFiltersLimit = limits.authenticatedSavedFiltersLimit;
case AppUserRole.guestUser:
accountType = 'guest';
followedItemsLimit = limits.guestFollowedItemsLimit;
savedHeadlinesLimit = limits.guestSavedHeadlinesLimit;
savedFiltersLimit = limits.guestSavedFiltersLimit;
}

// 3. Check if proposed preferences exceed limits
Expand Down Expand Up @@ -155,6 +169,12 @@ class DefaultUserPreferenceLimitService implements UserPreferenceLimitService {
'for your account type ($accountType).',
);
}
if (updatedPreferences.savedFilters.length > savedFiltersLimit) {
throw ForbiddenException(
'You have reached the maximum number of saved filters allowed '
'for your account type ($accountType).',
);
}
} on HttpException {
// Propagate known exceptions from repositories
rethrow;
Expand Down
34 changes: 17 additions & 17 deletions pubspec.lock
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "828b984517edec069266579c624c7af9fbe0e2ac"
resolved-ref: "828b984517edec069266579c624c7af9fbe0e2ac"
ref: "v1.2.0"
resolved-ref: d052799c1ebb7bcdd1a725a2a7919948c14fa001
url: "https://github.com/flutter-news-app-full-source-code/core.git"
source: git
version: "0.0.0"
version: "1.2.0"
coverage:
dependency: transitive
description:
Expand Down Expand Up @@ -158,26 +158,26 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "960a00882045ee252274d9d57bfca606c1fe5d64"
resolved-ref: "960a00882045ee252274d9d57bfca606c1fe5d64"
ref: "v1.0.0"
resolved-ref: b9a8a8c2c660928c22f2d38d657000bcae4c74d6
url: "https://github.com/flutter-news-app-full-source-code/data-client.git"
source: git
version: "0.0.0"
data_mongodb:
dependency: "direct main"
description:
path: "."
ref: ee2ace6243f1ad4710c192c36215d3ce9e91c7a3
resolved-ref: ee2ace6243f1ad4710c192c36215d3ce9e91c7a3
ref: "v1.0.0"
resolved-ref: f55b686acdbc0af9c617df4833733a07f9208b57
url: "https://github.com/flutter-news-app-full-source-code/data-mongodb.git"
source: git
version: "0.0.0"
data_repository:
dependency: "direct main"
description:
path: "."
ref: f8f01f1191286efbba41fa2bb369fb16eb652ccf
resolved-ref: f8f01f1191286efbba41fa2bb369fb16eb652ccf
ref: "v1.0.0"
resolved-ref: "7f9242d810d60fefd2f883b19e1650e8e4eb41a3"
url: "https://github.com/flutter-news-app-full-source-code/data-repository.git"
source: git
version: "0.0.0"
Expand Down Expand Up @@ -225,26 +225,26 @@ packages:
dependency: "direct main"
description:
path: "."
ref: c5e36d06b58918056dde4a58d177a39fb66bfe24
resolved-ref: c5e36d06b58918056dde4a58d177a39fb66bfe24
ref: "v1.0.0"
resolved-ref: "31faf0e429aeea519204dfdd26afdba36ea1d8dc"
url: "https://github.com/flutter-news-app-full-source-code/email-client.git"
source: git
version: "0.0.0"
email_repository:
dependency: "direct main"
description:
path: "."
ref: a68acd99c37b844af4eb3ed9f2eb9fd494c57f73
resolved-ref: a68acd99c37b844af4eb3ed9f2eb9fd494c57f73
ref: "v1.0.0"
resolved-ref: "2be152f3c48acd35d0a79a01d7258a4e8e8ab399"
url: "https://github.com/flutter-news-app-full-source-code/email-repository.git"
source: git
version: "0.0.0"
email_sendgrid:
dependency: "direct main"
description:
path: "."
ref: "4cd256b1a65a648db2519d8b26b4e9174d4d3a0c"
resolved-ref: "4cd256b1a65a648db2519d8b26b4e9174d4d3a0c"
ref: "v1.0.0"
resolved-ref: f28572a0c0598348391df7701a205249f2454031
url: "https://github.com/flutter-news-app-full-source-code/email-sendgrid.git"
source: git
version: "0.0.0"
Expand Down Expand Up @@ -316,8 +316,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "57f6bcfc0f209ecc135fdcb688194045ec87e6e8"
resolved-ref: "57f6bcfc0f209ecc135fdcb688194045ec87e6e8"
ref: "v1.0.1"
resolved-ref: ce550196f78ee2e95aa9e985759179265983689d
url: "https://github.com/flutter-news-app-full-source-code/http-client.git"
source: git
version: "0.0.0"
Expand Down
17 changes: 9 additions & 8 deletions pubspec.yaml
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: flutter_news_app_api_server_full_source_code
description: The complete backend API server for the Flutter News App Toolkit, built with Dart Frog. Powers authentication, data management, user settings, and more.
repository: https://github.com/flutter-news-app-full-source-code/flutter-news-app-api-server-full-source-code
publish_to: none
version: 1.0.0

environment:
sdk: ^3.9.0
Expand All @@ -11,38 +12,38 @@ dependencies:
core:
git:
url: https://github.com/flutter-news-app-full-source-code/core.git
ref: 828b984517edec069266579c624c7af9fbe0e2ac
ref: v1.2.0
dart_frog: ^1.1.0
dart_jsonwebtoken: ^3.2.0
data_client:
git:
url: https://github.com/flutter-news-app-full-source-code/data-client.git
ref: 960a00882045ee252274d9d57bfca606c1fe5d64
ref: v1.0.0
data_mongodb:
git:
url: https://github.com/flutter-news-app-full-source-code/data-mongodb.git
ref: ee2ace6243f1ad4710c192c36215d3ce9e91c7a3
ref: v1.0.0
data_repository:
git:
url: https://github.com/flutter-news-app-full-source-code/data-repository.git
ref: f8f01f1191286efbba41fa2bb369fb16eb652ccf
ref: v1.0.0
dotenv: ^4.2.0
email_client:
git:
url: https://github.com/flutter-news-app-full-source-code/email-client.git
ref: c5e36d06b58918056dde4a58d177a39fb66bfe24
ref: v1.0.0
email_repository:
git:
url: https://github.com/flutter-news-app-full-source-code/email-repository.git
ref: a68acd99c37b844af4eb3ed9f2eb9fd494c57f73
ref: v1.0.0
email_sendgrid:
git:
url: https://github.com/flutter-news-app-full-source-code/email-sendgrid.git
ref: 4cd256b1a65a648db2519d8b26b4e9174d4d3a0c
ref: v1.0.0
http_client:
git:
url: https://github.com/flutter-news-app-full-source-code/http-client.git
ref: 57f6bcfc0f209ecc135fdcb688194045ec87e6e8
ref: v1.0.1
json_annotation: ^4.9.0
logging: ^1.3.0
meta: ^1.16.0
Expand Down
Loading

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /