diff options
Diffstat (limited to 'app/src/main')
19 files changed, 333 insertions, 481 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java index be9b4cb9..7e926d51 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java @@ -24,26 +24,33 @@ import java.util.List; import github.daneren2005.dsub.service.DownloadFile; import github.daneren2005.dsub.view.SongView; +import github.daneren2005.dsub.view.UpdateView; -public class DownloadFileAdapter extends ArrayAdapter<DownloadFile> { - Context context; +public class DownloadFileAdapter extends SectionAdapter<DownloadFile> { + public static int VIEW_TYPE_DOWNLOAD_FILE = 1; public DownloadFileAdapter(Context context, List<DownloadFile> entries) { - super(context, android.R.layout.simple_list_item_1, entries); - this.context = context; + super(context, entries); + } + public DownloadFileAdapter(Context context, List<DownloadFile> entries, OnItemClickedListener onItemClickedListener) { + super(context, entries); + this.onItemClickedListener = onItemClickedListener; + } + + @Override + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + return new UpdateView.UpdateViewHolder(new SongView(context)); + } + + @Override + public void onBindViewHolder(UpdateView.UpdateViewHolder holder, DownloadFile item, int viewType) { + SongView songView = (SongView) holder.getUpdateView(); + songView.setObject(item.getSong(), false); + songView.setDownloadFile(item); } @Override - public View getView(int position, View convertView, ViewGroup parent) { - SongView view; - if (convertView != null && convertView instanceof SongView) { - view = (SongView) convertView; - } else { - view = new SongView(context); - } - DownloadFile downloadFile = getItem(position); - view.setObject(downloadFile.getSong(), false); - view.setDownloadFile(downloadFile); - return view; + public int getItemViewType(DownloadFile item) { + return VIEW_TYPE_DOWNLOAD_FILE; } } diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/EntryAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryAdapter.java deleted file mode 100644 index 9cc96ae0..00000000 --- a/app/src/main/java/github/daneren2005/dsub/adapter/EntryAdapter.java +++ /dev/null @@ -1,82 +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 <http://www.gnu.org/licenses/>. - - Copyright 2010 (C) Sindre Mehus - */ -package github.daneren2005.dsub.adapter; - -import android.content.Context; - -import java.util.List; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import github.daneren2005.dsub.domain.MusicDirectory; -import github.daneren2005.dsub.util.ImageLoader; -import github.daneren2005.dsub.view.AlbumView; -import github.daneren2005.dsub.view.ArtistEntryView; -import github.daneren2005.dsub.view.SongView; - -/** - * @author Sindre Mehus - */ -public class EntryAdapter extends ArrayAdapter<MusicDirectory.Entry> { - private final static String TAG = EntryAdapter.class.getSimpleName(); - private final Context activity; - private final ImageLoader imageLoader; - private final boolean checkable; - private List<MusicDirectory.Entry> entries; - - public EntryAdapter(Context activity, ImageLoader imageLoader, List<MusicDirectory.Entry> entries, boolean checkable) { - super(activity, android.R.layout.simple_list_item_1, entries); - this.entries = entries; - this.activity = activity; - this.imageLoader = imageLoader; - this.checkable = checkable; - } - - public void removeAt(int position) { - entries.remove(position); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - MusicDirectory.Entry entry = getItem(position); - - if (entry.isDirectory()) { - if(entry.isAlbum()) { - AlbumView view; - view = new AlbumView(activity, false); - view.setObject(entry, imageLoader); - return view; - } else { - ArtistEntryView view = new ArtistEntryView(activity); - view.setObject(entry); - return view; - } - } else { - SongView view; - if (convertView != null && convertView instanceof SongView) { - view = (SongView) convertView; - } else { - view = new SongView(activity); - } - view.setObject(entry, checkable); - return view; - } - } -} 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 8d9a8682..599870d7 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/SectionAdapter.java @@ -224,6 +224,23 @@ public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewH return null; } + public int getItemPosition(T item) { + if(sections.size() == 1 && !singleSectionHeader) { + return sections.get(0).indexOf(item); + } + + int subPosition = 0; + for(List<T> section: sections) { + subPosition += section.size() + 1; + + int position = section.indexOf(item); + if(position != -1) { + return position + subPosition; + } + } + + return -1; + } public void setContextItem(UpdateView updateView, T item) { contextView = updateView; diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java index 45c3ead1..d99b294b 100644 --- a/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java +++ b/app/src/main/java/github/daneren2005/dsub/adapter/SettingsAdapter.java @@ -16,44 +16,83 @@ package github.daneren2005.dsub.adapter; import android.content.Context; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; import java.util.List; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.User; +import github.daneren2005.dsub.util.ImageLoader; import github.daneren2005.dsub.view.SettingView; +import github.daneren2005.dsub.view.UpdateView; import static github.daneren2005.dsub.domain.User.Setting; -public class SettingsAdapter extends ArrayAdapter<Setting> { - private final Context context; +public class SettingsAdapter extends SectionAdapter<Setting> { + public final int VIEW_TYPE_SETTING = 1; + + private final User user; private final boolean editable; + private final ImageLoader imageLoader; - public SettingsAdapter(Context context, User user, boolean editable) { - super(context, R.layout.basic_list_item, user.getSettings()); - this.context = context; + public SettingsAdapter(Context context, User user, ImageLoader imageLoader, boolean editable) { + super(context, user.getSettings(), imageLoader != null); + this.user = user; + this.imageLoader = imageLoader; this.editable = editable; + + List<Setting> settings = sections.get(0); + for(Setting setting: settings) { + if(setting.getValue()) { + addSelected(setting); + } + } } - public SettingsAdapter(Context context, List<Setting> settings, boolean editable) { - super(context, R.layout.basic_list_item, settings); - this.context = context; - this.editable = editable; + public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) { + View header = LayoutInflater.from(context).inflate(R.layout.user_header, parent, false); + return new UpdateView.UpdateViewHolder(header, false); } + public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String description) { + View header = holder.getView(); - @Override - public View getView(int position, View convertView, ViewGroup parent) { - Setting entry = getItem(position); - SettingView view; - if (convertView != null && convertView instanceof SettingView) { - view = (SettingView) convertView; + ImageView coverArtView = (ImageView) header.findViewById(R.id.user_avatar); + imageLoader.loadAvatar(context, coverArtView, user.getUsername()); + + TextView usernameView = (TextView) header.findViewById(R.id.user_username); + usernameView.setText(user.getUsername()); + + final TextView emailView = (TextView) header.findViewById(R.id.user_email); + if(user.getEmail() != null) { + emailView.setText(user.getEmail()); } else { - view = new SettingView(context); + emailView.setVisibility(View.GONE); + } + } + + @Override + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + return new UpdateView.UpdateViewHolder(new SettingView(context)); + } + + @Override + public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Setting item, int viewType) { + holder.getUpdateView().setObject(item, editable); + } + + @Override + public int getItemViewType(Setting item) { + return VIEW_TYPE_SETTING; + } + + @Override + public void setChecked(UpdateView updateView, boolean checked) { + if(updateView instanceof SettingView) { + ((SettingView) updateView).setChecked(checked); } - view.setObject(entry, editable); - return view; } } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java index 59229c3f..5a3d63ad 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java @@ -30,6 +30,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import github.daneren2005.dsub.R; +import github.daneren2005.dsub.adapter.SectionAdapter; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.service.DownloadFile; import github.daneren2005.dsub.service.DownloadService; @@ -38,13 +39,15 @@ import github.daneren2005.dsub.util.ProgressListener; import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.adapter.DownloadFileAdapter; +import github.daneren2005.dsub.view.UpdateView; -public class DownloadFragment extends SelectListFragment<DownloadFile> { +public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> { private long currentRevision; private ScheduledExecutorService executorService; public DownloadFragment() { serialize = false; + pullToRefresh = false; } @Override @@ -80,7 +83,7 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> { } @Override - public ArrayAdapter getAdapter(List<DownloadFile> objs) { + public SectionAdapter getAdapter(List<DownloadFile> objs) { return new DownloadFileAdapter(context, objs); } @@ -91,9 +94,6 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> { return new ArrayList<DownloadFile>(); } - listView.setOnScrollListener(null); - refreshLayout.setEnabled(false); - List<DownloadFile> songList = new ArrayList<DownloadFile>(); songList.addAll(downloadService.getBackgroundDownloads()); currentRevision = downloadService.getDownloadListUpdateRevision(); @@ -106,7 +106,7 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> { } @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + public void onItemClicked(DownloadFile item) { } @@ -144,11 +144,13 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> { @Override public void onCreateContextMenu(android.view.ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, view, menuInfo); + UpdateView targetView = adapter.getContextView(); + menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0); - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - Object selectedItem = ((DownloadFile) listView.getItemAtPosition(info.position)).getSong(); + DownloadFile downloadFile = adapter.getContextItem(); + MusicDirectory.Entry selectedItem = downloadFile.getSong(); onCreateContextMenu(menu, view, menuInfo, selectedItem); - if(selectedItem instanceof MusicDirectory.Entry && !((MusicDirectory.Entry) selectedItem).isVideo() && !Util.isOffline(context)) { + if(!selectedItem.isVideo() && !Util.isOffline(context)) { menu.removeItem(R.id.song_menu_remove_playlist); } @@ -161,9 +163,8 @@ public class DownloadFragment extends SelectListFragment<DownloadFile> { return false; } - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); - Object selectedItem = ((DownloadFile) listView.getItemAtPosition(info.position)).getSong(); - + DownloadFile downloadFile = adapter.getContextItem(); + MusicDirectory.Entry selectedItem = downloadFile.getSong(); if(onContextItemSelected(menuItem, selectedItem)) { return true; } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java index b9ef412c..851e9478 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java @@ -31,6 +31,9 @@ import android.os.Bundle; import android.os.Handler; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.MediaRouteButton; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.ContextMenu; import android.view.Display; @@ -55,6 +58,7 @@ import android.widget.TextView; import android.widget.ViewFlipper; import github.daneren2005.dsub.R; import github.daneren2005.dsub.activity.SubsonicFragmentActivity; +import github.daneren2005.dsub.adapter.SectionAdapter; import github.daneren2005.dsub.audiofx.EqualizerController; import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.PlayerState; @@ -70,6 +74,7 @@ import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.adapter.DownloadFileAdapter; import github.daneren2005.dsub.view.FadeOutAnimation; +import github.daneren2005.dsub.view.SongView; import github.daneren2005.dsub.view.UpdateView; import github.daneren2005.dsub.util.Util; @@ -79,10 +84,9 @@ import github.daneren2005.dsub.util.*; import github.daneren2005.dsub.view.AutoRepeatButton; import java.util.ArrayList; import java.util.concurrent.ScheduledFuture; -import com.mobeta.android.dslv.*; import github.daneren2005.dsub.activity.SubsonicActivity; -public class NowPlayingFragment extends SubsonicFragment implements OnGestureListener { +public class NowPlayingFragment extends SubsonicFragment implements OnGestureListener, SectionAdapter.OnItemClickedListener<DownloadFile> { private static final String TAG = NowPlayingFragment.class.getSimpleName(); private static final int PERCENTAGE_OF_SCREEN_FOR_SWIPE = 10; private static final int INCREMENT_TIME = 5000; @@ -97,7 +101,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis private TextView emptyTextView; private TextView songTitleTextView; private ImageView albumArtImageView; - private DragSortListView playlistView; + private RecyclerView playlistView; private TextView positionTextView; private TextView durationTextView; private TextView statusTextView; @@ -172,7 +176,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis durationTextView = (TextView)rootView.findViewById(R.id.download_duration); statusTextView = (TextView)rootView.findViewById(R.id.download_status); progressBar = (SeekBar)rootView.findViewById(R.id.download_progress_bar); - playlistView = (DragSortListView)rootView.findViewById(R.id.download_list); previousButton = (AutoRepeatButton)rootView.findViewById(R.id.download_previous); nextButton = (AutoRepeatButton)rootView.findViewById(R.id.download_next); pauseButton =rootView.findViewById(R.id.download_pause); @@ -184,6 +187,45 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis rateGoodButton = (ImageButton) rootView.findViewById(R.id.download_rating_good); toggleListButton =rootView.findViewById(R.id.download_toggle_list); + playlistView = (RecyclerView)rootView.findViewById(R.id.download_list); + setupLayoutManager(playlistView, false); + ItemTouchHelper touchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT) { + @Override + public boolean onMove(RecyclerView recyclerView, final RecyclerView.ViewHolder fromHolder, final RecyclerView.ViewHolder toHolder) { + new SilentBackgroundTask<Void>(context) { + private int from; + private int to; + + @Override + protected Void doInBackground() throws Throwable { + from = fromHolder.getAdapterPosition(); + to = toHolder.getAdapterPosition(); + getDownloadService().swap(true, from, to); + return null; + } + + @Override + protected void done(Void result) { + songListAdapter.notifyItemMoved(from, to); + } + }.execute(); + + return true; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + SongView songView = (SongView) ((UpdateView.UpdateViewHolder) viewHolder).getUpdateView(); + DownloadFile downloadFile = songView.getDownloadFile(); + + DownloadService downloadService = getDownloadService(); + downloadService.remove(downloadFile); + songListAdapter.removeItem(downloadFile); + currentRevision = downloadService.getDownloadListUpdateRevision(); + } + }); + touchHelper.attachToRecyclerView(playlistView); + starButton = (ImageButton)rootView.findViewById(R.id.download_star); if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_STAR, true)) { starButton.setOnClickListener(new OnClickListener() { @@ -499,47 +541,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } } }); - playlistView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> parent, View view, final int position, long id) { - warnIfStorageUnavailable(); - new SilentBackgroundTask<Void>(context) { - @Override - protected Void doInBackground() throws Throwable { - getDownloadService().play(position); - return null; - } - - @Override - protected void done(Void result) { - onCurrentChanged(); - onProgressChanged(); - } - }.execute(); - } - }); - playlistView.setDropListener(new DragSortListView.DropListener() { - @Override - public void drop(final int from, final int to) { - new SilentBackgroundTask<Void>(context) { - @Override - protected Void doInBackground() throws Throwable { - getDownloadService().swap(true, from, to); - onDownloadListChanged(); - - return null; - } - }.execute(); - } - }); - playlistView.setRemoveListener(new DragSortListView.RemoveListener() { - @Override - public void remove(int which) { - getDownloadService().remove(which); - onDownloadListChanged(); - } - }); - registerForContextMenu(playlistView); if(Build.MODEL.equals("Nexus 4") || Build.MODEL.equals("GT-I9100")) { @@ -606,10 +607,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis if(!primaryFragment) { return; } + UpdateView targetView = songListAdapter.getContextView(); + menuInfo = new AdapterView.AdapterContextMenuInfo(targetView, 0, 0); if (view == playlistView) { - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - DownloadFile downloadFile = (DownloadFile) playlistView.getItemAtPosition(info.position); + DownloadFile downloadFile = songListAdapter.getContextItem(); android.view.MenuInflater inflater = context.getMenuInflater(); if(Util.isOffline(context)) { @@ -634,8 +636,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis return false; } - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); - DownloadFile downloadFile = (DownloadFile) playlistView.getItemAtPosition(info.position); + DownloadFile downloadFile = songListAdapter.getContextItem(); return menuItemSelected(menuItem.getItemId(), downloadFile) || super.onContextItemSelected(menuItem); } @@ -997,18 +998,18 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis return; } - for (int i = 0; i < songListAdapter.getCount(); i++) { - if (currentPlaying == playlistView.getItemAtPosition(i)) { - playlistView.setSelectionFromTop(i, 40); - return; - } + // Try to get position of current playing/downloading + int position = songListAdapter.getItemPosition(currentPlaying); + if(position == -1) { + DownloadFile currentDownloading = getDownloadService().getCurrentDownloading(); + position = songListAdapter.getItemPosition(currentDownloading); } - DownloadFile currentDownloading = getDownloadService().getCurrentDownloading(); - for (int i = 0; i < songListAdapter.getCount(); i++) { - if (currentDownloading == playlistView.getItemAtPosition(i)) { - playlistView.setSelectionFromTop(i, 40); - return; - } + + // If found, scroll to it + if(position != -1) { + // RecyclerView.scrollToPosition just puts it on the screen (ie: bottom if scrolled below it) + LinearLayoutManager layoutManager = (LinearLayoutManager) playlistView.getLayoutManager(); + layoutManager.scrollToPositionWithOffset(position, 0); } } @@ -1162,9 +1163,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } if(songListAdapter == null || refresh) { - songList = new ArrayList<DownloadFile>(); + songList = new ArrayList<>(); songList.addAll(list); - playlistView.setAdapter(songListAdapter = new DownloadFileAdapter(context, songList)); + playlistView.setAdapter(songListAdapter = new DownloadFileAdapter(context, songList, NowPlayingFragment.this)); } else { songList.clear(); songList.addAll(list); @@ -1590,4 +1591,19 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis public boolean onSingleTapUp(MotionEvent e) { return false; } + + @Override + public void onItemClicked(final DownloadFile item) { + warnIfStorageUnavailable(); + new SilentBackgroundTask<Void>(context) { + @Override + protected Void doInBackground() throws Throwable { + getDownloadService().play(item); + + onCurrentChanged(); + onProgressChanged(); + return null; + } + }.execute(); + } } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectListFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectListFragment.java deleted file mode 100644 index 6f73f6e8..00000000 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectListFragment.java +++ /dev/null @@ -1,163 +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 <http://www.gnu.org/licenses/>. - - Copyright 2010 (C) Sindre Mehus - */ -package github.daneren2005.dsub.fragments; - -import android.os.Bundle; -import android.support.v4.widget.SwipeRefreshLayout; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import github.daneren2005.dsub.R; -import github.daneren2005.dsub.service.MusicService; -import github.daneren2005.dsub.service.MusicServiceFactory; -import github.daneren2005.dsub.util.BackgroundTask; -import github.daneren2005.dsub.util.Constants; -import github.daneren2005.dsub.util.ProgressListener; -import github.daneren2005.dsub.util.TabBackgroundTask; - -public abstract class SelectListFragment<T> extends SubsonicFragment implements AdapterView.OnItemClickListener { - private static final String TAG = SelectListFragment.class.getSimpleName(); - protected ListView listView; - protected ArrayAdapter adapter; - protected BackgroundTask<List<T>> currentTask; - protected List<T> objects; - protected boolean serialize = true; - - @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - - if(bundle != null && serialize) { - objects = (List<T>) bundle.getSerializable(Constants.FRAGMENT_LIST); - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - if(serialize) { - outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) objects); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { - rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false); - - refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout); - refreshLayout.setOnRefreshListener(this); - - listView = (ListView)rootView.findViewById(R.id.fragment_list); - listView.setOnItemClickListener(this); - setupScrollList(listView); - registerForContextMenu(listView); - - if(objects == null) { - refresh(false); - } else { - listView.setAdapter(adapter = getAdapter(objects)); - } - - return rootView; - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { - if(!primaryFragment) { - return; - } - - menuInflater.inflate(getOptionsMenu(), menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); - } - - @Override - protected void refresh(final boolean refresh) { - int titleRes = getTitleResource(); - if(titleRes != 0) { - setTitle(getTitleResource()); - } - listView.setVisibility(View.GONE); - - // Cancel current running task before starting another one - if(currentTask != null) { - currentTask.cancel(); - } - - currentTask = new TabBackgroundTask<List<T>>(this) { - @Override - protected List<T> doInBackground() throws Throwable { - MusicService musicService = MusicServiceFactory.getMusicService(context); - - objects = new ArrayList<T>(); - - try { - objects = getObjects(musicService, refresh, this); - } catch (Exception x) { - Log.e(TAG, "Failed to load", x); - } - - return objects; - } - - @Override - protected void done(List<T> result) { - if (result != null && !result.isEmpty()) { - // Toggle fast scroll to get around issue when length of list changes - listView.setFastScrollEnabled(false); - listView.setAdapter(adapter = getAdapter(result)); - listView.setFastScrollEnabled(true); - - onFinishRefresh(); - listView.setVisibility(View.VISIBLE); - } else { - setEmpty(true); - } - - currentTask = null; - } - }; - currentTask.execute(); - } - - public abstract int getOptionsMenu(); - public abstract ArrayAdapter getAdapter(List<T> objs); - public abstract List<T> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception; - public abstract int getTitleResource(); - - public void onFinishRefresh() { - - } -} diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java index e91a163c..bf25db77 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectVideoFragment.java @@ -19,7 +19,6 @@ import android.view.ContextMenu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; -import android.widget.ArrayAdapter; import java.util.List; @@ -29,7 +28,6 @@ import github.daneren2005.dsub.adapter.SectionAdapter; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.util.ProgressListener; -import github.daneren2005.dsub.adapter.EntryAdapter; import github.daneren2005.dsub.view.UpdateView; public class SelectVideoFragment extends SelectRecyclerFragment<MusicDirectory.Entry> { diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java index 00c7c603..25196d66 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/UserFragment.java @@ -15,71 +15,30 @@ package github.daneren2005.dsub.fragments; -import android.app.Activity; import android.os.Bundle; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; + +import java.util.List; import github.daneren2005.dsub.R; -import github.daneren2005.dsub.activity.SubsonicActivity; +import github.daneren2005.dsub.adapter.SectionAdapter; import github.daneren2005.dsub.domain.ServerInfo; import github.daneren2005.dsub.domain.User; +import github.daneren2005.dsub.service.MusicService; import github.daneren2005.dsub.util.Constants; -import github.daneren2005.dsub.util.ImageLoader; +import github.daneren2005.dsub.util.ProgressListener; import github.daneren2005.dsub.util.UserUtil; import github.daneren2005.dsub.adapter.SettingsAdapter; -public class UserFragment extends SubsonicFragment{ - private ListView listView; +public class UserFragment extends SelectRecyclerFragment<User.Setting>{ private User user; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { - rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false); - - refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout); - refreshLayout.setEnabled(false); - + public void onCreate(Bundle bundle) { + super.onCreate(bundle); Bundle args = getArguments(); user = (User) args.getSerializable(Constants.INTENT_EXTRA_NAME_ID); - - listView = (ListView)rootView.findViewById(R.id.fragment_list); - createHeader(); - listView.setAdapter(new SettingsAdapter(context, user.getSettings(), UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10"))); - - setTitle(user.getUsername()); - - return rootView; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - ((SubsonicActivity) activity).supportInvalidateOptionsMenu(); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { - // For some reason this is called before onAttach - if(!primaryFragment || context == null) { - return; - } - - if(UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10")) { - menuInflater.inflate(R.menu.user, menu); - } else if(UserUtil.isCurrentRole(User.SETTINGS)) { - menuInflater.inflate(R.menu.user_user, menu); - } else { - menuInflater.inflate(R.menu.empty, menu); - } + pullToRefresh = false; } @Override @@ -103,23 +62,35 @@ public class UserFragment extends SubsonicFragment{ return false; } - private void createHeader() { - View header = LayoutInflater.from(context).inflate(R.layout.user_header, listView, false); + @Override + public int getOptionsMenu() { + if(UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10")) { + return R.menu.user; + } else if(UserUtil.isCurrentRole(User.SETTINGS)) { + return R.menu.user_user; + } else { + return R.menu.empty; + } + } + + @Override + public SectionAdapter<User.Setting> getAdapter(List<User.Setting> objs) { + return new SettingsAdapter(context, user, getImageLoader(), UserUtil.isCurrentAdmin() && ServerInfo.checkServerVersion(context, "1.10")); + } - final ImageLoader imageLoader = getImageLoader(); - ImageView coverArtView = (ImageView) header.findViewById(R.id.user_avatar); - imageLoader.loadAvatar(context, coverArtView, user.getUsername()); + @Override + public List<User.Setting> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception { + return user.getSettings(); + } - TextView usernameView = (TextView) header.findViewById(R.id.user_username); - usernameView.setText(user.getUsername()); + @Override + public int getTitleResource() { + setTitle(user.getUsername()); + return 0; + } - final TextView emailView = (TextView) header.findViewById(R.id.user_email); - if(user.getEmail() != null) { - emailView.setText(user.getEmail()); - } else { - emailView.setVisibility(View.GONE); - } + @Override + public void onItemClicked(User.Setting item) { - listView.addHeaderView(header); } } diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java index c0268933..40521051 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java @@ -886,6 +886,9 @@ public class DownloadService extends Service { public synchronized void play(int index) { play(index, true); } + public synchronized void play(DownloadFile downloadFile) { + play(downloadList.indexOf(downloadFile)); + } private synchronized void play(int index, boolean start) { play(index, start, 0); } @@ -1818,6 +1821,10 @@ public class DownloadService extends Service { applyReplayGain(mediaPlayer, currentPlaying); } + public synchronized void swap(boolean mainList, DownloadFile from, DownloadFile to) { + List<DownloadFile> list = mainList ? downloadList : backgroundDownloadList; + swap(mainList, list.indexOf(from), list.indexOf(to)); + } public synchronized void swap(boolean mainList, int from, int to) { List<DownloadFile> list = mainList ? downloadList : backgroundDownloadList; int max = list.size(); diff --git a/app/src/main/java/github/daneren2005/dsub/util/UserUtil.java b/app/src/main/java/github/daneren2005/dsub/util/UserUtil.java index 5c5f1543..fb2de05e 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/UserUtil.java +++ b/app/src/main/java/github/daneren2005/dsub/util/UserUtil.java @@ -21,8 +21,11 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.support.v7.app.ActionBarActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; +import android.view.WindowManager; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; @@ -183,6 +186,7 @@ public final class UserUtil { .setCancelable(true); AlertDialog dialog = builder.create(); + dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); dialog.show(); } } @@ -248,7 +252,6 @@ public final class UserUtil { protected Void doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(context); musicService.updateUser(user, context, null); - user.setSettings(user.getSettings()); return null; } @@ -378,8 +381,11 @@ public final class UserUtil { final TextView usernameView = (TextView) layout.findViewById(R.id.username); final TextView emailView = (TextView) layout.findViewById(R.id.email); final TextView passwordView = (TextView) layout.findViewById(R.id.password); - final ListView listView = (ListView) layout.findViewById(R.id.settings_list); - listView.setAdapter(new SettingsAdapter(context, user, true)); + final RecyclerView recyclerView = (RecyclerView) layout.findViewById(R.id.settings_list); + LinearLayoutManager layoutManager = new LinearLayoutManager(context); + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(new SettingsAdapter(context, user, null, true)); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.menu_add_user) diff --git a/app/src/main/java/github/daneren2005/dsub/view/SettingView.java b/app/src/main/java/github/daneren2005/dsub/view/SettingView.java index 1c78706e..63b2c844 100644 --- a/app/src/main/java/github/daneren2005/dsub/view/SettingView.java +++ b/app/src/main/java/github/daneren2005/dsub/view/SettingView.java @@ -17,8 +17,9 @@ package github.daneren2005.dsub.view; import android.content.Context; import android.view.LayoutInflater; -import android.view.View; -import android.widget.CheckedTextView; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.User; @@ -26,16 +27,28 @@ import github.daneren2005.dsub.domain.User; import static github.daneren2005.dsub.domain.User.Setting; public class SettingView extends UpdateView { - Setting setting; + private final TextView titleView; + private final CheckBox checkBox; - CheckedTextView view; + private Setting setting; + private boolean enabled = false; public SettingView(Context context) { super(context, false); this.context = context; - LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_multiple_choice, this, true); + LayoutInflater.from(context).inflate(R.layout.basic_choice_item, this, true); - view = (CheckedTextView) findViewById(android.R.id.text1); + titleView = (TextView) findViewById(R.id.item_name); + checkBox = (CheckBox) findViewById(R.id.item_checkbox); + checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if(setting != null) { + setting.setValue(isChecked); + } + } + }); + checkBox.setClickable(false); } protected void setObjectImpl(Object obj, Object editable) { @@ -74,29 +87,29 @@ public class SettingView extends UpdateView { res = R.string.admin_role_lastfm; } else { // Last resort to display the raw value - view.setText(name); + titleView.setText(name); } if(res != -1) { - view.setText(res); + titleView.setText(res); } if(setting.getValue()) { - view.setChecked(setting.getValue()); + checkBox.setChecked(setting.getValue()); } else { - view.setChecked(false); + checkBox.setChecked(false); } - if((Boolean) editable) { - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - view.toggle(); - setting.setValue(view.isChecked()); - } - }); - } else { - view.setOnClickListener(null); - } + enabled = (Boolean) editable; + checkBox.setEnabled(enabled); + } + + @Override + public boolean isCheckable() { + return this.enabled; + } + + public void setChecked(boolean checked) { + checkBox.setChecked(checked); } } diff --git a/app/src/main/res/layout/basic_choice_item.xml b/app/src/main/res/layout/basic_choice_item.xml new file mode 100644 index 00000000..00a45be4 --- /dev/null +++ b/app/src/main/res/layout/basic_choice_item.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="?attr/selectableItemBackground"> + + <TextView + android:id="@+id/item_name" + android:layout_width="0dip" + android:layout_height="?android:attr/listPreferredItemHeight" + android:layout_weight="1" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="left|center_vertical" + android:paddingLeft="6dip" + android:paddingRight="6dip" + android:background="@android:color/transparent"/> + + <CheckBox + android:id="@+id/item_checkbox" + android:layout_width="wrap_content" + android:layout_height="fill_parent" + android:layout_gravity="right|center_vertical" + android:checkMark="?android:attr/listChoiceIndicatorMultiple" + style="@style/MoreButton"/> +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/create_user.xml b/app/src/main/res/layout/create_user.xml index eac6e5cb..e2f6c4eb 100644 --- a/app/src/main/res/layout/create_user.xml +++ b/app/src/main/res/layout/create_user.xml @@ -67,11 +67,10 @@ android:layout_marginLeft="4dp" /> </LinearLayout> - <ListView + <android.support.v7.widget.RecyclerView android:id="@+id/settings_list" android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1.0" - android:fastScrollEnabled="true"/> - + android:scrollbars="vertical"/> </LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/download_playlist.xml b/app/src/main/res/layout/download_playlist.xml index 8a73ef3b..afb46081 100644 --- a/app/src/main/res/layout/download_playlist.xml +++ b/app/src/main/res/layout/download_playlist.xml @@ -1,31 +1,28 @@ <?xml version="1.0" encoding="utf-8"?> - <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:layout_weight="1"> + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layout_weight="1"> <View - android:layout_width="fill_parent" - android:layout_height="1px" - android:background="@color/dividerColor"/> + android:layout_width="fill_parent" + android:layout_height="1px" + android:background="@color/dividerColor"/> <TextView - android:id="@+id/download_empty" - android:text="@string/download.empty" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:padding="10dip"/> + android:id="@+id/download_empty" + android:text="@string/download.empty" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="10dip"/> - <com.mobeta.android.dslv.DragSortListView - style="@style/DragDropListView" + <android.support.v7.widget.RecyclerView android:id="@+id/download_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" - android:cacheColorHint="#00000000" - android:fastScrollEnabled="true"/> + android:scrollbars="vertical"/> </LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/select_album_header.xml b/app/src/main/res/layout/select_album_header.xml index d028a476..e3a09443 100644 --- a/app/src/main/res/layout/select_album_header.xml +++ b/app/src/main/res/layout/select_album_header.xml @@ -148,6 +148,12 @@ android:textAppearance="?android:attr/textAppearanceMedium"/> </LinearLayout> </FrameLayout> + + <View + android:layout_width="fill_parent" + android:layout_height="1px" + android:background="@color/dividerColor" + android:layout_gravity="bottom"/> </FrameLayout> diff --git a/app/src/main/res/layout/select_artist_header.xml b/app/src/main/res/layout/select_artist_header.xml index 0ac9e6a6..168120d9 100644 --- a/app/src/main/res/layout/select_artist_header.xml +++ b/app/src/main/res/layout/select_artist_header.xml @@ -42,4 +42,9 @@ </LinearLayout> </LinearLayout> + + <View + android:layout_width="fill_parent" + android:layout_height="1px" + android:background="@color/dividerColor"/> </LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/user_header.xml b/app/src/main/res/layout/user_header.xml index 0b303afe..a9ff4bee 100644 --- a/app/src/main/res/layout/user_header.xml +++ b/app/src/main/res/layout/user_header.xml @@ -52,6 +52,12 @@ android:autoLink="email"/> </LinearLayout> + + <View + android:layout_width="fill_parent" + android:layout_height="1px" + android:background="@color/dividerColor" + android:layout_alignParentBottom="true"/> </RelativeLayout> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index c4a53b99..cfe446f3 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -59,23 +59,6 @@ <item name="android:paddingLeft">16dip</item> </style> - <style name="DragDropListView"> - <item name="drag_enabled">true</item> - <item name="collapsed_height">1dp</item> - <item name="drag_scroll_start">1.0</item> - <item name="max_drag_scroll_speed">2.0</item> - <item name="float_alpha">0.6</item> - <item name="slide_shuffle_speed">0.3</item> - <item name="track_drag_sort">false</item> - <item name="use_default_controller">true</item> - <item name="drag_handle_id">@id/drag_handle</item> - <item name="sort_enabled">true</item> - <item name="remove_enabled">false</item> - <item name="remove_mode">flingRemove</item> - <item name="drag_start_mode">onLongPress</item> - <item name="float_background_color">@android:color/transparent</item> - </style> - <style name="MainAlbumButton"> <item name="android:drawablePadding">6dip</item> <item name="android:layout_width">fill_parent</item> |