From 36a9f62b10b97374355073e8317f49761bcbd5d8 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 20 Aug 2015 17:53:00 -0700 Subject: Add fast scroller to more stuff as well as fixed some bugs with it --- .../daneren2005/dsub/adapter/AlbumListAdapter.java | 165 --------------------- .../dsub/adapter/AlphabeticalAlbumAdapter.java | 44 ++++++ .../daneren2005/dsub/adapter/ArtistAdapter.java | 8 +- .../daneren2005/dsub/adapter/GenreAdapter.java | 8 +- .../daneren2005/dsub/adapter/PlaylistAdapter.java | 8 +- .../dsub/adapter/PodcastChannelAdapter.java | 8 +- .../daneren2005/dsub/adapter/SectionAdapter.java | 36 +++++ .../dsub/adapter/TopRatedAlbumAdapter.java | 44 ++++++ .../dsub/fragments/SelectDirectoryFragment.java | 42 ++++-- .../github/daneren2005/dsub/view/FastScroller.java | 14 +- app/src/main/res/layout/select_album.xml | 27 ---- 11 files changed, 173 insertions(+), 231 deletions(-) delete mode 100644 app/src/main/java/github/daneren2005/dsub/adapter/AlbumListAdapter.java create mode 100644 app/src/main/java/github/daneren2005/dsub/adapter/AlphabeticalAlbumAdapter.java create mode 100644 app/src/main/java/github/daneren2005/dsub/adapter/TopRatedAlbumAdapter.java delete mode 100644 app/src/main/res/layout/select_album.xml diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/AlbumListAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/AlbumListAdapter.java deleted file mode 100644 index 47f82259..00000000 --- a/app/src/main/java/github/daneren2005/dsub/adapter/AlbumListAdapter.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see . - - Copyright 2010 (C) Sindre Mehus - */ -package github.daneren2005.dsub.adapter; - -import android.content.Context; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.SectionIndexer; - -import com.commonsware.cwac.endless.EndlessAdapter; -import github.daneren2005.dsub.R; -import github.daneren2005.dsub.domain.MusicDirectory; -import github.daneren2005.dsub.domain.ServerInfo; -import github.daneren2005.dsub.service.MusicService; -import github.daneren2005.dsub.service.MusicServiceFactory; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -public class AlbumListAdapter extends EndlessAdapter implements SectionIndexer { - private static final String TAG = AlbumListAdapter.class.getSimpleName(); - Context context; - ArrayAdapter adapter; - String type; - String extra; - int size; - int offset; - List entries; - - private boolean shouldIndex = false; - private Object[] sections; - private Integer[] positions; - - public AlbumListAdapter(Context context, ArrayAdapter adapter, String type, String extra, int size) { - super(adapter); - this.context = context; - this.adapter = adapter; - this.type = type; - this.extra = extra; - this.size = size; - this.offset = size; - - if("alphabeticalByName".equals(this.type)) { - shouldIndex = true; - recreateIndexes(); - } - } - - @Override - protected boolean cacheInBackground() throws Exception { - MusicService service = MusicServiceFactory.getMusicService(context); - MusicDirectory result; - if(("genres".equals(type) && ServerInfo.checkServerVersion(context, "1.10.0")) || "years".equals(type)) { - result = service.getAlbumList(type, extra, size, offset, false, context, null); - } else if("genres".equals(type) || "genres-songs".equals(type)) { - result = service.getSongsByGenre(extra, size, offset, context, null); - } else { - result = service.getAlbumList(type, size, offset, shouldIndex, context, null); - } - entries = result.getChildren(); - return entries.size() > 0; - } - - @Override - protected void appendCachedData() { - for(MusicDirectory.Entry entry: entries) { - adapter.add(entry); - } - offset += entries.size(); - recreateIndexes(); - } - - @Override - protected View getPendingView(ViewGroup parent) { - View progress = LayoutInflater.from(context).inflate(R.layout.tab_progress, null); - progress.setVisibility(View.VISIBLE); - return progress; - } - - private void recreateIndexes() { - try { - if (!shouldIndex) { - return; - } - - Set sectionSet = new LinkedHashSet(30); - List positionList = new ArrayList(30); - for (int i = 0; i < adapter.getCount(); i++) { - MusicDirectory.Entry entry = adapter.getItem(i); - String index; - if (entry.getAlbum() != null) { - index = entry.getAlbum().substring(0, 1); - if (!Character.isLetter(index.charAt(0))) { - index = "#"; - } - } else { - index = "*"; - } - - if (!sectionSet.contains(index)) { - sectionSet.add(index); - positionList.add(i); - } - } - sections = sectionSet.toArray(new Object[sectionSet.size()]); - positions = positionList.toArray(new Integer[positionList.size()]); - } catch(Exception e) { - Log.e(TAG, "Error while recreating indexes"); - } - } - - @Override - public Object[] getSections() { - if(sections != null) { - return sections; - } else { - return new Object[0]; - } - } - - @Override - public int getPositionForSection(int section) { - if(sections != null) { - section = Math.min(section, positions.length - 1); - return positions[section]; - } else { - return 0; - } - } - - @Override - public int getSectionForPosition(int pos) { - if(sections != null) { - for (int i = 0; i < sections.length - 1; i++) { - if (pos < positions[i + 1]) { - return i; - } - } - return sections.length - 1; - } else { - return 0; - } - } -} diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/AlphabeticalAlbumAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/AlphabeticalAlbumAdapter.java new file mode 100644 index 00000000..ccb3df4e --- /dev/null +++ b/app/src/main/java/github/daneren2005/dsub/adapter/AlphabeticalAlbumAdapter.java @@ -0,0 +1,44 @@ +/* + This file is part of Subsonic. + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see . + Copyright 2015 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.adapter; + +import android.content.Context; + +import java.util.List; + +import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.util.ImageLoader; +import github.daneren2005.dsub.view.FastScroller; + +public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implements FastScroller.BubbleTextGetter { + public AlphabeticalAlbumAdapter(Context context, List entries, ImageLoader imageLoader, boolean largeCell) { + super(context, entries, imageLoader, largeCell); + } + + @Override + public String getTextToShowInBubble(int position) { + // Make sure that we are not trying to get an item for the loading placeholder + if(position >= sections.get(0).size()) { + if(sections.get(0).size() > 0) { + return getTextToShowInBubble(position - 1); + } else { + return "*"; + } + } else { + return getNameIndex(getItemForPosition(position).getAlbum()); + } + } +} diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java index 9116e587..2eea0e74 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java @@ -125,13 +125,7 @@ public class ArtistAdapter extends SectionAdapter implements FastScrolle @Override public String getTextToShowInBubble(int position) { - Artist artist = getItemForPosition(position); - - if(artist == null) { - return ""; - } else { - return artist.getName().substring(0, 1); - } + return getNameIndex(getItemForPosition(position).getName(), true); } public interface OnMusicFolderChanged { diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java index 7e6954f9..70aa5fe3 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/GenreAdapter.java @@ -18,12 +18,13 @@ package github.daneren2005.dsub.adapter; import android.content.Context; import android.view.ViewGroup; import github.daneren2005.dsub.domain.Genre; +import github.daneren2005.dsub.view.FastScroller; import github.daneren2005.dsub.view.GenreView; import github.daneren2005.dsub.view.UpdateView; import java.util.List; -public class GenreAdapter extends SectionAdapter{ +public class GenreAdapter extends SectionAdapter implements FastScroller.BubbleTextGetter{ public static int VIEW_TYPE_GENRE = 1; public GenreAdapter(Context context, List genres, OnItemClickedListener listener) { @@ -45,4 +46,9 @@ public class GenreAdapter extends SectionAdapter{ public int getItemViewType(Genre item) { return VIEW_TYPE_GENRE; } + + @Override + public String getTextToShowInBubble(int position) { + return getNameIndex(getItemForPosition(position).getName()); + } } diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java index d7a9e8d7..7f7aacff 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/PlaylistAdapter.java @@ -62,12 +62,6 @@ public class PlaylistAdapter extends SectionAdapter implements FastScr @Override public String getTextToShowInBubble(int position) { - Playlist playlist = getItemForPosition(position); - - if(playlist == null) { - return ""; - } else { - return playlist.getName().substring(0, 1); - } + return getNameIndex(getItemForPosition(position).getName()); } } diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java index c1b132c7..f3eed393 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/PodcastChannelAdapter.java @@ -48,12 +48,6 @@ public class PodcastChannelAdapter extends SectionAdapter implem @Override public String getTextToShowInBubble(int position) { - PodcastChannel podcast = getItemForPosition(position); - - if(podcast == null) { - return ""; - } else { - return podcast.getName().substring(0, 1); - } + return getNameIndex(getItemForPosition(position).getName()); } } diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java index eec1dedb..53cc5e99 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java @@ -16,6 +16,7 @@ package github.daneren2005.dsub.adapter; import android.content.Context; +import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Build; import android.support.v7.widget.PopupMenu; @@ -39,7 +40,9 @@ import java.util.List; import github.daneren2005.dsub.R; import github.daneren2005.dsub.activity.SubsonicFragmentActivity; +import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.MenuUtil; +import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.view.BasicHeaderView; import github.daneren2005.dsub.view.UpdateView; import github.daneren2005.dsub.view.UpdateView.UpdateViewHolder; @@ -47,6 +50,7 @@ import github.daneren2005.dsub.view.UpdateView.UpdateViewHolder; public abstract class SectionAdapter extends RecyclerView.Adapter> { private static String TAG = SectionAdapter.class.getSimpleName(); public static int VIEW_TYPE_HEADER = 0; + public static String[] ignoredArticles; protected Context context; protected List headers; @@ -461,6 +465,38 @@ public abstract class SectionAdapter extends RecyclerView.Adapter { void onItemClicked(T item); void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, T item); diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/TopRatedAlbumAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/TopRatedAlbumAdapter.java new file mode 100644 index 00000000..876e5907 --- /dev/null +++ b/app/src/main/java/github/daneren2005/dsub/adapter/TopRatedAlbumAdapter.java @@ -0,0 +1,44 @@ +/* + This file is part of Subsonic. + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see . + Copyright 2015 (C) Scott Jackson +*/ + +package github.daneren2005.dsub.adapter; + +import android.content.Context; + +import java.util.List; + +import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.util.ImageLoader; +import github.daneren2005.dsub.view.FastScroller; + +public class TopRatedAlbumAdapter extends EntryInfiniteGridAdapter implements FastScroller.BubbleTextGetter { + public TopRatedAlbumAdapter(Context context, List entries, ImageLoader imageLoader, boolean largeCell) { + super(context, entries, imageLoader, largeCell); + } + + @Override + public String getTextToShowInBubble(int position) { + // Make sure that we are not trying to get an item for the loading placeholder + if(position >= sections.get(0).size()) { + if(sections.get(0).size() > 0) { + return getTextToShowInBubble(position - 1); + } else { + return "*"; + } + } else { + return Integer.toString(getItemForPosition(position).getRating()); + } + } +} 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 a5c4ca2c..6fbf49bc 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -30,9 +30,11 @@ 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; @@ -57,6 +59,7 @@ 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.view.FastScroller; import github.daneren2005.dsub.view.GridSpacingDecoration; import github.daneren2005.dsub.view.MyLeadingMarginSpan2; import github.daneren2005.dsub.view.UpdateView; @@ -72,6 +75,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section private static final String TAG = SelectDirectoryFragment.class.getSimpleName(); private RecyclerView recyclerView; + private FastScroller fastScroller; private EntryGridAdapter entryGridAdapter; private Boolean licenseValid; private List albums; @@ -113,7 +117,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section restoredInstance = true; } } - + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -161,7 +165,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } } - 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); @@ -170,8 +174,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section largeAlbums = true; } - recyclerView = (RecyclerView) rootView.findViewById(R.id.select_album_entries); + recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler); recyclerView.setHasFixedSize(true); + fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller); setupScrollList(recyclerView); if(largeAlbums) { @@ -258,7 +263,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } else { menuInflater.inflate(R.menu.select_podcast_episode, menu); - + if(!UserUtil.canPodcast()) { menu.removeItem(R.id.menu_download_all); } @@ -403,7 +408,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section if(refreshListing) { refresh = true; } - + if(currentTask != null) { currentTask.cancel(); } @@ -459,7 +464,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section return dir; } - + @Override protected void done(Pair result) { SelectDirectoryFragment.this.name = result.getFirst().getName(); @@ -468,7 +473,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } }.execute(); } - + private void getRecursiveMusicDirectory(final String id, final String name, final boolean refresh) { setTitle(name); @@ -486,7 +491,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section root.replaceChildren(songs); return root; } - + private void getSongsRecursively(MusicDirectory parent, List songs) throws Exception { songs.addAll(parent.getChildren(false, true)); for (Entry dir : parent.getChildren(true, false)) { @@ -501,7 +506,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section getSongsRecursively(musicDirectory, songs); } } - + @Override protected void done(Pair result) { SelectDirectoryFragment.this.name = result.getFirst().getName(); @@ -521,7 +526,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } }.execute(); } - + private void getPodcast(final String podcastId, final String podcastName, final boolean refresh) { setTitle(podcastName); @@ -602,7 +607,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section public LoadTask(boolean refresh) { super(SelectDirectoryFragment.this); this.refresh = refresh; - + currentTask = this; } @@ -613,7 +618,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section MusicService musicService = MusicServiceFactory.getMusicService(context); MusicDirectory dir = load(musicService); licenseValid = musicService.isLicenseValid(context, this); - + albums = dir.getChildren(true, false); entries = dir.getChildren(); @@ -641,7 +646,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section Log.w(TAG, "Failed to get Artist Info even though it should be supported"); } } - + return new Pair(dir, licenseValid); } @@ -671,7 +676,13 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section entryGridAdapter = new EntryGridAdapter(context, entries, getImageLoader(), largeAlbums); entryGridAdapter.setRemoveFromPlaylist(playlistId != null); } else { - entryGridAdapter = new EntryInfiniteGridAdapter(context, entries, getImageLoader(), largeAlbums); + 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); + } // Setup infinite loading based on scrolling final EntryInfiniteGridAdapter infiniteGridAdapter = (EntryInfiniteGridAdapter) entryGridAdapter; @@ -763,6 +774,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } recyclerView.setAdapter(entryGridAdapter); + if(entryGridAdapter instanceof FastScroller.BubbleTextGetter) { + fastScroller.attachRecyclerView(recyclerView); + } context.supportInvalidateOptionsMenu(); if(scrollToPosition != -1) { diff --git a/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java b/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java index ee7aef4b..1cc11c08 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java +++ b/app/src/main/java/github/daneren2005/dsub/view/FastScroller.java @@ -24,6 +24,7 @@ import android.support.annotation.NonNull; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; +import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -35,6 +36,7 @@ import github.daneren2005.dsub.R; import static android.support.v7.widget.RecyclerView.OnScrollListener; public class FastScroller extends LinearLayout { + private static final String TAG = FastScroller.class.getSimpleName(); private static final int BUBBLE_ANIMATION_DURATION = 100; private static final int TRACK_SNAP_RANGE = 5; @@ -57,7 +59,7 @@ public class FastScroller extends LinearLayout { } public FastScroller(final Context context,final AttributeSet attrs) { - super(context,attrs); + super(context, attrs); initialise(context); } @@ -134,8 +136,14 @@ public class FastScroller extends LinearLayout { proportion = y/(float)height; int targetPos = getValueInRange(0,itemCount-1,(int)(proportion*(float)itemCount)); ((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(targetPos,0); - String bubbleText = ((BubbleTextGetter)recyclerView.getAdapter()).getTextToShowInBubble(targetPos); - bubble.setText(bubbleText); + + try { + String bubbleText = ((BubbleTextGetter) recyclerView.getAdapter()).getTextToShowInBubble(targetPos); + bubble.setText(bubbleText); + } catch(Exception e) { + Log.e(TAG, "Item count: " + itemCount); + Log.e(TAG, "Error getting text for bubble", e); + } } } diff --git a/app/src/main/res/layout/select_album.xml b/app/src/main/res/layout/select_album.xml deleted file mode 100644 index e72ccffd..00000000 --- a/app/src/main/res/layout/select_album.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file -- cgit v1.2.3