work on item deletion from playlists

This commit is contained in:
dkanada 2020-04-30 23:13:53 +09:00
commit 930f7e8aa3
8 changed files with 131 additions and 22 deletions

View file

@ -19,13 +19,12 @@ import com.kabouzeid.gramophone.util.ViewUtil;
import java.util.List; import java.util.List;
@SuppressWarnings("unchecked")
public class OrderablePlaylistSongAdapter extends PlaylistSongAdapter implements DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> { public class OrderablePlaylistSongAdapter extends PlaylistSongAdapter implements DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
private OnMoveItemListener onMoveItemListener; private OnMoveItemListener onMoveItemListener;
public OrderablePlaylistSongAdapter(@NonNull AppCompatActivity activity, @NonNull List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, @Nullable OnMoveItemListener onMoveItemListener) { public OrderablePlaylistSongAdapter(@NonNull AppCompatActivity activity, @NonNull List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, @Nullable OnMoveItemListener onMoveItemListener) {
super(activity, (List<Song>) dataSet, itemLayoutRes, usePalette, cabHolder); super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
setMultiSelectMenuRes(R.menu.menu_playlists_songs_selection); setMultiSelectMenuRes(R.menu.menu_playlists_songs_selection);
this.onMoveItemListener = onMoveItemListener; this.onMoveItemListener = onMoveItemListener;
} }
@ -47,7 +46,7 @@ public class OrderablePlaylistSongAdapter extends PlaylistSongAdapter implements
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Song> selection) { protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Song> selection) {
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case R.id.action_remove_from_playlist: case R.id.action_remove_from_playlist:
RemoveFromPlaylistDialog.create((List<Song>) (List) selection).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST"); RemoveFromPlaylistDialog.create(selection).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
return; return;
} }

View file

@ -7,9 +7,11 @@ import androidx.fragment.app.DialogFragment;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.interfaces.MediaCallback;
import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.PlaylistUtil; import com.kabouzeid.gramophone.util.PlaylistUtil;
import com.kabouzeid.gramophone.util.QueryUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,8 +28,10 @@ public class AddToPlaylistDialog extends DialogFragment {
@NonNull @NonNull
public static AddToPlaylistDialog create(List<Song> songs) { public static AddToPlaylistDialog create(List<Song> songs) {
AddToPlaylistDialog dialog = new AddToPlaylistDialog(); AddToPlaylistDialog dialog = new AddToPlaylistDialog();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelableArrayList("songs", new ArrayList<>(songs)); args.putParcelableArrayList("songs", new ArrayList<>(songs));
dialog.setArguments(args); dialog.setArguments(args);
return dialog; return dialog;
} }
@ -35,19 +39,11 @@ public class AddToPlaylistDialog extends DialogFragment {
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
final List<Playlist> playlists = new ArrayList<>(); List<Playlist> playlists = new ArrayList<>();
MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
CharSequence[] playlistNames = new CharSequence[playlists.size() + 1];
playlistNames[0] = getActivity().getResources().getString(R.string.action_new_playlist);
for (int i = 1; i < playlistNames.length; i++) {
playlistNames[i] = playlists.get(i - 1).name;
}
return new MaterialDialog.Builder(getActivity())
.title(R.string.action_add_to_playlist) .title(R.string.action_add_to_playlist)
.items(playlistNames) .items(getActivity().getResources().getString(R.string.action_new_playlist))
.itemsCallback((materialDialog, view, i, charSequence) -> { .itemsCallback((materialDialog, view, i, charSequence) -> {
// noinspection unchecked
final List<Song> songs = getArguments().getParcelableArrayList("songs"); final List<Song> songs = getArguments().getParcelableArrayList("songs");
if (songs == null) return; if (songs == null) return;
@ -60,5 +56,22 @@ public class AddToPlaylistDialog extends DialogFragment {
} }
}) })
.build(); .build();
QueryUtil.getPlaylists(new MediaCallback() {
@Override
public void onLoadMedia(List<?> media) {
playlists.addAll((List<Playlist>) media);
CharSequence[] names = new CharSequence[playlists.size() + 1];
names[0] = getActivity().getResources().getString(R.string.action_new_playlist);
for (int i = 0; i < playlists.size(); i++) {
names[i + 1] = playlists.get(i).name;
}
dialog.setItems(names);
}
});
return dialog;
} }
} }

View file

