Replace action/callback utils with ItemActionButton

This just replaces all previous usages of `ActionButtonUtils` and
`DefaultActionButtonCallback` with the newly created `ItemActionButton`
class.
This commit is contained in:
Anderson Mesquita 2019-05-02 20:34:10 -04:00
parent 1d64057fd4
commit 2450b0817b
11 changed files with 22 additions and 311 deletions

View File

@ -1,9 +0,0 @@
package de.danoeh.antennapod.adapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.util.LongList;
interface ActionButtonCallback {
/** Is called when the action button of a list item has been pressed. */
void onActionButtonPressed(FeedItem item, LongList queueIds);
}

View File

@ -1,97 +0,0 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.content.res.TypedArray;
import android.view.View;
import android.widget.ImageButton;
import org.apache.commons.lang3.Validate;
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.DownloadRequester;
/**
* Utility methods for the action button that is displayed on the right hand side
* of a listitem.
*/
class ActionButtonUtils {
private final int[] labels;
private final TypedArray drawables;
private final Context context;
public ActionButtonUtils(Context context) {
Validate.notNull(context);
this.context = context.getApplicationContext();
drawables = context.obtainStyledAttributes(new int[] {
R.attr.av_play,
R.attr.navigation_cancel,
R.attr.av_download,
R.attr.av_pause,
R.attr.navigation_accept,
R.attr.content_new
});
labels = new int[] {
R.string.play_label,
R.string.cancel_download_label,
R.string.download_label,
R.string.mark_read_label,
R.string.add_to_queue_label
};
}
/**
* Sets the displayed bitmap and content description of the given
* action button so that it matches the state of the FeedItem.
*/
@SuppressWarnings("ResourceType")
public void configureActionButton(ImageButton butSecondary, FeedItem item, boolean isInQueue) {
Validate.isTrue(butSecondary != null && item != null, "butSecondary or item was null");
final FeedMedia media = item.getMedia();
if (media != null) {
final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
if (!media.isDownloaded()) {
if (isDownloadingMedia) {
// item is being downloaded
butSecondary.setVisibility(View.VISIBLE);
butSecondary.setImageDrawable(drawables.getDrawable(1));
butSecondary.setContentDescription(context.getString(labels[1]));
} else {
// item is not downloaded and not being downloaded
if(DefaultActionButtonCallback.userAllowedMobileDownloads() ||
!DefaultActionButtonCallback.userChoseAddToQueue() || isInQueue) {
butSecondary.setVisibility(View.VISIBLE);
butSecondary.setImageDrawable(drawables.getDrawable(2));
butSecondary.setContentDescription(context.getString(labels[2]));
} else {
// mobile download not allowed yet, item is not in queue and user chose add to queue
butSecondary.setVisibility(View.VISIBLE);
butSecondary.setImageDrawable(drawables.getDrawable(5));
butSecondary.setContentDescription(context.getString(labels[4]));
}
}
} else {
// item is downloaded
butSecondary.setVisibility(View.VISIBLE);
if (media.isCurrentlyPlaying()) {
butSecondary.setImageDrawable(drawables.getDrawable(3));
} else {
butSecondary.setImageDrawable(drawables.getDrawable(0));
}
butSecondary.setContentDescription(context.getString(labels[0]));
}
} else {
if (item.isPlayed()) {
butSecondary.setVisibility(View.INVISIBLE);
} else {
butSecondary.setVisibility(View.VISIBLE);
butSecondary.setImageDrawable(drawables.getDrawable(4));
butSecondary.setContentDescription(context.getString(labels[3]));
}
}
}
}

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
@ -26,6 +27,7 @@ import java.lang.ref.WeakReference;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.storage.DownloadRequester;
@ -46,8 +48,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
private final WeakReference<MainActivity> mainActivityRef;
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
private final boolean showOnlyNewEpisodes;
private FeedItem selectedItem;
@ -57,13 +57,10 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
public AllEpisodesRecycleAdapter(MainActivity mainActivity,
ItemAccess itemAccess,
ActionButtonCallback actionButtonCallback,
boolean showOnlyNewEpisodes) {
super();
this.mainActivityRef = new WeakReference<>(mainActivity);
this.itemAccess = itemAccess;
this.actionButtonUtils = new ActionButtonUtils(mainActivity);
this.actionButtonCallback = actionButtonCallback;
this.showOnlyNewEpisodes = showOnlyNewEpisodes;
playingBackGroundColor = ThemeUtils.getColorFromAttr(mainActivity, R.attr.currently_playing_background);
@ -186,10 +183,11 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.queueStatus.setVisibility(View.INVISIBLE);
}
actionButtonUtils.configureActionButton(holder.butSecondary, item, isInQueue);
ItemActionButton actionButton = ItemActionButton.forItem(item, isInQueue);
actionButton.configure(holder.butSecondary, mainActivityRef.get());
holder.butSecondary.setFocusable(false);
holder.butSecondary.setTag(item);
holder.butSecondary.setOnClickListener(secondaryActionListener);
new CoverLoader(mainActivityRef.get())
.withUri(item.getImageLocation())
@ -215,14 +213,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
return itemAccess.getCount();
}
private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds());
}
};
public class Holder extends RecyclerView.ViewHolder
implements View.OnClickListener,
View.OnCreateContextMenuListener,

