Extract action button utils/callback into classes

This splits the logic in `ActionButtonUtils` and
`DefaultActionButtonCallback` into multiple specialized classes to
reduce duplication figuring out which button/action to use while at the
same time making each individual button to have a single responsability.
This commit is contained in:
Anderson Mesquita 2019-05-02 20:06:36 -04:00
parent c327fd59c9
commit 1d64057fd4
7 changed files with 377 additions and 0 deletions

View File

@ -0,0 +1,32 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
class AddToQueueActionButton extends ItemActionButton {
AddToQueueActionButton(FeedItem item) {
super(item);
}
@Override
@StringRes
public int getLabel() {
return R.string.add_to_queue_label;
}
@Override
@AttrRes
public int getDrawable() {
return R.attr.content_new;
}
@Override
public void onClick(Context context) {
MobileDownloadHelper.confirmMobileDownload(context, item);
}
}

View File

@ -0,0 +1,44 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import android.widget.Toast;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester;
class CancelDownloadActionButton extends ItemActionButton {
CancelDownloadActionButton(FeedItem item) {
super(item);
}
@Override
@StringRes
public int getLabel() {
return R.string.cancel_download_label;
}
@Override
@AttrRes
public int getDrawable() {
return R.attr.navigation_cancel;
}
@Override
public void onClick(Context context) {
FeedMedia media = item.getMedia();
DownloadRequester.getInstance().cancelDownload(context, media);
if (UserPreferences.isEnableAutodownload()) {
DBWriter.setFeedItemAutoDownload(media.getItem(), false);
Toast.makeText(context, R.string.download_canceled_autodownload_enabled_msg, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, R.string.download_canceled_msg, Toast.LENGTH_LONG).show();
}
}
}

View File

@ -0,0 +1,74 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.widget.Toast;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.NetworkUtils;
class DownloadActionButton extends ItemActionButton {
private boolean isInQueue;
DownloadActionButton(FeedItem item, boolean isInQueue) {
super(item);
this.isInQueue = isInQueue;
}
@Override
@StringRes
public int getLabel() {
return R.string.download_label;
}
@Override
@AttrRes
public int getDrawable() {
return R.attr.av_download;
}
@Override
public void onClick(Context context) {
final FeedMedia media = item.getMedia();
if (media == null || shouldNotDownload(media)) {
return;
}
if (NetworkUtils.isDownloadAllowed() || MobileDownloadHelper.userAllowedMobileDownloads()) {
downloadEpisode(context);
} else if (MobileDownloadHelper.userChoseAddToQueue() && !isInQueue) {
addEpisodeToQueue(context);
} else {
MobileDownloadHelper.confirmMobileDownload(context, item);
}
}
private boolean shouldNotDownload(@NonNull FeedMedia media) {
boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
return isDownloading || media.isDownloaded();
}
private void addEpisodeToQueue(Context context) {
DBWriter.addQueueItem(context, item);
Toast.makeText(context, R.string.added_to_queue_label, Toast.LENGTH_SHORT).show();
}
private void downloadEpisode(Context context) {
try {
DBTasks.downloadFeedItems(context, item);
Toast.makeText(context, R.string.status_downloading_label, Toast.LENGTH_SHORT).show();
} catch (DownloadRequestException e) {
e.printStackTrace();
DownloadRequestErrorDialogCreator.newRequestErrorDialog(context, e.getMessage());
}
}
}

View File

@ -0,0 +1,63 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.view.View;
import android.widget.ImageButton;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.storage.DownloadRequester;
public abstract class ItemActionButton {
FeedItem item;
ItemActionButton(FeedItem item) {
this.item = item;
}
@StringRes
abstract public int getLabel();
@AttrRes
abstract public int getDrawable();
abstract public void onClick(Context context);
public int getVisibility() {
return View.VISIBLE;
}
@NonNull
public static ItemActionButton forItem(@NonNull FeedItem item, boolean isInQueue) {
final FeedMedia media = item.getMedia();
if (media == null) {
return new MarkAsPlayedActionButton(item);
}
final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
if (media.isDownloaded()) {
return new PlayActionButton(item);
} else if (isDownloadingMedia) {
return new CancelDownloadActionButton(item);
} else if (MobileDownloadHelper.userAllowedMobileDownloads() || !MobileDownloadHelper.userChoseAddToQueue() || isInQueue) {
return new DownloadActionButton(item, isInQueue);
} else {
return new AddToQueueActionButton(item);
}
}
public void configure(@NonNull ImageButton button, Context context) {
TypedArray drawables = context.obtainStyledAttributes(new int[]{getDrawable()});
button.setVisibility(getVisibility());
button.setContentDescription(context.getString(getLabel()));
button.setImageDrawable(drawables.getDrawable(0));
button.setOnClickListener((view) -> onClick(context));
drawables.recycle();
}
}

