diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java index ddb6fe0c..6f4cdae5 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumAdapter.java @@ -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 { private static final String TAG = "AlbumAdapter"; @@ -75,7 +76,16 @@ public class AlbumAdapter extends RecyclerView.Adapter 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 diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/ArtistAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/ArtistAdapter.java index fbef52a5..c9fc0618 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/ArtistAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/ArtistAdapter.java @@ -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 { private static final String TAG = "ArtistAdapter"; @@ -72,7 +73,16 @@ public class ArtistAdapter extends RecyclerView.Adapter> searchGenre(String name); + + @Query("SELECT name FROM genre WHERE name LIKE :query || '%' OR name like '% ' || :query || '%' GROUP BY name LIMIT :number") + List searchSuggestions(String query, int number); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/database/dao/RecentSearchDao.java b/app/src/main/java/com/cappielloantonio/play/database/dao/RecentSearchDao.java index c7076322..1fa8ddd6 100644 --- a/app/src/main/java/com/cappielloantonio/play/database/dao/RecentSearchDao.java +++ b/app/src/main/java/com/cappielloantonio/play/database/dao/RecentSearchDao.java @@ -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> getLast(int limit); + @Query("SELECT * FROM recent_search GROUP BY search ORDER BY search DESC LIMIT :limit") + List getRecent(int limit); @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(RecentSearch search); + @Delete + void delete(RecentSearch search); + @Query("DELETE FROM recent_search") void deleteAll(); } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/model/RecentSearch.java b/app/src/main/java/com/cappielloantonio/play/model/RecentSearch.java index 2380275b..372e2d7b 100644 --- a/app/src/main/java/com/cappielloantonio/play/model/RecentSearch.java +++ b/app/src/main/java/com/cappielloantonio/play/model/RecentSearch.java @@ -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; } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java index 4cdab9c4..1ee94e05 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/GenreRepository.java @@ -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> listLiveGenres; private LiveData> listLiveAlbumGenre; + private LiveData> searchListLiveGenre; public GenreRepository(Application application) { AppDatabase database = AppDatabase.getInstance(application); @@ -110,4 +113,48 @@ public class GenreRepository { genreDao.deleteAll(); } } + + public LiveData> searchListLiveGenre(String name) { + searchListLiveGenre = genreDao.searchGenre(name); + return searchListLiveGenre; + } + + public List getSearchSuggestion(String query) { + List 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 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 getSuggestions() { + return suggestions; + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/repository/RecentSearchRepository.java b/app/src/main/java/com/cappielloantonio/play/repository/RecentSearchRepository.java index afa94dd0..400b7195 100644 --- a/app/src/main/java/com/cappielloantonio/play/repository/RecentSearchRepository.java +++ b/app/src/main/java/com/cappielloantonio/play/repository/RecentSearchRepository.java @@ -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> listLiveRecentSearches; public RecentSearchRepository(Application application) { AppDatabase database = AppDatabase.getInstance(application); recentSearchDao = database.recentSearchDao(); - listLiveRecentSearches = recentSearchDao.getLast(3); - } - - public LiveData> 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 getRecentSearchSuggestion() { + List 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 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 getRecent() { + return recent; + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java index 295bf239..6b782953 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java @@ -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(); + } + } } diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java index 9765c515..da647e3d 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/SearchViewModel.java @@ -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> searchSong; private LiveData> searchAlbum; private LiveData> searchArtist; - private LiveData> recentSearches; + private LiveData> 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> searchSong(String title) { searchSong = songRepository.searchListLiveSong(title); return searchSong; @@ -56,17 +74,17 @@ public class SearchViewModel extends AndroidViewModel { return searchArtist; } - public LiveData> getSearchList() { - recentSearches = recentSearchRepository.getListLiveRecentSearches(); - return recentSearches; + public LiveData> 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 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 hashSet = new LinkedHashSet<>(suggestions); ArrayList suggestionsWithoutDuplicates = new ArrayList<>(hashSet); return suggestionsWithoutDuplicates; } + + public List getRecentSearchSuggestion() { + ArrayList suggestions = new ArrayList<>(); + suggestions.addAll(recentSearchRepository.getRecentSearchSuggestion()); + + return suggestions; + } } diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index d6cf5c3c..8e241c5e 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -42,159 +42,143 @@ android:layout_height="wrap_content" android:layout_below="@id/persistentSearchView" > + + android:orientation="vertical" + android:paddingBottom="@dimen/global_padding_bottom" + android:visibility="gone"> - + - - - - - - - - - - - - - - + android:paddingBottom="8dp"> - - - + android:paddingBottom="8dp" /> + + + + + android:paddingBottom="8dp" /> + + + + + android:paddingBottom="8dp" /> + + + + + + + + diff --git a/app/src/main/res/layout/item_library_genre.xml b/app/src/main/res/layout/item_library_genre.xml index 444f4efa..6fe97b27 100644 --- a/app/src/main/res/layout/item_library_genre.xml +++ b/app/src/main/res/layout/item_library_genre.xml @@ -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" diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 1e9b5a80..b21c6a11 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -129,6 +129,9 @@ +