diff options
Diffstat (limited to 'app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java')
-rw-r--r-- | app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java | 717 |
1 files changed, 268 insertions, 449 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 841a6369..6fbf49bc 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -1,7 +1,7 @@ package github.daneren2005.dsub.fragments; import android.annotation.TargetApi; -import android.app.AlertDialog; +import android.support.v7.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -9,12 +9,14 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.text.Html; import android.text.SpannableString; import android.text.Spanned; import android.text.method.LinkMovementMethod; import android.util.Log; -import android.view.ContextMenu; import android.view.Display; import android.view.LayoutInflater; import android.view.Menu; @@ -22,31 +24,29 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.GridView; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.ListAdapter; -import android.widget.ListView; import android.widget.RatingBar; import android.widget.RelativeLayout; import android.widget.TextView; import github.daneren2005.dsub.R; +import github.daneren2005.dsub.adapter.AlphabeticalAlbumAdapter; +import github.daneren2005.dsub.adapter.EntryInfiniteGridAdapter; +import github.daneren2005.dsub.adapter.EntryGridAdapter; +import github.daneren2005.dsub.adapter.SectionAdapter; +import github.daneren2005.dsub.adapter.TopRatedAlbumAdapter; import github.daneren2005.dsub.domain.ArtistInfo; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.ServerInfo; import github.daneren2005.dsub.domain.Share; import github.daneren2005.dsub.service.DownloadService; +import github.daneren2005.dsub.util.DrawableTint; import github.daneren2005.dsub.util.ImageLoader; -import github.daneren2005.dsub.adapter.AlbumGridAdapter; -import github.daneren2005.dsub.adapter.EntryAdapter; import java.io.Serializable; import java.util.Iterator; import java.util.List; -import github.daneren2005.dsub.activity.DownloadActivity; import github.daneren2005.dsub.domain.PodcastEpisode; import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.service.MusicServiceFactory; @@ -59,9 +59,10 @@ import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.TabBackgroundTask; import github.daneren2005.dsub.util.UserUtil; import github.daneren2005.dsub.util.Util; -import github.daneren2005.dsub.adapter.AlbumListAdapter; -import github.daneren2005.dsub.view.HeaderGridView; +import github.daneren2005.dsub.view.FastScroller; +import github.daneren2005.dsub.view.GridSpacingDecoration; import github.daneren2005.dsub.view.MyLeadingMarginSpan2; +import github.daneren2005.dsub.view.UpdateView; import java.util.ArrayList; import java.util.Arrays; @@ -70,17 +71,15 @@ import java.util.Set; import static github.daneren2005.dsub.domain.MusicDirectory.Entry; -public class SelectDirectoryFragment extends SubsonicFragment implements AdapterView.OnItemClickListener { +public class SelectDirectoryFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Entry> { private static final String TAG = SelectDirectoryFragment.class.getSimpleName(); - private GridView albumList; - private ListView entryList; + private RecyclerView recyclerView; + private FastScroller fastScroller; + private EntryGridAdapter entryGridAdapter; private Boolean licenseValid; - private EntryAdapter entryAdapter; private List<Entry> albums; private List<Entry> entries; - private boolean albumContext = false; - private boolean addAlbumHeader = false; private LoadTask currentTask; private ArtistInfo artistInfo; private String artistInfoDelayed; @@ -114,12 +113,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter super.onCreate(bundle); if(bundle != null) { entries = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST); - albums = (List<Entry>) bundle.getSerializable(Constants.FRAGMENT_LIST2); artistInfo = (ArtistInfo) bundle.getSerializable(Constants.FRAGMENT_EXTRA); restoredInstance = true; } } - + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -167,33 +165,41 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } } - rootView = inflater.inflate(R.layout.select_album, container, false); + rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false); refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout); refreshLayout.setOnRefreshListener(this); - entryList = (ListView) rootView.findViewById(R.id.select_album_entries); - entryList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - entryList.setOnItemClickListener(this); - setupScrollList(entryList); - if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) { largeAlbums = true; } - if(albumListType == null || "starred".equals(albumListType) || !largeAlbums) { - albumList = (GridView) inflater.inflate(R.layout.unscrollable_grid_view, entryList, false); - addAlbumHeader = true; - } else { - ViewGroup rootGroup = (ViewGroup) rootView.findViewById(R.id.select_album_layout); - albumList = (GridView) inflater.inflate(R.layout.grid_view, rootGroup, false); - rootGroup.removeView(entryList); - rootGroup.addView(albumList); + recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler); + recyclerView.setHasFixedSize(true); + fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller); + setupScrollList(recyclerView); - setupScrollList(albumList); + if(largeAlbums) { + final int columns = context.getResources().getInteger(R.integer.Grid_Columns); + GridLayoutManager gridLayoutManager = new GridLayoutManager(context, columns); + gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + int viewType = entryGridAdapter.getItemViewType(position); + if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == EntryInfiniteGridAdapter.VIEW_TYPE_LOADING) { + return columns; + } else { + return 1; + } + } + }); + recyclerView.addItemDecoration(new GridSpacingDecoration()); + recyclerView.setLayoutManager(gridLayoutManager); + } else { + LinearLayoutManager layoutManager = new LinearLayoutManager(context); + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + recyclerView.setLayoutManager(layoutManager); } - registerForContextMenu(entryList); - setupAlbumList(); if(entries == null) { if(primaryFragment || secondaryFragment) { @@ -257,7 +263,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } else { menuInflater.inflate(R.menu.select_podcast_episode, menu); - + if(!UserUtil.canPodcast()) { menu.removeItem(R.id.menu_download_all); } @@ -273,36 +279,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.menu_play_now: - playNow(false, false); - return true; - case R.id.menu_play_last: - playNow(false, true); - return true; - case R.id.menu_play_next: - playNow(false, true, true); - return true; - case R.id.menu_shuffle: - playNow(true, false); - return true; - case R.id.menu_download: - downloadBackground(false); - selectAll(false, false); - return true; - case R.id.menu_cache: - downloadBackground(true); - selectAll(false, false); - return true; - case R.id.menu_delete: - delete(); - selectAll(false, false); - return true; - case R.id.menu_add_playlist: - if(getSelectedSongs().isEmpty()) { - selectAll(true, false); - } - addToPlaylist(getSelectedSongs()); - return true; case R.id.menu_remove_playlist: removeFromPlaylist(playlistId, playlistName, getSelectedIndexes()); return true; @@ -331,32 +307,8 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, view, menuInfo); - - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - - Entry entry; - if(view.getId() == R.id.select_album_entries) { - if(info.position == 0) { - return; - } - entry = (Entry) entryList.getItemAtPosition(info.position); - // When List has Grid embedded in header, this is called against the header as well - if(entry != null) { - albumContext = false; - } - } else { - entry = (Entry) albumList.getItemAtPosition(info.position); - albumContext = true; - } - - // Don't try to display a context menu if error here - if(entry == null) { - return; - } - - onCreateContextMenu(menu, view, menuInfo, entry); + public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Entry entry) { + onCreateContextMenuSupport(menu, menuInflater, updateView, entry); if(!entry.isVideo() && !Util.isOffline(context) && (playlistId == null || !playlistOwner) && (podcastId == null || Util.isOffline(context) && podcastId != null)) { menu.removeItem(R.id.song_menu_remove_playlist); } @@ -378,88 +330,70 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter recreateContextMenu(menu); } - @Override - public boolean onContextItemSelected(MenuItem menuItem) { - if(menuItem.getGroupId() != getSupportTag()) { - return false; - } - - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); - Object selectedItem; - int headers = entryList.getHeaderViewsCount(); - if(albumContext) { - selectedItem = albumList.getItemAtPosition(info.position); - } else { - if(info.position == 0) { - return false; - } - selectedItem = entries.get(info.position - headers); - } - - if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, false) && menuItem.getItemId() == R.id.song_menu_play_now) { - List<Entry> songs = new ArrayList<Entry>(); - Iterator it = entries.listIterator(info.position - headers); - while(it.hasNext()) { - songs.add((Entry) it.next()); - } - - playNow(songs); - return true; - } - - if(onContextItemSelected(menuItem, selectedItem)) { + public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Entry> updateView, Entry entry) { + if(onContextItemSelected(menuItem, entry)) { return true; } switch (menuItem.getItemId()) { case R.id.song_menu_remove_playlist: - removeFromPlaylist(playlistId, playlistName, Arrays.<Integer>asList(info.position - headers)); + removeFromPlaylist(playlistId, playlistName, Arrays.<Integer>asList(entries.indexOf(entry))); break; case R.id.song_menu_server_download: - downloadPodcastEpisode((PodcastEpisode)selectedItem); + downloadPodcastEpisode((PodcastEpisode) entry); break; case R.id.song_menu_server_delete: - deletePodcastEpisode((PodcastEpisode)selectedItem); + deletePodcastEpisode((PodcastEpisode) entry); break; } - + return true; } @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - if (position >= 0) { - Entry entry = (Entry) parent.getItemAtPosition(position); - if (entry.isDirectory()) { - SubsonicFragment fragment = new SelectDirectoryFragment(); - Bundle args = new Bundle(); - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId()); - args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle()); - args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, entry); - if ("newest".equals(albumListType)) { - args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true); - } - if(entry.getArtist() == null && entry.getParent() == null) { - args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); - } - fragment.setArguments(args); + public void onItemClicked(Entry entry) { + if (entry.isDirectory()) { + SubsonicFragment fragment = new SelectDirectoryFragment(); + Bundle args = new Bundle(); + args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId()); + args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle()); + args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, entry); + if ("newest".equals(albumListType)) { + args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true); + } + if(!entry.isAlbum()) { + args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); + } + fragment.setArguments(args); + + replaceFragment(fragment, true); + } else if (entry.isVideo()) { + playVideo(entry); + } else if(entry instanceof PodcastEpisode) { + String status = ((PodcastEpisode)entry).getStatus(); + if("error".equals(status)) { + Util.toast(context, R.string.select_podcasts_error); + return; + } else if(!"completed".equals(status)) { + Util.toast(context, R.string.select_podcasts_skipped); + return; + } - replaceFragment(fragment, true); - } else if (entry.isVideo()) { - playVideo(entry); - } else if(entry instanceof PodcastEpisode) { - String status = ((PodcastEpisode)entry).getStatus(); - if("error".equals(status)) { - Util.toast(context, R.string.select_podcasts_error); - return; - } else if(!"completed".equals(status)) { - Util.toast(context, R.string.select_podcasts_skipped); - return; + playNow(Arrays.asList(entry)); + } else { + List<Entry> songs = new ArrayList<Entry>(); + + if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, true)) { + Iterator it = entries.listIterator(entries.indexOf(entry)); + while(it.hasNext()) { + songs.add((Entry) it.next()); } - - playNow(Arrays.asList(entry)); + } else { + songs.add(entry); } + + playNow(songs); } } @@ -474,12 +408,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter if(refreshListing) { refresh = true; } - + if(currentTask != null) { currentTask.cancel(); } - - entryList.setVisibility(View.INVISIBLE); + + recyclerView.setVisibility(View.INVISIBLE); if (playlistId != null) { getPlaylist(playlistId, playlistName, refresh); } else if(podcastId != null) { @@ -491,7 +425,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter getShare(share, refresh); } } else if (albumListType != null) { - getAlbumList(albumListType, albumListSize); + getAlbumList(albumListType, albumListSize, refresh); } else { if(showAll) { getRecursiveMusicDirectory(id, name, refresh); @@ -530,7 +464,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter return dir; } - + @Override protected void done(Pair<MusicDirectory, Boolean> result) { SelectDirectoryFragment.this.name = result.getFirst().getName(); @@ -539,7 +473,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } }.execute(); } - + private void getRecursiveMusicDirectory(final String id, final String name, final boolean refresh) { setTitle(name); @@ -557,7 +491,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter root.replaceChildren(songs); return root; } - + private void getSongsRecursively(MusicDirectory parent, List<Entry> songs) throws Exception { songs.addAll(parent.getChildren(false, true)); for (Entry dir : parent.getChildren(true, false)) { @@ -572,7 +506,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter getSongsRecursively(musicDirectory, songs); } } - + @Override protected void done(Pair<MusicDirectory, Boolean> result) { SelectDirectoryFragment.this.name = result.getFirst().getName(); @@ -592,7 +526,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } }.execute(); } - + private void getPodcast(final String podcastId, final String podcastName, final boolean refresh) { setTitle(podcastName); @@ -626,7 +560,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }.execute(); } - private void getAlbumList(final String albumListType, final int size) { + private void getAlbumList(final String albumListType, final int size, final boolean refresh) { if ("newest".equals(albumListType)) { setTitle(R.string.main_albums_newest); } else if ("random".equals(albumListType)) { @@ -652,7 +586,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter if ("starred".equals(albumListType)) { result = service.getStarredList(context, this); } else if(("genres".equals(albumListType) && ServerInfo.checkServerVersion(context, "1.10.0")) || "years".equals(albumListType)) { - result = service.getAlbumList(albumListType, albumListExtra, size, 0, context, this); + result = service.getAlbumList(albumListType, albumListExtra, size, 0, refresh, context, this); if(result.getChildrenSize() == 0 && "genres".equals(albumListType)) { SelectDirectoryFragment.this.albumListType = "genres-songs"; result = service.getSongsByGenre(albumListExtra, size, 0, context, this); @@ -660,7 +594,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } else if("genres".equals(albumListType) || "genres-songs".equals(albumListType)) { result = service.getSongsByGenre(albumListExtra, size, 0, context, this); } else { - result = service.getAlbumList(albumListType, size, 0, context, this); + result = service.getAlbumList(albumListType, size, 0, refresh, context, this); } return result; } @@ -673,7 +607,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter public LoadTask(boolean refresh) { super(SelectDirectoryFragment.this); this.refresh = refresh; - + currentTask = this; } @@ -684,13 +618,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter MusicService musicService = MusicServiceFactory.getMusicService(context); MusicDirectory dir = load(musicService); licenseValid = musicService.isLicenseValid(context, this); - + albums = dir.getChildren(true, false); - if(largeAlbums) { - entries = dir.getChildren(false, true); - } else { - entries = dir.getChildren(); - } + entries = dir.getChildren(); // This isn't really an artist if no albums on it! if(albums.size() == 0) { @@ -716,7 +646,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter Log.w(TAG, "Failed to get Artist Info even though it should be supported"); } } - + return new Pair<MusicDirectory, Boolean>(dir, licenseValid); } @@ -727,121 +657,132 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } } + @Override + protected SectionAdapter<Entry> getCurrentAdapter() { + return entryGridAdapter; + } + private void finishLoading() { - // Show header if not album list type and not root and not artist - // For Subsonic 5.1+ display a header for artists with getArtistInfo data if it exists - View header = null; - if(albumListType == null && !"root".equals(id) && (!artist || artistInfo != null || artistInfoDelayed != null)) { - header = createHeader(); + boolean validData = !entries.isEmpty() || !albums.isEmpty(); + if(!validData) { + setEmpty(true); + } - if(header != null && artistInfoDelayed != null) { - final View finalHeader = header.findViewById(R.id.select_album_header); - final View headerProgress = header.findViewById(R.id.header_progress); + if(validData) { + recyclerView.setVisibility(View.VISIBLE); + } - finalHeader.setVisibility(View.INVISIBLE); - headerProgress.setVisibility(View.VISIBLE); + if(albumListType == null || "starred".equals(albumListType)) { + entryGridAdapter = new EntryGridAdapter(context, entries, getImageLoader(), largeAlbums); + entryGridAdapter.setRemoveFromPlaylist(playlistId != null); + } else { + if("alphabeticalByName".equals(albumListType)) { + entryGridAdapter = new AlphabeticalAlbumAdapter(context, entries, getImageLoader(), largeAlbums); + } else if("highest".equals(albumListType)) { + entryGridAdapter = new TopRatedAlbumAdapter(context, entries, getImageLoader(), largeAlbums); + } else { + entryGridAdapter = new EntryInfiniteGridAdapter(context, entries, getImageLoader(), largeAlbums); + } - new SilentBackgroundTask<Void>(context) { - @Override - protected Void doInBackground() throws Throwable { - MusicService musicService = MusicServiceFactory.getMusicService(context); - artistInfo = musicService.getArtistInfo(artistInfoDelayed, false, true, context, this); + // Setup infinite loading based on scrolling + final EntryInfiniteGridAdapter infiniteGridAdapter = (EntryInfiniteGridAdapter) entryGridAdapter; + infiniteGridAdapter.setData(albumListType, albumListExtra, albumListSize); - return null; - } + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + } - @Override - protected void done(Void result) { - /*if(albumList instanceof HeaderGridView) { - HeaderGridView headerGridView = (HeaderGridView) albumList; - headerGridView.invalidateRowHeight(); - ((BaseAdapter) headerGridView.getAdapter()).notifyDataSetChanged(); - }*/ - - setupCoverArt(finalHeader); - setupTextDisplay(finalHeader); - setupButtonEvents(finalHeader); - - finalHeader.setVisibility(View.VISIBLE); - headerProgress.setVisibility(View.GONE); + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + + RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + int totalItemCount = layoutManager.getItemCount(); + int lastVisibleItem; + if(layoutManager instanceof GridLayoutManager) { + lastVisibleItem = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition(); + } else if(layoutManager instanceof LinearLayoutManager) { + lastVisibleItem = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); + } else { + return; } - }.execute(); - } - // Only add header to entry list if we aren't going recreate album grid as root anyways - if(header != null && entryList != null && (!addAlbumHeader || entries.size() > 0)) { - entryList.addHeaderView(header, null, false); - header = null; - } - } - - // Needs to be added here, GB crashes if you to try to remove the header view before adapter is set - if(addAlbumHeader) { - if(entries.size() > 0 || playlistId != null || podcastId != null) { - entryList.addHeaderView(albumList); - } else { - ViewGroup rootGroup = (ViewGroup) rootView.findViewById(R.id.select_album_layout); - albumList = (GridView) context.getLayoutInflater().inflate(R.layout.grid_view, rootGroup, false); - rootGroup.removeView(entryList); - rootGroup.addView(albumList); - - setupScrollList(albumList); - setupAlbumList(); - - // This should only not be null for a artist with only albums - if(header != null) { - HeaderGridView headerGridView = (HeaderGridView) albumList; - headerGridView.addHeaderView(header); + if(totalItemCount > 0 && lastVisibleItem >= totalItemCount - 2) { + infiniteGridAdapter.loadMore(); + } } - } - addAlbumHeader = false; + }); } - - boolean validData = !entries.isEmpty() || !albums.isEmpty(); - if(!validData) { - setEmpty(true); + entryGridAdapter.setOnItemClickedListener(this); + // Always show artist if this is not a artist we are viewing + if(!artist) { + entryGridAdapter.setShowArtist(true); } - // Always going to have entries in entryAdapter - entryAdapter = new EntryAdapter(context, getImageLoader(), entries, (podcastId == null)); - ListAdapter listAdapter = entryAdapter; - // Song-only genre needs to always be entry list + infinite adapter - if("genres-songs".equals(albumListType)) { - ViewGroup rootGroup = (ViewGroup) rootView.findViewById(R.id.select_album_layout); - if(rootGroup.findViewById(R.id.gridview) != null && largeAlbums) { - rootGroup.removeView(albumList); - rootGroup.addView(entryList); - } - listAdapter = new AlbumListAdapter(context, entryAdapter, albumListType, albumListExtra, albumListSize); - } else if(albumListType == null || "starred".equals(albumListType)) { - // Only set standard album adapter if not album list and largeAlbums is true - if(largeAlbums) { - albumList.setAdapter(new AlbumGridAdapter(context, getImageLoader(), albums, !artist)); - } - } else { - // If album list, use infinite adapters for either depending on whether or not largeAlbums is true - if(largeAlbums) { - albumList.setAdapter(new AlbumListAdapter(context, new AlbumGridAdapter(context, getImageLoader(), albums, true), albumListType, albumListExtra, albumListSize)); - } else { - listAdapter = new AlbumListAdapter(context, entryAdapter, albumListType, albumListExtra, albumListSize); + // Show header if not album list type and not root and not artist + // For Subsonic 5.1+ display a header for artists with getArtistInfo data if it exists + boolean addedHeader = false; + if(albumListType == null && !"root".equals(id) && (!artist || artistInfo != null || artistInfoDelayed != null) && (share == null || entries.size() != albums.size())) { + View header = createHeader(); + + if(header != null) { + if (artistInfoDelayed != null) { + final View finalHeader = header.findViewById(R.id.select_album_header); + final View headerProgress = header.findViewById(R.id.header_progress); + + finalHeader.setVisibility(View.INVISIBLE); + headerProgress.setVisibility(View.VISIBLE); + + new SilentBackgroundTask<Void>(context) { + @Override + protected Void doInBackground() throws Throwable { + MusicService musicService = MusicServiceFactory.getMusicService(context); + artistInfo = musicService.getArtistInfo(artistInfoDelayed, false, true, context, this); + + return null; + } + + @Override + protected void done(Void result) { + setupCoverArt(finalHeader); + setupTextDisplay(finalHeader); + setupButtonEvents(finalHeader); + + finalHeader.setVisibility(View.VISIBLE); + headerProgress.setVisibility(View.GONE); + } + }.execute(); + } + + entryGridAdapter.setHeader(header); + addedHeader = true; } } - entryList.setAdapter(listAdapter); - if(validData) { - entryList.setVisibility(View.VISIBLE); - } - context.supportInvalidateOptionsMenu(); + int scrollToPosition = -1; if(lookupEntry != null) { for(int i = 0; i < entries.size(); i++) { if(lookupEntry.equals(entries.get(i).getTitle())) { - entryList.setSelection(i + entryList.getHeaderViewsCount()); + scrollToPosition = i; + entryGridAdapter.addSelected(entries.get(i)); lookupEntry = null; break; } } } + recyclerView.setAdapter(entryGridAdapter); + if(entryGridAdapter instanceof FastScroller.BubbleTextGetter) { + fastScroller.attachRecyclerView(recyclerView); + } + context.supportInvalidateOptionsMenu(); + + if(scrollToPosition != -1) { + recyclerView.scrollToPosition(scrollToPosition + (addedHeader ? 1 : 0)); + } + Bundle args = getArguments(); boolean playAll = args.getBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false); if (playAll && !restoredInstance) { @@ -849,169 +790,52 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } } - private void setupAlbumList() { - albumList.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - Entry entry = (Entry) parent.getItemAtPosition(position); - SubsonicFragment fragment = new SelectDirectoryFragment(); - Bundle args = new Bundle(); - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId()); - args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle()); - args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, entry); - if ("newest".equals(albumListType)) { - args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true); - } - if(entry.getArtist() == null && entry.getParent() == null) { - args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); - } - fragment.setArguments(args); - - replaceFragment(fragment, true); - } - }); - - registerForContextMenu(entryList); - registerForContextMenu(albumList); - } - - private void playNow(final boolean shuffle, final boolean append) { - playNow(shuffle, append, false); - } - private void playNow(final boolean shuffle, final boolean append, final boolean playNext) { - if(getSelectedSongs().size() > 0) { - download(append, false, !append, playNext, shuffle); - selectAll(false, false); + @Override + protected void playNow(final boolean shuffle, final boolean append, final boolean playNext) { + List<Entry> songs = getSelectedEntries(); + if(!songs.isEmpty()) { + download(songs, append, false, !append, playNext, shuffle); + entryGridAdapter.clearSelected(); } else { playAll(shuffle, append); } } private void playAll(final boolean shuffle, final boolean append) { - boolean hasSubFolders = false; - for (int i = 0; i < entryList.getCount(); i++) { - Entry entry = (Entry) entryList.getItemAtPosition(i); - if (entry != null && entry.isDirectory()) { - hasSubFolders = true; - break; - } - } - if(albums.size() > 0) { - hasSubFolders = true; - } + boolean hasSubFolders = !albums.isEmpty(); if (hasSubFolders && (id != null || share != null || "starred".equals(albumListType))) { downloadRecursively(id, false, append, !append, shuffle, false); } else if(hasSubFolders && albumListType != null) { downloadRecursively(albums, shuffle, append); } else { - selectAll(true, false); - download(append, false, !append, false, shuffle); - selectAll(false, false); + download(entries, append, false, !append, false, shuffle); } } - private void selectAll(boolean selected, boolean toast) { - int count = entryList.getCount(); - int selectedCount = 0; - for (int i = 0; i < count; i++) { - Entry entry = (Entry) entryList.getItemAtPosition(i); - if (entry != null && !entry.isDirectory() && !entry.isVideo()) { - entryList.setItemChecked(i, selected); - selectedCount++; - } - } - - // Display toast: N tracks selected / N tracks unselected - if (toast) { - int toastResId = selected ? R.string.select_album_n_selected - : R.string.select_album_n_unselected; - Util.toast(context, context.getString(toastResId, selectedCount)); - } - } - - private List<Entry> getSelectedSongs() { - List<Entry> songs = new ArrayList<Entry>(10); - int count = entryList.getCount(); - for (int i = 0; i < count; i++) { - if (entryList.isItemChecked(i)) { - Entry entry = (Entry) entryList.getItemAtPosition(i); - // Don't try to add directories or 1-starred songs - if(!entry.isDirectory() && entry.getRating() != 1) { - songs.add(entry); - } - } - } - return songs; - } - private List<Integer> getSelectedIndexes() { + List<Entry> selected = entryGridAdapter.getSelected(); List<Integer> indexes = new ArrayList<Integer>(); - int count = entryList.getCount(); - int headers = entryList.getHeaderViewsCount(); - for (int i = 0; i < count; i++) { - if (entryList.isItemChecked(i)) { - indexes.add(i - headers); - } + for(Entry entry: selected) { + indexes.add(entries.indexOf(entry)); } return indexes; } - private void download(final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle) { - if (getDownloadService() == null) { - return; - } - - final List<Entry> songs = getSelectedSongs(); - warnIfStorageUnavailable(); - - // Conditions for using play now button - if(!append && !save && autoplay && !playNext && !shuffle) { - // Call playNow which goes through and tries to use bookmark information - playNow(songs, playlistName, playlistId); - return; - } - - LoadingTask<Void> onValid = new LoadingTask<Void>(context) { - @Override - protected Void doInBackground() throws Throwable { - if (!append) { - getDownloadService().clear(); - } - - getDownloadService().download(songs, save, autoplay, playNext, shuffle); - if (playlistName != null) { - getDownloadService().setSuggestedPlaylistName(playlistName, playlistId); - } else { - getDownloadService().setSuggestedPlaylistName(null, null); - } - return null; - } - - @Override - protected void done(Void result) { - if (autoplay) { - Util.startActivityWithoutTransition(context, DownloadActivity.class); - } else if (save) { - Util.toast(context, - context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); - } else if (append) { - Util.toast(context, - context.getResources().getQuantityString(R.plurals.select_album_n_songs_added, songs.size(), songs.size())); - } - } - }; - + @Override + protected void executeOnValid(RecursiveLoader onValid) { checkLicenseAndTrialPeriod(onValid); } - private void downloadBackground(final boolean save) { + + @Override + protected void downloadBackground(final boolean save) { + List<Entry> songs = getSelectedEntries(); if(playlistId != null) { - selectAll(true, false); + songs = entries; } - List<Entry> songs = getSelectedSongs(); if(songs.isEmpty()) { // Get both songs and albums downloadRecursively(id, save, false, false, false, true); @@ -1019,21 +843,23 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter downloadBackground(save, songs); } } - private void downloadBackground(final boolean save, final List<Entry> songs) { + @Override + protected void downloadBackground(final boolean save, final List<Entry> entries) { if (getDownloadService() == null) { return; } warnIfStorageUnavailable(); - LoadingTask<Void> onValid = new LoadingTask<Void>(context) { + RecursiveLoader onValid = new RecursiveLoader(context) { @Override - protected Void doInBackground() throws Throwable { + protected Boolean doInBackground() throws Throwable { + getSongsRecursively(entries, songs); getDownloadService().downloadBackground(songs, save); return null; } @Override - protected void done(Void result) { + protected void done(Boolean result) { Util.toast(context, context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); } }; @@ -1041,15 +867,21 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter checkLicenseAndTrialPeriod(onValid); } - private void delete() { - List<Entry> songs = getSelectedSongs(); - if(songs.isEmpty()) { - selectAll(true, false); - songs = getSelectedSongs(); + @Override + protected void download(List<Entry> entries, boolean append, boolean save, boolean autoplay, boolean playNext, boolean shuffle) { + download(entries, append, save, autoplay, playNext, shuffle, playlistName, playlistId); + } - // Also delete all directories - for(Entry album: albums) { - deleteRecursively(album); + @Override + protected void delete() { + List<Entry> songs = getSelectedEntries(); + if(songs.isEmpty()) { + for(Entry entry: entries) { + if(entry.isDirectory()) { + deleteRecursively(entry); + } else { + songs.add(entry); + } } } if (getDownloadService() != null) { @@ -1068,11 +900,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override protected void done(Void result) { - for(int i = indexes.size() - 1; i >= 0; i--) { - entryList.setItemChecked(indexes.get(i) + 1, false); - entryAdapter.removeAt(indexes.get(i)); + for(Integer index: indexes) { + entryGridAdapter.removeAt(index); } - entryAdapter.notifyDataSetChanged(); Util.toast(context, context.getResources().getString(R.string.removed_playlist, indexes.size(), name)); } @@ -1144,7 +974,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter public void onClick(DialogInterface dialog, int which) { new LoadingTask<Void>(context, true) { @Override - protected Void doInBackground() throws Throwable { + protected Void doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(context); musicService.deletePodcastEpisode(episode.getEpisodeId(), episode.getParent(), null, context); if (getDownloadService() != null) { @@ -1157,8 +987,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override protected void done(Void result) { - entries.remove(episode); - entryAdapter.notifyDataSetChanged(); + entryGridAdapter.removeItem(episode); } @Override @@ -1172,7 +1001,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } public void unstarSelected() { - List<Entry> selected = getSelectedSongs(); + List<Entry> selected = getSelectedEntries(); if(selected.size() == 0) { selected = entries; } @@ -1219,10 +1048,8 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter Util.toast(context, context.getResources().getString(R.string.starring_content_unstarred, Integer.toString(unstar.size()))); for(Entry entry: unstar) { - entries.remove(entry); + entryGridAdapter.removeItem(entry); } - entryAdapter.notifyDataSetChanged(); - selectAll(false, false); } @Override @@ -1335,31 +1162,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override protected void done(Void result) { - Util.startActivityWithoutTransition(context, DownloadActivity.class); + context.openNowPlaying(); } }.execute(); } private View createHeader() { - View header = entryList.findViewById(R.id.select_album_header_wrapper); - boolean add = false; - if(header == null) { - header = LayoutInflater.from(context).inflate(R.layout.select_album_header, entryList, false); - add = true; - } + View header = LayoutInflater.from(context).inflate(R.layout.select_album_header, null, false); setupCoverArt(header); setupTextDisplay(header); + setupButtonEvents(header); - if(add) { - setupButtonEvents(header); - } - - if(add) { - return header; - } else { - return null; - } + return header; } private void setupCoverArt(View header) { @@ -1508,11 +1323,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } else { artistView.setMaxLines(minLines); } - - if(albumList instanceof HeaderGridView) { - HeaderGridView headerGridView = (HeaderGridView) albumList; - ((BaseAdapter) headerGridView.getAdapter()).notifyDataSetChanged(); - } } }); artistView.setMovementMethod(LinkMovementMethod.getInstance()); @@ -1559,14 +1369,23 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter final ImageButton starButton = (ImageButton) header.findViewById(R.id.select_album_star); if(directory != null && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_STAR, true) && artistInfo == null) { - starButton.setImageResource(directory.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off); + if(directory.isStarred()) { + starButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_toggle_star)); + } else { + starButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.star_outline)); + } starButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { toggleStarred(directory, new OnStarChange() { @Override void starChange(boolean starred) { - starButton.setImageResource(directory.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off); + if(directory.isStarred()) { + starButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.star_outline)); + starButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_toggle_star)); + } else { + starButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.star_outline)); + } } }); } |