View File

@ -1,139 +0,0 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.content.Intent;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import org.apache.commons.lang3.Validate;
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.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
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;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
/**
* Default implementation of an ActionButtonCallback
*/
public class DefaultActionButtonCallback implements ActionButtonCallback {
private static final String TAG = "DefaultActionButtonCallback";
private final Context context;
private static final int TEN_MINUTES_IN_MILLIS = 60 * 1000 * 10;
// remember timestamp when user allowed downloading via mobile connection
private static long allowMobileDownloadsTimestamp;
private static long onlyAddToQueueTimeStamp;
public DefaultActionButtonCallback(Context context) {
Validate.notNull(context);
this.context = context;
}
public static boolean userAllowedMobileDownloads() {
return System.currentTimeMillis() - allowMobileDownloadsTimestamp < TEN_MINUTES_IN_MILLIS;
}
public static boolean userChoseAddToQueue() {
return System.currentTimeMillis() - onlyAddToQueueTimeStamp < TEN_MINUTES_IN_MILLIS;
}
@Override
public void onActionButtonPressed(final FeedItem item, final LongList queueIds) {
if (item.hasMedia()) {
final FeedMedia media = item.getMedia();
boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
if (!isDownloading && !media.isDownloaded()) {
if (NetworkUtils.isDownloadAllowed() || userAllowedMobileDownloads()) {
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());
}
} else if(userChoseAddToQueue() && !queueIds.contains(item.getId())) {
DBWriter.addQueueItem(context, item);
Toast.makeText(context, R.string.added_to_queue_label, Toast.LENGTH_SHORT).show();
} else {
confirmMobileDownload(context, item);
}
} else if (isDownloading) {
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();
}
} else { // media is downloaded
if (media.isCurrentlyPlaying()) {
new PlaybackServiceStarter(context, media)
.startWhenPrepared(true)
.shouldStream(false)
.start();
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
} else if (media.isCurrentlyPaused()) {
new PlaybackServiceStarter(context, media)
.startWhenPrepared(true)
.shouldStream(false)
.start();
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE);
} else {
DBTasks.playMedia(context, media, false, true, false);
}
}
} else {
if (!item.isPlayed()) {
DBWriter.markItemPlayed(item, FeedItem.PLAYED, true);
}
}
}
private void confirmMobileDownload(final Context context, final FeedItem item) {
MaterialDialog.Builder builder = new MaterialDialog.Builder(context);
builder
.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) -> {
allowMobileDownloadsTimestamp = 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());
}
});
LongList queueIds = DBReader.getQueueIDList();
if(!queueIds.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) -> {
onlyAddToQueueTimeStamp = System.currentTimeMillis();
DBWriter.addQueueItem(context, item);
Toast.makeText(context, R.string.added_to_queue_label, Toast.LENGTH_SHORT).show();
});
}
builder.show();
}
}

View File

