Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ interface MarvelDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertSearchKeyword(Keyword: SearchHistoryEntity): Completable

@Query("SELECT * FROM SEARCH_HISTORY_TABLE")
fun getSearchHistory(): Observable<List<SearchHistoryEntity>>

@Query("SELECT * FROM CHARACTER_TABLE")
fun getAllCharacters(): Observable<List<CharacterEntity>>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -31,7 +33,8 @@ interface MarvelRepository {
stringFavorites: String?,
): MutableList<FavoriteItem>?

fun saveSearchKeyword(keyword: String):Completable
fun saveSearchKeyword(keyword: String, id: Long = 0): Completable
fun getSearchHistory(): Observable<List<SearchHistory>>

//endregion
//region remote db
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -85,8 +86,12 @@ class MarvelRepositoryImp @Inject constructor(
stringFavorites, object : TypeToken<List<FavoriteItem>>() {}.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<List<SearchHistory>> {
return dao.getSearchHistory().map { entityToDomainContainer.searchHistoryMapper.map(it) }
}

override fun getCharactersByName(
Expand Down
10 changes: 9 additions & 1 deletion app/src/main/java/com/example/herohub/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ data class EntityToDomainContainer @Inject constructor(
val comicMapper: ComicEntityToComic,
val eventMapper: EventEntityToEvent,
val seriesMapper: SeriesEntityToSeries,
val searchHistoryMapper: SearchHistoryMapper,
)
Original file line number Diff line number Diff line change
@@ -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<SearchHistoryEntity>, List<SearchHistory>> {
override fun map(input: List<SearchHistoryEntity>): List<SearchHistory> {
return input.map {
SearchHistory(
id = it.id,
name = it.name
)
}
}
}
Original file line number Diff line number Diff line change
@@ -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,
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ class SearchFragment : BaseFragment<FragmentSearchScreenBinding>() {
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(
Expand All @@ -30,7 +32,7 @@ class SearchFragment : BaseFragment<FragmentSearchScreenBinding>() {

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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<SearchHistory>(listener) {
override val layoutId: Int = R.layout.item_search_history
}

interface SearchHistoryInteractionListener : BaseInteractionListener {
fun <T> onClickItemHistory(item: T)
}
31 changes: 28 additions & 3 deletions app/src/main/java/com/example/herohub/ui/search/SearchViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<EventHandler<Character>>()
Expand All @@ -36,8 +38,13 @@ class SearchViewModel @Inject constructor(

private val searchQuerySubject = PublishSubject.create<String>()

private val _searchHistory = MutableLiveData<List<SearchHistory>>()
val searchHistory: LiveData<List<SearchHistory>> = _searchHistory

init {
searchByMediatorLiveData()
getSearchHistory()
log("search history:${_searchHistory.value}")
}

@SuppressLint("CheckResult")
Expand All @@ -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>) {
_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")
Expand All @@ -81,5 +101,10 @@ class SearchViewModel @Inject constructor(

override fun <T> onClickItem(item: T) {
_eventClick.postValue(EventHandler(item as Character))
saveSearchHistory(item.name.toString(), item.id!!.toLong())
}

override fun <T> onClickItemHistory(item: T) {
searchQuery.postValue(item.toString())
}
}
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/baseline_close_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#000000"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
</vector>
23 changes: 22 additions & 1 deletion app/src/main/res/layout/fragment_search_screen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@
android:text="@={viewModel.searchQuery}"
app:layout_constraintTop_toTopOf="parent" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_search_history"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/spacing_medium"
android:layout_marginTop="@dimen/spacing_small"
android:clipChildren="false"
android:clipToPadding="false"
android:elevation="@dimen/spacing_tiny"
android:fitsSystemWindows="true"
android:visibility="visible"
app:items="@{viewModel.searchHistory}"
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/search_bar"
app:spanCount="4"
tools:listitem="@layout/item_search_history" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_search_result"
android:layout_width="match_parent"
Expand All @@ -42,12 +61,13 @@
android:layout_marginTop="@dimen/spacing_small"
android:clipToPadding="false"
android:visibility="visible"
android:elevation="@dimen/spacing_tiny"
app:items="@{viewModel.searchResult}"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/search_bar"
app:layout_constraintTop_toBottomOf="@id/rv_search_history"
app:showWhenSuccess="@{viewModel.response}"
app:spanCount="2"
tools:listitem="@layout/item_search" />
Expand All @@ -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}"
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/res/layout/item_search_history.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="item"
type="com.example.herohub.domain.model.SearchHistory" />

<variable
name="listener"
type="com.example.herohub.ui.search.SearchHistoryInteractionListener" />
</data>

<com.google.android.material.chip.Chip
android:id="@+id/text_search_history"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_small"
android:clickable="true"
android:onClick="@{() -> listener.onClickItemHistory(item.name)}"
android:text="@{item.name}"
android:textAlignment="center"
android:textColor="?attr/colorOnSurface"
tools:text="3-D MAN" />

</layout>