mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 09:33:33 +00:00
Search page renewed
This commit is contained in:
parent
a4dc5f643d
commit
a7fd7688ab
13 changed files with 358 additions and 174 deletions
|
|
@ -17,6 +17,7 @@ import com.cappielloantonio.play.model.Album;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder> {
|
||||
private static final String TAG = "AlbumAdapter";
|
||||
|
|
@ -75,7 +76,16 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
|
|||
public void onClick(View view) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable("album_object", albums.get(getBindingAdapterPosition()));
|
||||
Navigation.findNavController(view).navigate(R.id.action_libraryFragment_to_albumPageFragment, bundle);
|
||||
|
||||
if (Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.searchFragment) {
|
||||
Navigation.findNavController(view).navigate(R.id.action_searchFragment_to_albumPageFragment, bundle);
|
||||
}
|
||||
else if(Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.libraryFragment) {
|
||||
Navigation.findNavController(view).navigate(R.id.action_libraryFragment_to_albumPageFragment, bundle);
|
||||
}
|
||||
else if(Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.albumCatalogueFragment) {
|
||||
Navigation.findNavController(view).navigate(R.id.action_albumCatalogueFragment_to_albumPageFragment, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.cappielloantonio.play.model.Artist;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder> {
|
||||
private static final String TAG = "ArtistAdapter";
|
||||
|
|
@ -72,7 +73,16 @@ public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder
|
|||
public void onClick(View view) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable("artist_object", artists.get(getBindingAdapterPosition()));
|
||||
Navigation.findNavController(view).navigate(R.id.action_libraryFragment_to_artistPageFragment, bundle);
|
||||
|
||||
if (Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.searchFragment) {
|
||||
Navigation.findNavController(view).navigate(R.id.action_searchFragment_to_artistPageFragment, bundle);
|
||||
}
|
||||
else if(Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.libraryFragment) {
|
||||
Navigation.findNavController(view).navigate(R.id.action_libraryFragment_to_artistPageFragment, bundle);
|
||||
}
|
||||
else if(Objects.requireNonNull(Navigation.findNavController(view).getCurrentDestination()).getId() == R.id.artistCatalogueFragment) {
|
||||
Navigation.findNavController(view).navigate(R.id.action_artistCatalogueFragment_to_artistPageFragment, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import com.cappielloantonio.play.model.Song;
|
|||
import com.cappielloantonio.play.model.SongArtistCross;
|
||||
import com.cappielloantonio.play.model.SongGenreCross;
|
||||
|
||||
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class, SongGenreCross.class, Queue.class, AlbumArtistCross.class, SongArtistCross.class, PlaylistSongCross.class}, version = 10, exportSchema = false)
|
||||
@Database(entities = {Album.class, Artist.class, Genre.class, Playlist.class, Song.class, RecentSearch.class, SongGenreCross.class, Queue.class, AlbumArtistCross.class, SongArtistCross.class, PlaylistSongCross.class}, version = 11, exportSchema = false)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
private static final String TAG = "AppDatabase";
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import androidx.room.Insert;
|
|||
import androidx.room.OnConflictStrategy;
|
||||
import androidx.room.Query;
|
||||
|
||||
import com.cappielloantonio.play.model.Artist;
|
||||
import com.cappielloantonio.play.model.Genre;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -27,4 +28,10 @@ public interface GenreDao {
|
|||
|
||||
@Query("DELETE FROM genre")
|
||||
void deleteAll();
|
||||
|
||||
@Query("SELECT * FROM genre WHERE name LIKE '%' || :name || '%'")
|
||||
LiveData<List<Genre>> searchGenre(String name);
|
||||
|
||||
@Query("SELECT name FROM genre WHERE name LIKE :query || '%' OR name like '% ' || :query || '%' GROUP BY name LIMIT :number")
|
||||
List<String> searchSuggestions(String query, int number);
|
||||
}
|
||||
|
|
@ -13,12 +13,15 @@ import java.util.List;
|
|||
|
||||
@Dao
|
||||
public interface RecentSearchDao {
|
||||
@Query("SELECT * FROM recent_search GROUP BY search ORDER BY id DESC LIMIT :limit")
|
||||
LiveData<List<RecentSearch>> getLast(int limit);
|
||||
@Query("SELECT * FROM recent_search GROUP BY search ORDER BY search DESC LIMIT :limit")
|
||||
List<String> getRecent(int limit);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
void insert(RecentSearch search);
|
||||
|
||||
@Delete
|
||||
void delete(RecentSearch search);
|
||||
|
||||
@Query("DELETE FROM recent_search")
|
||||
void deleteAll();
|
||||
}
|
||||
|
|
@ -8,10 +8,7 @@ import androidx.room.PrimaryKey;
|
|||
@Entity(tableName = "recent_search")
|
||||
public class RecentSearch {
|
||||
@NonNull
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = "id")
|
||||
private int id;
|
||||
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "search")
|
||||
private String search;
|
||||
|
||||
|
|
@ -20,14 +17,6 @@ public class RecentSearch {
|
|||
}
|
||||
|
||||
@NonNull
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@NonNull int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getSearch() {
|
||||
return search;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ import android.app.Application;
|
|||
import androidx.lifecycle.LiveData;
|
||||
|
||||
import com.cappielloantonio.play.database.AppDatabase;
|
||||
import com.cappielloantonio.play.database.dao.ArtistDao;
|
||||
import com.cappielloantonio.play.database.dao.GenreDao;
|
||||
import com.cappielloantonio.play.database.dao.SongGenreCrossDao;
|
||||
import com.cappielloantonio.play.model.Artist;
|
||||
import com.cappielloantonio.play.model.Genre;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -17,6 +19,7 @@ public class GenreRepository {
|
|||
private SongGenreCrossDao songGenreCrossDao;
|
||||
private LiveData<List<Genre>> listLiveGenres;
|
||||
private LiveData<List<Genre>> listLiveAlbumGenre;
|
||||
private LiveData<List<Genre>> searchListLiveGenre;
|
||||
|
||||
public GenreRepository(Application application) {
|
||||
AppDatabase database = AppDatabase.getInstance(application);
|
||||
|
|
@ -110,4 +113,48 @@ public class GenreRepository {
|
|||
genreDao.deleteAll();
|
||||
}
|
||||
}
|
||||
|
||||
public LiveData<List<Genre>> searchListLiveGenre(String name) {
|
||||
searchListLiveGenre = genreDao.searchGenre(name);
|
||||
return searchListLiveGenre;
|
||||
}
|
||||
|
||||
public List<String> getSearchSuggestion(String query) {
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
|
||||
SearchSuggestionsThreadSafe suggestionsThread = new SearchSuggestionsThreadSafe(genreDao, query, 5);
|
||||
Thread thread = new Thread(suggestionsThread);
|
||||
thread.start();
|
||||
|
||||
try {
|
||||
thread.join();
|
||||
suggestions = suggestionsThread.getSuggestions();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
private static class SearchSuggestionsThreadSafe implements Runnable {
|
||||
private GenreDao genreDao;
|
||||
private String query;
|
||||
private int number;
|
||||
private List<String> suggestions = new ArrayList<>();
|
||||
|
||||
public SearchSuggestionsThreadSafe(GenreDao genreDao, String query, int number) {
|
||||
this.genreDao = genreDao;
|
||||
this.query = query;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
suggestions = genreDao.searchSuggestions(query, number);
|
||||
}
|
||||
|
||||
public List<String> getSuggestions() {
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,20 +8,15 @@ import com.cappielloantonio.play.database.AppDatabase;
|
|||
import com.cappielloantonio.play.database.dao.RecentSearchDao;
|
||||
import com.cappielloantonio.play.model.RecentSearch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RecentSearchRepository {
|
||||
private RecentSearchDao recentSearchDao;
|
||||
private LiveData<List<RecentSearch>> listLiveRecentSearches;
|
||||
|
||||
public RecentSearchRepository(Application application) {
|
||||
AppDatabase database = AppDatabase.getInstance(application);
|
||||
recentSearchDao = database.recentSearchDao();
|
||||
listLiveRecentSearches = recentSearchDao.getLast(3);
|
||||
}
|
||||
|
||||
public LiveData<List<RecentSearch>> getListLiveRecentSearches() {
|
||||
return listLiveRecentSearches;
|
||||
}
|
||||
|
||||
public void insert(RecentSearch recentSearch) {
|
||||
|
|
@ -30,6 +25,27 @@ public class RecentSearchRepository {
|
|||
thread.start();
|
||||
}
|
||||
|
||||
public void delete(RecentSearch recentSearch) {
|
||||
DeleteThreadSafe delete = new DeleteThreadSafe(recentSearchDao, recentSearch);
|
||||
Thread thread = new Thread(delete);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private static class DeleteThreadSafe implements Runnable {
|
||||
private RecentSearchDao recentSearchDao;
|
||||
private RecentSearch recentSearch;
|
||||
|
||||
public DeleteThreadSafe(RecentSearchDao recentSearchDao, RecentSearch recentSearch) {
|
||||
this.recentSearchDao = recentSearchDao;
|
||||
this.recentSearch = recentSearch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
recentSearchDao.delete(recentSearch);
|
||||
}
|
||||
}
|
||||
|
||||
private static class InsertThreadSafe implements Runnable {
|
||||
private RecentSearchDao recentSearchDao;
|
||||
private RecentSearch recentSearch;
|
||||
|
|
@ -63,4 +79,41 @@ public class RecentSearchRepository {
|
|||
recentSearchDao.deleteAll();
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getRecentSearchSuggestion() {
|
||||
List<String> recent = new ArrayList<>();
|
||||
|
||||
RecentThreadSafe suggestionsThread = new RecentThreadSafe(recentSearchDao,10);
|
||||
Thread thread = new Thread(suggestionsThread);
|
||||
thread.start();
|
||||
|
||||
try {
|
||||
thread.join();
|
||||
recent = suggestionsThread.getRecent();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return recent;
|
||||
}
|
||||
|
||||
private static class RecentThreadSafe implements Runnable {
|
||||
private RecentSearchDao recentSearchDao;
|
||||
private int limit;
|
||||
private List<String> recent = new ArrayList<>();
|
||||
|
||||
public RecentThreadSafe(RecentSearchDao recentSearchDao, int limit) {
|
||||
this.recentSearchDao = recentSearchDao;
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
recent = recentSearchDao.getRecent(limit);
|
||||
}
|
||||
|
||||
public List<String> getRecent() {
|
||||
return recent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,18 @@ import androidx.lifecycle.ViewModelProvider;
|
|||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.cappielloantonio.play.R;
|
||||
import com.cappielloantonio.play.adapter.AlbumAdapter;
|
||||
import com.cappielloantonio.play.adapter.AlbumCatalogueAdapter;
|
||||
import com.cappielloantonio.play.adapter.ArtistAdapter;
|
||||
import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter;
|
||||
import com.cappielloantonio.play.adapter.GenreCatalogueAdapter;
|
||||
import com.cappielloantonio.play.adapter.RecentSearchAdapter;
|
||||
import com.cappielloantonio.play.adapter.SongResultSearchAdapter;
|
||||
import com.cappielloantonio.play.databinding.FragmentSearchBinding;
|
||||
import com.cappielloantonio.play.helper.recyclerview.GridItemDecoration;
|
||||
import com.cappielloantonio.play.model.RecentSearch;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.ui.activities.MainActivity;
|
||||
import com.cappielloantonio.play.viewmodel.SearchViewModel;
|
||||
import com.paulrybitskyi.persistentsearchview.adapters.model.SuggestionItem;
|
||||
|
|
@ -35,10 +40,10 @@ public class SearchFragment extends Fragment {
|
|||
private MainActivity activity;
|
||||
private SearchViewModel searchViewModel;
|
||||
|
||||
private RecentSearchAdapter recentSearchAdapter;
|
||||
private SongResultSearchAdapter songResultSearchAdapter;
|
||||
private AlbumCatalogueAdapter albumResultSearchAdapter;
|
||||
private ArtistCatalogueAdapter artistResultSearchAdapter;
|
||||
private AlbumAdapter albumAdapter;
|
||||
private ArtistAdapter artistAdapter;
|
||||
private GenreCatalogueAdapter genreCatalogueAdapter;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
|
@ -49,8 +54,6 @@ public class SearchFragment extends Fragment {
|
|||
View view = bind.getRoot();
|
||||
searchViewModel = new ViewModelProvider(requireActivity()).get(SearchViewModel.class);
|
||||
|
||||
init();
|
||||
initRecentSearchView();
|
||||
initSearchResultView();
|
||||
initSearchView();
|
||||
|
||||
|
|
@ -63,30 +66,18 @@ public class SearchFragment extends Fragment {
|
|||
activity.setBottomNavigationBarVisibility(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
inputFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
bind = null;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
bind.clearAllSearchTextViewClickable.setOnClickListener(v -> searchViewModel.deleteAllRecentSearch());
|
||||
}
|
||||
|
||||
private void initRecentSearchView() {
|
||||
bind.recentlySearchedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
bind.recentlySearchedTracksRecyclerView.setHasFixedSize(true);
|
||||
|
||||
recentSearchAdapter = new RecentSearchAdapter(requireContext());
|
||||
recentSearchAdapter.setClickListener((view, position) -> {
|
||||
RecentSearch search = recentSearchAdapter.getItem(position);
|
||||
search(search.getSearch());
|
||||
});
|
||||
bind.recentlySearchedTracksRecyclerView.setAdapter(recentSearchAdapter);
|
||||
|
||||
searchViewModel.getSearchList().observe(requireActivity(), recentSearches -> recentSearchAdapter.setItems(recentSearches));
|
||||
}
|
||||
|
||||
private void initSearchResultView() {
|
||||
// Songs
|
||||
bind.searchResultTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
|
|
@ -96,28 +87,47 @@ public class SearchFragment extends Fragment {
|
|||
bind.searchResultTracksRecyclerView.setAdapter(songResultSearchAdapter);
|
||||
|
||||
// Albums
|
||||
bind.searchResultAlbumRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2));
|
||||
bind.searchResultAlbumRecyclerView.addItemDecoration(new GridItemDecoration(2, 20, false));
|
||||
bind.searchResultAlbumRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
bind.searchResultAlbumRecyclerView.setHasFixedSize(true);
|
||||
|
||||
albumResultSearchAdapter = new AlbumCatalogueAdapter(requireContext());
|
||||
bind.searchResultAlbumRecyclerView.setAdapter(albumResultSearchAdapter);
|
||||
albumAdapter = new AlbumAdapter(requireContext());
|
||||
bind.searchResultAlbumRecyclerView.setAdapter(albumAdapter);
|
||||
|
||||
// Artist
|
||||
bind.searchResultArtistRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2));
|
||||
bind.searchResultArtistRecyclerView.addItemDecoration(new GridItemDecoration(2, 20, false));
|
||||
// Artists
|
||||
bind.searchResultArtistRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
bind.searchResultArtistRecyclerView.setHasFixedSize(true);
|
||||
|
||||
artistResultSearchAdapter = new ArtistCatalogueAdapter(requireContext());
|
||||
bind.searchResultArtistRecyclerView.setAdapter(artistResultSearchAdapter);
|
||||
artistAdapter = new ArtistAdapter(requireContext());
|
||||
bind.searchResultArtistRecyclerView.setAdapter(artistAdapter);
|
||||
|
||||
// Genres
|
||||
bind.searchResultGenreRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2));
|
||||
bind.searchResultGenreRecyclerView.addItemDecoration(new GridItemDecoration(2, 16, false));
|
||||
bind.searchResultGenreRecyclerView.setHasFixedSize(true);
|
||||
|
||||
genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext());
|
||||
genreCatalogueAdapter.setClickListener((view, position) -> {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(Song.BY_GENRE, Song.BY_GENRE);
|
||||
bundle.putParcelable("genre_object", genreCatalogueAdapter.getItem(position));
|
||||
activity.navController.navigate(R.id.action_searchFragment_to_songListPageFragment, bundle);
|
||||
});
|
||||
bind.searchResultGenreRecyclerView.setAdapter(genreCatalogueAdapter);
|
||||
}
|
||||
|
||||
private void initSearchView() {
|
||||
if (isQueryValid(searchViewModel.getQuery())) {
|
||||
search(searchViewModel.getQuery());
|
||||
}
|
||||
|
||||
bind.persistentSearchView.setInputQuery(searchViewModel.getQuery());
|
||||
setSuggestions();
|
||||
|
||||
bind.persistentSearchView.setOnSearchQueryChangeListener((searchView, oldQuery, newQuery) -> {
|
||||
if (!newQuery.trim().equals("") && newQuery.trim().length() > 1) {
|
||||
searchView.setSuggestions(SuggestionCreationUtil.asRegularSearchSuggestions(searchViewModel.getSearchSuggestion(newQuery)), false);
|
||||
} else {
|
||||
searchView.setSuggestions(new ArrayList<>());
|
||||
setSuggestions();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -133,27 +143,69 @@ public class SearchFragment extends Fragment {
|
|||
});
|
||||
|
||||
bind.persistentSearchView.setOnSearchConfirmedListener((searchView, query) -> {
|
||||
search(query);
|
||||
if (isQueryValid(query)) {
|
||||
searchView.collapse();
|
||||
search(query);
|
||||
}
|
||||
else {
|
||||
Toast.makeText(requireContext(), "Enter at least three characters", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
bind.persistentSearchView.setOnSuggestionChangeListener(new OnSuggestionChangeListener() {
|
||||
@Override
|
||||
public void onSuggestionPicked(SuggestionItem suggestion) {
|
||||
search(suggestion.getItemModel().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuggestionRemoved(SuggestionItem suggestion) {
|
||||
searchViewModel.deleteRecentSearch(suggestion.getItemModel().getText());
|
||||
}
|
||||
});
|
||||
|
||||
bind.persistentSearchView.setOnClearInputBtnClickListener(v -> searchViewModel.setQuery(""));
|
||||
}
|
||||
|
||||
private void setSuggestions() {
|
||||
bind.persistentSearchView.setSuggestions(SuggestionCreationUtil.asRecentSearchSuggestions(searchViewModel.getRecentSearchSuggestion()), false);
|
||||
}
|
||||
|
||||
public void search(String query) {
|
||||
if (!query.trim().equals("") && query.trim().length() > 2) {
|
||||
searchViewModel.insertNewSearch(query);
|
||||
bind.persistentSearchView.collapse();
|
||||
searchViewModel.setQuery(query);
|
||||
|
||||
bind.persistentSearchView.setInputQuery(query);
|
||||
performSearch(query.trim());
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Enter at least three characters", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
bind.persistentSearchView.setInputQuery(query);
|
||||
performSearch(query);
|
||||
}
|
||||
|
||||
private void performSearch(String query) {
|
||||
searchViewModel.searchSong(query).observe(requireActivity(), songs -> songResultSearchAdapter.setItems(songs));
|
||||
searchViewModel.searchAlbum(query).observe(requireActivity(), albums -> albumResultSearchAdapter.setItems(albums));
|
||||
searchViewModel.searchArtist(query).observe(requireActivity(), artists -> artistResultSearchAdapter.setItems(artists));
|
||||
searchViewModel.searchSong(query).observe(requireActivity(), songs -> {
|
||||
if(bind != null) bind.searchSongSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
songResultSearchAdapter.setItems(songs);
|
||||
});
|
||||
searchViewModel.searchAlbum(query).observe(requireActivity(), albums -> {
|
||||
if(bind != null) bind.searchAlbumSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
albumAdapter.setItems(albums);
|
||||
});
|
||||
searchViewModel.searchArtist(query).observe(requireActivity(), artists -> {
|
||||
if(bind != null) bind.searchArtistSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
artistAdapter.setItems(artists);
|
||||
});
|
||||
searchViewModel.searchGenre(query).observe(requireActivity(), genres -> {
|
||||
if(bind != null) bind.searchGenreSector.setVisibility(!genres.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
genreCatalogueAdapter.setItems(genres);
|
||||
});
|
||||
|
||||
bind.searchResultLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private boolean isQueryValid(String query) {
|
||||
return !query.equals("") && query.trim().length() > 2;
|
||||
}
|
||||
|
||||
private void inputFocus() {
|
||||
if(!isQueryValid(searchViewModel.getQuery())) {
|
||||
bind.persistentSearchView.expand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@ import androidx.lifecycle.LiveData;
|
|||
|
||||
import com.cappielloantonio.play.model.Album;
|
||||
import com.cappielloantonio.play.model.Artist;
|
||||
import com.cappielloantonio.play.model.Genre;
|
||||
import com.cappielloantonio.play.model.RecentSearch;
|
||||
import com.cappielloantonio.play.model.Song;
|
||||
import com.cappielloantonio.play.repository.AlbumRepository;
|
||||
import com.cappielloantonio.play.repository.ArtistRepository;
|
||||
import com.cappielloantonio.play.repository.GenreRepository;
|
||||
import com.cappielloantonio.play.repository.RecentSearchRepository;
|
||||
import com.cappielloantonio.play.repository.SongRepository;
|
||||
|
||||
|
|
@ -22,15 +24,18 @@ import java.util.List;
|
|||
public class SearchViewModel extends AndroidViewModel {
|
||||
private static final String TAG = "SearchViewModel";
|
||||
|
||||
private String query = "";
|
||||
|
||||
private SongRepository songRepository;
|
||||
private AlbumRepository albumRepository;
|
||||
private ArtistRepository artistRepository;
|
||||
private GenreRepository genreRepository;
|
||||
private RecentSearchRepository recentSearchRepository;
|
||||
|
||||
private LiveData<List<Song>> searchSong;
|
||||
private LiveData<List<Album>> searchAlbum;
|
||||
private LiveData<List<Artist>> searchArtist;
|
||||
private LiveData<List<RecentSearch>> recentSearches;
|
||||
private LiveData<List<Genre>> searchGenre;
|
||||
|
||||
public SearchViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
|
@ -38,9 +43,22 @@ public class SearchViewModel extends AndroidViewModel {
|
|||
songRepository = new SongRepository(application);
|
||||
albumRepository = new AlbumRepository(application);
|
||||
artistRepository = new ArtistRepository(application);
|
||||
genreRepository = new GenreRepository(application);
|
||||
recentSearchRepository = new RecentSearchRepository(application);
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query) {
|
||||
this.query = query;
|
||||
|
||||
if(!query.isEmpty()) {
|
||||
insertNewSearch(query);
|
||||
}
|
||||
}
|
||||
|
||||
public LiveData<List<Song>> searchSong(String title) {
|
||||
searchSong = songRepository.searchListLiveSong(title);
|
||||
return searchSong;
|
||||
|
|
@ -56,17 +74,17 @@ public class SearchViewModel extends AndroidViewModel {
|
|||
return searchArtist;
|
||||
}
|
||||
|
||||
public LiveData<List<RecentSearch>> getSearchList() {
|
||||
recentSearches = recentSearchRepository.getListLiveRecentSearches();
|
||||
return recentSearches;
|
||||
public LiveData<List<Genre>> searchGenre(String name) {
|
||||
searchGenre = genreRepository.searchListLiveGenre(name);
|
||||
return searchGenre;
|
||||
}
|
||||
|
||||
public void insertNewSearch(String search) {
|
||||
recentSearchRepository.insert(new RecentSearch(search));
|
||||
}
|
||||
|
||||
public void deleteAllRecentSearch() {
|
||||
recentSearchRepository.deleteAll();
|
||||
public void deleteRecentSearch(String search) {
|
||||
recentSearchRepository.delete(new RecentSearch(search));
|
||||
}
|
||||
|
||||
public List<String> getSearchSuggestion(String query) {
|
||||
|
|
@ -74,10 +92,18 @@ public class SearchViewModel extends AndroidViewModel {
|
|||
suggestions.addAll(songRepository.getSearchSuggestion(query));
|
||||
suggestions.addAll(albumRepository.getSearchSuggestion(query));
|
||||
suggestions.addAll(artistRepository.getSearchSuggestion(query));
|
||||
suggestions.addAll(genreRepository.getSearchSuggestion(query));
|
||||
|
||||
LinkedHashSet<String> hashSet = new LinkedHashSet<>(suggestions);
|
||||
ArrayList<String> suggestionsWithoutDuplicates = new ArrayList<>(hashSet);
|
||||
|
||||
return suggestionsWithoutDuplicates;
|
||||
}
|
||||
|
||||
public List<String> getRecentSearchSuggestion() {
|
||||
ArrayList<String> suggestions = new ArrayList<>();
|
||||
suggestions.addAll(recentSearchRepository.getRecentSearchSuggestion());
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,159 +42,143 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/persistentSearchView" >
|
||||
|
||||
<!-- Search result -->
|
||||
<LinearLayout
|
||||
android:id="@+id/search_result_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/global_padding_bottom"
|
||||
android:visibility="gone">
|
||||
|
||||
<!-- Recent searched -->
|
||||
<!-- Songs -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Label and button -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Recent Searches"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/clear_all_search_text_view_clickable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Clear all"
|
||||
android:textColor="@color/subtitleTextColor"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recently_searched_tracks_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:nestedScrollingEnabled="false"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Search result -->
|
||||
<LinearLayout
|
||||
android:id="@+id/search_result_layout"
|
||||
android:id="@+id/search_song_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/global_padding_bottom"
|
||||
android:visibility="gone">
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<!-- Label -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:text="Search results"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="Songs"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="18sp"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_tracks_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="24dp"
|
||||
android:nestedScrollingEnabled="false"/>
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Album -->
|
||||
<LinearLayout
|
||||
android:id="@+id/search_album_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="Albums"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="18sp"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_album_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:nestedScrollingEnabled="false"/>
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Artist -->
|
||||
<LinearLayout
|
||||
android:id="@+id/search_artist_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="Artists"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="18sp"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_artist_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="56dp"
|
||||
android:nestedScrollingEnabled="false"/>
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Genre -->
|
||||
<LinearLayout
|
||||
android:id="@+id/search_genre_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="Genres"
|
||||
android:textColor="@color/titleTextColor"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_result_genre_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="8dp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
android:id="@+id/genre_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:gravity="center_vertical"
|
||||
android:fontFamily="@font/open_sans_font_family"
|
||||
android:paddingStart="8dp"
|
||||
android:text="@string/label_placeholder"
|
||||
|
|
|
|||
|
|
@ -129,6 +129,9 @@
|
|||
<action
|
||||
android:id="@+id/action_searchFragment_to_albumPageFragment"
|
||||
app:destination="@id/albumPageFragment" />
|
||||
<action
|
||||
android:id="@+id/action_searchFragment_to_songListPageFragment"
|
||||
app:destination="@id/songListPageFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/filterFragment"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue