summaryrefslogtreecommitdiff
path: root/src/de
diff options
context:
space:
mode:
Diffstat (limited to 'src/de')
-rw-r--r--src/de/danoeh/antennapod/activity/AudioplayerActivity.java10
-rw-r--r--src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java107
-rw-r--r--src/de/danoeh/antennapod/util/Converter.java14
-rw-r--r--src/de/danoeh/antennapod/util/playback/PlaybackController.java6
-rw-r--r--src/de/danoeh/antennapod/util/playback/Timeline.java19
5 files changed, 93 insertions, 63 deletions
diff --git a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
index 090c3f1f5..abd383152 100644
--- a/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/src/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -33,11 +33,12 @@ import de.danoeh.antennapod.service.playback.PlaybackService;
import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.util.playback.ExternalMedia;
import de.danoeh.antennapod.util.playback.Playable;
+import de.danoeh.antennapod.util.playback.PlaybackController;
/**
* Activity for playing audio files.
*/
-public class AudioplayerActivity extends MediaplayerActivity {
+public class AudioplayerActivity extends MediaplayerActivity implements ItemDescriptionFragment.ItemDescriptionFragmentCallback {
private static final int POS_COVER = 0;
private static final int POS_DESCR = 1;
private static final int POS_CHAPTERS = 2;
@@ -293,7 +294,7 @@ public class AudioplayerActivity extends MediaplayerActivity {
case POS_DESCR:
if (descriptionFragment == null) {
descriptionFragment = ItemDescriptionFragment
- .newInstance(media, true);
+ .newInstance(media, true, true);
}
currentlyShownFragment = descriptionFragment;
break;
@@ -603,6 +604,11 @@ public class AudioplayerActivity extends MediaplayerActivity {
clearStatusMsg();
}
+ @Override
+ public PlaybackController getPlaybackController() {
+ return controller;
+ }
+
public interface AudioplayerContentFragment {
public void onDataSetChanged(Playable media);
}
diff --git a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
index bf6974982..e2d7f32a2 100644
--- a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -2,8 +2,11 @@ package de.danoeh.antennapod.fragment;
import android.annotation.SuppressLint;
import android.app.Activity;
-import android.content.*;
-import android.content.res.TypedArray;
+import android.content.ActivityNotFoundException;
+import android.content.ClipData;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@@ -12,12 +15,18 @@ import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.util.TypedValue;
-import android.view.*;
+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.webkit.WebViewClient;
import android.widget.Toast;
+
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.feed.FeedItem;
@@ -26,11 +35,12 @@ import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.util.ShareUtils;
import de.danoeh.antennapod.util.ShownotesProvider;
import de.danoeh.antennapod.util.playback.Playable;
-import org.apache.commons.lang3.StringEscapeUtils;
-
-import java.util.concurrent.Callable;
+import de.danoeh.antennapod.util.playback.PlaybackController;
+import de.danoeh.antennapod.util.playback.Timeline;
-/** Displays the description of a Playable object in a Webview. */
+/**
+ * Displays the description of a Playable object in a Webview.
+ */
public class ItemDescriptionFragment extends Fragment {
private static final String TAG = "ItemDescriptionFragment";
@@ -43,6 +53,7 @@ public class ItemDescriptionFragment extends Fragment {
private static final String ARG_FEEDITEM_ID = "arg.feeditem";
private static final String ARG_SAVE_STATE = "arg.saveState";
+ private static final String ARG_HIGHLIGHT_TIMECODES = "arg.highlightTimecodes";
private WebView webvDescription;
@@ -63,21 +74,29 @@ public class ItemDescriptionFragment extends Fragment {
*/
private boolean saveState;
+ /**
+ * True if Fragment should highlight timecodes (e.g. time codes in the HH:MM:SS format).
+ */
+ private boolean highlightTimecodes;
+
public static ItemDescriptionFragment newInstance(Playable media,
- boolean saveState) {
+ boolean saveState,
+ boolean highlightTimecodes) {
ItemDescriptionFragment f = new ItemDescriptionFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_PLAYABLE, media);
args.putBoolean(ARG_SAVE_STATE, saveState);
+ args.putBoolean(ARG_HIGHLIGHT_TIMECODES, highlightTimecodes);
f.setArguments(args);
return f;
}
- public static ItemDescriptionFragment newInstance(FeedItem item, boolean saveState) {
+ public static ItemDescriptionFragment newInstance(FeedItem item, boolean saveState, boolean highlightTimecodes) {
ItemDescriptionFragment f = new ItemDescriptionFragment();
Bundle args = new Bundle();
args.putLong(ARG_FEEDITEM_ID, item.getId());
args.putBoolean(ARG_SAVE_STATE, saveState);
+ args.putBoolean(ARG_HIGHLIGHT_TIMECODES, highlightTimecodes);
f.setArguments(args);
return f;
}
@@ -106,12 +125,22 @@ public class ItemDescriptionFragment extends Fragment {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- e.printStackTrace();
- return false;
+ if (Timeline.isTimecodeLink(url)) {
+ int time = Timeline.getTimecodeLinkTime(url);
+ if (getActivity() != null && getActivity() instanceof ItemDescriptionFragmentCallback) {
+ PlaybackController pc = ((ItemDescriptionFragmentCallback) getActivity()).getPlaybackController();
+ if (pc != null) {
+ pc.seekTo(time);
+ }
+ }
+ } else {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ e.printStackTrace();
+ return true;
+ }
}
return true;
}
@@ -178,6 +207,7 @@ public class ItemDescriptionFragment extends Fragment {
Log.d(TAG, "Creating fragment");
Bundle args = getArguments();
saveState = args.getBoolean(ARG_SAVE_STATE, false);
+ highlightTimecodes = args.getBoolean(ARG_HIGHLIGHT_TIMECODES, false);
}
@@ -229,21 +259,6 @@ public class ItemDescriptionFragment extends Fragment {
}
}
- /**
- * Return the CSS style of the Webview.
- *
- * @param textColor the default color to use for the text in the webview. This
- * value is inserted directly into the CSS String.
- */
- private String applyWebviewStyle(String textColor, String data) {
- final String WEBVIEW_STYLE = "<html><head><style type=\"text/css\"> @font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; 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
@@ -254,10 +269,13 @@ public class ItemDescriptionFragment extends Fragment {
if (BuildConfig.DEBUG)
Log.d(TAG,
"Link of webview was long-pressed. Extra: "
- + r.getExtra());
+ + r.getExtra()
+ );
selectedURL = r.getExtra();
- webvDescription.showContextMenu();
- return true;
+ if (!Timeline.isTimecodeLink(selectedURL)) {
+ webvDescription.showContextMenu();
+ return true;
+ }
}
selectedURL = null;
return false;
@@ -364,22 +382,10 @@ public class ItemDescriptionFragment extends Fragment {
if (BuildConfig.DEBUG)
Log.d(TAG, "Loading Webview");
try {
- Callable<String> shownotesLoadTask = shownotesProvider.loadShownotes();
- final String shownotes = shownotesLoadTask.call();
-
- data = StringEscapeUtils.unescapeHtml4(shownotes);
Activity activity = getActivity();
if (activity != null) {
- TypedArray res = activity
- .getTheme()
- .obtainStyledAttributes(
- new int[]{android.R.attr.textColorPrimary});
- int colorResource = res.getColor(0, 0);
- String colorString = String.format("#%06X",
- 0xFFFFFF & colorResource);
- Log.i(TAG, "text color: " + colorString);
- res.recycle();
- data = applyWebviewStyle(colorString, data);
+ Timeline timeline = new Timeline(activity, shownotesProvider);
+ data = timeline.processShownotes(highlightTimecodes);
} else {
cancel(true);
}
@@ -409,7 +415,8 @@ public class ItemDescriptionFragment extends Fragment {
if (BuildConfig.DEBUG)
Log.d(TAG,
"Saving scroll position: "
- + webvDescription.getScrollY());
+ + webvDescription.getScrollY()
+ );
editor.putInt(PREF_SCROLL_Y, webvDescription.getScrollY());
editor.putString(PREF_PLAYABLE_ID, media.getIdentifier()
.toString());
@@ -447,4 +454,8 @@ public class ItemDescriptionFragment extends Fragment {
}
return false;
}
+
+ public interface ItemDescriptionFragmentCallback {
+ public PlaybackController getPlaybackController();
+ }
}
diff --git a/src/de/danoeh/antennapod/util/Converter.java b/src/de/danoeh/antennapod/util/Converter.java
index bc3d9edd3..f4c2b2f66 100644
--- a/src/de/danoeh/antennapod/util/Converter.java
+++ b/src/de/danoeh/antennapod/util/Converter.java
@@ -80,24 +80,24 @@ public final class Converter {
}
/** Converts long duration string (HH:MM:SS) to milliseconds. */
- public static long durationStringLongToMs(String input) {
+ public static int durationStringLongToMs(String input) {
String[] parts = input.split(":");
if (parts.length != 3) {
return 0;
}
- return Long.valueOf(parts[0]) * 3600 * 1000 +
- Long.valueOf(parts[1]) * 60 * 1000 +
- Long.valueOf(parts[2]) * 1000;
+ return Integer.valueOf(parts[0]) * 3600 * 1000 +
+ Integer.valueOf(parts[1]) * 60 * 1000 +
+ Integer.valueOf(parts[2]) * 1000;
}
/** Converts short duration string (HH:MM) to milliseconds. */
- public static long durationStringShortToMs(String input) {
+ public static int durationStringShortToMs(String input) {
String[] parts = input.split(":");
if (parts.length != 2) {
return 0;
}
- return Long.valueOf(parts[0]) * 3600 * 1000 +
- Long.valueOf(parts[1]) * 1000 * 60;
+ return Integer.valueOf(parts[0]) * 3600 * 1000 +
+ Integer.valueOf(parts[1]) * 1000 * 60;
}
}
diff --git a/src/de/danoeh/antennapod/util/playback/PlaybackController.java b/src/de/danoeh/antennapod/util/playback/PlaybackController.java
index 5783b5bc5..a979ddc1c 100644
--- a/src/de/danoeh/antennapod/util/playback/PlaybackController.java
+++ b/src/de/danoeh/antennapod/util/playback/PlaybackController.java
@@ -680,6 +680,12 @@ public abstract class PlaybackController {
}
}
+ public void seekTo(int time) {
+ if (playbackService != null) {
+ playbackService.seekTo(time);
+ }
+ }
+
public void setVideoSurface(SurfaceHolder holder) {
if (playbackService != null) {
playbackService.setVideoSurface(holder);
diff --git a/src/de/danoeh/antennapod/util/playback/Timeline.java b/src/de/danoeh/antennapod/util/playback/Timeline.java
index 6e00f725c..33ffb054c 100644
--- a/src/de/danoeh/antennapod/util/playback/Timeline.java
+++ b/src/de/danoeh/antennapod/util/playback/Timeline.java
@@ -27,7 +27,7 @@ import de.danoeh.antennapod.util.ShownotesProvider;
public class Timeline {
private static final String TAG = "Timeline";
- private static final String WEBVIEW_STYLE = "<style type=\"text/css\"> @font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; 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; }";
+ private static final String WEBVIEW_STYLE = "<style type=\"text/css\"> @font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } a.timecode { color: #669900; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }";
private ShownotesProvider shownotesProvider;
@@ -56,7 +56,7 @@ public class Timeline {
}
private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))");
- private static final String TIMECODE_LINK = "<a href=\"antennapod://timecode/%d\">%s</a>";
+ private static final String TIMECODE_LINK = "<a class=\"timecode\" href=\"antennapod://timecode/%d\">%s</a>";
private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b(?:(?:(([0-9][0-9])):))?(([0-9][0-9])):(([0-9][0-9]))\\b");
/**
@@ -69,6 +69,7 @@ public class Timeline {
* @return The processed HTML string.
*/
public String processShownotes(final boolean addTimecodes) {
+ final Playable playable = (shownotesProvider instanceof Playable) ? (Playable) shownotesProvider : null;
// load shownotes
@@ -103,9 +104,15 @@ public class Timeline {
while (matcherLong.find()) {
String h = matcherLong.group(1);
String group = matcherLong.group(0);
- long time = (h != null) ? Converter.durationStringLongToMs(group) :
+ int time = (h != null) ? Converter.durationStringLongToMs(group) :
Converter.durationStringShortToMs(group);
- String rep = String.format(TIMECODE_LINK, time, group);
+
+ String rep;
+ if (playable == null || playable.getDuration() > time) {
+ rep = String.format(TIMECODE_LINK, time, group);
+ } else {
+ rep = group;
+ }
matcherLong.appendReplacement(buffer, rep);
}
@@ -129,13 +136,13 @@ public class Timeline {
* Returns the time in milliseconds that is attached to this link or -1
* if the link is no valid timecode link.
*/
- public static long getTimecodeLinkTime(String link) {
+ public static int getTimecodeLinkTime(String link) {
if (isTimecodeLink(link)) {
Matcher m = TIMECODE_LINK_REGEX.matcher(link);
try {
if (m.find()) {
- return Long.valueOf(m.group(1));
+ return Integer.valueOf(m.group(1));
}
} catch (NumberFormatException e) {
e.printStackTrace();