Skip to content

Commit 2424f00

Browse files
committed
- creates a generic sealed interface for compose ui state
- updates compose view model to use simple states
1 parent 46751bf commit 2424f00

File tree

4 files changed

+40
-65
lines changed

4 files changed

+40
-65
lines changed

app/src/main/java/org/wikipedia/language/addlanguages/AddLanguagesListActivity.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class AddLanguagesListActivity : BaseActivity() {
2727
LanguagesListScreen(
2828
modifier = Modifier
2929
.fillMaxSize(),
30-
languageListUiState = uiState,
30+
uiState = uiState,
3131
onBackButtonClick = {
3232
finish()
3333
},

app/src/main/java/org/wikipedia/language/addlanguages/AddLanguagesListScreen.kt

+21-18
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,12 @@ import org.wikipedia.compose.components.error.ComposeWikiErrorParentView
4444
import org.wikipedia.compose.components.error.WikiErrorClickEvents
4545
import org.wikipedia.compose.theme.WikipediaTheme
4646
import org.wikipedia.util.StringUtil
47+
import org.wikipedia.util.UiState
4748

4849
@Composable
4950
fun LanguagesListScreen(
5051
modifier: Modifier = Modifier,
51-
languageListUiState: LanguageListUiState,
52+
uiState: UiState<List<LanguageListItem>>,
5253
onBackButtonClick: () -> Unit,
5354
onSearchQueryChange: (String) -> Unit,
5455
onListItemClick: (code: String) -> Unit,
@@ -82,40 +83,41 @@ fun LanguagesListScreen(
8283
},
8384
containerColor = WikipediaTheme.colors.paperColor
8485
) { paddingValues ->
85-
when (languageListUiState) {
86-
is LanguageListUiState.Error -> {
86+
when (uiState) {
87+
UiState.Loading -> {
8788
Box(
8889
modifier = modifier
8990
.fillMaxSize()
9091
.padding(paddingValues)
91-
// Add bottom padding when keyboard is visible for android 15 and above
92-
.padding(bottom = if (isKeyboardVisible) imeHeight else 0.dp),
93-
contentAlignment = Alignment.Center
9492
) {
95-
ComposeWikiErrorParentView(
93+
CircularProgressIndicator(
9694
modifier = Modifier
97-
.fillMaxWidth(),
98-
caught = languageListUiState.error,
99-
errorClickEvents = wikiErrorClickEvents
95+
.align(Alignment.BottomEnd)
96+
.padding(24.dp),
97+
color = WikipediaTheme.colors.progressiveColor
10098
)
10199
}
102100
}
103-
is LanguageListUiState.Loading -> {
101+
is UiState.Error -> {
104102
Box(
105103
modifier = modifier
106104
.fillMaxSize()
107105
.padding(paddingValues)
106+
// Add bottom padding when keyboard is visible for android 15 and above
107+
.padding(bottom = if (isKeyboardVisible) imeHeight else 0.dp),
108+
contentAlignment = Alignment.Center
108109
) {
109-
CircularProgressIndicator(
110+
ComposeWikiErrorParentView(
110111
modifier = Modifier
111-
.align(Alignment.BottomEnd)
112-
.padding(24.dp),
113-
color = WikipediaTheme.colors.progressiveColor
112+
.fillMaxWidth(),
113+
caught = uiState.error,
114+
errorClickEvents = wikiErrorClickEvents
114115
)
115116
}
116117
}
117-
is LanguageListUiState.Success -> {
118-
if (languageListUiState.languagesItems.isEmpty()) {
118+
is UiState.Success -> {
119+
val languagesItems = uiState.data
120+
if (languagesItems.isEmpty()) {
119121
Box(
120122
modifier = modifier
121123
.fillMaxSize()
@@ -132,12 +134,13 @@ fun LanguagesListScreen(
132134
}
133135
return@Scaffold
134136
}
137+
135138
LazyColumn(
136139
modifier = modifier
137140
.fillMaxSize()
138141
.padding(paddingValues),
139142
) {
140-
items(languageListUiState.languagesItems) { languageItem ->
143+
items(languagesItems) { languageItem ->
141144
if (languageItem.headerText.isNotEmpty()) {
142145
ListHeader(
143146
modifier = Modifier

app/src/main/java/org/wikipedia/language/addlanguages/AddLanguagesViewModel.kt

+12-46
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import androidx.lifecycle.viewModelScope
55
import kotlinx.coroutines.CoroutineExceptionHandler
66
import kotlinx.coroutines.Job
77
import kotlinx.coroutines.flow.MutableStateFlow
8-
import kotlinx.coroutines.flow.StateFlow
98
import kotlinx.coroutines.flow.asStateFlow
109
import kotlinx.coroutines.isActive
1110
import kotlinx.coroutines.launch
@@ -14,6 +13,7 @@ import org.wikipedia.R
1413
import org.wikipedia.WikipediaApp
1514
import org.wikipedia.dataclient.ServiceFactory
1615
import org.wikipedia.dataclient.mwapi.SiteMatrix
16+
import org.wikipedia.util.UiState
1717
import org.wikipedia.util.log.L
1818

1919
class AddLanguagesViewModel : ViewModel() {
@@ -25,12 +25,12 @@ class AddLanguagesViewModel : ViewModel() {
2525
private val _siteInfoList = MutableStateFlow<List<SiteMatrix.SiteInfo>>(emptyList())
2626

2727
// UI state exposed to Compose
28-
private val _uiState = MutableStateFlow<LanguageListUiState>(LanguageListUiState.Loading)
29-
val uiState: StateFlow<LanguageListUiState> = _uiState.asStateFlow()
28+
private val _uiState = MutableStateFlow<UiState<List<LanguageListItem>>>(UiState.Loading)
29+
val uiState = _uiState.asStateFlow()
3030

3131
private val handler = CoroutineExceptionHandler { _, throwable ->
3232
L.e(throwable)
33-
_uiState.value = LanguageListUiState.Error(throwable)
33+
_uiState.value = UiState.Error(throwable)
3434
}
3535

3636
private var fetchJob: Job? = null
@@ -43,50 +43,31 @@ class AddLanguagesViewModel : ViewModel() {
4343
fetchJob?.cancel()
4444

4545
// Set to loading state
46-
_uiState.value = LanguageListUiState.Loading
46+
_uiState.value = UiState.Loading
4747

4848
// fetch site matrix
4949
fetchJob = viewModelScope.launch(handler) {
50-
_uiState.value = LanguageListUiState.Loading
50+
_uiState.value = UiState.Loading
5151
val siteMatrix = ServiceFactory.get(WikipediaApp.instance.wikiSite).getSiteMatrix()
5252
val sites = SiteMatrix.getSites(siteMatrix)
5353
_siteInfoList.value = sites
5454

5555
// isActive checks if the job is still active
5656
// does not update the list if the coroutine has been cancelled
5757
if (isActive) {
58-
updateSearchTerm(getCurrentSearchTerm(), siteInfoAvailable = true)
58+
updateSearchTerm("")
5959
}
6060
}
6161
}
6262

63-
fun updateSearchTerm(term: String, siteInfoAvailable: Boolean = isSiteInfoLoaded()) {
63+
fun updateSearchTerm(term: String) {
6464
viewModelScope.launch {
65-
_uiState.value = LanguageListUiState.Success(
66-
searchTerm = term,
67-
languagesItems = getFilteredLanguageList(term, siteInfoAvailable),
68-
isSiteInfoLoaded = siteInfoAvailable
69-
)
70-
}
71-
}
72-
73-
private fun isSiteInfoLoaded(): Boolean {
74-
return when (val state = _uiState.value) {
75-
is LanguageListUiState.Success -> state.isSiteInfoLoaded
76-
else -> false
77-
}
78-
}
79-
80-
private fun getCurrentSearchTerm(): String {
81-
return when (val state = _uiState.value) {
82-
is LanguageListUiState.Success -> state.searchTerm
83-
else -> ""
65+
_uiState.value = UiState.Success(getFilteredLanguageList(term))
8466
}
8567
}
8668

8769
private fun getFilteredLanguageList(
8870
searchTerm: String,
89-
siteInfoAvailable: Boolean
9071
): List<LanguageListItem> {
9172
val results = mutableListOf<LanguageListItem>()
9273
val filter = StringUtils.stripAccents(searchTerm)
@@ -95,16 +76,14 @@ class AddLanguagesViewModel : ViewModel() {
9576
filter,
9677
suggestedLanguageCodes,
9778
WikipediaApp.instance.getString(R.string.languages_list_suggested_text),
98-
results,
99-
siteInfoAvailable
79+
results
10080
)
10181

10282
addFilteredLanguageListItems(
10383
filter,
10484
nonSuggestedLanguageCodes,
10585
WikipediaApp.instance.getString(R.string.languages_list_all_text),
106-
results,
107-
siteInfoAvailable
86+
results
10887
)
10988

11089
return results
@@ -115,7 +94,6 @@ class AddLanguagesViewModel : ViewModel() {
11594
codes: List<String>,
11695
headerText: String,
11796
results: MutableList<LanguageListItem>,
118-
siteInfoAvailable: Boolean
11997
) {
12098
var first = true
12199
for (code in codes) {
@@ -124,9 +102,7 @@ class AddLanguagesViewModel : ViewModel() {
124102
)
125103

126104
// Only attempt to get canonical name if the site is available
127-
val canonicalName = if (siteInfoAvailable) {
128-
StringUtils.stripAccents(getCanonicalName(code))
129-
} else ""
105+
val canonicalName = StringUtils.stripAccents(getCanonicalName(code))
130106

131107
if (filter.isEmpty() || code.contains(filter, true) ||
132108
localizedName.contains(filter, true) ||
@@ -163,13 +139,3 @@ data class LanguageListItem(
163139
val canonicalName: String = "",
164140
val headerText: String = "",
165141
)
166-
167-
sealed interface LanguageListUiState {
168-
data object Loading : LanguageListUiState
169-
data class Error(val error: Throwable) : LanguageListUiState
170-
data class Success(
171-
val searchTerm: String,
172-
val languagesItems: List<LanguageListItem> = emptyList(),
173-
val isSiteInfoLoaded: Boolean = false
174-
) : LanguageListUiState
175-
}

app/src/main/java/org/wikipedia/util/Resource.kt

+6
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ open class Resource<T> {
55
class Success<T>(val data: T) : Resource<T>()
66
class Error<T>(val throwable: Throwable) : Resource<T>()
77
}
8+
9+
sealed interface UiState<out T> {
10+
data object Loading : UiState<Nothing>
11+
data class Success<T>(val data: T) : UiState<T>
12+
data class Error(val error: Throwable) : UiState<Nothing>
13+
}

0 commit comments

Comments
 (0)