feat(characters:presentation): UI-agnostic MVI ViewModel (REDI-87)

- CharacterListState (characters, isLoading, isLoadingNextPage, currentPage, endReached, error: UiText?),
  CharacterListAction (OnCharacterClick/OnRetry/OnLoadNextPage), CharacterListEvent (NavigateToDetail/ShowSnackbar).
- CharacterListViewModel: state via .update, one-time events via Channel, DataError -> UiText on failure,
  pagination persisted in SavedStateHandle (rebuilds list up to the saved page after process death).
- CharacterUi + Character.toCharacterUi().
- NO Compose/Views deps: verified no androidx.compose on the compile classpath. Stability via
  ImmutableList instead of @Stable (which would require compose-runtime) — the only compose-named
  transitive is kotlinx-immutable's annotations-only stub, not the Compose framework.
This commit is contained in:
2026-06-10 12:43:30 +02:00
parent 0bb96baa4d
commit 2a419df43e
7 changed files with 204 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ composeBom = "2026.03.01"
# Async / serialization
coroutines = "1.10.2"
kotlinxSerialization = "1.8.1"
kotlinxCollectionsImmutable = "0.3.8"
# DI
koin = "4.1.0"
@@ -87,6 +88,7 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinxCollectionsImmutable" }
# --- Koin (versions via BOM) ---
koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin" }