@ -7,7 +7,6 @@ import android.support.v4.content.ContextCompat;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.BaseAdapter;
@ -18,6 +17,7 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
@ -31,14 +31,12 @@ import de.danoeh.antennapod.core.util.ThemeUtils;
*/
public class FeedItemlistAdapter extends BaseAdapter {
private final ActionButtonCallback callback;
private final ItemAccess itemAccess;
private final Context context;
private final boolean showFeedtitle;
private final int selectedItemIndex;
/** true if played items should be made partially transparent */
private final boolean makePlayedItemsTransparent;
private final ActionButtonUtils actionButtonUtils;
private static final int SELECTION_NONE = -1;
@ -47,16 +45,13 @@ public class FeedItemlistAdapter extends BaseAdapter {
public FeedItemlistAdapter(Context context,
ItemAccess itemAccess,
ActionButtonCallback callback,
boolean showFeedtitle,
boolean makePlayedItemsTransparent) {
super();
this.callback = callback;
this.context = context;
this.itemAccess = itemAccess;
this.showFeedtitle = showFeedtitle;
this.selectedItemIndex = SELECTION_NONE;
this.actionButtonUtils = new ActionButtonUtils(context);
this.makePlayedItemsTransparent = makePlayedItemsTransparent;
playingBackGroundColor = ThemeUtils.getColorFromAttr(context, R.attr.currently_playing_background);
@ -199,10 +194,11 @@ public class FeedItemlistAdapter extends BaseAdapter {
}
}
actionButtonUtils.configureActionButton(holder.butAction, item, isInQueue);
ItemActionButton actionButton = ItemActionButton.forItem(item, isInQueue);
actionButton.configure(holder.butAction, context);
holder.butAction.setFocusable(false);
holder.butAction.setTag(item);
holder.butAction.setOnClickListener(butActionListener);
} else {
convertView.setVisibility(View.GONE);
@ -210,14 +206,6 @@ public class FeedItemlistAdapter extends BaseAdapter {
return convertView;
}
private final OnClickListener butActionListener = new OnClickListener() {
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
callback.onActionButtonPressed(item, itemAccess.getQueueIds());
}
};
static class Holder {
LinearLayout container;
TextView title;

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
@ -22,8 +23,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.joanzapata.iconify.Iconify;
import org.apache.commons.lang3.ArrayUtils;
@ -32,9 +31,9 @@ import java.lang.ref.WeakReference;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
@ -54,8 +53,6 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
private final WeakReference<MainActivity> mainActivity;
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
private final ItemTouchHelper itemTouchHelper;
private boolean locked;
@ -67,13 +64,10 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
public QueueRecyclerAdapter(MainActivity mainActivity,
ItemAccess itemAccess,
ActionButtonCallback actionButtonCallback,
ItemTouchHelper itemTouchHelper) {
super();
this.mainActivity = new WeakReference<>(mainActivity);
this.itemAccess = itemAccess;
this.actionButtonUtils = new ActionButtonUtils(mainActivity);
this.actionButtonCallback = actionButtonCallback;
this.itemTouchHelper = itemTouchHelper;
locked = UserPreferences.isQueueLocked();
@ -287,10 +281,11 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
}
}
actionButtonUtils.configureActionButton(butSecondary, item, true);
ItemActionButton actionButton = ItemActionButton.forItem(item, true);
actionButton.configure(butSecondary, mainActivity.get());
butSecondary.setFocusable(false);
butSecondary.setTag(item);
butSecondary.setOnClickListener(secondaryActionListener);
new CoverLoader(mainActivity.get())
.withUri(item.getImageLocation())
@ -302,15 +297,6 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
}
private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds());
}
};
public interface ItemAccess {
FeedItem getItem(int position);
int getCount();

View File

@ -31,7 +31,6 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
@ -350,8 +349,7 @@ public class AllEpisodesFragment extends Fragment {
if (episodes != null && episodes.size() > 0) {
if (listAdapter == null) {
MainActivity mainActivity = (MainActivity) getActivity();
listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess,
new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes());
listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes());
listAdapter.setHasStableIds(true);
recyclerView.setAdapter(listAdapter);
emptyView.updateAdapter(listAdapter);

View File

@ -42,7 +42,7 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.CastEnabledActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
@ -61,7 +61,6 @@ import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.Flavors;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.playback.Timeline;
@ -232,9 +231,9 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
if (item == null) {
return;
}
DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getActivity());
actionButtonCallback.onActionButtonPressed(item, item.isTagged(FeedItem.TAG_QUEUE) ?
LongList.of(item.getId()) : new LongList(0));
ItemActionButton actionButton = ItemActionButton.forItem(item, item.isTagged(FeedItem.TAG_QUEUE));
actionButton.onClick(getActivity());
FeedMedia media = item.getMedia();
if (media != null && media.isDownloaded()) {
// playback was started, dialog should close itself

View File

@ -37,7 +37,6 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.FeedInfoActivity;
import de.danoeh.antennapod.activity.FeedSettingsActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
@ -428,7 +427,7 @@ public class ItemlistFragment extends ListFragment {
setListAdapter(null);
setupHeaderView();
setupFooterView();
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(getActivity()), false, true);
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, false, true);
setListAdapter(adapter);
}
refreshHeaderView();

View File

@ -17,7 +17,6 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
@ -216,8 +215,7 @@ public class PlaybackHistoryFragment extends ListFragment {
// played items shoudln't be transparent for this fragment since, *all* items
// in this fragment will, by definition, be played. So it serves no purpose and can make
// it harder to read.
adapter = new FeedItemlistAdapter(getActivity(), itemAccess,
new DefaultActionButtonCallback(getActivity()), true, false);
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, true, false);
setListAdapter(adapter);
}
setListShown(true);

View File

@ -28,7 +28,6 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.QueueRecyclerAdapter;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.DownloadEvent;
@ -525,8 +524,7 @@ public class QueueFragment extends Fragment {
if (queue != null && queue.size() > 0) {
if (recyclerAdapter == null) {
MainActivity activity = (MainActivity) getActivity();
recyclerAdapter = new QueueRecyclerAdapter(activity, itemAccess,
new DefaultActionButtonCallback(activity), itemTouchHelper);
recyclerAdapter = new QueueRecyclerAdapter(activity, itemAccess, itemTouchHelper);
recyclerAdapter.setHasStableIds(true);
recyclerView.setAdapter(recyclerAdapter);
emptyView.updateAdapter(recyclerAdapter);