Visual changes to Search

This commit is contained in:
Prathamesh More 2021-09-26 17:09:46 +05:30
parent fb603bc0c5
commit 4054d89f46
6 changed files with 93 additions and 129 deletions

View file

@ -19,6 +19,7 @@ import androidx.lifecycle.*
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.db.* import code.name.monkey.retromusic.db.*
import code.name.monkey.retromusic.fragments.ReloadType.* import code.name.monkey.retromusic.fragments.ReloadType.*
import code.name.monkey.retromusic.fragments.search.Filter
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.*
@ -139,9 +140,9 @@ class LibraryViewModel(
} }
} }
fun search(query: String?, filters: List<Boolean>) { fun search(query: String?, filter: Filter) {
viewModelScope.launch(IO) { viewModelScope.launch(IO) {
val result = repository.search(query, filters) val result = repository.search(query, filter)
searchResults.postValue(result) searchResults.postValue(result)
} }
} }

View file

@ -25,7 +25,7 @@ import android.text.TextWatcher
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.CompoundButton import androidx.annotation.IdRes
import androidx.core.view.* import androidx.core.view.*
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -36,14 +36,17 @@ import code.name.monkey.retromusic.adapter.SearchAdapter
import code.name.monkey.retromusic.databinding.FragmentSearchBinding import code.name.monkey.retromusic.databinding.FragmentSearchBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.views.addAlpha
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.transition.MaterialSharedAxis import com.google.android.material.transition.MaterialSharedAxis
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWatcher, class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWatcher,
CompoundButton.OnCheckedChangeListener { ChipGroup.OnCheckedChangeListener {
companion object { companion object {
const val QUERY = "query" const val QUERY = "query"
const val REQ_CODE_SPEECH_INPUT = 9001 const val REQ_CODE_SPEECH_INPUT = 9001
@ -96,27 +99,22 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
private fun setupChips() { private fun setupChips() {
val chips = binding.searchFilterGroup.children.map { it as Chip } val chips = binding.searchFilterGroup.children.map { it as Chip }
val states = arrayOf( if (!PreferenceUtil.materialYou) {
intArrayOf(-android.R.attr.state_checked), val states = arrayOf(
intArrayOf(android.R.attr.state_checked) intArrayOf(-android.R.attr.state_checked),
) intArrayOf(android.R.attr.state_checked)
)
val colors = intArrayOf( val colors = intArrayOf(
android.R.color.transparent, android.R.color.transparent,
ThemeStore.accentColor(requireContext()) ThemeStore.accentColor(requireContext()).addAlpha(0.5F)
) )
chips.forEach { chips.forEach {
it.chipBackgroundColor = ColorStateList(states, colors) it.chipBackgroundColor = ColorStateList(states, colors)
it.chipIconTint = ColorStateList.valueOf(ThemeStore.textColorPrimary(requireContext())) }
it.chipStrokeColor =
ColorStateList.valueOf(ThemeStore.textColorSecondary(requireContext()))
.withAlpha(30)
it.closeIconTint =
ColorStateList.valueOf(ThemeStore.textColorPrimaryInverse(requireContext()))
it.chipStrokeWidth = 2F
it.setOnCheckedChangeListener(this)
} }
binding.searchFilterGroup.setOnCheckedChangeListener(this)
} }
private fun showData(data: List<Any>) { private fun showData(data: List<Any>) {
@ -168,13 +166,18 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
TransitionManager.beginDelayedTransition(binding.appBarLayout) TransitionManager.beginDelayedTransition(binding.appBarLayout)
binding.voiceSearch.isGone = query.isNotEmpty() binding.voiceSearch.isGone = query.isNotEmpty()
binding.clearText.isVisible = query.isNotEmpty() binding.clearText.isVisible = query.isNotEmpty()
val filters = getFilters() val filter = getFilter()
libraryViewModel.search(query, filters) libraryViewModel.search(query, filter)
} }
private fun getFilters(): List<Boolean> { private fun getFilter(): Filter {
return binding.searchFilterGroup.children.toList().map { return when (binding.searchFilterGroup.checkedChipId) {
(it as Chip).isChecked R.id.chip_audio -> Filter.SONGS
R.id.chip_artists -> Filter.ARTISTS
R.id.chip_albums -> Filter.ALBUMS
R.id.chip_album_artists -> Filter.ALBUM_ARTISTS
R.id.chip_genres -> Filter.GENRES
else -> Filter.NO_FILTER
} }
} }
@ -221,28 +224,20 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
} }
} }
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { override fun onCheckedChanged(group: ChipGroup?, @IdRes checkedId: Int) {
val checkedChip = (buttonView as Chip)
checkedChip.isCloseIconVisible = isChecked
if (isChecked) {
val color = ThemeStore.textColorPrimaryInverse(requireContext())
checkedChip.apply {
setTextColor(color)
chipIconTint = ColorStateList.valueOf(color)
chipStrokeWidth = 0F
}
} else {
val color = ThemeStore.textColorPrimary(requireContext())
checkedChip.apply {
setTextColor(color)
chipIconTint = ColorStateList.valueOf(color)
chipStrokeWidth = 2F
}
}
search(binding.searchView.text.toString()) search(binding.searchView.text.toString())
} }
} }
enum class Filter {
SONGS,
ARTISTS,
ALBUMS,
ALBUM_ARTISTS,
GENRES,
NO_FILTER
}
fun TextInputEditText.clearText() { fun TextInputEditText.clearText() {
text = null text = null
} }

