diff options
author | Tom Hennen <TomHennen@users.noreply.github.com> | 2015-06-16 20:17:04 -0400 |
---|---|---|
committer | Tom Hennen <TomHennen@users.noreply.github.com> | 2015-06-16 20:17:04 -0400 |
commit | ec4ed747b6de9ab98d3ad31a0256a77b8e8cc25c (patch) | |
tree | 7dfa03fff2e7a7a9fc0d32b74e313668e9b6bcb2 /app/src/main/java/de/danoeh/antennapod/adapter | |
parent | f88c80cced6c3b529a6ef1addafaa930fb41d58f (diff) | |
parent | 3d102449bc2bf78b6c5645ee738e6658c9cb155f (diff) | |
download | AntennaPod-ec4ed747b6de9ab98d3ad31a0256a77b8e8cc25c.zip |
Merge pull request #881 from AntennaPod/develop1.2
Release of 1.2
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod/adapter')
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java | 40 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java (renamed from app/src/main/java/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java) | 46 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java | 103 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java | 102 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java | 50 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java | 177 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java | 18 |
7 files changed, 420 insertions, 116 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java index 8d3e73429..8e347a819 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java @@ -10,7 +10,9 @@ 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.DBReader; import de.danoeh.antennapod.core.storage.DownloadRequester; +import de.danoeh.antennapod.core.util.LongList; /** * Utility methods for the action button that is displayed on the right hand side @@ -26,9 +28,21 @@ public class ActionButtonUtils { Validate.notNull(context); this.context = context; - 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}); - labels = new int[]{R.string.play_label, R.string.cancel_download_label, R.string.download_label, R.string.mark_read_label}; + 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 + }; } /** @@ -50,18 +64,26 @@ public class ActionButtonUtils { butSecondary.setContentDescription(context.getString(labels[1])); } else { // item is not downloaded and not being downloaded - butSecondary.setVisibility(View.VISIBLE); - butSecondary.setImageDrawable(drawables.getDrawable(2)); - butSecondary.setContentDescription(context.getString(labels[2])); + LongList queueIds = DBReader.getQueueIDList(context); + if(DefaultActionButtonCallback.userAllowedMobileDownloads() || + !DefaultActionButtonCallback.userChoseAddToQueue() || queueIds.contains(item.getId())) { + 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 not being downloaded + // item is downloaded butSecondary.setVisibility(View.VISIBLE); if (media.isCurrentlyPlaying()) { butSecondary.setImageDrawable(drawables.getDrawable(3)); } else { - butSecondary - .setImageDrawable(drawables.getDrawable(0)); + butSecondary.setImageDrawable(drawables.getDrawable(0)); } butSecondary.setContentDescription(context.getString(labels[0])); } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java index 1f98ec158..d96326053 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NewEpisodesListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java @@ -22,19 +22,22 @@ import de.danoeh.antennapod.core.util.Converter; /** * List adapter for the list of new episodes */ -public class NewEpisodesListAdapter extends BaseAdapter { +public class AllEpisodesListAdapter extends BaseAdapter { private final Context context; private final ItemAccess itemAccess; private final ActionButtonCallback actionButtonCallback; private final ActionButtonUtils actionButtonUtils; + private final boolean showOnlyNewEpisodes; - public NewEpisodesListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback) { + public AllEpisodesListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback, + boolean showOnlyNewEpisodes) { super(); this.context = context; this.itemAccess = itemAccess; this.actionButtonUtils = new ActionButtonUtils(context); this.actionButtonCallback = actionButtonCallback; + this.showOnlyNewEpisodes = showOnlyNewEpisodes; } @Override @@ -77,8 +80,8 @@ public class NewEpisodesListAdapter extends BaseAdapter { .findViewById(R.id.butSecondaryAction); holder.queueStatus = (ImageView) convertView .findViewById(R.id.imgvInPlaylist); - holder.downloadProgress = (ProgressBar) convertView - .findViewById(R.id.pbar_download_progress); + holder.progress = (ProgressBar) convertView + .findViewById(R.id.pbar_progress); holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage); holder.txtvDuration = (TextView) convertView.findViewById(R.id.txtvDuration); convertView.setTag(holder); @@ -88,7 +91,7 @@ public class NewEpisodesListAdapter extends BaseAdapter { holder.title.setText(item.getTitle()); holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL)); - if (item.isRead()) { + if (showOnlyNewEpisodes || item.isRead() || false == itemAccess.isNew(item)) { holder.statusUnread.setVisibility(View.INVISIBLE); } else { holder.statusUnread.setVisibility(View.VISIBLE); @@ -106,23 +109,27 @@ public class NewEpisodesListAdapter extends BaseAdapter { holder.txtvDuration.setText(""); } + FeedItem.State state = item.getState(); if (isDownloadingMedia) { - holder.downloadProgress.setVisibility(View.VISIBLE); - holder.txtvDuration.setVisibility(View.GONE); - holder.pubDate.setVisibility(View.GONE); + holder.progress.setVisibility(View.VISIBLE); + // item is being downloaded + holder.progress.setProgress(itemAccess.getItemDownloadProgressPercent(item)); + } else if (state == FeedItem.State.PLAYING + || state == FeedItem.State.IN_PROGRESS) { + if (media.getDuration() > 0) { + int progress = (int) (100.0 * media.getPosition() / media.getDuration()); + holder.progress.setProgress(progress); + holder.progress.setVisibility(View.VISIBLE); + } } else { - holder.txtvDuration.setVisibility(View.VISIBLE); - holder.pubDate.setVisibility(View.VISIBLE); - holder.downloadProgress.setVisibility(View.GONE); + holder.progress.setVisibility(View.GONE); } - if (!media.isDownloaded()) { - if (isDownloadingMedia) { - // item is being downloaded - holder.downloadProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item)); - } - } + } else { + holder.progress.setVisibility(View.GONE); + holder.txtvDuration.setVisibility(View.GONE); } + if (itemAccess.isInQueue(item)) { holder.queueStatus.setVisibility(View.VISIBLE); } else { @@ -157,7 +164,7 @@ public class NewEpisodesListAdapter extends BaseAdapter { View statusUnread; ImageView queueStatus; ImageView imageView; - ProgressBar downloadProgress; + ProgressBar progress; TextView txtvDuration; ImageButton butSecondary; } @@ -171,5 +178,8 @@ public class NewEpisodesListAdapter extends BaseAdapter { int getItemDownloadProgressPercent(FeedItem item); boolean isInQueue(FeedItem item); + + boolean isNew(FeedItem item); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java index 14644dd68..223fe17f6 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java @@ -1,6 +1,8 @@ package de.danoeh.antennapod.adapter; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.widget.Toast; @@ -10,43 +12,77 @@ 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.gpoddernet.model.GpodnetEpisodeAction; +import de.danoeh.antennapod.core.preferences.GpodnetPreferences; +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.LongList; +import de.danoeh.antennapod.core.util.NetworkUtils; /** * 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) { - if (item.hasMedia()) { final FeedMedia media = item.getMedia(); boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media); if (!isDownloading && !media.isDownloaded()) { - 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(context); + if (NetworkUtils.isDownloadAllowed(context) || 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.getId()); + 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); - Toast.makeText(context, R.string.download_cancelled_msg, Toast.LENGTH_SHORT).show(); + if(UserPreferences.isEnableAutodownload()) { + DBWriter.setFeedItemAutoDownload(context, 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 (item.hasMedia() && item.getMedia().isCurrentlyPlaying()) { context.sendBroadcast(new Intent(PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE)); @@ -61,7 +97,58 @@ public class DefaultActionButtonCallback implements ActionButtonCallback { } else { if (!item.isRead()) { DBWriter.markItemRead(context, item, true, true); + + if(GpodnetPreferences.loggedIn()) { + // gpodder: send played action + FeedMedia media = item.getMedia(); + GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, GpodnetEpisodeAction.Action.PLAY) + .currentDeviceId() + .currentTimestamp() + .started(media.getDuration() / 1000) + .position(media.getDuration() / 1000) + .total(media.getDuration() / 1000) + .build(); + GpodnetPreferences.enqueueEpisodeAction(action); + } } } } + + private void confirmMobileDownload(final Context context, final FeedItem item) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder + .setTitle(R.string.confirm_mobile_download_dialog_title) + .setMessage(context.getText(R.string.confirm_mobile_download_dialog_message)) + .setPositiveButton(context.getText(R.string.confirm_mobile_download_dialog_enable_temporarily), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int 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(context); + if(!queueIds.contains(item.getId())) { + builder.setNeutralButton(context.getText(R.string.confirm_mobile_download_dialog_only_add_to_queue), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onlyAddToQueueTimeStamp = System.currentTimeMillis(); + DBWriter.addQueueItem(context, item.getId()); + Toast.makeText(context, R.string.added_to_queue_label, Toast.LENGTH_SHORT).show(); + } + }) + .setMessage(context.getText(R.string.confirm_mobile_download_dialog_message_not_in_queue)); + } else { + builder.setMessage(context.getText(R.string.confirm_mobile_download_dialog_message)); + } + builder.create() + .show(); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java index f982e86ce..f29cfdf2f 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java @@ -2,20 +2,34 @@ package de.danoeh.antennapod.adapter; import android.content.Context; import android.text.format.DateUtils; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.Button; import android.widget.TextView; +import android.widget.Toast; + +import com.joanzapata.android.iconify.Iconify; + +import java.util.Date; + import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.service.download.DownloadStatus; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBTasks; +import de.danoeh.antennapod.core.storage.DownloadRequestException; /** Displays a list of DownloadStatus entries. */ public class DownloadLogAdapter extends BaseAdapter { + private final String TAG = "DownloadLogAdapter"; + private Context context; private ItemAccess itemAccess; @@ -35,11 +49,11 @@ public class DownloadLogAdapter extends BaseAdapter { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.downloadlog_item, parent, false); + holder.icon = (TextView) convertView.findViewById(R.id.txtvIcon); + holder.retry = (Button) convertView.findViewById(R.id.btnRetry); + holder.date = (TextView) convertView.findViewById(R.id.txtvDate); holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); holder.type = (TextView) convertView.findViewById(R.id.txtvType); - holder.date = (TextView) convertView.findViewById(R.id.txtvDate); - holder.successful = (TextView) convertView - .findViewById(R.id.txtvStatus); holder.reason = (TextView) convertView .findViewById(R.id.txtvReason); convertView.setTag(holder); @@ -62,33 +76,99 @@ public class DownloadLogAdapter extends BaseAdapter { status.getCompletionDate().getTime(), System.currentTimeMillis(), 0, 0)); if (status.isSuccessful()) { - holder.successful.setTextColor(convertView.getResources().getColor( + holder.icon.setTextColor(convertView.getResources().getColor( R.color.download_success_green)); - holder.successful.setText(R.string.download_successful); + holder.icon.setText("{fa-check-circle}"); + Iconify.addIcons(holder.icon); + holder.retry.setVisibility(View.GONE); holder.reason.setVisibility(View.GONE); } else { - holder.successful.setTextColor(convertView.getResources().getColor( + holder.icon.setTextColor(convertView.getResources().getColor( R.color.download_failed_red)); - holder.successful.setText(R.string.download_failed); + holder.icon.setText("{fa-times-circle}"); + Iconify.addIcons(holder.icon); String reasonText = status.getReason().getErrorString(context); if (status.getReasonDetailed() != null) { reasonText += ": " + status.getReasonDetailed(); } holder.reason.setText(reasonText); holder.reason.setVisibility(View.VISIBLE); + if(status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE && + !newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) { + holder.retry.setVisibility(View.VISIBLE); + holder.retry.setText("{fa-repeat}"); + Iconify.addIcons(holder.retry); + holder.retry.setOnClickListener(clickListener); + ButtonHolder btnHolder; + if(holder.retry.getTag() != null) { + btnHolder = (ButtonHolder) holder.retry.getTag(); + } else { + btnHolder = new ButtonHolder(); + } + btnHolder.typeId = status.getFeedfileType(); + btnHolder.id = status.getFeedfileId(); + holder.retry.setTag(btnHolder); + } else { + holder.retry.setVisibility(View.GONE); + holder.retry.setOnClickListener(null); + holder.retry.setTag(null); + } } return convertView; } + private final View.OnClickListener clickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + ButtonHolder holder = (ButtonHolder) v.getTag(); + if(holder.typeId == Feed.FEEDFILETYPE_FEED) { + Feed feed = DBReader.getFeed(context, holder.id); + feed.setLastUpdate(new Date(0)); // force refresh + try { + DBTasks.refreshFeed(context, feed); + } catch (DownloadRequestException e) { + e.printStackTrace(); + } + } else if(holder.typeId == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + FeedMedia media = DBReader.getFeedMedia(context, holder.id); + try { + DBTasks.downloadFeedItems(context, media.getItem()); + Toast.makeText(context, R.string.status_downloading_label, Toast.LENGTH_SHORT).show(); + } catch (DownloadRequestException e) { + e.printStackTrace(); + DownloadRequestErrorDialogCreator.newRequestErrorDialog(context, e.getMessage()); + } + } else { + Log.wtf(TAG, "Unexpected type id: " + holder.typeId); + } + v.setVisibility(View.GONE); + } + }; + + private boolean newerWasSuccessful(int position, int feedTypeId, long id) { + for (int i = 0; i < position; i++) { + DownloadStatus status = getItem(i); + if (status.getFeedfileType() == feedTypeId && status.getFeedfileId() == id && + status.isSuccessful()) return true; + } + return false; + } + static class Holder { + TextView icon; + Button retry; TextView title; TextView type; TextView date; - TextView successful; TextView reason; } + static class ButtonHolder { + int typeId; + long id; + } + @Override public int getCount() { return itemAccess.getCount(); @@ -104,9 +184,9 @@ public class DownloadLogAdapter extends BaseAdapter { return position; } - public static interface ItemAccess { - public int getCount(); - public DownloadStatus getItem(int position); + public interface ItemAccess { + int getCount(); + DownloadStatus getItem(int position); } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java index d56bfc587..b39e23d42 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java @@ -7,9 +7,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import android.widget.*; +import android.widget.Adapter; +import android.widget.BaseAdapter; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.nineoldandroids.view.ViewHelper; + import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; @@ -105,22 +112,15 @@ public class FeedItemlistAdapter extends BaseAdapter { } holder.title.setText(buffer.toString()); - FeedItem.State state = item.getState(); - switch (state) { - case PLAYING: - holder.statusUnread.setVisibility(View.INVISIBLE); - holder.episodeProgress.setVisibility(View.VISIBLE); - break; - case IN_PROGRESS: - holder.statusUnread.setVisibility(View.INVISIBLE); - holder.episodeProgress.setVisibility(View.VISIBLE); - break; - case NEW: - holder.statusUnread.setVisibility(View.VISIBLE); - break; - default: - holder.statusUnread.setVisibility(View.INVISIBLE); - break; + if(false == item.isRead() && itemAccess.isNew(item)) { + holder.statusUnread.setVisibility(View.VISIBLE); + } else { + holder.statusUnread.setVisibility(View.INVISIBLE); + } + if(item.isRead()) { + ViewHelper.setAlpha(convertView, 0.5f); + } else { + ViewHelper.setAlpha(convertView, 1.0f); } holder.published.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_ABBREV_ALL)); @@ -146,10 +146,10 @@ public class FeedItemlistAdapter extends BaseAdapter { item.getMedia())) { holder.episodeProgress.setVisibility(View.VISIBLE); holder.episodeProgress.setProgress(((ItemAccess) itemAccess).getItemDownloadProgressPercent(item)); - holder.published.setVisibility(View.GONE); } else { - holder.episodeProgress.setVisibility(View.GONE); - holder.published.setVisibility(View.VISIBLE); + if(media.getPosition() == 0) { + holder.episodeProgress.setVisibility(View.GONE); + } } TypedArray typeDrawables = context.obtainStyledAttributes( @@ -211,14 +211,18 @@ public class FeedItemlistAdapter extends BaseAdapter { notifyDataSetChanged(); } - public static interface ItemAccess { - public boolean isInQueue(FeedItem item); + public interface ItemAccess { + + boolean isInQueue(FeedItem item); int getItemDownloadProgressPercent(FeedItem item); int getCount(); FeedItem getItem(int position); + + boolean isNew(FeedItem item); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java index 17cd71f86..0d2d5cfa0 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java @@ -1,41 +1,52 @@ package de.danoeh.antennapod.adapter; import android.content.Context; +import android.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.preference.PreferenceManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.IconTextView; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import com.squareup.picasso.Picasso; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.fragment.AddFeedFragment; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; +import de.danoeh.antennapod.fragment.DownloadsFragment; +import de.danoeh.antennapod.fragment.NewEpisodesFragment; +import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; +import de.danoeh.antennapod.fragment.QueueFragment; /** * BaseAdapter for the navigation drawer */ -public class NavListAdapter extends BaseAdapter { +public class NavListAdapter extends BaseAdapter + implements SharedPreferences.OnSharedPreferenceChangeListener { public static final int VIEW_TYPE_COUNT = 3; public static final int VIEW_TYPE_NAV = 0; public static final int VIEW_TYPE_SECTION_DIVIDER = 1; public static final int VIEW_TYPE_SUBSCRIPTION = 2; - public static final int[] NAV_TITLES = { - R.string.queue_label, - R.string.new_episodes_label, - R.string.all_episodes_label, - R.string.downloads_label, - R.string.playback_history_label, - R.string.add_feed_label}; - - private final Drawable[] drawables; - - public static final int SUBSCRIPTION_OFFSET = 1 + NAV_TITLES.length; + private static List<String> tags; + private static String[] titles; private ItemAccess itemAccess; private Context context; @@ -44,28 +55,79 @@ public class NavListAdapter extends BaseAdapter { this.itemAccess = itemAccess; this.context = context; - TypedArray ta = context.obtainStyledAttributes(new int[]{ - R.attr.stat_playlist, - R.attr.ic_new, - R.attr.feed, - R.attr.av_download, - R.attr.ic_history, - R.attr.content_new}); - drawables = new Drawable[]{ta.getDrawable(0), ta.getDrawable(1), ta.getDrawable(2), - ta.getDrawable(3), ta.getDrawable(4), ta.getDrawable(5)}; + titles = context.getResources().getStringArray(R.array.nav_drawer_titles); + loadItems(); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.registerOnSharedPreferenceChangeListener(this); + } + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals(UserPreferences.PREF_HIDDEN_DRAWER_ITEMS)) { + loadItems(); + } + } + + private void loadItems() { + List<String> newTags = new ArrayList<String>(Arrays.asList(MainActivity.NAV_DRAWER_TAGS)); + List<String> hiddenFragments = UserPreferences.getHiddenDrawerItems(); + for(String hidden : hiddenFragments) { + newTags.remove(hidden); + } + tags = newTags; + notifyDataSetChanged(); + } + + public String getLabel(String tag) { + int index = ArrayUtils.indexOf(MainActivity.NAV_DRAWER_TAGS, tag); + return titles[index]; + } + + private Drawable getDrawable(String tag) { + int icon; + switch (tag) { + case QueueFragment.TAG: + icon = R.attr.stat_playlist; + break; + case NewEpisodesFragment.TAG: + icon = R.attr.ic_new; + break; + case AllEpisodesFragment.TAG: + icon = R.attr.feed; + break; + case DownloadsFragment.TAG: + icon = R.attr.av_download; + break; + case PlaybackHistoryFragment.TAG: + icon = R.attr.ic_history; + break; + case AddFeedFragment.TAG: + icon = R.attr.content_new; + break; + default: + return null; + } + TypedArray ta = context.obtainStyledAttributes(new int[] { icon } ); + Drawable result = ta.getDrawable(0); ta.recycle(); + return result; + } + + public List<String> getTags() { + return Collections.unmodifiableList(tags); } + @Override public int getCount() { - return NAV_TITLES.length + 1 + itemAccess.getCount(); + return getSubscriptionOffset() + itemAccess.getCount(); } @Override public Object getItem(int position) { int viewType = getItemViewType(position); if (viewType == VIEW_TYPE_NAV) { - return context.getString(NAV_TITLES[position]); + return getLabel(tags.get(position)); } else if (viewType == VIEW_TYPE_SECTION_DIVIDER) { return ""; } else { @@ -80,9 +142,9 @@ public class NavListAdapter extends BaseAdapter { @Override public int getItemViewType(int position) { - if (0 <= position && position < NAV_TITLES.length) { + if (0 <= position && position < tags.size()) { return VIEW_TYPE_NAV; - } else if (position < NAV_TITLES.length + 1) { + } else if (position < getSubscriptionOffset()) { return VIEW_TYPE_SECTION_DIVIDER; } else { return VIEW_TYPE_SUBSCRIPTION; @@ -94,6 +156,11 @@ public class NavListAdapter extends BaseAdapter { return VIEW_TYPE_COUNT; } + public int getSubscriptionOffset() { + return tags.size() > 0 ? tags.size() + 1 : 0; + } + + @Override public View getView(int position, View convertView, ViewGroup parent) { int viewType = getItemViewType(position); @@ -103,7 +170,7 @@ public class NavListAdapter extends BaseAdapter { } else if (viewType == VIEW_TYPE_SECTION_DIVIDER) { v = getSectionDividerView(convertView, parent); } else { - v = getFeedView(position - SUBSCRIPTION_OFFSET, convertView, parent); + v = getFeedView(position - getSubscriptionOffset(), convertView, parent); } if (v != null && viewType != VIEW_TYPE_SECTION_DIVIDER) { TextView txtvTitle = (TextView) v.findViewById(R.id.txtvTitle); @@ -125,9 +192,9 @@ public class NavListAdapter extends BaseAdapter { convertView = inflater.inflate(R.layout.nav_listitem, parent, false); + holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); holder.count = (TextView) convertView.findViewById(R.id.txtvCount); - holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); convertView.setTag(holder); } else { holder = (NavHolder) convertView.getTag(); @@ -135,7 +202,7 @@ public class NavListAdapter extends BaseAdapter { holder.title.setText(title); - if (NAV_TITLES[position] == R.string.queue_label) { + if (tags.get(position).equals(QueueFragment.TAG)) { int queueSize = itemAccess.getQueueSize(); if (queueSize > 0) { holder.count.setVisibility(View.VISIBLE); @@ -143,8 +210,8 @@ public class NavListAdapter extends BaseAdapter { } else { holder.count.setVisibility(View.GONE); } - } else if (NAV_TITLES[position] == R.string.new_episodes_label) { - int unreadItems = itemAccess.getNumberOfUnreadItems(); + } else if (tags.get(position).equals(NewEpisodesFragment.TAG)) { + int unreadItems = itemAccess.getNumberOfNewItems(); if (unreadItems > 0) { holder.count.setVisibility(View.VISIBLE); holder.count.setText(String.valueOf(unreadItems)); @@ -155,7 +222,7 @@ public class NavListAdapter extends BaseAdapter { holder.count.setVisibility(View.GONE); } - holder.image.setImageDrawable(drawables[position]); + holder.image.setImageDrawable(getDrawable(tags.get(position))); return convertView; } @@ -183,45 +250,63 @@ public class NavListAdapter extends BaseAdapter { convertView = inflater.inflate(R.layout.nav_feedlistitem, parent, false); - holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); holder.image = (ImageView) convertView.findViewById(R.id.imgvCover); + holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); + holder.failure = (IconTextView) convertView.findViewById(R.id.itxtvFailure); + holder.count = (TextView) convertView.findViewById(R.id.txtvCount); convertView.setTag(holder); } else { holder = (FeedHolder) convertView.getTag(); } - holder.title.setText(feed.getTitle()); - Picasso.with(context) .load(feed.getImageUri()) .fit() .into(holder.image); + holder.title.setText(feed.getTitle()); + + + if(feed.hasLastUpdateFailed()) { + RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) holder.title.getLayoutParams(); + p.addRule(RelativeLayout.LEFT_OF, R.id.itxtvFailure); + holder.failure.setVisibility(View.VISIBLE); + } else { + RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) holder.title.getLayoutParams(); + p.addRule(RelativeLayout.LEFT_OF, R.id.txtvCount); + holder.failure.setVisibility(View.GONE); + } + int feedUnreadItems = itemAccess.getNumberOfUnreadFeedItems(feed.getId()); + if(feedUnreadItems > 0) { + holder.count.setVisibility(View.VISIBLE); + holder.count.setText(String.valueOf(feedUnreadItems)); + holder.count.setTypeface(holder.title.getTypeface()); + } else { + holder.count.setVisibility(View.GONE); + } return convertView; } static class NavHolder { + ImageView image; TextView title; TextView count; - ImageView image; } static class FeedHolder { - TextView title; ImageView image; + TextView title; + IconTextView failure; + TextView count; } - public interface ItemAccess { - public int getCount(); - - public Feed getItem(int position); - - public int getSelectedItemIndex(); - - public int getQueueSize(); - - public int getNumberOfUnreadItems(); + int getCount(); + Feed getItem(int position); + int getSelectedItemIndex(); + int getQueueSize(); + int getNumberOfNewItems(); + int getNumberOfUnreadFeedItems(long feedId); } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java index a256dc129..bba5a00a9 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueListAdapter.java @@ -14,9 +14,9 @@ import android.widget.TextView; import com.squareup.picasso.Picasso; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.feed.EventDistributor; 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.DownloadRequester; import de.danoeh.antennapod.core.util.Converter; @@ -31,6 +31,8 @@ public class QueueListAdapter extends BaseAdapter { private final ActionButtonCallback actionButtonCallback; private final ActionButtonUtils actionButtonUtils; + private boolean locked; + public QueueListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback) { super(); @@ -38,6 +40,12 @@ public class QueueListAdapter extends BaseAdapter { this.itemAccess = itemAccess; this.actionButtonUtils = new ActionButtonUtils(context); this.actionButtonCallback = actionButtonCallback; + locked = UserPreferences.isQueueLocked(); + } + + public void setLocked(boolean locked) { + this.locked = locked; + notifyDataSetChanged(); } @Override @@ -67,6 +75,7 @@ public class QueueListAdapter extends BaseAdapter { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.queue_listitem, parent, false); + holder.dragHandle = (ImageView) convertView.findViewById(R.id.drag_handle); holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage); holder.title = (TextView) convertView.findViewById(R.id.txtvTitle); holder.pubDate = (TextView) convertView.findViewById(R.id.txtvPubDate); @@ -83,6 +92,12 @@ public class QueueListAdapter extends BaseAdapter { holder = (Holder) convertView.getTag(); } + if(locked) { + holder.dragHandle.setVisibility(View.GONE); + } else { + holder.dragHandle.setVisibility(View.VISIBLE); + } + holder.title.setText(item.getTitle()); FeedMedia media = item.getMedia(); @@ -143,6 +158,7 @@ public class QueueListAdapter extends BaseAdapter { static class Holder { + ImageView dragHandle; ImageView imageView; TextView title; TextView pubDate; |