Skip to content

Commit ed24227

Browse files
committed
refactor(README): restructure user engagement section and improve notification details
- Moved user engagement and notification content to a new section - Enhanced details on notification engine capabilities and advantages - Improved architecture and infrastructure section formatting - Added business logic check for AppReview creation to ensure unique review per user
1 parent 6d6864f commit ed24227

File tree

2 files changed

+43
-25
lines changed

2 files changed

+43
-25
lines changed

README.md

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,6 @@ The API automatically validates the structure of all incoming data, ensuring tha
7272
> **Your Advantage:** This eliminates an entire class of runtime errors and saves you from writing tedious, repetitive validation code. Your data models remain consistent and your API stays resilient against malformed requests.
7373
7474
---
75-
76-
### 📲 Dynamic & Personalized Notifications
77-
A complete, multi-provider notification engine that empowers you to engage users with timely and relevant alerts, seamlessly integrated into their app experience.
78-
- **Editorial-Driven Alerts:** Any piece of content can be designated as "breaking news" from the content dashboard, triggering immediate, high-priority push notifications that are also captured in each user's in-app notification center.
79-
- **User-Crafted Notification Streams:** Users can create and save persistent **Saved Headline Filters** based on any combination of content filters (such as topics, sources, or regions). They can then subscribe to notifications for that filter, receiving alerts only for the news they care about.
80-
- **Flexible Delivery Mechanisms:** The system is architected to support multiple notification types for each subscription, from immediate alerts to scheduled daily or weekly digests.
81-
- **Provider Agnostic:** The engine is built to be provider-agnostic, with out-of-the-box support for Firebase (FCM) and OneSignal. The active provider can be switched remotely without any code changes.
82-
- **Intelligent, Self-Healing Delivery:** The notification engine is designed for long-term reliability. It automatically detects and prunes invalid device tokens—for example, when a user uninstalls the app—ensuring the system remains efficient and notifications are only sent to active devices.
83-
> **Your Advantage:** You get a complete, secure, and scalable notification system that enhances user engagement and can be managed entirely from the web dashboard.
84-
85-
</details>
86-
87-
<details>
88-
<summary><strong>🏗️ Architecture & Infrastructure</strong></summary>
89-
90-
### 🚀 High-Performance by Design
91-
Built on a modern, minimalist foundation to ensure low latency and excellent performance.
9275
- **Dart Frog Core:** Leverages the high-performance Dart Frog framework for a fast, efficient, and scalable backend.
9376
- **Clean, Layered Architecture:** A strict separation of concerns into distinct layers makes the codebase clean, maintainable, and easy to reason about.
9477
> **Your Advantage:** Your backend is built on a solid, modern foundation that is both powerful and a pleasure to work with, reducing maintenance overhead.
@@ -110,6 +93,26 @@ Say goodbye to risky manual database updates. A professional, versioned migratio
11093
11194
</details>
11295

96+
<details>
97+
<summary><strong>📲 User Engagement & Notifications</strong></summary>
98+
99+
### 🔔 A Dynamic, Multi-Channel Notification Engine
100+
A complete, multi-provider notification engine empowers you to engage users with timely and relevant alerts, seamlessly integrated into their app experience.
101+
- **Editorial-Driven Alerts:** Designate any content as "breaking news" from the dashboard to trigger immediate, high-priority push notifications to all relevant subscribers.
102+
- **User-Crafted Notification Streams:** Allow users to create and save persistent filters based on any combination of content attributes (such as topics or sources) and subscribe to receive notifications that match their exact interests.
103+
- **Centralized In-App Inbox:** Every push notification is automatically captured as a persistent in-app message, giving users a central place to catch up on alerts they may have missed.
104+
- **Provider Agnostic & Scalable:** The engine is built to be provider-agnostic, with out-of-the-box support for Firebase (FCM) and OneSignal. The active provider can be switched remotely without any code changes.
105+
- **Intelligent, Self-Healing Delivery:** The system is designed for long-term efficiency. It automatically detects and prunes invalid device tokens—for example, when a user uninstalls the app—ensuring your delivery infrastructure remains clean and performant.
106+
> **Your Advantage:** Drive user re-engagement with a powerful and flexible notification system that delivers both broad-reaching alerts and deeply personalized content streams, all built on a scalable, self-healing, and provider-agnostic architecture.
107+
108+
</details>
109+
110+
<details>
111+
<summary><strong>🏗️ Architecture & Infrastructure</strong></summary>
112+
113+
### 🚀 High-Performance by Design
114+
Built on a modern, minimalist foundation to ensure low latency and excellent performance.
115+
113116
## 🔑 Licensing
114117
This `Flutter News App API Server` package is an integral part of the [**Flutter News App Full Source Code Toolkit**](https://github.com/flutter-news-app-full-source-code). For comprehensive details regarding licensing, including trial and commercial options for the entire toolkit, please refer to the main toolkit organization page.
115118

lib/src/registry/data_operation_registry.dart

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,11 @@ class DataOperationRegistry {
212212
),
213213
'app_review': (c, uid, f, s, p) =>
214214
c.read<DataRepository<AppReview>>().readAll(
215-
userId: uid,
216-
filter: f,
217-
sort: s,
218-
pagination: p,
219-
),
215+
userId: uid,
216+
filter: f,
217+
sort: s,
218+
pagination: p,
219+
),
220220
});
221221

222222
// --- Register Item Creators ---
@@ -361,6 +361,21 @@ class DataOperationRegistry {
361361
);
362362
}
363363

364+
// Business Logic Check: Ensure a user can only have one AppReview record.
365+
// This prevents creating multiple feedback entries, adhering to the
366+
// intended "create once, update later" workflow.
367+
final appReviewRepository = context.read<DataRepository<AppReview>>();
368+
final existingReviews = await appReviewRepository.readAll(
369+
filter: {'userId': authenticatedUser.id},
370+
);
371+
372+
if (existingReviews.items.isNotEmpty) {
373+
_log.warning(
374+
'User ${authenticatedUser.id} attempted to create a second AppReview record.',
375+
);
376+
throw const ConflictException('An app review record already exists.');
377+
}
378+
364379
return context.read<DataRepository<AppReview>>().create(item: item);
365380
},
366381
});
@@ -534,9 +549,9 @@ class DataOperationRegistry {
534549
),
535550
'app_review': (c, id, item, uid) =>
536551
c.read<DataRepository<AppReview>>().update(
537-
id: id,
538-
item: item as AppReview,
539-
),
552+
id: id,
553+
item: item as AppReview,
554+
),
540555
});
541556

542557
// --- Register Item Deleters ---

0 commit comments

Comments
 (0)