Skip to content

Commit 0a406c4

Browse files
Merge branch 'hotfix/update-sort-dialog'
2 parents d125cbf + bf0c46a commit 0a406c4

2 files changed

Lines changed: 121 additions & 6 deletions

File tree

features/home/src/main/java/com/smarttoolfactory/home/HomeFragment.kt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.smarttoolfactory.home
22

33
import android.app.Dialog
4+
import android.content.DialogInterface
45
import android.os.Bundle
56
import androidx.appcompat.app.AlertDialog
67
import androidx.fragment.app.DialogFragment
@@ -150,27 +151,45 @@ class SortDialogFragment : DialogFragment() {
150151

151152
private lateinit var viewModel: HomeToolbarVM
152153

154+
private var currentItem = 0
155+
private var checkedItem = currentItem
156+
153157
override fun onCreate(savedInstanceState: Bundle?) {
154158
super.onCreate(savedInstanceState)
155159
viewModel = ViewModelProvider(requireActivity()).get(HomeToolbarVM::class.java)
156160
}
157161

158162
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
159163

160-
val items = viewModel.sortPropertyList.toTypedArray()
161-
items[0] = "Featured"
164+
val displayNames = viewModel.sortPropertyList.toTypedArray()
165+
currentItem = viewModel.sortPropertyList.indexOf(viewModel.currentSortFilter)
166+
checkedItem = currentItem
162167

163-
val checkedItem = viewModel.sortPropertyList.indexOf(viewModel.currentSortFilter)
168+
displayNames[0] = "Featured"
164169

165170
val builder = AlertDialog.Builder(requireActivity())
166171
builder.setTitle("Sorting")
167172
.setNegativeButton("CANCEL") { dialog, which ->
168173
dismiss()
169174
}
170-
.setSingleChoiceItems(items, checkedItem) { dialog, which ->
171-
viewModel.queryBySort.value = Event(viewModel.sortPropertyList[which])
172-
dismiss()
175+
.setSingleChoiceItems(displayNames, currentItem) { dialog, which ->
176+
checkedItem = which
177+
}.setOnDismissListener {
178+
179+
// Alternative 1 works as soon as user changes the option
180+
// if (currentItem != checkedItem) {
181+
// viewModel.queryBySort.value = Event(viewModel.sortPropertyList[checkedItem])
182+
// }
183+
// dismiss()
173184
}
174185
return builder.create()
175186
}
187+
188+
override fun onDismiss(dialog: DialogInterface) {
189+
super.onDismiss(dialog)
190+
// Alternative works after dialog is dismissed
191+
if (currentItem != checkedItem) {
192+
viewModel.queryBySort.value = Event(viewModel.sortPropertyList[checkedItem])
193+
}
194+
}
176195
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.smarttoolfactory.domain.usecase
2+
3+
import com.smarttoolfactory.data.constant.ORDER_BY_NONE
4+
import com.smarttoolfactory.data.model.local.PropertyEntity
5+
import com.smarttoolfactory.data.repository.PropertyRepositoryCoroutines
6+
import com.smarttoolfactory.domain.dispatcher.UseCaseDispatchers
7+
import com.smarttoolfactory.domain.error.EmptyDataException
8+
import com.smarttoolfactory.domain.mapper.PropertyEntityToItemListMapper
9+
import com.smarttoolfactory.domain.model.PropertyItem
10+
import javax.inject.Inject
11+
import kotlinx.coroutines.flow.Flow
12+
import kotlinx.coroutines.flow.catch
13+
import kotlinx.coroutines.flow.emitAll
14+
import kotlinx.coroutines.flow.flow
15+
import kotlinx.coroutines.flow.flowOf
16+
import kotlinx.coroutines.flow.flowOn
17+
import kotlinx.coroutines.flow.map
18+
19+
/**
20+
* UseCase for getting UI Item list with offline first or offline last approach.
21+
*
22+
* * *Offline-first* first source to look for data is local data source, or database,
23+
* if database is empty or if caching is used it's expiry date is over, looks for remote source
24+
* for data. If both of the sources are empty, either return empty list or error to notify UI.
25+
*
26+
* This approach is good for when user is offline or have no internet connection, additional logic
27+
* can be added to check if user is offline to not deleted cached data.
28+
*
29+
* * *Offline-last* always checks remote data source for data and applies to database or offline
30+
* source as last resort. Offline-last is used especially when user refreshes data with a UI
31+
* element to get the latest data or new data is always first preference.
32+
*/
33+
class GetPropertiesUseCasePaged @Inject constructor(
34+
private val repository: PropertyRepositoryCoroutines,
35+
private val mapper: PropertyEntityToItemListMapper,
36+
private val dispatcherProvider: UseCaseDispatchers
37+
) {
38+
39+
/**
40+
* Function to retrieve data from repository with offline-last which checks
41+
* REMOTE data source first.
42+
*
43+
* * Check out Remote Source first
44+
* * If empty data or null returned throw empty set exception
45+
* * If error occurred while fetching data from remote: Try to fetch data from db
46+
* * If data is fetched from remote source: delete old data, save new data and return new data
47+
* * If both network and db don't have any data throw empty set exception
48+
*
49+
*/
50+
fun getPagedOfflineLast(page: Int, orderBy: String): Flow<List<PropertyItem>> {
51+
return flow { emit(repository.fetchEntitiesFromRemote(orderBy)) }
52+
.map {
53+
if (it.isNullOrEmpty()) {
54+
throw EmptyDataException("No Data is available in Remote source!")
55+
} else {
56+
repository.run {
57+
58+
if (page == 1) {
59+
deletePropertyEntities()
60+
}
61+
62+
// 🔥 Add an insert order since we are not using Room's ORDER BY
63+
it.forEachIndexed { index, propertyEntity ->
64+
propertyEntity.insertOrder = index
65+
}
66+
savePropertyEntities(it)
67+
68+
getPropertyEntitiesFromLocal()
69+
}
70+
}
71+
}
72+
.flowOn(dispatcherProvider.ioDispatcher)
73+
// This is where remote exception or least likely db exceptions are caught
74+
.catch { throwable ->
75+
emitAll(flowOf(repository.getPropertyEntitiesFromLocal()))
76+
}
77+
.map {
78+
toPropertyListOrError(it)
79+
}
80+
}
81+
82+
private fun toPropertyListOrError(entityList: List<PropertyEntity>): List<PropertyItem> {
83+
return if (!entityList.isNullOrEmpty()) {
84+
mapper.map(entityList)
85+
} else {
86+
throw EmptyDataException("Empty data mapping error!")
87+
}
88+
}
89+
90+
fun getCurrentSortKey(defaultKey: String = ORDER_BY_NONE): Flow<String> {
91+
return flow { emit(repository.getSortOrderKey()) }
92+
.catch {
93+
emitAll(flowOf(defaultKey))
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)