View file

@ -19,6 +19,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.db.* import code.name.monkey.retromusic.db.*
import code.name.monkey.retromusic.fragments.search.Filter
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.model.smartplaylist.NotPlayedPlaylist import code.name.monkey.retromusic.model.smartplaylist.NotPlayedPlaylist
import code.name.monkey.retromusic.network.LastFMService import code.name.monkey.retromusic.network.LastFMService
@ -51,7 +52,7 @@ interface Repository {
suspend fun albumArtists(): List<Artist> suspend fun albumArtists(): List<Artist>
suspend fun fetchLegacyPlaylist(): List<Playlist> suspend fun fetchLegacyPlaylist(): List<Playlist>
suspend fun fetchGenres(): List<Genre> suspend fun fetchGenres(): List<Genre>
suspend fun search(query: String?, filters: List<Boolean>): MutableList<Any> suspend fun search(query: String?, filter: Filter): MutableList<Any>
suspend fun getPlaylistSongs(playlist: Playlist): List<Song> suspend fun getPlaylistSongs(playlist: Playlist): List<Song>
suspend fun getGenre(genreId: Long): List<Song> suspend fun getGenre(genreId: Long): List<Song>
suspend fun artistInfo(name: String, lang: String?, cache: String?): Result<LastFmArtist> suspend fun artistInfo(name: String, lang: String?, cache: String?): Result<LastFmArtist>
@ -163,8 +164,8 @@ class RealRepository(
override suspend fun allSongs(): List<Song> = songRepository.songs() override suspend fun allSongs(): List<Song> = songRepository.songs()
override suspend fun search(query: String?, filters: List<Boolean>): MutableList<Any> = override suspend fun search(query: String?, filter: Filter): MutableList<Any> =
searchRepository.searchAll(context, query, filters) searchRepository.searchAll(context, query, filter)
override suspend fun getPlaylistSongs(playlist: Playlist): List<Song> = override suspend fun getPlaylistSongs(playlist: Playlist): List<Song> =
if (playlist is AbsCustomPlaylist) { if (playlist is AbsCustomPlaylist) {

View file

@ -16,6 +16,7 @@ package code.name.monkey.retromusic.repository
import android.content.Context import android.content.Context
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.fragments.search.Filter
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
@ -28,11 +29,11 @@ class RealSearchRepository(
private val roomRepository: RoomRepository, private val roomRepository: RoomRepository,
private val genreRepository: GenreRepository, private val genreRepository: GenreRepository,
) { ) {
fun searchAll(context: Context, query: String?, filters: List<Boolean>): MutableList<Any> { fun searchAll(context: Context, query: String?, filter: Filter): MutableList<Any> {
val results = mutableListOf<Any>() val results = mutableListOf<Any>()
query?.let { searchString -> if (query.isNullOrEmpty()) return results
val isAll = !filters.contains(true) query.let { searchString ->
val songs: List<Song> = if (filters[0] || isAll) { val songs: List<Song> = if (filter == Filter.SONGS || filter == Filter.NO_FILTER) {
songRepository.songs(searchString) songRepository.songs(searchString)
} else { } else {
emptyList() emptyList()
@ -42,16 +43,17 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.songs)) results.add(context.resources.getString(R.string.songs))
results.addAll(songs) results.addAll(songs)
} }
val artists: List<Artist> = if (filters[1] || isAll) { val artists: List<Artist> =
artistRepository.artists(searchString) if (filter == Filter.ARTISTS || filter == Filter.NO_FILTER) {
} else { artistRepository.artists(searchString)
emptyList() } else {
} emptyList()
}
if (artists.isNotEmpty()) { if (artists.isNotEmpty()) {
results.add(context.resources.getString(R.string.artists)) results.add(context.resources.getString(R.string.artists))
results.addAll(artists) results.addAll(artists)
} }
val albums: List<Album> = if (filters[2] || isAll) { val albums: List<Album> = if (filter == Filter.ALBUMS || filter == Filter.NO_FILTER) {
albumRepository.albums(searchString) albumRepository.albums(searchString)
} else { } else {
emptyList() emptyList()
@ -60,16 +62,17 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.albums)) results.add(context.resources.getString(R.string.albums))
results.addAll(albums) results.addAll(albums)
} }
val albumArtists: List<Artist> = if (filters[3] || isAll) { val albumArtists: List<Artist> =
artistRepository.albumArtists(searchString) if (filter == Filter.ALBUM_ARTISTS || filter == Filter.NO_FILTER) {
} else { artistRepository.albumArtists(searchString)
emptyList() } else {
} emptyList()
}
if (albumArtists.isNotEmpty()) { if (albumArtists.isNotEmpty()) {
results.add(context.resources.getString(R.string.album_artist)) results.add(context.resources.getString(R.string.album_artist))
results.addAll(albumArtists) results.addAll(albumArtists)
} }
val genres: List<Genre> = if (filters[4] || isAll) { val genres: List<Genre> = if (filter == Filter.GENRES || filter == Filter.NO_FILTER) {
genreRepository.genres().filter { genre -> genreRepository.genres().filter { genre ->
genre.name.lowercase() genre.name.lowercase()
.contains(searchString.lowercase()) .contains(searchString.lowercase())
@ -82,13 +85,13 @@ class RealSearchRepository(
results.addAll(genres) results.addAll(genres)
} }
/* val playlist = roomRepository.playlists().filter { playlist -> /* val playlist = roomRepository.playlists().filter { playlist ->
playlist.playlistName.toLowerCase(Locale.getDefault()) playlist.playlistName.toLowerCase(Locale.getDefault())
.contains(searchString.toLowerCase(Locale.getDefault())) .contains(searchString.toLowerCase(Locale.getDefault()))
} }
if (playlist.isNotEmpty()) { if (playlist.isNotEmpty()) {
results.add(context.getString(R.string.playlists)) results.add(context.getString(R.string.playlists))
results.addAll(playlist) results.addAll(playlist)
}*/ }*/
} }
return results return results
} }

View file

@ -88,89 +88,43 @@
android:id="@+id/searchFilterGroup" android:id="@+id/searchFilterGroup"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:singleLine="true"> app:singleLine="true"
app:singleSelection="true">
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/chip_audio" android:id="@+id/chip_audio"
style="@style/Widget.MaterialComponents.Chip.Filter" style="@style/SearchChipStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="false" android:text="@string/songs" />
android:text="@string/songs"
android:textSize="16sp"
app:checkedIconEnabled="false"
app:chipEndPadding="10dp"
app:chipIcon="@drawable/ic_audiotrack"
app:chipIconEnabled="true"
app:chipMinHeight="40dp"
app:chipStartPadding="10dp"
app:iconEndPadding="5dp" />
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/chip_artists" android:id="@+id/chip_artists"
style="@style/Widget.MaterialComponents.Chip.Filter" style="@style/SearchChipStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="false" android:text="@string/artists" />
android:text="@string/artists"
android:textSize="16sp"
app:checkedIconEnabled="false"
app:chipEndPadding="10dp"
app:chipIcon="@drawable/ic_artist"
app:chipIconEnabled="true"
app:chipMinHeight="40dp"
app:chipStartPadding="10dp"
app:iconEndPadding="5dp" />
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/chip_albums" android:id="@+id/chip_albums"
style="@style/Widget.MaterialComponents.Chip.Filter" style="@style/SearchChipStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="false" android:text="@string/albums" />
android:text="@string/albums"
android:textSize="16sp"
app:checkedIconEnabled="false"
app:chipEndPadding="10dp"
app:chipIcon="@drawable/ic_album"
app:chipIconEnabled="true"
app:chipMinHeight="40dp"
app:chipStartPadding="10dp"
app:iconEndPadding="5dp" />
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/chip_album_artists" android:id="@+id/chip_album_artists"
style="@style/Widget.MaterialComponents.Chip.Filter" style="@style/SearchChipStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="false" android:text="@string/album_artist" />
android:text="@string/album_artist"
android:textSize="16sp"
app:checkedIconEnabled="false"
app:chipEndPadding="10dp"
app:chipIcon="@drawable/ic_album_artist"
app:chipIconEnabled="true"
app:chipMinHeight="40dp"
app:chipStartPadding="10dp"
app:iconEndPadding="5dp" />
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/chip_genres" android:id="@+id/chip_genres"
style="@style/Widget.MaterialComponents.Chip.Filter" style="@style/SearchChipStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="false" android:text="@string/genres" />
android:text="@string/genres"
android:textSize="16sp"
app:checkedIconEnabled="false"
app:chipEndPadding="10dp"
app:chipIcon="@drawable/ic_guitar"
app:chipIconEnabled="true"
app:chipMinHeight="40dp"
app:chipStartPadding="10dp"
app:iconEndPadding="5dp" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
</HorizontalScrollView> </HorizontalScrollView>

View file

@ -212,6 +212,16 @@
<item name="cornerFamily">rounded</item> <item name="cornerFamily">rounded</item>
<item name="cornerSize">5%</item> <item name="cornerSize">5%</item>
</style> </style>
<style name="SearchChipStyle" parent="Widget.Material3.Chip.Filter">
<item name="android:checked">false</item>
<item name="android:textSize">16sp</item>
<item name="checkedIconEnabled">true</item>
<item name="chipEndPadding">10dp</item>
<item name="chipIconEnabled">true</item>
<item name="chipMinHeight">40dp</item>
<item name="chipStartPadding">10dp</item>
</style>
<!--Bottom Sheet Dialog Style--> <!--Bottom Sheet Dialog Style-->
<style name="BottomSheetDialogStyle" parent="Theme.Design.BottomSheetDialog"> <style name="BottomSheetDialogStyle" parent="Theme.Design.BottomSheetDialog">
<item name="android:windowIsFloating">false</item> <item name="android:windowIsFloating">false</item>