Skip to content

Commit e77a09d

Browse files
committed
Filtering and Ordering (custom room queries)
1 parent d06226a commit e77a09d

File tree

9 files changed

+225
-18
lines changed

9 files changed

+225
-18
lines changed

app/src/main/java/com/codingwithmitch/openapi/api/main/OpenApiMainService.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ interface OpenApiMainService {
3636
fun searchListBlogPosts(
3737
@Header("Authorization") authorization: String,
3838
@Query("search") query: String,
39+
@Query("ordering") ordering: String,
3940
@Query("page") page: Int
4041
): LiveData<GenericApiResponse<BlogListSearchResponse>>
4142

app/src/main/java/com/codingwithmitch/openapi/persistence/BlogPostDao.kt

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,68 @@ interface BlogPostDao {
1818
SELECT * FROM blog_post
1919
WHERE title LIKE '%' || :query || '%'
2020
OR body LIKE '%' || :query || '%'
21-
OR username LIKE '%' || :query || '%'
21+
OR username LIKE '%' || :query || '%'
2222
LIMIT (:page * :pageSize)
2323
""")
24-
fun getAllBlogPosts(query: String, page: Int, pageSize: Int = PAGINATION_PAGE_SIZE): LiveData<List<BlogPost>>
24+
fun getAllBlogPosts(
25+
query: String,
26+
page: Int,
27+
pageSize: Int = PAGINATION_PAGE_SIZE
28+
): LiveData<List<BlogPost>>
2529

26-
@Query("SELECT * FROM blog_post WHERE title LIKE '%' || :query || '%' OR body LIKE '%' || :query || '%' OR username LIKE '%' || :query || '%' ORDER BY date_updated DESC LIMIT (:page * :pageSize)")
27-
fun searchBlogPostsOrderByDateDESC(query: String, page: Int, pageSize: Int = PAGINATION_PAGE_SIZE): LiveData<List<BlogPost>>
30+
@Query("""
31+
SELECT * FROM blog_post
32+
WHERE title LIKE '%' || :query || '%'
33+
OR body LIKE '%' || :query || '%'
34+
OR username LIKE '%' || :query || '%'
35+
ORDER BY date_updated DESC LIMIT (:page * :pageSize)
36+
""")
37+
fun searchBlogPostsOrderByDateDESC(
38+
query: String,
39+
page: Int,
40+
pageSize: Int = PAGINATION_PAGE_SIZE
41+
): LiveData<List<BlogPost>>
2842

29-
@Query("SELECT * FROM blog_post WHERE title LIKE '%' || :query || '%' OR body LIKE '%' || :query || '%' OR username LIKE '%' || :query || '%' ORDER BY date_updated ASC LIMIT (:page * :pageSize)")
30-
fun searchBlogPostsOrderByDateASC(query: String, page: Int, pageSize: Int = PAGINATION_PAGE_SIZE): LiveData<List<BlogPost>>
43+
@Query("""
44+
SELECT * FROM blog_post
45+
WHERE title LIKE '%' || :query || '%'
46+
OR body LIKE '%' || :query || '%'
47+
OR username LIKE '%' || :query || '%'
48+
ORDER BY date_updated ASC LIMIT (:page * :pageSize)""")
49+
fun searchBlogPostsOrderByDateASC(
50+
query: String,
51+
page: Int,
52+
pageSize: Int = PAGINATION_PAGE_SIZE
53+
): LiveData<List<BlogPost>>
3154

32-
@Query("SELECT * FROM blog_post WHERE title LIKE '%' || :query || '%' OR body LIKE '%' || :query || '%' OR username LIKE '%' || :query || '%' ORDER BY username DESC LIMIT (:page * :pageSize)")
33-
fun searchBlogPostsOrderByAuthorDESC(query: String, page: Int, pageSize: Int = PAGINATION_PAGE_SIZE): LiveData<List<BlogPost>>
55+
@Query("""
56+
SELECT * FROM blog_post
57+
WHERE title LIKE '%' || :query || '%'
58+
OR body LIKE '%' || :query || '%'
59+
OR username LIKE '%' || :query || '%'
60+
ORDER BY username DESC LIMIT (:page * :pageSize)""")
61+
fun searchBlogPostsOrderByAuthorDESC(
62+
query: String,
63+
page: Int,
64+
pageSize: Int = PAGINATION_PAGE_SIZE
65+
): LiveData<List<BlogPost>>
3466

35-
@Query("SELECT * FROM blog_post WHERE title LIKE '%' || :query || '%' OR body LIKE '%' || :query || '%' OR username LIKE '%' || :query || '%' ORDER BY username ASC LIMIT (:page * :pageSize)")
36-
fun searchBlogPostsOrderByAuthorASC(query: String, page: Int, pageSize: Int = PAGINATION_PAGE_SIZE): LiveData<List<BlogPost>>
67+
@Query("""
68+
SELECT * FROM blog_post
69+
WHERE title LIKE '%' || :query || '%'
70+
OR body LIKE '%' || :query || '%'
71+
OR username LIKE '%' || :query || '%'
72+
ORDER BY username ASC LIMIT (:page * :pageSize)
73+
""")
74+
fun searchBlogPostsOrderByAuthorASC(
75+
query: String,
76+
page: Int,
77+
pageSize: Int = PAGINATION_PAGE_SIZE
78+
): LiveData<List<BlogPost>>
3779
}
3880

3981

4082

83+
84+
85+
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.codingwithmitch.openapi.persistence
2+
3+
import androidx.lifecycle.LiveData
4+
import com.codingwithmitch.openapi.models.BlogPost
5+
import com.codingwithmitch.openapi.persistence.BlogQueryUtils.Companion.ORDER_BY_ASC_DATE_UPDATED
6+
import com.codingwithmitch.openapi.persistence.BlogQueryUtils.Companion.ORDER_BY_ASC_USERNAME
7+
import com.codingwithmitch.openapi.persistence.BlogQueryUtils.Companion.ORDER_BY_DESC_DATE_UPDATED
8+
import com.codingwithmitch.openapi.persistence.BlogQueryUtils.Companion.ORDER_BY_DESC_USERNAME
9+
10+
class BlogQueryUtils {
11+
12+
13+
companion object{
14+
private val TAG: String = "AppDebug"
15+
16+
// values
17+
const val BLOG_ORDER_ASC: String = ""
18+
const val BLOG_ORDER_DESC: String = "-"
19+
const val BLOG_FILTER_USERNAME = "username"
20+
const val BLOG_FILTER_DATE_UPDATED = "date_updated"
21+
22+
val ORDER_BY_ASC_DATE_UPDATED = BLOG_ORDER_ASC + BLOG_FILTER_DATE_UPDATED
23+
val ORDER_BY_DESC_DATE_UPDATED = BLOG_ORDER_DESC + BLOG_FILTER_DATE_UPDATED
24+
val ORDER_BY_ASC_USERNAME = BLOG_ORDER_ASC + BLOG_FILTER_USERNAME
25+
val ORDER_BY_DESC_USERNAME = BLOG_ORDER_DESC + BLOG_FILTER_USERNAME
26+
}
27+
}
28+
29+
30+
fun BlogPostDao.returnOrderedBlogQuery(
31+
query: String,
32+
filterAndOrder: String,
33+
page: Int
34+
): LiveData<List<BlogPost>> {
35+
36+
when{
37+
38+
filterAndOrder.contains(ORDER_BY_DESC_DATE_UPDATED) ->{
39+
return searchBlogPostsOrderByDateDESC(
40+
query = query,
41+
page = page)
42+
}
43+
44+
filterAndOrder.contains(ORDER_BY_ASC_DATE_UPDATED) ->{
45+
return searchBlogPostsOrderByDateASC(
46+
query = query,
47+
page = page)
48+
}
49+
50+
filterAndOrder.contains(ORDER_BY_DESC_USERNAME) ->{
51+
return searchBlogPostsOrderByAuthorDESC(
52+
query = query,
53+
page = page)
54+
}
55+
56+
filterAndOrder.contains(ORDER_BY_ASC_USERNAME) ->{
57+
return searchBlogPostsOrderByAuthorASC(
58+
query = query,
59+
page = page)
60+
}
61+
else ->
62+
return searchBlogPostsOrderByDateASC(
63+
query = query,
64+
page = page
65+
)
66+
}
67+
}

app/src/main/java/com/codingwithmitch/openapi/repository/main/BlogRepository.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import com.codingwithmitch.openapi.api.main.responses.BlogListSearchResponse
88
import com.codingwithmitch.openapi.models.AuthToken
99
import com.codingwithmitch.openapi.models.BlogPost
1010
import com.codingwithmitch.openapi.persistence.BlogPostDao
11+
import com.codingwithmitch.openapi.persistence.returnOrderedBlogQuery
1112
import com.codingwithmitch.openapi.repository.JobManager
1213
import com.codingwithmitch.openapi.repository.NetworkBoundResource
1314
import com.codingwithmitch.openapi.session.SessionManager
1415
import com.codingwithmitch.openapi.ui.DataState
1516
import com.codingwithmitch.openapi.ui.main.blog.state.BlogViewState
17+
import com.codingwithmitch.openapi.ui.main.blog.state.BlogViewState.*
1618
import com.codingwithmitch.openapi.util.ApiSuccessResponse
1719
import com.codingwithmitch.openapi.util.Constants.Companion.PAGINATION_PAGE_SIZE
1820
import com.codingwithmitch.openapi.util.DateUtils
@@ -38,6 +40,7 @@ constructor(
3840
fun searchBlogPosts(
3941
authToken: AuthToken,
4042
query: String,
43+
filterAndOrder: String,
4144
page: Int
4245
): LiveData<DataState<BlogViewState>> {
4346
return object: NetworkBoundResource<BlogListSearchResponse, List<BlogPost>, BlogViewState>(
@@ -90,20 +93,22 @@ constructor(
9093
return openApiMainService.searchListBlogPosts(
9194
"Token ${authToken.token!!}",
9295
query = query,
96+
ordering = filterAndOrder,
9397
page = page
9498
)
9599
}
96100

97101
override fun loadFromCache(): LiveData<BlogViewState> {
98-
return blogPostDao.getAllBlogPosts(
102+
return blogPostDao.returnOrderedBlogQuery(
99103
query = query,
104+
filterAndOrder = filterAndOrder,
100105
page = page)
101106
.switchMap {
102107
object: LiveData<BlogViewState>(){
103108
override fun onActive() {
104109
super.onActive()
105110
value = BlogViewState(
106-
BlogViewState.BlogFields(
111+
BlogFields(
107112
blogList = it,
108113
isQueryInProgress = true
109114
)

app/src/main/java/com/codingwithmitch/openapi/ui/main/blog/BlogFragment.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ class BlogFragment : BaseBlogFragment(),
201201
onBlogSearchOrFilter()
202202
swipe_refresh.isRefreshing = false
203203
}
204+
205+
204206
}
205207

206208

app/src/main/java/com/codingwithmitch/openapi/ui/main/blog/state/BlogViewState.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.codingwithmitch.openapi.ui.main.blog.state
22

33
import com.codingwithmitch.openapi.models.BlogPost
4+
import com.codingwithmitch.openapi.persistence.BlogQueryUtils.Companion.BLOG_ORDER_ASC
5+
import com.codingwithmitch.openapi.persistence.BlogQueryUtils.Companion.ORDER_BY_ASC_DATE_UPDATED
46

57
data class BlogViewState (
68

@@ -16,7 +18,9 @@ data class BlogViewState (
1618
var searchQuery: String = "",
1719
var page: Int = 1,
1820
var isQueryInProgress: Boolean = false,
19-
var isQueryExhausted: Boolean = false
21+
var isQueryExhausted: Boolean = false,
22+
var filter: String = ORDER_BY_ASC_DATE_UPDATED,
23+
var order: String = BLOG_ORDER_ASC
2024
)
2125

2226
data class ViewBlogFields(

app/src/main/java/com/codingwithmitch/openapi/ui/main/blog/viewmodel/BlogViewModel.kt

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package com.codingwithmitch.openapi.ui.main.blog.viewmodel
33
import android.content.SharedPreferences
44
import androidx.lifecycle.LiveData
55
import com.bumptech.glide.RequestManager
6+
import com.codingwithmitch.openapi.models.BlogPost
7+
import com.codingwithmitch.openapi.persistence.BlogQueryUtils
68
import com.codingwithmitch.openapi.repository.main.BlogRepository
79
import com.codingwithmitch.openapi.session.SessionManager
810
import com.codingwithmitch.openapi.ui.BaseViewModel
@@ -12,6 +14,8 @@ import com.codingwithmitch.openapi.ui.main.blog.state.BlogStateEvent
1214
import com.codingwithmitch.openapi.ui.main.blog.state.BlogStateEvent.*
1315
import com.codingwithmitch.openapi.ui.main.blog.state.BlogViewState
1416
import com.codingwithmitch.openapi.util.AbsentLiveData
17+
import com.codingwithmitch.openapi.util.PreferenceKeys.Companion.BLOG_FILTER
18+
import com.codingwithmitch.openapi.util.PreferenceKeys.Companion.BLOG_ORDER
1519
import javax.inject.Inject
1620

1721
class BlogViewModel
@@ -20,18 +24,35 @@ constructor(
2024
private val sessionManager: SessionManager,
2125
private val blogRepository: BlogRepository,
2226
private val sharedPreferences: SharedPreferences,
23-
private val requestManager: RequestManager
27+
private val editor: SharedPreferences.Editor
2428
): BaseViewModel<BlogStateEvent, BlogViewState>(){
2529

30+
31+
init {
32+
setBlogFilter(
33+
sharedPreferences.getString(
34+
BLOG_FILTER,
35+
BlogQueryUtils.BLOG_FILTER_DATE_UPDATED
36+
)
37+
)
38+
setBlogOrder(
39+
sharedPreferences.getString(
40+
BLOG_ORDER,
41+
BlogQueryUtils.BLOG_ORDER_ASC
42+
)
43+
)
44+
}
45+
2646
override fun handleStateEvent(stateEvent: BlogStateEvent): LiveData<DataState<BlogViewState>> {
2747
when(stateEvent){
2848

2949
is BlogSearchEvent -> {
3050
return sessionManager.cachedToken.value?.let { authToken ->
3151
blogRepository.searchBlogPosts(
32-
authToken,
33-
viewState.value!!.blogFields.searchQuery,
34-
viewState.value!!.blogFields.page
52+
authToken = authToken,
53+
query = getSearchQuery(),
54+
filterAndOrder = getOrder() + getFilter(),
55+
page = getPage()
3556
)
3657
}?: AbsentLiveData.create()
3758
}
@@ -55,6 +76,14 @@ constructor(
5576
return BlogViewState()
5677
}
5778

79+
fun saveFilterOptions(filter: String, order: String){
80+
editor.putString(BLOG_FILTER, filter)
81+
editor.apply()
82+
83+
editor.putString(BLOG_ORDER, order)
84+
editor.apply()
85+
}
86+
5887
fun cancelActiveJobs(){
5988
blogRepository.cancelActiveJobs() // cancel active jobs
6089
handlePendingData() // hide progress bar
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.codingwithmitch.openapi.ui.main.blog.viewmodel
2+
3+
fun BlogViewModel.getFilter(): String {
4+
getCurrentViewStateOrNew().let {
5+
return it.blogFields.filter
6+
}
7+
}
8+
9+
fun BlogViewModel.getOrder(): String {
10+
getCurrentViewStateOrNew().let {
11+
return it.blogFields.order
12+
}
13+
}
14+
15+
fun BlogViewModel.getSearchQuery(): String {
16+
getCurrentViewStateOrNew().let {
17+
return it.blogFields.searchQuery
18+
}
19+
}
20+
21+
fun BlogViewModel.getPage(): Int{
22+
getCurrentViewStateOrNew().let {
23+
return it.blogFields.page
24+
}
25+
}

app/src/main/java/com/codingwithmitch/openapi/ui/main/blog/viewmodel/Setters.kt

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,33 @@ fun BlogViewModel.setQueryInProgress(isInProgress: Boolean){
3737
val update = getCurrentViewStateOrNew()
3838
update.blogFields.isQueryInProgress = isInProgress
3939
setViewState(update)
40-
}
40+
}
41+
42+
43+
// Filter can be "date_updated" or "username"
44+
fun BlogViewModel.setBlogFilter(filter: String?){
45+
filter?.let{
46+
val update = getCurrentViewStateOrNew()
47+
update.blogFields.filter = filter
48+
setViewState(update)
49+
}
50+
}
51+
52+
// Order can be "-" or ""
53+
// Note: "-" = DESC, "" = ASC
54+
fun BlogViewModel.setBlogOrder(order: String){
55+
val update = getCurrentViewStateOrNew()
56+
update.blogFields.order = order
57+
setViewState(update)
58+
}
59+
60+
61+
62+
63+
64+
65+
66+
67+
68+
69+

0 commit comments

Comments
 (0)