diff options
-rw-r--r-- | res/layout/external_itemlist_item.xml | 45 | ||||
-rw-r--r-- | res/values/ids.xml | 6 | ||||
-rw-r--r-- | res/values/strings.xml | 6 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java | 48 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java | 106 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/service/PlaybackService.java | 7 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/service/download/HttpDownloader.java | 15 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/util/ShareUtils.java | 2 |
8 files changed, 223 insertions, 12 deletions
diff --git a/res/layout/external_itemlist_item.xml b/res/layout/external_itemlist_item.xml index 347a75e24..4367b5d9f 100644 --- a/res/layout/external_itemlist_item.xml +++ b/res/layout/external_itemlist_item.xml @@ -80,4 +80,49 @@ android:layout_marginTop="4dp" android:layout_toLeftOf="@id/butAction" /> + <TextView + android:id="@+id/statusUnread" + android:layout_width="wrap_content" + android:layout_height="18dp" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_margin="8dp" + android:background="@color/status_unread" + android:gravity="center" + android:minWidth="@dimen/status_indicator_width" + android:text="@string/new_label" + android:textAlignment="center" + android:textColor="@color/white" + android:textSize="@dimen/text_size_micro" + android:textStyle="bold" /> + + <ImageView + android:id="@+id/statusPlaying" + android:layout_width="@dimen/status_indicator_width" + android:layout_height="18dp" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_margin="8dp" + android:background="@color/status_playing" + android:gravity="center" + android:padding="2dp" + android:src="@drawable/av_play_dark" /> + + <TextView + android:id="@+id/statusInProgress" + android:layout_width="wrap_content" + android:layout_height="18dp" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_margin="8dp" + android:background="@color/status_progress" + android:gravity="center" + android:minWidth="@dimen/status_indicator_width" + android:paddingLeft="2dp" + android:paddingRight="2dp" + android:textAlignment="center" + android:textColor="@color/white" + android:textSize="@dimen/text_size_micro" + android:textStyle="bold" /> + </RelativeLayout>
\ No newline at end of file diff --git a/res/values/ids.xml b/res/values/ids.xml index 1b717b4c5..476969668 100644 --- a/res/values/ids.xml +++ b/res/values/ids.xml @@ -9,6 +9,10 @@ <item name="enqueue_all_item" type="id"/> <item name="download_all_item" type="id"/> <item name="clear_history_item" type="id"/> + <item name="open_in_browser_item" type="id"/> + <item name="copy_url_item" type="id"/> + <item name="share_url_item" type="id"/> <item name="organize_queue_item" type="id"/> - <item name="drag_handle" type="id" /> + <item name="drag_handle" type="id"/> + </resources>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 62d60c5ac..83e4c3427 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -14,6 +14,12 @@ <string name="download_log_label">Download log</string> <string name="playback_history_label">Playback history</string> + <!-- Webview actions --> + <string name="open_in_browser_label">Open in browser</string> + <string name="copy_url_label">Copy URL</string> + <string name="share_url_label">Share URL</string> + <string name="copied_url_msg">Copied URL to clipboard.</string> + <!-- Playback history --> <string name="clear_history_label">Clear history</string> diff --git a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java index 75ae96ebe..2670dfa44 100644 --- a/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java +++ b/src/de/danoeh/antennapod/adapter/ExternalEpisodesListAdapter.java @@ -106,6 +106,12 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter { .findViewById(R.id.imgvFeedimage); holder.butAction = (ImageButton) convertView .findViewById(R.id.butAction); + holder.statusPlaying = (View) convertView + .findViewById(R.id.statusPlaying); + holder.statusUnread = (View) convertView + .findViewById(R.id.statusUnread); + holder.statusInProgress = (TextView) convertView + .findViewById(R.id.statusInProgress); convertView.setTag(holder); } else { holder = (Holder) convertView.getTag(); @@ -113,6 +119,39 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter { holder.title.setText(item.getTitle()); holder.feedTitle.setText(item.getFeed().getTitle()); + + if (groupPosition == GROUP_POS_QUEUE) { + FeedItem.State state = item.getState(); + switch (state) { + case PLAYING: + holder.statusPlaying.setVisibility(View.VISIBLE); + holder.statusUnread.setVisibility(View.GONE); + holder.statusInProgress.setVisibility(View.GONE); + break; + case IN_PROGRESS: + holder.statusPlaying.setVisibility(View.GONE); + holder.statusUnread.setVisibility(View.GONE); + holder.statusInProgress.setVisibility(View.VISIBLE); + holder.statusInProgress.setText(Converter + .getDurationStringLong(item.getMedia().getPosition())); + break; + case NEW: + holder.statusPlaying.setVisibility(View.GONE); + holder.statusUnread.setVisibility(View.VISIBLE); + holder.statusInProgress.setVisibility(View.GONE); + break; + default: + holder.statusPlaying.setVisibility(View.GONE); + holder.statusUnread.setVisibility(View.GONE); + holder.statusInProgress.setVisibility(View.GONE); + break; + } + } else { + holder.statusPlaying.setVisibility(View.GONE); + holder.statusUnread.setVisibility(View.GONE); + holder.statusInProgress.setVisibility(View.GONE); + } + FeedMedia media = item.getMedia(); if (media != null) { TypedArray drawables = context.obtainStyledAttributes(new int[] { @@ -121,7 +160,8 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter { if (!media.isDownloaded()) { if (DownloadRequester.getInstance().isDownloadingFile(media)) { holder.downloadStatus.setVisibility(View.VISIBLE); - holder.downloadStatus.setImageDrawable(drawables.getDrawable(1)); + holder.downloadStatus.setImageDrawable(drawables + .getDrawable(1)); } else { holder.downloadStatus.setVisibility(View.GONE); } @@ -129,7 +169,8 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter { + Converter.byteToString(media.getSize())); } else { holder.downloadStatus.setVisibility(View.VISIBLE); - holder.downloadStatus.setImageDrawable(drawables.getDrawable(0)); + holder.downloadStatus + .setImageDrawable(drawables.getDrawable(0)); holder.lenSize.setText(context .getString(R.string.length_prefix) + Converter.getDurationStringLong(media.getDuration())); @@ -165,6 +206,9 @@ public class ExternalEpisodesListAdapter extends BaseExpandableListAdapter { ImageView downloadStatus; ImageView feedImage; ImageButton butAction; + View statusUnread; + View statusPlaying; + TextView statusInProgress; } @Override diff --git a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 387823348..52a5400ef 100644 --- a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -4,16 +4,28 @@ import org.apache.commons.lang3.StringEscapeUtils; import android.annotation.SuppressLint; import android.app.Activity; +import android.content.ClipData; +import android.content.Context; +import android.content.Intent; import android.content.res.TypedArray; +import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.util.Log; +import android.util.TypedValue; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebView; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.Toast; import com.actionbarsherlock.app.SherlockFragment; @@ -23,6 +35,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.feed.Feed; import de.danoeh.antennapod.feed.FeedItem; import de.danoeh.antennapod.feed.FeedManager; +import de.danoeh.antennapod.util.ShareUtils; /** Displays the description of a FeedItem in a Webview. */ public class ItemDescriptionFragment extends SherlockFragment { @@ -39,6 +52,9 @@ public class ItemDescriptionFragment extends SherlockFragment { private String descriptionRef; private String contentEncodedRef; + /** URL that was selected via long-press. */ + private String selectedURL; + public static ItemDescriptionFragment newInstance(FeedItem item) { ItemDescriptionFragment f = new ItemDescriptionFragment(); Bundle args = new Bundle(); @@ -64,7 +80,11 @@ public class ItemDescriptionFragment extends SherlockFragment { webvDescription.setBackgroundColor(0); } webvDescription.getSettings().setUseWideViewPort(false); - webvDescription.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); + webvDescription.getSettings().setLayoutAlgorithm( + LayoutAlgorithm.NARROW_COLUMNS); + webvDescription.getSettings().setLoadWithOverviewMode(true); + webvDescription.setOnLongClickListener(webViewLongClickListener); + registerForContextMenu(webvDescription); return webvDescription; } @@ -175,9 +195,85 @@ public class ItemDescriptionFragment extends SherlockFragment { * the default color to use for the text in the webview. This * value is inserted directly into the CSS String. * */ - private String getWebViewStyle(String textColor) { - final String WEBVIEW_STYLE = "<head><style type=\"text/css\"> * { color: %s; font-family: Helvetica; line-height: 1.5em; font-size: 12pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; }</style></head>"; - return String.format(WEBVIEW_STYLE, textColor); + private String applyWebviewStyle(String textColor, String data) { + final String WEBVIEW_STYLE = "<html><head><style type=\"text/css\"> * { color: %s; font-family: Helvetica; line-height: 1.5em; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }</style></head><body>%s</body></html>"; + final int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics()); + return String.format(WEBVIEW_STYLE, textColor, "100%", pageMargin, pageMargin, pageMargin, pageMargin, data); + } + + private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + WebView.HitTestResult r = webvDescription.getHitTestResult(); + if (r != null + && r.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) { + if (AppConfig.DEBUG) + Log.d(TAG, + "Link of webview was long-pressed. Extra: " + + r.getExtra()); + selectedURL = r.getExtra(); + webvDescription.showContextMenu(); + return true; + } + selectedURL = null; + return false; + } + }; + + @SuppressLint("NewApi") + @Override + public boolean onContextItemSelected(MenuItem item) { + boolean handled = selectedURL != null; + if (selectedURL != null) { + switch (item.getItemId()) { + case R.id.open_in_browser_item: + Uri uri = Uri.parse(selectedURL); + getActivity() + .startActivity(new Intent(Intent.ACTION_VIEW, uri)); + break; + case R.id.share_url_item: + ShareUtils.shareLink(getActivity(), selectedURL); + break; + case R.id.copy_url_item: + if (android.os.Build.VERSION.SDK_INT >= 11) { + ClipData clipData = ClipData.newPlainText(selectedURL, + selectedURL); + android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity() + .getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(clipData); + } else { + android.text.ClipboardManager cm = (android.text.ClipboardManager) getActivity() + .getSystemService(Context.CLIPBOARD_SERVICE); + cm.setText(selectedURL); + } + Toast t = Toast.makeText(getActivity(), R.string.copied_url_msg, Toast.LENGTH_SHORT); + t.show(); + break; + default: + handled = false; + break; + + } + selectedURL = null; + } + return handled; + + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + if (selectedURL != null) { + super.onCreateContextMenu(menu, v, menuInfo); + menu.add(Menu.NONE, R.id.open_in_browser_item, Menu.NONE, + R.string.open_in_browser_label); + menu.add(Menu.NONE, R.id.copy_url_item, Menu.NONE, + R.string.copy_url_label); + menu.add(Menu.NONE, R.id.share_url_item, Menu.NONE, + R.string.share_url_label); + menu.setHeaderTitle(selectedURL); + } } private AsyncTask<Void, Void, Void> createLoader() { @@ -239,7 +335,7 @@ public class ItemDescriptionFragment extends SherlockFragment { 0xFFFFFF & colorResource); Log.i(TAG, "text color: " + colorString); res.recycle(); - data = getWebViewStyle(colorString) + data; + data = applyWebviewStyle(colorString, data); } else { cancel(true); } diff --git a/src/de/danoeh/antennapod/service/PlaybackService.java b/src/de/danoeh/antennapod/service/PlaybackService.java index c43668260..62370ff6d 100644 --- a/src/de/danoeh/antennapod/service/PlaybackService.java +++ b/src/de/danoeh/antennapod/service/PlaybackService.java @@ -449,7 +449,7 @@ public class PlaybackService extends Service { case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: if (status == PlayerStatus.PLAYING) { - pause(false, true); + pause(true, true); } else if (status == PlayerStatus.PAUSED) { play(); } else if (status == PlayerStatus.PREPARING) { @@ -469,7 +469,7 @@ public class PlaybackService extends Service { break; case KeyEvent.KEYCODE_MEDIA_PAUSE: if (status == PlayerStatus.PLAYING) { - pause(false, true); + pause(true, true); } break; } @@ -796,6 +796,7 @@ public class PlaybackService extends Service { player.pause(); if (abandonFocus) { audioManager.abandonAudioFocus(audioFocusChangeListener); + pausedBecauseOfTransientAudiofocusLoss = false; disableSleepTimer(); } cancelPositionSaver(); @@ -1158,7 +1159,7 @@ public class PlaybackService extends Service { .getDefaultSharedPreferences(getApplicationContext()) .getBoolean(PodcastApp.PREF_PAUSE_ON_HEADSET_DISCONNECT, false); if (pauseOnDisconnect && status == PlayerStatus.PLAYING) { - pause(false, true); + pause(true, true); } } diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java index 4a4d9e58b..7cb487c1a 100644 --- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java +++ b/src/de/danoeh/antennapod/service/download/HttpDownloader.java @@ -163,6 +163,7 @@ public class HttpDownloader extends Downloader { status.setReasonDetailed(reasonDetailed); status.setDone(true); status.setSuccessful(false); + cleanup(); } private void onCancelled() { @@ -172,6 +173,20 @@ public class HttpDownloader extends Downloader { status.setDone(true); status.setSuccessful(false); status.setCancelled(true); + cleanup(); + } + + /** Deletes unfinished downloads. */ + private void cleanup() { + if (status != null && status.getFeedFile() != null && status.getFeedFile().getFile_url() != null) { + File dest = new File(status.getFeedFile().getFile_url()); + if (dest.exists()) { + boolean rc = dest.delete(); + if (AppConfig.DEBUG) Log.d(TAG, "Deleted file " + dest.getName() + "; Result: " + rc); + } else { + if (AppConfig.DEBUG) Log.d(TAG, "cleanup() didn't delete file: does not exist."); + } + } } } diff --git a/src/de/danoeh/antennapod/util/ShareUtils.java b/src/de/danoeh/antennapod/util/ShareUtils.java index 0317adcd5..941fc62ae 100644 --- a/src/de/danoeh/antennapod/util/ShareUtils.java +++ b/src/de/danoeh/antennapod/util/ShareUtils.java @@ -11,7 +11,7 @@ public class ShareUtils { private ShareUtils() {} - private static void shareLink(Context context, String link) { + public static void shareLink(Context context, String link) { Intent i = new Intent(Intent.ACTION_SEND); i.setType("text/plain"); i.putExtra(Intent.EXTRA_SUBJECT, "Sharing URL"); |