load global playlists on main activity

This commit is contained in:
dkanada 2020-04-29 15:49:59 +09:00
commit 5fcd9e979a
11 changed files with 76 additions and 157 deletions

View file

@ -65,7 +65,7 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
@Override
public long getItemId(int position) {
return dataSet.get(position).id;
return dataSet.get(position).id.hashCode();
}
@Override
@ -151,11 +151,7 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
}
break;
case R.id.action_save_playlist:
if (selection.size() == 1) {
PlaylistMenuHelper.handleMenuClick(activity, selection.get(0), menuItem);
} else {
new SavePlaylistsAsyncTask(activity).execute(selection);
}
// TODO remove
break;
default:
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.getItemId());
@ -163,42 +159,6 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
}
}
private static class SavePlaylistsAsyncTask extends WeakContextAsyncTask<List<Playlist>, String, String> {
public SavePlaylistsAsyncTask(Context context) {
super(context);
}
@Override
protected String doInBackground(List<Playlist>... params) {
int successes = 0;
int failures = 0;
String dir = "";
for (Playlist playlist : params[0]) {
try {
dir = PlaylistsUtil.savePlaylist(App.getInstance().getApplicationContext(), playlist).getParent();
successes++;
} catch (IOException e) {
failures++;
e.printStackTrace();
}
}
return failures == 0
? String.format(App.getInstance().getApplicationContext().getString(R.string.saved_x_playlists_to_x), successes, dir)
: String.format(App.getInstance().getApplicationContext().getString(R.string.saved_x_playlists_to_x_failed_to_save_x), successes, dir, failures);
}
@Override
protected void onPostExecute(String string) {
super.onPostExecute(string);
Context context = getContext();
if (context != null) {
Toast.makeText(context, string, Toast.LENGTH_LONG).show();
}
}
}
@NonNull
private List<Song> getSongList(@NonNull List<Playlist> playlists) {
final List<Song> songs = new ArrayList<>();
@ -206,7 +166,7 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
if (playlist instanceof AbsSmartPlaylist) {
songs.addAll(((AbsSmartPlaylist) playlist).getSongs(activity));
} else {
songs.addAll(PlaylistSongLoader.getPlaylistSongList(activity, playlist.id));
songs.addAll(PlaylistSongLoader.getPlaylistSongList(activity, playlist.id.hashCode()));
}
}

View file