View File

@ -0,0 +1,41 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import android.view.View;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBWriter;
class MarkAsPlayedActionButton extends ItemActionButton {
MarkAsPlayedActionButton(FeedItem item) {
super(item);
}
@Override
@StringRes
public int getLabel() {
return R.string.mark_read_label;
}
@Override
@AttrRes
public int getDrawable() {
return R.attr.navigation_accept;
}
@Override
public void onClick(Context context) {
if (!item.isPlayed()) {
DBWriter.markItemPlayed(item, FeedItem.PLAYED, true);
}
}
@Override
public int getVisibility() {
return (item.isPlayed()) ? View.INVISIBLE : View.VISIBLE;
}
}

View File

@ -0,0 +1,60 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
class MobileDownloadHelper {
private static long addToQueueTimestamp;
private static long allowMobileDownloadTimestamp;
private static final int TEN_MINUTES_IN_MILLIS = 10 * 60 * 1000;
static boolean userChoseAddToQueue() {
return System.currentTimeMillis() - addToQueueTimestamp < TEN_MINUTES_IN_MILLIS;
}
static boolean userAllowedMobileDownloads() {
return System.currentTimeMillis() - allowMobileDownloadTimestamp < TEN_MINUTES_IN_MILLIS;
}
static void confirmMobileDownload(final Context context, final FeedItem item) {
MaterialDialog.Builder builder = new MaterialDialog.Builder(context)
.title(R.string.confirm_mobile_download_dialog_title)
.content(R.string.confirm_mobile_download_dialog_message)
.positiveText(context.getText(R.string.confirm_mobile_download_dialog_enable_temporarily))
.onPositive((dialog, which) -> downloadFeedItems(context, item));
if (!DBReader.getQueueIDList().contains(item.getId())) {
builder
.content(R.string.confirm_mobile_download_dialog_message_not_in_queue)
.neutralText(R.string.confirm_mobile_download_dialog_only_add_to_queue)
.onNeutral((dialog, which) -> addToQueue(context, item));
}
builder.show();
}
private static void addToQueue(Context context, FeedItem item) {
addToQueueTimestamp = System.currentTimeMillis();
DBWriter.addQueueItem(context, item);
Toast.makeText(context, R.string.added_to_queue_label, Toast.LENGTH_SHORT).show();
}
private static void downloadFeedItems(Context context, FeedItem item) {
allowMobileDownloadTimestamp = System.currentTimeMillis();
try {
DBTasks.downloadFeedItems(context, item);
Toast.makeText(context, R.string.status_downloading_label, Toast.LENGTH_SHORT).show();
} catch (DownloadRequestException e) {
e.printStackTrace();
DownloadRequestErrorDialogCreator.newRequestErrorDialog(context, e.getMessage());
}
}
}

View File

@ -0,0 +1,63 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import static de.danoeh.antennapod.core.service.playback.PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE;
import static de.danoeh.antennapod.core.service.playback.PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE;
class PlayActionButton extends ItemActionButton {
PlayActionButton(FeedItem item) {
super(item);
}
@Override
@StringRes
public int getLabel() {
return R.string.play_label;
}
@Override
@AttrRes
public int getDrawable() {
FeedMedia media = item.getMedia();
if (media != null && media.isCurrentlyPlaying()) {
return R.attr.av_pause;
} else {
return R.attr.av_play;
}
}
@Override
public void onClick(Context context) {
FeedMedia media = item.getMedia();
if (media == null) {
return;
}
if (media.isPlaying()) {
togglePlayPause(context, media);
} else {
DBTasks.playMedia(context, media, false, true, false);
}
}
private void togglePlayPause(Context context, FeedMedia media) {
new PlaybackServiceStarter(context, media)
.startWhenPrepared(true)
.shouldStream(false)
.start();
String pauseOrResume = media.isCurrentlyPlaying() ? ACTION_PAUSE_PLAY_CURRENT_EPISODE : ACTION_RESUME_PLAY_CURRENT_EPISODE;
IntentUtils.sendLocalBroadcast(context, pauseOrResume);
}
}