Skip to content

Commit d7ecbb8

Browse files
committed
Merge branch 'feat/search' into development
2 parents 52305bc + 5d49e0e commit d7ecbb8

File tree

7 files changed

+108
-10
lines changed

7 files changed

+108
-10
lines changed

app/src/main/java/com/arctouch/codechallenge/api/TmdbApi.kt

+7
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@ interface TmdbApi {
3636
@Query("api_key") apiKey: String = API_KEY,
3737
@Query("language") language: String = DEFAULT_LANGUAGE
3838
): Observable<Movie>
39+
40+
@GET("search/movie")
41+
suspend fun getMoviesByName(
42+
@Query("query") title: String,
43+
@Query("api_key") apiKey: String = API_KEY,
44+
@Query("language") language: String = DEFAULT_LANGUAGE
45+
): UpcomingMoviesResponse
3946
}

app/src/main/java/com/arctouch/codechallenge/di/TmbRepository.kt

+8
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,12 @@ class TmbRepositoryImpl(private val api: TmdbApi) : TmbRepository {
2525
return api.movie(id, apiKey, language)
2626
}
2727

28+
override suspend fun getMoviesByName(
29+
title: String,
30+
apiKey: String,
31+
language: String
32+
): UpcomingMoviesResponse {
33+
return api.getMoviesByName(title)
34+
}
35+
2836
}

app/src/main/java/com/arctouch/codechallenge/ui/home/HomeFragment.kt

+53-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package com.arctouch.codechallenge.ui.home
22

3+
import android.app.SearchManager
4+
import android.content.Context
35
import android.nfc.tech.MifareUltralight.PAGE_SIZE
46
import android.os.Bundle
5-
import android.view.LayoutInflater
6-
import android.view.View
7-
import android.view.ViewGroup
7+
import android.view.*
8+
import androidx.appcompat.widget.SearchView
89
import androidx.fragment.app.Fragment
910
import androidx.lifecycle.LifecycleOwner
1011
import androidx.lifecycle.Observer
@@ -21,7 +22,9 @@ class HomeFragment : Fragment() {
2122

2223
private val mViewModel: HomeViewModel by viewModel()
2324
private var isLoading = false
25+
private var isSearching = false
2426
private lateinit var adapter: HomeAdapter
27+
private lateinit var searchView: SearchView
2528

2629
override fun onCreateView(
2730
inflater: LayoutInflater,
@@ -33,17 +36,61 @@ class HomeFragment : Fragment() {
3336

3437
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
3538
super.onViewCreated(view, savedInstanceState)
39+
setHasOptionsMenu(true)
3640
setUpAdapter(mViewModel.upcomingMovies.value)
3741
configScrollListener(recyclerView)
3842
observeViewModel()
3943
}
4044

45+
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
46+
inflater.inflate(R.menu.search_menu, menu)
47+
val searchAction = menu.findItem(R.id.search_action)
48+
searchAction.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
49+
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
50+
isSearching = true
51+
return true
52+
}
53+
54+
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
55+
isSearching = false
56+
return true
57+
}
58+
})
59+
searchView = searchAction?.actionView as SearchView
60+
configSearchView()
61+
super.onCreateOptionsMenu(menu, inflater)
62+
}
63+
64+
private fun configSearchView() {
65+
val searchManager = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager
66+
searchView.setSearchableInfo(searchManager.getSearchableInfo(activity?.componentName))
67+
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
68+
override fun onQueryTextChange(newText: String?): Boolean {
69+
if (newText.isNullOrEmpty()) {
70+
setUpAdapter(mViewModel.upcomingMovies.value)
71+
mViewModel.getUpComingMovies()
72+
isSearching = false
73+
} else {
74+
mViewModel.searchMovies(newText)
75+
}
76+
return true
77+
}
78+
79+
override fun onQueryTextSubmit(query: String?): Boolean {
80+
return true
81+
}
82+
})
83+
}
84+
4185
private fun observeViewModel() {
4286
mViewModel.upcomingMovies.observe(this as LifecycleOwner, Observer {
4387
isLoading = false
4488
progressBar.visibility = View.GONE
4589
adapter.notifyDataSetChanged()
4690
})
91+
mViewModel.searchLiveData.observe(this as LifecycleOwner, Observer {
92+
setUpAdapter(it.toMutableList())
93+
})
4794
}
4895

