Skip to content

Commit e3906bc

Browse files
authored
Merge pull request #16 from flutter-news-app-full-source-code/sync-mobiel-client-docs
Sync mobiel client docs
2 parents 8708fe5 + 3574f5b commit e3906bc

File tree

6 files changed

+61
-7
lines changed

6 files changed

+61
-7
lines changed

astro.config.mjs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,10 @@ export default defineConfig({
161161
{ label: 'Overview', link: '/mobile-client/features/' },
162162
{ label: 'Account', link: '/mobile-client/features/account' },
163163
{ label: 'Authentication', link: '/mobile-client/features/authentication' },
164-
{ label: 'Entity Details', link: '/mobile-client/features/entity-details' },
165-
{ label: 'Headline Details', link: '/mobile-client/features/headline-details' },
164+
{ label: 'Ad System', link: '/mobile-client/features/ad-system' },
166165
{ label: 'Headlines Feed', link: '/mobile-client/features/headlines-feed' },
166+
{ label: 'Headline Details', link: '/mobile-client/features/headline-details' },
167+
{ label: 'Entity Details', link: '/mobile-client/features/entity-details' },
167168
{ label: 'Search', link: '/mobile-client/features/search' },
168169
{ label: 'Settings', link: '/mobile-client/features/settings' },
169170
{ label: 'Status Pages', link: '/mobile-client/features/status-pages' },

src/content/docs/mobile-client/architecture/routing.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The mobile client employs a sophisticated, multi-path startup sequence to handle
1111
The startup logic is orchestrated by the `AppBloc` and the root `_AppView` widget. The path the user experiences depends on their initial authentication status.
1212

1313
<Aside>
14-
A key architectural decision is that the **Remote Configuration API requires authentication**. This means the app must first establish a user session (even an anonymous one) before it can check for maintenance mode or required updates.
14+
A key architectural decision is that the **Remote Configuration API requires authentication**. This means the app must first establish a user session (even an anonymous one) before it can check for maintenance mode or required updates. This pre-flight check is crucial for the app's stability and security.
1515
</Aside>
1616

1717
### Path 1: New or Logged-Out User
@@ -27,11 +27,11 @@ In this scenario, the user is taken directly to the sign-in screen without any i
2727

2828
### Path 2: Existing User (Authenticated or Anonymous)
2929

30-
This flow handles users who already have an active session.
30+
This flow handles users who already have an active session, ensuring stability by performing critical checks before rendering the main UI.
3131

3232
1. **Auth Check**: On startup, the `AppBloc` finds an existing user session.
3333
2. **Initial State**: The `AppBloc` emits the corresponding status (`authenticated` or `anonymous`) and immediately dispatches an `AppConfigFetchRequested` event.
34-
3. **Pre-Router Status Pages**: The `_onAppConfigFetchRequested` handler sets the state to `AppStatus.configFetching`. The `_AppView` widget detects this critical status and displays a full-screen `StatusPage` *before* building the main router. This pre-flight check handles several possibilities:
34+
3. **Pre-Router Status Pages**: The `_onAppConfigFetchRequested` handler sets the state to `AppStatus.configFetching`. The `_AppView` widget detects this critical status and displays a full-screen `StatusPage` *before* building the main router. This stable startup sequence is critical and handles several possibilities:
3535
- **Loading**: A `StatusPage` with a loading indicator is shown.
3636
- **Failure**: If the config fetch fails, the `StatusPage` shows a retry button.
3737
- **Maintenance/Update**: If the config dictates, a `MaintenancePage` or `UpdateRequiredPage` is shown.

src/content/docs/mobile-client/architecture/state-management.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { Aside } from '@astrojs/starlight/components';
66

77
The mobile client uses the **BLoC (Business Logic Component)** pattern for state management. This pattern helps to separate the presentation layer from the business logic, making the application more structured, testable, and maintainable.
88

9+
While most features have their own dedicated BLoC, the most important one is the global `AppBloc`, which manages the application's core state, including user authentication, settings, and the overall application status (`AppStatus`).
10+
911
Every feature in the application that requires managing state has its own BLoC.
1012

1113
### The Core Components of BLoC
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: 'Feature: Ad System'
3+
description: Learn about the provider-agnostic ad system for monetization.
4+
---
5+
import { Card, CardGrid, Aside } from '@astrojs/starlight/components';
6+
7+
The mobile client includes a sophisticated, provider-agnostic ad system designed for monetization while ensuring architectural stability and a smooth user experience.
8+
9+
## Core Architecture
10+
11+
The ad system is built on a decoupled architecture that avoids tying the application to a single ad network SDK.
12+
13+
<CardGrid>
14+
<Card title="Provider-Agnostic Design" icon="interoperability">
15+
The system uses a generic `NativeAd` model and an abstract `AdProvider` interface. This allows the application to use different ad networks by creating a new implementation of the `AdProvider`. The initial implementation is for **Google AdMob**.
16+
</Card>
17+
<Card title="Lifecycle Management" icon="lifecycle">
18+
A critical challenge with native ad SDKs is managing the lifecycle of ad objects, which can lead to crashes if not handled correctly. This system solves this by managing ad objects within a `StatefulWidget` (`AdmobNativeAdWidget`) and a central `AdCacheService`, preventing premature disposal of ads that are scrolled off-screen.
19+
</Card>
20+
<Card title="Performance via Caching" icon="cache">
21+
The `AdCacheService` acts as a singleton that stores loaded native ads. When an ad slot scrolls into view, the app first checks the cache. This prevents redundant network requests, leading to smoother scrolling and reduced data usage. The cache is strategically cleared on major content refreshes to ensure ad relevance.
22+
</Card>
23+
<Card title="Platform Safety" icon="shield">
24+
On platforms where native ad SDKs are not supported (like web), a `NoOpAdProvider` is used. This provider renders a visual placeholder instead of a real ad, which prevents `MissingPluginException` crashes at startup and allows for consistent UI testing across all platforms.
25+
</Card>
26+
</CardGrid>
27+
28+
## Integration with the Feed
29+
30+
The ad system is seamlessly integrated into any scrollable list of content, such as the main headlines feed or entity details pages.
31+
32+
- **`FeedDecoratorService`**: This service is responsible for injecting `AdPlaceholder` objects into the feed's content list based on rules defined in the `RemoteConfig`. These placeholders are simple, stateless markers indicating where an ad should appear.
33+
34+
- **`AdLoaderWidget`**: This `StatefulWidget` is rendered when an `AdPlaceholder` is in the list. It contains the logic to:
35+
1. Check the `AdCacheService` for a cached ad corresponding to the placeholder's ID.
36+
2. If no ad is cached, it requests a new one from the `AdService`.
37+
3. It manages its own loading and error states, displaying a shimmer while loading or a placeholder on failure.
38+
4. Once an ad is loaded, it is stored in the cache and displayed.
39+
40+
- **Theme & Format Aware Ads**: The `AdService` requests ads with theme-aware styling (`AdThemeStyle`) and the correct template size (`HeadlineImageStyle`). This ensures that ads match the user's current theme (light/dark mode) and the visual density of the surrounding content.
41+
42+
This architecture ensures that the complex, stateful logic of ad loading is encapsulated at the widget level, keeping the BLoC layer clean and focused on managing the primary content.

src/content/docs/mobile-client/features/authentication.mdx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The mobile client features a robust authentication system that supports both ema
88

99
## The Authentication Flow
1010

11-
The authentication flow is designed to be simple and secure, using a passwordless email and code verification system.
11+
The authentication flow is designed to be simple and secure, using a passwordless email and code verification system. It also includes user-friendly improvements for a smoother experience.
1212

1313
<Steps>
1414
1. **Choose Sign-In Method**
@@ -21,7 +21,7 @@ The authentication flow is designed to be simple and secure, using a passwordles
2121

2222
3. **Verify Code**
2323

24-
After a code is sent, the user is taken to the `EmailCodeVerificationPage`. They enter the 6-digit code they received. The `AuthenticationBloc` processes an `AuthenticationVerifyCodeRequested` event, which calls the `AuthRepository` to verify the code.
24+
After a code is sent, the user is taken to the `EmailCodeVerificationPage`. They enter the 6-digit code they received into an improved code entry field powered by the `pinput` widget. The `AuthenticationBloc` processes an `AuthenticationVerifyCodeRequested` event, which calls the `AuthRepository` to verify the code.
2525

2626
4. **Authenticated State**
2727

@@ -32,6 +32,11 @@ The authentication flow is designed to be simple and secure, using a passwordles
3232

3333
The app also supports an anonymous sign-in flow. When the user chooses to continue anonymously, the `AuthenticationBloc` dispatches an `AuthenticationAnonymousSignInRequested` event. The `AuthRepository` creates a new anonymous user, and the `AppBloc` transitions to a special `anonymous` state. This allows guest users to browse content with certain limitations, and they can choose to link their account to a permanent email address at any time.
3434

35+
## Security and UX Enhancements
36+
37+
- **Request Cooldown**: To prevent abuse of the email service, a 60-second cooldown is enforced between sign-in code requests. The UI provides a visual countdown timer, informing the user when they can request a new code.
38+
- **Enhanced Code Input**: The code verification screen uses the `pinput` widget to provide a more polished and user-friendly experience for entering the 6-digit code.
39+
3540
## Core Components
3641

3742
- **`AuthenticationBloc`**: Located in `lib/authentication/bloc/`, this BLoC orchestrates the entire authentication process. It listens to events from the UI, interacts with the `AuthRepository`, and emits states that reflect the current status of the authentication flow (e.g., `loading`, `failure`, `requestCodeSuccess`).

src/content/docs/mobile-client/features/index.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,8 @@ The mobile client is packed with features designed for a modern, engaging news a
3636
Learn how users can customize the application's appearance, language, and feed display.
3737
[Read more &rarr;](/docs/mobile-client/features/settings/)
3838
</Card>
39+
<Card title="Ad System" icon="money">
40+
Learn about the provider-agnostic ad system for monetization.
41+
[Read more &rarr;](/docs/mobile-client/features/ad-system/)
42+
</Card>
3943
</CardGrid>

0 commit comments

Comments
 (0)