diff --git a/app/src/main/java/com/example/herohub/data/local/SearchHistoryEntity.kt b/app/src/main/java/com/example/herohub/data/local/SearchHistoryEntity.kt index c95da85c..f8f37d6b 100644 --- a/app/src/main/java/com/example/herohub/data/local/SearchHistoryEntity.kt +++ b/app/src/main/java/com/example/herohub/data/local/SearchHistoryEntity.kt @@ -3,7 +3,7 @@ package com.example.herohub.data.local import androidx.room.Entity import androidx.room.PrimaryKey -@Entity +@Entity(tableName = "SEARCH_HISTORY_TABLE") data class SearchHistoryEntity( @PrimaryKey(autoGenerate = true) val id: Long =0, val name: String diff --git a/app/src/main/java/com/example/herohub/data/local/dao/MarvelDao.kt b/app/src/main/java/com/example/herohub/data/local/dao/MarvelDao.kt index fcd4c66e..4070c522 100644 --- a/app/src/main/java/com/example/herohub/data/local/dao/MarvelDao.kt +++ b/app/src/main/java/com/example/herohub/data/local/dao/MarvelDao.kt @@ -14,6 +14,9 @@ interface MarvelDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertSearchKeyword(Keyword: SearchHistoryEntity): Completable + @Query("SELECT * FROM SEARCH_HISTORY_TABLE") + fun getSearchHistory(): Observable> + @Query("SELECT * FROM CHARACTER_TABLE") fun getAllCharacters(): Observable> diff --git a/app/src/main/java/com/example/herohub/data/repository/MarvelRepository.kt b/app/src/main/java/com/example/herohub/data/repository/MarvelRepository.kt index 6b812c90..f6de85ac 100644 --- a/app/src/main/java/com/example/herohub/data/repository/MarvelRepository.kt +++ b/app/src/main/java/com/example/herohub/data/repository/MarvelRepository.kt @@ -4,9 +4,11 @@ import com.example.herohub.domain.model.Character import com.example.herohub.domain.model.Comic import com.example.herohub.domain.model.Event import com.example.herohub.domain.model.FavoriteItem +import com.example.herohub.domain.model.SearchHistory import com.example.herohub.domain.model.Series import com.example.herohub.ui.utils.UiState import com.google.gson.Gson +import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.Single @@ -31,7 +33,8 @@ interface MarvelRepository { stringFavorites: String?, ): MutableList? - fun saveSearchKeyword(keyword: String):Completable + fun saveSearchKeyword(keyword: String, id: Long = 0): Completable + fun getSearchHistory(): Observable> //endregion //region remote db diff --git a/app/src/main/java/com/example/herohub/data/repository/MarvelRepositoryImp.kt b/app/src/main/java/com/example/herohub/data/repository/MarvelRepositoryImp.kt index f45b29e2..0e3daee2 100644 --- a/app/src/main/java/com/example/herohub/data/repository/MarvelRepositoryImp.kt +++ b/app/src/main/java/com/example/herohub/data/repository/MarvelRepositoryImp.kt @@ -14,6 +14,7 @@ import com.example.herohub.domain.model.Character import com.example.herohub.domain.model.Comic import com.example.herohub.domain.model.Event import com.example.herohub.domain.model.FavoriteItem +import com.example.herohub.domain.model.SearchHistory import com.example.herohub.domain.model.Series import com.example.herohub.ui.utils.UiState import com.google.gson.Gson @@ -85,8 +86,12 @@ class MarvelRepositoryImp @Inject constructor( stringFavorites, object : TypeToken>() {}.type ) - override fun saveSearchKeyword(keyword: String): Completable { - return dao.insertSearchKeyword(SearchHistoryEntity(name = keyword)) + override fun saveSearchKeyword(keyword: String, id: Long): Completable { + return dao.insertSearchKeyword(SearchHistoryEntity(name = keyword, id = id)) + } + + override fun getSearchHistory(): Observable> { + return dao.getSearchHistory().map { entityToDomainContainer.searchHistoryMapper.map(it) } } override fun getCharactersByName( diff --git a/app/src/main/java/com/example/herohub/di/RepositoryModule.kt b/app/src/main/java/com/example/herohub/di/RepositoryModule.kt index f16516d2..52f89fdf 100644 --- a/app/src/main/java/com/example/herohub/di/RepositoryModule.kt +++ b/app/src/main/java/com/example/herohub/di/RepositoryModule.kt @@ -18,6 +18,7 @@ import com.example.herohub.domain.mapper.entity_to_domain_mapper.CharacterEntity import com.example.herohub.domain.mapper.entity_to_domain_mapper.ComicEntityToComic import com.example.herohub.domain.mapper.entity_to_domain_mapper.EntityToDomainContainer import com.example.herohub.domain.mapper.entity_to_domain_mapper.EventEntityToEvent +import com.example.herohub.domain.mapper.entity_to_domain_mapper.SearchHistoryMapper import com.example.herohub.domain.mapper.entity_to_domain_mapper.SeriesEntityToSeries import dagger.Module import dagger.Provides @@ -64,8 +65,15 @@ object RepositoryModule { comicMapper: ComicEntityToComic, eventMapper: EventEntityToEvent, seriesMapper: SeriesEntityToSeries, + searchHistoryMapper: SearchHistoryMapper, ): EntityToDomainContainer = - EntityToDomainContainer(characterMapper, comicMapper, eventMapper, seriesMapper) + EntityToDomainContainer( + characterMapper, + comicMapper, + eventMapper, + seriesMapper, + searchHistoryMapper + ) @Singleton @Provides diff --git a/app/src/main/java/com/example/herohub/domain/mapper/entity_to_domain_mapper/EntityToDomainContainer.kt b/app/src/main/java/com/example/herohub/domain/mapper/entity_to_domain_mapper/EntityToDomainContainer.kt index 81d8dae1..eb36edda 100644 --- a/app/src/main/java/com/example/herohub/domain/mapper/entity_to_domain_mapper/EntityToDomainContainer.kt +++ b/app/src/main/java/com/example/herohub/domain/mapper/entity_to_domain_mapper/EntityToDomainContainer.kt @@ -7,4 +7,5 @@ data class EntityToDomainContainer @Inject constructor( val comicMapper: ComicEntityToComic, val eventMapper: EventEntityToEvent, val seriesMapper: SeriesEntityToSeries, + val searchHistoryMapper: SearchHistoryMapper, ) diff --git a/app/src/main/java/com/example/herohub/domain/mapper/entity_to_domain_mapper/SearchHistoryMapper.kt b/app/src/main/java/com/example/herohub/domain/mapper/entity_to_domain_mapper/SearchHistoryMapper.kt new file mode 100644 index 00000000..c17dd84b --- /dev/null +++ b/app/src/main/java/com/example/herohub/domain/mapper/entity_to_domain_mapper/SearchHistoryMapper.kt @@ -0,0 +1,22 @@ +package com.example.herohub.domain.mapper.entity_to_domain_mapper + +import com.example.herohub.data.local.SearchHistoryEntity +import com.example.herohub.domain.mapper.Mapper +import com.example.herohub.domain.model.SearchHistory +import javax.inject.Inject + +/** + * Created by Asia sama on 5/19/2023. + * sehunexo710@gmail.com + */ +class SearchHistoryMapper @Inject constructor() : + Mapper, List> { + override fun map(input: List): List { + return input.map { + SearchHistory( + id = it.id, + name = it.name + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/herohub/domain/model/SearchHistory.kt b/app/src/main/java/com/example/herohub/domain/model/SearchHistory.kt new file mode 100644 index 00000000..8c05cf20 --- /dev/null +++ b/app/src/main/java/com/example/herohub/domain/model/SearchHistory.kt @@ -0,0 +1,10 @@ +package com.example.herohub.domain.model + +/** + * Created by Asia sama on 5/19/2023. + * sehunexo710@gmail.com + */ +data class SearchHistory( + val id: Long, + val name: String, +) diff --git a/app/src/main/java/com/example/herohub/ui/search/SearchFragment.kt b/app/src/main/java/com/example/herohub/ui/search/SearchFragment.kt index d1dde778..c46696f9 100644 --- a/app/src/main/java/com/example/herohub/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/example/herohub/ui/search/SearchFragment.kt @@ -16,9 +16,11 @@ class SearchFragment : BaseFragment() { override val layoutIdFragment = R.layout.fragment_search_screen override val viewModel: SearchViewModel by viewModels() private val adapter: SearchAdapter by lazy { SearchAdapter(viewModel) } + private val searchHistoryAdapter: SearchHistoryAdapter by lazy { SearchHistoryAdapter(viewModel) } override fun setup() { binding.rvSearchResult.adapter = adapter + binding.rvSearchHistory.adapter = searchHistoryAdapter viewModel.eventClick.observe(this, EventObserve { val action = SearchFragmentDirections.actionSearchFragmentToCharactersDetailsFragment( @@ -30,7 +32,7 @@ class SearchFragment : BaseFragment() { binding.searchBar.setOnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_SEARCH) { - viewModel.saveSearchHistory(viewModel.searchQuery.value.toString()) + viewModel.saveSearchHistory(viewModel.searchQuery.value.toString(), 0) log(viewModel.searchQuery.value.toString()) true } else { diff --git a/app/src/main/java/com/example/herohub/ui/search/SearchHistoryAdapter.kt b/app/src/main/java/com/example/herohub/ui/search/SearchHistoryAdapter.kt new file mode 100644 index 00000000..e461657b --- /dev/null +++ b/app/src/main/java/com/example/herohub/ui/search/SearchHistoryAdapter.kt @@ -0,0 +1,16 @@ +package com.example.herohub.ui.search + + +import com.example.herohub.R +import com.example.herohub.domain.model.SearchHistory +import com.example.herohub.ui.base.BaseAdapter +import com.example.herohub.ui.base.BaseInteractionListener + +class SearchHistoryAdapter(listener: SearchHistoryInteractionListener) : + BaseAdapter(listener) { + override val layoutId: Int = R.layout.item_search_history +} + +interface SearchHistoryInteractionListener : BaseInteractionListener { + fun onClickItemHistory(item: T) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/herohub/ui/search/SearchViewModel.kt b/app/src/main/java/com/example/herohub/ui/search/SearchViewModel.kt index 269dfb65..a3e3d3d9 100644 --- a/app/src/main/java/com/example/herohub/ui/search/SearchViewModel.kt +++ b/app/src/main/java/com/example/herohub/ui/search/SearchViewModel.kt @@ -7,10 +7,12 @@ import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import com.example.herohub.data.repository.MarvelRepository import com.example.herohub.domain.model.Character +import com.example.herohub.domain.model.SearchHistory import com.example.herohub.ui.base.BaseViewModel import com.example.herohub.ui.utils.EventHandler import com.example.herohub.ui.utils.UiState import dagger.hilt.android.lifecycle.HiltViewModel +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.subjects.PublishSubject import java.util.concurrent.TimeUnit @@ -20,7 +22,7 @@ import javax.inject.Inject @HiltViewModel class SearchViewModel @Inject constructor( private val marvelRepositoryImp: MarvelRepository, -) : BaseViewModel(), SearchInteractionListener { +) : BaseViewModel(), SearchInteractionListener, SearchHistoryInteractionListener { override val TAG: String = this::class.java.simpleName.toString() private val _eventClick = MutableLiveData>() @@ -36,8 +38,13 @@ class SearchViewModel @Inject constructor( private val searchQuerySubject = PublishSubject.create() + private val _searchHistory = MutableLiveData>() + val searchHistory: LiveData> = _searchHistory + init { searchByMediatorLiveData() + getSearchHistory() + log("search history:${_searchHistory.value}") } @SuppressLint("CheckResult") @@ -60,8 +67,21 @@ class SearchViewModel @Inject constructor( ) } - fun saveSearchHistory(keyword: String) { - marvelRepositoryImp.saveSearchKeyword(keyword) + @SuppressLint("CheckResult") + private fun getSearchHistory() { + marvelRepositoryImp.getSearchHistory() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(::onGetSearchHistorySuccess, ::onGetCharacterFailure) + } + + private fun onGetSearchHistorySuccess(searchHistories: List) { + _searchHistory.postValue(searchHistories) + Log.e("TAG", "onGetSearchHistorySuccess: $searchHistories") + } + + fun saveSearchHistory(keyword: String, id: Long) { + marvelRepositoryImp.saveSearchKeyword(keyword, id) .subscribeOn(Schedulers.io()) .subscribe() Log.e("TAG", "saveSearchHistory: $keyword") @@ -81,5 +101,10 @@ class SearchViewModel @Inject constructor( override fun onClickItem(item: T) { _eventClick.postValue(EventHandler(item as Character)) + saveSearchHistory(item.name.toString(), item.id!!.toLong()) + } + + override fun onClickItemHistory(item: T) { + searchQuery.postValue(item.toString()) } } \ No newline at end of file diff --git a/app/src/main/res/drawable/baseline_close_24.xml b/app/src/main/res/drawable/baseline_close_24.xml new file mode 100644 index 00000000..35b13485 --- /dev/null +++ b/app/src/main/res/drawable/baseline_close_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_search_screen.xml b/app/src/main/res/layout/fragment_search_screen.xml index 101603d5..c87c7184 100644 --- a/app/src/main/res/layout/fragment_search_screen.xml +++ b/app/src/main/res/layout/fragment_search_screen.xml @@ -34,6 +34,25 @@ android:text="@={viewModel.searchQuery}" app:layout_constraintTop_toTopOf="parent" /> + + @@ -56,6 +76,7 @@ android:id="@+id/image_search" android:layout_width="300dp" android:layout_height="400dp" + android:alpha="0.4" android:background="@drawable/search3" app:hideWhenNotFound="@{viewModel.searchResult}" app:hideWhenSearch="@{viewModel.searchQuery}" diff --git a/app/src/main/res/layout/item_search_history.xml b/app/src/main/res/layout/item_search_history.xml new file mode 100644 index 00000000..057d8c7f --- /dev/null +++ b/app/src/main/res/layout/item_search_history.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + \ No newline at end of file