4996
private fun loadMoreMovies() {
@@ -72,6 +119,9 @@ class HomeFragment : Fragment() {
72119

73120
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
74121
super.onScrolled(recyclerView, dx, dy)
122+
if (isSearching) {
123+
return
124+
}
75125
val layoutManager = recyclerView
76126
.layoutManager as LinearLayoutManager
77127
val visibleItemCount: Int = layoutManager.childCount

app/src/main/java/com/arctouch/codechallenge/ui/home/HomeViewModel.kt

+22-7
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@ import androidx.lifecycle.MutableLiveData
55
import androidx.lifecycle.ViewModel
66
import androidx.lifecycle.viewModelScope
77
import com.arctouch.codechallenge.App
8-
import com.arctouch.codechallenge.api.TmdbApi
98
import com.arctouch.codechallenge.data.Cache
109
import com.arctouch.codechallenge.model.Movie
10+
import com.arctouch.codechallenge.model.UpcomingMoviesResponse
1111
import kotlinx.coroutines.launch
1212

1313
class HomeViewModel : ViewModel() {
1414

1515
private val api = App.api
1616
private val _upcomingMovies = MutableLiveData<MutableList<Movie>>()
1717
val upcomingMovies: LiveData<MutableList<Movie>> = _upcomingMovies
18+
private val _searchLiveData = MutableLiveData<MutableList<Movie>>()
19+
var searchLiveData: LiveData<MutableList<Movie>> = _searchLiveData
20+
1821
private var page: Long = 0
1922

2023
init {
@@ -26,12 +29,24 @@ class HomeViewModel : ViewModel() {
2629
page = page.plus(1)
2730
viewModelScope.launch {
2831
val upcomingMoviesResponse = api.upcomingMovies(page = page)
29-
val moviesWithGenres = upcomingMoviesResponse.results.map { movie ->
30-
movie.copy(genres = Cache.genres.filter { movie.genreIds?.contains(it.id) == true })
31-
}
32-
val teste = _upcomingMovies.value
33-
teste?.addAll(moviesWithGenres)
34-
_upcomingMovies.postValue(teste)
32+
val moviesWithGenres = addGenres(upcomingMoviesResponse)
33+
val list = _upcomingMovies.value
34+
list?.addAll(moviesWithGenres)
35+
_upcomingMovies.postValue(list)
36+
}
37+
}
38+
39+
fun searchMovies(query: String) {
40+
viewModelScope.launch {
41+
val upcomingMoviesResponse = api.getMoviesByName(query)
42+
val moviesWithGenres = addGenres(upcomingMoviesResponse)
43+
_searchLiveData.postValue(moviesWithGenres.toMutableList())
44+
}
45+
}
46+
47+
private fun addGenres(upcomingMoviesResponse: UpcomingMoviesResponse): List<Movie> {
48+
return upcomingMoviesResponse.results.map { movie ->
49+
movie.copy(genres = Cache.genres.filter { movie.genreIds?.contains(it.id) == true })
3550
}
3651
}
3752
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector android:height="24dp" android:tint="#FFFFFF"
2+
android:viewportHeight="24.0" android:viewportWidth="24.0"
3+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
4+
<path android:fillColor="#FF000000" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
5+
</vector>

app/src/main/res/menu/search_menu.xml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
5+
<item
6+
android:id="@+id/search_action"
7+
android:icon="@drawable/ic_search_white_24dp"
8+
android:title="@string/search"
9+
app:actionViewClass="androidx.appcompat.widget.SearchView"
10+
app:showAsAction="always" />
11+
12+
</menu>

app/src/main/res/values/strings.xml

+1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
<string name="app_name">Code Challenge</string>
33
<string name="movie_genres">Gêneros: %1s</string>
44
<string name="release_date">Data de Lançamento: %1$s</string>
5+
<string name="search">Search</string>
56
</resources>

0 commit comments

Comments
 (0)