mirror of
https://github.com/antebudimir/tempus.git
synced 2026-04-15 16:27:26 +00:00
feat: implemented download queue fab
This commit is contained in:
parent
1ff0b83a19
commit
540aa9ba73
6 changed files with 70 additions and 14 deletions
|
|
@ -18,8 +18,10 @@ import com.cappielloantonio.tempo.databinding.ItemPlayerQueueSongBinding;
|
||||||
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||||
import com.cappielloantonio.tempo.interfaces.MediaIndexCallback;
|
import com.cappielloantonio.tempo.interfaces.MediaIndexCallback;
|
||||||
|
import com.cappielloantonio.tempo.service.DownloaderManager;
|
||||||
import com.cappielloantonio.tempo.service.MediaManager;
|
import com.cappielloantonio.tempo.service.MediaManager;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
|
import com.cappielloantonio.tempo.util.DownloadUtil;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
|
@ -94,6 +96,20 @@ public class PlayerSongQueueAdapter extends RecyclerView.Adapter<PlayerSongQueue
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DownloaderManager downloaderManager = DownloadUtil.getDownloadTracker(holder.itemView.getContext());
|
||||||
|
|
||||||
|
if (downloaderManager != null) {
|
||||||
|
boolean isDownloaded = downloaderManager.isDownloaded(song.getId());
|
||||||
|
|
||||||
|
if (isDownloaded) {
|
||||||
|
holder.item.downloadIndicatorIcon.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
holder.item.downloadIndicatorIcon.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
holder.item.downloadIndicatorIcon.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
if (Preferences.showItemRating()) {
|
if (Preferences.showItemRating()) {
|
||||||
if (song.getStarred() == null && song.getUserRating() == null) {
|
if (song.getStarred() == null && song.getUserRating() == null) {
|
||||||
holder.item.ratingIndicatorImageView.setVisibility(View.GONE);
|
holder.item.ratingIndicatorImageView.setVisibility(View.GONE);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.session.MediaBrowser;
|
import androidx.media3.session.MediaBrowser;
|
||||||
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.session.SessionToken;
|
import androidx.media3.session.SessionToken;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
@ -22,6 +23,8 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.databinding.InnerFragmentPlayerQueueBinding;
|
import com.cappielloantonio.tempo.databinding.InnerFragmentPlayerQueueBinding;
|
||||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||||
|
import com.cappielloantonio.tempo.model.Download;
|
||||||
|
import com.cappielloantonio.tempo.service.DownloaderManager;
|
||||||
import com.cappielloantonio.tempo.service.MediaManager;
|
import com.cappielloantonio.tempo.service.MediaManager;
|
||||||
import com.cappielloantonio.tempo.service.MediaService;
|
import com.cappielloantonio.tempo.service.MediaService;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
|
|
@ -29,6 +32,8 @@ import com.cappielloantonio.tempo.subsonic.models.PlayQueue;
|
||||||
import com.cappielloantonio.tempo.ui.adapter.PlayerSongQueueAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.PlayerSongQueueAdapter;
|
||||||
import com.cappielloantonio.tempo.ui.dialog.PlaylistChooserDialog;
|
import com.cappielloantonio.tempo.ui.dialog.PlaylistChooserDialog;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
|
import com.cappielloantonio.tempo.util.DownloadUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.MappingUtil;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
import com.cappielloantonio.tempo.viewmodel.PlaybackViewModel;
|
||||||
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
|
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
|
||||||
|
|
@ -383,14 +388,43 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleDownloadAllClick() {
|
private void handleDownloadAllClick() {
|
||||||
Log.d(TAG, "Download All Clicked! (Placeholder)");
|
Log.d(TAG, "Download All Clicked!");
|
||||||
|
|
||||||
|
List<Child> queueSongs = playerSongQueueAdapter.getItems();
|
||||||
|
|
||||||
|
if (queueSongs == null || queueSongs.isEmpty()) {
|
||||||
|
Toast.makeText(requireContext(), "Queue is empty", Toast.LENGTH_SHORT).show();
|
||||||
|
toggleFabMenu();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MediaItem> mediaItemsToDownload = MappingUtil.mapMediaItems(queueSongs);
|
||||||
|
|
||||||
|
List<com.cappielloantonio.tempo.model.Download> downloadModels = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Child child : queueSongs) {
|
||||||
|
com.cappielloantonio.tempo.model.Download downloadModel =
|
||||||
|
new com.cappielloantonio.tempo.model.Download(child);
|
||||||
|
downloadModel.setArtist(child.getArtist());
|
||||||
|
downloadModel.setAlbum(child.getAlbum());
|
||||||
|
downloadModel.setCoverArtId(child.getCoverArtId());
|
||||||
|
downloadModels.add(downloadModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloaderManager downloaderManager = DownloadUtil.getDownloadTracker(requireContext());
|
||||||
|
|
||||||
|
if (downloaderManager != null) {
|
||||||
|
downloaderManager.download(mediaItemsToDownload, downloadModels);
|
||||||
|
Toast.makeText(requireContext(), "Starting download of " + queueSongs.size() + " songs in the background.", Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "DownloaderManager not initialized. Check DownloadUtil.");
|
||||||
|
Toast.makeText(requireContext(), "Download service unavailable.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
toggleFabMenu();
|
toggleFabMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleLoadQueueClick() {
|
private void handleLoadQueueClick() {
|
||||||
Log.d(TAG, "Load Queue Clicked!");
|
Log.d(TAG, "Load Queue Clicked!");
|
||||||
|
|
||||||
// Double-check that sync is enabled (shouldn't be visible if disabled, but just in case)
|
|
||||||
if (!Preferences.isSyncronizationEnabled()) {
|
if (!Preferences.isSyncronizationEnabled()) {
|
||||||
toggleFabMenu();
|
toggleFabMenu();
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.repository.AlbumRepository;
|
import com.cappielloantonio.tempo.repository.AlbumRepository;
|
||||||
import com.cappielloantonio.tempo.repository.DownloadRepository;
|
|
||||||
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
|
|
@ -21,7 +20,6 @@ import java.util.List;
|
||||||
|
|
||||||
public class AlbumListPageViewModel extends AndroidViewModel {
|
public class AlbumListPageViewModel extends AndroidViewModel {
|
||||||
private final AlbumRepository albumRepository;
|
private final AlbumRepository albumRepository;
|
||||||
private final DownloadRepository downloadRepository;
|
|
||||||
|
|
||||||
public String title;
|
public String title;
|
||||||
public ArtistID3 artist;
|
public ArtistID3 artist;
|
||||||
|
|
@ -32,9 +30,7 @@ public class AlbumListPageViewModel extends AndroidViewModel {
|
||||||
|
|
||||||
public AlbumListPageViewModel(@NonNull Application application) {
|
public AlbumListPageViewModel(@NonNull Application application) {
|
||||||
super(application);
|
super(application);
|
||||||
|
|
||||||
albumRepository = new AlbumRepository();
|
albumRepository = new AlbumRepository();
|
||||||
downloadRepository = new DownloadRepository();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<AlbumID3>> getAlbumList(LifecycleOwner owner) {
|
public LiveData<List<AlbumID3>> getAlbumList(LifecycleOwner owner) {
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:text="Save Queue to Playlist"
|
android:text="@string/player_queue_save_to_playlist"
|
||||||
tools:ignore="HardcodedText"
|
|
||||||
app:icon="@android:drawable/ic_menu_edit" />
|
app:icon="@android:drawable/ic_menu_edit" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
|
@ -45,8 +44,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:text="Download All (TODO)"
|
android:text="@string/menu_download_all_button"
|
||||||
tools:ignore="HardcodedText"
|
|
||||||
app:icon="@android:drawable/stat_sys_download_done" />
|
app:icon="@android:drawable/stat_sys_download_done" />
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -56,8 +54,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:text="Load Queue"
|
android:text="@string/player_queue_load_queue"
|
||||||
tools:ignore="HardcodedText"
|
|
||||||
app:icon="@android:drawable/ic_menu_revert" />
|
app:icon="@android:drawable/ic_menu_revert" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
|
@ -82,7 +79,7 @@
|
||||||
android:id="@+id/fab_menu_toggle"
|
android:id="@+id/fab_menu_toggle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="Toggle action menu (TODO: Fix Localization)"
|
android:contentDescription="Toggle FAB Action menu"
|
||||||
tools:ignore="HardcodedText"
|
tools:ignore="HardcodedText"
|
||||||
app:srcCompat="@drawable/ic_add" />
|
app:srcCompat="@drawable/ic_add" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,17 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/download_indicator_icon"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:src="@drawable/ic_download" app:layout_constraintBottom_toBottomOf="@+id/queue_song_cover_image_view"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/queue_song_holder_image"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/queue_song_cover_image_view"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/queue_song_holder_image"
|
android:id="@+id/queue_song_holder_image"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,8 @@
|
||||||
<string name="player_playback_speed">%1$.2fx</string>
|
<string name="player_playback_speed">%1$.2fx</string>
|
||||||
<string name="player_queue_clean_all_button">Clean play queue</string>
|
<string name="player_queue_clean_all_button">Clean play queue</string>
|
||||||
<string name="player_queue_save_queue_success">Saved play queue</string>
|
<string name="player_queue_save_queue_success">Saved play queue</string>
|
||||||
|
<string name="player_queue_save_to_playlist">Save Queue to Playlist</string>
|
||||||
|
<string name="player_queue_load_queue">Load Queue</string>
|
||||||
<string name="player_lyrics_download_content_description">Download lyrics for offline playback</string>
|
<string name="player_lyrics_download_content_description">Download lyrics for offline playback</string>
|
||||||
<string name="player_lyrics_downloaded_content_description">Lyrics downloaded for offline playback</string>
|
<string name="player_lyrics_downloaded_content_description">Lyrics downloaded for offline playback</string>
|
||||||
<string name="player_lyrics_download_success">Lyrics saved for offline playback.</string>
|
<string name="player_lyrics_download_success">Lyrics saved for offline playback.</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue