diff options
Diffstat (limited to 'core/src/main/java/de/danoeh')
12 files changed, 135 insertions, 60 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java b/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java index 29e2456b2..1b4cbc0ea 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java +++ b/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java @@ -71,6 +71,11 @@ class UpdateManager { UserPreferences.setEpisodeCleanupValue(oldValueInDays * 24); } // else 0 or special negative values, no change needed } + if (oldVersionCode < 1070197) { + if (prefs.getBoolean("prefMobileUpdate", false)) { + prefs.edit().putString(UserPreferences.PREF_MOBILE_UPDATE, "everything").apply(); + } + } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 39994ec16..f3a43e2d0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -594,7 +594,7 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void setDownloaded(boolean downloaded) { super.setDownloaded(downloaded); - if(item != null && downloaded) { + if(item != null && downloaded && item.isNew()) { item.setPlayed(false); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java index ec10b78aa..552c1b691 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java @@ -31,6 +31,6 @@ public class ApGlideModule extends AppGlideModule { @Override public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { - registry.append(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); + registry.replace(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index bd5276100..2e742e979 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -21,10 +21,8 @@ import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.NetworkUtils; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; +import okhttp3.*; +import okhttp3.internal.http.RealResponseBody; /** * @see com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader @@ -111,10 +109,16 @@ class ApOkHttpUrlLoader implements ModelLoader<String, InputStream> { @Override public Response intercept(Chain chain) throws IOException { - if (NetworkUtils.isDownloadAllowed()) { + if (NetworkUtils.isImageAllowed()) { return chain.proceed(chain.request()); } else { - return null; + return new Response.Builder() + .protocol(Protocol.HTTP_2) + .code(420) + .message("Policy Not Fulfilled") + .body(ResponseBody.create(null, new byte[0])) + .request(chain.request()) + .build(); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java index 3af5e9080..2588cfdee 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java @@ -14,6 +14,7 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; @@ -587,7 +588,7 @@ public class GpodnetService { String result = null; ResponseBody body = null; try { - String credential = Credentials.basic(username, password); + String credential = Credentials.basic(username, password, Charset.forName("UTF-8")); Request authRequest = request.newBuilder().header("Authorization", credential).build(); Response response = httpClient.newCall(authRequest).execute(); checkStatusCode(response); diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 1feecd849..805f0c1b6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -77,7 +77,7 @@ public class UserPreferences { // Network private static final String PREF_ENQUEUE_DOWNLOADED = "prefEnqueueDownloaded"; public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall"; - private static final String PREF_MOBILE_UPDATE = "prefMobileUpdate"; + public static final String PREF_MOBILE_UPDATE = "prefMobileUpdateAllowed"; public static final String PREF_EPISODE_CLEANUP = "prefEpisodeCleanup"; public static final String PREF_PARALLEL_DOWNLOADS = "prefParallelDownloads"; public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize"; @@ -380,8 +380,16 @@ public class UserPreferences { } } + public static String getMobileUpdatesEnabled() { + return prefs.getString(PREF_MOBILE_UPDATE, "images"); + } + public static boolean isAllowMobileUpdate() { - return prefs.getBoolean(PREF_MOBILE_UPDATE, false); + return getMobileUpdatesEnabled().equals("everything"); + } + + public static boolean isAllowMobileImages() { + return isAllowMobileUpdate() || getMobileUpdatesEnabled().equals("images"); } public static int getParallelDownloads() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 83aa4c780..63227e550 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -882,10 +882,6 @@ public final class DBReader { continue; } - // played duration used to be reset when the item is added to the playback history - if (media.getPlaybackCompletionDate() != null) { - feedPlayedTime += media.getDuration() / 1000; - } feedPlayedTime += media.getPlayedDuration() / 1000; if (item.isPlayed()) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index f1410b894..1daa43025 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1253,9 +1253,15 @@ public class PodDBAdapter { } public final int getNumberOfNewItems() { - final String query = "SELECT COUNT(" + KEY_ID + ")" - + " FROM " + TABLE_NAME_FEED_ITEMS - + " WHERE " + KEY_READ + "=" + FeedItem.NEW; + Object[] args = new String[]{ + TABLE_NAME_FEED_ITEMS + "." + KEY_ID, + TABLE_NAME_FEED_ITEMS, + TABLE_NAME_FEEDS, + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID, + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.NEW + + " AND " + TABLE_NAME_FEEDS + "." + KEY_KEEP_UPDATED + " > 0" + }; + final String query = String.format("SELECT COUNT(%s) FROM %s INNER JOIN %s ON %s WHERE %s", args); Cursor c = db.rawQuery(query, null); int result = 0; if (c.moveToFirst()) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java index 6966667bf..6ecca941a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java @@ -74,13 +74,14 @@ public final class Converter { return String.format(Locale.getDefault(), "%02d:%02d:%02d", h, m, s); } - /** Converts milliseconds to a string containing hours and minutes */ - public static String getDurationStringShort(int duration) { - int h = duration / HOURS_MIL; - int rest = duration - h * HOURS_MIL; - int m = rest / MINUTES_MIL; - - return String.format(Locale.getDefault(), "%02d:%02d", h, m); + /** Converts milliseconds to a string containing hours and minutes or minutes and seconds*/ + public static String getDurationStringShort(int duration, boolean durationIsInHours) { + int firstPartBase = durationIsInHours ? HOURS_MIL : MINUTES_MIL; + int firstPart = duration / firstPartBase; + int leftoverFromFirstPart = duration - firstPart * firstPartBase; + int secondPart = leftoverFromFirstPart / (durationIsInHours ? MINUTES_MIL : SECONDS_MIL); + + return String.format(Locale.getDefault(), "%02d:%02d", firstPart, secondPart); } /** Converts long duration string (HH:MM:SS) to milliseconds. */ @@ -94,14 +95,20 @@ public final class Converter { Integer.parseInt(parts[2]) * 1000; } - /** Converts short duration string (HH:MM) to milliseconds. */ - public static int durationStringShortToMs(String input) { + /** + * Converts short duration string (XX:YY) to milliseconds. If durationIsInHours is true then the + * format is HH:MM, otherwise it's MM:SS. + * */ + public static int durationStringShortToMs(String input, boolean durationIsInHours) { String[] parts = input.split(":"); if (parts.length != 2) { return 0; } - return Integer.parseInt(parts[0]) * 3600 * 1000 + - Integer.parseInt(parts[1]) * 1000 * 60; + + int modifier = durationIsInHours ? 60 : 1; + + return Integer.parseInt(parts[0]) * 60 * 1000 * modifier+ + Integer.parseInt(parts[1]) * 1000 * modifier; } /** Converts milliseconds to a localized string containing hours and minutes */ diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java index b34ba196d..9bdd375ce 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java @@ -90,9 +90,13 @@ public class NetworkUtils { return info != null && info.isConnected(); } - public static boolean isDownloadAllowed() { - return UserPreferences.isAllowMobileUpdate() || !NetworkUtils.isNetworkMetered(); - } + public static boolean isDownloadAllowed() { + return UserPreferences.isAllowMobileUpdate() || !NetworkUtils.isNetworkMetered(); + } + + public static boolean isImageAllowed() { + return UserPreferences.isAllowMobileImages() || !NetworkUtils.isNetworkMetered(); + } private static boolean isNetworkMetered() { ConnectivityManager connManager = (ConnectivityManager) context diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 91009a196..6498b9ff1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -407,8 +407,8 @@ public abstract class PlaybackController { pauseResource = res.getResourceId(1, R.drawable.ic_pause_grey600_36dp); res.recycle(); } else { - playResource = R.drawable.ic_av_play_circle_outline_80dp; - pauseResource = R.drawable.ic_av_pause_circle_outline_80dp; + playResource = R.drawable.ic_av_play_white_80dp; + pauseResource = R.drawable.ic_av_pause_white_80dp; } Log.d(TAG, "status: " + status.toString()); @@ -800,7 +800,7 @@ public abstract class PlaybackController { res.getResourceId(0, de.danoeh.antennapod.core.R.drawable.ic_play_arrow_grey600_36dp)); res.recycle(); } else { - getPlayButton().setImageResource(R.drawable.ic_av_play_circle_outline_80dp); + getPlayButton().setImageResource(R.drawable.ic_av_play_white_80dp); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 34cfe6d05..56550bb06 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -7,6 +7,7 @@ import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.util.TypedValue; import org.jsoup.Jsoup; @@ -14,6 +15,7 @@ import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import java.util.ArrayList; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -68,7 +70,7 @@ public class Timeline { private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))"); 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"); + private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b((\\d+):)?(\\d+):(\\d{2})\\b"); private static final Pattern LINE_BREAK_REGEX = Pattern.compile("<br */?>"); @@ -127,35 +129,12 @@ public class Timeline { // apply timecode links if (addTimecodes) { - Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX); - Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); - for (Element element : elementsWithTimeCodes) { - Matcher matcherLong = TIMECODE_REGEX.matcher(element.html()); - StringBuffer buffer = new StringBuffer(); - while (matcherLong.find()) { - String h = matcherLong.group(1); - String group = matcherLong.group(0); - int time = (h != null) ? Converter.durationStringLongToMs(group) : - Converter.durationStringShortToMs(group); - - String rep; - if (playable == null || playable.getDuration() > time) { - rep = String.format(Locale.getDefault(), TIMECODE_LINK, time, group); - } else { - rep = group; - } - matcherLong.appendReplacement(buffer, rep); - } - matcherLong.appendTail(buffer); - - element.html(buffer.toString()); - } + addTimecodes(document, playable); } return document.toString(); } - /** * Returns true if the given link is a timecode link. */ @@ -186,4 +165,69 @@ public class Timeline { public void setShownotesProvider(@NonNull ShownotesProvider shownotesProvider) { this.shownotesProvider = shownotesProvider; } + + private void addTimecodes(Document document, final Playable playable) { + Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX); + Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); + + if (elementsWithTimeCodes.size() == 0) { + // No elements with timecodes + return; + } + + int playableDuration = playable == null ? Integer.MAX_VALUE : playable.getDuration(); + boolean useHourFormat = true; + + if (playableDuration != Integer.MAX_VALUE) { + + // We need to decide if we are going to treat short timecodes as HH:MM or MM:SS. To do + // so we will parse all the short timecodes and see if they fit in the duration. If one + // does not we will use MM:SS, otherwise all will be parsed as HH:MM. + for (Element element : elementsWithTimeCodes) { + Matcher matcherForElement = TIMECODE_REGEX.matcher(element.html()); + while (matcherForElement.find()) { + + // We only want short timecodes right now. + if (matcherForElement.group(1) == null) { + int time = Converter.durationStringShortToMs(matcherForElement.group(0), true); + + // If the parsed timecode is greater then the duration then we know we need to + // use the minute format so we are done. + if (time > playableDuration) { + useHourFormat = false; + break; + } + } + } + + if (!useHourFormat) { + break; + } + } + } + + for (Element element : elementsWithTimeCodes) { + + Matcher matcherForElement = TIMECODE_REGEX.matcher(element.html()); + StringBuffer buffer = new StringBuffer(); + + while (matcherForElement.find()) { + String group = matcherForElement.group(0); + + int time = matcherForElement.group(1) != null + ? Converter.durationStringLongToMs(group) + : Converter.durationStringShortToMs(group, useHourFormat); + + String replacementText = group; + if (time < playableDuration) { + replacementText = String.format(Locale.getDefault(), TIMECODE_LINK, time, group); + } + + matcherForElement.appendReplacement(buffer, replacementText); + } + + matcherForElement.appendTail(buffer); + element.html(buffer.toString()); + } + } } |