Skip to content
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
57 changes: 29 additions & 28 deletions docs/core/core-module.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,53 @@
# Core Module

The **core** package provides foundational building blocks shared across AppToolkit features. It offers base domain models, UI abstractions, utility helpers and dependency injection qualifiers used throughout the library.
The **core** package provides building blocks shared across the app. It offers domain models, ViewModel classes, utility helpers and dependency injection qualifiers used throughout the project.

## Packages

### domain
Defines reusable result wrappers and UI state models, plus base use case interfaces for repositories and operations.
Houses use case classes and other business logic that operate on repositories.

### ui
Hosts composable components and base classes like `ScreenViewModel` and `DefaultSnackbarHost` that standardize screen state handling and Snackbar presentation.
Contains Activities, Fragments and ViewModels such as `MainViewModel`.

### utils
Includes helpers, extensions, constants and `DispatcherProvider` to access standard `CoroutineDispatcher` instances.
Provides helpers like `OpenSourceLicensesUtils`, `ReviewHelper` and `EdgeToEdgeDelegate`.

### di
Contains qualifiers such as `GithubToken` to assist dependency injection frameworks.
Contains Hilt modules and qualifiers for dependency injection.

## Usage examples

### ScreenViewModel
```kotlin
class ExampleViewModel : ScreenViewModel<UiScreen, ExampleEvent, ExampleAction>(
initialState = UiStateScreen(data = UiScreen())
) {
// handle events
### ViewModel
```java
public class MainViewModel extends ViewModel {
private final ShouldShowStartupScreenUseCase shouldShowStartupScreenUseCase;

public MainViewModel(ShouldShowStartupScreenUseCase shouldShowStartupScreenUseCase) {
this.shouldShowStartupScreenUseCase = shouldShowStartupScreenUseCase;
}

public boolean shouldShowStartupScreen() {
return shouldShowStartupScreenUseCase.invoke();
}
}
```

### DefaultSnackbarHost
```kotlin
val snackbarHostState = remember { SnackbarHostState() }

Scaffold(
snackbarHost = { DefaultSnackbarHost(snackbarState = snackbarHostState) }
) { /* screen content */ }
### Snackbar helper
```java
Snackbar.make(view, "Message", Snackbar.LENGTH_SHORT).show();
```

### DispatcherProvider
```kotlin
class ExampleRepository(private val dispatchers: DispatcherProvider) {
suspend fun load() = withContext(dispatchers.io) {
/* blocking work */
}
}
### ReviewHelper
```java
ReviewHelper.launchInAppReviewIfEligible(activity, sessionCount, hasPromptedBefore, () -> {
// callback when review flow finishes
});
```

## See also

- [[Library]] – overview of all modules and features.
- [[Issue-Reporter-Module]] – demonstrates use of `ScreenViewModel` and networking helpers.
- [[Support-Module]] – integrates `DispatcherProvider` for billing and donation flows.
- [[Architecture]] – overview of app layers.
- [[Data Layer]] – repository and data source details.
- [[UI Components]] – common reusable views.

86 changes: 62 additions & 24 deletions docs/core/data-layer.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,80 @@
# Data Layer

This page outlines the data-related building blocks provided by AppToolkit.
This page outlines how the app manages and persists data.

## HTTP client
## Repositories

`apptoolkit/data/client` exposes **KtorClient**, a factory for a preconfigured Ktor `HttpClient`. It installs JSON content negotiation, request timeouts, default headers and optional logging so callers only need to supply their own endpoints.
Repositories expose data to the rest of the app and hide the underlying storage.

### Setup

```kotlin
val client = KtorClient().createClient(enableLogging = true)
```java
public interface MainRepository {
boolean shouldShowStartupScreen();
void markStartupScreenShown();
}
```

## DataStore

The `apptoolkit/data/datastore` package wraps Android DataStore in a singleton `CommonDataStore`. It centralizes preferences such as startup flags, theme options and user consents, exposing them as Kotlin `Flow`s with suspend functions to persist updates.
`DefaultMainRepository` implements these methods using `SharedPreferences`:

### Usage
```java
public class DefaultMainRepository implements MainRepository {
private final Context context;

```kotlin
val dataStore = CommonDataStore.getInstance(context)
public DefaultMainRepository(Context context) {
this.context = context.getApplicationContext();
}

// Observe a value
val adsEnabled = dataStore.ads(default = true)
@Override
public boolean shouldShowStartupScreen() {
SharedPreferences startup = context.getSharedPreferences("startup", Context.MODE_PRIVATE);
return startup.getBoolean("value", true);
}

// Save a value
scope.launch { dataStore.saveThemeMode("dark") }
@Override
public void markStartupScreenShown() {
SharedPreferences startup = context.getSharedPreferences("startup", Context.MODE_PRIVATE);
startup.edit().putBoolean("value", false).apply();
}
}
```

## Ads
## Data sources

Remote and local sources supply the repositories with data. For example, `DefaultHomeRemoteDataSource` uses Volley to fetch promoted apps:

```java
public class DefaultHomeRemoteDataSource implements HomeRemoteDataSource {
private final RequestQueue requestQueue;
private final String apiUrl;

public DefaultHomeRemoteDataSource(RequestQueue requestQueue, String apiUrl) {
this.requestQueue = requestQueue;
this.apiUrl = apiUrl;
}

@Override
public void fetchPromotedApps(PromotedAppsCallback callback) {
JsonObjectRequest request = new JsonObjectRequest(
Request.Method.GET,
apiUrl,
null,
response -> { /* parse and callback */ },
error -> { /* handle error */ }
);
requestQueue.add(request);
}
}
```

Ads are configured through preferences in `CommonDataStore` via the `ads` flag and related consent entries. The `core/ads` package provides `AdsCoreManager`, which checks those preferences before initializing Google Mobile Ads and manages app-open ad loading and display.
## Models

Use `AdsCoreManager` when the application should show an app-open ad on start or resume:
Model classes like `PromotedApp` encapsulate the data returned by the layer:

```kotlin
val adsManager = AdsCoreManager(context, buildInfoProvider)
scope.launch { adsManager.initializeAds("ca-app-pub-xxxxxxxxxxxxxxxx/xxxxxxxxxx") }
adsManager.showAdIfAvailable(activity, scope)
```java
public record PromotedApp(String name, String packageName, String iconUrl) {}
```

## See also

- [[Architecture]] – overview of app layers.
- [[Core Module]] – shared utilities and components.

Loading