@ -27,8 +27,7 @@ public class CreatePlaylistDialog extends DialogFragment {
@NonNull @NonNull
public static CreatePlaylistDialog create(@Nullable Song song) { public static CreatePlaylistDialog create(@Nullable Song song) {
List<Song> list = new ArrayList<>(); List<Song> list = new ArrayList<>();
if (song != null) if (song != null) list.add(song);
list.add(song);
return create(list); return create(list);
} }
@ -53,7 +52,7 @@ public class CreatePlaylistDialog extends DialogFragment {
final String name = charSequence.toString().trim(); final String name = charSequence.toString().trim();
if (getActivity() == null || getArguments() == null || name.isEmpty()) return; if (getActivity() == null || getArguments() == null || name.isEmpty()) return;
List<Song> songs = getArguments().getParcelableArrayList(SONGS); List<Song> songs = getArguments().getParcelableArrayList(SONGS);
if (songs != null && !songs.isEmpty()) { if (songs != null) {
PlaylistUtil.createPlaylist(name, songs); PlaylistUtil.createPlaylist(name, songs);
} }
}) })

View file

@ -8,6 +8,8 @@ import android.text.Html;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.PlaylistUtil; import com.kabouzeid.gramophone.util.PlaylistUtil;
@ -26,8 +28,10 @@ public class RemoveFromPlaylistDialog extends DialogFragment {
@NonNull @NonNull
public static RemoveFromPlaylistDialog create(List<Song> songs) { public static RemoveFromPlaylistDialog create(List<Song> songs) {
RemoveFromPlaylistDialog dialog = new RemoveFromPlaylistDialog(); RemoveFromPlaylistDialog dialog = new RemoveFromPlaylistDialog();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelableArrayList("songs", new ArrayList<>(songs)); args.putParcelableArrayList("songs", new ArrayList<>(songs));
dialog.setArguments(args); dialog.setArguments(args);
return dialog; return dialog;
} }
@ -36,6 +40,7 @@ public class RemoveFromPlaylistDialog extends DialogFragment {
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
final List<Song> songs = getArguments().getParcelableArrayList("songs"); final List<Song> songs = getArguments().getParcelableArrayList("songs");
int title; int title;
CharSequence content; CharSequence content;
if (songs.size() > 1) { if (songs.size() > 1) {
@ -53,7 +58,9 @@ public class RemoveFromPlaylistDialog extends DialogFragment {
.negativeText(android.R.string.cancel) .negativeText(android.R.string.cancel)
.onPositive((dialog, which) -> { .onPositive((dialog, which) -> {
if (getActivity() == null) return; if (getActivity() == null) return;
PlaylistUtil.deleteItems(songs, songs.get(0).id);
PlaylistSong song = (PlaylistSong) songs.get(0);
PlaylistUtil.deleteItems(songs, song.playlistId);
}) })
.build(); .build();
} }

View file

@ -0,0 +1,42 @@
package com.kabouzeid.gramophone.model;
import android.os.Parcel;
import org.jellyfin.apiclient.model.dto.BaseItemDto;
public class PlaylistSong extends Song {
public final String playlistId;
public PlaylistSong(BaseItemDto itemDto, String playlistId) {
super(itemDto);
this.playlistId = playlistId;
}
public PlaylistSong(String id, String title, int trackNumber, int year, long duration, String albumId, String albumName, String artistId, String artistName, final String playlistId) {
super("", title, trackNumber, year, duration, "", albumName, "", artistName);
this.playlistId = playlistId;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(this.playlistId);
}
protected PlaylistSong(Parcel in) {
super(in);
this.playlistId = in.readString();
}
public static final Creator<PlaylistSong> CREATOR = new Creator<PlaylistSong>() {
public PlaylistSong createFromParcel(Parcel source) {
return new PlaylistSong(source);
}
public PlaylistSong[] newArray(int size) {
return new PlaylistSong[size];
}
};
}

View file

@ -26,10 +26,10 @@ import com.kabouzeid.gramophone.helper.menu.PlaylistMenuHelper;
import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.interfaces.MediaCallback; import com.kabouzeid.gramophone.interfaces.MediaCallback;
import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.model.playlist.AbsSmartPlaylist; import com.kabouzeid.gramophone.model.playlist.AbsSmartPlaylist;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity; import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
import com.kabouzeid.gramophone.util.QueryUtil;
import com.kabouzeid.gramophone.util.ThemeUtil; import com.kabouzeid.gramophone.util.ThemeUtil;
import com.kabouzeid.gramophone.util.PlaylistUtil; import com.kabouzeid.gramophone.util.PlaylistUtil;
import com.kabouzeid.gramophone.util.ViewUtil; import com.kabouzeid.gramophone.util.ViewUtil;
@ -80,10 +80,10 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
ItemQuery query = new ItemQuery(); ItemQuery query = new ItemQuery();
query.setParentId(playlist.id); query.setParentId(playlist.id);
QueryUtil.getSongs(query, new MediaCallback() { PlaylistUtil.getPlaylist(query, new MediaCallback() {
@Override @Override
public void onLoadMedia(List<?> media) { public void onLoadMedia(List<?> media) {
adapter.getDataSet().addAll((List<Song>) media); adapter.getDataSet().addAll((List<PlaylistSong>) media);
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} }
}); });

View file

@ -1,17 +1,46 @@
package com.kabouzeid.gramophone.util; package com.kabouzeid.gramophone.util;
import com.kabouzeid.gramophone.App; import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.interfaces.MediaCallback;
import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import org.jellyfin.apiclient.interaction.EmptyResponse; import org.jellyfin.apiclient.interaction.EmptyResponse;
import org.jellyfin.apiclient.interaction.Response; import org.jellyfin.apiclient.interaction.Response;
import org.jellyfin.apiclient.model.dto.BaseItemDto;
import org.jellyfin.apiclient.model.playlists.PlaylistCreationRequest; import org.jellyfin.apiclient.model.playlists.PlaylistCreationRequest;
import org.jellyfin.apiclient.model.querying.ItemQuery;
import org.jellyfin.apiclient.model.querying.ItemsResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class PlaylistUtil { public class PlaylistUtil {
public static void getPlaylist(ItemQuery query, MediaCallback callback) {
query.setIncludeItemTypes(new String[]{"Audio"});
query.setUserId(App.getApiClient().getCurrentUserId());
query.setLimit(100);
query.setRecursive(true);
if (QueryUtil.currentLibrary != null && query.getParentId() == null) query.setParentId(QueryUtil.currentLibrary.getId());
App.getApiClient().GetItemsAsync(query, new Response<ItemsResult>() {
@Override
public void onResponse(ItemsResult result) {
List<PlaylistSong> songs = new ArrayList<>();
for (BaseItemDto itemDto : result.getItems()) {
songs.add(new PlaylistSong(itemDto, query.getParentId()));
}
callback.onLoadMedia(songs);
}
@Override
public void onError(Exception exception) {
exception.printStackTrace();
}
});
}
public static void createPlaylist(final String name, final List<Song> songs) { public static void createPlaylist(final String name, final List<Song> songs) {
ArrayList<String> ids = new ArrayList<>(); ArrayList<String> ids = new ArrayList<>();
for (Song song : songs) { for (Song song : songs) {
@ -21,7 +50,7 @@ public class PlaylistUtil {
PlaylistCreationRequest request = new PlaylistCreationRequest(); PlaylistCreationRequest request = new PlaylistCreationRequest();
request.setUserId(App.getApiClient().getCurrentUserId()); request.setUserId(App.getApiClient().getCurrentUserId());
request.setName(name); request.setName(name);
request.setItemIdList(ids); if (ids.size() != 0) request.setItemIdList(ids);
App.getApiClient().CreatePlaylist(request, new Response<>()); App.getApiClient().CreatePlaylist(request, new Response<>());
} }
@ -54,5 +83,23 @@ public class PlaylistUtil {
} }
public static void renamePlaylist(final String playlist, final String name) { public static void renamePlaylist(final String playlist, final String name) {
String user = App.getApiClient().getCurrentUserId();
App.getApiClient().GetItemAsync(playlist, user, new Response<BaseItemDto>() {
@Override
public void onResponse(BaseItemDto itemDto) {
itemDto.setName(name);
renamePlaylistInner(itemDto);
}
@Override
public void onError(Exception exception) {
exception.printStackTrace();
}
});
}
public static void renamePlaylistInner(final BaseItemDto itemDto) {
// TODO find a method to upload metadata changes
// at some point this could become metadata utilities
} }
} }

View file

@ -23,6 +23,8 @@ import java.util.List;
public class QueryUtil { public class QueryUtil {
public static BaseItemDto currentLibrary; public static BaseItemDto currentLibrary;
// TODO return BaseItemDto everywhere
// will simplify the code for the getPlaylists method
public static void getLibraries(MediaCallback callback) { public static void getLibraries(MediaCallback callback) {
String id = App.getApiClient().getCurrentUserId(); String id = App.getApiClient().getCurrentUserId();
App.getApiClient().GetUserViews(id, new Response<ItemsResult>() { App.getApiClient().GetUserViews(id, new Response<ItemsResult>() {