feat: added the ability to request download for an unplayed podcast episode

This commit is contained in:
antonio 2023-07-31 11:39:35 +02:00
parent 1ebe9ff8ba
commit b267b904cc
10 changed files with 79 additions and 2 deletions

View file

@ -20,6 +20,7 @@ public interface ClickCallback {
default void onServerClick(Bundle bundle) {}
default void onServerLongClick(Bundle bundle) {}
default void onPodcastEpisodeClick(Bundle bundle) {}
default void onPodcastEpisodeAltClick(Bundle bundle) {}
default void onPodcastEpisodeLongClick(Bundle bundle) {}
default void onPodcastChannelClick(Bundle bundle) {}
default void onPodcastChannelLongClick(Bundle bundle) {}

View file

@ -133,4 +133,21 @@ public class PodcastRepository {
}
});
}
public void downloadPodcastEpisode(String episodeId) {
App.getSubsonicClientInstance(false)
.getPodcastClient()
.downloadPodcastEpisode(episodeId)
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
}
@Override
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
}
});
}
}

View file

@ -48,4 +48,9 @@ public class PodcastClient {
Log.d(TAG, "deletePodcastEpisode()");
return podcastService.deletePodcastEpisode(subsonic.getParams(), episodeId);
}
public Call<ApiResponse> downloadPodcastEpisode(String episodeId) {
Log.d(TAG, "downloadPodcastEpisode()");
return podcastService.downloadPodcastEpisode(subsonic.getParams(), episodeId);
}
}

View file

@ -27,4 +27,7 @@ public interface PodcastService {
@GET("deletePodcastEpisode")
Call<ApiResponse> deletePodcastEpisode(@QueryMap Map<String, String> params, @Query("id") String id);
@GET("downloadPodcastEpisode")
Call<ApiResponse> downloadPodcastEpisode(@QueryMap Map<String, String> params, @Query("id") String id);
}

View file

@ -57,6 +57,7 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
holder.item.podcastPlayButton.setEnabled(podcastEpisode.getStatus().equals("completed"));
holder.item.podcastMoreButton.setVisibility(podcastEpisode.getStatus().equals("completed") ? View.VISIBLE : View.GONE);
holder.item.podcastDownloadRequestButton.setVisibility(podcastEpisode.getStatus().equals("completed") ? View.GONE : View.VISIBLE);
}
@Override
@ -93,6 +94,7 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
item.podcastPlayButton.setOnClickListener(v -> onClick());
item.podcastMoreButton.setOnClickListener(v -> openMore());
item.podcastDownloadRequestButton.setOnClickListener(v -> requestDownload());
}
public void onClick() {
@ -120,6 +122,17 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
return false;
}
public void requestDownload() {
PodcastEpisode podcastEpisode = podcastEpisodes.get(getBindingAdapterPosition());
if (!podcastEpisode.getStatus().equals("completed")) {
Bundle bundle = new Bundle();
bundle.putParcelable(Constants.PODCAST_OBJECT, podcastEpisodes.get(getBindingAdapterPosition()));
click.onPodcastEpisodeAltClick(bundle);
}
}
}
public void sort(String order) {

View file

@ -28,6 +28,7 @@ import com.cappielloantonio.tempo.util.Constants;
import com.cappielloantonio.tempo.util.MusicUtil;
import com.cappielloantonio.tempo.util.UIUtil;
import com.cappielloantonio.tempo.viewmodel.PodcastChannelPageViewModel;
import com.google.android.material.snackbar.Snackbar;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;
@ -169,4 +170,14 @@ public class PodcastChannelPageFragment extends Fragment implements ClickCallbac
public void onPodcastEpisodeLongClick(Bundle bundle) {
Navigation.findNavController(requireView()).navigate(R.id.podcastEpisodeBottomSheetDialog, bundle);
}
@Override
public void onPodcastEpisodeAltClick(Bundle bundle) {
PodcastEpisode episode = bundle.getParcelable(Constants.PODCAST_OBJECT);
podcastChannelPageViewModel.requestPodcastEpisodeDownload(episode);
Snackbar.make(requireView(), R.string.podcast_episode_download_request_snackbar, Snackbar.LENGTH_SHORT)
.setAnchorView(activity.bind.bottomNavigation)
.show();
}
}

View file

@ -8,6 +8,7 @@ import androidx.lifecycle.LiveData;
import com.cappielloantonio.tempo.repository.PodcastRepository;
import com.cappielloantonio.tempo.subsonic.models.PodcastChannel;
import com.cappielloantonio.tempo.subsonic.models.PodcastEpisode;
import java.util.List;
@ -33,4 +34,8 @@ public class PodcastChannelPageViewModel extends AndroidViewModel {
public void setPodcastChannel(PodcastChannel podcastChannel) {
this.podcastChannel = podcastChannel;
}
public void requestPodcastEpisodeDownload(PodcastEpisode podcastEpisode) {
podcastRepository.downloadPodcastEpisode(podcastEpisode.getId());
}
}

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@color/titleTextColor"
android:pathData="M439,878Q363,870 297.5,835.5Q232,801 184,747.5Q136,694 108.5,625Q81,556 81,479Q81,324 183.5,210.5Q286,97 440,80L440,160Q319,177 240,267.5Q161,358 161,479Q161,600 240,690.5Q319,781 439,798L439,878ZM479,680L278,478L335,421L439,525L439,280L519,280L519,525L622,422L679,480L479,680ZM519,878L519,798Q562,792 601.5,775Q641,758 675,732L733,790Q686,827 632,849.5Q578,872 519,878ZM677,226Q642,200 602.5,183Q563,166 520,160L520,80Q579,86 633,108.5Q687,131 733,168L677,226ZM789,732L733,675Q759,641 775,601.5Q791,562 797,519L879,519Q871,578 849,632.5Q827,687 789,732ZM797,439Q791,396 775,356.5Q759,317 733,283L789,226Q827,271 850,325.5Q873,380 879,439L797,439Z"/>
</vector>

View file

@ -20,9 +20,9 @@
style="@style/LabelMedium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:ellipsize="end"
android:maxLines="5"
android:layout_marginStart="12dp"
android:text="@string/label_placeholder"
app:layout_constraintBottom_toTopOf="@+id/podcast_subtitle_label"
app:layout_constraintEnd_toEndOf="parent"
@ -36,9 +36,9 @@
style="@style/LabelSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:ellipsize="end"
android:maxLines="2"
android:layout_marginStart="12dp"
android:text="@string/label_placeholder"
app:layout_constraintBottom_toTopOf="@id/podcast_upper_divider"
app:layout_constraintEnd_toEndOf="parent"
@ -100,9 +100,21 @@
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:icon="@drawable/ic_more_vert"
app:layout_constraintBottom_toBottomOf="@+id/podcast_play_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/podcast_play_button" />
<Button
android:id="@+id/podcast_download_request_button"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:icon="@drawable/ic_podcast_download"
app:layout_constraintBottom_toBottomOf="@+id/podcast_play_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/podcast_play_button" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -134,6 +134,7 @@
<string name="podcast_channel_editor_dialog_hint_rss_url">RSS Url</string>
<string name="podcast_channel_editor_dialog_title">Podcast Channel</string>
<string name="podcast_release_date_duration_formatter">%1$s • %2$s</string>
<string name="podcast_episode_download_request_snackbar">Your request has been sent to the server</string>
<string name="podcast_info_empty_subtitle">Once you add a channel, you\'ll find it here</string>
<string name="podcast_info_empty_title">No podcasts found!</string>
<string name="podcast_info_empty_button">Click to hide the section\nThe effects will be visible on restart</string>