aboutsummaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java10
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java25
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java9
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java3
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/SimilarArtistAdapter.java53
-rw-r--r--app/src/main/java/github/daneren2005/dsub/domain/Artist.java10
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java29
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java58
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java23
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java78
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java3
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java14
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/CachedMusicService.java22
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java5
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadService.java3
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/MusicService.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java5
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java45
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/parser/EntryListParser.java (renamed from app/src/main/java/github/daneren2005/dsub/service/parser/AlbumListParser.java)7
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Constants.java1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Util.java27
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/SongView.java3
-rw-r--r--app/src/main/res/menu/drawer_menu.xml2
-rw-r--r--app/src/main/res/menu/multiselect_nowplaying.xml27
-rw-r--r--app/src/main/res/menu/multiselect_nowplaying_offline.xml9
-rw-r--r--app/src/main/res/menu/nowplaying.xml5
-rw-r--r--app/src/main/res/menu/nowplaying_context.xml4
-rw-r--r--app/src/main/res/menu/nowplaying_context_offline.xml2
-rw-r--r--app/src/main/res/menu/nowplaying_offline.xml5
-rw-r--r--app/src/main/res/menu/similar_artists.xml4
-rw-r--r--app/src/main/res/values-de/strings.xml1
-rw-r--r--app/src/main/res/values-es/strings.xml1
-rw-r--r--app/src/main/res/values-hu/strings.xml1
-rw-r--r--app/src/main/res/values-nl/strings.xml1
-rw-r--r--app/src/main/res/values-pt-rPT/strings.xml1
-rw-r--r--app/src/main/res/values-sv/strings.xml1
-rw-r--r--app/src/main/res/values/attrs.xml1
-rw-r--r--app/src/main/res/values/strings.xml10
-rw-r--r--app/src/main/res/values/themes.xml3
42 files changed, 420 insertions, 99 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
index e6be70f7..9e18b47a 100644
--- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
+++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
@@ -93,6 +93,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
private SlidingUpPanelLayout slideUpPanel;
private SlidingUpPanelLayout.PanelSlideListener panelSlideListener;
+ private boolean isPanelClosing = false;
private NowPlayingFragment nowPlayingFragment;
private SubsonicFragment secondaryFragment;
private Toolbar mainToolbar;
@@ -195,6 +196,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
@Override
public void onPanelCollapsed(View panel) {
+ isPanelClosing = false;
bottomBar.setVisibility(View.VISIBLE);
nowPlayingToolbar.setVisibility(View.GONE);
nowPlayingFragment.setPrimaryFragment(false);
@@ -204,6 +206,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
@Override
public void onPanelExpanded(View panel) {
+ isPanelClosing = false;
currentFragment.stopActionMode();
// Disable custom view before switching
@@ -341,6 +344,10 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
super.onNewIntent(intent);
if(currentFragment != null && intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
+ if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
+ closeNowPlaying();
+ }
+
if(currentFragment instanceof SearchFragment) {
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
@@ -483,7 +490,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
@Override
public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) {
- if(slideUpPanel != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
+ if(slideUpPanel != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && !isPanelClosing) {
secondaryFragment = fragment;
nowPlayingFragment.setPrimaryFragment(false);
secondaryFragment.setPrimaryFragment(true);
@@ -573,6 +580,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
@Override
public void closeNowPlaying() {
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
+ isPanelClosing = true;
}
private SubsonicFragment getNewFragment(String fragmentType) {
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 d4613994..5b3dc289 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/DownloadFileAdapter.java
@@ -16,13 +16,18 @@
package github.daneren2005.dsub.adapter;
import android.content.Context;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import java.util.List;
+import github.daneren2005.dsub.R;
import github.daneren2005.dsub.service.DownloadFile;
+import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.view.FastScroller;
import github.daneren2005.dsub.view.SongView;
import github.daneren2005.dsub.view.UpdateView;
@@ -33,6 +38,7 @@ public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements
public DownloadFileAdapter(Context context, List<DownloadFile> entries, OnItemClickedListener onItemClickedListener) {
super(context, entries);
this.onItemClickedListener = onItemClickedListener;
+ this.checkable = true;
}
@Override
@@ -43,7 +49,7 @@ public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements
@Override
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, DownloadFile item, int viewType) {
SongView songView = (SongView) holder.getUpdateView();
- songView.setObject(item.getSong(), false);
+ songView.setObject(item.getSong(), Util.isBatchMode(context));
songView.setDownloadFile(item);
}
@@ -56,4 +62,21 @@ public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements
public String getTextToShowInBubble(int position) {
return null;
}
+
+ @Override
+ public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
+ if(Util.isOffline(context)) {
+ menuInflater.inflate(R.menu.multiselect_nowplaying_offline, menu);
+ } else {
+ menuInflater.inflate(R.menu.multiselect_nowplaying, menu);
+ }
+
+ if(!selected.isEmpty()) {
+ MenuItem starItem = menu.findItem(R.id.menu_star);
+ if(starItem != null) {
+ boolean isStarred = selected.get(0).getSong().isStarred();
+ starItem.setTitle(isStarred ? R.string.common_unstar : R.string.common_star);
+ }
+ }
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java
index 2c4f75dc..6c1c14da 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/EntryInfiniteGridAdapter.java
@@ -26,6 +26,7 @@ import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.MusicDirectory.Entry;
import github.daneren2005.dsub.domain.ServerInfo;
+import github.daneren2005.dsub.fragments.MainFragment;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.util.ImageLoader;
@@ -88,6 +89,10 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
this.type = type;
this.extra = extra;
this.size = size;
+
+ if(super.getItemCount() < size) {
+ allLoaded = true;
+ }
}
public void loadMore() {
@@ -110,7 +115,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
appendCachedData(newData);
loading = false;
- if(newData.isEmpty()) {
+ if(newData.size() < size) {
allLoaded = true;
notifyDataSetChanged();
}
@@ -126,6 +131,8 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter {
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 if(type.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) {
+ result = service.getSongList(type, size, offset, context, null);
} else {
result = service.getAlbumList(type, size, offset, false, context, null);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java
index 8f1f1c38..473366fe 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/MainAdapter.java
@@ -100,6 +100,9 @@ public class MainAdapter extends SectionAdapter<Integer> {
} else if("videos".equals(header)) {
display = context.getResources().getString(R.string.main_videos);
checkBox.setVisibility(View.GONE);
+ } else if("songs".equals(header)) {
+ display = context.getResources().getString(R.string.search_songs);
+ checkBox.setVisibility(View.GONE);
} else {
display = header;
checkBox.setVisibility(View.GONE);
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/SimilarArtistAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/SimilarArtistAdapter.java
new file mode 100644
index 00000000..2234d4cd
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/SimilarArtistAdapter.java
@@ -0,0 +1,53 @@
+/*
+ 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 2016 (C) Scott Jackson
+*/
+
+package github.daneren2005.dsub.adapter;
+
+import android.content.Context;
+import android.view.ViewGroup;
+
+import java.util.List;
+
+import github.daneren2005.dsub.domain.Artist;
+import github.daneren2005.dsub.view.ArtistView;
+import github.daneren2005.dsub.view.UpdateView;
+
+public class SimilarArtistAdapter extends SectionAdapter<Artist> {
+ public static int VIEW_TYPE_ARTIST = 4;
+
+ public SimilarArtistAdapter(Context context, List<Artist> artists, OnItemClickedListener onItemClickedListener) {
+ super(context, artists);
+ this.onItemClickedListener = onItemClickedListener;
+ }
+ public SimilarArtistAdapter(Context context, List<String> headers, List<List<Artist>> sections, OnItemClickedListener onItemClickedListener) {
+ super(context, headers, sections);
+ this.onItemClickedListener = onItemClickedListener;
+ }
+
+ @Override
+ public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
+ return new UpdateView.UpdateViewHolder(new ArtistView(context));
+ }
+
+ @Override
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Artist item, int viewType) {
+ holder.getUpdateView().setObject(item);
+ }
+
+ @Override
+ public int getItemViewType(Artist item) {
+ return VIEW_TYPE_ARTIST;
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/domain/Artist.java b/app/src/main/java/github/daneren2005/dsub/domain/Artist.java
index 56e8f92e..9d4cbe29 100644
--- a/app/src/main/java/github/daneren2005/dsub/domain/Artist.java
+++ b/app/src/main/java/github/daneren2005/dsub/domain/Artist.java
@@ -30,6 +30,8 @@ import java.util.List;
*/
public class Artist implements Serializable {
private static final String TAG = Artist.class.getSimpleName();
+ public static final String ROOT_ID = "-1";
+ public static final String MISSING_ID = "-2";
private String id;
private String name;
@@ -38,6 +40,14 @@ public class Artist implements Serializable {
private Integer rating;
private int closeness;
+ public Artist() {
+
+ }
+ public Artist(String id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
public String getId() {
return id;
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
index f048587b..65ed99b9 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
@@ -46,6 +46,11 @@ import javax.net.ssl.HttpsURLConnection;
public class MainFragment extends SelectRecyclerFragment<Integer> {
private static final String TAG = MainFragment.class.getSimpleName();
+ public static final String SONGS_LIST_PREFIX = "songs-";
+ public static final String SONGS_NEWEST = SONGS_LIST_PREFIX + "newest";
+ public static final String SONGS_TOP_PLAYED = SONGS_LIST_PREFIX + "topPlayed";
+ public static final String SONGS_RECENT = SONGS_LIST_PREFIX + "recent";
+ public static final String SONGS_FREQUENT = SONGS_LIST_PREFIX + "frequent";
public MainFragment() {
super();
@@ -124,6 +129,22 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
sections.add(albums);
headers.add("albums");
+ if(ServerInfo.isMadsonic6(context)) {
+ List<Integer> songs = new ArrayList<>();
+
+ songs.add(R.string.main_songs_newest);
+ if(ServerInfo.checkServerVersion(context, "2.0.1")) {
+ songs.add(R.string.main_songs_top_played);
+ }
+ songs.add(R.string.main_songs_recent);
+ if(ServerInfo.checkServerVersion(context, "2.0.1")) {
+ songs.add(R.string.main_songs_frequent);
+ }
+
+ sections.add(songs);
+ headers.add("songs");
+ }
+
if(ServerInfo.checkServerVersion(context, "1.8")) {
List<Integer> videos = Arrays.asList(R.string.main_videos);
sections.add(videos);
@@ -383,6 +404,14 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
showAlbumList("alphabeticalByName");
} else if(item == R.string.main_videos) {
showVideos();
+ } else if (item == R.string.main_songs_newest) {
+ showAlbumList(SONGS_NEWEST);
+ } else if (item == R.string.main_songs_top_played) {
+ showAlbumList(SONGS_TOP_PLAYED);
+ } else if (item == R.string.main_songs_recent) {
+ showAlbumList(SONGS_RECENT);
+ } else if (item == R.string.main_songs_frequent) {
+ showAlbumList(SONGS_FREQUENT);
}
}
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 d77f476f..5de9c595 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
@@ -457,6 +457,10 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
mediaRouteButton.setRouteSelector(downloadService.getRemoteSelector());
}
}
+
+ if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false)) {
+ menu.findItem(R.id.menu_batch_mode).setChecked(true);
+ }
}
@Override
@@ -474,7 +478,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
menuInflater.inflate(R.menu.nowplaying_context_offline, menu);
} else {
menuInflater.inflate(R.menu.nowplaying_context, menu);
- menu.findItem(R.id.menu_star).setTitle(downloadFile.getSong().isStarred() ? R.string.common_unstar : R.string.common_star);
+ menu.findItem(R.id.song_menu_star).setTitle(downloadFile.getSong().isStarred() ? R.string.common_unstar : R.string.common_star);
}
if (downloadFile.getSong().getParent() == null) {
@@ -620,9 +624,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
createNewPlaylist(entries, true);
return true;
- case R.id.menu_star:
- UpdateHelper.toggleStarred(context, song.getSong());
- return true;
case R.id.menu_rate:
UpdateHelper.setRating(context, song.getSong());
return true;
@@ -634,11 +635,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
startTimer();
}
return true;
- case R.id.menu_add_playlist:
- songs = new ArrayList<Entry>(1);
- songs.add(song.getSong());
- addToPlaylist(songs);
- return true;
case R.id.menu_info:
displaySongInfo(song.getSong());
return true;
@@ -663,7 +659,18 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
// Any failed condition will get here
Util.toast(context, "Failed to start equalizer. Try restarting.");
return true;
- } default:
+ }case R.id.menu_batch_mode:
+ if(Util.isBatchMode(context)) {
+ Util.setBatchMode(context, false);
+ songListAdapter.notifyDataSetChanged();
+ } else {
+ Util.setBatchMode(context, true);
+ songListAdapter.notifyDataSetChanged();
+ }
+ context.supportInvalidateOptionsMenu();
+
+ return true;
+ default:
return false;
}
}
@@ -1158,11 +1165,23 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
@Override
public void onSongChanged(DownloadFile currentPlaying, int currentPlayingIndex) {
this.currentPlaying = currentPlaying;
+ setupSubtitle(currentPlayingIndex);
+ }
+
+ private void setupSubtitle(int currentPlayingIndex) {
if (currentPlaying != null) {
Entry song = currentPlaying.getSong();
songTitleTextView.setText(song.getTitle());
getImageLoader().loadImage(albumArtImageView, song, true, true);
- setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize));
+
+ DownloadService downloadService = getDownloadService();
+ if(downloadService.isShufflePlayEnabled()) {
+ setSubtitle(context.getResources().getString(R.string.download_playerstate_playing_shuffle));
+ } else if(downloadService.isArtistRadio()) {
+ setSubtitle(context.getResources().getString(R.string.download_playerstate_playing_artist_radio));
+ } else {
+ setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize));
+ }
} else {
songTitleTextView.setText(null);
getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false);
@@ -1199,10 +1218,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
scrollWhenLoaded = false;
}
- setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize));
if(this.currentPlaying != currentPlaying) {
onSongChanged(currentPlaying, currentPlayingIndex);
onMetadataUpdate(currentPlaying != null ? currentPlaying.getSong() : null, DownloadService.METADATA_UPDATED_ALL);
+ } else {
+ setupSubtitle(currentPlayingIndex);
}
}
@@ -1356,4 +1376,18 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
break;
}
}
+
+ @Override
+ protected List<Entry> getSelectedEntries() {
+ List<DownloadFile> selected = getCurrentAdapter().getSelected();
+ List<Entry> entries = new ArrayList<>();
+
+ for(DownloadFile downloadFile: selected) {
+ if(downloadFile.getSong() != null) {
+ entries.add(downloadFile.getSong());
+ }
+ }
+
+ return entries;
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
index d21b82e0..5c659a6a 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
@@ -130,7 +130,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case R.id.menu_search:
+ case R.id.menu_global_search:
context.startSearch(currentQuery, false, null, false);
return true;
}
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 4209cfd6..718ad5c5 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
@@ -387,16 +387,17 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
} 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());
+ if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, true) && (albumListType == null || "starred".equals(albumListType))) {
+ for(Entry song: entries) {
+ if(!song.isDirectory() && !song.isVideo()) {
+ songs.add(song);
+ }
}
+ playNow(songs, entry, 0);
} else {
songs.add(entry);
+ playNow(songs);
}
-
- playNow(songs);
}
}
@@ -580,6 +581,14 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
setTitle(albumListExtra);
} else if("alphabeticalByName".equals(albumListType)) {
setTitle(R.string.main_albums_alphabetical);
+ } if (MainFragment.SONGS_NEWEST.equals(albumListType)) {
+ setTitle(R.string.main_songs_newest);
+ } else if (MainFragment.SONGS_TOP_PLAYED.equals(albumListType)) {
+ setTitle(R.string.main_songs_top_played);
+ } else if (MainFragment.SONGS_RECENT.equals(albumListType)) {
+ setTitle(R.string.main_songs_recent);
+ } else if (MainFragment.SONGS_FREQUENT.equals(albumListType)) {
+ setTitle(R.string.main_songs_frequent);
}
new LoadTask(true) {
@@ -596,6 +605,8 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
}
} else if("genres".equals(albumListType) || "genres-songs".equals(albumListType)) {
result = service.getSongsByGenre(albumListExtra, size, 0, context, this);
+ } else if(albumListType.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) {
+ result = service.getSongList(albumListType, size, 0, context, this);
} else {
result = service.getAlbumList(albumListType, size, 0, refresh, context, this);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java
index 93e3a93a..a41b9d6f 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SimilarArtistFragment.java
@@ -15,14 +15,16 @@
package github.daneren2005.dsub.fragments;
+import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.adapter.ArtistAdapter;
import github.daneren2005.dsub.adapter.SectionAdapter;
+import github.daneren2005.dsub.adapter.SimilarArtistAdapter;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.ArtistInfo;
import github.daneren2005.dsub.domain.MusicDirectory;
@@ -35,6 +37,8 @@ import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.view.UpdateView;
import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@@ -52,18 +56,6 @@ public class SimilarArtistFragment extends SelectRecyclerFragment<Artist> {
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
- super.onCreateOptionsMenu(menu, menuInflater);
- if(!primaryFragment) {
- return;
- }
-
- if(info.getMissingArtists().isEmpty()) {
- menu.removeItem(R.id.menu_show_missing);
- }
- }
-
- @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_play_now:
@@ -72,9 +64,6 @@ public class SimilarArtistFragment extends SelectRecyclerFragment<Artist> {
case R.id.menu_shuffle:
playAll(true);
return true;
- case R.id.menu_show_missing:
- showMissingArtists();
- break;
}
return super.onOptionsItemSelected(item);
@@ -82,8 +71,10 @@ public class SimilarArtistFragment extends SelectRecyclerFragment<Artist> {
@Override
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Artist> updateView, Artist item) {
- onCreateContextMenuSupport(menu, menuInflater, updateView, item);
- recreateContextMenu(menu);
+ if(!Artist.MISSING_ID.equals(item.getId())) {
+ onCreateContextMenuSupport(menu, menuInflater, updateView, item);
+ recreateContextMenu(menu);
+ }
}
@Override
@@ -93,14 +84,21 @@ public class SimilarArtistFragment extends SelectRecyclerFragment<Artist> {
@Override
public void onItemClicked(UpdateView<Artist> updateView, Artist artist) {
- SubsonicFragment fragment = new SelectDirectoryFragment();
- Bundle args = new Bundle();
- args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
- args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
- args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
- fragment.setArguments(args);
-
- replaceFragment(fragment);
+ if(Artist.MISSING_ID.equals(artist.getId())) {
+ String url = "http://www.last.fm/music/" + URLEncoder.encode(artist.getName());
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ startActivity(intent);
+ } else {
+ SubsonicFragment fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
+ fragment.setArguments(args);
+
+ replaceFragment(fragment);
+ }
}
@Override
@@ -109,8 +107,22 @@ public class SimilarArtistFragment extends SelectRecyclerFragment<Artist> {
}
@Override
- public SectionAdapter getAdapter(List<Artist> objects) {
- return new ArtistAdapter(context, objects, this);
+ public SectionAdapter getAdapter(List<Artist> artists) {
+ if(info.getMissingArtists().isEmpty()) {
+ return new SimilarArtistAdapter(context, artists, this);
+ } else {
+ List<String> headers = new ArrayList<>();
+ headers.add(null);
+ headers.add(context.getResources().getString(R.string.menu_similar_artists_missing));
+
+ List<Artist> missingArtists = new ArrayList<>();
+ for(String artistName: info.getMissingArtists()) {
+ Artist artist = new Artist(Artist.MISSING_ID, artistName);
+ missingArtists.add(artist);
+ }
+
+ return new SimilarArtistAdapter(context, headers, Arrays.asList(artists, missingArtists), this);
+ }
}
@Override
@@ -124,16 +136,6 @@ public class SimilarArtistFragment extends SelectRecyclerFragment<Artist> {
return R.string.menu_similar_artists;
}
- private void showMissingArtists() {
- StringBuilder b = new StringBuilder();
-
- for(String name: info.getMissingArtists()) {
- b.append("<h3><a href=\"https://www.google.com/#q=" + URLEncoder.encode(name) + "\">" + name + "</a></h3> ");
- }
-
- Util.showHTMLDialog(context, R.string.menu_similar_artists, b.toString());
- }
-
private void playAll(final boolean shuffle) {
new RecursiveLoader(context) {
@Override
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
index bc2418eb..0cb433c2 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
@@ -326,6 +326,9 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
public boolean onContextItemSelected(MenuItem menuItem, Object selectedItem) {
Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null;
Entry entry = selectedItem instanceof Entry ? (Entry) selectedItem : null;
+ if(selectedItem instanceof DownloadFile) {
+ entry = ((DownloadFile) selectedItem).getSong();
+ }
List<Entry> songs = new ArrayList<Entry>(1);
songs.add(entry);
diff --git a/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java b/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java
index aa353def..35d419bb 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java
@@ -58,6 +58,7 @@ public class AutoMediaBrowserService extends MediaBrowserService {
private static final String PODCAST_PREFIX = "po-";
private static final String ALBUM_TYPE_PREFIX = "ty-";
private static final String MUSIC_DIRECTORY_PREFIX = "md-";
+ private static final int MAX_DOUBLE_LINE_ITEMS = 9;
private DownloadService downloadService;
private Handler handler = new Handler();
@@ -194,7 +195,7 @@ public class AutoMediaBrowserService extends MediaBrowserService {
albumListType = "newest";
}
- return musicService.getAlbumList(albumListType, 40, 0, true, downloadService, null);
+ return musicService.getAlbumList(albumListType, MAX_DOUBLE_LINE_ITEMS, 0, true, downloadService, null);
}
@Override
@@ -286,6 +287,7 @@ public class AutoMediaBrowserService extends MediaBrowserService {
protected void done(MusicDirectory podcasts) {
List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>();
+ int i = 0;
for(Entry entry: podcasts.getChildren(false, true)) {
PodcastEpisode podcast = (PodcastEpisode) entry;
Bundle podcastExtras = new Bundle();
@@ -294,12 +296,16 @@ public class AutoMediaBrowserService extends MediaBrowserService {
MediaDescription description = new MediaDescription.Builder()
.setTitle(podcast.getTitle())
- .setSubtitle(Util.formatDate(downloadService, podcast.getDate()))
+ .setSubtitle(Util.formatDate(downloadService, podcast.getDate(), false))
.setMediaId(PODCAST_PREFIX + podcast.getId())
.setExtras(podcastExtras)
.build();
mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_PLAYABLE));
+ i++;
+ if(i >= MAX_DOUBLE_LINE_ITEMS) {
+ break;
+ }
}
result.sendResult(mediaItems);
@@ -364,7 +370,7 @@ public class AutoMediaBrowserService extends MediaBrowserService {
.setExtras(shuffleExtras);
mediaItems.add(new MediaBrowser.MediaItem(shuffle.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE));
- /*Bundle playLastExtras = new Bundle();
+ Bundle playLastExtras = new Bundle();
playLastExtras.putString(idConstant, id);
playLastExtras.putBoolean(Constants.INTENT_EXTRA_PLAY_LAST, true);
@@ -372,7 +378,7 @@ public class AutoMediaBrowserService extends MediaBrowserService {
playLast.setTitle(downloadService.getString(R.string.menu_play_last))
.setMediaId("playLast-" + id)
.setExtras(playLastExtras);
- mediaItems.add(new MediaBrowser.MediaItem(playLast.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE));*/
+ mediaItems.add(new MediaBrowser.MediaItem(playLast.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE));
result.sendResult(mediaItems);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/service/CachedMusicService.java b/app/src/main/java/github/daneren2005/dsub/service/CachedMusicService.java
index 49cb217d..52268d82 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/CachedMusicService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/CachedMusicService.java
@@ -72,6 +72,7 @@ public class CachedMusicService implements MusicService {
private static final int TTL_MUSIC_DIR = 5 * 60; // Five minutes
public static final int CACHE_UPDATE_LIST = 1;
public static final int CACHE_UPDATE_METADATA = 2;
+ private static final int CACHED_LAST_FM = 24 * 60;
private final RESTMusicService musicService;
private final TimeLimitedCache<Boolean> cachedLicenseValid = new TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS);
@@ -667,6 +668,11 @@ public class CachedMusicService implements MusicService {
}
@Override
+ public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
+ return musicService.getSongList(type, size, offset, context, progressListener);
+ }
+
+ @Override
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
return musicService.getRandomSongs(size, artistId, context, progressListener);
}
@@ -1147,12 +1153,22 @@ public class CachedMusicService implements MusicService {
String cacheName = getCacheName(context, "artistInfo", id);
ArtistInfo info = null;
if(!refresh) {
- info = FileUtil.deserialize(context, cacheName, ArtistInfo.class);
+ info = FileUtil.deserialize(context, cacheName, ArtistInfo.class, CACHED_LAST_FM);
}
if(info == null && allowNetwork) {
- info = musicService.getArtistInfo(id, refresh, allowNetwork, context, progressListener);
- FileUtil.serialize(context, info, cacheName);
+ try {
+ info = musicService.getArtistInfo(id, refresh, allowNetwork, context, progressListener);
+ FileUtil.serialize(context, info, cacheName);
+ } catch(Exception e) {
+ Log.w(TAG, "Failed to refresh Artist Info");
+ info = FileUtil.deserialize(context, cacheName, ArtistInfo.class);
+
+ // Nothing ever cached, throw error further upstream
+ if(info == null) {
+ throw e;
+ }
+ }
}
return info;
diff --git a/app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java b/app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java
index 670ea7d2..bc54f486 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java
@@ -503,7 +503,7 @@ public class ChromeCastController extends RemoteController {
try {
Cast.CastApi.setMessageReceivedCallbacks(apiClient, mediaPlayer.getNamespace(), mediaPlayer);
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, "Exception while creating channel", e);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java
index ac8b44d6..7044410b 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java
@@ -379,7 +379,8 @@ public class DownloadFile implements BufferFile {
return "DownloadFile (" + song + ")";
}
- @Override
+ // Don't do this. Causes infinite loop if two instances of same song
+ /*@Override
public boolean equals(Object o) {
if (this == o) {
return true;
@@ -390,7 +391,7 @@ public class DownloadFile implements BufferFile {
DownloadFile downloadFile = (DownloadFile) o;
return Util.equals(this.getSong(), downloadFile.getSong());
- }
+ }*/
private class DownloadTask extends SilentBackgroundTask<Void> {
private MusicService musicService;
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 a4f88ee2..3e771d70 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
@@ -601,6 +601,9 @@ public class DownloadService extends Service {
}
editor.commit();
}
+ public boolean isArtistRadio() {
+ return artistRadio;
+ }
public synchronized void shuffle() {
Collections.shuffle(downloadList);
diff --git a/app/src/main/java/github/daneren2005/dsub/service/MusicService.java b/app/src/main/java/github/daneren2005/dsub/service/MusicService.java
index 2972bb7c..876b45fd 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/MusicService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/MusicService.java
@@ -94,6 +94,8 @@ public interface MusicService {
MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
+ MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
+
MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception;
MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception;
diff --git a/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java b/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java
index a1657f39..3048a0db 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/OfflineMusicService.java
@@ -588,6 +588,11 @@ public class OfflineMusicService implements MusicService {
}
@Override
+ public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
+ throw new OfflineException(ERRORMSG);
+ }
+
+ @Override
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
throw new OfflineException(ERRORMSG);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java b/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java
index 4a6e5108..a7a68205 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java
@@ -72,7 +72,8 @@ import android.util.Log;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.*;
-import github.daneren2005.dsub.service.parser.AlbumListParser;
+import github.daneren2005.dsub.fragments.MainFragment;
+import github.daneren2005.dsub.service.parser.EntryListParser;
import github.daneren2005.dsub.service.parser.ArtistInfoParser;
import github.daneren2005.dsub.service.parser.BookmarkParser;
import github.daneren2005.dsub.service.parser.ChatMessageParser;
@@ -571,7 +572,7 @@ public class RESTMusicService implements MusicService {
Reader reader = getReader(context, progressListener, method, null, names, values, true);
try {
- return new AlbumListParser(context, getInstance(context)).parse(reader, progressListener);
+ return new EntryListParser(context, getInstance(context)).parse(reader, progressListener);
} finally {
Util.close(reader);
}
@@ -637,13 +638,49 @@ public class RESTMusicService implements MusicService {
Reader reader = getReader(context, progressListener, method, null, names, values, true);
try {
- return new AlbumListParser(context, instance).parse(reader, progressListener);
+ return new EntryListParser(context, instance).parse(reader, progressListener);
} finally {
Util.close(reader);
}
}
- @Override
+ @Override
+ public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
+ List<String> names = new ArrayList<String>();
+ List<Object> values = new ArrayList<Object>();
+
+ names.add("size");
+ values.add(size);
+ names.add("offset");
+ values.add(offset);
+
+ String method;
+ switch(type) {
+ case MainFragment.SONGS_NEWEST:
+ method = "getNewaddedSongs";
+ break;
+ case MainFragment.SONGS_TOP_PLAYED:
+ method = "getTopplayedSongs";
+ break;
+ case MainFragment.SONGS_RECENT:
+ method = "getLastplayedSongs";
+ break;
+ case MainFragment.SONGS_FREQUENT:
+ method = "getMostplayedSongs";
+ break;
+ default:
+ method = "getNewaddedSongs";
+ }
+
+ Reader reader = getReader(context, progressListener, method, null, names, values, true);
+ try {
+ return new EntryListParser(context, getInstance(context)).parse(reader, progressListener);
+ } finally {
+ Util.close(reader);
+ }
+ }
+
+ @Override
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
checkServerVersion(context, "1.11", "Artist radio is not supported");
diff --git a/app/src/main/java/github/daneren2005/dsub/service/parser/AlbumListParser.java b/app/src/main/java/github/daneren2005/dsub/service/parser/EntryListParser.java
index 213cc6b3..f91aaae1 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/parser/AlbumListParser.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/parser/EntryListParser.java
@@ -29,9 +29,9 @@ import java.io.Reader;
/**
* @author Sindre Mehus
*/
-public class AlbumListParser extends MusicDirectoryEntryParser {
+public class EntryListParser extends MusicDirectoryEntryParser {
- public AlbumListParser(Context context, int instance) {
+ public EntryListParser(Context context, int instance) {
super(context, instance);
}
@@ -50,6 +50,9 @@ public class AlbumListParser extends MusicDirectoryEntryParser {
entry.setDirectory(true);
}
dir.addChild(entry);
+ } else if ("song".equals(name)) {
+ MusicDirectory.Entry entry = parseEntry("");
+ dir.addChild(entry);
} else if ("error".equals(name)) {
handleError();
}
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Constants.java b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
index bfb85492..00682947 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Constants.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
@@ -169,6 +169,7 @@ public final class Constants {
public static final String PREFERENCES_KEY_COLOR_ACTION_BAR = "colorActionBar";
public static final String PREFERENCES_KEY_SHUFFLE_BY_ALBUM = "shuffleByAlbum";
public static final String PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER = "neverResumePlayQueue";
+ public static final String PREFERENCES_KEY_BATCH_MODE = "batchMode";
public static final String OFFLINE_SCROBBLE_COUNT = "scrobbleCount";
public static final String OFFLINE_SCROBBLE_ID = "scrobbleID";
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java
index bf4af20d..98bbe1df 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Util.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java
@@ -107,6 +107,7 @@ public final class Util {
private static DecimalFormat BYTE_LOCALIZED_FORMAT = null;
private static SimpleDateFormat DATE_FORMAT_SHORT = new SimpleDateFormat("MMM d h:mm a");
private static SimpleDateFormat DATE_FORMAT_LONG = new SimpleDateFormat("MMM d, yyyy h:mm a");
+ private static SimpleDateFormat DATE_FORMAT_NO_TIME = new SimpleDateFormat("MMM d, yyyy");
private static int CURRENT_YEAR = new Date().getYear();
public static final String EVENT_META_CHANGED = "github.daneren2005.dsub.EVENT_META_CHANGED";
@@ -376,6 +377,12 @@ public final class Util {
int cacheSize = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_CACHE_SIZE, "-1"));
return cacheSize == -1 ? Integer.MAX_VALUE : cacheSize;
}
+ public static boolean isBatchMode(Context context) {
+ return Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false);
+ }
+ public static void setBatchMode(Context context, boolean batchMode) {
+ Util.getPreferences(context).edit().putBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, batchMode).commit();
+ }
public static String getRestUrl(Context context, String method) {
return getRestUrl(context, method, true);
@@ -901,26 +908,38 @@ public final class Util {
}
public static String formatDate(Context context, String dateString) {
+ return formatDate(context, dateString, true);
+ }
+ public static String formatDate(Context context, String dateString, boolean includeTime) {
try {
+ dateString = dateString.replace(' ', 'T');
boolean isDateNormalized = ServerInfo.checkServerVersion(context, "1.11");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
if (isDateNormalized) {
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
- return formatDate(dateFormat.parse(dateString));
+ return formatDate(dateFormat.parse(dateString), includeTime);
} catch(ParseException e) {
+ Log.e(TAG, "Failed to parse date string", e);
return dateString;
}
}
public static String formatDate(Date date) {
+ return formatDate(date, true);
+ }
+ public static String formatDate(Date date, boolean includeTime) {
if(date == null) {
return "Never";
} else {
- if(date.getYear() != CURRENT_YEAR) {
- return DATE_FORMAT_LONG.format(date);
+ if(includeTime) {
+ if (date.getYear() != CURRENT_YEAR) {
+ return DATE_FORMAT_LONG.format(date);
+ } else {
+ return DATE_FORMAT_SHORT.format(date);
+ }
} else {
- return DATE_FORMAT_SHORT.format(date);
+ return DATE_FORMAT_NO_TIME.format(date);
}
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
index bad9c0f6..47c77cac 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
@@ -415,7 +415,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
}
}
- downloadService.download(entries, false, true, false, shuffle, startIndex, startPosition);
+ downloadService.download(entries, false, !append, false, shuffle, startIndex, startPosition);
}
private void noResults() {
diff --git a/app/src/main/java/github/daneren2005/dsub/view/SongView.java b/app/src/main/java/github/daneren2005/dsub/view/SongView.java
index c7634b34..2c0580af 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/SongView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/SongView.java
@@ -106,8 +106,7 @@ public class SongView extends UpdateView2<MusicDirectory.Entry, Boolean> {
if(artist.length() != 0) {
artist.append(" - ");
}
- int index = date.indexOf(" ");
- artist.append(date.substring(0, index != -1 ? index : date.length()));
+ artist.append(Util.formatDate(context, date, false));
}
}
else if(song.getArtist() != null) {
diff --git a/app/src/main/res/menu/drawer_menu.xml b/app/src/main/res/menu/drawer_menu.xml
index b3e70cfa..21d324a9 100644
--- a/app/src/main/res/menu/drawer_menu.xml
+++ b/app/src/main/res/menu/drawer_menu.xml
@@ -3,7 +3,7 @@
xmlns:compat="http://schemas.android.com/apk/res-auto">
<item
- android:id="@+id/menu_search"
+ android:id="@+id/menu_global_search"
android:icon="?attr/search"
android:title="@string/menu.search"
compat:showAsAction="always|withText"/>
diff --git a/app/src/main/res/menu/multiselect_nowplaying.xml b/app/src/main/res/menu/multiselect_nowplaying.xml
new file mode 100644
index 00000000..9d361bf0
--- /dev/null
+++ b/app/src/main/res/menu/multiselect_nowplaying.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:compat="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menu_download"
+ android:title="@string/common.download"
+ android:icon="?attr/download"
+ compat:showAsAction="ifRoom|withText"/>
+
+ <item
+ android:id="@+id/menu_delete"
+ android:title="@string/menu.delete_cache"
+ android:icon="?attr/remove"
+ compat:showAsAction="ifRoom|withText"/>
+
+ <item
+ android:id="@+id/menu_cache"
+ android:title="@string/common.pin"/>
+
+ <item
+ android:id="@+id/menu_add_playlist"
+ android:title="@string/menu.add_playlist"/>
+
+ <item
+ android:id="@+id/menu_star"
+ android:title="@string/common.star"/>
+</menu>
diff --git a/app/src/main/res/menu/multiselect_nowplaying_offline.xml b/app/src/main/res/menu/multiselect_nowplaying_offline.xml
new file mode 100644
index 00000000..044836c6
--- /dev/null
+++ b/app/src/main/res/menu/multiselect_nowplaying_offline.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:compat="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menu_delete"
+ android:title="@string/menu.delete_cache"
+ android:icon="?attr/remove"
+ compat:showAsAction="ifRoom|withText"/>
+</menu>
diff --git a/app/src/main/res/menu/nowplaying.xml b/app/src/main/res/menu/nowplaying.xml
index 60255692..9c198e9a 100644
--- a/app/src/main/res/menu/nowplaying.xml
+++ b/app/src/main/res/menu/nowplaying.xml
@@ -33,6 +33,11 @@
android:title="@string/equalizer.label"
android:checkable="true"/>
+ <item
+ android:id="@+id/menu_batch_mode"
+ android:title="@string/download.batch_mode"
+ android:checkable="true"/>
+
<item
android:id="@+id/menu_screen_on_off"
android:title="@string/download.menu_screen_on"
diff --git a/app/src/main/res/menu/nowplaying_context.xml b/app/src/main/res/menu/nowplaying_context.xml
index 60d6288e..06f4afcb 100644
--- a/app/src/main/res/menu/nowplaying_context.xml
+++ b/app/src/main/res/menu/nowplaying_context.xml
@@ -26,7 +26,7 @@
<group android:id="@+id/hide_star">
<item
- android:id="@+id/menu_star"
+ android:id="@+id/song_menu_star"
android:title="@string/common.star"/>
</group>
@@ -44,7 +44,7 @@
<group android:id="@+id/server_1.8">
<item
- android:id="@+id/menu_add_playlist"
+ android:id="@+id/song_menu_add_playlist"
android:title="@string/menu.add_playlist"/>
</group>
</menu>
diff --git a/app/src/main/res/menu/nowplaying_context_offline.xml b/app/src/main/res/menu/nowplaying_context_offline.xml
index 5f8009ff..14c95ab6 100644
--- a/app/src/main/res/menu/nowplaying_context_offline.xml
+++ b/app/src/main/res/menu/nowplaying_context_offline.xml
@@ -22,7 +22,7 @@
<group android:id="@+id/hide_star">
<item
- android:id="@+id/menu_star"
+ android:id="@+id/song_menu_star"
android:title="@string/common.star"/>
</group>
</menu>
diff --git a/app/src/main/res/menu/nowplaying_offline.xml b/app/src/main/res/menu/nowplaying_offline.xml
index bba5ba00..d1f6f706 100644
--- a/app/src/main/res/menu/nowplaying_offline.xml
+++ b/app/src/main/res/menu/nowplaying_offline.xml
@@ -25,6 +25,11 @@
android:id="@+id/menu_equalizer"
android:title="@string/equalizer.label"
android:checkable="true"/>
+
+ <item
+ android:id="@+id/menu_batch_mode"
+ android:title="@string/download.batch_mode"
+ android:checkable="true"/>
<item
android:id="@+id/menu_screen_on_off"
diff --git a/app/src/main/res/menu/similar_artists.xml b/app/src/main/res/menu/similar_artists.xml
index f6c30fb2..2557381e 100644
--- a/app/src/main/res/menu/similar_artists.xml
+++ b/app/src/main/res/menu/similar_artists.xml
@@ -13,8 +13,4 @@
android:icon="?attr/shuffle"
android:title="@string/menu.shuffle"
compat:showAsAction="ifRoom|withText"/>
-
- <item
- android:id="@+id/menu_show_missing"
- android:title="@string/menu.show_missing"/>
</menu> \ No newline at end of file
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 13453ae6..3ab30895 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -106,7 +106,6 @@
<string name="menu.rate">Setze Bewertung</string>
<string name="menu.top_tracks">Last.FM Top Medien</string>
<string name="menu.similar_artists">Ähnliche Künstler</string>
- <string name="menu.show_missing">Zeige fehlende</string>
<string name="menu.start_radio">Starte Radio</string>
<string name="menu.first_level_artist">Erste Ebene sind Künstler</string>
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index f56e939e..47f7ce7f 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -96,7 +96,6 @@
<string name="menu.rate">Establecer valoración</string>
<string name="menu.top_tracks">Tp Tracks de Last.FM</string>
<string name="menu.similar_artists">Artistas similares</string>
- <string name="menu.show_missing">Mostrar los que faltan</string>
<string name="menu.start_radio">Iniciar radio</string>
<string name="playlist.label">Listas de reproducción</string>
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index ea8d3eeb..11302cd3 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -111,7 +111,6 @@
<string name="menu.rate">Értékelés</string>
<string name="menu.top_tracks">Last.fm legjobb dalok</string>
<string name="menu.similar_artists">Hasonló előadók</string>
- <string name="menu.show_missing">Hiányzó megjelenítése</string>
<string name="menu.start_radio">Rádió indítása</string>
<string name="menu.first_level_artist">Részletes megjelenítés</string>
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 4bf21c67..545e9505 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -109,7 +109,6 @@
<string name="menu.rate">Bepaal rating</string>
<string name="menu.top_tracks">Laatste .FM Top Nummers</string>
<string name="menu.similar_artists">Gelijke artiesten</string>
- <string name="menu.show_missing">Toon missende</string>
<string name="menu.start_radio">Start radio</string>
<string name="menu.first_level_artist">Eerste niveau artiesten</string>
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index 03b65571..75042859 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -110,7 +110,6 @@
<string name="menu.rate">Classificar</string>
<string name="menu.top_tracks">Top faixas do Last.FM</string>
<string name="menu.similar_artists">Artistas semelhantes</string>
- <string name="menu.show_missing">Mostrar os que faltam</string>
<string name="menu.start_radio">Iniciar rádio</string>
<string name="menu.first_level_artist">Artistas no primeiro nível</string>
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index 38add733..8288d155 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -111,7 +111,6 @@
<string name="menu.rate">Sätt betyg </string>
<string name="menu.top_tracks">Last.FM topp spår</string>
<string name="menu.similar_artists">Liknande artister</string>
- <string name="menu.show_missing">Visa saknade</string>
<string name="menu.start_radio">Starta radio</string>
<string name="menu.first_level_artist">Första steget artister</string>
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index d97a3b21..c8553dc0 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -37,6 +37,7 @@
<attr name="rating_good" format="reference"/>
<attr name="radio" format="reference"/>
<attr name="star_outline" format="reference"/>
+ <attr name="download" format="reference"/>
<attr name="drawerItemsIcons" format="reference"/>
<attr name="drawerHome" format="reference"/>
<attr name="drawerLibrary" format="reference"/>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5d0aacd7..b7efff1a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -76,6 +76,10 @@
<string name="main.albums_alphabetical">Alphabetically</string>
<string name="main.videos">Videos</string>
<string name="main.songs_genres">@string/main.albums_genres</string>
+ <string name="main.songs_newest">@string/main.albums_newest</string>
+ <string name="main.songs_top_played">Top Played</string>
+ <string name="main.songs_recent">@string/main.albums_recent</string>
+ <string name="main.songs_frequent">@string/main.albums_frequent</string>
<string name="main.back_confirm">Press back again to exit</string>
<string name="main.scan_complete">Completed scan of Server</string>
<string name="main.artist">Artist</string>
@@ -111,7 +115,7 @@
<string name="menu.rate">Set Rating</string>
<string name="menu.top_tracks">Last.FM Top Tracks</string>
<string name="menu.similar_artists">Similar Artists</string>
- <string name="menu.show_missing">Show missing</string>
+ <string name="menu.similar_artists.missing">Missing Artists</string>
<string name="menu.start_radio">Start Radio</string>
<string name="menu.first_level_artist">First level artists</string>
@@ -186,7 +190,8 @@
<string name="download.playerstate_downloading">Downloading - %s</string>
<string name="download.playerstate_mobile_disabled">Waiting for WiFi network to download</string>
<string name="download.playerstate_buffering">Buffering</string>
- <string name="download.playerstate_playing_shuffle">Playing shuffle</string>
+ <string name="download.playerstate_playing_shuffle">Shuffle mode</string>
+ <string name="download.playerstate_playing_artist_radio">Artist radio</string>
<string name="download.menu_show_album">Show Album</string>
<string name="download.menu_lyrics">Lyrics</string>
<string name="download.menu_remove_all">Remove all</string>
@@ -227,6 +232,7 @@
<string name="download.restore_play_queue">continue from where you left off on another device at</string>
<string name="download.thumbs_up">Thumbs Up</string>
<string name="download.thumbs_down">Thumbs Down</string>
+ <string name="download.batch_mode">Batch Mode</string>
<string name="sync.new_podcasts">New podcasts available</string>
<string name="sync.new_playlists">New songs in playlists</string>
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 790d91de..4915c012 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -38,6 +38,7 @@
<item name="rating_good">@drawable/ic_action_rating_good_light</item>
<item name="radio">@drawable/ic_menu_radio_dark</item>
<item name="star_outline">@drawable/ic_toggle_star_outline_light</item>
+ <item name="download">@drawable/ic_menu_download_dark</item>
<item name="drawerHome">@drawable/main_offline_light</item>
<item name="drawerLibrary">@drawable/ic_menu_library_light</item>
<item name="drawerPlaylists">@drawable/ic_menu_playlist_light</item>
@@ -103,6 +104,7 @@
<item name="rating_good">@drawable/ic_action_rating_good_dark</item>
<item name="radio">@drawable/ic_menu_radio_dark</item>
<item name="star_outline">@drawable/ic_toggle_star_outline_dark</item>
+ <item name="download">@drawable/ic_menu_download_dark</item>
<item name="drawerHome">@drawable/main_offline_dark</item>
<item name="drawerLibrary">@drawable/ic_menu_library_dark</item>
<item name="drawerPlaylists">@drawable/ic_menu_playlist_dark</item>
@@ -190,6 +192,7 @@
<item name="add_person">@drawable/ic_menu_add_person_light</item>
<item name="password">@drawable/ic_menu_password_light</item>
<item name="radio">@drawable/ic_menu_radio_light</item>
+ <item name="download">@drawable/ic_menu_download_light</item>
<item name="actionModeBackground">@color/background_material_light</item>
<item name="actionModeStyle">@style/LightActionMode</item>
<item name="actionModeCloseButtonStyle">@style/DarkCloseButton</item>