Feature: Dictionary Overview Screen
Relevant source files
The following files were used as context for generating this wiki page:- app/src/main/java/com/vocabri/ui/screens/dictionary/DictionaryScreen.kt
- app/src/main/java/com/vocabri/ui/screens/dictionary/viewmodel/DictionaryViewModel.kt
- app/src/main/java/com/vocabri/di/AppModule.kt
- app/src/main/java/com/vocabri/ui/navigation/AppNavigation.kt
- app/src/test/java/com/vocabri/ui/dictionary/DictionaryViewModelTest.kt
- app/src/main/res/values/strings.xml
- app/src/main/java/com/vocabri/ui/screens/dictionarydetails/DictionaryDetailsScreen.kt
The Dictionary Overview Screen serves as the main entry point for users to browse their personal vocabulary. It presents a summarized view of all saved words, categorized by their part of speech. This screen allows users to see a high-level breakdown of their dictionary and navigate to more detailed views for each category. The architecture is reactive, utilizing Jetpack Compose for the UI, a ViewModel for state management, and Kotlin Flows for data observation.
Architecture Overview
The feature follows a standard MVVM (Model-View-ViewModel) pattern. The UI layer, implemented with Jetpack Compose, observes a state flow from the DictionaryViewModel. The ViewModel, in turn, orchestrates data retrieval by invoking a use case, which interacts with the repository layer to fetch word groups from the local database.
This diagram illustrates the dependency flow between the key components of the Dictionary Overview screen.
UI Layer (DictionaryScreen.kt)
The user interface is built entirely with Jetpack Compose. The main entry point is the DictionaryScreen composable, which obtains an instance of DictionaryViewModel via Koin and observes its state.
Sources: app/src/main/java/com/vocabri/ui/screens/dictionary/DictionaryScreen.kt:68-72
State Handling
The DictionaryScreenRoot composable is responsible for rendering the UI based on the current DictionaryState exposed by the ViewModel. This ensures a clear separation between state logic and UI representation.
| State | UI Representation |
|---|---|
Loading | Displays a set of shimmering skeleton loaders to indicate data is being fetched. |
Empty | Shows a message "The dictionary is empty. Add your first word!" and a button to add a new word. |
GroupsLoaded | Displays a grid of WordGroupCard and WordGroupHighlightedCard components for each part of speech. |
Error | Shows an error message and a "Retry" button. |
Sources: app/src/main/java/com/vocabri/ui/screens/dictionary/DictionaryScreen.kt:105-123, app/src/androidTest/java/com/vocabri/test/ui/dictionary/DictionaryScreenStateTest.kt:39-65
The following diagram shows the state transitions managed by the DictionaryViewModel and rendered by the UI.
Layout and Components
The WordListScreen composable arranges word groups in a responsive layout.
- In portrait mode, it shows a highlighted card for "All Words" at the top, followed by a grid of other categories.
- In landscape mode, all cards, including "All Words", are displayed in a single adaptive grid.
The primary components are:
WordGroupHighlightedCard: A visually distinct card for the "All words" category.WordGroupCard: A standard card for other categories like "Nouns", "Verbs", etc.
Each card displays the category title and the number of words it contains.
Sources: app/src/main/java/com/vocabri/ui/screens/dictionary/DictionaryScreen.kt:205-253
Event Handling
User interactions on the DictionaryScreen are handled as events passed to the DictionaryViewModel.
| Event | Action |
|---|---|
AddWordClicked | Navigates to the AddWord screen. |
OnGroupCardClicked | Navigates to the DictionaryDetails screen for the selected PartOfSpeech. |
RetryClicked | Triggers the retry() function in the ViewModel to re-fetch data. |
Sources: app/src/main/java/com/vocabri/ui/screens/dictionary/DictionaryScreen.kt:91-101
ViewModel Layer (DictionaryViewModel.kt)
The DictionaryViewModel is the state holder for the screen. It is responsible for initiating data loading, transforming domain models into UI models, and managing the screen's lifecycle.
Sources: app/src/main/java/com/vocabri/ui/screens/dictionary/viewmodel/DictionaryViewModel.kt
Data Loading Flow
Upon initialization, the ViewModel launches a coroutine to call observeWordGroupsUseCase.execute(). This use case returns a Flow of WordGroup data from the repository. The ViewModel collects this flow, handles loading and error states, and maps the domain models to WordGroupUiModel instances for the UI.
This sequence diagram shows the data loading process:
Model Transformation
The DictionaryViewModel transforms the WordGroup domain model into a WordGroupUiModel suitable for display. This involves using the ResourcesRepository to resolve localized strings for the group title and subtitle.
private fun WordGroup.toUiModel(): WordGroupUiModel = WordGroupUiModel(
partOfSpeech = partOfSpeech,
titleText = resourcesRepository.getString(partOfSpeech.toTitleResId),
subtitleText = resourcesRepository.getString(R.string.dictionary_group_words_count, wordCount),
)
Sources: app/src/main/java/com/vocabri/ui/screens/dictionary/viewmodel/DictionaryViewModel.kt:86-90, app/src/main/res/values/strings.xml:31
Navigation
The DictionaryScreen is a primary destination in the app's bottom navigation bar, defined as the startDestination in AppNavigation.kt.
When a user taps on a word group card, the app navigates to the DictionaryDetailsScreen. The partOfSpeech of the selected group is passed as a navigation argument, ensuring the details screen can load the correct list of words.
This diagram shows the navigation flow from the Dictionary Overview screen.
Dependency Injection
The DictionaryViewModel and its dependencies are managed by Koin. The appModule defines how to construct the ViewModel.
@ExcludeFromCoverage
val appModule = module {
viewModelOf(::MainViewModel)
viewModelOf(::DictionaryViewModel)
viewModelOf(::AddWordViewModel)
// ...
}