@ -58,7 +58,7 @@ public class CreatePlaylistDialog extends DialogFragment {
final String name = charSequence.toString().trim();
if (!name.isEmpty()) {
if (!PlaylistsUtil.doesPlaylistExist(getActivity(), name)) {
final int playlistId = PlaylistsUtil.createPlaylist(getActivity(), name);
final String playlistId = PlaylistsUtil.createPlaylist(getActivity(), name);
if (getActivity() != null) {
// noinspection unchecked
List<Song> songs = getArguments().getParcelableArrayList(SONGS);

View file

@ -54,7 +54,7 @@ public class DeletePlaylistDialog extends DialogFragment {
.negativeText(android.R.string.cancel)
.onPositive((dialog, which) -> {
if (getActivity() == null) return;
PlaylistsUtil.deletePlaylists(getActivity(), playlists);
PlaylistsUtil.deletePlaylist(getActivity(), playlists);
})
.build();
}

View file

@ -24,7 +24,7 @@ public class M3UWriter implements M3UConstants {
if (playlist instanceof AbsSmartPlaylist) {
songs = ((AbsSmartPlaylist) playlist).getSongs(context);
} else {
songs = PlaylistSongLoader.getPlaylistSongList(context, playlist.id);
songs = PlaylistSongLoader.getPlaylistSongList(context, playlist.id.hashCode());
}
if (songs.size() > 0) {

View file

@ -40,13 +40,13 @@ public class PlaylistMenuHelper {
AddToPlaylistDialog.create(new ArrayList<>(getPlaylistSongs(activity, playlist))).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
return true;
case R.id.action_rename_playlist:
RenamePlaylistDialog.create(playlist.id).show(activity.getSupportFragmentManager(), "RENAME_PLAYLIST");
RenamePlaylistDialog.create(playlist.id.hashCode()).show(activity.getSupportFragmentManager(), "RENAME_PLAYLIST");
return true;
case R.id.action_delete_playlist:
DeletePlaylistDialog.create(playlist).show(activity.getSupportFragmentManager(), "DELETE_PLAYLIST");
return true;
case R.id.action_save_playlist:
new SavePlaylistAsyncTask(activity).execute(playlist);
// TODO remove
return true;
}
return false;
@ -56,32 +56,6 @@ public class PlaylistMenuHelper {
private static List<? extends Song> getPlaylistSongs(@NonNull Activity activity, Playlist playlist) {
return playlist instanceof AbsSmartPlaylist ?
((AbsSmartPlaylist) playlist).getSongs(activity) :
PlaylistSongLoader.getPlaylistSongList(activity, playlist.id);
}
private static class SavePlaylistAsyncTask extends WeakContextAsyncTask<Playlist, String, String> {
public SavePlaylistAsyncTask(Context context) {
super(context);
}
@Override
protected String doInBackground(Playlist... params) {
try {
return String.format(App.getInstance().getApplicationContext().getString(R.string.saved_playlist_to), PlaylistsUtil.savePlaylist(App.getInstance().getApplicationContext(), params[0]));
} catch (IOException e) {
e.printStackTrace();
return String.format(App.getInstance().getApplicationContext().getString(R.string.failed_to_save_playlist), e);
}
}
@Override
protected void onPostExecute(String string) {
super.onPostExecute(string);
Context context = getContext();
if (context != null) {
Toast.makeText(context, string, Toast.LENGTH_LONG).show();
}
}
PlaylistSongLoader.getPlaylistSongList(activity, playlist.id.hashCode());
}
}

View file

@ -2,19 +2,25 @@ package com.kabouzeid.gramophone.model;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import org.jellyfin.apiclient.model.dto.BaseItemDto;
public class Playlist implements Parcelable {
public final int id;
public final String id;
public final String name;
public Playlist(BaseItemDto itemDto) {
this.id = itemDto.getId();
this.name = itemDto.getName();
}
public Playlist(final int id, final String name) {
this.id = id;
this.id = Integer.toString(id);
this.name = name;
}
public Playlist() {
this.id = -1;
this.id = "";
this.name = "";
}
@ -24,21 +30,17 @@ public class Playlist implements Parcelable {
if (o == null || getClass() != o.getClass()) return false;
Playlist playlist = (Playlist) o;
if (id != playlist.id) return false;
return name != null ? name.equals(playlist.name) : playlist.name == null;
return id.equals(playlist.id);
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
return id.hashCode();
}
@Override
public String toString() {
return "Playlist{" + "id=" + id + ", name='" + name + '\'' + '}';
return id;
}
@Override
@ -48,12 +50,12 @@ public class Playlist implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.id);
dest.writeString(this.name);
}
protected Playlist(Parcel in) {
this.id = in.readInt();
this.id = in.readString();
this.name = in.readString();
}

View file

@ -302,7 +302,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
playlistSongs = ((AbsSmartPlaylist) playlist).getSongs(getApplicationContext());
} else {
//noinspection unchecked
playlistSongs = (List) PlaylistSongLoader.getPlaylistSongList(getApplicationContext(), playlist.id);
playlistSongs = (List) PlaylistSongLoader.getPlaylistSongList(getApplicationContext(), playlist.id.hashCode());
}
if (!playlistSongs.isEmpty()) {
if (shuffleMode == SHUFFLE_MODE_SHUFFLE) {

View file

@ -191,7 +191,7 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
}
// Playlist renamed
final String playlistName = PlaylistsUtil.getNameForPlaylist(this, playlist.id);
final String playlistName = PlaylistsUtil.getNameForPlaylist(this, playlist.id.hashCode());
if (!playlistName.equals(playlist.name)) {
playlist = PlaylistLoader.getPlaylist(this, playlist.id);
setToolbarTitle(playlist.name);
@ -268,7 +268,7 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
return ((AbsSmartPlaylist) playlist).getSongs(getContext());
} else {
//noinspection unchecked
return (List) PlaylistSongLoader.getPlaylistSongList(getContext(), playlist.id);
return (List) PlaylistSongLoader.getPlaylistSongList(getContext(), playlist.id.hashCode());
}
}
}

View file

@ -4,16 +4,16 @@ import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.PlaylistAdapter;
import com.kabouzeid.gramophone.interfaces.LoaderIds;
import com.kabouzeid.gramophone.loader.PlaylistLoader;
import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader;
import com.kabouzeid.gramophone.interfaces.MediaCallback;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.util.QueryUtil;
import org.jellyfin.apiclient.model.querying.ItemQuery;
import java.util.ArrayList;
import java.util.List;
@ -21,14 +21,10 @@ import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlaylistsFragment extends AbsLibraryPagerRecyclerViewFragment<PlaylistAdapter, LinearLayoutManager> implements LoaderManager.LoaderCallbacks<List<Playlist>> {
private static final int LOADER_ID = LoaderIds.PLAYLISTS_FRAGMENT;
public class PlaylistsFragment extends AbsLibraryPagerRecyclerViewFragment<PlaylistAdapter, LinearLayoutManager> {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(LOADER_ID, null, this);
}
@NonNull
@ -41,7 +37,17 @@ public class PlaylistsFragment extends AbsLibraryPagerRecyclerViewFragment<Playl
@Override
protected PlaylistAdapter createAdapter() {
List<Playlist> dataSet = getAdapter() == null ? new ArrayList<>() : getAdapter().getDataSet();
return new PlaylistAdapter(getLibraryFragment().getMainActivity(), dataSet, R.layout.item_list_single_row, getLibraryFragment());
PlaylistAdapter adapter = new PlaylistAdapter(getLibraryFragment().getMainActivity(), dataSet, R.layout.item_list_single_row, getLibraryFragment());
QueryUtil.getPlaylists(new MediaCallback() {
@Override
public void onLoadMedia(List<?> media) {
dataSet.addAll((List<Playlist>) media);
adapter.notifyDataSetChanged();
}
});
return adapter;
}
@Override
@ -51,39 +57,5 @@ public class PlaylistsFragment extends AbsLibraryPagerRecyclerViewFragment<Playl
@Override
public void onMediaStoreChanged() {
getLoaderManager().restartLoader(LOADER_ID, null, this);
}
@Override
public Loader<List<Playlist>> onCreateLoader(int id, Bundle args) {
return new AsyncPlaylistLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<List<Playlist>> loader, List<Playlist> data) {
getAdapter().swapDataSet(data);
}
@Override
public void onLoaderReset(Loader<List<Playlist>> loader) {
getAdapter().swapDataSet(new ArrayList<>());
}
private static class AsyncPlaylistLoader extends WrappedAsyncTaskLoader<List<Playlist>> {
public AsyncPlaylistLoader(Context context) {
super(context);
}
private static List<Playlist> getAllPlaylists(Context context) {
List<Playlist> playlists = new ArrayList<>();
playlists.addAll(PlaylistLoader.getAllPlaylists(context));
return playlists;
}
@Override
public List<Playlist> loadInBackground() {
return getAllPlaylists(getContext());
}
}
}

View file

@ -1,30 +1,15 @@
package com.kabouzeid.gramophone.util;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.widget.Toast;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.M3UWriter;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static android.provider.MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@ -33,26 +18,26 @@ public class PlaylistsUtil {
return false;
}
public static int createPlaylist(@NonNull final Context context, @Nullable final String name) {
return -1;
public static String createPlaylist(@NonNull final Context context, @Nullable final String name) {
return "";
}
public static void deletePlaylists(@NonNull final Context context, @NonNull final List<Playlist> playlists) {
public static void deletePlaylist(@NonNull final Context context, @NonNull final List<Playlist> playlists) {
}
public static void addToPlaylist(@NonNull final Context context, final Song song, final int playlistId, final boolean showToastOnFinish) {
public static void addToPlaylist(@NonNull final Context context, final Song song, final String playlistId, final boolean showToastOnFinish) {
}
public static void addToPlaylist(@NonNull final Context context, @NonNull final List<Song> songs, final int playlistId, final boolean showToastOnFinish) {
public static void addToPlaylist(@NonNull final Context context, @NonNull final List<Song> songs, final String playlistId, final boolean showToastOnFinish) {
}
public static void removeFromPlaylist(@NonNull final Context context, @NonNull final Song song, int playlistId) {
public static void removeFromPlaylist(@NonNull final Context context, @NonNull final Song song, String playlistId) {
}
public static void removeFromPlaylist(@NonNull final Context context, @NonNull final List<PlaylistSong> songs) {
}
public static boolean moveItem(@NonNull final Context context, int playlistId, int from, int to) {
public static boolean moveItem(@NonNull final Context context, String playlistId, int from, int to) {
return true;
}

View file

@ -5,6 +5,7 @@ import com.kabouzeid.gramophone.interfaces.MediaCallback;
import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.model.Artist;
import com.kabouzeid.gramophone.model.Genre;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.Song;
import org.jellyfin.apiclient.interaction.Response;
@ -39,6 +40,31 @@ public class QueryUtil {
});
}
public static void getPlaylists(MediaCallback callback) {
ItemQuery query = new ItemQuery();
query.setIncludeItemTypes(new String[]{"Playlist"});
query.setUserId(App.getApiClient().getCurrentUserId());
query.setLimit(100);
query.setRecursive(true);
if (currentLibrary != null && query.getParentId() == null) query.setParentId(currentLibrary.getId());
App.getApiClient().GetItemsAsync(query, new Response<ItemsResult>() {
@Override
public void onResponse(ItemsResult result) {
List<Playlist> playlists = new ArrayList<>();
for (BaseItemDto itemDto : result.getItems()) {
playlists.add(new Playlist(itemDto));
}
callback.onLoadMedia(playlists);
}
@Override
public void onError(Exception exception) {
exception.printStackTrace();
}
});
}
public static void getGenres(MediaCallback callback) {
ItemsByNameQuery query = new ItemsByNameQuery();
query.setUserId(App.getApiClient().getCurrentUserId());