From f0be828bbfca870f69e71e17d9b6173288904aa7 Mon Sep 17 00:00:00 2001 From: James Wells Date: Thu, 18 Mar 2021 23:23:00 -0400 Subject: [PATCH] Convert SelectAlbumFragment to kotlin Signed-off-by: James Wells --- .../fragment/SelectAlbumFragment.java | 1271 ----------------- .../fragment/SelectAlbumFragment.kt | 1145 +++++++++++++++ 2 files changed, 1145 insertions(+), 1271 deletions(-) delete mode 100644 ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SelectAlbumFragment.java create mode 100644 ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SelectAlbumFragment.kt diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SelectAlbumFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SelectAlbumFragment.java deleted file mode 100644 index d66eb87d..00000000 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SelectAlbumFragment.java +++ /dev/null @@ -1,1271 +0,0 @@ -package org.moire.ultrasonic.fragment; - -import android.os.Bundle; -import android.view.ContextMenu; -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.ImageView; -import android.widget.ListView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.navigation.Navigation; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import org.jetbrains.annotations.NotNull; -import org.moire.ultrasonic.R; -import org.moire.ultrasonic.data.ActiveServerProvider; -import org.moire.ultrasonic.domain.MusicDirectory; -import org.moire.ultrasonic.domain.Share; -import org.moire.ultrasonic.service.DownloadFile; -import org.moire.ultrasonic.service.MediaPlayerController; -import org.moire.ultrasonic.service.MusicService; -import org.moire.ultrasonic.service.MusicServiceFactory; -import org.moire.ultrasonic.subsonic.DownloadHandler; -import org.moire.ultrasonic.subsonic.ImageLoaderProvider; -import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker; -import org.moire.ultrasonic.subsonic.ShareHandler; -import org.moire.ultrasonic.subsonic.VideoPlayer; -import org.moire.ultrasonic.util.AlbumHeader; -import org.moire.ultrasonic.util.CancellationToken; -import org.moire.ultrasonic.util.Constants; -import org.moire.ultrasonic.util.EntryByDiscAndTrackComparator; -import org.moire.ultrasonic.util.Pair; -import org.moire.ultrasonic.util.FragmentBackgroundTask; -import org.moire.ultrasonic.util.Util; -import org.moire.ultrasonic.view.AlbumView; -import org.moire.ultrasonic.view.EntryAdapter; -import org.moire.ultrasonic.view.SongView; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; - -import kotlin.Lazy; -import timber.log.Timber; - -import static org.koin.java.KoinJavaComponent.inject; - -/** - * Displays a group of playable media from the library, which can be an Album, a Playlist, etc. - */ -public class SelectAlbumFragment extends Fragment { - - public static final String allSongsId = "-1"; - private SwipeRefreshLayout refreshAlbumListView; - private ListView albumListView; - private View header; - private View albumButtons; - private View emptyView; - private ImageView selectButton; - private ImageView playNowButton; - private ImageView playNextButton; - private ImageView playLastButton; - private ImageView pinButton; - private ImageView unpinButton; - private ImageView downloadButton; - private ImageView deleteButton; - private ImageView moreButton; - private boolean playAllButtonVisible; - private boolean shareButtonVisible; - private MenuItem playAllButton; - private MenuItem shareButton; - private boolean showHeader = true; - private final Random random = new java.security.SecureRandom(); - - private final Lazy mediaPlayerControllerLazy = inject(MediaPlayerController.class); - private final Lazy videoPlayer = inject(VideoPlayer.class); - private final Lazy downloadHandler = inject(DownloadHandler.class); - private final Lazy networkAndStorageChecker = inject(NetworkAndStorageChecker.class); - private final Lazy imageLoaderProvider = inject(ImageLoaderProvider.class); - private final Lazy shareHandler = inject(ShareHandler.class); - private CancellationToken cancellationToken; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - Util.applyTheme(this.getContext()); - super.onCreate(savedInstanceState); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return inflater.inflate(R.layout.select_album, container, false); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - cancellationToken = new CancellationToken(); - - albumButtons = view.findViewById(R.id.menu_album); - - refreshAlbumListView = view.findViewById(R.id.select_album_entries_refresh); - albumListView = view.findViewById(R.id.select_album_entries_list); - - refreshAlbumListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() - { - @Override - public void onRefresh() { - updateDisplay(true); - } - }); - - header = LayoutInflater.from(getContext()).inflate(R.layout.select_album_header, albumListView, false); - - albumListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - albumListView.setOnItemClickListener(new AdapterView.OnItemClickListener() - { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) - { - if (position >= 0) - { - MusicDirectory.Entry entry = (MusicDirectory.Entry) parent.getItemAtPosition(position); - if (entry != null && entry.isDirectory()) - { - Bundle bundle = new Bundle(); - bundle.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId()); - bundle.putBoolean(Constants.INTENT_EXTRA_NAME_IS_ALBUM, entry.isDirectory()); - bundle.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle()); - bundle.putString(Constants.INTENT_EXTRA_NAME_PARENT_ID, entry.getParent()); - Navigation.findNavController(view).navigate(R.id.selectAlbumFragment, bundle); - } - else if (entry != null && entry.isVideo()) - { - videoPlayer.getValue().playVideo(entry); - } - else - { - enableButtons(); - } - } - } - }); - - // TODO: Long click on an item will first try to maximize / collapse the item, even when it fits inside the TextView. - // The context menu is only displayed on the second long click... This may be improved somehow, e.g. checking first if the texts fit - albumListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener(){ - @Override - public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { - if (view instanceof AlbumView) { - AlbumView albumView = (AlbumView) view; - if (!albumView.isMaximized()) { - albumView.maximizeOrMinimize(); - return true; - } else { - return false; - } - } - if (view instanceof SongView) { - SongView songView = (SongView) view; - songView.maximizeOrMinimize(); - return true; - } - return false; - } - }); - - selectButton = view.findViewById(R.id.select_album_select); - playNowButton = view.findViewById(R.id.select_album_play_now); - playNextButton = view.findViewById(R.id.select_album_play_next); - playLastButton = view.findViewById(R.id.select_album_play_last); - pinButton = view.findViewById(R.id.select_album_pin); - unpinButton = view.findViewById(R.id.select_album_unpin); - downloadButton = view.findViewById(R.id.select_album_download); - deleteButton = view.findViewById(R.id.select_album_delete); - moreButton = view.findViewById(R.id.select_album_more); - emptyView = view.findViewById(R.id.select_album_empty); - - selectButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - selectAllOrNone(); - } - }); - playNowButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - playNow(false); - } - }); - playNextButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - downloadHandler.getValue().download(SelectAlbumFragment.this,true, false, false, true, false, getSelectedSongs(albumListView)); - selectAll(false, false); - } - }); - playLastButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - playNow(true); - } - }); - pinButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - downloadBackground(true); - selectAll(false, false); - } - }); - unpinButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - unpin(); - selectAll(false, false); - } - }); - downloadButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - downloadBackground(false); - selectAll(false, false); - } - }); - deleteButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - delete(); - selectAll(false, false); - } - }); - - registerForContextMenu(albumListView); - setHasOptionsMenu(true); - enableButtons(); - updateDisplay(false); - } - - private void updateDisplay(boolean refresh) - { - String id = getArguments().getString(Constants.INTENT_EXTRA_NAME_ID); - boolean isAlbum = getArguments().getBoolean(Constants.INTENT_EXTRA_NAME_IS_ALBUM, false); - String name = getArguments().getString(Constants.INTENT_EXTRA_NAME_NAME); - String parentId = getArguments().getString(Constants.INTENT_EXTRA_NAME_PARENT_ID); - String playlistId = getArguments().getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID); - String podcastChannelId = getArguments().getString(Constants.INTENT_EXTRA_NAME_PODCAST_CHANNEL_ID); - String playlistName = getArguments().getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME); - String shareId = getArguments().getString(Constants.INTENT_EXTRA_NAME_SHARE_ID); - String shareName = getArguments().getString(Constants.INTENT_EXTRA_NAME_SHARE_NAME); - String albumListType = getArguments().getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE); - String genreName = getArguments().getString(Constants.INTENT_EXTRA_NAME_GENRE_NAME); - int albumListTitle = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, 0); - int getStarredTracks = getArguments().getInt(Constants.INTENT_EXTRA_NAME_STARRED, 0); - int getVideos = getArguments().getInt(Constants.INTENT_EXTRA_NAME_VIDEOS, 0); - int getRandomTracks = getArguments().getInt(Constants.INTENT_EXTRA_NAME_RANDOM, 0); - int albumListSize = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0); - int albumListOffset = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0); - - if (playlistId != null) - { - getPlaylist(playlistId, playlistName); - } - else if (podcastChannelId != null) { - getPodcastEpisodes(podcastChannelId); - } - else if (shareId != null) - { - getShare(shareId, shareName); - } - else if (albumListType != null) - { - getAlbumList(albumListType, albumListTitle, albumListSize, albumListOffset); - } - else if (genreName != null) - { - getSongsForGenre(genreName, albumListSize, albumListOffset); - } - else if (getStarredTracks != 0) - { - getStarred(); - } - else if (getVideos != 0) - { - getVideos(refresh); - } - else if (getRandomTracks != 0) - { - getRandom(albumListSize); - } - else - { - if (!ActiveServerProvider.Companion.isOffline(getActivity()) && Util.getShouldUseId3Tags(getActivity())) - { - if (isAlbum) - { - getAlbum(refresh, id, name, parentId); - } - else - { - getArtist(refresh, id, name); - } - } - else - { - getMusicDirectory(refresh, id, name, parentId); - } - } - } - - @Override - public void onCreateContextMenu(@NotNull ContextMenu menu, @NotNull View view, ContextMenu.ContextMenuInfo menuInfo) - { - super.onCreateContextMenu(menu, view, menuInfo); - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - - MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(info.position); - - if (entry != null && entry.isDirectory()) - { - MenuInflater inflater = getActivity().getMenuInflater(); - inflater.inflate(R.menu.select_album_context, menu); - } - - shareButton = menu.findItem(R.id.menu_item_share); - - if (shareButton != null) - { - shareButton.setVisible(!ActiveServerProvider.Companion.isOffline(getContext())); - } - - MenuItem downloadMenuItem = menu.findItem(R.id.album_menu_download); - - if (downloadMenuItem != null) - { - downloadMenuItem.setVisible(!ActiveServerProvider.Companion.isOffline(getContext())); - } - } - - @Override - public boolean onContextItemSelected(MenuItem menuItem) - { - Timber.d("onContextItemSelected"); - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); - - if (info == null) - { - return true; - } - - MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(info.position); - - if (entry == null) - { - return true; - } - - String entryId = entry.getId(); - - int itemId = menuItem.getItemId(); - if (itemId == R.id.album_menu_play_now) { - downloadHandler.getValue().downloadRecursively(this, entryId, false, false, true, false, false, false, false, false); - } else if (itemId == R.id.album_menu_play_next) { - downloadHandler.getValue().downloadRecursively(this, entryId, false, false, false, false, false, true, false, false); - } else if (itemId == R.id.album_menu_play_last) { - downloadHandler.getValue().downloadRecursively(this, entryId, false, true, false, false, false, false, false, false); - } else if (itemId == R.id.album_menu_pin) { - downloadHandler.getValue().downloadRecursively(this, entryId, true, true, false, false, false, false, false, false); - } else if (itemId == R.id.album_menu_unpin) { - downloadHandler.getValue().downloadRecursively(this, entryId, false, false, false, false, false, false, true, false); - } else if (itemId == R.id.album_menu_download) { - downloadHandler.getValue().downloadRecursively(this, entryId, false, false, false, false, true, false, false, false); - } else if (itemId == R.id.select_album_play_all) { - playAll(); - } else if (itemId == R.id.menu_item_share) { - List entries = new ArrayList<>(1); - entries.add(entry); - shareHandler.getValue().createShare(this, entries, refreshAlbumListView, cancellationToken); - return true; - } else { - return super.onContextItemSelected(menuItem); - } - return true; - } - - @Override - public void onPrepareOptionsMenu(@NotNull Menu menu) - { - super.onPrepareOptionsMenu(menu); - playAllButton = menu.findItem(R.id.select_album_play_all); - - if (playAllButton != null) - { - playAllButton.setVisible(playAllButtonVisible); - } - - shareButton = menu.findItem(R.id.menu_item_share); - - if (shareButton != null) - { - shareButton.setVisible(shareButtonVisible); - } - } - - @Override - public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { - inflater.inflate(R.menu.select_album, menu); - super.onCreateOptionsMenu(menu, inflater); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) - { - int itemId = item.getItemId(); - if (itemId == R.id.select_album_play_all) { - playAll(); - return true; - } else if (itemId == R.id.menu_item_share) { - shareHandler.getValue().createShare(this, getSelectedSongs(albumListView), refreshAlbumListView, cancellationToken); - return true; - } - - return false; - } - - @Override - public void onDestroyView() { - cancellationToken.cancel(); - super.onDestroyView(); - } - - private void playNow(final boolean append) - { - List selectedSongs = getSelectedSongs(albumListView); - - if (!selectedSongs.isEmpty()) - { - downloadHandler.getValue().download(this, append, false, !append, false, false, selectedSongs); - selectAll(false, false); - } - else - { - playAll(false, append); - } - } - - private void playAll() - { - playAll(false, false); - } - - private void playAll(final boolean shuffle, final boolean append) - { - boolean hasSubFolders = false; - - for (int i = 0; i < albumListView.getCount(); i++) - { - MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(i); - if (entry != null && entry.isDirectory()) - { - hasSubFolders = true; - break; - } - } - - boolean isArtist = getArguments().getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false); - String id = getArguments().getString(Constants.INTENT_EXTRA_NAME_ID); - - if (hasSubFolders && id != null) - { - downloadHandler.getValue().downloadRecursively(this, id, false, append, !append, shuffle, false, false, false, isArtist); - } - else - { - selectAll(true, false); - downloadHandler.getValue().download(this, append, false, !append, false, shuffle, getSelectedSongs(albumListView)); - selectAll(false, false); - } - } - - private static List getSelectedSongs(ListView albumListView) - { - List songs = new ArrayList<>(10); - - if (albumListView != null) - { - int count = albumListView.getCount(); - for (int i = 0; i < count; i++) - { - if (albumListView.isItemChecked(i)) - { - songs.add((MusicDirectory.Entry) albumListView.getItemAtPosition(i)); - } - } - } - - return songs; - } - - private void getMusicDirectory(final boolean refresh, final String id, final String name, final String parentId) - { - FragmentTitle.Companion.setTitle(this, name); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - MusicDirectory root = new MusicDirectory(); - - if (allSongsId.equals(id)) - { - MusicDirectory musicDirectory = service.getMusicDirectory(parentId, name, refresh, getContext()); - - List songs = new LinkedList<>(); - getSongsRecursively(musicDirectory, songs); - - for (MusicDirectory.Entry song : songs) - { - if (!song.isDirectory()) - { - root.addChild(song); - } - } - } - else - { - MusicDirectory musicDirectory = service.getMusicDirectory(id, name, refresh, getContext()); - - if (Util.getShouldShowAllSongsByArtist(getContext()) && musicDirectory.findChild(allSongsId) == null && musicDirectory.getChildren(true, false).size() == musicDirectory.getChildren(true, true).size()) - { - MusicDirectory.Entry allSongs = new MusicDirectory.Entry(); - - allSongs.setDirectory(true); - allSongs.setArtist(name); - allSongs.setParent(id); - allSongs.setId(allSongsId); - allSongs.setTitle(String.format(getResources().getString(R.string.select_album_all_songs), name)); - - root.addChild(allSongs); - - List children = musicDirectory.getChildren(); - - if (children != null) - { - root.addAll(children); - } - } - else - { - root = musicDirectory; - } - } - - return root; - } - - private void getSongsRecursively(MusicDirectory parent, List songs) throws Exception - { - for (MusicDirectory.Entry song : parent.getChildren(false, true)) - { - if (!song.isVideo() && !song.isDirectory()) - { - songs.add(song); - } - } - - MusicService musicService = MusicServiceFactory.getMusicService(getContext()); - - for (MusicDirectory.Entry dir : parent.getChildren(true, false)) - { - MusicDirectory root; - - if (!allSongsId.equals(dir.getId())) - { - root = musicService.getMusicDirectory(dir.getId(), dir.getTitle(), false, getContext()); - - getSongsRecursively(root, songs); - } - } - } - }.execute(); - } - - private void getArtist(final boolean refresh, final String id, final String name) - { - FragmentTitle.Companion.setTitle(this, name); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - MusicDirectory root = new MusicDirectory(); - - MusicDirectory musicDirectory = service.getArtist(id, name, refresh, getContext()); - - if (Util.getShouldShowAllSongsByArtist(getContext()) && musicDirectory.findChild(allSongsId) == null && musicDirectory.getChildren(true, false).size() == musicDirectory.getChildren(true, true).size()) - { - MusicDirectory.Entry allSongs = new MusicDirectory.Entry(); - - allSongs.setDirectory(true); - allSongs.setArtist(name); - allSongs.setParent(id); - allSongs.setId(allSongsId); - allSongs.setTitle(String.format(getResources().getString(R.string.select_album_all_songs), name)); - - root.addFirst(allSongs); - - List children = musicDirectory.getChildren(); - - if (children != null) - { - root.addAll(children); - } - } - else - { - root = musicDirectory; - } - - return root; - } - }.execute(); - } - - private void getAlbum(final boolean refresh, final String id, final String name, final String parentId) - { - FragmentTitle.Companion.setTitle(this, name); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - MusicDirectory musicDirectory; - - if (allSongsId.equals(id)) - { - MusicDirectory root = new MusicDirectory(); - - Collection songs = new LinkedList<>(); - getSongsForArtist(parentId, songs); - - for (MusicDirectory.Entry song : songs) - { - if (!song.isDirectory()) - { - root.addChild(song); - } - } - - musicDirectory = root; - } - else - { - musicDirectory = service.getAlbum(id, name, refresh, getContext()); - } - - return musicDirectory; - } - - private void getSongsForArtist(String id, Collection songs) throws Exception - { - MusicService musicService = MusicServiceFactory.getMusicService(getContext()); - MusicDirectory artist = musicService.getArtist(id, "", false, getContext()); - - for (MusicDirectory.Entry album : artist.getChildren()) - { - if (!allSongsId.equals(album.getId())) - { - MusicDirectory albumDirectory = musicService.getAlbum(album.getId(), "", false, getContext()); - - for (MusicDirectory.Entry song : albumDirectory.getChildren()) - { - if (!song.isVideo()) - { - songs.add(song); - } - } - } - } - } - }.execute(); - } - - private void getSongsForGenre(final String genre, final int count, final int offset) - { - FragmentTitle.Companion.setTitle(this, genre); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - return service.getSongsByGenre(genre, count, offset, getContext()); - } - - @Override - protected void done(Pair result) - { - // Hide more button when results are less than album list size - if (result.getFirst().getChildren().size() < getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0)) - { - moreButton.setVisibility(View.GONE); - } - else - { - moreButton.setVisibility(View.VISIBLE); - } - - moreButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - String genre = getArguments().getString(Constants.INTENT_EXTRA_NAME_GENRE_NAME); - int size = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0); - int offset = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0) + size; - - Bundle bundle = new Bundle(); - bundle.putString(Constants.INTENT_EXTRA_NAME_GENRE_NAME, genre); - bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, size); - bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, offset); - Navigation.findNavController(getView()).navigate(R.id.selectAlbumFragment, bundle); - } - }); - - super.done(result); - } - }.execute(); - } - - private void getStarred() - { - FragmentTitle.Companion.setTitle(this, R.string.main_songs_starred); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - return Util.getShouldUseId3Tags(getContext()) ? Util.getSongsFromSearchResult(service.getStarred2(getContext())) : Util.getSongsFromSearchResult(service.getStarred(getContext())); - } - }.execute(); - } - - private void getVideos(final boolean refresh) - { - showHeader = false; - - FragmentTitle.Companion.setTitle(this, R.string.main_videos); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - return service.getVideos(refresh, getContext()); - } - }.execute(); - } - - private void getRandom(final int size) - { - FragmentTitle.Companion.setTitle(this, R.string.main_songs_random); - - new LoadTask() - { - @Override - protected boolean sortableCollection() { - return false; - } - - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - return service.getRandomSongs(size, getContext()); - } - }.execute(); - } - - private void getPlaylist(final String playlistId, final String playlistName) - { - FragmentTitle.Companion.setTitle(this, playlistName); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - return service.getPlaylist(playlistId, playlistName, getContext()); - } - }.execute(); - } - - private void getPodcastEpisodes(final String podcastChannelId) - { - FragmentTitle.Companion.setTitle(this, R.string.podcasts_label); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - return service.getPodcastEpisodes(podcastChannelId, getContext()); - } - }.execute(); - } - - private void getShare(final String shareId, final CharSequence shareName) - { - FragmentTitle.Companion.setTitle(this, shareName); - //setActionBarSubtitle(shareName); - - new LoadTask() - { - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - List shares = service.getShares(true, getContext()); - - MusicDirectory md = new MusicDirectory(); - - for (Share share : shares) - { - if (share.getId().equals(shareId)) - { - for (MusicDirectory.Entry entry : share.getEntries()) - { - md.addChild(entry); - } - - break; - } - } - - return md; - } - }.execute(); - } - - private void getAlbumList(final String albumListType, final int albumListTitle, final int size, final int offset) - { - showHeader = false; - - FragmentTitle.Companion.setTitle(this, albumListTitle); - //setActionBarSubtitle(albumListTitle); - - new LoadTask() - { - @Override - protected boolean sortableCollection() { - return !albumListType.equals("newest") && !albumListType.equals("random") && - !albumListType.equals("highest") && !albumListType.equals("recent") && - !albumListType.equals("frequent"); - } - - @Override - protected MusicDirectory load(MusicService service) throws Exception - { - return Util.getShouldUseId3Tags(getContext()) ? service.getAlbumList2(albumListType, size, offset, getContext()) : service.getAlbumList(albumListType, size, offset, getContext()); - } - - @Override - protected void done(Pair result) - { - if (!result.getFirst().getChildren().isEmpty()) - { - pinButton.setVisibility(View.GONE); - unpinButton.setVisibility(View.GONE); - downloadButton.setVisibility(View.GONE); - deleteButton.setVisibility(View.GONE); - - // Hide more button when results are less than album list size - if (result.getFirst().getChildren().size() < getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0)) - { - moreButton.setVisibility(View.GONE); - } - else - { - moreButton.setVisibility(View.VISIBLE); - - moreButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - int albumListTitle = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, 0); - String type = getArguments().getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE); - int size = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0); - int offset = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0) + size; - - Bundle bundle = new Bundle(); - bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, albumListTitle); - bundle.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type); - bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, size); - bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, offset); - Navigation.findNavController(getView()).navigate(R.id.selectAlbumFragment, bundle); - } - }); - } - } - else - { - moreButton.setVisibility(View.GONE); - } - - super.done(result); - } - }.execute(); - } - - private void selectAllOrNone() - { - boolean someUnselected = false; - int count = albumListView.getCount(); - - for (int i = 0; i < count; i++) - { - if (!albumListView.isItemChecked(i) && albumListView.getItemAtPosition(i) instanceof MusicDirectory.Entry) - { - someUnselected = true; - break; - } - } - - selectAll(someUnselected, true); - } - - private void selectAll(boolean selected, boolean toast) - { - int count = albumListView.getCount(); - int selectedCount = 0; - - for (int i = 0; i < count; i++) - { - MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(i); - if (entry != null && !entry.isDirectory() && !entry.isVideo()) - { - albumListView.setItemChecked(i, selected); - selectedCount++; - } - } - - // Display toast: N tracks selected / N tracks unselected - if (toast) - { - int toastResId = selected ? R.string.select_album_n_selected : R.string.select_album_n_unselected; - Util.toast(getActivity(), getString(toastResId, selectedCount)); - } - - enableButtons(); - } - - private void enableButtons() - { - List selection = getSelectedSongs(albumListView); - boolean enabled = !selection.isEmpty(); - boolean unpinEnabled = false; - boolean deleteEnabled = false; - - int pinnedCount = 0; - - for (MusicDirectory.Entry song : selection) - { - DownloadFile downloadFile = mediaPlayerControllerLazy.getValue().getDownloadFileForSong(song); - if (downloadFile.isWorkDone()) - { - deleteEnabled = true; - } - - if (downloadFile.isSaved()) - { - pinnedCount++; - unpinEnabled = true; - } - } - - playNowButton.setVisibility(enabled ? View.VISIBLE : View.GONE); - playNextButton.setVisibility(enabled ? View.VISIBLE : View.GONE); - playLastButton.setVisibility(enabled ? View.VISIBLE : View.GONE); - pinButton.setVisibility((enabled && !ActiveServerProvider.Companion.isOffline(getContext()) && selection.size() > pinnedCount) ? View.VISIBLE : View.GONE); - unpinButton.setVisibility(enabled && unpinEnabled ? View.VISIBLE : View.GONE); - downloadButton.setVisibility(enabled && !deleteEnabled && !ActiveServerProvider.Companion.isOffline(getContext()) ? View.VISIBLE : View.GONE); - deleteButton.setVisibility(enabled && deleteEnabled ? View.VISIBLE : View.GONE); - } - - private void downloadBackground(final boolean save) - { - List songs = getSelectedSongs(albumListView); - - if (songs.isEmpty()) - { - selectAll(true, false); - songs = getSelectedSongs(albumListView); - } - - downloadBackground(save, songs); - } - - private void downloadBackground(final boolean save, final List songs) - { - Runnable onValid = new Runnable() - { - @Override - public void run() - { - networkAndStorageChecker.getValue().warnIfNetworkOrStorageUnavailable(); - mediaPlayerControllerLazy.getValue().downloadBackground(songs, save); - - if (save) - { - Util.toast(getContext(), getResources().getQuantityString(R.plurals.select_album_n_songs_pinned, songs.size(), songs.size())); - } - else - { - Util.toast(getContext(), getResources().getQuantityString(R.plurals.select_album_n_songs_downloaded, songs.size(), songs.size())); - } - } - }; - onValid.run(); - } - - private void delete() - { - List songs = getSelectedSongs(albumListView); - - if (songs.isEmpty()) - { - selectAll(true, false); - songs = getSelectedSongs(albumListView); - } - - mediaPlayerControllerLazy.getValue().delete(songs); - } - - private void unpin() - { - List songs = getSelectedSongs(albumListView); - Util.toast(getContext(), getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size())); - mediaPlayerControllerLazy.getValue().unpin(songs); - } - - private abstract class LoadTask extends FragmentBackgroundTask> - { - - public LoadTask() - { - super(SelectAlbumFragment.this.getActivity(), true, refreshAlbumListView, cancellationToken); - } - - protected abstract MusicDirectory load(MusicService service) throws Exception; - - protected boolean sortableCollection() { - return true; - } - - @Override - protected Pair doInBackground() throws Throwable - { - MusicService musicService = MusicServiceFactory.getMusicService(getContext()); - MusicDirectory dir = load(musicService); - boolean valid = musicService.isLicenseValid(getContext()); - return new Pair<>(dir, valid); - } - - @Override - protected void done(Pair result) - { - MusicDirectory musicDirectory = result.getFirst(); - List entries = musicDirectory.getChildren(); - - if (sortableCollection() && Util.getShouldSortByDisc(getContext())) - { - Collections.sort(entries, new EntryByDiscAndTrackComparator()); - } - - boolean allVideos = true; - int songCount = 0; - - for (MusicDirectory.Entry entry : entries) - { - if (!entry.isVideo()) - { - allVideos = false; - } - - if (!entry.isDirectory()) - { - songCount++; - } - } - - final int listSize = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0); - - if (songCount > 0) - { - if (showHeader) - { - String intentAlbumName = getArguments().getString(Constants.INTENT_EXTRA_NAME_NAME); - String directoryName = musicDirectory.getName(); - View header = createHeader(entries, intentAlbumName != null ? intentAlbumName : directoryName, songCount); - - if (header != null && albumListView.getHeaderViewsCount() == 0) - { - albumListView.addHeaderView(header, null, false); - } - } - - pinButton.setVisibility(View.VISIBLE); - unpinButton.setVisibility(View.VISIBLE); - downloadButton.setVisibility(View.VISIBLE); - deleteButton.setVisibility(View.VISIBLE); - selectButton.setVisibility(allVideos ? View.GONE : View.VISIBLE); - playNowButton.setVisibility(View.VISIBLE); - playNextButton.setVisibility(View.VISIBLE); - playLastButton.setVisibility(View.VISIBLE); - - if (listSize == 0 || songCount < listSize) - { - moreButton.setVisibility(View.GONE); - } - else - { - moreButton.setVisibility(View.VISIBLE); - - if (getArguments().getInt(Constants.INTENT_EXTRA_NAME_RANDOM, 0) > 0) - { - moreButton.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - int offset = getArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0) + listSize; - - Bundle bundle = new Bundle(); - bundle.putInt(Constants.INTENT_EXTRA_NAME_RANDOM, 1); - bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, listSize); - bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, offset); - Navigation.findNavController(getView()).navigate(R.id.selectAlbumFragment, bundle); - } - }); - } - } - } - else - { - pinButton.setVisibility(View.GONE); - unpinButton.setVisibility(View.GONE); - downloadButton.setVisibility(View.GONE); - deleteButton.setVisibility(View.GONE); - selectButton.setVisibility(View.GONE); - playNowButton.setVisibility(View.GONE); - playNextButton.setVisibility(View.GONE); - playLastButton.setVisibility(View.GONE); - - if (listSize == 0 || result.getFirst().getChildren().size() < listSize) - { - albumButtons.setVisibility(View.GONE); - } - else - { - moreButton.setVisibility(View.VISIBLE); - } - } - - enableButtons(); - - boolean isAlbumList = getArguments().containsKey(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE); - playAllButtonVisible = !(isAlbumList || entries.isEmpty()) && !allVideos; - shareButtonVisible = !ActiveServerProvider.Companion.isOffline(getContext()) && songCount > 0; - - emptyView.setVisibility(entries.isEmpty() ? View.VISIBLE : View.GONE); - - if (playAllButton != null) - { - playAllButton.setVisible(playAllButtonVisible); - } - - if (shareButton != null) - { - shareButton.setVisible(shareButtonVisible); - } - - albumListView.setAdapter(new EntryAdapter(getContext(), imageLoaderProvider.getValue().getImageLoader(), entries, true)); - - boolean playAll = getArguments().getBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false); - if (playAll && songCount > 0) - { - playAll(getArguments().getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, false), false); - } - } - - protected View createHeader(List entries, CharSequence name, int songCount) - { - ImageView coverArtView = (ImageView) header.findViewById(R.id.select_album_art); - int artworkSelection = random.nextInt(entries.size()); - imageLoaderProvider.getValue().getImageLoader().loadImage(coverArtView, entries.get(artworkSelection), false, Util.getAlbumImageSize(getContext()), false, true); - - AlbumHeader albumHeader = AlbumHeader.processEntries(getContext(), entries); - - TextView titleView = (TextView) header.findViewById(R.id.select_album_title); - titleView.setText(name != null ? name : FragmentTitle.Companion.getTitle(SelectAlbumFragment.this)); //getActionBarSubtitle()); - - // Don't show a header if all entries are videos - if (albumHeader.getIsAllVideo()) - { - return null; - } - - TextView artistView = header.findViewById(R.id.select_album_artist); - String artist; - - artist = albumHeader.getArtists().size() == 1 ? albumHeader.getArtists().iterator().next() : albumHeader.getGrandParents().size() == 1 ? albumHeader.getGrandParents().iterator().next() : getResources().getString(R.string.common_various_artists); - - artistView.setText(artist); - - TextView genreView = header.findViewById(R.id.select_album_genre); - String genre; - - genre = albumHeader.getGenres().size() == 1 ? albumHeader.getGenres().iterator().next() : getResources().getString(R.string.common_multiple_genres); - - genreView.setText(genre); - - TextView yearView = header.findViewById(R.id.select_album_year); - String year; - - year = albumHeader.getYears().size() == 1 ? albumHeader.getYears().iterator().next().toString() : getResources().getString(R.string.common_multiple_years); - - yearView.setText(year); - - TextView songCountView = header.findViewById(R.id.select_album_song_count); - String songs = getResources().getQuantityString(R.plurals.select_album_n_songs, songCount, songCount); - songCountView.setText(songs); - - String duration = Util.formatTotalDuration(albumHeader.getTotalDuration()); - - TextView durationView = header.findViewById(R.id.select_album_duration); - durationView.setText(duration); - - return header; - } - } -} diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SelectAlbumFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SelectAlbumFragment.kt new file mode 100644 index 00000000..4c96c1c6 --- /dev/null +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/SelectAlbumFragment.kt @@ -0,0 +1,1145 @@ +package org.moire.ultrasonic.fragment + +import android.os.Bundle +import android.view.ContextMenu +import android.view.ContextMenu.ContextMenuInfo +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.AdapterContextMenuInfo +import android.widget.AdapterView.OnItemClickListener +import android.widget.AdapterView.OnItemLongClickListener +import android.widget.ImageView +import android.widget.ListView +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.navigation.Navigation +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener +import java.security.SecureRandom +import java.util.Collections +import java.util.LinkedList +import java.util.Random +import org.koin.android.ext.android.inject +import org.moire.ultrasonic.R +import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline +import org.moire.ultrasonic.domain.MusicDirectory +import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle +import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle +import org.moire.ultrasonic.service.MediaPlayerController +import org.moire.ultrasonic.service.MusicService +import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService +import org.moire.ultrasonic.subsonic.DownloadHandler +import org.moire.ultrasonic.subsonic.ImageLoaderProvider +import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker +import org.moire.ultrasonic.subsonic.ShareHandler +import org.moire.ultrasonic.subsonic.VideoPlayer +import org.moire.ultrasonic.util.AlbumHeader +import org.moire.ultrasonic.util.CancellationToken +import org.moire.ultrasonic.util.Constants +import org.moire.ultrasonic.util.EntryByDiscAndTrackComparator +import org.moire.ultrasonic.util.FragmentBackgroundTask +import org.moire.ultrasonic.util.Util +import org.moire.ultrasonic.view.AlbumView +import org.moire.ultrasonic.view.EntryAdapter +import org.moire.ultrasonic.view.SongView +import timber.log.Timber + +/** + * Displays a group of playable media from the library, which can be an Album, a Playlist, etc. + */ +class SelectAlbumFragment : Fragment() { + + private val allSongsId = "-1" + private var refreshAlbumListView: SwipeRefreshLayout? = null + private var albumListView: ListView? = null + private var header: View? = null + private var albumButtons: View? = null + private var emptyView: View? = null + private var selectButton: ImageView? = null + private var playNowButton: ImageView? = null + private var playNextButton: ImageView? = null + private var playLastButton: ImageView? = null + private var pinButton: ImageView? = null + private var unpinButton: ImageView? = null + private var downloadButton: ImageView? = null + private var deleteButton: ImageView? = null + private var moreButton: ImageView? = null + private var playAllButtonVisible = false + private var shareButtonVisible = false + private var playAllButton: MenuItem? = null + private var shareButton: MenuItem? = null + private var showHeader = true + private val random: Random = SecureRandom() + + private val mediaPlayerController: MediaPlayerController by inject() + private val videoPlayer: VideoPlayer by inject() + private val downloadHandler: DownloadHandler by inject() + private val networkAndStorageChecker: NetworkAndStorageChecker by inject() + private val imageLoaderProvider: ImageLoaderProvider by inject() + private val shareHandler: ShareHandler by inject() + private var cancellationToken: CancellationToken? = null + + override fun onCreate(savedInstanceState: Bundle?) { + Util.applyTheme(this.context) + super.onCreate(savedInstanceState) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.select_album, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + cancellationToken = CancellationToken() + + albumButtons = view.findViewById(R.id.menu_album) + + refreshAlbumListView = view.findViewById(R.id.select_album_entries_refresh) + albumListView = view.findViewById(R.id.select_album_entries_list) + + refreshAlbumListView!!.setOnRefreshListener( + OnRefreshListener + { + updateDisplay(true) + } + ) + + header = LayoutInflater.from(context).inflate( + R.layout.select_album_header, albumListView, + false + ) + + albumListView!!.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE) + albumListView!!.setOnItemClickListener( + OnItemClickListener + { parent, theView, position, _ -> + if (position >= 0) { + val entry = parent.getItemAtPosition(position) as MusicDirectory.Entry? + if (entry != null && entry.isDirectory) { + val bundle = Bundle() + bundle.putString(Constants.INTENT_EXTRA_NAME_ID, entry.id) + bundle.putBoolean(Constants.INTENT_EXTRA_NAME_IS_ALBUM, entry.isDirectory) + bundle.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.title) + bundle.putString(Constants.INTENT_EXTRA_NAME_PARENT_ID, entry.parent) + Navigation.findNavController(theView).navigate( + R.id.selectAlbumFragment, + bundle + ) + } else if (entry != null && entry.isVideo) { + videoPlayer.playVideo(entry) + } else { + enableButtons() + } + } + } + ) + + // TODO Long click on an item will first try to maximize / collapse the item, even when it + // fits inside the TextView. The context menu is only displayed on the second long click... + // This may be improved somehow, e.g. checking first if the texts fit + albumListView!!.setOnItemLongClickListener( + OnItemLongClickListener + { _, theView, _, _ -> + if (theView is AlbumView) { + val albumView = theView + if (!albumView.isMaximized) { + albumView.maximizeOrMinimize() + return@OnItemLongClickListener true + } else { + return@OnItemLongClickListener false + } + } + if (theView is SongView) { + theView.maximizeOrMinimize() + return@OnItemLongClickListener true + } + false + } + ) + + selectButton = view.findViewById(R.id.select_album_select) + playNowButton = view.findViewById(R.id.select_album_play_now) + playNextButton = view.findViewById(R.id.select_album_play_next) + playLastButton = view.findViewById(R.id.select_album_play_last) + pinButton = view.findViewById(R.id.select_album_pin) + unpinButton = view.findViewById(R.id.select_album_unpin) + downloadButton = view.findViewById(R.id.select_album_download) + deleteButton = view.findViewById(R.id.select_album_delete) + moreButton = view.findViewById(R.id.select_album_more) + emptyView = view.findViewById(R.id.select_album_empty) + + selectButton!!.setOnClickListener( + View.OnClickListener + { + selectAllOrNone() + } + ) + playNowButton!!.setOnClickListener( + View.OnClickListener + { + playNow(false) + } + ) + playNextButton!!.setOnClickListener( + View.OnClickListener + { + downloadHandler.download( + this@SelectAlbumFragment, true, + false, false, true, false, + getSelectedSongs(albumListView) + ) + selectAll(false, false) + } + ) + playLastButton!!.setOnClickListener( + View.OnClickListener + { + playNow(true) + } + ) + pinButton!!.setOnClickListener( + View.OnClickListener + { + downloadBackground(true) + selectAll(false, false) + } + ) + unpinButton!!.setOnClickListener( + View.OnClickListener + { + unpin() + selectAll(false, false) + } + ) + downloadButton!!.setOnClickListener( + View.OnClickListener + { + downloadBackground(false) + selectAll(false, false) + } + ) + deleteButton!!.setOnClickListener( + View.OnClickListener + { + delete() + selectAll(false, false) + } + ) + + registerForContextMenu(albumListView!!) + setHasOptionsMenu(true) + enableButtons() + updateDisplay(false) + } + + private fun updateDisplay(refresh: Boolean) { + val id = requireArguments().getString(Constants.INTENT_EXTRA_NAME_ID) + val isAlbum = requireArguments().getBoolean(Constants.INTENT_EXTRA_NAME_IS_ALBUM, false) + val name = requireArguments().getString(Constants.INTENT_EXTRA_NAME_NAME) + val parentId = requireArguments().getString(Constants.INTENT_EXTRA_NAME_PARENT_ID) + val playlistId = requireArguments().getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID) + val podcastChannelId = requireArguments().getString( + Constants.INTENT_EXTRA_NAME_PODCAST_CHANNEL_ID + ) + val playlistName = requireArguments().getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME) + val shareId = requireArguments().getString(Constants.INTENT_EXTRA_NAME_SHARE_ID) + val shareName = requireArguments().getString(Constants.INTENT_EXTRA_NAME_SHARE_NAME) + val albumListType = requireArguments().getString( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE + ) + val genreName = requireArguments().getString(Constants.INTENT_EXTRA_NAME_GENRE_NAME) + val albumListTitle = requireArguments().getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, 0 + ) + val getStarredTracks = requireArguments().getInt(Constants.INTENT_EXTRA_NAME_STARRED, 0) + val getVideos = requireArguments().getInt(Constants.INTENT_EXTRA_NAME_VIDEOS, 0) + val getRandomTracks = requireArguments().getInt(Constants.INTENT_EXTRA_NAME_RANDOM, 0) + val albumListSize = requireArguments().getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0 + ) + val albumListOffset = requireArguments().getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0 + ) + + if (playlistId != null) { + getPlaylist(playlistId, playlistName) + } else if (podcastChannelId != null) { + getPodcastEpisodes(podcastChannelId) + } else if (shareId != null) { + getShare(shareId, shareName) + } else if (albumListType != null) { + getAlbumList(albumListType, albumListTitle, albumListSize, albumListOffset) + } else if (genreName != null) { + getSongsForGenre(genreName, albumListSize, albumListOffset) + } else if (getStarredTracks != 0) { + starred + } else if (getVideos != 0) { + getVideos(refresh) + } else if (getRandomTracks != 0) { + getRandom(albumListSize) + } else { + if (!isOffline(activity) && Util.getShouldUseId3Tags(activity)) { + if (isAlbum) { + getAlbum(refresh, id, name, parentId) + } else { + getArtist(refresh, id, name) + } + } else { + getMusicDirectory(refresh, id, name, parentId) + } + } + } + + override fun onCreateContextMenu(menu: ContextMenu, view: View, menuInfo: ContextMenuInfo?) { + super.onCreateContextMenu(menu, view, menuInfo) + val info = menuInfo as AdapterContextMenuInfo? + + val entry = albumListView!!.getItemAtPosition(info!!.position) as MusicDirectory.Entry? + + if (entry != null && entry.isDirectory) { + val inflater = requireActivity().menuInflater + inflater.inflate(R.menu.select_album_context, menu) + } + + shareButton = menu.findItem(R.id.menu_item_share) + + if (shareButton != null) { + shareButton!!.isVisible = !isOffline(context) + } + + val downloadMenuItem = menu.findItem(R.id.album_menu_download) + if (downloadMenuItem != null) { + downloadMenuItem.isVisible = !isOffline(context) + } + } + + override fun onContextItemSelected(menuItem: MenuItem): Boolean { + Timber.d("onContextItemSelected") + val info = menuItem.menuInfo as AdapterContextMenuInfo? ?: return true + + val entry = albumListView!!.getItemAtPosition(info.position) as MusicDirectory.Entry? + ?: return true + + val entryId = entry.id + + val itemId = menuItem.itemId + if (itemId == R.id.album_menu_play_now) { + downloadHandler.downloadRecursively( + this, entryId, false, false, true, false, false, false, false, false + ) + } else if (itemId == R.id.album_menu_play_next) { + downloadHandler.downloadRecursively( + this, entryId, false, false, false, false, false, true, false, false + ) + } else if (itemId == R.id.album_menu_play_last) { + downloadHandler.downloadRecursively( + this, entryId, false, true, false, false, false, false, false, false + ) + } else if (itemId == R.id.album_menu_pin) { + downloadHandler.downloadRecursively( + this, entryId, true, true, false, false, false, false, false, false + ) + } else if (itemId == R.id.album_menu_unpin) { + downloadHandler.downloadRecursively( + this, entryId, false, false, false, false, false, false, true, false + ) + } else if (itemId == R.id.album_menu_download) { + downloadHandler.downloadRecursively( + this, entryId, false, false, false, false, true, false, false, false + ) + } else if (itemId == R.id.select_album_play_all) { + playAll() + } else if (itemId == R.id.menu_item_share) { + val entries: MutableList = ArrayList(1) + entries.add(entry) + shareHandler.createShare( + this, entries, refreshAlbumListView, + cancellationToken!! + ) + return true + } else { + return super.onContextItemSelected(menuItem) + } + return true + } + + override fun onPrepareOptionsMenu(menu: Menu) { + super.onPrepareOptionsMenu(menu) + playAllButton = menu.findItem(R.id.select_album_play_all) + + if (playAllButton != null) { + playAllButton!!.isVisible = playAllButtonVisible + } + + shareButton = menu.findItem(R.id.menu_item_share) + + if (shareButton != null) { + shareButton!!.isVisible = shareButtonVisible + } + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.select_album, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val itemId = item.itemId + if (itemId == R.id.select_album_play_all) { + playAll() + return true + } else if (itemId == R.id.menu_item_share) { + shareHandler.createShare( + this, getSelectedSongs(albumListView), + refreshAlbumListView, cancellationToken!! + ) + return true + } + + return false + } + + override fun onDestroyView() { + cancellationToken!!.cancel() + super.onDestroyView() + } + + private fun playNow(append: Boolean) { + val selectedSongs = getSelectedSongs(albumListView) + + if (!selectedSongs.isEmpty()) { + downloadHandler.download( + this, append, false, !append, false, + false, selectedSongs + ) + selectAll(false, false) + } else { + playAll(false, append) + } + } + + private fun playAll(shuffle: Boolean = false, append: Boolean = false) { + var hasSubFolders = false + + for (i in 0 until albumListView!!.count) { + val entry = albumListView!!.getItemAtPosition(i) as MusicDirectory.Entry? + if (entry != null && entry.isDirectory) { + hasSubFolders = true + break + } + } + + val isArtist = requireArguments().getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false) + val id = requireArguments().getString(Constants.INTENT_EXTRA_NAME_ID) + + if (hasSubFolders && id != null) { + downloadHandler.downloadRecursively( + this, id, false, append, !append, + shuffle, false, false, false, isArtist + ) + } else { + selectAll(true, false) + downloadHandler.download( + this, append, false, !append, false, + shuffle, getSelectedSongs(albumListView) + ) + selectAll(false, false) + } + } + + private fun getMusicDirectory(refresh: Boolean, id: String?, name: String?, parentId: String?) { + setTitle(this, name) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + var root = MusicDirectory() + + if (allSongsId == id) { + val musicDirectory = service.getMusicDirectory(parentId, name, refresh, context) + + val songs: MutableList = LinkedList() + getSongsRecursively(musicDirectory, songs) + + for (song in songs) { + if (!song.isDirectory) { + root.addChild(song) + } + } + } else { + val musicDirectory = service.getMusicDirectory(id, name, refresh, context) + + if (Util.getShouldShowAllSongsByArtist(context) && + musicDirectory.findChild(allSongsId) == null && + musicDirectory.getChildren(true, false).size == + musicDirectory.getChildren(true, true).size + ) { + val allSongs = MusicDirectory.Entry() + + allSongs.isDirectory = true + allSongs.artist = name + allSongs.parent = id + allSongs.id = allSongsId + allSongs.title = String.format( + resources.getString(R.string.select_album_all_songs), name + ) + + root.addChild(allSongs) + root.addAll(musicDirectory.getChildren()) + } else { + root = musicDirectory + } + } + return root + } + + private fun getSongsRecursively( + parent: MusicDirectory, + songs: MutableList + ) { + for (song in parent.getChildren(false, true)) { + if (!song.isVideo && !song.isDirectory) { + songs.add(song) + } + } + + val musicService = getMusicService(context!!) + + for ((id1, _, _, title) in parent.getChildren(true, false)) { + var root: MusicDirectory + + if (allSongsId != id1) { + root = musicService.getMusicDirectory(id1, title, false, context) + + getSongsRecursively(root, songs) + } + } + } + }.execute() + } + + private fun getArtist(refresh: Boolean, id: String?, name: String?) { + setTitle(this, name) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + + var root = MusicDirectory() + + val musicDirectory = service.getArtist(id, name, refresh, context) + + if (Util.getShouldShowAllSongsByArtist(context) && + musicDirectory.findChild(allSongsId) == null && + musicDirectory.getChildren(true, false).size == + musicDirectory.getChildren(true, true).size + ) { + val allSongs = MusicDirectory.Entry() + + allSongs.isDirectory = true + allSongs.artist = name + allSongs.parent = id + allSongs.id = allSongsId + allSongs.title = String.format( + resources.getString(R.string.select_album_all_songs), name + ) + + root.addFirst(allSongs) + root.addAll(musicDirectory.getChildren()) + } else { + root = musicDirectory + } + return root + } + }.execute() + } + + private fun getAlbum(refresh: Boolean, id: String?, name: String?, parentId: String?) { + setTitle(this, name) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + + val musicDirectory: MusicDirectory + + musicDirectory = if (allSongsId == id) { + val root = MusicDirectory() + + val songs: MutableCollection = LinkedList() + getSongsForArtist(parentId, songs) + + for (song in songs) { + if (!song.isDirectory) { + root.addChild(song) + } + } + root + } else { + service.getAlbum(id, name, refresh, context) + } + return musicDirectory + } + + private fun getSongsForArtist( + id: String?, + songs: MutableCollection + ) { + + val musicService = getMusicService(context!!) + val artist = musicService.getArtist(id, "", false, context) + + for ((id1) in artist.getChildren()) { + if (allSongsId != id1) { + val albumDirectory = musicService.getAlbum(id1, "", false, context) + + for (song in albumDirectory.getChildren()) { + if (!song.isVideo) { + songs.add(song) + } + } + } + } + } + }.execute() + } + + private fun getSongsForGenre(genre: String, count: Int, offset: Int) { + setTitle(this, genre) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + return service.getSongsByGenre(genre, count, offset, context) + } + + override fun done(result: Pair) { + // Hide more button when results are less than album list size + if (result.first.getChildren().size < arguments!!.getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0 + ) + ) { + moreButton!!.visibility = View.GONE + } else { + moreButton!!.visibility = View.VISIBLE + } + + moreButton!!.setOnClickListener { + val theGenre = arguments!!.getString(Constants.INTENT_EXTRA_NAME_GENRE_NAME) + val size = arguments!!.getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0) + val theOffset = arguments!!.getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0 + ) + size + val bundle = Bundle() + bundle.putString(Constants.INTENT_EXTRA_NAME_GENRE_NAME, theGenre) + bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, size) + bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, theOffset) + Navigation.findNavController(view!!).navigate(R.id.selectAlbumFragment, bundle) + } + + super.done(result) + } + }.execute() + } + + private val starred: Unit + get() { + setTitle(this, R.string.main_songs_starred) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + return if (Util.getShouldUseId3Tags(context)) + Util.getSongsFromSearchResult(service.getStarred2(context)) + else + Util.getSongsFromSearchResult(service.getStarred(context)) + } + }.execute() + } + + private fun getVideos(refresh: Boolean) { + showHeader = false + + setTitle(this, R.string.main_videos) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + return service.getVideos(refresh, context) + } + }.execute() + } + + private fun getRandom(size: Int) { + setTitle(this, R.string.main_songs_random) + + object : LoadTask() { + override fun sortableCollection(): Boolean { + return false + } + + override fun load(service: MusicService): MusicDirectory { + return service.getRandomSongs(size, context) + } + }.execute() + } + + private fun getPlaylist(playlistId: String, playlistName: String?) { + + setTitle(this, playlistName) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + return service.getPlaylist(playlistId, playlistName, context) + } + }.execute() + } + + private fun getPodcastEpisodes(podcastChannelId: String) { + + setTitle(this, R.string.podcasts_label) + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + return service.getPodcastEpisodes(podcastChannelId, context) + } + }.execute() + } + + private fun getShare(shareId: String, shareName: CharSequence?) { + + setTitle(this, shareName) + // setActionBarSubtitle(shareName); + + object : LoadTask() { + override fun load(service: MusicService): MusicDirectory { + val shares = service.getShares(true, context) + + val md = MusicDirectory() + + for (share in shares) { + if (share.id == shareId) { + for (entry in share.getEntries()) { + md.addChild(entry) + } + break + } + } + return md + } + }.execute() + } + + private fun getAlbumList(albumListType: String, albumListTitle: Int, size: Int, offset: Int) { + + showHeader = false + + setTitle(this, albumListTitle) + // setActionBarSubtitle(albumListTitle); + + object : LoadTask() { + override fun sortableCollection(): Boolean { + return albumListType != "newest" && albumListType != "random" && + albumListType != "highest" && albumListType != "recent" && + albumListType != "frequent" + } + + override fun load(service: MusicService): MusicDirectory { + return if (Util.getShouldUseId3Tags(context)) + service.getAlbumList2(albumListType, size, offset, context) + else + service.getAlbumList(albumListType, size, offset, context) + } + + override fun done(result: Pair) { + if (!result.first.getChildren().isEmpty()) { + pinButton!!.visibility = View.GONE + unpinButton!!.visibility = View.GONE + downloadButton!!.visibility = View.GONE + deleteButton!!.visibility = View.GONE + + // Hide more button when results are less than album list size + if (result.first.getChildren().size < arguments!!.getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0 + ) + ) { + moreButton!!.visibility = View.GONE + } else { + moreButton!!.visibility = View.VISIBLE + moreButton!!.setOnClickListener { + val theAlbumListTitle = arguments!!.getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, 0 + ) + val type = arguments!!.getString( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE + ) + val theSize = arguments!!.getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0 + ) + val theOffset = arguments!!.getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0 + ) + theSize + + val bundle = Bundle() + bundle.putInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TITLE, theAlbumListTitle + ) + bundle.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type) + bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, theSize) + bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, theOffset) + Navigation.findNavController(view!!).navigate( + R.id.selectAlbumFragment, bundle + ) + } + } + } else { + moreButton!!.visibility = View.GONE + } + super.done(result) + } + }.execute() + } + + private fun selectAllOrNone() { + var someUnselected = false + val count = albumListView!!.count + + for (i in 0 until count) { + if (!albumListView!!.isItemChecked(i) && + albumListView!!.getItemAtPosition(i) is MusicDirectory.Entry + ) { + someUnselected = true + break + } + } + selectAll(someUnselected, true) + } + + private fun selectAll(selected: Boolean, toast: Boolean) { + val count = albumListView!!.count + var selectedCount = 0 + + for (i in 0 until count) { + val entry = albumListView!!.getItemAtPosition(i) as MusicDirectory.Entry? + if (entry != null && !entry.isDirectory && !entry.isVideo) { + albumListView!!.setItemChecked(i, selected) + selectedCount++ + } + } + + // Display toast: N tracks selected / N tracks unselected + if (toast) { + val toastResId = if (selected) + R.string.select_album_n_selected + else + R.string.select_album_n_unselected + Util.toast(activity, getString(toastResId, selectedCount)) + } + enableButtons() + } + + private fun enableButtons() { + val selection = getSelectedSongs(albumListView) + val enabled = !selection.isEmpty() + var unpinEnabled = false + var deleteEnabled = false + + var pinnedCount = 0 + + for (song in selection) { + val downloadFile = mediaPlayerController.getDownloadFileForSong(song) + if (downloadFile.isWorkDone) { + deleteEnabled = true + } + if (downloadFile.isSaved) { + pinnedCount++ + unpinEnabled = true + } + } + + playNowButton!!.visibility = if (enabled) View.VISIBLE else View.GONE + playNextButton!!.visibility = if (enabled) View.VISIBLE else View.GONE + playLastButton!!.visibility = if (enabled) View.VISIBLE else View.GONE + pinButton!!.visibility = if (enabled && !isOffline(context) && selection.size > pinnedCount) + View.VISIBLE + else + View.GONE + unpinButton!!.visibility = if (enabled && unpinEnabled) View.VISIBLE else View.GONE + downloadButton!!.visibility = if (enabled && !deleteEnabled && !isOffline(context)) + View.VISIBLE + else + View.GONE + deleteButton!!.visibility = if (enabled && deleteEnabled) View.VISIBLE else View.GONE + } + + private fun downloadBackground(save: Boolean) { + var songs = getSelectedSongs(albumListView) + + if (songs.isEmpty()) { + selectAll(true, false) + songs = getSelectedSongs(albumListView) + } + + downloadBackground(save, songs) + } + + private fun downloadBackground(save: Boolean, songs: List) { + val onValid = Runnable { + networkAndStorageChecker.warnIfNetworkOrStorageUnavailable() + mediaPlayerController.downloadBackground(songs, save) + + if (save) { + Util.toast( + context, + resources.getQuantityString( + R.plurals.select_album_n_songs_pinned, songs.size, songs.size + ) + ) + } else { + Util.toast( + context, + resources.getQuantityString( + R.plurals.select_album_n_songs_downloaded, songs.size, songs.size + ) + ) + } + } + onValid.run() + } + + private fun delete() { + var songs = getSelectedSongs(albumListView) + + if (songs.isEmpty()) { + selectAll(true, false) + songs = getSelectedSongs(albumListView) + } + + mediaPlayerController.delete(songs) + } + + private fun unpin() { + val songs = getSelectedSongs(albumListView) + Util.toast( + context, + resources.getQuantityString( + R.plurals.select_album_n_songs_unpinned, songs.size, songs.size + ) + ) + mediaPlayerController.unpin(songs) + } + + private abstract inner class LoadTask : FragmentBackgroundTask>( + this@SelectAlbumFragment.activity, true, refreshAlbumListView, + cancellationToken + ) { + + protected abstract fun load(service: MusicService): MusicDirectory + protected open fun sortableCollection(): Boolean { + return true + } + + override fun doInBackground(): Pair { + val musicService = getMusicService(context!!) + val dir = load(musicService) + val valid = musicService.isLicenseValid(context) + return Pair(dir, valid) + } + + protected override fun done(result: Pair) { + val musicDirectory = result.first + val entries = musicDirectory.getChildren() + + if (sortableCollection() && Util.getShouldSortByDisc(context)) { + Collections.sort(entries, EntryByDiscAndTrackComparator()) + } + + var allVideos = true + var songCount = 0 + + for (entry in entries) { + if (!entry.isVideo) { + allVideos = false + } + if (!entry.isDirectory) { + songCount++ + } + } + + val listSize = arguments!!.getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0) + + if (songCount > 0) { + if (showHeader) { + val intentAlbumName = arguments!!.getString(Constants.INTENT_EXTRA_NAME_NAME) + val directoryName = musicDirectory.name + val header = createHeader( + entries, intentAlbumName ?: directoryName, + songCount + ) + if (header != null && albumListView!!.headerViewsCount == 0) { + albumListView!!.addHeaderView(header, null, false) + } + } + + pinButton!!.visibility = View.VISIBLE + unpinButton!!.visibility = View.VISIBLE + downloadButton!!.visibility = View.VISIBLE + deleteButton!!.visibility = View.VISIBLE + selectButton!!.visibility = if (allVideos) View.GONE else View.VISIBLE + playNowButton!!.visibility = View.VISIBLE + playNextButton!!.visibility = View.VISIBLE + playLastButton!!.visibility = View.VISIBLE + + if (listSize == 0 || songCount < listSize) { + moreButton!!.visibility = View.GONE + } else { + moreButton!!.visibility = View.VISIBLE + if (arguments!!.getInt(Constants.INTENT_EXTRA_NAME_RANDOM, 0) > 0) { + moreButton!!.setOnClickListener { + val offset = arguments!!.getInt( + Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0 + ) + listSize + val bundle = Bundle() + bundle.putInt(Constants.INTENT_EXTRA_NAME_RANDOM, 1) + bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, listSize) + bundle.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, offset) + Navigation.findNavController(view!!).navigate( + R.id.selectAlbumFragment, bundle + ) + } + } + } + } else { + pinButton!!.visibility = View.GONE + unpinButton!!.visibility = View.GONE + downloadButton!!.visibility = View.GONE + deleteButton!!.visibility = View.GONE + selectButton!!.visibility = View.GONE + playNowButton!!.visibility = View.GONE + playNextButton!!.visibility = View.GONE + playLastButton!!.visibility = View.GONE + + if (listSize == 0 || result.first.getChildren().size < listSize) { + albumButtons!!.visibility = View.GONE + } else { + moreButton!!.visibility = View.VISIBLE + } + } + + enableButtons() + + val isAlbumList = arguments!!.containsKey(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE) + playAllButtonVisible = !(isAlbumList || entries.isEmpty()) && !allVideos + shareButtonVisible = !isOffline(context) && songCount > 0 + + emptyView!!.visibility = if (entries.isEmpty()) View.VISIBLE else View.GONE + + if (playAllButton != null) { + playAllButton!!.isVisible = playAllButtonVisible + } + + if (shareButton != null) { + shareButton!!.isVisible = shareButtonVisible + } + + albumListView!!.adapter = EntryAdapter( + context, + imageLoaderProvider.getImageLoader(), entries, true + ) + + val playAll = arguments!!.getBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false) + if (playAll && songCount > 0) { + playAll( + arguments!!.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, false), + false + ) + } + } + + protected fun createHeader( + entries: List, + name: CharSequence?, + songCount: Int + ): View? { + val coverArtView = header!!.findViewById(R.id.select_album_art) as ImageView + val artworkSelection = random.nextInt(entries.size) + imageLoaderProvider.getImageLoader().loadImage( + coverArtView, entries[artworkSelection], false, + Util.getAlbumImageSize(context), false, true + ) + + val albumHeader = AlbumHeader.processEntries(context, entries) + + val titleView = header!!.findViewById(R.id.select_album_title) as TextView + titleView.text = name ?: getTitle(this@SelectAlbumFragment) // getActionBarSubtitle()); + + // Don't show a header if all entries are videos + if (albumHeader.isAllVideo) { + return null + } + + val artistView = header!!.findViewById(R.id.select_album_artist) + val artist: String + + artist = if (albumHeader.artists.size == 1) + albumHeader.artists.iterator().next() + else if (albumHeader.grandParents.size == 1) + albumHeader.grandParents.iterator().next() + else + resources.getString(R.string.common_various_artists) + + artistView.text = artist + + val genreView = header!!.findViewById(R.id.select_album_genre) + val genre: String + + genre = if (albumHeader.genres.size == 1) + albumHeader.genres.iterator().next() + else + resources.getString(R.string.common_multiple_genres) + + genreView.text = genre + + val yearView = header!!.findViewById(R.id.select_album_year) + val year: String + + year = if (albumHeader.years.size == 1) + albumHeader.years.iterator().next().toString() + else + resources.getString(R.string.common_multiple_years) + + yearView.text = year + + val songCountView = header!!.findViewById(R.id.select_album_song_count) + val songs = resources.getQuantityString( + R.plurals.select_album_n_songs, songCount, + songCount + ) + songCountView.text = songs + + val duration = Util.formatTotalDuration(albumHeader.totalDuration) + + val durationView = header!!.findViewById(R.id.select_album_duration) + durationView.text = duration + + return header + } + } + + private fun getSelectedSongs(albumListView: ListView?): List { + val songs: MutableList = ArrayList(10) + + if (albumListView != null) { + val count = albumListView.count + for (i in 0 until count) { + if (albumListView.isItemChecked(i)) { + songs.add(albumListView.getItemAtPosition(i) as MusicDirectory.Entry?) + } + } + } + + return songs + } +}