summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorTom Hennen <tom.hennen@gmail.com>2015-08-15 14:39:11 -0400
committerTom Hennen <tom.hennen@gmail.com>2015-08-15 14:39:11 -0400
commit0dcc1a33f171471d09dd64093df385a173a95271 (patch)
tree2b63d30574e093c717a8b9021441724339c77cab /core/src
parentbf2ba3b7c72f00e70d64fbd938a8f028cb75f3cd (diff)
parent928c438268ec4eab6f05bf2aa60f24e2d10156c1 (diff)
downloadAntennaPod-0dcc1a33f171471d09dd64093df385a173a95271.zip
merged version 1.3 to master
Diffstat (limited to 'core/src')
-rw-r--r--core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java27
-rw-r--r--core/src/main/AndroidManifest.xml3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ApplicationCallbacks.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java27
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java (renamed from core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java)2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java527
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java26
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java24
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java25
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java55
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java48
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java33
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java11
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java141
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java267
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java19
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java193
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java665
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java19
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java76
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java76
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java81
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java26
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java14
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java139
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java72
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java154
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java82
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java132
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java24
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java355
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/Converter.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java40
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java31
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java49
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java49
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java2
-rw-r--r--core/src/main/res/values-az/strings.xml4
-rw-r--r--core/src/main/res/values-ca/strings.xml9
-rw-r--r--core/src/main/res/values-cs-rCZ/strings.xml88
-rw-r--r--core/src/main/res/values-da/strings.xml9
-rw-r--r--core/src/main/res/values-de/strings.xml84
-rw-r--r--core/src/main/res/values-es-rES/strings.xml4
-rw-r--r--core/src/main/res/values-es/strings.xml84
-rw-r--r--core/src/main/res/values-fr/strings.xml103
-rw-r--r--core/src/main/res/values-hi-rIN/strings.xml4
-rw-r--r--core/src/main/res/values-it-rIT/strings.xml55
-rw-r--r--core/src/main/res/values-iw-rIL/strings.xml15
-rw-r--r--core/src/main/res/values-ja/strings.xml81
-rw-r--r--core/src/main/res/values-ko/strings.xml81
-rw-r--r--core/src/main/res/values-nl/strings.xml4
-rw-r--r--core/src/main/res/values-no/strings.xml31
-rw-r--r--core/src/main/res/values-pl-rPL/strings.xml9
-rw-r--r--core/src/main/res/values-pt-rBR/strings.xml4
-rw-r--r--core/src/main/res/values-pt/strings.xml106
-rw-r--r--core/src/main/res/values-ro-rRO/strings.xml4
-rw-r--r--core/src/main/res/values-ru/strings.xml31
-rw-r--r--core/src/main/res/values-sv-rSE/strings.xml190
-rw-r--r--core/src/main/res/values-tr/strings.xml55
-rw-r--r--core/src/main/res/values-uk-rUA/strings.xml87
-rw-r--r--core/src/main/res/values-zh-rCN/strings.xml7
-rw-r--r--core/src/main/res/values/arrays.xml77
-rw-r--r--core/src/main/res/values/colors.xml1
-rw-r--r--core/src/main/res/values/strings.xml202
-rw-r--r--core/src/main/res/values/styles.xml4
80 files changed, 2986 insertions, 2130 deletions
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java
index 2a2d6414a..2727b1447 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java
+++ b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java
@@ -13,6 +13,7 @@ public class DateUtilsTest extends AndroidTestCase {
public void testParseDateWithMicroseconds() throws Exception {
GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 13, 31, 4);
+ exp.setTimeZone(TimeZone.getTimeZone("UTC"));
Date expected = new Date(exp.getTimeInMillis() + 963);
Date actual = DateUtils.parse("2015-03-28T13:31:04.963870");
assertEquals(expected, actual);
@@ -20,6 +21,7 @@ public class DateUtilsTest extends AndroidTestCase {
public void testParseDateWithCentiseconds() throws Exception {
GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 13, 31, 4);
+ exp.setTimeZone(TimeZone.getTimeZone("UTC"));
Date expected = new Date(exp.getTimeInMillis() + 960);
Date actual = DateUtils.parse("2015-03-28T13:31:04.96");
assertEquals(expected, actual);
@@ -27,6 +29,7 @@ public class DateUtilsTest extends AndroidTestCase {
public void testParseDateWithDeciseconds() throws Exception {
GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 13, 31, 4);
+ exp.setTimeZone(TimeZone.getTimeZone("UTC"));
Date expected = new Date(exp.getTimeInMillis() + 900);
Date actual = DateUtils.parse("2015-03-28T13:31:04.9");
assertEquals(expected.getTime()/1000, actual.getTime()/1000);
@@ -66,6 +69,14 @@ public class DateUtilsTest extends AndroidTestCase {
assertEquals(expected, actual);
}
+ public void testParseDateWithTimezoneName2() throws Exception {
+ GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 6, 31, 0);
+ exp.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Date expected = new Date(exp.getTimeInMillis());
+ Date actual = DateUtils.parse("Sat, 28 Mar 2015 01:31 EST");
+ assertEquals(expected, actual);
+ }
+
public void testParseDateWithTimeZoneOffset() throws Exception {
GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 12, 16, 12);
exp.setTimeZone(TimeZone.getTimeZone("UTC"));
@@ -74,4 +85,20 @@ public class DateUtilsTest extends AndroidTestCase {
assertEquals(expected, actual);
}
+ public void testAsctime() throws Exception {
+ GregorianCalendar exp = new GregorianCalendar(2011, 4, 25, 12, 33, 00);
+ exp.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Date expected = new Date(exp.getTimeInMillis());
+ Date actual = DateUtils.parse("Wed, 25 May 2011 12:33:00");
+ assertEquals(expected, actual);
+ }
+
+ public void testMultipleConsecutiveSpaces() throws Exception {
+ GregorianCalendar exp = new GregorianCalendar(2010, 2, 23, 6, 6, 26);
+ exp.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Date expected = new Date(exp.getTimeInMillis());
+ Date actual = DateUtils.parse("Tue, 23 Mar 2010 01:06:26 -0500");
+ assertEquals(expected, actual);
+ }
+
}
diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml
index 3ec519844..17dcb4ad8 100644
--- a/core/src/main/AndroidManifest.xml
+++ b/core/src/main/AndroidManifest.xml
@@ -23,6 +23,9 @@
<service
android:name=".service.GpodnetSyncService"
android:enabled="true" />
+ <service
+ android:name=".service.FeedMediaSizeService"
+ android:enabled="true" />
<receiver
android:name=".receiver.MediaButtonReceiver"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ApplicationCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/ApplicationCallbacks.java
index 3bc1ce4eb..1064e98ac 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ApplicationCallbacks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ApplicationCallbacks.java
@@ -20,5 +20,4 @@ public interface ApplicationCallbacks {
*/
public Intent getStorageErrorActivity(Context context);
- public void setUpdateInterval(long updateInterval);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
index 1a2671555..6619e706b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
@@ -21,7 +21,5 @@ public class ClientConfig {
public static FlattrCallbacks flattrCallbacks;
- public static StorageCallbacks storageCallbacks;
-
public static DBTasksCallbacks dbTasksCallbacks;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java
deleted file mode 100644
index 5d1a0fffc..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.danoeh.antennapod.core;
-
-import android.database.sqlite.SQLiteDatabase;
-
-/**
- * Callbacks for the classes in the storage package of the core module.
- */
-public interface StorageCallbacks {
-
- /**
- * Returns the current version of the database.
- *
- * @return The non-negative version number of the database.
- */
- public int getDatabaseVersion();
-
- /**
- * Upgrades the given database from an old version to a newer version.
- *
- * @param db The database that is supposed to be upgraded.
- * @param oldVersion The old version of the database.
- * @param newVersion The version that the database is supposed to be upgraded to.
- */
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
-
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java
index a13130082..732fa2d27 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java
@@ -12,6 +12,7 @@ import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -85,15 +86,18 @@ public class DownloadObserver {
if (downloadService == null) {
connectToDownloadService();
}
- callback.onContentChanged();
+ if (downloadService != null) {
+ callback.onContentChanged(downloadService.getDownloads());
+ } else {
+ // the service is gone, there are no more downloads.
+ callback.onContentChanged(new ArrayList<Downloader>());
+ }
startRefresher();
}
};
public interface Callback {
- void onContentChanged();
-
- void onDownloadDataAvailable(List<Downloader> downloaderList);
+ void onContentChanged(List<Downloader> downloaderList);
}
private void connectToDownloadService() {
@@ -116,7 +120,7 @@ public class DownloadObserver {
Log.d(TAG, "Connection to service established");
List<Downloader> downloaderList = downloadService.getDownloads();
if (downloaderList != null && !downloaderList.isEmpty()) {
- callback.onDownloadDataAvailable(downloaderList);
+ callback.onContentChanged(downloaderList);
startRefresher();
}
}
@@ -156,12 +160,14 @@ public class DownloadObserver {
handler.post(new Runnable() {
@Override
public void run() {
- callback.onContentChanged();
if (downloadService != null) {
List<Downloader> downloaderList = downloadService.getDownloads();
+ callback.onContentChanged(downloaderList);
if (downloaderList == null || downloaderList.isEmpty()) {
Thread.currentThread().interrupt();
}
+ } else {
+ callback.onContentChanged(new ArrayList<Downloader>());
}
}
});
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java
index 5d2d5d441..f91d4557e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java
@@ -90,7 +90,7 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke
return ExitCode.NO_TOKEN;
}
- if (!NetworkUtils.networkAvailable(context)) {
+ if (!NetworkUtils.networkAvailable()) {
return ExitCode.NO_NETWORK;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java
index c0d8049db..edd69f15b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java
@@ -6,7 +6,7 @@ import android.net.Uri;
* Classes that implement this interface provide access to an image resource that can
* be loaded by the Picasso library.
*/
-public interface PicassoImageResource {
+public interface ImageResource {
/**
* This scheme should be used by PicassoImageResources to
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java
deleted file mode 100644
index 09fe0d654..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java
+++ /dev/null
@@ -1,527 +0,0 @@
-package de.danoeh.antennapod.core.asynctask;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.squareup.okhttp.Interceptor;
-import com.squareup.okhttp.OkHttpClient;
-import com.squareup.okhttp.Response;
-import com.squareup.picasso.Cache;
-import com.squareup.picasso.LruCache;
-import com.squareup.picasso.OkHttpDownloader;
-import com.squareup.picasso.Picasso;
-import com.squareup.picasso.Request;
-import com.squareup.picasso.RequestHandler;
-import com.squareup.picasso.Transformation;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import de.danoeh.antennapod.core.service.download.HttpDownloader;
-import de.danoeh.antennapod.core.storage.DBReader;
-
-/**
- * Provides access to Picasso instances.
- */
-public class PicassoProvider {
-
- private static final String TAG = "PicassoProvider";
-
- private static final boolean DEBUG = false;
-
- private static ExecutorService executorService;
- private static Cache memoryCache;
-
- private static synchronized ExecutorService getExecutorService() {
- if (executorService == null) {
- executorService = Executors.newFixedThreadPool(3);
- }
- return executorService;
- }
-
- private static synchronized Cache getMemoryCache(Context context) {
- if (memoryCache == null) {
- memoryCache = new LruCache(context);
- }
- return memoryCache;
- }
-
- private static volatile boolean picassoSetup = false;
-
- public static synchronized void setupPicassoInstance(Context appContext) {
- if (picassoSetup) {
- return;
- }
- OkHttpClient client = new OkHttpClient();
- client.interceptors().add(new BasicAuthenticationInterceptor(appContext));
- Picasso picasso = new Picasso.Builder(appContext)
- .indicatorsEnabled(DEBUG)
- .loggingEnabled(DEBUG)
- .downloader(new OkHttpDownloader(client))
- .addRequestHandler(new MediaRequestHandler(appContext))
- .executor(getExecutorService())
- .memoryCache(getMemoryCache(appContext))
- .listener(new Picasso.Listener() {
- @Override
- public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) {
- Log.e(TAG, "Failed to load Uri:" + uri.toString());
- e.printStackTrace();
- }
- })
- .build();
- Picasso.setSingletonInstance(picasso);
- picassoSetup = true;
- }
-
- private static class BasicAuthenticationInterceptor implements Interceptor {
-
- private final Context context;
-
- public BasicAuthenticationInterceptor(Context context) {
- this.context = context;
- }
-
- @Override
- public Response intercept(Chain chain) throws IOException {
- com.squareup.okhttp.Request request = chain.request();
- String url = request.urlString();
- String authentication = DBReader.getImageAuthentication(context, url);
-
- if(TextUtils.isEmpty(authentication)) {
- Log.d(TAG, "no credentials for '" + url + "'");
- return chain.proceed(request);
- }
-
- // add authentication
- String[] auth = authentication.split(":");
- String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1");
- com.squareup.okhttp.Request newRequest = request
- .newBuilder()
- .addHeader("Authorization", credentials)
- .build();
- Log.d(TAG, "Basic authentication with ISO-8859-1 encoding");
- Response response = chain.proceed(newRequest);
- if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
- credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "UTF-8");
- newRequest = request
- .newBuilder()
- .addHeader("Authorization", credentials)
- .build();
- Log.d(TAG, "Basic authentication with UTF-8 encoding");
- return chain.proceed(newRequest);
- } else {
- return response;
- }
- }
- }
-
- private static class MediaRequestHandler extends RequestHandler {
-
- final Context context;
-
- public MediaRequestHandler(Context context) {
- super();
- this.context = context;
- }
-
- @Override
- public boolean canHandleRequest(Request data) {
- return StringUtils.equals(data.uri.getScheme(), PicassoImageResource.SCHEME_MEDIA);
- }
-
- @Override
- public Result load(Request data, int networkPolicy) throws IOException {
- Bitmap bitmap = null;
- MediaMetadataRetriever mmr = null;
- try {
- mmr = new MediaMetadataRetriever();
- mmr.setDataSource(data.uri.getPath());
- byte[] image = mmr.getEmbeddedPicture();
- if (image != null) {
- bitmap = decodeStreamFromByteArray(data, image);
- }
- } catch (RuntimeException e) {
- Log.e(TAG, "Failed to decode image in media file", e);
- } finally {
- if (mmr != null) {
- mmr.release();
- }
- }
-
- if (bitmap == null) {
- // this should never, happen, but sometimes it does, so fallback
- // check for fallback Uri
- String fallbackParam = data.uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK);
- if (fallbackParam != null) {
- Uri fallback = Uri.parse(fallbackParam);
- bitmap = decodeStreamFromFile(data, fallback);
- }
- }
- return new Result(bitmap, Picasso.LoadedFrom.DISK);
-
- }
-
- /* Copied/Adapted from Picasso RequestHandler classes */
-
- private Bitmap decodeStreamFromByteArray(Request data, byte[] bytes) throws IOException {
-
- final BitmapFactory.Options options = createBitmapOptions(data);
- final ByteArrayInputStream in = new ByteArrayInputStream(bytes);
- in.mark(0);
- if (requiresInSampleSize(options)) {
- try {
- BitmapFactory.decodeStream(in, null, options);
- } finally {
- in.reset();
- }
- calculateInSampleSize(data.targetWidth, data.targetHeight, options, data);
- }
- try {
- return BitmapFactory.decodeStream(in, null, options);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- private Bitmap decodeStreamFromFile(Request data, Uri uri) throws IOException {
- ContentResolver contentResolver = context.getContentResolver();
- final BitmapFactory.Options options = createBitmapOptions(data);
- if (requiresInSampleSize(options)) {
- InputStream is = null;
- try {
- is = contentResolver.openInputStream(uri);
- BitmapFactory.decodeStream(is, null, options);
- } finally {
- IOUtils.closeQuietly(is);
- }
- calculateInSampleSize(data.targetWidth, data.targetHeight, options, data);
- }
- InputStream is = contentResolver.openInputStream(uri);
- try {
- return BitmapFactory.decodeStream(is, null, options);
- } finally {
- IOUtils.closeQuietly(is);
- }
- }
-
- private BitmapFactory.Options createBitmapOptions(Request data) {
- final boolean justBounds = data.hasSize();
- final boolean hasConfig = data.config != null;
- BitmapFactory.Options options = null;
- if (justBounds || hasConfig) {
- options = new BitmapFactory.Options();
- options.inJustDecodeBounds = justBounds;
- if (hasConfig) {
- options.inPreferredConfig = data.config;
- }
- }
- return options;
- }
-
- private static boolean requiresInSampleSize(BitmapFactory.Options options) {
- return options != null && options.inJustDecodeBounds;
- }
-
- private static void calculateInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options,
- Request request) {
- calculateInSampleSize(reqWidth, reqHeight, options.outWidth, options.outHeight, options,
- request);
- }
-
- private static void calculateInSampleSize(int reqWidth, int reqHeight, int width, int height,
- BitmapFactory.Options options, Request request) {
- int sampleSize = 1;
- if (height > reqHeight || width > reqWidth) {
- final int heightRatio;
- final int widthRatio;
- if (reqHeight == 0) {
- sampleSize = (int) Math.floor((float) width / (float) reqWidth);
- } else if (reqWidth == 0) {
- sampleSize = (int) Math.floor((float) height / (float) reqHeight);
- } else {
- heightRatio = (int) Math.floor((float) height / (float) reqHeight);
- widthRatio = (int) Math.floor((float) width / (float) reqWidth);
- sampleSize = request.centerInside
- ? Math.max(heightRatio, widthRatio)
- : Math.min(heightRatio, widthRatio);
- }
- }
- options.inSampleSize = sampleSize;
- options.inJustDecodeBounds = false;
- }
- }
-
- public static final int BLUR_RADIUS = 1;
- public static final int BLUR_IMAGE_SIZE = 100;
- public static final String BLUR_KEY = "blur";
-
- public static final Transformation blurTransformation = new Transformation() {
- @Override
- public Bitmap transform(Bitmap source) {
- Bitmap result = fastblur(source, BLUR_RADIUS);
- if (result == null) {
- // just return the original
- // for some reason we couldn't transform it.
- return source;
- }
- source.recycle();
- return result;
- }
-
- @Override
- public String key() {
- return BLUR_KEY;
- }
- };
-
- public static Bitmap fastblur(Bitmap sentBitmap, int radius) {
-
- // Stack Blur v1.0 from
- // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
- //
- // Java Author: Mario Klingemann <mario at quasimondo.com>
- // http://incubator.quasimondo.com
- // created Feburary 29, 2004
- // Android port : Yahel Bouaziz <yahel at kayenko.com>
- // http://www.kayenko.com
- // ported april 5th, 2012
-
- // This is a compromise between Gaussian Blur and Box blur
- // It creates much better looking blurs than Box Blur, but is
- // 7x faster than my Gaussian Blur implementation.
- //
- // I called it Stack Blur because this describes best how this
- // filter works internally: it creates a kind of moving stack
- // of colors whilst scanning through the image. Thereby it
- // just has to add one new block of color to the right side
- // of the stack and remove the leftmost color. The remaining
- // colors on the topmost layer of the stack are either added on
- // or reduced by one, depending on if they are on the right or
- // on the left side of the stack.
- //
- // If you are using this algorithm in your code please add
- // the following line:
- //
- // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
- Bitmap.Config config = sentBitmap.getConfig();
- if (config == null) {
- // Sometimes the config can be null, in those cases
- // we don't do a transform.
- return null;
- }
-
- Bitmap bitmap = sentBitmap.copy(config, true);
-
- if (radius < 1) {
- return (null);
- }
-
- int w = bitmap.getWidth();
- int h = bitmap.getHeight();
-
- int[] pix = new int[w * h];
- Log.e("pix", w + " " + h + " " + pix.length);
- bitmap.getPixels(pix, 0, w, 0, 0, w, h);
-
- int wm = w - 1;
- int hm = h - 1;
- int wh = w * h;
- int div = radius + radius + 1;
-
- int r[] = new int[wh];
- int g[] = new int[wh];
- int b[] = new int[wh];
- int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
- int vmin[] = new int[Math.max(w, h)];
-
- int divsum = (div + 1) >> 1;
- divsum *= divsum;
- int dv[] = new int[256 * divsum];
- for (i = 0; i < 256 * divsum; i++) {
- dv[i] = (i / divsum);
- }
-
- yw = yi = 0;
-
- int[][] stack = new int[div][3];
- int stackpointer;
- int stackstart;
- int[] sir;
- int rbs;
- int r1 = radius + 1;
- int routsum, goutsum, boutsum;
- int rinsum, ginsum, binsum;
-
- for (y = 0; y < h; y++) {
- rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
- for (i = -radius; i <= radius; i++) {
- p = pix[yi + Math.min(wm, Math.max(i, 0))];
- sir = stack[i + radius];
- sir[0] = (p & 0xff0000) >> 16;
- sir[1] = (p & 0x00ff00) >> 8;
- sir[2] = (p & 0x0000ff);
- rbs = r1 - Math.abs(i);
- rsum += sir[0] * rbs;
- gsum += sir[1] * rbs;
- bsum += sir[2] * rbs;
- if (i > 0) {
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- } else {
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- }
- }
- stackpointer = radius;
-
- for (x = 0; x < w; x++) {
-
- r[yi] = dv[rsum];
- g[yi] = dv[gsum];
- b[yi] = dv[bsum];
-
- rsum -= routsum;
- gsum -= goutsum;
- bsum -= boutsum;
-
- stackstart = stackpointer - radius + div;
- sir = stack[stackstart % div];
-
- routsum -= sir[0];
- goutsum -= sir[1];
- boutsum -= sir[2];
-
- if (y == 0) {
- vmin[x] = Math.min(x + radius + 1, wm);
- }
- p = pix[yw + vmin[x]];
-
- sir[0] = (p & 0xff0000) >> 16;
- sir[1] = (p & 0x00ff00) >> 8;
- sir[2] = (p & 0x0000ff);
-
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
-
- rsum += rinsum;
- gsum += ginsum;
- bsum += binsum;
-
- stackpointer = (stackpointer + 1) % div;
- sir = stack[(stackpointer) % div];
-
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
-
- rinsum -= sir[0];
- ginsum -= sir[1];
- binsum -= sir[2];
-
- yi++;
- }
- yw += w;
- }
- for (x = 0; x < w; x++) {
- rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
- yp = -radius * w;
- for (i = -radius; i <= radius; i++) {
- yi = Math.max(0, yp) + x;
-
- sir = stack[i + radius];
-
- sir[0] = r[yi];
- sir[1] = g[yi];
- sir[2] = b[yi];
-
- rbs = r1 - Math.abs(i);
-
- rsum += r[yi] * rbs;
- gsum += g[yi] * rbs;
- bsum += b[yi] * rbs;
-
- if (i > 0) {
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- } else {
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- }
-
- if (i < hm) {
- yp += w;
- }
- }
- yi = x;
- stackpointer = radius;
- for (y = 0; y < h; y++) {
- // Preserve alpha channel: ( 0xff000000 & pix[yi] )
- pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
-
- rsum -= routsum;
- gsum -= goutsum;
- bsum -= boutsum;
-
- stackstart = stackpointer - radius + div;
- sir = stack[stackstart % div];
-
- routsum -= sir[0];
- goutsum -= sir[1];
- boutsum -= sir[2];
-
- if (x == 0) {
- vmin[y] = Math.min(y + r1, hm) * w;
- }
- p = x + vmin[y];
-
- sir[0] = r[p];
- sir[1] = g[p];
- sir[2] = b[p];
-
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
-
- rsum += rinsum;
- gsum += ginsum;
- bsum += binsum;
-
- stackpointer = (stackpointer + 1) % div;
- sir = stack[stackpointer];
-
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
-
- rinsum -= sir[0];
- ginsum -= sir[1];
- binsum -= sir[2];
-
- yi += w;
- }
- }
-
- Log.e("pix", w + " " + h + " " + pix.length);
- bitmap.setPixels(pix, 0, w, 0, 0, w, h);
-
- return (bitmap);
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java
index ba1add895..fea2bbb2b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java
@@ -4,7 +4,7 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Log;
-import de.danoeh.antennapod.core.BuildConfig;
+
import de.danoeh.antennapod.core.R;
/**
@@ -12,12 +12,16 @@ import de.danoeh.antennapod.core.R;
* classes can handle events like confirmation or cancellation.
*/
public abstract class ConfirmationDialog {
- private static final String TAG = "ConfirmationDialog";
- Context context;
+ private static final String TAG = ConfirmationDialog.class.getSimpleName();
+
+ protected Context context;
int titleId;
int messageId;
+ int positiveText;
+ int negativeText;
+
public ConfirmationDialog(Context context, int titleId, int messageId) {
this.context = context;
this.titleId = titleId;
@@ -25,18 +29,26 @@ public abstract class ConfirmationDialog {
}
public void onCancelButtonPressed(DialogInterface dialog) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Dialog was cancelled");
+ Log.d(TAG, "Dialog was cancelled");
dialog.dismiss();
}
+ public void setPositiveText(int id) {
+ this.positiveText = id;
+ }
+
+ public void setNegativeText(int id) {
+ this.negativeText = id;
+ }
+
+
public abstract void onConfirmButtonPressed(DialogInterface dialog);
public final AlertDialog createNewDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(titleId);
builder.setMessage(messageId);
- builder.setPositiveButton(R.string.confirm_label,
+ builder.setPositiveButton(positiveText != 0 ? positiveText : R.string.confirm_label,
new DialogInterface.OnClickListener() {
@Override
@@ -44,7 +56,7 @@ public abstract class ConfirmationDialog {
onConfirmButtonPressed(dialog);
}
});
- builder.setNegativeButton(R.string.cancel_label,
+ builder.setNegativeButton(negativeText != 0 ? negativeText : R.string.cancel_label,
new DialogInterface.OnClickListener() {
@Override
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java
new file mode 100644
index 000000000..94e186b7a
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java
@@ -0,0 +1,24 @@
+package de.danoeh.antennapod.core.event;
+
+import de.danoeh.antennapod.core.feed.FeedMedia;
+
+public class FeedMediaEvent {
+
+ public enum Action {
+ UPDATE
+ }
+
+ public final Action action;
+ public final FeedMedia media;
+
+ private FeedMediaEvent(Action action, FeedMedia media) {
+ this.action = action;
+ this.media = media;
+ }
+
+ public static FeedMediaEvent update(FeedMedia media) {
+ return new FeedMediaEvent(Action.UPDATE, media);
+ }
+
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java
new file mode 100644
index 000000000..3769d6bb1
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java
@@ -0,0 +1,36 @@
+package de.danoeh.antennapod.core.event;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+public class ProgressEvent {
+
+ public enum Action {
+ START, END
+ }
+
+ public final Action action;
+ public final String message;
+
+ private ProgressEvent(Action action, String message) {
+ this.action = action;
+ this.message = message;
+ }
+
+ public static ProgressEvent start(String message) {
+ return new ProgressEvent(Action.START, message);
+ }
+
+ public static ProgressEvent end() {
+ return new ProgressEvent(Action.END, null);
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append("action", action)
+ .append("message", message)
+ .toString();
+ }
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
index 29ba721fe..2a483ca9b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
@@ -10,7 +10,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import de.danoeh.antennapod.core.asynctask.PicassoImageResource;
+import de.danoeh.antennapod.core.asynctask.ImageResource;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
import de.danoeh.antennapod.core.util.flattr.FlattrThing;
@@ -20,7 +20,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing;
*
* @author daniel
*/
-public class Feed extends FeedFile implements FlattrThing, PicassoImageResource {
+public class Feed extends FeedFile implements FlattrThing, ImageResource {
public static final int FEEDFILETYPE_FEED = 0;
public static final String TYPE_RSS2 = "rss";
public static final String TYPE_RSS091 = "rss";
@@ -167,7 +167,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
*/
public Feed(String url, Date lastUpdate, String title, String username, String password) {
this(url, lastUpdate, title);
- preferences = new FeedPreferences(0, true, username, password);
+ preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, username, password);
}
@@ -177,10 +177,21 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource
*/
public boolean hasNewItems() {
for (FeedItem item : items) {
- if (item.getState() == FeedItem.State.UNREAD) {
- if (item.getMedia() != null) {
- return true;
- }
+ if (item.isNew()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if at least one item in the itemlist is unread.
+ *
+ */
+ public boolean hasUnplayedItems() {
+ for (FeedItem item : items) {
+ if (false == item.isNew() && false == item.isPlayed()) {
+ return true;
}
}
return false;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java
index c6f24367e..f77a78721 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java
@@ -4,10 +4,10 @@ import android.net.Uri;
import java.io.File;
-import de.danoeh.antennapod.core.asynctask.PicassoImageResource;
+import de.danoeh.antennapod.core.asynctask.ImageResource;
-public class FeedImage extends FeedFile implements PicassoImageResource {
+public class FeedImage extends FeedFile implements ImageResource {
public static final int FEEDFILETYPE_FEEDIMAGE = 1;
protected String title;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
index 1168c60e4..9229172f0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
@@ -10,7 +10,7 @@ import java.util.List;
import java.util.concurrent.Callable;
import de.danoeh.antennapod.core.ClientConfig;
-import de.danoeh.antennapod.core.asynctask.PicassoImageResource;
+import de.danoeh.antennapod.core.asynctask.ImageResource;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.ShownotesProvider;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
@@ -21,7 +21,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing;
*
* @author daniel
*/
-public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, PicassoImageResource {
+public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, ImageResource {
/**
* The id/guid that can be found in the rss/atom feed. Might not be set.
@@ -44,7 +44,11 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
private Feed feed;
private long feedId;
- private boolean read;
+ private int state;
+ public final static int NEW = -1;
+ public final static int UNPLAYED = 0;
+ public final static int PLAYED = 1;
+
private String paymentLink;
private FlattrStatus flattrStatus;
@@ -66,7 +70,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
private boolean autoDownload = true;
public FeedItem() {
- this.read = true;
+ this.state = UNPLAYED;
this.flattrStatus = new FlattrStatus();
this.hasChapters = false;
}
@@ -75,7 +79,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
* This constructor is used by DBReader.
* */
public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId,
- FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, boolean read,
+ FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state,
String itemIdentifier, boolean autoDownload) {
this.id = id;
this.title = title;
@@ -86,7 +90,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
this.flattrStatus = flattrStatus;
this.hasChapters = hasChapters;
this.image = image;
- this.read = read;
+ this.state = state;
this.itemIdentifier = itemIdentifier;
this.autoDownload = autoDownload;
}
@@ -94,13 +98,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
/**
* This constructor should be used for creating test objects.
*/
- public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed) {
+ public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed) {
this.id = id;
this.title = title;
this.itemIdentifier = itemIdentifier;
this.link = link;
this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null;
- this.read = read;
+ this.state = state;
this.feed = feed;
this.flattrStatus = new FlattrStatus();
this.hasChapters = false;
@@ -109,13 +113,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
/**
* This constructor should be used for creating test objects involving chapter marks.
*/
- public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed, boolean hasChapters) {
+ public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed, boolean hasChapters) {
this.id = id;
this.title = title;
this.itemIdentifier = itemIdentifier;
this.link = link;
this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null;
- this.read = read;
+ this.state = state;
this.feed = feed;
this.flattrStatus = new FlattrStatus();
this.hasChapters = hasChapters;
@@ -238,12 +242,25 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
this.feed = feed;
}
- public boolean isRead() {
- return read;
+ public boolean isNew() {
+ return state == NEW;
+ }
+
+
+ public void setNew() {
+ state = NEW;
}
- public void setRead(boolean read) {
- this.read = read;
+ public boolean isPlayed() {
+ return state == PLAYED;
+ }
+
+ public void setPlayed(boolean played) {
+ if(played) {
+ state = PLAYED;
+ } else {
+ state = UNPLAYED;
+ }
}
private boolean isInProgress() {
@@ -257,11 +274,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
public void setContentEncoded(String contentEncoded) {
this.contentEncoded = contentEncoded;
}
-
- public void setFlattrStatus(FlattrStatus status) {
- this.flattrStatus = status;
- }
-
+
public FlattrStatus getFlattrStatus() {
return flattrStatus;
}
@@ -320,7 +333,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
public Uri getImageUri() {
if(media != null && media.hasEmbeddedPicture()) {
return media.getImageUri();
- } else if (hasItemImageDownloaded()) {
+ } else if (image != null) {
return image.getImageUri();
} else if (feed != null) {
return feed.getImageUri();
@@ -342,7 +355,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
return State.IN_PROGRESS;
}
}
- return (isRead() ? State.READ : State.UNREAD);
+ return (isPlayed() ? State.READ : State.UNREAD);
}
public long getFeedId() {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
index 4ad084b39..2fd5666c8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java
@@ -61,9 +61,9 @@ public class FeedItemFilter {
}
List<FeedItem> result = new ArrayList<FeedItem>();
for(FeedItem item : items) {
- if(hideUnplayed && false == item.isRead()) continue;
+ if(hideUnplayed && false == item.isPlayed()) continue;
if(hidePaused && item.getState() == FeedItem.State.IN_PROGRESS) continue;
- if(hidePlayed && item.isRead()) continue;
+ if(hidePlayed && item.isPlayed()) continue;
boolean isQueued = DBReader.getQueueIDList(context).contains(item.getId());
if(hideQueued && isQueued) continue;
if(hideNotQueued && false == isQueued) continue;
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 ee05020cc..9dbf6cc61 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
@@ -28,6 +28,15 @@ public class FeedMedia extends FeedFile implements Playable {
public static final String PREF_MEDIA_ID = "FeedMedia.PrefMediaId";
public static final String PREF_FEED_ID = "FeedMedia.PrefFeedId";
+ /**
+ * Indicates we've checked on the size of the item via the network
+ * and got an invalid response. Using Integer.MIN_VALUE because
+ * 1) we'll still check on it in case it gets downloaded (it's <= 0)
+ * 2) By default all FeedMedia have a size of 0 if we don't know it,
+ * so this won't conflict with existing practice.
+ */
+ private static final int CHECKED_ON_SIZE_BUT_UNKNOWN = Integer.MIN_VALUE;
+
private int duration;
private int position; // Current position in file
private int played_duration; // How many ms of this file have been played (for autoflattring)
@@ -35,6 +44,8 @@ public class FeedMedia extends FeedFile implements Playable {
private String mime_type;
private volatile FeedItem item;
private Date playbackCompletionDate;
+
+ // if null: unknown, will be checked
private Boolean hasEmbeddedPicture;
/* Used for loading item when restoring from parcel. */
@@ -63,6 +74,15 @@ public class FeedMedia extends FeedFile implements Playable {
? null : (Date) playbackCompletionDate.clone();
}
+ public FeedMedia(long id, FeedItem item, int duration, int position,
+ long size, String mime_type, String file_url, String download_url,
+ boolean downloaded, Date playbackCompletionDate, int played_duration,
+ Boolean hasEmbeddedPicture) {
+ this(id, item, duration, position, size, mime_type, file_url, download_url, downloaded,
+ playbackCompletionDate, played_duration);
+ this.hasEmbeddedPicture = hasEmbeddedPicture;
+ }
+
@Override
public String getHumanReadableIdentifier() {
if (item != null && item.getTitle() != null) {
@@ -175,6 +195,9 @@ public class FeedMedia extends FeedFile implements Playable {
public void setPosition(int position) {
this.position = position;
+ if(position > 0 && item.isNew()) {
+ this.item.setPlayed(false);
+ }
}
public long getSize() {
@@ -185,6 +208,18 @@ public class FeedMedia extends FeedFile implements Playable {
this.size = size;
}
+ /**
+ * Indicates we asked the service what the size was, but didn't
+ * get a valid answer and we shoudln't check using the network again.
+ */
+ public void setCheckedOnSizeButUnknown() {
+ this.size = CHECKED_ON_SIZE_BUT_UNKNOWN;
+ }
+
+ public boolean checkedOnSizeButUnknown() {
+ return (CHECKED_ON_SIZE_BUT_UNKNOWN == this.size);
+ }
+
public String getMime_type() {
return mime_type;
}
@@ -354,14 +389,16 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public void saveCurrentPosition(SharedPreferences pref, int newPosition) {
- setPosition(newPosition);
DBWriter.setFeedMediaPlaybackInformation(ClientConfig.applicationCallbacks.getApplicationInstance(), this);
+ if(item.isNew()) {
+ DBWriter.markItemRead(ClientConfig.applicationCallbacks.getApplicationInstance(), false, item.getId());
+ }
+ setPosition(newPosition);
}
@Override
public void onPlaybackStart() {
}
-
@Override
public void onPlaybackCompleted() {
@@ -429,9 +466,16 @@ public class FeedMedia extends FeedFile implements Playable {
}
}
+ public void setHasEmbeddedPicture(Boolean hasEmbeddedPicture) {
+ this.hasEmbeddedPicture = hasEmbeddedPicture;
+ }
+
@Override
public void setDownloaded(boolean downloaded) {
super.setDownloaded(downloaded);
+ if(downloaded) {
+ item.setPlayed(false);
+ }
}
@Override
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
index 2f0304182..88da865cc 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.feed;
import android.content.Context;
import de.danoeh.antennapod.core.storage.DBWriter;
import org.apache.commons.lang3.StringUtils;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
/**
* Contains preferences for a single feed.
@@ -11,19 +12,26 @@ public class FeedPreferences {
private long feedID;
private boolean autoDownload;
+ public enum AutoDeleteAction {
+ GLOBAL,
+ YES,
+ NO
+ }
+ private AutoDeleteAction auto_delete_action;
private String username;
private String password;
- public FeedPreferences(long feedID, boolean autoDownload, String username, String password) {
+ public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, String username, String password) {
this.feedID = feedID;
this.autoDownload = autoDownload;
+ this.auto_delete_action = auto_delete_action;
this.username = username;
this.password = password;
}
/**
- * Compare another FeedPreferences with this one. The feedID and autoDownload attribute are excluded from the
+ * Compare another FeedPreferences with this one. The feedID, autoDownload and AutoDeleteAction attribute are excluded from the
* comparison.
*
* @return True if the two objects are different.
@@ -41,7 +49,7 @@ public class FeedPreferences {
}
/**
- * Update this FeedPreferences object from another one. The feedID and autoDownload attributes are excluded
+ * Update this FeedPreferences object from another one. The feedID, autoDownload and AutoDeleteAction attributes are excluded
* from the update.
*/
public void updateFromOther(FeedPreferences other) {
@@ -67,6 +75,28 @@ public class FeedPreferences {
this.autoDownload = autoDownload;
}
+ public AutoDeleteAction getAutoDeleteAction() {
+ return auto_delete_action;
+ }
+
+ public void setAutoDeleteAction(AutoDeleteAction auto_delete_action) {
+ this.auto_delete_action = auto_delete_action;
+ }
+
+ public boolean getCurrentAutoDelete() {
+ switch (auto_delete_action) {
+ case GLOBAL:
+ return UserPreferences.isAutoDelete();
+
+ case YES:
+ return true;
+
+ case NO:
+ return false;
+ }
+ return false; // TODO - add exceptions here
+ }
+
public void save(Context context) {
DBWriter.setFeedPreferences(context, this);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java
index c8497f509..97d086e5b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java
@@ -8,7 +8,7 @@ import java.util.List;
public class QueueEvent {
public enum Action {
- ADDED, ADDED_ITEMS, REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED
+ ADDED, ADDED_ITEMS, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED
}
public final Action action;
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
new file mode 100644
index 000000000..0baff9723
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java
@@ -0,0 +1,33 @@
+package de.danoeh.antennapod.core.glide;
+
+import android.content.Context;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.GlideBuilder;
+import com.bumptech.glide.load.DecodeFormat;
+import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
+import com.bumptech.glide.load.model.GlideUrl;
+import com.bumptech.glide.module.GlideModule;
+
+import java.io.InputStream;
+
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
+/**
+ * {@see com.bumptech.glide.integration.okhttp.OkHttpGlideModule}
+ */
+public class ApGlideModule implements GlideModule {
+
+ @Override
+ public void applyOptions(Context context, GlideBuilder builder) {
+ builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
+ builder.setDiskCache(new InternalCacheDiskCacheFactory(context,
+ UserPreferences.getImageCacheSize()));
+ }
+
+ @Override
+ public void registerComponents(Context context, Glide glide) {
+ glide.register(GlideUrl.class, InputStream.class, new ApOkHttpUrlLoader.Factory());
+ }
+
+} \ No newline at end of file
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java
new file mode 100644
index 000000000..fc1acd0e1
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java
@@ -0,0 +1,11 @@
+package de.danoeh.antennapod.core.glide;
+
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+
+/**
+ * The settings that AntennaPod will use for various Glide options
+ */
+public class ApGlideSettings {
+
+ public static final DiskCacheStrategy AP_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL;
+}
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
new file mode 100644
index 000000000..c7ac146b5
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java
@@ -0,0 +1,141 @@
+package de.danoeh.antennapod.core.glide;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.bumptech.glide.load.model.GenericLoaderFactory;
+import com.bumptech.glide.load.model.GlideUrl;
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.squareup.okhttp.Interceptor;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Response;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+
+import de.danoeh.antennapod.core.ClientConfig;
+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;
+
+/**
+ * @see com.bumptech.glide.integration.okhttp.OkHttpUrlLoader
+ */
+public class ApOkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {
+
+ private static final String TAG = ApOkHttpUrlLoader.class.getSimpleName();
+
+ /**
+ * The default factory for {@link ApOkHttpUrlLoader}s.
+ */
+ public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
+
+ private static volatile OkHttpClient internalClient;
+ private OkHttpClient client;
+
+ private static OkHttpClient getInternalClient() {
+ if (internalClient == null) {
+ synchronized (Factory.class) {
+ if (internalClient == null) {
+ internalClient = AntennapodHttpClient.getHttpClient();
+ internalClient.interceptors().add(new NetworkAllowanceInterceptor());
+ internalClient.interceptors().add(new BasicAuthenticationInterceptor());
+ }
+ }
+ }
+ return internalClient;
+ }
+
+ /**
+ * Constructor for a new Factory that runs requests using a static singleton client.
+ */
+ public Factory() {
+ this(getInternalClient());
+ }
+
+ /**
+ * Constructor for a new Factory that runs requests using given client.
+ */
+ public Factory(OkHttpClient client) {
+ this.client = client;
+ }
+
+ @Override
+ public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories) {
+ return new ApOkHttpUrlLoader(client);
+ }
+
+ @Override
+ public void teardown() {
+ // Do nothing, this instance doesn't own the client.
+ }
+ }
+
+ private final OkHttpClient client;
+
+ public ApOkHttpUrlLoader(OkHttpClient client) {
+ this.client = client;
+ }
+
+ @Override
+ public DataFetcher<InputStream> getResourceFetcher(GlideUrl model, int width, int height) {
+ return new OkHttpStreamFetcher(client, model);
+ }
+
+ private static class NetworkAllowanceInterceptor implements Interceptor {
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ if (NetworkUtils.isDownloadAllowed()) {
+ return chain.proceed(chain.request());
+ } else {
+ return null;
+ }
+ }
+
+ }
+
+ private static class BasicAuthenticationInterceptor implements Interceptor {
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ com.squareup.okhttp.Request request = chain.request();
+ String url = request.urlString();
+ Context context = ClientConfig.applicationCallbacks.getApplicationInstance();
+ String authentication = DBReader.getImageAuthentication(context, url);
+
+ if(TextUtils.isEmpty(authentication)) {
+ Log.d(TAG, "no credentials for '" + url + "'");
+ return chain.proceed(request);
+ }
+
+ // add authentication
+ String[] auth = authentication.split(":");
+ String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1");
+ com.squareup.okhttp.Request newRequest = request
+ .newBuilder()
+ .addHeader("Authorization", credentials)
+ .build();
+ Log.d(TAG, "Basic authentication with ISO-8859-1 encoding");
+ Response response = chain.proceed(newRequest);
+ if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
+ credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "UTF-8");
+ newRequest = request
+ .newBuilder()
+ .addHeader("Authorization", credentials)
+ .build();
+ Log.d(TAG, "Basic authentication with UTF-8 encoding");
+ return chain.proceed(newRequest);
+ } else {
+ return response;
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
new file mode 100644
index 000000000..ee58c2f39
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
@@ -0,0 +1,267 @@
+package de.danoeh.antennapod.core.glide;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.media.ThumbnailUtils;
+import android.util.Log;
+
+import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
+
+public class FastBlurTransformation extends BitmapTransformation {
+
+ private static final String TAG = FastBlurTransformation.class.getSimpleName();
+
+ private static final int STACK_BLUR_RADIUS = 1;
+ private static final int BLUR_IMAGE_WIDTH = 150;
+
+ public FastBlurTransformation(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected Bitmap transform(BitmapPool pool, Bitmap source,
+ int outWidth, int outHeight) {
+ int targetWidth = BLUR_IMAGE_WIDTH;
+ int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth);
+ Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight);
+ Bitmap result = fastBlur(resized, STACK_BLUR_RADIUS);
+ if (result == null) {
+ Log.w(TAG, "result was null");
+ return source;
+ }
+ return result;
+ }
+
+ @Override
+ public String getId() {
+ return "FastBlurTransformation[width=" + BLUR_IMAGE_WIDTH + "px,radius=" + STACK_BLUR_RADIUS +"]";
+ }
+
+ private static Bitmap fastBlur(Bitmap bitmap, int radius) {
+
+ // Stack Blur v1.0 from
+ // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
+ //
+ // Java Author: Mario Klingemann <mario at quasimondo.com>
+ // http://incubator.quasimondo.com
+ // created Feburary 29, 2004
+ // Android port : Yahel Bouaziz <yahel at kayenko.com>
+ // http://www.kayenko.com
+ // ported april 5th, 2012
+
+ // This is a compromise between Gaussian Blur and Box blur
+ // It creates much better looking blurs than Box Blur, but is
+ // 7x faster than my Gaussian Blur implementation.
+ //
+ // I called it Stack Blur because this describes best how this
+ // filter works internally: it creates a kind of moving stack
+ // of colors whilst scanning through the image. Thereby it
+ // just has to add one new block of color to the right side
+ // of the stack and remove the leftmost color. The remaining
+ // colors on the topmost layer of the stack are either added on
+ // or reduced by one, depending on if they are on the right or
+ // on the left side of the stack.
+ //
+ // If you are using this algorithm in your code please add
+ // the following line:
+ //
+ // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
+
+ if (radius < 1) {
+ return null;
+ }
+
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ int[] pix = new int[w * h];
+ bitmap.getPixels(pix, 0, w, 0, 0, w, h);
+
+ int wm = w - 1;
+ int hm = h - 1;
+ int wh = w * h;
+ int div = radius + radius + 1;
+
+ int r[] = new int[wh];
+ int g[] = new int[wh];
+ int b[] = new int[wh];
+ int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
+ int vmin[] = new int[Math.max(w, h)];
+
+ int divsum = (div + 1) >> 1;
+ divsum *= divsum;
+ int dv[] = new int[256 * divsum];
+ for (i = 0; i < 256 * divsum; i++) {
+ dv[i] = (i / divsum);
+ }
+
+ yw = yi = 0;
+
+ int[][] stack = new int[div][3];
+ int stackpointer;
+ int stackstart;
+ int[] sir;
+ int rbs;
+ int r1 = radius + 1;
+ int routsum, goutsum, boutsum;
+ int rinsum, ginsum, binsum;
+
+ for (y = 0; y < h; y++) {
+ rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
+ for (i = -radius; i <= radius; i++) {
+ p = pix[yi + Math.min(wm, Math.max(i, 0))];
+ sir = stack[i + radius];
+ sir[0] = (p & 0xff0000) >> 16;
+ sir[1] = (p & 0x00ff00) >> 8;
+ sir[2] = (p & 0x0000ff);
+ rbs = r1 - Math.abs(i);
+ rsum += sir[0] * rbs;
+ gsum += sir[1] * rbs;
+ bsum += sir[2] * rbs;
+ if (i > 0) {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ } else {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ }
+ }
+ stackpointer = radius;
+
+ for (x = 0; x < w; x++) {
+
+ r[yi] = dv[rsum];
+ g[yi] = dv[gsum];
+ b[yi] = dv[bsum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+
+ if (y == 0) {
+ vmin[x] = Math.min(x + radius + 1, wm);
+ }
+ p = pix[yw + vmin[x]];
+
+ sir[0] = (p & 0xff0000) >> 16;
+ sir[1] = (p & 0x00ff00) >> 8;
+ sir[2] = (p & 0x0000ff);
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[(stackpointer) % div];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+
+ yi++;
+ }
+ yw += w;
+ }
+ for (x = 0; x < w; x++) {
+ rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
+ yp = -radius * w;
+ for (i = -radius; i <= radius; i++) {
+ yi = Math.max(0, yp) + x;
+
+ sir = stack[i + radius];
+
+ sir[0] = r[yi];
+ sir[1] = g[yi];
+ sir[2] = b[yi];
+
+ rbs = r1 - Math.abs(i);
+
+ rsum += r[yi] * rbs;
+ gsum += g[yi] * rbs;
+ bsum += b[yi] * rbs;
+
+ if (i > 0) {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ } else {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ }
+
+ if (i < hm) {
+ yp += w;
+ }
+ }
+ yi = x;
+ stackpointer = radius;
+ for (y = 0; y < h; y++) {
+ // Preserve alpha channel: ( 0xff000000 & pix[yi] )
+ pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+
+ if (x == 0) {
+ vmin[y] = Math.min(y + r1, hm) * w;
+ }
+ p = x + vmin[y];
+
+ sir[0] = r[p];
+ sir[1] = g[p];
+ sir[2] = b[p];
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[stackpointer];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+
+ yi += w;
+ }
+ }
+ bitmap.setPixels(pix, 0, w, 0, 0, w, h);
+ return bitmap;
+ }
+
+} \ No newline at end of file
diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java
index bd6210d13..efe39485e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java
@@ -93,7 +93,12 @@ public class GpodnetEpisodeAction {
if(StringUtils.isEmpty(podcast) || StringUtils.isEmpty(episode) || StringUtils.isEmpty(actionString)) {
return null;
}
- GpodnetEpisodeAction.Action action = GpodnetEpisodeAction.Action.valueOf(actionString.toUpperCase());
+ GpodnetEpisodeAction.Action action;
+ try {
+ action = GpodnetEpisodeAction.Action.valueOf(actionString.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
String deviceId = object.optString("device", "");
GpodnetEpisodeAction.Builder builder = new GpodnetEpisodeAction.Builder(podcast, episode, action)
.deviceId(deviceId);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java
index c3c6ce8c5..1401d5f39 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java
@@ -8,7 +8,6 @@ import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -217,26 +216,36 @@ public class GpodnetPreferences {
public static void removeRemovedFeeds(Collection<String> removed) {
ensurePreferencesLoaded();
+ feedListLock.lock();
removedFeeds.removeAll(removed);
writePreference(PREF_SYNC_REMOVED, removedFeeds);
+ feedListLock.unlock();
}
- public static synchronized void enqueueEpisodeAction(GpodnetEpisodeAction action) {
+ public static void enqueueEpisodeAction(GpodnetEpisodeAction action) {
ensurePreferencesLoaded();
+ feedListLock.lock();
queuedEpisodeActions.add(action);
writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions));
+ feedListLock.unlock();
GpodnetSyncService.sendSyncActionsIntent(ClientConfig.applicationCallbacks.getApplicationInstance());
}
public static List<GpodnetEpisodeAction> getQueuedEpisodeActions() {
ensurePreferencesLoaded();
- return Collections.unmodifiableList(queuedEpisodeActions);
+ List<GpodnetEpisodeAction> copy = new ArrayList();
+ feedListLock.lock();
+ copy.addAll(queuedEpisodeActions);
+ feedListLock.unlock();
+ return copy;
}
- public static synchronized void removeQueuedEpisodeActions(Collection<GpodnetEpisodeAction> queued) {
+ public static void removeQueuedEpisodeActions(Collection<GpodnetEpisodeAction> queued) {
ensurePreferencesLoaded();
+ feedListLock.lock();
queuedEpisodeActions.removeAll(queued);
writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions));
+ feedListLock.unlock();
}
/**
@@ -252,12 +261,14 @@ public class GpodnetPreferences {
setUsername(null);
setPassword(null);
setDeviceID(null);
+ feedListLock.lock();
addedFeeds.clear();
writePreference(PREF_SYNC_ADDED, addedFeeds);
removedFeeds.clear();
writePreference(PREF_SYNC_REMOVED, removedFeeds);
queuedEpisodeActions.clear();
writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions));
+ feedListLock.unlock();
setLastSubscriptionSyncTimestamp(0);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java
index 714f1b051..dfe056f14 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/PlaybackPreferences.java
@@ -3,11 +3,7 @@ package de.danoeh.antennapod.core.preferences;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
-import android.util.Log;
-import org.apache.commons.lang3.Validate;
-
-import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.feed.EventDistributor;
/**
@@ -15,159 +11,104 @@ import de.danoeh.antennapod.core.feed.EventDistributor;
* instance of this class must first be instantiated via createInstance() or
* otherwise every public method will throw an Exception when called.
*/
-public class PlaybackPreferences implements
- SharedPreferences.OnSharedPreferenceChangeListener {
- private static final String TAG = "PlaybackPreferences";
-
- /**
- * Contains the feed id of the currently playing item if it is a FeedMedia
- * object.
- */
- public static final String PREF_CURRENTLY_PLAYING_FEED_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedId";
-
- /**
- * Contains the id of the currently playing FeedMedia object or
- * NO_MEDIA_PLAYING if the currently playing media is no FeedMedia object.
- */
- public static final String PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedMediaId";
-
- /**
- * Type of the media object that is currently being played. This preference
- * is set to NO_MEDIA_PLAYING after playback has been completed and is set
- * as soon as the 'play' button is pressed.
- */
- public static final String PREF_CURRENTLY_PLAYING_MEDIA = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
-
- /** True if last played media was streamed. */
- public static final String PREF_CURRENT_EPISODE_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
-
- /** True if last played media was a video. */
- public static final String PREF_CURRENT_EPISODE_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
-
- /** The current player status as int. */
+public class PlaybackPreferences implements SharedPreferences.OnSharedPreferenceChangeListener {
+
+ private static final String TAG = "PlaybackPreferences";
+
+ /**
+ * Contains the feed id of the currently playing item if it is a FeedMedia
+ * object.
+ */
+ public static final String PREF_CURRENTLY_PLAYING_FEED_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedId";
+
+ /**
+ * Contains the id of the currently playing FeedMedia object or
+ * NO_MEDIA_PLAYING if the currently playing media is no FeedMedia object.
+ */
+ public static final String PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedMediaId";
+
+ /**
+ * Type of the media object that is currently being played. This preference
+ * is set to NO_MEDIA_PLAYING after playback has been completed and is set
+ * as soon as the 'play' button is pressed.
+ */
+ public static final String PREF_CURRENTLY_PLAYING_MEDIA = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
+
+ /**
+ * True if last played media was streamed.
+ */
+ public static final String PREF_CURRENT_EPISODE_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
+
+ /**
+ * True if last played media was a video.
+ */
+ public static final String PREF_CURRENT_EPISODE_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
+
+ /**
+ * The current player status as int.
+ */
public static final String PREF_CURRENT_PLAYER_STATUS = "de.danoeh.antennapod.preferences.currentPlayerStatus";
- /** Value of PREF_CURRENTLY_PLAYING_MEDIA if no media is playing. */
- public static final long NO_MEDIA_PLAYING = -1;
+ /**
+ * Value of PREF_CURRENTLY_PLAYING_MEDIA if no media is playing.
+ */
+ public static final long NO_MEDIA_PLAYING = -1;
- /** Value of PREF_CURRENT_PLAYER_STATUS if media player status is playing. */
+ /**
+ * Value of PREF_CURRENT_PLAYER_STATUS if media player status is playing.
+ */
public static final int PLAYER_STATUS_PLAYING = 1;
- /** Value of PREF_CURRENT_PLAYER_STATUS if media player status is paused. */
+ /**
+ * Value of PREF_CURRENT_PLAYER_STATUS if media player status is paused.
+ */
public static final int PLAYER_STATUS_PAUSED = 2;
- /** Value of PREF_CURRENT_PLAYER_STATUS if media player status is neither playing nor paused. */
+ /**
+ * Value of PREF_CURRENT_PLAYER_STATUS if media player status is neither playing nor paused.
+ */
public static final int PLAYER_STATUS_OTHER = 3;
- private long currentlyPlayingFeedId;
- private long currentlyPlayingFeedMediaId;
- private long currentlyPlayingMedia;
- private boolean currentEpisodeIsStream;
- private boolean currentEpisodeIsVideo;
- private int currentPlayerStatus;
-
- private static PlaybackPreferences instance;
- private Context context;
-
- private PlaybackPreferences(Context context) {
- this.context = context;
- loadPreferences();
- }
+ private static PlaybackPreferences instance;
+ private static SharedPreferences prefs;
- /**
- * Sets up the UserPreferences class.
- *
- * @throws IllegalArgumentException
- * if context is null
- * */
- public static void createInstance(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Creating new instance of UserPreferences");
- Validate.notNull(context);
-
- instance = new PlaybackPreferences(context);
-
- PreferenceManager.getDefaultSharedPreferences(context)
- .registerOnSharedPreferenceChangeListener(instance);
- }
+ private PlaybackPreferences() {
+ }
- private void loadPreferences() {
- SharedPreferences sp = PreferenceManager
- .getDefaultSharedPreferences(context);
- currentlyPlayingFeedId = sp.getLong(PREF_CURRENTLY_PLAYING_FEED_ID, -1);
- currentlyPlayingFeedMediaId = sp.getLong(
- PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
- currentlyPlayingMedia = sp.getLong(PREF_CURRENTLY_PLAYING_MEDIA,
- NO_MEDIA_PLAYING);
- currentEpisodeIsStream = sp.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
- currentEpisodeIsVideo = sp.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
- currentPlayerStatus = sp.getInt(PREF_CURRENT_PLAYER_STATUS,
- PLAYER_STATUS_OTHER);
- }
+ public static void init(Context context) {
+ instance = new PlaybackPreferences();
+ prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ prefs.registerOnSharedPreferenceChangeListener(instance);
+ }
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
- if (key.equals(PREF_CURRENTLY_PLAYING_FEED_ID)) {
- currentlyPlayingFeedId = sp.getLong(PREF_CURRENTLY_PLAYING_FEED_ID,
- -1);
-
- } else if (key.equals(PREF_CURRENTLY_PLAYING_MEDIA)) {
- currentlyPlayingMedia = sp
- .getLong(PREF_CURRENTLY_PLAYING_MEDIA, -1);
-
- } else if (key.equals(PREF_CURRENT_EPISODE_IS_STREAM)) {
- currentEpisodeIsStream = sp.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
-
- } else if (key.equals(PREF_CURRENT_EPISODE_IS_VIDEO)) {
- currentEpisodeIsVideo = sp.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
-
- } else if (key.equals(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID)) {
- currentlyPlayingFeedMediaId = sp.getLong(
- PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
- }
- else if (key.equals(PREF_CURRENT_PLAYER_STATUS)) {
- currentPlayerStatus = sp.getInt(PREF_CURRENT_PLAYER_STATUS,
- PLAYER_STATUS_OTHER);
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key.equals(PREF_CURRENT_PLAYER_STATUS)) {
EventDistributor.getInstance().sendPlayerStatusUpdateBroadcast();
}
- }
-
- private static void instanceAvailable() {
- if (instance == null) {
- throw new IllegalStateException(
- "UserPreferences was used before being set up");
- }
- }
-
+ }
public static long getLastPlayedFeedId() {
- instanceAvailable();
- return instance.currentlyPlayingFeedId;
+ return prefs.getLong(PREF_CURRENTLY_PLAYING_FEED_ID, -1);
}
public static long getCurrentlyPlayingMedia() {
- instanceAvailable();
- return instance.currentlyPlayingMedia;
+ return prefs.getLong(PREF_CURRENTLY_PLAYING_MEDIA, NO_MEDIA_PLAYING);
}
public static long getCurrentlyPlayingFeedMediaId() {
- return instance.currentlyPlayingFeedMediaId;
+ return prefs.getLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
}
public static boolean getCurrentEpisodeIsStream() {
- instanceAvailable();
- return instance.currentEpisodeIsStream;
+ return prefs.getBoolean(PREF_CURRENT_EPISODE_IS_STREAM, true);
}
public static boolean getCurrentEpisodeIsVideo() {
- instanceAvailable();
- return instance.currentEpisodeIsVideo;
+ return prefs.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
}
public static int getCurrentPlayerStatus() {
- instanceAvailable();
- return instance.currentPlayerStatus;
+ return prefs.getInt(PREF_CURRENT_PLAYER_STATUS, PLAYER_STATUS_OTHER);
}
-
}
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 594241573..d56829c70 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
@@ -5,6 +5,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
@@ -18,6 +19,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -29,21 +31,23 @@ import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver;
/**
* Provides access to preferences set by the user in the settings screen. A
* private instance of this class must first be instantiated via
- * createInstance() or otherwise every public method will throw an Exception
+ * init() or otherwise every public method will throw an Exception
* when called.
*/
-public class UserPreferences implements
- SharedPreferences.OnSharedPreferenceChangeListener {
+public class UserPreferences {
public static final String IMPORT_DIR = "import/";
private static final String TAG = "UserPreferences";
- // User Infercasce
+ // User Interface
public static final String PREF_THEME = "prefTheme";
public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems";
+ public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder";
+ public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedCounter";
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify";
+ public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport";
// Queue
public static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront";
@@ -54,7 +58,7 @@ public class UserPreferences implements
public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue";
public static final String PREF_AUTO_DELETE = "prefAutoDelete";
public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs";
- private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray";
+ public static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray";
public static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss";
public static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall";
@@ -74,193 +78,42 @@ public class UserPreferences implements
// Other
public static final String PREF_DATA_FOLDER = "prefDataFolder";
+ public static final String PREF_IMAGE_CACHE_SIZE = "prefImageCacheSize";
// Mediaplayer
public static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
private static final String PREF_FAST_FORWARD_SECS = "prefFastForwardSecs";
private static final String PREF_REWIND_SECS = "prefRewindSecs";
public static final String PREF_QUEUE_LOCKED = "prefQueueLocked";
+ public static final String IMAGE_CACHE_DEFAULT_VALUE = "100";
+ public static final int IMAGE_CACHE_SIZE_MINIMUM = 20;
- // TODO: Make this value configurable
- private static final float PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT = 0.8f;
-
+ // Constants
private static int EPISODE_CACHE_SIZE_UNLIMITED = -1;
+ public static int FEED_ORDER_UNPLAYED_EPISODES = 0;
+ public static int FEED_ORDER_ALPHABETICAL = 1;
+ public static int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0;
+ public static int FEED_COUNTER_SHOW_NEW = 1;
+ public static int FEED_COUNTER_SHOW_UNPLAYED = 2;
+ public static int FEED_COUNTER_SHOW_NONE = 3;
- private static UserPreferences instance;
- private final Context context;
-
- // User Interface
- private int theme;
- private List<String> hiddenDrawerItems;
- private int notifyPriority;
- private boolean persistNotify;
-
- // Queue
- private boolean enqueueAtFront;
-
- // Playback
- private boolean pauseOnHeadsetDisconnect;
- private boolean unpauseOnHeadsetReconnect;
- private boolean followQueue;
- private boolean autoDelete;
- private int smartMarkAsPlayedSecs;
- private String[] playbackSpeedArray;
- private boolean pauseForFocusLoss;
- private boolean resumeAfterCall;
-
- // Network
- private long updateInterval;
- private boolean allowMobileUpdate;
- private int parallelDownloads;
- private int episodeCacheSize;
- private boolean enableAutodownload;
- private boolean enableAutodownloadOnBattery;
- private boolean enableAutodownloadWifiFilter;
- private String[] autodownloadSelectedNetworks;
-
- // Services
- private boolean autoFlattr;
- private float autoFlattrPlayedDurationThreshold;
-
- // Settings somewhere in the GUI
- private String playbackSpeed;
- private int fastForwardSecs;
- private int rewindSecs;
- private boolean queueLocked;
-
-
- private UserPreferences(Context context) {
- this.context = context;
- loadPreferences();
- }
+ private static Context context;
+ private static SharedPreferences prefs;
/**
* Sets up the UserPreferences class.
*
* @throws IllegalArgumentException if context is null
*/
- public static void createInstance(Context context) {
+ public static void init(Context context) {
Log.d(TAG, "Creating new instance of UserPreferences");
Validate.notNull(context);
- instance = new UserPreferences(context);
+ UserPreferences.context = context;
+ UserPreferences.prefs = PreferenceManager.getDefaultSharedPreferences(context);
createImportDirectory();
createNoMediaFile();
- PreferenceManager.getDefaultSharedPreferences(context)
- .registerOnSharedPreferenceChangeListener(instance);
-
- }
-
- private void loadPreferences() {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
-
- // User Interface
- theme = readThemeValue(sp.getString(PREF_THEME, "0"));
- if (sp.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) {
- notifyPriority = NotificationCompat.PRIORITY_MAX;
- } else {
- notifyPriority = NotificationCompat.PRIORITY_DEFAULT;
- }
- hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ','));
- persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false);
-
- // Queue
- enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false);
-
- // Playback
- pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
- unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true);
- followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false);
- autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
- smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
- playbackSpeedArray = readPlaybackSpeedArray(sp.getString(
- PREF_PLAYBACK_SPEED_ARRAY, null));
- pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false);
-
- // Network
- updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL, "0"));
- allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false);
- parallelDownloads = Integer.valueOf(sp.getString(PREF_PARALLEL_DOWNLOADS, "6"));
- EPISODE_CACHE_SIZE_UNLIMITED = context.getResources().getInteger(
- R.integer.episode_cache_size_unlimited);
- episodeCacheSize = readEpisodeCacheSizeInternal(sp.getString(PREF_EPISODE_CACHE_SIZE, "20"));
- enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
- enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true);
- enableAutodownloadWifiFilter = sp.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false);
- autodownloadSelectedNetworks = StringUtils.split(
- sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ',');
-
- // Services
- autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false);
- autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD,
- PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT);
-
- // MediaPlayer
- playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
- fastForwardSecs = sp.getInt(PREF_FAST_FORWARD_SECS, 30);
- rewindSecs = sp.getInt(PREF_REWIND_SECS, 30);
- queueLocked = sp.getBoolean(PREF_QUEUE_LOCKED, false);
- }
-
- private int readThemeValue(String valueFromPrefs) {
- switch (Integer.parseInt(valueFromPrefs)) {
- case 0:
- return R.style.Theme_AntennaPod_Light;
- case 1:
- return R.style.Theme_AntennaPod_Dark;
- default:
- return R.style.Theme_AntennaPod_Light;
- }
- }
-
- private long readUpdateInterval(String valueFromPrefs) {
- int hours = Integer.parseInt(valueFromPrefs);
- return TimeUnit.HOURS.toMillis(hours);
- }
-
- private int readEpisodeCacheSizeInternal(String valueFromPrefs) {
- if (valueFromPrefs.equals(context
- .getString(R.string.pref_episode_cache_unlimited))) {
- return EPISODE_CACHE_SIZE_UNLIMITED;
- } else {
- return Integer.valueOf(valueFromPrefs);
- }
- }
-
- private String[] readPlaybackSpeedArray(String valueFromPrefs) {
- String[] selectedSpeeds = null;
- // If this preference hasn't been set yet, return the default options
- if (valueFromPrefs == null) {
- String[] allSpeeds = context.getResources().getStringArray(
- R.array.playback_speed_values);
- List<String> speedList = new LinkedList<String>();
- for (String speedStr : allSpeeds) {
- float speed = Float.parseFloat(speedStr);
- if (speed < 2.0001 && speed * 10 % 1 == 0) {
- speedList.add(speedStr);
- }
- }
- selectedSpeeds = speedList.toArray(new String[speedList.size()]);
- } else {
- try {
- JSONArray jsonArray = new JSONArray(valueFromPrefs);
- selectedSpeeds = new String[jsonArray.length()];
- for (int i = 0; i < jsonArray.length(); i++) {
- selectedSpeeds[i] = jsonArray.getString(i);
- }
- } catch (JSONException e) {
- Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray");
- e.printStackTrace();
- }
- }
- return selectedSpeeds;
- }
-
- private static void instanceAvailable() {
- if (instance == null) {
- throw new IllegalStateException("UserPreferences was used before being set up");
- }
}
/**
@@ -269,8 +122,7 @@ public class UserPreferences implements
* @return R.style.Theme_AntennaPod_Light or R.style.Theme_AntennaPod_Dark
*/
public static int getTheme() {
- instanceAvailable();
- return instance.theme;
+ return readThemeValue(prefs.getString(PREF_THEME, "0"));
}
public static int getNoTitleTheme() {
@@ -283,8 +135,18 @@ public class UserPreferences implements
}
public static List<String> getHiddenDrawerItems() {
- instanceAvailable();
- return new ArrayList<String>(instance.hiddenDrawerItems);
+ String hiddenItems = prefs.getString(PREF_HIDDEN_DRAWER_ITEMS, "");
+ return new ArrayList<String>(Arrays.asList(StringUtils.split(hiddenItems, ',')));
+ }
+
+ public static int getFeedOrder() {
+ String value = prefs.getString(PREF_DRAWER_FEED_ORDER, "0");
+ return Integer.valueOf(value);
+ }
+
+ public static int getFeedCounter() {
+ String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "0");
+ return Integer.valueOf(value);
}
/**
@@ -293,8 +155,11 @@ public class UserPreferences implements
* @return NotificationCompat.PRIORITY_MAX or NotificationCompat.PRIORITY_DEFAULT
*/
public static int getNotifyPriority() {
- instanceAvailable();
- return instance.notifyPriority;
+ if (prefs.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) {
+ return NotificationCompat.PRIORITY_MAX;
+ } else {
+ return NotificationCompat.PRIORITY_DEFAULT;
+ }
}
/**
@@ -303,8 +168,16 @@ public class UserPreferences implements
* @return {@code true} if notifications are persistent, {@code false} otherwise
*/
public static boolean isPersistNotify() {
- instanceAvailable();
- return instance.persistNotify;
+ return prefs.getBoolean(PREF_PERSISTENT_NOTIFICATION, false);
+ }
+
+ /**
+ * Returns true if download reports are shown
+ *
+ * @return {@code true} if download reports are shown, {@code false} otherwise
+ */
+ public static boolean showDownloadReport() {
+ return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true);
}
/**
@@ -313,73 +186,77 @@ public class UserPreferences implements
* @return {@code true} if new queue elements are added to the front; {@code false} otherwise
*/
public static boolean enqueueAtFront() {
- instanceAvailable();
- return instance.enqueueAtFront;
+ return prefs.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false);
}
public static boolean isPauseOnHeadsetDisconnect() {
- instanceAvailable();
- return instance.pauseOnHeadsetDisconnect;
+ return prefs.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
}
public static boolean isUnpauseOnHeadsetReconnect() {
- instanceAvailable();
- return instance.unpauseOnHeadsetReconnect;
+ return prefs.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true);
}
public static boolean isFollowQueue() {
- instanceAvailable();
- return instance.followQueue;
+ return prefs.getBoolean(PREF_FOLLOW_QUEUE, false);
}
public static boolean isAutoDelete() {
- instanceAvailable();
- return instance.autoDelete;
+ return prefs.getBoolean(PREF_AUTO_DELETE, false);
}
public static int getSmartMarkAsPlayedSecs() {
- instanceAvailable();
- return instance.smartMarkAsPlayedSecs;
+ return Integer.valueOf(prefs.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
}
public static boolean isAutoFlattr() {
- instanceAvailable();
- return instance.autoFlattr;
+ return prefs.getBoolean(PREF_AUTO_FLATTR, false);
}
public static String getPlaybackSpeed() {
- instanceAvailable();
- return instance.playbackSpeed;
+ return prefs.getString(PREF_PLAYBACK_SPEED, "1.0");
}
public static String[] getPlaybackSpeedArray() {
- instanceAvailable();
- return instance.playbackSpeedArray;
+ return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null));
}
public static boolean shouldPauseForFocusLoss() {
- instanceAvailable();
- return instance.pauseForFocusLoss;
+ return prefs.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false);
}
public static long getUpdateInterval() {
- instanceAvailable();
- return instance.updateInterval;
+ String updateInterval = prefs.getString(PREF_UPDATE_INTERVAL, "0");
+ if(false == updateInterval.contains(":")) {
+ return readUpdateInterval(updateInterval);
+ } else {
+ return 0;
+ }
+ }
+
+ public static int[] getUpdateTimeOfDay() {
+ String datetime = prefs.getString(PREF_UPDATE_INTERVAL, "");
+ if(datetime.length() >= 3 && datetime.contains(":")) {
+ String[] parts = datetime.split(":");
+ int hourOfDay = Integer.valueOf(parts[0]);
+ int minute = Integer.valueOf(parts[1]);
+ return new int[] { hourOfDay, minute };
+ } else {
+ return new int[0];
+ }
}
public static boolean isAllowMobileUpdate() {
- instanceAvailable();
- return instance.allowMobileUpdate;
+ return prefs.getBoolean(PREF_MOBILE_UPDATE, false);
}
public static int getParallelDownloads() {
- instanceAvailable();
- return instance.parallelDownloads;
+ return Integer.valueOf(prefs.getString(PREF_PARALLEL_DOWNLOADS, "4"));
}
public static int getEpisodeCacheSizeUnlimited() {
- return EPISODE_CACHE_SIZE_UNLIMITED;
+ return context.getResources().getInteger(R.integer.episode_cache_size_unlimited);
}
/**
@@ -388,33 +265,40 @@ public class UserPreferences implements
* 'unlimited'.
*/
public static int getEpisodeCacheSize() {
- instanceAvailable();
- return instance.episodeCacheSize;
+ return readEpisodeCacheSizeInternal(prefs.getString(PREF_EPISODE_CACHE_SIZE, "20"));
}
public static boolean isEnableAutodownload() {
- instanceAvailable();
- return instance.enableAutodownload;
+ return prefs.getBoolean(PREF_ENABLE_AUTODL, false);
}
public static boolean isEnableAutodownloadOnBattery() {
- instanceAvailable();
- return instance.enableAutodownloadOnBattery;
+ return prefs.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true);
}
public static boolean isEnableAutodownloadWifiFilter() {
- instanceAvailable();
- return instance.enableAutodownloadWifiFilter;
+ return prefs.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false);
+ }
+
+ public static int getImageCacheSize() {
+ String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE);
+ int cacheSizeInt = Integer.valueOf(cacheSizeString);
+ // if the cache size is too small the user won't get any images at all
+ // that's bad, force it back to the default.
+ if (cacheSizeInt < IMAGE_CACHE_SIZE_MINIMUM) {
+ prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).apply();
+ cacheSizeInt = Integer.valueOf(IMAGE_CACHE_DEFAULT_VALUE);
+ }
+ int cacheSizeMB = cacheSizeInt * 1024 * 1024;
+ return cacheSizeMB;
}
public static int getFastFowardSecs() {
- instanceAvailable();
- return instance.fastForwardSecs;
+ return prefs.getInt(PREF_FAST_FORWARD_SECS, 30);
}
public static int getRewindSecs() {
- instanceAvailable();
- return instance.rewindSecs;
+ return prefs.getInt(PREF_REWIND_SECS, 30);
}
@@ -423,145 +307,38 @@ public class UserPreferences implements
* duration.
*/
public static float getAutoFlattrPlayedDurationThreshold() {
- instanceAvailable();
- return instance.autoFlattrPlayedDurationThreshold;
+ return prefs.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, 0.8f);
}
public static String[] getAutodownloadSelectedNetworks() {
- instanceAvailable();
- return instance.autodownloadSelectedNetworks;
+ String selectedNetWorks = prefs.getString(PREF_AUTODL_SELECTED_NETWORKS, "");
+ return StringUtils.split(selectedNetWorks, ',');
}
public static boolean shouldResumeAfterCall() {
- instanceAvailable();
- return instance.resumeAfterCall;
+ return prefs.getBoolean(PREF_RESUME_AFTER_CALL, true);
}
public static boolean isQueueLocked() {
- instanceAvailable();
- return instance.queueLocked;
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
- Log.d(TAG, "Registered change of user preferences. Key: " + key);
- switch(key) {
- // User Interface
- case PREF_THEME:
- theme = readThemeValue(sp.getString(PREF_THEME, ""));
- break;
- case PREF_HIDDEN_DRAWER_ITEMS:
- hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ','));
- break;
- case PREF_EXPANDED_NOTIFICATION:
- if (sp.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) {
- notifyPriority = NotificationCompat.PRIORITY_MAX;
- } else {
- notifyPriority = NotificationCompat.PRIORITY_DEFAULT;
- }
- break;
- case PREF_PERSISTENT_NOTIFICATION:
- persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false);
- break;
- // Queue
- case PREF_QUEUE_ADD_TO_FRONT:
- enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false);
- break;
- // Playback
- case PREF_PAUSE_ON_HEADSET_DISCONNECT:
- pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
- break;
- case PREF_UNPAUSE_ON_HEADSET_RECONNECT:
- unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true);
- break;
- case PREF_FOLLOW_QUEUE:
- followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false);
- break;
- case PREF_AUTO_DELETE:
- autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false);
- break;
- case PREF_SMART_MARK_AS_PLAYED_SECS:
- smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
- break;
- case PREF_PLAYBACK_SPEED_ARRAY:
- playbackSpeedArray = readPlaybackSpeedArray(sp.getString(PREF_PLAYBACK_SPEED_ARRAY, null));
- break;
- case PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS:
- pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false);
- break;
- case PREF_RESUME_AFTER_CALL:
- resumeAfterCall = sp.getBoolean(PREF_RESUME_AFTER_CALL, true);
- break;
- // Network
- case PREF_UPDATE_INTERVAL:
- updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL, "0"));
- ClientConfig.applicationCallbacks.setUpdateInterval(updateInterval);
- break;
- case PREF_MOBILE_UPDATE:
- allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false);
- break;
- case PREF_PARALLEL_DOWNLOADS:
- parallelDownloads = Integer.valueOf(sp.getString(PREF_PARALLEL_DOWNLOADS, "6"));
- break;
- case PREF_EPISODE_CACHE_SIZE:
- episodeCacheSize = readEpisodeCacheSizeInternal(sp.getString(PREF_EPISODE_CACHE_SIZE, "20"));
- break;
- case PREF_ENABLE_AUTODL:
- enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
- break;
- case PREF_ENABLE_AUTODL_ON_BATTERY:
- enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true);
- break;
- case PREF_ENABLE_AUTODL_WIFI_FILTER:
- enableAutodownloadWifiFilter = sp.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false);
- break;
- case PREF_AUTODL_SELECTED_NETWORKS:
- autodownloadSelectedNetworks = StringUtils.split(
- sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ',');
- break;
- // Services
- case PREF_AUTO_FLATTR:
- autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false);
- break;
- case PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD:
- autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD,
- PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT);
- break;
- // Mediaplayer
- case PREF_PLAYBACK_SPEED:
- playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
- break;
- case PREF_FAST_FORWARD_SECS:
- fastForwardSecs = sp.getInt(PREF_FAST_FORWARD_SECS, 30);
- break;
- case PREF_REWIND_SECS:
- rewindSecs = sp.getInt(PREF_REWIND_SECS, 30);
- break;
- case PREF_QUEUE_LOCKED:
- queueLocked = sp.getBoolean(PREF_QUEUE_LOCKED, false);
- break;
- default:
- Log.w(TAG, "Unhandled key: " + key);
- }
+ return prefs.getBoolean(PREF_QUEUE_LOCKED, false);
}
public static void setPrefFastForwardSecs(int secs) {
- Log.d(TAG, "setPrefFastForwardSecs(" + secs +")");
- SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(instance.context).edit();
- editor.putInt(PREF_FAST_FORWARD_SECS, secs);
- editor.commit();
+ prefs.edit()
+ .putInt(PREF_FAST_FORWARD_SECS, secs)
+ .apply();
}
public static void setPrefRewindSecs(int secs) {
- Log.d(TAG, "setPrefRewindSecs(" + secs +")");
- SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(instance.context).edit();
- editor.putInt(PREF_REWIND_SECS, secs);
- editor.commit();
+ prefs.edit()
+ .putInt(PREF_REWIND_SECS, secs)
+ .apply();
}
public static void setPlaybackSpeed(String speed) {
- PreferenceManager.getDefaultSharedPreferences(instance.context).edit()
- .putString(PREF_PLAYBACK_SPEED, speed).apply();
+ prefs.edit()
+ .putString(PREF_PLAYBACK_SPEED, speed)
+ .apply();
}
public static void setPlaybackSpeedArray(String[] speeds) {
@@ -569,72 +346,117 @@ public class UserPreferences implements
for (String speed : speeds) {
jsonArray.put(speed);
}
- PreferenceManager.getDefaultSharedPreferences(instance.context).edit()
- .putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString())
- .apply();
+ prefs.edit()
+ .putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString())
+ .apply();
+ }
+
+ public static void setAutodownloadSelectedNetworks(String[] value) {
+ prefs.edit()
+ .putString(PREF_AUTODL_SELECTED_NETWORKS, StringUtils.join(value, ','))
+ .apply();
}
- public static void setAutodownloadSelectedNetworks(Context context,
- String[] value) {
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(context.getApplicationContext())
- .edit();
- editor.putString(PREF_AUTODL_SELECTED_NETWORKS,
- StringUtils.join(value, ','));
- editor.commit();
+ /**
+ * Sets the update interval value.
+ */
+ public static void setUpdateInterval(long hours) {
+ prefs.edit()
+ .putString(PREF_UPDATE_INTERVAL, String.valueOf(hours))
+ .apply();
+ // when updating with an interval, we assume the user wants
+ // to update *now* and then every 'hours' interval thereafter.
+ restartUpdateAlarm(true);
}
/**
- * Sets the update interval value. Should only be used for testing purposes!
+ * Sets the update interval value.
*/
- public static void setUpdateInterval(Context context, long newValue) {
- instanceAvailable();
- SharedPreferences.Editor editor = PreferenceManager
- .getDefaultSharedPreferences(context.getApplicationContext())
- .edit();
- editor.putString(PREF_UPDATE_INTERVAL,
- String.valueOf(newValue));
- editor.commit();
- instance.updateInterval = newValue;
+ public static void setUpdateTimeOfDay(int hourOfDay, int minute) {
+ prefs.edit()
+ .putString(PREF_UPDATE_INTERVAL, hourOfDay + ":" + minute)
+ .apply();
+ restartUpdateAlarm(false);
}
/**
* Change the auto-flattr settings
*
- * @param context For accessing the shared preferences
* @param enabled Whether automatic flattring should be enabled at all
* @param autoFlattrThreshold The percentage of playback time after which an episode should be
* flattrd. Must be a value between 0 and 1 (inclusive)
* */
- public static void setAutoFlattrSettings(Context context, boolean enabled, float autoFlattrThreshold) {
- instanceAvailable();
+ public static void setAutoFlattrSettings( boolean enabled, float autoFlattrThreshold) {
Validate.inclusiveBetween(0.0, 1.0, autoFlattrThreshold);
- PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext())
- .edit()
- .putBoolean(PREF_AUTO_FLATTR, enabled)
- .putFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, autoFlattrThreshold)
- .commit();
- instance.autoFlattr = enabled;
- instance.autoFlattrPlayedDurationThreshold = autoFlattrThreshold;
+ prefs.edit()
+ .putBoolean(PREF_AUTO_FLATTR, enabled)
+ .putFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, autoFlattrThreshold)
+ .apply();
}
public static void setHiddenDrawerItems(Context context, List<String> items) {
- instanceAvailable();
- instance.hiddenDrawerItems = items;
String str = StringUtils.join(items, ',');
- PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext())
- .edit()
- .putString(PREF_HIDDEN_DRAWER_ITEMS, str)
- .commit();
+ prefs.edit()
+ .putString(PREF_HIDDEN_DRAWER_ITEMS, str)
+ .apply();
}
public static void setQueueLocked(boolean locked) {
- instanceAvailable();
- instance.queueLocked = locked;
- PreferenceManager.getDefaultSharedPreferences(instance.context)
- .edit()
- .putBoolean(PREF_QUEUE_LOCKED, locked)
- .commit();
+ prefs.edit()
+ .putBoolean(PREF_QUEUE_LOCKED, locked)
+ .apply();
+ }
+
+ private static int readThemeValue(String valueFromPrefs) {
+ switch (Integer.parseInt(valueFromPrefs)) {
+ case 0:
+ return R.style.Theme_AntennaPod_Light;
+ case 1:
+ return R.style.Theme_AntennaPod_Dark;
+ default:
+ return R.style.Theme_AntennaPod_Light;
+ }
+ }
+
+ private static long readUpdateInterval(String valueFromPrefs) {
+ int hours = Integer.parseInt(valueFromPrefs);
+ return TimeUnit.HOURS.toMillis(hours);
+ }
+
+ private static int readEpisodeCacheSizeInternal(String valueFromPrefs) {
+ if (valueFromPrefs.equals(context.getString(R.string.pref_episode_cache_unlimited))) {
+ return EPISODE_CACHE_SIZE_UNLIMITED;
+ } else {
+ return Integer.valueOf(valueFromPrefs);
+ }
+ }
+
+ private static String[] readPlaybackSpeedArray(String valueFromPrefs) {
+ String[] selectedSpeeds = null;
+ // If this preference hasn't been set yet, return the default options
+ if (valueFromPrefs == null) {
+ String[] allSpeeds = context.getResources().getStringArray(R.array.playback_speed_values);
+ List<String> speedList = new LinkedList<String>();
+ for (String speedStr : allSpeeds) {
+ float speed = Float.parseFloat(speedStr);
+ if (speed < 2.0001 && speed * 10 % 1 == 0) {
+ speedList.add(speedStr);
+ }
+ }
+ selectedSpeeds = speedList.toArray(new String[speedList.size()]);
+ } else {
+ try {
+ JSONArray jsonArray = new JSONArray(valueFromPrefs);
+ selectedSpeeds = new String[jsonArray.length()];
+ for (int i = 0; i < jsonArray.length(); i++) {
+ selectedSpeeds[i] = jsonArray.getString(i);
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray");
+ e.printStackTrace();
+ }
+ }
+ return selectedSpeeds;
}
@@ -648,9 +470,6 @@ public class UserPreferences implements
* could not be created.
*/
public static File getDataFolder(Context context, String type) {
- instanceAvailable();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(context.getApplicationContext());
String strDir = prefs.getString(PREF_DATA_FOLDER, null);
if (strDir == null) {
Log.d(TAG, "Using default data folder");
@@ -696,12 +515,9 @@ public class UserPreferences implements
public static void setDataFolder(String dir) {
Log.d(TAG, "Result from DirectoryChooser: " + dir);
- instanceAvailable();
- SharedPreferences prefs = PreferenceManager
- .getDefaultSharedPreferences(instance.context);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(PREF_DATA_FOLDER, dir);
- editor.commit();
+ prefs.edit()
+ .putString(PREF_DATA_FOLDER, dir)
+ .apply();
createImportDirectory();
}
@@ -709,8 +525,7 @@ public class UserPreferences implements
* Create a .nomedia file to prevent scanning by the media scanner.
*/
private static void createNoMediaFile() {
- File f = new File(instance.context.getExternalFilesDir(null),
- ".nomedia");
+ File f = new File(context.getExternalFilesDir(null), ".nomedia");
if (!f.exists()) {
try {
f.createNewFile();
@@ -727,8 +542,7 @@ public class UserPreferences implements
* available
*/
private static void createImportDirectory() {
- File importDir = getDataFolder(instance.context,
- IMPORT_DIR);
+ File importDir = getDataFolder(context, IMPORT_DIR);
if (importDir != null) {
if (importDir.exists()) {
Log.d(TAG, "Import directory already exists");
@@ -741,32 +555,69 @@ public class UserPreferences implements
}
}
+ public static void restartUpdateAlarm(boolean now) {
+ int[] timeOfDay = getUpdateTimeOfDay();
+ Log.d(TAG, "timeOfDay: " + Arrays.toString(timeOfDay));
+ if (timeOfDay.length == 2) {
+ restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]);
+ } else {
+ long hours = getUpdateInterval();
+ long startTrigger = hours;
+ if (now) {
+ startTrigger = TimeUnit.SECONDS.toMillis(10);
+ }
+ restartUpdateIntervalAlarm(startTrigger, hours);
+ }
+ }
+
/**
- * Updates alarm registered with the AlarmManager service or deactivates it.
+ * Sets the interval in which the feeds are refreshed automatically
*/
- public static void restartUpdateAlarm(long triggerAtMillis, long intervalMillis) {
- instanceAvailable();
+ public static void restartUpdateIntervalAlarm(long triggerAtMillis, long intervalMillis) {
Log.d(TAG, "Restarting update alarm.");
- AlarmManager alarmManager = (AlarmManager) instance.context
- .getSystemService(Context.ALARM_SERVICE);
- PendingIntent updateIntent = PendingIntent.getBroadcast(
- instance.context, 0, new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0);
+ AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0,
+ new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0);
alarmManager.cancel(updateIntent);
- if (intervalMillis != 0) {
- alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, intervalMillis,
+ if (intervalMillis > 0) {
+ alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + triggerAtMillis,
updateIntent);
- Log.d(TAG, "Changed alarm to new interval");
+ Log.d(TAG, "Changed alarm to new interval " + TimeUnit.MILLISECONDS.toHours(intervalMillis) + " h");
} else {
Log.d(TAG, "Automatic update was deactivated");
}
}
+ /**
+ * Sets time of day the feeds are refreshed automatically
+ */
+ public static void restartUpdateTimeOfDayAlarm(int hoursOfDay, int minute) {
+ Log.d(TAG, "Restarting update alarm.");
+ AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0,
+ new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0);
+ alarmManager.cancel(updateIntent);
+
+ Calendar now = Calendar.getInstance();
+ Calendar alarm = (Calendar)now.clone();
+ alarm.set(Calendar.HOUR_OF_DAY, hoursOfDay);
+ alarm.set(Calendar.MINUTE, minute);
+ if (alarm.before(now) || alarm.equals(now)) {
+ alarm.add(Calendar.DATE, 1);
+ }
+ Log.d(TAG, "Alarm set for: " + alarm.toString() + " : " + alarm.getTimeInMillis());
+ alarmManager.set(AlarmManager.RTC_WAKEUP,
+ alarm.getTimeInMillis(),
+ updateIntent);
+ Log.d(TAG, "Changed alarm to new time of day " + hoursOfDay + ":" + minute);
+ }
/**
* Reads episode cache size as it is saved in the episode_cache_size_values array.
*/
public static int readEpisodeCacheSize(String valueFromPrefs) {
- instanceAvailable();
- return instance.readEpisodeCacheSizeInternal(valueFromPrefs);
+ return readEpisodeCacheSizeInternal(valueFromPrefs);
}
+
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java
index 84277b6d5..7fa92f30c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java
@@ -7,28 +7,25 @@ import android.util.Log;
import org.apache.commons.lang3.StringUtils;
-import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.ClientConfig;
+import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
/** Listens for events that make it necessary to reset the update alarm. */
public class AlarmUpdateReceiver extends BroadcastReceiver {
+
private static final String TAG = "AlarmUpdateReceiver";
@Override
public void onReceive(Context context, Intent intent) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Received intent");
+ Log.d(TAG, "Received intent");
if (StringUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resetting update alarm after reboot");
+ Log.d(TAG, "Resetting update alarm after reboot");
} else if (StringUtils.equals(intent.getAction(), Intent.ACTION_PACKAGE_REPLACED)) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Resetting update alarm after app upgrade");
+ Log.d(TAG, "Resetting update alarm after app upgrade");
}
-
- ClientConfig.applicationCallbacks.setUpdateInterval(UserPreferences.getUpdateInterval());
-
+ PlaybackPreferences.init(context);
+ UserPreferences.init(context);
+ UserPreferences.restartUpdateAlarm(false);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
index d37f97a5f..b959c7301 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.util.Log;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.util.NetworkUtils;
@@ -18,11 +19,12 @@ public class FeedUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received intent");
- if (NetworkUtils.isDownloadAllowed(context)) {
- DBTasks.refreshExpiredFeeds(context);
+ if (NetworkUtils.isDownloadAllowed()) {
+ DBTasks.refreshAllFeeds(context, null);
} else {
Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed");
}
+ UserPreferences.restartUpdateAlarm(false);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java
new file mode 100644
index 000000000..2f6e67a28
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java
@@ -0,0 +1,76 @@
+package de.danoeh.antennapod.core.service;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+
+import de.danoeh.antennapod.core.event.FeedMediaEvent;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.greenrobot.event.EventBus;
+
+public class FeedMediaSizeService extends IntentService {
+
+ private final static String TAG = "FeedMediaSizeService";
+
+ public FeedMediaSizeService() {
+ super(TAG);
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ Log.d(TAG, "onHandleIntent()");
+ if(false == NetworkUtils.isDownloadAllowed()) {
+ return;
+ }
+ List<FeedMedia> list = DBReader.getFeedMediaUnknownSize(this);
+ for (FeedMedia media : list) {
+ Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url());
+ if(false == NetworkUtils.isDownloadAllowed()) {
+ return;
+ }
+ long size = Integer.MIN_VALUE;
+ if (media.isDownloaded()) {
+ File mediaFile = new File(media.getLocalMediaUrl());
+ if(mediaFile.exists()) {
+ size = mediaFile.length();
+ }
+ } else if (false == media.checkedOnSizeButUnknown()) {
+ // only query the network if we haven't already checked
+ HttpURLConnection conn = null;
+ try {
+ URL url = new URL(media.getDownload_url());
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestProperty("Accept-Encoding", "");
+ conn.setRequestMethod("HEAD");
+ size = conn.getContentLength();
+ } catch (IOException e) {
+ Log.d(TAG, media.getDownload_url());
+ e.printStackTrace();
+ } finally {
+ if (conn != null) {
+ conn.disconnect();
+ }
+ }
+ }
+ if (size <= 0) {
+ // they didn't tell us the size, but we don't want to keep querying on it
+ media.setCheckedOnSizeButUnknown();
+ } else {
+ media.setSize(size);
+ }
+ Log.d(TAG, "Size now: " + media.getSize());
+ DBWriter.setFeedMedia(this, media);
+ EventBus.getDefault().post(FeedMediaEvent.update(media));
+ }
+ }
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java
index 3f2222f42..b80b4303f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java
@@ -108,7 +108,7 @@ public class GpodnetSyncService extends Service {
private synchronized void sync() {
- if (GpodnetPreferences.loggedIn() == false || NetworkUtils.networkAvailable(this) == false) {
+ if (GpodnetPreferences.loggedIn() == false || NetworkUtils.networkAvailable() == false) {
stopSelf();
return;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
index e7b226eca..4fdaf6843 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
@@ -243,7 +243,7 @@ public class DownloadService extends Service {
handler = new Handler();
newMediaFiles = Collections.synchronizedList(new ArrayList<Long>());
reportQueue = Collections.synchronizedList(new ArrayList<DownloadStatus>());
- downloads = new ArrayList<Downloader>();
+ downloads = Collections.synchronizedList(new ArrayList<Downloader>());
numberOfDownloads = new AtomicInteger(0);
IntentFilter cancelDownloadReceiverFilter = new IntentFilter();
@@ -309,7 +309,8 @@ public class DownloadService extends Service {
Log.d(TAG, "Service shutting down");
isRunning = false;
- if (ClientConfig.downloadServiceCallbacks.shouldCreateReport()) {
+ if (ClientConfig.downloadServiceCallbacks.shouldCreateReport() &&
+ UserPreferences.showDownloadReport()) {
updateReport();
}
@@ -324,7 +325,13 @@ public class DownloadService extends Service {
cancelNotificationUpdater();
unregisterReceiver(cancelDownloadReceiver);
+ // TODO: I'm not sure this is actually needed.
+ // We could just invoke the autodownloadUndownloadeditems method
+ // and it would get everything it's supposed to. By sending it the
+ // items in newMediaFiles we're overriding the download algorithm,
+ // which is not something we should probably do.
if (!newMediaFiles.isEmpty()) {
+ Log.d(TAG, "newMediaFiles exist, autodownload them");
DBTasks.autodownloadUndownloadedItems(getApplicationContext(),
ArrayUtils.toPrimitive(newMediaFiles.toArray(new Long[newMediaFiles.size()])));
}
@@ -434,6 +441,7 @@ public class DownloadService extends Service {
} else {
Log.e(TAG, "Could not cancel download with url " + url);
}
+ sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
} else if (StringUtils.equals(intent.getAction(), ACTION_CANCEL_ALL_DOWNLOADS)) {
for (Downloader d : downloads) {
@@ -774,52 +782,18 @@ public class DownloadService extends Service {
for (int i = 0; i < savedFeeds.length; i++) {
Feed savedFeed = savedFeeds[i];
- // Download Feed Image if provided and not downloaded
- if (savedFeed.getImage() != null
- && savedFeed.getImage().isDownloaded() == false) {
- Log.d(TAG, "Feed has image; Downloading....");
- savedFeed.getImage().setOwner(savedFeed);
- final Feed savedFeedRef = savedFeed;
- try {
- requester.downloadImage(DownloadService.this,
- savedFeedRef.getImage());
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DBWriter.addDownloadStatus(
- DownloadService.this,
- new DownloadStatus(
- savedFeedRef.getImage(),
- savedFeedRef
- .getImage()
- .getHumanReadableIdentifier(),
- DownloadError.ERROR_REQUEST_ERROR,
- false, e.getMessage()
- )
- );
- }
- }
// queue new media files for automatic download
for (FeedItem item : savedFeed.getItems()) {
if(item.getPubDate() == null) {
Log.d(TAG, item.toString());
}
- if(item.getImage() != null && item.getImage().isDownloaded() == false) {
- item.getImage().setOwner(item);
- try {
- requester.downloadImage(DownloadService.this,
- item.getImage());
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
- }
- if (!item.isRead() && item.hasMedia() && !item.getMedia().isDownloaded()) {
+ if (item.isNew() && item.hasMedia() && !item.getMedia().isDownloaded()) {
newMediaFiles.add(item.getMedia().getId());
}
}
// If loadAllPages=true, check if another page is available and queue it for download
-
final boolean loadAllPages = results.get(i).first.getArguments().getBoolean(DownloadRequester.REQUEST_ARG_LOAD_ALL_PAGES);
final Feed feed = results.get(i).second.feed;
if (loadAllPages && feed.getNextPageLink() != null) {
@@ -889,7 +863,7 @@ public class DownloadService extends Service {
feed.setFile_url(request.getDestination());
feed.setId(request.getFeedfileId());
feed.setDownloaded(true);
- feed.setPreferences(new FeedPreferences(0, true,
+ feed.setPreferences(new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL,
request.getUsername(), request.getPassword()));
feed.setPageNr(request.getArguments().getInt(DownloadRequester.REQUEST_ARG_PAGE_NR, 0));
@@ -1143,6 +1117,7 @@ public class DownloadService extends Service {
boolean chaptersRead = false;
media.setDownloaded(true);
media.setFile_url(request.getDestination());
+ media.setHasEmbeddedPicture(null);
// Get duration
MediaMetadataRetriever mmr = null;
@@ -1170,12 +1145,16 @@ public class DownloadService extends Service {
}
try {
- if (chaptersRead) {
- DBWriter.setFeedItem(DownloadService.this, media.getItem()).get();
- }
+ // we've received the media, we don't want to autodownload it again
+ FeedItem item = media.getItem();
+ item.setAutoDownload(false);
+
+ // update the db
+ DBWriter.setFeedItem(DownloadService.this, item).get();
+
DBWriter.setFeedMedia(DownloadService.this, media).get();
- if (!DBTasks.isInQueue(DownloadService.this, media.getItem().getId())) {
- DBWriter.addQueueItem(DownloadService.this, media.getItem().getId()).get();
+ if (!DBTasks.isInQueue(DownloadService.this, item.getId())) {
+ DBWriter.addQueueItem(DownloadService.this, item.getId()).get();
}
} catch (ExecutionException e) {
e.printStackTrace();
@@ -1240,7 +1219,16 @@ public class DownloadService extends Service {
}
public List<Downloader> getDownloads() {
- return downloads;
+ if (downloads == null) {
+ // this is unusual, but it should be OK, we'll return
+ // an empty list to make it easy for people
+ return new ArrayList<Downloader>();
+ }
+
+ // return a copy of downloads, but the copy doesn't need to be synchronized.
+ synchronized (downloads) {
+ return new ArrayList<Downloader>(downloads);
+ }
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index 3f6769ee4..7e3f27856 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -29,12 +29,16 @@ import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.widget.Toast;
-import com.squareup.picasso.Picasso;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.bumptech.glide.request.animation.GlideAnimation;
+import com.bumptech.glide.request.target.SimpleTarget;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.util.List;
+import java.util.concurrent.ExecutionException;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
@@ -42,6 +46,7 @@ import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction.Action;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
@@ -442,7 +447,7 @@ public class PlaybackService extends Service {
}
writePlayerStatusPlaybackPreferences();
- final Playable playable = mediaPlayer.getPSMPInfo().playable;
+ final Playable playable = newInfo.playable;
// Gpodder: send play action
if(GpodnetPreferences.loggedIn() && playable instanceof FeedMedia) {
@@ -525,7 +530,7 @@ public class PlaybackService extends Service {
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
final String TAG = "PlaybackService.onErrorListener";
Log.w(TAG, "An error has occured: " + what + " " + extra);
- if (mediaPlayer.getPSMPInfo().playerStatus == PlayerStatus.PLAYING) {
+ if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) {
mediaPlayer.pause(true, false);
}
sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what);
@@ -549,7 +554,7 @@ public class PlaybackService extends Service {
private void endPlayback(boolean playNextEpisode) {
Log.d(TAG, "Playback ended");
- final Playable playable = mediaPlayer.getPSMPInfo().playable;
+ final Playable playable = mediaPlayer.getPlayable();
if (playable == null) {
Log.e(TAG, "Cannot end playback: media was null");
return;
@@ -584,7 +589,7 @@ public class PlaybackService extends Service {
}
// Delete episode if enabled
- if(UserPreferences.isAutoDelete()) {
+ if(item.getFeed().getPreferences().getCurrentAutoDelete()) {
DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
Log.d(TAG, "Episode Deleted");
}
@@ -634,7 +639,7 @@ public class PlaybackService extends Service {
writePlaybackPreferencesNoMediaPlaying();
if (nextMedia != null) {
- stream = !playable.localFileAvailable();
+ stream = !nextMedia.localFileAvailable();
mediaPlayer.playMediaObject(nextMedia, stream, startWhenPrepared, prepareImmediately);
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
(nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO);
@@ -744,8 +749,7 @@ public class PlaybackService extends Service {
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext()).edit();
- PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
- int playerStatus = getCurrentPlayerStatusAsInt(info.playerStatus);
+ int playerStatus = getCurrentPlayerStatusAsInt(mediaPlayer.getPlayerStatus());
editor.putInt(
PlaybackPreferences.PREF_CURRENT_PLAYER_STATUS, playerStatus);
@@ -770,7 +774,7 @@ public class PlaybackService extends Service {
/**
* Used by setupNotification to load notification data in another thread.
*/
- private AsyncTask<Void, Void, Void> notificationSetupTask;
+ private Thread notificationSetupThread;
/**
* Prepares notification and starts the service in the foreground.
@@ -781,50 +785,47 @@ public class PlaybackService extends Service {
PlaybackService.getPlayerActivityIntent(this),
PendingIntent.FLAG_UPDATE_CURRENT);
- if (notificationSetupTask != null) {
- notificationSetupTask.cancel(true);
+ if (notificationSetupThread != null) {
+ notificationSetupThread.interrupt();
}
- notificationSetupTask = new AsyncTask<Void, Void, Void>() {
+ Runnable notificationSetupTask = new Runnable() {
Bitmap icon = null;
@Override
- protected Void doInBackground(Void... params) {
+ public void run() {
Log.d(TAG, "Starting background work");
if (android.os.Build.VERSION.SDK_INT >= 11) {
if (info.playable != null) {
+ int iconSize = getResources().getDimensionPixelSize(
+ android.R.dimen.notification_large_icon_width);
try {
- int iconSize = getResources().getDimensionPixelSize(
- android.R.dimen.notification_large_icon_width);
- icon = Picasso.with(PlaybackService.this)
+ icon = Glide.with(PlaybackService.this)
.load(info.playable.getImageUri())
- .resize(iconSize, iconSize)
+ .asBitmap()
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .into(-1, -1) // this resizing would not be exact, so we have
+ // scale the bitmap ourselves
.get();
- } catch (IOException e) {
+ icon = Bitmap.createScaledBitmap(icon, iconSize, iconSize, true);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
e.printStackTrace();
}
}
-
}
if (icon == null) {
icon = BitmapFactory.decodeResource(getApplicationContext().getResources(),
ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext()));
}
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
if (mediaPlayer == null) {
return;
}
- PlaybackServiceMediaPlayer.PSMPInfo newInfo = mediaPlayer.getPSMPInfo();
+ PlayerStatus playerStatus = mediaPlayer.getPlayerStatus();
final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext());
- if (!isCancelled() &&
- started &&
- info.playable != null) {
+ if (!Thread.currentThread().isInterrupted() && started && info.playable != null) {
String contentText = info.playable.getFeedTitle();
String contentTitle = info.playable.getEpisodeTitle();
Notification notification = null;
@@ -865,7 +866,7 @@ public class PlaybackService extends Service {
.setLargeIcon(icon)
.setSmallIcon(smallIcon)
.setPriority(UserPreferences.getNotifyPriority()); // set notification priority
- if (newInfo.playerStatus == PlayerStatus.PLAYING) {
+ if (playerStatus == PlayerStatus.PLAYING) {
notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action
getString(R.string.pause_label),
pauseButtonPendingIntent);
@@ -902,15 +903,9 @@ public class PlaybackService extends Service {
Log.d(TAG, "Notification set up");
}
}
-
};
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- notificationSetupTask
- .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- notificationSetupTask.execute();
- }
-
+ notificationSetupThread = new Thread(notificationSetupTask);
+ notificationSetupThread.start();
}
/**
@@ -923,7 +918,7 @@ public class PlaybackService extends Service {
int position = getCurrentPosition();
int duration = getDuration();
float playbackSpeed = getCurrentPlaybackSpeed();
- final Playable playable = mediaPlayer.getPSMPInfo().playable;
+ final Playable playable = mediaPlayer.getPlayable();
if (position != INVALID_TIME && duration != INVALID_TIME && playable != null) {
Log.d(TAG, "Saving current position to " + position);
if (updatePlayedDuration && playable instanceof FeedMedia) {
@@ -1200,12 +1195,10 @@ public class PlaybackService extends Service {
}
public PlayerStatus getStatus() {
- return mediaPlayer.getPSMPInfo().playerStatus;
+ return mediaPlayer.getPlayerStatus();
}
- public Playable getPlayable() {
- return mediaPlayer.getPSMPInfo().playable;
- }
+ public Playable getPlayable() { return mediaPlayer.getPlayable(); }
public void setSpeed(float speed) {
mediaPlayer.setSpeed(speed);
@@ -1231,7 +1224,7 @@ public class PlaybackService extends Service {
public void seekTo(final int t) {
if(mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING
&& GpodnetPreferences.loggedIn()) {
- final Playable playable = mediaPlayer.getPSMPInfo().playable;
+ final Playable playable = mediaPlayer.getPlayable();
if (playable instanceof FeedMedia) {
FeedMedia media = (FeedMedia) playable;
FeedItem item = media.getItem();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
index 7a8e38c59..835a8c1d1 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
@@ -196,7 +196,7 @@ public class PlaybackServiceMediaPlayer {
DBWriter.markItemRead(context, item, true, false);
DBWriter.removeQueueItem(context, item, false);
DBWriter.addItemToPlaybackHistory(context, oldMedia);
- if (UserPreferences.isAutoDelete()) {
+ if (item.getFeed().getPreferences().getCurrentAutoDelete()) {
Log.d(TAG, "Delete " + oldMedia.toString());
DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId());
}
@@ -623,10 +623,6 @@ public class PlaybackServiceMediaPlayer {
return mediaType;
}
- public PlayerStatus getPlayerStatus() {
- return playerStatus;
- }
-
public boolean isStreaming() {
return stream;
}
@@ -706,6 +702,26 @@ public class PlaybackServiceMediaPlayer {
}
/**
+ * Returns the current status, if you need the media and the player status together, you should
+ * use getPSMPInfo() to make sure they're properly synchronized. Otherwise a race condition
+ * could result in nonsensical results (like a status of PLAYING, but a null playable)
+ * @return the current player status
+ */
+ public PlayerStatus getPlayerStatus() {
+ return playerStatus;
+ }
+
+ /**
+ * Returns the current media, if you need the media and the player status together, you should
+ * use getPSMPInfo() to make sure they're properly synchronized. Otherwise a race condition
+ * could result in nonsensical results (like a status of PLAYING, but a null playable)
+ * @return the current media. May be null
+ */
+ public Playable getPlayable() {
+ return media;
+ }
+
+ /**
* Returns a token to this object's MediaSession. The MediaSession should only be used for notifications
* at the moment.
*
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java
index f647fd537..a07705e69 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java
@@ -28,7 +28,7 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
List<FeedItem> delete;
for (FeedItem item : downloadedItems) {
if (item.hasMedia() && item.getMedia().isDownloaded()
- && !queue.contains(item.getId()) && item.isRead()) {
+ && !queue.contains(item.getId()) && item.isPlayed()) {
candidates.add(item);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java
index 92de1eee7..c2e971dce 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java
@@ -22,7 +22,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
private final APCleanupAlgorithm cleanupAlgorithm = new APCleanupAlgorithm();
/**
- * Looks for undownloaded episodes in the queue or list of unread items and request a download if
+ * Looks for undownloaded episodes in the queue or list of new items and request a download if
* 1. Network is available
* 2. The device is charging or the user allows auto download on battery
* 3. There is free space in the episode cache
@@ -40,7 +40,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
public void run() {
// true if we should auto download based on network status
- boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable(context)
+ boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable()
&& UserPreferences.isEnableAutodownload();
// true if we should auto download based on power status
@@ -57,12 +57,12 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
candidates = DBReader.getFeedItems(context, mediaIds);
} else {
final List<FeedItem> queue = DBReader.getQueue(context);
- final List<FeedItem> unreadItems = DBReader.getUnreadItemsList(context);
- candidates = new ArrayList<FeedItem>(queue.size() + unreadItems.size());
+ final List<FeedItem> newItems = DBReader.getNewItemsList(context);
+ candidates = new ArrayList<FeedItem>(queue.size() + newItems.size());
candidates.addAll(queue);
- for(FeedItem unreadItem : unreadItems) {
- if(candidates.contains(unreadItem) == false) {
- candidates.add(unreadItem);
+ for(FeedItem newItem : newItems) {
+ if(candidates.contains(newItem) == false) {
+ candidates.add(newItem);
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java
deleted file mode 100644
index 420bbc09d..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package de.danoeh.antennapod.core.storage;
-
-import android.content.Context;
-import android.util.Log;
-
-import org.apache.commons.io.FileUtils;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-import de.danoeh.antennapod.core.feed.FeedItem;
-
-/**
- * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPodSP apps.
- */
-public class APSPCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
- private static final String TAG = "APSPCleanupAlgorithm";
-
- final int numberOfNewAutomaticallyDownloadedEpisodes;
-
- public APSPCleanupAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
- this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
- }
-
- /**
- * Performs an automatic cleanup. Episodes that have been downloaded first will also be deleted first.
- * The episode that is currently playing as well as the n most recent episodes (the exact value is determined
- * by AppPreferences.numberOfNewAutomaticallyDownloadedEpisodes) will never be deleted.
- *
- * @param context
- * @param episodeSize The maximum amount of space that should be freed by this method
- * @return The number of episodes that have been deleted
- */
- @Override
- public int performCleanup(Context context, Integer episodeSize) {
- Log.i(TAG, String.format("performAutoCleanup(%d)", episodeSize));
- if (episodeSize <= 0) {
- return 0;
- }
-
- List<FeedItem> candidates = getAutoCleanupCandidates(context);
- List<FeedItem> deleteList = new ArrayList<FeedItem>();
- long deletedEpisodesSize = 0;
- Collections.sort(candidates, new Comparator<FeedItem>() {
- @Override
- public int compare(FeedItem lhs, FeedItem rhs) {
- File lFile = new File(lhs.getMedia().getFile_url());
- File rFile = new File(rhs.getMedia().getFile_url());
- if (!lFile.exists() || !rFile.exists()) {
- return 0;
- }
- if (FileUtils.isFileOlder(lFile, rFile)) {
- return -1;
- } else {
- return 1;
- }
- }
- });
- // listened episodes will be deleted first
- Iterator<FeedItem> it = candidates.iterator();
- if (it.hasNext()) {
- for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
- if (!i.getMedia().isPlaying() && i.getMedia().getPlaybackCompletionDate() != null) {
- it.remove();
- deleteList.add(i);
- deletedEpisodesSize += i.getMedia().getSize();
- }
- }
- }
-
- // delete unlistened old episodes if necessary
- it = candidates.iterator();
- if (it.hasNext()) {
- for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
- if (!i.getMedia().isPlaying()) {
- it.remove();
- deleteList.add(i);
- deletedEpisodesSize += i.getMedia().getSize();
- }
- }
- }
- for (FeedItem item : deleteList) {
- try {
- DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- Log.i(TAG, String.format("performAutoCleanup(%d) deleted %d episodes and freed %d bytes of memory",
- episodeSize, deleteList.size(), deletedEpisodesSize));
- return deleteList.size();
- }
-
- @Override
- public Integer getDefaultCleanupParameter(Context context) {
- return 0;
- }
-
- @Override
- public Integer getPerformCleanupParameter(Context context, List<FeedItem> items) {
- int episodeSize = 0;
- for (FeedItem item : items) {
- if (item.hasMedia() && !item.getMedia().isDownloaded()) {
- episodeSize += item.getMedia().getSize();
- }
- }
- return episodeSize;
- }
-
- /**
- * Returns list of FeedItems that have been downloaded, but are not one of the
- * [numberOfNewAutomaticallyDownloadedEpisodes] most recent items.
- */
- private List<FeedItem> getAutoCleanupCandidates(Context context) {
- List<FeedItem> downloaded = new ArrayList<FeedItem>(DBReader.getDownloadedItems(context));
- List<FeedItem> recent = new ArrayList<FeedItem>(DBReader.getRecentlyPublishedEpisodes(context,
- numberOfNewAutomaticallyDownloadedEpisodes));
- for (FeedItem r : recent) {
- if (r.hasMedia() && r.getMedia().isDownloaded()) {
- for (int i = 0; i < downloaded.size(); i++) {
- if (downloaded.get(i).getId() == r.getId()) {
- downloaded.remove(i);
- break;
- }
- }
- }
- }
-
- return downloaded;
-
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java
deleted file mode 100644
index f760ec0ce..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package de.danoeh.antennapod.core.storage;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.util.NetworkUtils;
-
-/**
- * Implements the automatic download algorithm used by AntennaPodSP apps.
- */
-public class APSPDownloadAlgorithm implements AutomaticDownloadAlgorithm {
- private static final String TAG = "APSPDownloadAlgorithm";
-
- private final int numberOfNewAutomaticallyDownloadedEpisodes;
-
- public APSPDownloadAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
- this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
- }
-
- /**
- * Downloads the most recent episodes automatically. The exact number of
- * episodes that will be downloaded can be set in the AppPreferences.
- *
- * @param context Used for accessing the DB.
- * @return A Runnable that will be submitted to an ExecutorService.
- */
- @Override
- public Runnable autoDownloadUndownloadedItems(final Context context, final long... mediaIds) {
- return new Runnable() {
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Performing auto-dl of undownloaded episodes");
- if (NetworkUtils.autodownloadNetworkAvailable(context)
- && UserPreferences.isEnableAutodownload()) {
-
- Arrays.sort(mediaIds);
- List<FeedItem> itemsToDownload = DBReader.getRecentlyPublishedEpisodes(context,
- numberOfNewAutomaticallyDownloadedEpisodes);
- Iterator<FeedItem> it = itemsToDownload.iterator();
-
- for (FeedItem item = it.next(); it.hasNext(); item = it.next()) {
- if (!item.hasMedia()
- || item.getMedia().isDownloaded()
- || Arrays.binarySearch(mediaIds, item.getMedia().getId()) < 0) {
- it.remove();
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Enqueueing " + itemsToDownload.size()
- + " items for automatic download");
- if (!itemsToDownload.isEmpty()) {
- try {
- DBTasks.downloadFeedItems(false, context,
- itemsToDownload.toArray(new FeedItem[itemsToDownload
- .size()]));
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
- }
- }
- }
- };
- }
-}
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 dc24c5784..5ed0a6ee3 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
@@ -22,6 +22,7 @@ import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.ID3Chapter;
import de.danoeh.antennapod.core.feed.SimpleChapter;
import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.LongIntMap;
@@ -114,36 +115,6 @@ public final class DBReader {
}
/**
- * Returns a list of 'expired Feeds', i.e. Feeds that have not been updated for a certain amount of time.
- *
- * @param context A context that is used for opening a database connection.
- * @param expirationTime Time that is used for determining whether a feed is outdated or not.
- * A Feed is considered expired if 'lastUpdate < (currentTime - expirationTime)' evaluates to true.
- * @return A list of Feeds, sorted alphabetically by their title. A Feed-object
- * of the returned list does NOT have its list of FeedItems yet. The FeedItem-list
- * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)}.
- */
- public static List<Feed> getExpiredFeedsList(final Context context, final long expirationTime) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime));
-
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
-
- Cursor feedlistCursor = adapter.getExpiredFeedsCursor(expirationTime);
- List<Feed> feeds = new ArrayList<Feed>(feedlistCursor.getCount());
-
- if (feedlistCursor.moveToFirst()) {
- do {
- Feed feed = extractFeedFromCursorRow(adapter, feedlistCursor);
- feeds.add(feed);
- } while (feedlistCursor.moveToNext());
- }
- feedlistCursor.close();
- return feeds;
- }
-
- /**
* Takes a list of FeedItems and loads their corresponding Feed-objects from the database.
* The feedID-attribute of a FeedItem must be set to the ID of its feed or the method will
* not find the correct feed of an item.
@@ -230,7 +201,7 @@ public final class DBReader {
new FlattrStatus(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)),
itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0,
image,
- (itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0),
+ itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ),
itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER),
itemlistCursor.getInt(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD)) > 0
);
@@ -274,6 +245,18 @@ public final class DBReader {
playbackCompletionDate = new Date(
playbackCompletionTime);
}
+ Boolean hasEmbeddedPicture;
+ switch(cursor.getInt(cursor.getColumnIndex(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) {
+ case 1:
+ hasEmbeddedPicture = Boolean.TRUE;
+ break;
+ case 0:
+ hasEmbeddedPicture = Boolean.FALSE;
+ break;
+ default:
+ hasEmbeddedPicture = null;
+ break;
+ }
return new FeedMedia(
mediaId,
@@ -286,7 +269,8 @@ public final class DBReader {
cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX),
cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0,
playbackCompletionDate,
- cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX));
+ cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX),
+ hasEmbeddedPicture);
}
private static Feed extractFeedFromCursorRow(PodDBAdapter adapter,
@@ -325,9 +309,9 @@ public final class DBReader {
if (image != null) {
image.setOwner(feed);
}
-
FeedPreferences preferences = new FeedPreferences(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID),
cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD) > 0,
+ FeedPreferences.AutoDeleteAction.values()[cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION)],
cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_USERNAME),
cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_PASSWORD));
@@ -469,8 +453,7 @@ public final class DBReader {
* Loads a list of FeedItems whose 'read'-attribute is set to false.
*
* @param context A context that is used for opening a database connection.
- * @return A list of FeedItems whose 'read'-attribute it set to false. If the FeedItems in the list are not used,
- * consider using {@link #getUnreadItemIds(android.content.Context)} instead.
+ * @return A list of FeedItems whose 'read'-attribute it set to false.
*/
public static List<FeedItem> getUnreadItemsList(Context context) {
if (BuildConfig.DEBUG)
@@ -538,6 +521,28 @@ public final class DBReader {
return itemIds;
}
+ /**
+ * Loads FeedMedia whose file size is unknown
+ *
+ * @param context A context that is used for opening a database connection.
+ * @return A list of FeedMedia items whose size is 0 (unknown and never tried to
+ * determine the correct size)
+ */
+ public static List<FeedMedia> getFeedMediaUnknownSize(Context context) {
+ PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ Cursor cursor = adapter.getFeedMediaUnknownSizeCursor();
+ List<FeedMedia> result = new ArrayList<>(cursor.getCount());
+ if (cursor.moveToFirst()) {
+ do {
+ FeedMedia media = extractFeedMediaFromCursorRow(cursor);
+ result.add(media);
+ } while (cursor.moveToNext());
+ }
+ cursor.close();
+ return result;
+ }
+
/**
* Loads a list of FeedItems sorted by pubDate in descending order.
@@ -866,7 +871,11 @@ public final class DBReader {
if (cursor.moveToFirst()) {
String username = cursor.getString(0);
String password = cursor.getString(1);
- return username + ":" + password;
+ if(username != null && password != null) {
+ return username + ":" + password;
+ } else {
+ return "";
+ }
}
return "";
} finally {
@@ -1001,20 +1010,6 @@ public final class DBReader {
}
/**
- * Returns a map containing the number of unread items per feed
- *
- * @param context A context that is used for opening a database connection.
- * @return The number of unread items per feed.
- */
- public static LongIntMap getNumberOfUnreadFeedItems(final Context context, long... feedIds) {
- PodDBAdapter adapter = new PodDBAdapter(context);
- adapter.open();
- final LongIntMap result = adapter.getNumberOfUnreadFeedItems(feedIds);
- adapter.close();
- return result;
- }
-
- /**
* Searches the DB for a FeedImage of the given id.
*
* @param context A context that is used for opening a database connection.
@@ -1142,27 +1137,42 @@ public final class DBReader {
for(int i=0; i < feeds.size(); i++) {
feedIds[i] = feeds.get(i).getId();
}
- final LongIntMap numUnreadFeedItems = adapter.getNumberOfUnreadFeedItems(feedIds);
- Collections.sort(feeds, new Comparator<Feed>() {
- @Override
- public int compare(Feed lhs, Feed rhs) {
- long numUnreadLhs = numUnreadFeedItems.get(lhs.getId());
- Log.d(TAG, "feed with id " + lhs.getId() + " has " + numUnreadLhs + " unread items");
- long numUnreadRhs = numUnreadFeedItems.get(rhs.getId());
- Log.d(TAG, "feed with id " + rhs.getId() + " has " + numUnreadRhs + " unread items");
- if(numUnreadLhs > numUnreadRhs) {
- // reverse natural order: podcast with most unplayed episodes first
- return -1;
- } else if(numUnreadLhs == numUnreadRhs) {
+ final LongIntMap feedCounters = adapter.getFeedCounters(feedIds);
+
+ Comparator<Feed> comparator;
+ int feedOrder = UserPreferences.getFeedOrder();
+ if(feedOrder == UserPreferences.FEED_ORDER_UNPLAYED_EPISODES) {
+ comparator = new Comparator<Feed>() {
+ @Override
+ public int compare(Feed lhs, Feed rhs) {
+ long counterLhs = feedCounters.get(lhs.getId());
+ long counterRhs = feedCounters.get(rhs.getId());
+ if(counterLhs > counterRhs) {
+ // reverse natural order: podcast with most unplayed episodes first
+ return -1;
+ } else if(counterLhs == counterRhs) {
+ return lhs.getTitle().compareTo(rhs.getTitle());
+ } else {
+ return 1;
+ }
+ }
+ };
+ } else {
+ comparator = new Comparator<Feed>() {
+ @Override
+ public int compare(Feed lhs, Feed rhs) {
+ if(lhs.getTitle() == null) {
+ return 1;
+ }
return lhs.getTitle().compareTo(rhs.getTitle());
- } else {
- return 1;
}
- }
- });
+ };
+ }
+
+ Collections.sort(feeds, comparator);
int queueSize = adapter.getQueueSize();
int numNewItems = adapter.getNumberOfNewItems();
- NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numUnreadFeedItems);
+ NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters);
adapter.close();
return result;
}
@@ -1171,14 +1181,16 @@ public final class DBReader {
public List<Feed> feeds;
public int queueSize;
public int numNewItems;
- public LongIntMap numUnreadFeedItems;
+ public LongIntMap feedCounters;
- public NavDrawerData(List<Feed> feeds, int queueSize, int numNewItems,
- LongIntMap numUnreadFeedItems) {
+ public NavDrawerData(List<Feed> feeds,
+ int queueSize,
+ int numNewItems,
+ LongIntMap feedIndicatorValues) {
this.feeds = feeds;
this.queueSize = queueSize;
this.numNewItems = numNewItems;
- this.numUnreadFeedItems = numUnreadFeedItems;
+ this.feedCounters = feedIndicatorValues;
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
index defce5930..770c4f7d7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
@@ -5,6 +5,9 @@ import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -29,6 +32,7 @@ import de.danoeh.antennapod.core.feed.FeedImage;
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.FeedMediaSizeService;
import de.danoeh.antennapod.core.service.GpodnetSyncService;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
@@ -180,6 +184,7 @@ public final class DBTasks {
if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) {
GpodnetSyncService.sendSyncIntent(context);
}
+ Log.d(TAG, "refreshAllFeeds autodownload");
autodownloadUndownloadedItems(context);
}
}.start();
@@ -188,47 +193,6 @@ public final class DBTasks {
}
}
- /**
- * Used by refreshExpiredFeeds to determine which feeds should be refreshed.
- * This method will use the value specified in the UserPreferences as the
- * expiration time.
- *
- * @param context Used for DB access.
- * @return A list of expired feeds. An empty list will be returned if there
- * are no expired feeds.
- */
- public static List<Feed> getExpiredFeeds(final Context context) {
- long millis = UserPreferences.getUpdateInterval();
-
- if (millis > 0) {
-
- List<Feed> feedList = DBReader.getExpiredFeedsList(context,
- millis);
- if (feedList.size() > 0) {
- refreshFeeds(context, feedList);
- }
- return feedList;
- } else {
- return new ArrayList<Feed>();
- }
- }
-
- /**
- * Refreshes expired Feeds in the list returned by the getExpiredFeedsList(Context, long) method in DBReader.
- * The expiration date parameter is determined by the update interval specified in {@link UserPreferences}.
- *
- * @param context Used for DB access.
- */
- public static void refreshExpiredFeeds(final Context context) {
- Log.d(TAG, "Refreshing expired feeds");
-
- new Thread() {
- public void run() {
- refreshFeeds(context, getExpiredFeeds(context));
- }
- }.start();
- }
-
private static void refreshFeeds(final Context context,
final List<Feed> feedList) {
@@ -320,24 +284,6 @@ public final class DBTasks {
}
/**
- * Notifies the database about a missing FeedImage file. This method will attempt to re-download the file.
- *
- * @param context Used for requesting the download.
- * @param image The FeedImage object.
- */
- public static void notifyInvalidImageFile(final Context context,
- final FeedImage image) {
- Log.i(TAG,
- "The DB was notified about an invalid image download. It will now try to re-download the image file");
- try {
- DownloadRequester.getInstance().downloadImage(context, image);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Log.w(TAG, "Failed to download invalid feed image");
- }
- }
-
- /**
* Notifies the database about a missing FeedMedia file. This method will correct the FeedMedia object's values in the
* DB and send a FeedUpdateBroadcast.
*/
@@ -439,6 +385,7 @@ public final class DBTasks {
* @return A Future that can be used for waiting for the methods completion.
*/
public static Future<?> autodownloadUndownloadedItems(final Context context, final long... mediaIds) {
+ Log.d(TAG, "autodownloadUndownloadedItems");
return autodownloadExec.submit(ClientConfig.dbTasksCallbacks.getAutomaticDownloadAlgorithm()
.autoDownloadUndownloadedItems(context, mediaIds));
@@ -564,7 +511,7 @@ public final class DBTasks {
// all new feeds will have the most recent item marked as unplayed
FeedItem mostRecent = newFeed.getMostRecentItem();
if (mostRecent != null) {
- mostRecent.setRead(false);
+ mostRecent.setNew();
}
newFeedsList.add(newFeed);
@@ -575,16 +522,16 @@ public final class DBTasks {
Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator());
- final boolean markNewItemsAsUnread;
+ final boolean markNewItems;
if (newFeed.getPageNr() == savedFeed.getPageNr()) {
if (savedFeed.compareWithOther(newFeed)) {
Log.d(TAG, "Feed has updated attribute values. Updating old feed's attributes");
savedFeed.updateFromOther(newFeed);
}
- markNewItemsAsUnread = true;
+ markNewItems = true;
} else {
Log.d(TAG, "New feed has a higher page number. Merging without marking as unread");
- markNewItemsAsUnread = false;
+ markNewItems = false;
savedFeed.setNextPageLink(newFeed.getNextPageLink());
}
if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) {
@@ -598,12 +545,11 @@ public final class DBTasks {
item.getIdentifyingValue());
if (oldItem == null) {
// item is new
- final int i = idx;
item.setFeed(savedFeed);
item.setAutoDownload(savedFeed.getPreferences().getAutoDownload());
- savedFeed.getItems().add(i, item);
- if (markNewItemsAsUnread) {
- item.setRead(false);
+ savedFeed.getItems().add(idx, item);
+ if (markNewItems) {
+ item.setNew();
}
} else {
oldItem.updateFromOther(item);
@@ -632,6 +578,8 @@ public final class DBTasks {
EventDistributor.getInstance().sendFeedUpdateBroadcast();
+ context.startService(new Intent(context, FeedMediaSizeService.class));
+
return resultFeeds;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index fe5d0dfd3..12bc208a6 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -13,10 +13,10 @@ import org.shredzone.flattr4j.model.Flattr;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
@@ -100,6 +100,7 @@ public class DBWriter {
}
media.setDownloaded(false);
media.setFile_url(null);
+ media.setHasEmbeddedPicture(false);
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
adapter.setMedia(media);
@@ -184,13 +185,15 @@ public class DBWriter {
}
// delete stored media files and mark them as read
List<FeedItem> queue = DBReader.getQueue(context);
- boolean queueWasModified = false;
+ List<FeedItem> removed = new ArrayList<>();
if (feed.getItems() == null) {
DBReader.getFeedItemList(context, feed);
}
for (FeedItem item : feed.getItems()) {
- queueWasModified |= queue.remove(item);
+ if(queue.remove(item)) {
+ removed.add(item);
+ }
if (item.getMedia() != null
&& item.getMedia().isDownloaded()) {
File mediaFile = new File(item.getMedia()
@@ -213,8 +216,10 @@ public class DBWriter {
}
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
- if (queueWasModified) {
+ if (removed.size() > 0) {
adapter.setQueue(queue);
+ EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.IRREVERSIBLE_REMOVED,
+ removed));
}
adapter.removeFeed(feed);
adapter.close();
@@ -351,7 +356,7 @@ public class DBWriter {
final PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
final List<FeedItem> queue = DBReader.getQueue(context, adapter);
- FeedItem item = null;
+ FeedItem item;
if (queue != null) {
if (!itemListContains(queue, itemId)) {
@@ -360,6 +365,9 @@ public class DBWriter {
queue.add(index, item);
adapter.setQueue(queue);
EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index));
+ if(item.isNew()) {
+ DBWriter.markItemRead(context, false, item.getId());
+ }
}
}
}
@@ -374,14 +382,20 @@ public class DBWriter {
}
+ public static Future<?> addQueueItem(final Context context,
+ final long... itemIds) {
+ return addQueueItem(context, false, itemIds);
+ }
+
/**
* Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true.
* If a FeedItem is already in the queue, the FeedItem will not change its position in the queue.
*
* @param context A context that is used for opening a database connection.
+ * @param performAutoDownload true if an auto-download process should be started after the operation.
* @param itemIds IDs of the FeedItem objects that should be added to the queue.
*/
- public static Future<?> addQueueItem(final Context context,
+ public static Future<?> addQueueItem(final Context context, final boolean performAutoDownload,
final long... itemIds) {
return dbExec.submit(new Runnable() {
@@ -390,43 +404,45 @@ public class DBWriter {
if (itemIds.length > 0) {
final PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
- final List<FeedItem> queue = DBReader.getQueue(context,
- adapter);
+ final List<FeedItem> queue = DBReader.getQueue(context, adapter);
if (queue != null) {
boolean queueModified = false;
- boolean unreadItemsModified = false;
- List<FeedItem> itemsToSave = new LinkedList<FeedItem>();
+ LongList markAsUnplayedIds = new LongList();
for (int i = 0; i < itemIds.length; i++) {
if (!itemListContains(queue, itemIds[i])) {
- final FeedItem item = DBReader.getFeedItem(
- context, itemIds[i]);
+ final FeedItem item = DBReader.getFeedItem(context, itemIds[i]);
if (item != null) {
// add item to either front ot back of queue
boolean addToFront = UserPreferences.enqueueAtFront();
-
- if(addToFront){
- queue.add(0, item);
+ if (addToFront) {
+ queue.add(0 + i, item);
} else {
queue.add(item);
}
-
queueModified = true;
+ if(item.isNew()) {
+ markAsUnplayedIds.add(item.getId());
+ }
}
}
}
if (queueModified) {
adapter.setQueue(queue);
EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue));
+ if(markAsUnplayedIds.size() > 0) {
+ DBWriter.markItemRead(context, false, markAsUnplayedIds.toArray());
+ }
}
}
adapter.close();
- DBTasks.autodownloadUndownloadedItems(context);
+ if (performAutoDownload) {
+ DBTasks.autodownloadUndownloadedItems(context);
+ }
}
}
});
-
}
/**
@@ -594,16 +610,25 @@ public class DBWriter {
adapter.close();
}
- /**
- * Sets the 'read'-attribute of a FeedItem to the specified value.
+ /*
+ * Sets the 'read'-attribute of all specified FeedItems
*
* @param context A context that is used for opening a database connection.
- * @param itemId ID of the FeedItem
* @param read New value of the 'read'-attribute
+ * @param itemIds IDs of the FeedItems.
*/
- public static Future<?> markItemRead(final Context context, final long itemId,
- final boolean read) {
- return markItemRead(context, itemId, read, 0, false);
+ public static Future<?> markItemRead(final Context context, final boolean read, final long... itemIds) {
+ return dbExec.submit(new Runnable() {
+ @Override
+ public void run() {
+ final PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ int played = read ? FeedItem.PLAYED : FeedItem.UNPLAYED;
+ adapter.setFeedItemRead(played, itemIds);
+ adapter.close();
+ EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
+ }
+ });
}
@@ -645,6 +670,35 @@ public class DBWriter {
* @param context A context that is used for opening a database connection.
* @param feedId ID of the Feed.
*/
+ public static Future<?> markFeedSeen(final Context context, final long feedId) {
+ return dbExec.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ final PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId);
+ long[] ids = new long[itemCursor.getCount()];
+ itemCursor.moveToFirst();
+ for (int i = 0; i < ids.length; i++) {
+ ids[i] = itemCursor.getLong(0);
+ itemCursor.moveToNext();
+ }
+ itemCursor.close();
+ adapter.setFeedItemRead(FeedItem.UNPLAYED, ids);
+ adapter.close();
+
+ EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
+ }
+ });
+ }
+
+ /**
+ * Sets the 'read'-attribute of all FeedItems of a specific Feed to true.
+ *
+ * @param context A context that is used for opening a database connection.
+ * @param feedId ID of the Feed.
+ */
public static Future<?> markFeedRead(final Context context, final long feedId) {
return dbExec.submit(new Runnable() {
@@ -660,13 +714,12 @@ public class DBWriter {
itemCursor.moveToNext();
}
itemCursor.close();
- adapter.setFeedItemRead(true, itemIds);
+ adapter.setFeedItemRead(FeedItem.PLAYED, itemIds);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
});
-
}
/**
@@ -689,7 +742,7 @@ public class DBWriter {
itemCursor.moveToNext();
}
itemCursor.close();
- adapter.setFeedItemRead(true, itemIds);
+ adapter.setFeedItemRead(FeedItem.PLAYED, itemIds);
adapter.close();
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
@@ -1057,9 +1110,34 @@ public class DBWriter {
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
});
+ }
+
+ /**
+ * Sets the 'auto_download'-attribute of specific FeedItem.
+ *
+ * @param context A context that is used for opening a database connection.
+ * @param feed This feed's episodes will be processed.
+ * @param autoDownload If true, auto download will be enabled for the feed's episodes. Else,
+ * it will be disabled.
+ */
+ public static Future<?> setFeedsItemsAutoDownload(final Context context, final Feed feed,
+ final boolean autoDownload) {
+ Log.d(TAG, (autoDownload ? "Enabling" : "Disabling") + " auto download for items of feed " + feed.getId());
+ return dbExec.submit(new Runnable() {
+ @Override
+ public void run() {
+ final PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ adapter.setFeedsItemsAutoDownload(feed, autoDownload);
+ adapter.close();
+
+ EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
+ }
+ });
}
+
/**
* Set filter of the feed
*
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
index 386304530..bc34523cc 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java
@@ -18,7 +18,6 @@ import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedFile;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
@@ -186,15 +185,6 @@ public class DownloadRequester {
downloadFeed(context, feed, false);
}
- public synchronized void downloadImage(Context context, FeedImage image)
- throws DownloadRequestException {
- if (feedFileValid(image)) {
- FeedFile container = (image.getOwner() instanceof FeedFile) ? (FeedFile) image.getOwner() : null;
- download(context, image, container, new File(getImagefilePath(context),
- getImagefileName(image)), false, null, null, 0, false, null);
- }
- }
-
public synchronized void downloadMedia(Context context, FeedMedia feedmedia)
throws DownloadRequestException {
if (feedFileValid(feedmedia)) {
@@ -332,20 +322,6 @@ public class DownloadRequester {
return "feed-" + FileNameGenerator.generateFileName(filename);
}
- public synchronized String getImagefilePath(Context context)
- throws DownloadRequestException {
- return getExternalFilesDirOrThrowException(context, IMAGE_DOWNLOADPATH)
- .toString() + "/";
- }
-
- public synchronized String getImagefileName(FeedImage image) {
- String filename = image.getDownload_url();
- if (image.getOwner() != null && image.getOwner().getHumanReadableIdentifier() != null) {
- filename = image.getOwner().getHumanReadableIdentifier();
- }
- return "image-" + FileNameGenerator.generateFileName(filename);
- }
-
public synchronized String getMediafilePath(Context context, FeedMedia media)
throws DownloadRequestException {
File externalStorage = getExternalFilesDirOrThrowException(
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 6fabf9005..edb7598ab 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
@@ -9,6 +9,7 @@ import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
+import android.media.MediaMetadataRetriever;
import android.text.TextUtils;
import android.util.Log;
@@ -18,7 +19,8 @@ import java.util.Arrays;
import java.util.List;
import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.ClientConfig;
+import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedComponent;
@@ -26,11 +28,11 @@ import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.LongIntMap;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
-
-;
+import de.greenrobot.event.EventBus;
// TODO Remove media column from feeditem table
@@ -148,6 +150,7 @@ public class PodDBAdapter {
public static final String KEY_CHAPTER_TYPE = "type";
public static final String KEY_PLAYBACK_COMPLETION_DATE = "playback_completion_date";
public static final String KEY_AUTO_DOWNLOAD = "auto_download";
+ public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action";
public static final String KEY_PLAYED_DURATION = "played_duration";
public static final String KEY_USERNAME = "username";
public static final String KEY_PASSWORD = "password";
@@ -155,6 +158,8 @@ public class PodDBAdapter {
public static final String KEY_NEXT_PAGE_LINK = "next_page_link";
public static final String KEY_HIDE = "hide";
public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed";
+ public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture";
+
// Table names
public static final String TABLE_NAME_FEEDS = "Feeds";
@@ -183,7 +188,8 @@ public class PodDBAdapter {
+ KEY_IS_PAGED + " INTEGER DEFAULT 0,"
+ KEY_NEXT_PAGE_LINK + " TEXT,"
+ KEY_HIDE + " TEXT,"
- + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0)";
+ + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0,"
+ + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0)";
public static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
+ TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
@@ -209,7 +215,7 @@ public class PodDBAdapter {
+ KEY_PLAYBACK_COMPLETION_DATE + " INTEGER,"
+ KEY_FEEDITEM + " INTEGER,"
+ KEY_PLAYED_DURATION + " INTEGER,"
- + KEY_AUTO_DOWNLOAD + " INTEGER)";
+ + KEY_HAS_EMBEDDED_PICTURE + " INTEGER)";
public static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE "
+ TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE
@@ -279,6 +285,7 @@ public class PodDBAdapter {
TABLE_NAME_FEEDS + "." + KEY_PASSWORD,
TABLE_NAME_FEEDS + "." + KEY_HIDE,
TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED,
+ TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION,
};
// column indices for FEED_SEL_STD
@@ -302,6 +309,7 @@ public class PodDBAdapter {
public static final int IDX_FEED_SEL_STD_NEXT_PAGE_LINK = 17;
public static final int IDX_FEED_SEL_PREFERENCES_USERNAME = 18;
public static final int IDX_FEED_SEL_PREFERENCES_PASSWORD = 19;
+ public static final int IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION = 22;
/**
* Select all columns from the feeditems-table except description and
@@ -364,8 +372,7 @@ public class PodDBAdapter {
private static synchronized PodDBHelper getDbHelperSingleton(Context appContext) {
if (dbHelperSingleton == null) {
- dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null,
- ClientConfig.storageCallbacks.getDatabaseVersion());
+ dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null);
}
return dbHelperSingleton;
}
@@ -458,6 +465,7 @@ public class PodDBAdapter {
}
ContentValues values = new ContentValues();
values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload());
+ values.put(KEY_AUTO_DELETE_ACTION,prefs.getAutoDeleteAction().ordinal());
values.put(KEY_USERNAME, prefs.getUsername());
values.put(KEY_PASSWORD, prefs.getPassword());
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
@@ -516,6 +524,7 @@ public class PodDBAdapter {
values.put(KEY_DOWNLOAD_URL, media.getDownload_url());
values.put(KEY_DOWNLOADED, media.isDownloaded());
values.put(KEY_FILE_URL, media.getFile_url());
+ values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture());
if (media.getPlaybackCompletionDate() != null) {
values.put(KEY_PLAYBACK_COMPLETION_DATE, media
@@ -736,7 +745,13 @@ public class PodDBAdapter {
setFeed(item.getFeed());
}
values.put(KEY_FEED, item.getFeed().getId());
- values.put(KEY_READ, item.isRead());
+ if(item.isNew()) {
+ values.put(KEY_READ, FeedItem.NEW);
+ } else if(item.isPlayed()) {
+ values.put(KEY_READ, FeedItem.PLAYED);
+ } else {
+ values.put(KEY_READ, FeedItem.UNPLAYED);
+ }
values.put(KEY_HAS_CHAPTERS, item.getChapters() != null || item.hasChapters());
values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier());
values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong());
@@ -768,7 +783,7 @@ public class PodDBAdapter {
db.beginTransaction();
ContentValues values = new ContentValues();
- values.put(KEY_READ, read);
+ values.put(KEY_READ, read ? FeedItem.PLAYED : FeedItem.UNPLAYED);
db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)});
if (resetMediaPosition) {
@@ -781,7 +796,7 @@ public class PodDBAdapter {
db.endTransaction();
}
- public void setFeedItemRead(boolean read, long... itemIds) {
+ public void setFeedItemRead(int read, long... itemIds) {
db.beginTransaction();
ContentValues values = new ContentValues();
for (long id : itemIds) {
@@ -846,6 +861,13 @@ public class PodDBAdapter {
new String[]{String.valueOf(feedItem.getId())});
}
+ public void setFeedsItemsAutoDownload(Feed feed, boolean autoDownload) {
+ final String sql = "UPDATE " + TABLE_NAME_FEED_ITEMS
+ + " SET " + KEY_AUTO_DOWNLOAD + "="+ (autoDownload ? "1" : "0")
+ + " WHERE " + KEY_FEED + "=" + feed.getId();
+ db.execSQL(sql);
+ }
+
public long getDownloadLogSize() {
final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_DOWNLOAD_LOG);
Cursor result = db.rawQuery(query, null);
@@ -874,8 +896,7 @@ public class PodDBAdapter {
values.put(KEY_ID, i);
values.put(KEY_FEEDITEM, item.getId());
values.put(KEY_FEED, item.getFeed().getId());
- db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values,
- SQLiteDatabase.CONFLICT_REPLACE);
+ db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
db.setTransactionSuccessful();
db.endTransaction();
@@ -967,13 +988,6 @@ public class PodDBAdapter {
return db.query(TABLE_NAME_FEEDS, new String[]{KEY_ID, KEY_DOWNLOAD_URL}, null, null, null, null, null);
}
- public final Cursor getExpiredFeedsCursor(long expirationTime) {
- Cursor c = db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_LASTUPDATE + " < " + String.valueOf(System.currentTimeMillis() - expirationTime),
- null, null, null,
- null);
- return c;
- }
-
/**
* Returns a cursor with all FeedItems of a Feed. Uses FEEDITEM_SEL_FI_SMALL
*
@@ -1053,6 +1067,7 @@ public class PodDBAdapter {
/**
* Returns a cursor which contains all feed items in the queue. The returned
* cursor uses the FEEDITEM_SEL_FI_SMALL selection.
+ * cursor uses the FEEDITEM_SEL_FI_SMALL selection.
*/
public final Cursor getQueueCursor() {
Object[] args = (Object[]) new String[]{
@@ -1084,44 +1099,46 @@ public class PodDBAdapter {
*/
public final Cursor getUnreadItemsCursor() {
Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_READ
- + "=0", null, null, null, KEY_PUBDATE + " DESC");
+ + "<" + FeedItem.PLAYED, null, null, null, KEY_PUBDATE + " DESC");
return c;
}
public final Cursor getNewItemIdsCursor() {
- final String query = "SELECT " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID
+ final String query = "SELECT " + KEY_ID
+ " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
- + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
+ + " WHERE " + KEY_READ + "=" + FeedItem.NEW;
+ return db.rawQuery(query, null);
+ }
+
+ public final Cursor getFeedMediaUnknownSizeCursor() {
+ final String query = "SELECT * "
+ + " FROM " + TABLE_NAME_FEED_MEDIA
+ + " WHERE " + KEY_SIZE + "<= 0";
return db.rawQuery(query, null);
}
/**
+ * Returns a cursor which contains all items of a feed that are considered new.
+ * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
+ */
+ public final Cursor getNewItemsIdsCursor(long feedId) {
+ final String query = "SELECT " + KEY_ID
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " WHERE " + KEY_FEED + "=" + feedId
+ + " AND " + KEY_READ + "=" + FeedItem.NEW
+ + " ORDER BY " + KEY_PUBDATE + " DESC";
+ Cursor c = db.rawQuery(query, null);
+ return c;
+ }
+
+ /**
* Returns a cursor which contains all feed items that are considered new.
* The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
*/
public final Cursor getNewItemsCursor() {
- final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
- + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL" // not in queue
+ final String query = "SELECT " + SEL_FI_SMALL_STR
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " WHERE " + KEY_READ + "=" + FeedItem.NEW
+ " ORDER BY " + KEY_PUBDATE + " DESC";
Cursor c = db.rawQuery(query, null);
return c;
@@ -1133,11 +1150,11 @@ public class PodDBAdapter {
}
public Cursor getDownloadedItemsCursor() {
- final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " WHERE "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0";
+ final String query = "SELECT " + SEL_FI_SMALL_STR
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " INNER JOIN " + TABLE_NAME_FEED_MEDIA
+ + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
+ + " WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0";
Cursor c = db.rawQuery(query, null);
return c;
}
@@ -1271,19 +1288,9 @@ public class PodDBAdapter {
}
public final int getNumberOfNewItems() {
- final String query = "SELECT COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ")"
- +" FROM " + TABLE_NAME_FEED_ITEMS
- + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " LEFT JOIN " + TABLE_NAME_QUEUE + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
- + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
+ final String query = "SELECT COUNT(" + KEY_ID + ")"
+ + " FROM " + TABLE_NAME_FEED_ITEMS
+ + " WHERE " + KEY_READ + "=" + FeedItem.NEW;
Cursor c = db.rawQuery(query, null);
int result = 0;
if (c.moveToFirst()) {
@@ -1293,7 +1300,20 @@ public class PodDBAdapter {
return result;
}
- public final LongIntMap getNumberOfUnreadFeedItems(long... feedIds) {
+ public final LongIntMap getFeedCounters(long... feedIds) {
+ int counter = UserPreferences.getFeedCounter();
+ String whereRead;
+ if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) {
+ whereRead = "(" + KEY_READ + "=" + FeedItem.NEW
+ + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")";
+ } else if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW) {
+ whereRead = KEY_READ + "=" + FeedItem.NEW;
+ } else if(counter == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) {
+ whereRead = KEY_READ + "=" + FeedItem.UNPLAYED;
+ } else {
+ return new LongIntMap(0);
+ }
+
// work around TextUtils.join wanting only boxed items
// and StringUtils.join() causing NoSuchMethodErrors on MIUI
StringBuilder builder = new StringBuilder();
@@ -1309,8 +1329,8 @@ public class PodDBAdapter {
final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count "
+ " FROM " + TABLE_NAME_FEED_ITEMS
+ " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") "
- + " AND " + KEY_READ + " = 0"
- + " GROUP BY " + KEY_FEED;
+ + " AND " + whereRead + " GROUP BY " + KEY_FEED;
+
Cursor c = db.rawQuery(query, null);
LongIntMap result = new LongIntMap(c.getCount());
if (c.moveToFirst()) {
@@ -1463,17 +1483,22 @@ public class PodDBAdapter {
* Helper class for opening the Antennapod database.
*/
private static class PodDBHelper extends SQLiteOpenHelper {
+
+ private final static int VERSION = 1030002;
+
+ private Context context;
+
/**
* Constructor.
*
* @param context Context to use
* @param name Name of the database
* @param factory to use for creating cursor objects
- * @param version number of the database
*/
public PodDBHelper(final Context context, final String name,
- final CursorFactory factory, final int version) {
- super(context, name, factory, version);
+ final CursorFactory factory) {
+ super(context, name, factory, VERSION);
+ this.context = context;
}
@Override
@@ -1497,7 +1522,199 @@ public class PodDBAdapter {
@Override
public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
final int newVersion) {
- ClientConfig.storageCallbacks.onUpgrade(db, oldVersion, newVersion);
+ EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database)));
+ Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
+ + newVersion + ".");
+ if (oldVersion <= 1) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ + KEY_TYPE + " TEXT");
+ }
+ if (oldVersion <= 2) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ + " ADD COLUMN " + KEY_LINK + " TEXT");
+ }
+ if (oldVersion <= 3) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_ITEM_IDENTIFIER + " TEXT");
+ }
+ if (oldVersion <= 4) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
+ + KEY_FEED_IDENTIFIER + " TEXT");
+ }
+ if (oldVersion <= 5) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ + " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
+ + " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT");
+ }
+ if (oldVersion <= 6) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ + " ADD COLUMN " + KEY_CHAPTER_TYPE + " INTEGER");
+ }
+ if (oldVersion <= 7) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_PLAYBACK_COMPLETION_DATE
+ + " INTEGER");
+ }
+ if (oldVersion <= 8) {
+ final int KEY_ID_POSITION = 0;
+ final int KEY_MEDIA_POSITION = 1;
+
+ // Add feeditem column to feedmedia table
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_FEEDITEM
+ + " INTEGER");
+ Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS,
+ new String[]{KEY_ID, KEY_MEDIA}, "? > 0",
+ new String[]{KEY_MEDIA}, null, null, null);
+ if (feeditemCursor.moveToFirst()) {
+ db.beginTransaction();
+ ContentValues contentValues = new ContentValues();
+ do {
+ long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
+ contentValues.put(KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
+ db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
+ contentValues.clear();
+ } while (feeditemCursor.moveToNext());
+ db.setTransactionSuccessful();
+ db.endTransaction();
+ }
+ feeditemCursor.close();
+ }
+ if (oldVersion <= 9) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_AUTO_DOWNLOAD
+ + " INTEGER DEFAULT 1");
+ }
+ if (oldVersion <= 10) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_FLATTR_STATUS
+ + " INTEGER");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_FLATTR_STATUS
+ + " INTEGER");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_PLAYED_DURATION
+ + " INTEGER");
+ }
+ if (oldVersion <= 11) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_USERNAME
+ + " TEXT");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_PASSWORD
+ + " TEXT");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_IMAGE
+ + " INTEGER");
+ }
+ if (oldVersion <= 12) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_IS_PAGED + " INTEGER DEFAULT 0");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_NEXT_PAGE_LINK + " TEXT");
+ }
+ if (oldVersion <= 13) {
+ // remove duplicate rows in "Chapters" table that were created because of a bug.
+ db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " +
+ "(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)",
+ PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
+ KEY_ID,
+ KEY_ID,
+ KEY_ID,
+ PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
+ KEY_TITLE,
+ KEY_START,
+ KEY_FEEDITEM,
+ KEY_LINK,
+ KEY_CHAPTER_TYPE));
+ }
+ if(oldVersion <= 14) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + " INTEGER");
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " SET " + KEY_AUTO_DOWNLOAD + " = "
+ + "(SELECT " + KEY_AUTO_DOWNLOAD
+ + " FROM " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + KEY_ID
+ + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ")");
+
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_HIDE + " TEXT");
+
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0");
+
+ // create indexes
+ db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM);
+ db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
+ }
+ if(oldVersion <= 15) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " ADD COLUMN " + KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1");
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
+ + " WHERE " + KEY_DOWNLOADED + "=0");
+ Cursor c = db.rawQuery("SELECT " + KEY_FILE_URL
+ + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " WHERE " + KEY_DOWNLOADED + "=1 "
+ + " AND " + KEY_HAS_EMBEDDED_PICTURE + "=-1", null);
+ if(c.moveToFirst()) {
+ MediaMetadataRetriever mmr = new MediaMetadataRetriever();
+ do {
+ String fileUrl = c.getString(0);
+ try {
+ mmr.setDataSource(fileUrl);
+ byte[] image = mmr.getEmbeddedPicture();
+ if (image != null) {
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=1"
+ + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'");
+ } else {
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
+ + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
+ + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'");
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ } while(c.moveToNext());
+ }
+ c.close();
+ }
+ if(oldVersion <= 16) {
+ String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID
+ + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON "
+ + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
+ + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
+ + " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON "
+ + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
+ + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
+ + " WHERE "
+ + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
+ + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
+ + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
+ + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
+ String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " SET " + KEY_READ + "=" + FeedItem.NEW
+ + " WHERE " + KEY_ID + " IN (" + selectNew + ")";
+ Log.d("Migration", "SQL: " + sql);
+ db.execSQL(sql);
+ }
+ if(oldVersion <= 17) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0");
+ }
+ if(oldVersion < 1030005) {
+ db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " +
+ "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " +
+ "AND id NOT IN (SELECT feeditem FROM Queue)");
+ }
+ EventBus.getDefault().post(ProgressEvent.end());
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
index 6455332be..31eb2efd6 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
@@ -57,6 +57,10 @@ public class NSRSS20 extends Namespace {
long size = 0;
try {
size = Long.parseLong(attributes.getValue(ENC_LEN));
+ if(size < 16384) {
+ // less than 16kb is suspicious, check manually
+ size = 0;
+ }
} catch (NumberFormatException e) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Length attribute could not be parsed.");
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 a0b514bd6..1b929b214 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
@@ -1,7 +1,10 @@
package de.danoeh.antennapod.core.util;
+import android.content.Context;
import android.util.Log;
+import de.danoeh.antennapod.core.R;
+
/** Provides methods for converting various units. */
public final class Converter {
/** Class shall not be instantiated. */
@@ -23,7 +26,7 @@ public final class Converter {
/** Determines the length of the number for best readability.*/
private static final int NUM_LENGTH = 1024;
-
+ private static final int DAYS_MIL = 86400000;
private static final int HOURS_MIL = 3600000;
private static final int MINUTES_MIL = 60000;
private static final int SECONDS_MIL = 1000;
@@ -99,5 +102,21 @@ public final class Converter {
return Integer.valueOf(parts[0]) * 3600 * 1000 +
Integer.valueOf(parts[1]) * 1000 * 60;
}
+
+ /** Converts milliseconds to a localized string containing hours and minutes */
+ public static String getDurationStringLocalized(Context context, long duration) {
+ int h = (int)(duration / HOURS_MIL);
+ int rest = (int)(duration - h * HOURS_MIL);
+ int m = rest / MINUTES_MIL;
+
+ String result = "";
+ if(h > 0) {
+ String hours = context.getResources().getQuantityString(R.plurals.time_hours_quantified, h, h);
+ result += hours + " ";
+ }
+ String minutes = context.getResources().getQuantityString(R.plurals.time_minutes_quantified, m, m);
+ result += minutes;
+ return result;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
index b6df2dc85..c0233f684 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
@@ -8,6 +8,7 @@ import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
+import java.util.TimeZone;
/**
* Parses several date formats.
@@ -16,49 +17,73 @@ public class DateUtils {
private static final String TAG = "DateUtils";
+ private static final SimpleDateFormat parser = new SimpleDateFormat("", Locale.US);
+ private static final TimeZone defaultTimezone = TimeZone.getTimeZone("GMT");
+
+ static {
+ parser.setLenient(false);
+ parser.setTimeZone(defaultTimezone);
+ }
+
public static Date parse(final String input) {
if(input == null) {
- throw new IllegalArgumentException("Date most not be null");
+ throw new IllegalArgumentException("Date must not be null");
}
- String date = input.replace('/', '-');
+ String date = input.trim().replace('/', '-').replaceAll("( ){2,}+", " ");
+
+ // if datetime is more precise than seconds, make sure the value is in ms
if(date.contains(".")) {
int start = date.indexOf('.');
int current = start+1;
while(current < date.length() && Character.isDigit(date.charAt(current))) {
current++;
}
+ // even more precise than microseconds: discard further decimal places
if(current - start > 4) {
if(current < date.length()-1) {
date = date.substring(0, start + 4) + date.substring(current);
} else {
date = date.substring(0, start + 4);
}
+ // less than 4 decimal places: pad to have a consistent format for the parser
} else if(current - start < 4) {
if(current < date.length()-1) {
date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start)) + date.substring(current);
} else {
date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start));
}
-
}
}
String[] patterns = {
"dd MMM yy HH:mm:ss Z",
"dd MMM yy HH:mm Z",
"EEE, dd MMM yyyy HH:mm:ss Z",
+ "EEE, dd MMM yyyy HH:mm:ss",
"EEE, dd MMMM yyyy HH:mm:ss Z",
+ "EEE, dd MMMM yyyy HH:mm:ss",
+ "EEEE, dd MMM yyyy HH:mm:ss Z",
"EEEE, dd MMM yy HH:mm:ss Z",
+ "EEEE, dd MMM yyyy HH:mm:ss",
+ "EEEE, dd MMM yy HH:mm:ss",
"EEE MMM d HH:mm:ss yyyy",
+ "EEE, dd MMM yyyy HH:mm Z",
+ "EEE, dd MMM yyyy HH:mm",
+ "EEE, dd MMMM yyyy HH:mm Z",
+ "EEE, dd MMMM yyyy HH:mm",
+ "EEEE, dd MMM yyyy HH:mm Z",
+ "EEEE, dd MMM yy HH:mm Z",
+ "EEEE, dd MMM yyyy HH:mm",
+ "EEEE, dd MMM yy HH:mm",
+ "EEE MMM d HH:mm yyyy",
"yyyy-MM-dd'T'HH:mm:ss",
- "yyyy-MM-dd'T'HH:mm:ss.SSS",
"yyyy-MM-dd'T'HH:mm:ss.SSS Z",
+ "yyyy-MM-dd'T'HH:mm:ss.SSS",
"yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm:ss'Z'",
"yyyy-MM-ddZ",
"yyyy-MM-dd"
};
- SimpleDateFormat parser = new SimpleDateFormat("", Locale.US);
- parser.setLenient(false);
+
ParsePosition pos = new ParsePosition(0);
for(String pattern : patterns) {
parser.applyPattern(pattern);
@@ -69,7 +94,7 @@ public class DateUtils {
}
}
- Log.d(TAG, "Could not parse date string \"" + input + "\"");
+ Log.d(TAG, "Could not parse date string \"" + input + "\" [" + date + "]");
return null;
}
@@ -109,6 +134,7 @@ public class DateUtils {
public static String formatRFC3339UTC(Date date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+ format.setTimeZone(defaultTimezone);
return format.format(date);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java
new file mode 100644
index 000000000..2d5a6e5a1
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java
@@ -0,0 +1,18 @@
+package de.danoeh.antennapod.core.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import java.util.List;
+
+public class IntentUtils {
+
+ public static boolean isCallable(final Context context, final Intent intent) {
+ List<ResolveInfo> list = context.getPackageManager().queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ return list.size() > 0;
+ }
+
+}
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 3a349e221..9296039f0 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
@@ -10,14 +10,16 @@ import android.util.Log;
import java.util.Arrays;
import java.util.List;
-import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.preferences.UserPreferences;
public class NetworkUtils {
- private static final String TAG = "NetworkUtils";
- private NetworkUtils() {
+ private static final String TAG = NetworkUtils.class.getSimpleName();
+ private static Context context;
+
+ public static void init(Context context) {
+ NetworkUtils.context = context;
}
/**
@@ -26,18 +28,16 @@ public class NetworkUtils {
* network that is on the 'selected networks' list of the Wi-Fi filter for
* automatic downloads and false otherwise.
* */
- public static boolean autodownloadNetworkAvailable(Context context) {
+ public static boolean autodownloadNetworkAvailable() {
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo != null) {
if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Device is connected to Wi-Fi");
+ Log.d(TAG, "Device is connected to Wi-Fi");
if (networkInfo.isConnected()) {
if (!UserPreferences.isEnableAutodownloadWifiFilter()) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Auto-dl filter is disabled");
+ Log.d(TAG, "Auto-dl filter is disabled");
return true;
} else {
WifiManager wm = (WifiManager) context
@@ -48,31 +48,28 @@ public class NetworkUtils {
.getAutodownloadSelectedNetworks());
if (selectedNetworks.contains(Integer.toString(wifiInfo
.getNetworkId()))) {
- if (BuildConfig.DEBUG)
- Log.d(TAG,
- "Current network is on the selected networks list");
+ Log.d(TAG, "Current network is on the selected networks list");
return true;
}
}
}
}
}
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Network for auto-dl is not available");
+ Log.d(TAG, "Network for auto-dl is not available");
return false;
}
- public static boolean networkAvailable(Context context) {
+ public static boolean networkAvailable() {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
return info != null && info.isConnected();
}
- public static boolean isDownloadAllowed(Context context) {
- return UserPreferences.isAllowMobileUpdate() || NetworkUtils.connectedToWifi(context);
+ public static boolean isDownloadAllowed() {
+ return UserPreferences.isAllowMobileUpdate() || NetworkUtils.connectedToWifi();
}
- public static boolean connectedToWifi(Context context) {
+ public static boolean connectedToWifi() {
ConnectivityManager connManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java
index 85f32ed50..35916a604 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java
@@ -2,6 +2,8 @@ package de.danoeh.antennapod.core.util;
import android.content.Context;
import android.content.Intent;
+
+import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
@@ -11,24 +13,49 @@ public class ShareUtils {
private ShareUtils() {}
- public static void shareLink(Context context, String link) {
+ public static void shareLink(Context context, String text) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
- i.putExtra(Intent.EXTRA_SUBJECT, "Sharing URL");
- i.putExtra(Intent.EXTRA_TEXT, link);
- context.startActivity(Intent.createChooser(i, "Share URL"));
+ i.putExtra(Intent.EXTRA_TEXT, text);
+ context.startActivity(Intent.createChooser(i, context.getString(R.string.share_url_label)));
}
-
- public static void shareFeedItemLink(Context context, FeedItem item) {
- shareLink(context, item.getLink());
+
+ public static void shareFeedlink(Context context, Feed feed) {
+ shareLink(context, feed.getTitle() + ": " + feed.getLink());
}
public static void shareFeedDownloadLink(Context context, Feed feed) {
- shareLink(context, feed.getDownload_url());
+ shareLink(context, feed.getTitle() + ": " + feed.getDownload_url());
}
-
- public static void shareFeedlink(Context context, Feed feed) {
- shareLink(context, feed.getLink());
+
+ public static void shareFeedItemLink(Context context, FeedItem item) {
+ shareFeedItemLink(context, item, false);
+ }
+
+ public static void shareFeedItemDownloadLink(Context context, FeedItem item) {
+ shareFeedItemDownloadLink(context, item, false);
+ }
+
+ private static String getItemShareText(FeedItem item) {
+ return item.getFeed().getTitle() + ": " + item.getTitle();
+ }
+
+ public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) {
+ String text = getItemShareText(item) + " " + item.getLink();
+ if(withPosition) {
+ int pos = item.getMedia().getPosition();
+ text = item.getLink() + " [" + Converter.getDurationStringLong(pos) + "]";
+ }
+ shareLink(context, text);
+ }
+
+ public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) {
+ String text = getItemShareText(item) + " " + item.getMedia().getDownload_url();
+ if(withPosition) {
+ int pos = item.getMedia().getPosition();
+ text += " [" + Converter.getDurationStringLong(pos) + "]";
+ }
+ shareLink(context, text);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java
index 50792ae26..3b9e6120c 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java
@@ -42,12 +42,6 @@ public class FlattrUtils {
private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken";
- // Flattr URL for this app.
- public static final String APP_URL = "http://antennapod.com";
- // Human-readable flattr-page.
- public static final String APP_LINK = "https://flattr.com/thing/745609/";
- public static final String APP_THING_ID = "745609";
-
private static volatile AccessToken cachedToken;
private static AndroidAuthenticator createAuthenticator() {
@@ -110,18 +104,6 @@ public class FlattrUtils {
storeToken(null);
}
- public static Thing getAppThing(Context context) {
- FlattrService fs = FlattrServiceCreator.getService(retrieveToken());
- try {
- Thing thing = fs.getThing(Thing.withId(APP_THING_ID));
- return thing;
- } catch (FlattrException e) {
- e.printStackTrace();
- showErrorDialog(context, e.getMessage());
- return null;
- }
- }
-
public static void clickUrl(Context context, String url)
throws FlattrException {
if (hasToken()) {
@@ -245,37 +227,6 @@ public class FlattrUtils {
}
}
- public static void showForbiddenDialog(final Context context,
- final String url) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.action_forbidden_title);
- builder.setMessage(R.string.action_forbidden_msg);
- builder.setPositiveButton(R.string.authenticate_now_label,
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- context.startActivity(
- ClientConfig.flattrCallbacks.getFlattrAuthenticationActivityIntent(context));
- }
-
- }
- );
- builder.setNegativeButton(R.string.visit_website_label,
- new OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Uri uri = Uri.parse(url);
- context.startActivity(new Intent(Intent.ACTION_VIEW,
- uri));
- }
-
- }
- );
- builder.create().show();
- }
-
public static void showErrorDialog(final Context context, final String msg) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.error_label);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
index 7ebd580f7..752e95985 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
@@ -7,7 +7,7 @@ import android.util.Log;
import java.util.List;
-import de.danoeh.antennapod.core.asynctask.PicassoImageResource;
+import de.danoeh.antennapod.core.asynctask.ImageResource;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
@@ -18,7 +18,7 @@ import de.danoeh.antennapod.core.util.ShownotesProvider;
* Interface for objects that can be played by the PlaybackService.
*/
public interface Playable extends Parcelable,
- ShownotesProvider, PicassoImageResource {
+ ShownotesProvider, ImageResource {
/**
* Save information about the playable in a preference so that it can be
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 a0d12d3e7..ba5428b81 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
@@ -555,7 +555,7 @@ public abstract class PlaybackController {
* Should be used by classes which implement the OnSeekBarChanged interface.
*/
public void onSeekBarStopTrackingTouch(SeekBar seekBar, float prog) {
- if (playbackService != null) {
+ if (playbackService != null && media != null) {
playbackService.seekTo((int) (prog * media.getDuration()));
setupPositionObserver();
}
diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml
index b52ecf4a4..3610f837e 100644
--- a/core/src/main/res/values-az/strings.xml
+++ b/core/src/main/res/values-az/strings.xml
@@ -46,7 +46,6 @@
<string name="mark_all_read_label">Hamısını oxunmuş kimi işarələ</string>
<string name="show_info_label">Məlumatı göstər</string>
<string name="share_link_label">Web-səhifəyi paylaş</string>
- <string name="share_source_label">Kanalı paylaş</string>
<string name="feed_delete_confirmation_msg">Bütün kanallar və epizodlar silinəçək.</string>
<!--actions on feeditems-->
<string name="download_label">Yüklə</string>
@@ -134,8 +133,6 @@
<string name="pref_followQueue_sum">Oynatma başa çatanda növbədə irəlidəki epizodu oynat</string>
<string name="playback_pref">Oynatma</string>
<string name="network_pref">Şəbəkə</string>
- <string name="pref_autoUpdateIntervall_title">Təzələmə intervalı</string>
- <string name="pref_autoUpdateIntervall_sum">Kanalın avtomatik təzələməsinin intervalını seç ya da keçir onu</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Təkçə Wi-Fi vasitəsiilə yüklə</string>
<string name="pref_followQueue_title">Fasiləsiz oynatma</string>
<string name="pref_downloadMediaOnWifiOnly_title">Wi-Fi vasitəsiilə yükləmə</string>
@@ -210,5 +207,6 @@
<string name="downloading_label">Yükləmə...</string>
<!--Content descriptions for image buttons-->
<!--Feed information screen-->
+ <!--Progress information-->
<!--AntennaPodSP-->
</resources>
diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml
index be7a73e6d..c4887e512 100644
--- a/core/src/main/res/values-ca/strings.xml
+++ b/core/src/main/res/values-ca/strings.xml
@@ -71,7 +71,6 @@
<string name="show_info_label">Mostra informació</string>
<string name="remove_feed_label">Esborra podcast</string>
<string name="share_link_label">Comparteix l\'enllaç de la plana</string>
- <string name="share_source_label">Comparteix l\'enllaç del canal</string>
<string name="feed_delete_confirmation_msg">Confirmeu que, efectivament, voleu suprimir aquest canal i tots els episodis que us n\'heu baixat.</string>
<string name="feed_remover_msg">S\'està esborrant el canal</string>
<string name="load_complete_feed">S\'ha actualitzat el canal</string>
@@ -197,8 +196,6 @@
<string name="pref_auto_delete_title">Esborrat automàtic</string>
<string name="playback_pref">Reproducció</string>
<string name="network_pref">Xarxa</string>
- <string name="pref_autoUpdateIntervall_title">Interval d\'actualització</string>
- <string name="pref_autoUpdateIntervall_sum">Especifiqueu l\'interval en què els canals s\'actualitzen de forma automàtica, o deshabiliteu la funcionalitat.</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Només baixa fitxers a través d\'una xarxa sense fils</string>
<string name="pref_followQueue_title">Reproducció continuada</string>
<string name="pref_downloadMediaOnWifiOnly_title">Baixa a través de xarxes sense fils</string>
@@ -240,8 +237,6 @@
<string name="pref_gpodnet_setlogin_information_sum">Canvia les dades d\'inici de sessió del vostre compte de gpodder.net</string>
<string name="pref_playback_speed_title">Velocitats de reproducció</string>
<string name="pref_playback_speed_sum">Personalitzeu les velocitats disponibles per a una velocitat de reproducció d\'àudio variable</string>
- <string name="pref_seek_delta_title">Salta a l\'instant</string>
- <string name="pref_seek_delta_sum">Salta aquesta quantitat de segons en rebobinar o en avançar ràpidament</string>
<string name="pref_gpodnet_sethostname_title">Definex nom del servidor</string>
<string name="pref_gpodnet_sethostname_use_default_host">Utilitza el servidor per defecte</string>
<string name="pref_expandNotify_title">Amplia la notificació</string>
@@ -283,9 +278,6 @@
<string name="sleep_timer_label">Temporitzador</string>
<string name="time_left_label">Temps restant:\u0020</string>
<string name="time_dialog_invalid_input">L\'entrada no és vàlida, ja que el temps ha de ser un nombre i no ho és</string>
- <string name="time_unit_seconds">segons</string>
- <string name="time_unit_minutes">minuts</string>
- <string name="time_unit_hours">hores</string>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">CATEGORIES</string>
<string name="gpodnet_toplist_header">TOP PODCASTS</string>
@@ -354,6 +346,7 @@
<!--Feed information screen-->
<string name="authentication_label">Autenticació</string>
<string name="authentication_descr">Canvieu el nom d\'usuari i contrasenya per a aquest podcast i els seus episodis.</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">S\'estan important les subscripcions des de les apps de propòsit únic...</string>
</resources>
diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml
index 90304a404..4a89a7d8c 100644
--- a/core/src/main/res/values-cs-rCZ/strings.xml
+++ b/core/src/main/res/values-cs-rCZ/strings.xml
@@ -27,6 +27,12 @@
<string name="drawer_open">Otevřít menu</string>
<string name="drawer_close">Zavřít menu</string>
<string name="drawer_preferences">Nastavení panelu</string>
+ <string name="drawer_feed_order_unplayed_episodes">Řadit dle počtu</string>
+ <string name="drawer_feed_order_alphabetical">Řadit abecedně</string>
+ <string name="drawer_feed_counter_new_unplayed">Počet nových a nepřehraných epizod</string>
+ <string name="drawer_feed_counter_new">Počet nových epizod</string>
+ <string name="drawer_feed_counter_unplayed">Počet nepřehraných epizod</string>
+ <string name="drawer_feed_counter_none">Žádné</string>
<!--Webview actions-->
<string name="open_in_browser_label">Otevřít v prohlížeči</string>
<string name="copy_url_label">Kopírovat URL</string>
@@ -38,6 +44,9 @@
<!--Other-->
<string name="confirm_label">Potvrdit</string>
<string name="cancel_label">Zrušit</string>
+ <string name="yes">Ano</string>
+ <string name="no">Ne
+</string>
<string name="author_label">Autor</string>
<string name="language_label">Jazyk</string>
<string name="url_label">URL</string>
@@ -60,7 +69,13 @@
<string name="close_label">Zavřít</string>
<string name="retry_label">Zkusit znovu</string>
<string name="auto_download_label">Zahrnout do automaticky stahovaných</string>
+ <string name="auto_download_apply_to_items_title">Použít na předchozí epizody</string>
+ <string name="auto_download_apply_to_items_message">Nová funkce <i>auto stahování</i> bude automaticky použita na nové epizody.\nChcete ji také použít na předchozí epizody?</string>
+ <string name="auto_delete_label">Automaticky smazat epizodu\n(přeskočit globální nastavení)</string>
<string name="parallel_downloads_suffix">\u0020paralelních stahování</string>
+ <string name="feed_auto_download_global">Globální</string>
+ <string name="feed_auto_download_always">Vždy</string>
+ <string name="feed_auto_download_never">Nikdy</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL kanálu</string>
<string name="etxtFeedurlHint">URL nebo webová stránka kanálu</string>
@@ -73,14 +88,20 @@
<string name="mark_all_read_msg">Všechny epizody označeny jako poslechnuté</string>
<string name="mark_all_read_confirmation_msg">Prosím potvrďte, že chcete označit všechny vybrané epizody jako poslechnuté.</string>
<string name="mark_all_read_feed_confirmation_msg">Prosím potvrďte, že chcete označit všechny epizody z tohoto zdroje jako poslechnuté.</string>
+ <string name="mark_all_seen_label">Označit vše jako zobrazené</string>
<string name="show_info_label">Informace o zdroji</string>
<string name="remove_feed_label">Odstranit podcast</string>
+ <string name="share_label">Sdílet...</string>
<string name="share_link_label">Sdílet odkaz</string>
- <string name="share_source_label">Sdílet adresu kanálu</string>
+ <string name="share_link_with_position_label">Sdílet odkaz s pozicí</string>
+ <string name="share_feed_url_label">Sdílet URL kanálu</string>
+ <string name="share_item_url_label">Sdílet URL epizody</string>
+ <string name="share_item_url_with_position_label">Sdílet URL epizody s pozicí</string>
<string name="feed_delete_confirmation_msg">Prosím potvrďte, že chcete smazat tento kanál včetně všech stažených epizod.</string>
<string name="feed_remover_msg">Odstranit kanál</string>
<string name="load_complete_feed">Obnovit kompletní kanál</string>
<string name="hide_episodes_title">Skrýt epizody</string>
+ <string name="episode_actions">Provést akce</string>
<string name="hide_unplayed_episodes_label">Neposlechnuté</string>
<string name="hide_paused_episodes_label">Pozastavené</string>
<string name="hide_played_episodes_label">Poslechnuté</string>
@@ -99,8 +120,8 @@
<string name="remove_label">Odstranit</string>
<string name="remove_episode_lable">Odstranit epizodu</string>
<string name="mark_read_label">Označit jako poslechnuté</string>
- <string name="mark_unread_label">Označit jako neposlechnuté</string>
<string name="marked_as_read_label">Označeno jako poslechnuté</string>
+ <string name="mark_unread_label">Označit jako neposlechnuté</string>
<string name="add_to_queue_label">Přidat do fronty</string>
<string name="added_to_queue_label">Přidáno do fronty</string>
<string name="remove_from_queue_label">Odebrat z fronty</string>
@@ -229,8 +250,12 @@
<string name="pref_smart_mark_as_played_title">Chytré označování jako poslechnuté</string>
<string name="playback_pref">Přehrávání</string>
<string name="network_pref">Síť</string>
- <string name="pref_autoUpdateIntervall_title">Interval aktualizace zdrojů</string>
- <string name="pref_autoUpdateIntervall_sum">Udává interval, ve kterém se kanály automaticky aktualizují nebo tuto funkci deaktivuje</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Aktualizovat interval nebo čas v průběhu dne</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Udat interval nebo přesný čas v průběhu dne pro automatickou aktualizaci kanálů</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">Můžete nastavit <i>interval</i> jako třeba \"každé 2 hodiny\", nastavit specifický <i>čas v průběhu dne</i> jako \"7:00\" nebo úplně <i>vypnout</i> automatické aktualizace.\n\n<small>Mějte na paměti: Časy aktualizací nejsou přesné. Možná zaznamenáte krátká zpoždění.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Vypnout</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Nastavit interval</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Nastavit čas v průběhu dne</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Stahovat soubory pouze pomocí WiFi</string>
<string name="pref_followQueue_title">Kontinuální přehrávání</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi stahování</string>
@@ -250,8 +275,14 @@
<string name="pref_auto_flattr_sum">Nastavit automatické flattrování</string>
<string name="user_interface_label">Uživatelské rozhraní</string>
<string name="pref_set_theme_title">Vybrat motiv</string>
+ <string name="pref_nav_drawer_title">Upravit navigační panel</string>
+ <string name="pref_nav_drawer_sum">Upravit vzhled navigačního panelu.</string>
<string name="pref_nav_drawer_items_title">Změnit navigační panel</string>
<string name="pref_nav_drawer_items_sum">Upravit zobrazení položek v navigačním panelu.</string>
+ <string name="pref_nav_drawer_feed_order_title">Nastavit pořadí sbírek</string>
+ <string name="pref_nav_drawer_feed_order_sum">Upravit pořadí vašich sbírek</string>
+ <string name="pref_nav_drawer_feed_counter_title">Nastavit počítadlo sbírek</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Upravit informaci zobrazovanou počítadlem sbírek</string>
<string name="pref_set_theme_sum">Změnit vzhled AntennaPod.</string>
<string name="pref_automatic_download_title">Automatické stahování</string>
<string name="pref_automatic_download_sum">Nastavení automatického stahování epizod.</string>
@@ -283,10 +314,14 @@
<string name="pref_expandNotify_sum">Vždy zobrazovat tlačítka pro přehrávání v upozornění.</string>
<string name="pref_persistNotify_title">Pevné ovládání přehrávání</string>
<string name="pref_persistNotify_sum">Zachovat upozornění a ovládání na obrazovce uzamčení i při pozastaveném přehrávání.</string>
+ <string name="pref_showDownloadReport_title">Zobrazit report stahování</string>
+ <string name="pref_showDownloadReport_sum">Pokud selže stahování, vygenerovat report zobrazující detaily o chybě.</string>
<string name="pref_expand_notify_unsupport_toast">Verze Androidu nižší než 4.1 nepodporují rozšířená upozornění.</string>
<string name="pref_queueAddToFront_sum">Přidávat nové epizody na začátek fronty.</string>
<string name="pref_queueAddToFront_title">Přidat na začátek.</string>
<string name="pref_smart_mark_as_played_disabled">Vypnuto</string>
+ <string name="pref_image_cache_size_title">Velikost odkládací paměti obrázků</string>
+ <string name="pref_image_cache_size_sum">Velikost diskové paměti pro obrázky.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Povolit automatické flattrování</string>
<string name="auto_flattr_after_percent">Flattrovat díl jakmile bude odehráno %d procent</string>
@@ -312,6 +347,7 @@
<string name="opml_import_error_dir_empty">Adresář importu je prázdný.</string>
<string name="select_all_label">Označit vše</string>
<string name="deselect_all_label">Zrušit výběr</string>
+ <string name="select_options_label">Vybrat ...</string>
<string name="choose_file_from_filesystem">Z místního souborového systému</string>
<string name="choose_file_from_external_application">Použít externí aplikaci</string>
<string name="opml_export_label">OPML export</string>
@@ -326,9 +362,24 @@
<string name="sleep_timer_label">Časovač vypnutí</string>
<string name="time_left_label">Zbývající čas:\u0020</string>
<string name="time_dialog_invalid_input">Neplatný vstup, musí být zadáno celé číslo</string>
- <string name="time_unit_seconds">sekund</string>
- <string name="time_unit_minutes">minut</string>
- <string name="time_unit_hours">hodin</string>
+ <string name="time_seconds">sekund</string>
+ <string name="time_minutes">minut</string>
+ <string name="time_hours">hodin</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 sekunda</item>
+ <item quantity="few">%d sekundy</item>
+ <item quantity="other">%d sekund</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minuta</item>
+ <item quantity="few">%d minuty</item>
+ <item quantity="other">%d minut</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 hodina</item>
+ <item quantity="few">%d hodiny</item>
+ <item quantity="other">%d hodin</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">KATEGORIE</string>
<string name="gpodnet_toplist_header">TOP PODCASTY</string>
@@ -373,6 +424,7 @@
<string name="pref_pausePlaybackForFocusLoss_title">Automatické pozastavení přehrávání</string>
<string name="pref_resumeAfterCall_sum">Pokračovat v přehrávání po ukončení telefonního hovoru</string>
<string name="pref_resumeAfterCall_title">Pokračovat po telefonátu</string>
+ <string name="pref_restart_required">Pro aktivování změn nastavení bylo třeba restartovat aplikaci AntennaPod.</string>
<!--Online feed view-->
<string name="subscribe_label">Odebírat</string>
<string name="subscribed_label">Odebíráno</string>
@@ -399,7 +451,29 @@
<!--Feed information screen-->
<string name="authentication_label">Ověření</string>
<string name="authentication_descr">Změnit uživatelské jméno a heslo pro tento podcast a jeho epizody.</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">Probíhá aktualizace databáze</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importuji odběry z jednoúčelových aplikací...</string>
<string name="search_itunes_label">Prohledat iTunes</string>
+ <string name="select_label"><b>Vybrat ...</b></string>
+ <string name="all_label">Vše</string>
+ <string name="selected_all_label">Vybrány všechny epizody</string>
+ <string name="none_label">Žádné</string>
+ <string name="deselected_all_label">Odebrány všechny epizody</string>
+ <string name="played_label">Přehrány</string>
+ <string name="selected_played_label">Vybrány přehrané epizody</string>
+ <string name="unplayed_label">Nepřehrány</string>
+ <string name="selected_unplayed_label">Odebrány nepřehrané epizody</string>
+ <string name="downloaded_label">Stažené</string>
+ <string name="selected_downloaded_label">Vybrány stažené epizody</string>
+ <string name="not_downloaded_label">Nestažené</string>
+ <string name="selected_not_downloaded_label">Vybrány nestažené epizody</string>
+ <string name="sort_title"><b>Řadit podle ...</b></string>
+ <string name="sort_title_a_z">Názvu (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Názvu (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Data (Nové \u2192 Staré)</string>
+ <string name="sort_date_old_new">Data (Staré \u2192 Nové)</string>
+ <string name="sort_duration_short_long">Délka (Krátké \u2192 Dlouhé)</string>
+ <string name="sort_duration_long_short">Délka (Dlouhé \u2192 Krátké)</string>
</resources>
diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml
index ba7fafca6..cc18185ec 100644
--- a/core/src/main/res/values-da/strings.xml
+++ b/core/src/main/res/values-da/strings.xml
@@ -71,7 +71,6 @@
<string name="show_info_label">Vis information</string>
<string name="remove_feed_label">Fjern podcast</string>
<string name="share_link_label">Del webside link</string>
- <string name="share_source_label">Del feed link</string>
<string name="feed_delete_confirmation_msg">Bekræft venligst at du vil fjerne dette feed og ALLE episoder du har downloadet fra dette feed.</string>
<string name="feed_remover_msg">Fjerner feed</string>
<string name="load_complete_feed">Opdater hele feed\'et</string>
@@ -197,8 +196,6 @@
<string name="pref_auto_delete_title">Slet Automatisk</string>
<string name="playback_pref">Afspilning</string>
<string name="network_pref">Netværk</string>
- <string name="pref_autoUpdateIntervall_title">Opdaterings interval</string>
- <string name="pref_autoUpdateIntervall_sum">Specificer et interval indenfor hvilket feeds opdaterer automatisk eller deaktiver det</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Download kun medie filer over WiFi</string>
<string name="pref_followQueue_title">Kontinuerlig afspilning</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi medie download</string>
@@ -240,8 +237,6 @@
<string name="pref_gpodnet_setlogin_information_sum">Skift din gpodder.net kontos login information.</string>
<string name="pref_playback_speed_title">Afspilningshastigheder</string>
<string name="pref_playback_speed_sum">Tilpas tilgængelige hastigheder for variabelt afspilningshastigheds plugin</string>
- <string name="pref_seek_delta_title">Søg tid</string>
- <string name="pref_seek_delta_sum">Søg så mange sekunder når der spoles tilbage eller frem</string>
<string name="pref_gpodnet_sethostname_title">Indstil værtsnavn</string>
<string name="pref_gpodnet_sethostname_use_default_host">Brug standard vært</string>
<string name="pref_expandNotify_title">Udvid notifikation</string>
@@ -283,9 +278,6 @@
<string name="sleep_timer_label">Søvn timer</string>
<string name="time_left_label">Tid tilbage:\u0020</string>
<string name="time_dialog_invalid_input">Ugyldig indtastning, tid skal være et heltal</string>
- <string name="time_unit_seconds">sekunder</string>
- <string name="time_unit_minutes">minutter</string>
- <string name="time_unit_hours">timer</string>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">KATEGORIER </string>
<string name="gpodnet_toplist_header">TOP PODCASTS</string>
@@ -354,6 +346,7 @@
<!--Feed information screen-->
<string name="authentication_label">Godkendelse</string>
<string name="authentication_descr">Skift dit brugernavn og kodeord for denne podcast og dets episoder.</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importerer abonnementer fra single-purpose apps…</string>
</resources>
diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml
index 93e52acb6..47a0d7877 100644
--- a/core/src/main/res/values-de/strings.xml
+++ b/core/src/main/res/values-de/strings.xml
@@ -27,6 +27,12 @@
<string name="drawer_open">Menü öffnen</string>
<string name="drawer_close">Menü schließen</string>
<string name="drawer_preferences">Seitenleisten-Einstellungen</string>
+ <string name="drawer_feed_order_unplayed_episodes">Sortieren nach Zähler</string>
+ <string name="drawer_feed_order_alphabetical">Alphabetisch sortieren</string>
+ <string name="drawer_feed_counter_new_unplayed">Anzahl neuer und ungespielter Episoden</string>
+ <string name="drawer_feed_counter_new">Anzahl neuer Episoden</string>
+ <string name="drawer_feed_counter_unplayed">Anzahl ungespielter Episoden</string>
+ <string name="drawer_feed_counter_none">Keine</string>
<!--Webview actions-->
<string name="open_in_browser_label">Im Browser öffnen</string>
<string name="copy_url_label">URL kopieren</string>
@@ -38,6 +44,8 @@
<!--Other-->
<string name="confirm_label">Bestätigen</string>
<string name="cancel_label">Abbrechen</string>
+ <string name="yes">Ja</string>
+ <string name="no">Nein</string>
<string name="author_label">Autor</string>
<string name="language_label">Sprache</string>
<string name="url_label">URL</string>
@@ -60,7 +68,13 @@
<string name="close_label">Schließen</string>
<string name="retry_label">Erneut versuchen</string>
<string name="auto_download_label">Automatisch herunterladen</string>
+ <string name="auto_download_apply_to_items_title">Auf bisherige Episoden anwenden</string>
+ <string name="auto_download_apply_to_items_message">Die neue Einstellung zum <i>Automatischen Download</i> wird automatisch auf neue Episoden angewandt.\nMöchtest du sie auch auf die bisherige Episoden anwenden?</string>
+ <string name="auto_delete_label">Episoden automatisch löschen\n(überschreibt globale Vorgabe)</string>
<string name="parallel_downloads_suffix">\u0020gleichzeitige Downloads</string>
+ <string name="feed_auto_download_global">Global</string>
+ <string name="feed_auto_download_always">Immer</string>
+ <string name="feed_auto_download_never">Nie</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">Feed URL</string>
<string name="etxtFeedurlHint">URL des Feeds oder der Webseite</string>
@@ -73,14 +87,20 @@
<string name="mark_all_read_msg">Alle Episoden als gespielt markieren</string>
<string name="mark_all_read_confirmation_msg">Bitte bestätige, dass alle Episoden als gespielt markiert werden sollen.</string>
<string name="mark_all_read_feed_confirmation_msg">Bitte bestätige, dass alle Episoden in diesem Feed als gespielt markiert werden sollen.</string>
+ <string name="mark_all_seen_label">Alle als gesehen markieren</string>
<string name="show_info_label">Informationen anzeigen</string>
<string name="remove_feed_label">Podcast entfernen</string>
+ <string name="share_label">Teile...</string>
<string name="share_link_label">Webseiten-Link teilen</string>
- <string name="share_source_label">Feed-Link teilen</string>
+ <string name="share_link_with_position_label">Teile Link mit Zeitmarke</string>
+ <string name="share_feed_url_label">Teile URL des Podcasts</string>
+ <string name="share_item_url_label">Teile URL der Episode</string>
+ <string name="share_item_url_with_position_label">Teile URL der Episode mit Zeitmarke</string>
<string name="feed_delete_confirmation_msg">Bitte bestätige, dass du diesen Feed und ALLE heruntergeladenen Episoden dieses Feeds entfernen möchtest.</string>
<string name="feed_remover_msg">Entferne Feed</string>
<string name="load_complete_feed">Kompletten Feed aktualisieren</string>
<string name="hide_episodes_title">Episoden verbergen</string>
+ <string name="episode_actions">Aktionen anwenden</string>
<string name="hide_unplayed_episodes_label">Ungespielt</string>
<string name="hide_paused_episodes_label">Pausiert</string>
<string name="hide_played_episodes_label">Gespielt</string>
@@ -99,8 +119,8 @@
<string name="remove_label">Entfernen</string>
<string name="remove_episode_lable">Episode entfernen</string>
<string name="mark_read_label">Als gespielt markieren</string>
- <string name="mark_unread_label">Als ungespielt markieren</string>
<string name="marked_as_read_label">Als gespielt markiert</string>
+ <string name="mark_unread_label">Als ungespielt markieren</string>
<string name="add_to_queue_label">Zur Abspielliste hinzufügen</string>
<string name="added_to_queue_label">Zur Abspielliste hinzugefügt</string>
<string name="remove_from_queue_label">Aus der Abspielliste entfernen</string>
@@ -229,8 +249,12 @@
<string name="pref_smart_mark_as_played_title">Schlaues als gespielt markieren</string>
<string name="playback_pref">Wiedergabe</string>
<string name="network_pref">Netzwerk</string>
- <string name="pref_autoUpdateIntervall_title">Aktualisierungsintervall</string>
- <string name="pref_autoUpdateIntervall_sum">Lege ein Intervall fest, in dem Feeds automatisch aktualisiert werden oder deaktiviere es</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Aktualisierungsintervall oder -tageszeit</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Lege ein Intervall oder eine Tageszeit zur automatischen Aktualisierung der Podcasts fest</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">Du kannst ein festes <i>Intervall</i> wie \"alle 2 Stunden\", eine bestimmte <i>Tageszeit</i> wie \"7 Uhr morgens\" festlegen oder die automatische Aktualisierung komplett <i>deaktivieren</i>.\n\n<small>Bitte beachte: Der Zeitpunkt der Aktualisierung ist ungenau. Du wirst vielleicht eine kurze Verzögerung bemerken.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Deaktivieren</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Intervall einstellen</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Tageszeit festlegen</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Lade Mediendateien nur über WiFi</string>
<string name="pref_followQueue_title">Durchgehendes Abspielen</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi Medien-Download</string>
@@ -250,8 +274,14 @@
<string name="pref_auto_flattr_sum">Automatisches Flattrn konfigurieren</string>
<string name="user_interface_label">Benutzeroberfläche</string>
<string name="pref_set_theme_title">Theme auswählen</string>
+ <string name="pref_nav_drawer_title">Seitenleiste anpassen</string>
+ <string name="pref_nav_drawer_sum">Passe das Aussehen der Seitenleiste an.</string>
<string name="pref_nav_drawer_items_title">Seitenleiste ändern</string>
<string name="pref_nav_drawer_items_sum">Ändere, welche Listen in der Seitenleiste erscheinen</string>
+ <string name="pref_nav_drawer_feed_order_title">Reihenfolge der Abonnements einstellen</string>
+ <string name="pref_nav_drawer_feed_order_sum">Ändere die Reihenfolge deiner Abonnements</string>
+ <string name="pref_nav_drawer_feed_counter_title">Abonnement-Zähler einstellen</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Ändere, welche Information der Abonnement-Zähler anzeigt</string>
<string name="pref_set_theme_sum">Ändere das Aussehen von AntennaPod.</string>
<string name="pref_automatic_download_title">Automatisches Herunterladen</string>
<string name="pref_automatic_download_sum">Konfiguriere das automatische Herunterladen von Episoden.</string>
@@ -283,10 +313,14 @@
<string name="pref_expandNotify_sum">Erweiterte Wiedergabebenachrichtigung mit Abspiel-, Pause- und Stop-Knöpfen anzeigen.</string>
<string name="pref_persistNotify_title">Persistente Wiedergabesteurung</string>
<string name="pref_persistNotify_sum">Zeige Wiedergabebedienelemente in der Benachrichtigung und im Lockscreen an, während die Wiedergabe pausiert ist.</string>
+ <string name="pref_showDownloadReport_title">Zeige Download-Bericht</string>
+ <string name="pref_showDownloadReport_sum">Wenn Downloads fehlschlagen, erstelle einen Bericht, der die Details des Fehlschlages beschreibt.</string>
<string name="pref_expand_notify_unsupport_toast">Android-Versionen vor 4.1 unterstützen keine erweiterten Benachrichtigungen.</string>
<string name="pref_queueAddToFront_sum">Fügen Sie neue Folgen auf den Anfang der Warteschlange.</string>
<string name="pref_queueAddToFront_title">Vorne in Abspielliste einreihen</string>
<string name="pref_smart_mark_as_played_disabled">Deaktiviert</string>
+ <string name="pref_image_cache_size_title">Größe des Bilder-Zwischenspeichers</string>
+ <string name="pref_image_cache_size_sum">Größe des Zwischenspeichers für Bilder</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Automatisches Flattrn aktivieren</string>
<string name="auto_flattr_after_percent">Flattr eine Episode, sobald %d Prozent gespielt worden sind</string>
@@ -312,6 +346,7 @@
<string name="opml_import_error_dir_empty">Der Import-Ordner ist leer.</string>
<string name="select_all_label">Alle auswählen</string>
<string name="deselect_all_label">Auswahl zurücksetzen</string>
+ <string name="select_options_label">Wähle aus ...</string>
<string name="choose_file_from_filesystem">Vom lokalen Dateisystem</string>
<string name="choose_file_from_external_application">Verwende externe Anwendung</string>
<string name="opml_export_label">OPML Export</string>
@@ -326,9 +361,21 @@
<string name="sleep_timer_label">Schlummerfunktion</string>
<string name="time_left_label">Zeit übrig:\u0020</string>
<string name="time_dialog_invalid_input">Ungültige Eingabe, Zeit muss eine Ganzzahl sein</string>
- <string name="time_unit_seconds">Sekunden</string>
- <string name="time_unit_minutes">Minuten</string>
- <string name="time_unit_hours">Stunden</string>
+ <string name="time_seconds">Sekunden</string>
+ <string name="time_minutes">Minuten</string>
+ <string name="time_hours">Stunden</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 Sekunde</item>
+ <item quantity="other">%d Sekunden</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 Minute</item>
+ <item quantity="other">%d Minuten</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 Stunde</item>
+ <item quantity="other">%d Stunden</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">KATEGORIEN</string>
<string name="gpodnet_toplist_header">BESTE PODCASTS</string>
@@ -373,6 +420,7 @@
<string name="pref_pausePlaybackForFocusLoss_title">Bei Unterbrechungen pausieren</string>
<string name="pref_resumeAfterCall_sum">Wiedergabe fortsetzen, wenn Anruf beendet ist</string>
<string name="pref_resumeAfterCall_title">Nach Anruf fortsetzen</string>
+ <string name="pref_restart_required">AntennaPod muss neu gestartet werden, damit die Änderungen wirksam werden.</string>
<!--Online feed view-->
<string name="subscribe_label">Abonnieren</string>
<string name="subscribed_label">Abonniert</string>
@@ -399,7 +447,29 @@
<!--Feed information screen-->
<string name="authentication_label">Authentifizierung</string>
<string name="authentication_descr">Ändere den Benutzernamen und das Passwort für diesen Podcast und dessen Episoden.</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">Datenbank wird aktualisiert</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importiere Abonnements aus Single-Purpose Apps</string>
<string name="search_itunes_label">iTunes durchsuchen</string>
+ <string name="select_label"><b>Wähle aus ...</b></string>
+ <string name="all_label">Alle</string>
+ <string name="selected_all_label">Alle Episoden ausgewählt</string>
+ <string name="none_label">Keine</string>
+ <string name="deselected_all_label">Alle Episoden abgewählt</string>
+ <string name="played_label">Gespielt</string>
+ <string name="selected_played_label">Gespielte Episoden ausgewählt</string>
+ <string name="unplayed_label">Ungespielt</string>
+ <string name="selected_unplayed_label">Ungespielte Episoden ausgewählt</string>
+ <string name="downloaded_label">Heruntergeladen</string>
+ <string name="selected_downloaded_label">Heruntergeladene Episoden ausgewählt</string>
+ <string name="not_downloaded_label">Nicht heruntergeladen</string>
+ <string name="selected_not_downloaded_label">Nicht heruntergeladene Episoden ausgewählt</string>
+ <string name="sort_title"><b>Sortieren nach ...</b></string>
+ <string name="sort_title_a_z">Titel (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Titel (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Datum (neu \u2192 alt)</string>
+ <string name="sort_date_old_new">Datum (alt \u2192 neu)</string>
+ <string name="sort_duration_short_long">Dauer (kurz \u2192 lang)</string>
+ <string name="sort_duration_long_short">Dauer (lang \u2192 kurz)</string>
</resources>
diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml
index d05c34876..2607d1794 100644
--- a/core/src/main/res/values-es-rES/strings.xml
+++ b/core/src/main/res/values-es-rES/strings.xml
@@ -42,7 +42,6 @@
<string name="mark_all_read_label">Marcar todo como leído</string>
<string name="show_info_label">Información del programa</string>
<string name="share_link_label">Compartir el enlace de la web</string>
- <string name="share_source_label">Compartir el enlace del canal</string>
<string name="feed_delete_confirmation_msg">Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo.</string>
<!--actions on feeditems-->
<string name="download_label">Descargar</string>
@@ -125,8 +124,6 @@
<string name="pref_followQueue_sum">Saltar al siguiente elemento de la cola al acabar la reproducción</string>
<string name="playback_pref">Reproducción</string>
<string name="network_pref">Red</string>
- <string name="pref_autoUpdateIntervall_title">Intervalo de actualización</string>
- <string name="pref_autoUpdateIntervall_sum">Especificar el intervalo en que se actualizarán automáticamente los canales, o desactivarlo</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Solo descargar los contenidos por WiFi</string>
<string name="pref_followQueue_title">Reproducción continua</string>
<string name="pref_downloadMediaOnWifiOnly_title">Descarga de contenidos por WiFi</string>
@@ -193,5 +190,6 @@
<!--Online feed view-->
<!--Content descriptions for image buttons-->
<!--Feed information screen-->
+ <!--Progress information-->
<!--AntennaPodSP-->
</resources>
diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml
index d5255a589..6670836db 100644
--- a/core/src/main/res/values-es/strings.xml
+++ b/core/src/main/res/values-es/strings.xml
@@ -27,6 +27,12 @@
<string name="drawer_open">Abrir menú</string>
<string name="drawer_close">Cerrar menú</string>
<string name="drawer_preferences">Preferencias del cajón</string>
+ <string name="drawer_feed_order_unplayed_episodes">Ordenar por cuenta</string>
+ <string name="drawer_feed_order_alphabetical">Ordenar alfabéticamente</string>
+ <string name="drawer_feed_counter_new_unplayed">Cantidad de episodios nuevos y no escuchados</string>
+ <string name="drawer_feed_counter_new">Cantidad de episodios nuevos</string>
+ <string name="drawer_feed_counter_unplayed">Cantidad de episodios no escuchados</string>
+ <string name="drawer_feed_counter_none">Ninguno</string>
<!--Webview actions-->
<string name="open_in_browser_label">Abrir en el navegador</string>
<string name="copy_url_label">Copiar URL</string>
@@ -38,6 +44,8 @@
<!--Other-->
<string name="confirm_label">Confirmar</string>
<string name="cancel_label">Cancelar</string>
+ <string name="yes">Sí</string>
+ <string name="no">No</string>
<string name="author_label">Autor</string>
<string name="language_label">Idioma</string>
<string name="url_label">URL</string>
@@ -60,7 +68,13 @@
<string name="close_label">Cerrar</string>
<string name="retry_label">Reintentar</string>
<string name="auto_download_label">Incluir en descargas automáticas</string>
+ <string name="auto_download_apply_to_items_title">Aplicar a episodios anteriores</string>
+ <string name="auto_download_apply_to_items_message">La nueva opción <i>Auto Descarga</i> se aplicará automáticamente a episodios nuevos.\n¿También desea aplicarlo a episodios anteriores?</string>
+ <string name="auto_delete_label">Auto borrar episodio\n(Ignorando los ajustes globales)</string>
<string name="parallel_downloads_suffix">\u0020descargas paralelas</string>
+ <string name="feed_auto_download_global">Global</string>
+ <string name="feed_auto_download_always">Siempre</string>
+ <string name="feed_auto_download_never">Nunca</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL del canal</string>
<string name="etxtFeedurlHint">URL del canal o del sitio web</string>
@@ -73,14 +87,20 @@
<string name="mark_all_read_msg">Se marcaron todos los episodios como escuchados</string>
<string name="mark_all_read_confirmation_msg">Por favor, confirme que desea marcar todos los episodios como escuchados.</string>
<string name="mark_all_read_feed_confirmation_msg">Por favor, confirme que desea marcar todos los episodios de este feed como escuchados.</string>
+ <string name="mark_all_seen_label">Marcar todos como vistos</string>
<string name="show_info_label">Información del programa</string>
<string name="remove_feed_label">Eliminar podcast</string>
+ <string name="share_label">Compartir...</string>
<string name="share_link_label">Compartir el enlace de la web</string>
- <string name="share_source_label">Compartir el enlace del canal</string>
+ <string name="share_link_with_position_label">Compartir enlace con posición</string>
+ <string name="share_feed_url_label">Compartir URL del canal</string>
+ <string name="share_item_url_label">Compartir URL del episodio</string>
+ <string name="share_item_url_with_position_label">Compartir URL del episodio con posición</string>
<string name="feed_delete_confirmation_msg">Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo.</string>
<string name="feed_remover_msg">Quitando el canal</string>
<string name="load_complete_feed">Actualizar el canal completo</string>
<string name="hide_episodes_title">Ocultar episodios</string>
+ <string name="episode_actions">Aplicar acciones</string>
<string name="hide_unplayed_episodes_label">No escuchados</string>
<string name="hide_paused_episodes_label">Pausados</string>
<string name="hide_played_episodes_label">Escuchados</string>
@@ -99,8 +119,8 @@
<string name="remove_label">Quitar</string>
<string name="remove_episode_lable">Quitar episodio</string>
<string name="mark_read_label">Marcar como escuchado</string>
- <string name="mark_unread_label">Marcar como no escuchado</string>
<string name="marked_as_read_label">Marcado como escuchado</string>
+ <string name="mark_unread_label">Marcar como no escuchado</string>
<string name="add_to_queue_label">Añadir a la cola</string>
<string name="added_to_queue_label">Añadido a la cola</string>
<string name="remove_from_queue_label">Quitar de la cola</string>
@@ -229,8 +249,12 @@
<string name="pref_smart_mark_as_played_title">Marcar como escuchado inteligente</string>
<string name="playback_pref">Reproducción</string>
<string name="network_pref">Red</string>
- <string name="pref_autoUpdateIntervall_title">Intervalo de actualización</string>
- <string name="pref_autoUpdateIntervall_sum">Especificar el intervalo en que se actualizarán automáticamente los canales, o desactivarlo</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Intervalo de actualización u hora del día</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Especificar el intervalo o la hora del día en que se actualizarán automáticamente los canales</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">Se puede ajustar un <i>intervalo</i> como \"cada 2 horas\", especificar una <i>hora del día</i> como \"7:00 AM\" o <i>deshabilitar</i> las actualizaciones automáticas.\n\n<small>Nota: Las horas de actualización no son exactas. Puede haber un ligero retraso.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Deshabilitar</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Ajustar intervalo</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Ajustar hora del día</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Solo descargar los contenidos por WiFi</string>
<string name="pref_followQueue_title">Reproducción continua</string>
<string name="pref_downloadMediaOnWifiOnly_title">Descarga de contenidos por WiFi</string>
@@ -250,8 +274,14 @@
<string name="pref_auto_flattr_sum">Configurar flattr automático</string>
<string name="user_interface_label">Interfaz de usuario</string>
<string name="pref_set_theme_title">Elegir un tema</string>
+ <string name="pref_nav_drawer_title">Personalizar el cajón de navegación</string>
+ <string name="pref_nav_drawer_sum">Personalizar la apariencia del cajón de navegación</string>
<string name="pref_nav_drawer_items_title">Cambiar el cajón de navegación</string>
<string name="pref_nav_drawer_items_sum">Cambiar los ítems que aparecen en el cajón de navegación</string>
+ <string name="pref_nav_drawer_feed_order_title">Ajustar orden de suscripción</string>
+ <string name="pref_nav_drawer_feed_order_sum">Cambiar el orden de las suscripciones</string>
+ <string name="pref_nav_drawer_feed_counter_title">Ajustar contador de suscripción</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Cambiar la información mostrada en el contador de suscripción</string>
<string name="pref_set_theme_sum">Cambiar la apariencia de AntennaPod.</string>
<string name="pref_automatic_download_title">Descarga automática</string>
<string name="pref_automatic_download_sum">Configurar la descarga automática de episodios.</string>
@@ -283,10 +313,14 @@
<string name="pref_expandNotify_sum">Expandir siempre la notificación para mostrar los botones de reproducción</string>
<string name="pref_persistNotify_title">Controles de reproducción persistentes</string>
<string name="pref_persistNotify_sum">Mantener la notificación y controles en pantalla de bloqueo cuando se pausa.</string>
+ <string name="pref_showDownloadReport_title">Mostrar informe de descarga</string>
+ <string name="pref_showDownloadReport_sum">Si la descarga falla, generar un informe con los detalles del fallo</string>
<string name="pref_expand_notify_unsupport_toast">Las versiones de Android anteriores a la 4.1 no soportan notificaciones expandidas</string>
<string name="pref_queueAddToFront_sum">Agregar nuevos episodios al principio de la cola.</string>
<string name="pref_queueAddToFront_title">Poner al principio de la cola.</string>
<string name="pref_smart_mark_as_played_disabled">Deshabilitado</string>
+ <string name="pref_image_cache_size_title">Tamaño de la caché de imágenes</string>
+ <string name="pref_image_cache_size_sum">Tamaño de la caché en disco para imágenes.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Habilitar Flattr automático</string>
<string name="auto_flattr_after_percent">Hacer Flattr del episodio en cuanto se haya reproducido el %d por ciento</string>
@@ -312,6 +346,7 @@
<string name="opml_import_error_dir_empty">El directorio de importación está vacío.</string>
<string name="select_all_label">Seleccionar todo</string>
<string name="deselect_all_label">Deseleccionar todo</string>
+ <string name="select_options_label">Seleccionar...</string>
<string name="choose_file_from_filesystem">Desde el sistema de ficheros local</string>
<string name="choose_file_from_external_application">Usar aplicación externa</string>
<string name="opml_export_label">Exportar a OPML</string>
@@ -326,9 +361,21 @@
<string name="sleep_timer_label">Temporizador</string>
<string name="time_left_label">Tiempo restante:\u0020</string>
<string name="time_dialog_invalid_input">Entrada no válida, el tiempo debe ser un entero</string>
- <string name="time_unit_seconds">segundos</string>
- <string name="time_unit_minutes">minutos</string>
- <string name="time_unit_hours">horas</string>
+ <string name="time_seconds">segundos</string>
+ <string name="time_minutes">minutos</string>
+ <string name="time_hours">horas</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 segundo</item>
+ <item quantity="other">%d segundos</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minuto</item>
+ <item quantity="other">%d minutos</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 hora</item>
+ <item quantity="other">%d horas</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">CATEGORÍAS</string>
<string name="gpodnet_toplist_header">MEJORES PODCASTS</string>
@@ -373,6 +420,7 @@
<string name="pref_pausePlaybackForFocusLoss_title">Pausar durante las interrupciones</string>
<string name="pref_resumeAfterCall_sum">Reanudar reproducción tras una llamada</string>
<string name="pref_resumeAfterCall_title">Reanudar tras una llamada</string>
+ <string name="pref_restart_required">Es necesario reiniciar AntennaPod para aplicar los cambios.</string>
<!--Online feed view-->
<string name="subscribe_label">Suscribirse</string>
<string name="subscribed_label">Suscrito</string>
@@ -399,7 +447,29 @@
<!--Feed information screen-->
<string name="authentication_label">Autenticación</string>
<string name="authentication_descr">Cambiar nombre y contraseña de este podcast y sus episodios</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">Actualizando la base de datos</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importando subscripciones de aplicaciones de uso específico...</string>
<string name="search_itunes_label">Buscar en iTunes</string>
+ <string name="select_label"><b>Seleccionar...</b></string>
+ <string name="all_label">Todo</string>
+ <string name="selected_all_label">Seleccionados todos los episodios</string>
+ <string name="none_label">Ninguno</string>
+ <string name="deselected_all_label">Deseleccionados todos los episodios</string>
+ <string name="played_label">Reproducido</string>
+ <string name="selected_played_label">Seleccionados episodios reproducidos</string>
+ <string name="unplayed_label">No reproducidos</string>
+ <string name="selected_unplayed_label">Seleccionados episodios no reproducidos</string>
+ <string name="downloaded_label">Descargado</string>
+ <string name="selected_downloaded_label">Seleccionados episodios descargados</string>
+ <string name="not_downloaded_label">No descargado</string>
+ <string name="selected_not_downloaded_label">Seleccionados episodios no descargados</string>
+ <string name="sort_title"><b>Ordenar por...</b></string>
+ <string name="sort_title_a_z">Título (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Título (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Fecha (Nuevo \u2192 Antiguo)</string>
+ <string name="sort_date_old_new">Fecha (Antiguo \u2192 Nuevo)</string>
+ <string name="sort_duration_short_long">Duración (Corto \u2192 Largo)</string>
+ <string name="sort_duration_long_short">Duración (Largo \u2192 Corto)</string>
</resources>
diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml
index 2f59e139d..10d3fe9a4 100644
--- a/core/src/main/res/values-fr/strings.xml
+++ b/core/src/main/res/values-fr/strings.xml
@@ -26,6 +26,12 @@
<!--Main activity-->
<string name="drawer_open">Ouvrir le menu</string>
<string name="drawer_close">Fermer le menu</string>
+ <string name="drawer_feed_order_unplayed_episodes">Trier par compteur</string>
+ <string name="drawer_feed_order_alphabetical">Trier alphabétiquement</string>
+ <string name="drawer_feed_counter_new_unplayed">Nombre de nouveaux épisodes non-lus</string>
+ <string name="drawer_feed_counter_new">Nombre de nouveaux épisodes</string>
+ <string name="drawer_feed_counter_unplayed">Nombre d\'épisodes non-lus</string>
+ <string name="drawer_feed_counter_none">Aucun</string>
<!--Webview actions-->
<string name="open_in_browser_label">Ouvrir dans le navigateur</string>
<string name="copy_url_label">Copier l\'URL</string>
@@ -37,8 +43,11 @@
<!--Other-->
<string name="confirm_label">Confirmer</string>
<string name="cancel_label">Annuler</string>
+ <string name="yes">Oui</string>
+ <string name="no">Non</string>
<string name="author_label">Auteur</string>
<string name="language_label">Langue</string>
+ <string name="url_label">URL</string>
<string name="podcast_settings_label">Préférences</string>
<string name="cover_label">Image</string>
<string name="error_label">Erreur</string>
@@ -58,7 +67,11 @@
<string name="close_label">Fermer</string>
<string name="retry_label">Réessayer</string>
<string name="auto_download_label">Télécharger automatiquement à l\'avenir</string>
+ <string name="auto_download_apply_to_items_title">Appliquer aux épisodes précédents</string>
<string name="parallel_downloads_suffix">\u0020téléchargements parallèles</string>
+ <string name="feed_auto_download_global">Global</string>
+ <string name="feed_auto_download_always">Toujours</string>
+ <string name="feed_auto_download_never">Jamais</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL du flux</string>
<string name="etxtFeedurlHint">URL ou flux ou site web</string>
@@ -71,13 +84,29 @@
<string name="mark_all_read_msg">Tous les épisodes ont été marqués comme lus</string>
<string name="mark_all_read_confirmation_msg">Veuillez confirmer que vous voulez bien marquer tous les épisodes comme lus</string>
<string name="mark_all_read_feed_confirmation_msg">Veuillez confirmer que vous voulez bien marquer tous les épisode de ce flux comme lus</string>
+ <string name="mark_all_seen_label">Marquer tout comme vu</string>
<string name="show_info_label">Voir les détails</string>
<string name="remove_feed_label">Supprimer le podcast</string>
+ <string name="share_label">Partager...</string>
<string name="share_link_label">Partager un lien vers le site</string>
- <string name="share_source_label">Partager le flux</string>
+ <string name="share_link_with_position_label">Partager lien avec position</string>
+ <string name="share_feed_url_label">Partager lien du flux</string>
+ <string name="share_item_url_label">Partager lien de l\'épisode</string>
+ <string name="share_item_url_with_position_label">Partager lien de l\'épisode avec position</string>
<string name="feed_delete_confirmation_msg">Veuillez confirmer que vous voulez bien supprimer ce flux et TOUS ses épisodes que vous avez téléchargés.</string>
<string name="feed_remover_msg">Flux en cours de suppression</string>
<string name="load_complete_feed">Mettre à jour tout le flux</string>
+ <string name="hide_episodes_title">Cacher épisodes</string>
+ <string name="episode_actions">Appliquer les actions</string>
+ <string name="hide_unplayed_episodes_label">Non joués</string>
+ <string name="hide_paused_episodes_label">En pause</string>
+ <string name="hide_played_episodes_label">Joués</string>
+ <string name="hide_queued_episodes_label">Rajouté à la liste</string>
+ <string name="hide_not_queued_episodes_label">Pas rajouté à la liste</string>
+ <string name="hide_downloaded_episodes_label">Téléchargé</string>
+ <string name="hide_not_downloaded_episodes_label">Non téléchargé</string>
+ <string name="filtered_label">Filtré</string>
+ <string name="refresh_failed_msg">{fa-exclamation-circle} Dernière mise à jour échouée</string>
<!--actions on feeditems-->
<string name="download_label">Télécharger</string>
<string name="play_label">Lire</string>
@@ -87,15 +116,18 @@
<string name="remove_label">Supprimer</string>
<string name="remove_episode_lable">Supprimer cet épisode</string>
<string name="mark_read_label">Marquer comme lu</string>
- <string name="mark_unread_label">Marquer comme non lu</string>
<string name="marked_as_read_label">Les épisodes ont été marqués comme lus</string>
+ <string name="mark_unread_label">Marquer comme non lu</string>
<string name="add_to_queue_label">Ajouter à la liste</string>
+ <string name="added_to_queue_label">Ajouté à la liste</string>
<string name="remove_from_queue_label">Supprimer de la liste</string>
<string name="visit_website_label">Visiter le site</string>
<string name="support_label">Flattr ça!</string>
<string name="enqueue_all_new">Ajouter tous à la liste</string>
<string name="download_all">Tous télécharger</string>
<string name="skip_episode_label">Passer cet épisode</string>
+ <string name="activate_auto_download">Activer téléchargement automatique</string>
+ <string name="deactivate_auto_download">Désactiver téléchargement automatique</string>
<!--Download messages and labels-->
<string name="download_successful">terminé</string>
<string name="download_failed">échoué</string>
@@ -114,6 +146,7 @@
<string name="cancel_all_downloads_label">Annuler tous les téléchargements</string>
<string name="download_canceled_msg">Téléchargement annulé</string>
<string name="download_report_title">Téléchargements terminés</string>
+ <string name="download_report_content_title">Rapport des téléchargements</string>
<string name="download_error_malformed_url">URL incorrecte</string>
<string name="download_error_io_error">Erreur d\'E/S</string>
<string name="download_error_request_error">Erreur de requête</string>
@@ -129,6 +162,9 @@
<string name="download_request_error_dialog_message_prefix">Une erreur s\'est produite durant le téléchargement du fichier :\u0020</string>
<string name="authentication_notification_title">Authentification requise</string>
<string name="authentication_notification_msg">La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe</string>
+ <string name="confirm_mobile_download_dialog_title">Confirmer téléchargement mobile</string>
+ <string name="confirm_mobile_download_dialog_only_add_to_queue">Rajouter à la liste</string>
+ <string name="confirm_mobile_download_dialog_enable_temporarily">Permettre temporairement</string>
<!--Mediaplayer messages-->
<string name="player_error_msg">Erreur !</string>
<string name="player_stopped_msg">Pas de lecture en cours</string>
@@ -143,6 +179,8 @@
<string name="playbackservice_notification_title">Lecture de podcast en cours</string>
<string name="unknown_media_key">AntennaPod - Touche média inconnue : %1$d</string>
<!--Queue operations-->
+ <string name="lock_queue">Bloquer la liste</string>
+ <string name="unlock_queue">Débloquer la liste</string>
<string name="clear_queue_label">Effacer la liste</string>
<string name="undo">Annuler</string>
<string name="removed_from_queue">Élément retiré</string>
@@ -200,10 +238,12 @@
<string name="pref_followQueue_sum">Après la fin d\'un épisode, passer au suivant</string>
<string name="pref_auto_delete_sum">Supprimer l\'épisode quand la lecture est finie</string>
<string name="pref_auto_delete_title">Supression automatique</string>
+ <string name="pref_smart_mark_as_played_sum">Marquer les épisodes comme lus même s\'il reste encore moins d\'un certain intervalle de temps</string>
+ <string name="pref_smart_mark_as_played_title">Marquer comme lu intelligent</string>
<string name="playback_pref">Lecture</string>
<string name="network_pref">Réseau</string>
- <string name="pref_autoUpdateIntervall_title">Intervalle de mise à jour</string>
- <string name="pref_autoUpdateIntervall_sum">Indiquer un intervalle de mise à jour automatique des flux, ou le désactiver</string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Désactiver</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Définir intervalle</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Ne télécharger les épisodes que par Wi-Fi</string>
<string name="pref_followQueue_title">Lecture continue</string>
<string name="pref_downloadMediaOnWifiOnly_title">Téléchargement en Wi-Fi</string>
@@ -223,6 +263,10 @@
<string name="pref_auto_flattr_sum">Configurer les paiements flattr automatiques</string>
<string name="user_interface_label">Interface utilisateur</string>
<string name="pref_set_theme_title">Choisir un thème</string>
+ <string name="pref_nav_drawer_feed_order_title">Définir ordre des abonnements</string>
+ <string name="pref_nav_drawer_feed_order_sum">Change l\'ordre de vos abonnements</string>
+ <string name="pref_nav_drawer_feed_counter_title">Définir compteur des abonnements</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Change l\'information affichée à côté du compteur des abonnements</string>
<string name="pref_set_theme_sum">Modifier l\'apparence d\'AntennaPod.</string>
<string name="pref_automatic_download_title">Téléchargement automatique</string>
<string name="pref_automatic_download_sum">Configurer le téléchargement automatique des épisodes.</string>
@@ -246,15 +290,22 @@
<string name="pref_gpodnet_setlogin_information_sum">Modifier les information de connexion pour votre compte gpodder.net</string>
<string name="pref_playback_speed_title">Vitesses de lecture</string>
<string name="pref_playback_speed_sum">Modifier la liste des vitesses disponibles pour la lecture audio</string>
+ <string name="pref_fast_forward">Avance rapide</string>
+ <string name="pref_rewind">Retour en arrière</string>
<string name="pref_gpodnet_sethostname_title">Choisir un nom de domaine</string>
<string name="pref_gpodnet_sethostname_use_default_host">Utiliser le nom de domaine par défaut</string>
<string name="pref_expandNotify_title">Etendre la notification</string>
<string name="pref_expandNotify_sum">Toujours étendre les notifications pour montrer les boutons de lecture</string>
<string name="pref_persistNotify_title">Boutons de lecture permanents</string>
<string name="pref_persistNotify_sum">Garder les notifications et les boutons de lecture sur l\'écran de verouillage quand la lecture est en pause</string>
+ <string name="pref_showDownloadReport_title">Afficher rapport des téléchargements</string>
+ <string name="pref_showDownloadReport_sum">Si les téléchargements échouent, générer un rapport des détails des échecs.</string>
<string name="pref_expand_notify_unsupport_toast">Les versions d\'Android antérieures à 4.1 ne sont pas compatibles avec les notifications élargies</string>
<string name="pref_queueAddToFront_sum">Ajouter de nouveaux épisodes en tête de file</string>
<string name="pref_queueAddToFront_title">Mettre au début de la file d\'attente</string>
+ <string name="pref_smart_mark_as_played_disabled">Désactivé</string>
+ <string name="pref_image_cache_size_title">Taille de la cache d\'image</string>
+ <string name="pref_image_cache_size_sum">Taille de l’espace disque pour stocker temporairement les images.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Activer le paiement flattr automatique</string>
<string name="auto_flattr_after_percent">Lancer un paiement flattr pour un épisode dès que %d de l\'épisode a été joué</string>
@@ -280,6 +331,7 @@
<string name="opml_import_error_dir_empty">Le répertoire d\'importation est vide.</string>
<string name="select_all_label">Tout choisir</string>
<string name="deselect_all_label">Ne rien choisir</string>
+ <string name="select_options_label">Sélectionner...</string>
<string name="choose_file_from_filesystem">Depuis le système de fichier local</string>
<string name="choose_file_from_external_application">Utiliser une application tierce</string>
<string name="opml_export_label">Exportation OPML</string>
@@ -294,9 +346,21 @@
<string name="sleep_timer_label">Arrêt automatique</string>
<string name="time_left_label">Durée restante :\u0020</string>
<string name="time_dialog_invalid_input">Entrée invalide, la durée doit être un nombre entier</string>
- <string name="time_unit_seconds">secondes</string>
- <string name="time_unit_minutes">minutes</string>
- <string name="time_unit_hours">heures</string>
+ <string name="time_seconds">secondes</string>
+ <string name="time_minutes">minutes</string>
+ <string name="time_hours">heures</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 seconde</item>
+ <item quantity="other">%d secondes</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minute</item>
+ <item quantity="other">%d minutes</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 heure</item>
+ <item quantity="other">%d heures</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">CATEGORIES</string>
<string name="gpodnet_toplist_header">PODCASTS POPULAIRES</string>
@@ -339,6 +403,9 @@
<string name="set_to_default_folder">Choisir le répertoire par défaut</string>
<string name="pref_pausePlaybackForFocusLoss_sum">Mettre la lecture en pause au lieu de baisser le volume quand une autre application veut jouer un son</string>
<string name="pref_pausePlaybackForFocusLoss_title">Mettre en pause lors des interruptions</string>
+ <string name="pref_resumeAfterCall_sum">Reprendre la lecture après un appel téléphonique</string>
+ <string name="pref_resumeAfterCall_title">Reprendre après appel</string>
+ <string name="pref_restart_required">AntennaPod doit être redémarré afin que ce changement prenne effet</string>
<!--Online feed view-->
<string name="subscribe_label">S\'abonner</string>
<string name="subscribed_label">Abonné</string>
@@ -365,7 +432,29 @@
<!--Feed information screen-->
<string name="authentication_label">Authentification</string>
<string name="authentication_descr">Modifier votre identifiant et mot de passe pour ce podcast et tous ses épisodes</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">Mise à jour de la base de données</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importation des abonnements à partir d\'applications à usage unique...</string>
<string name="search_itunes_label">Chercher sur iTunes</string>
+ <string name="select_label"><b>Sélectionner ...</b></string>
+ <string name="all_label">Tout</string>
+ <string name="selected_all_label">Sélectionné tous les épisodes</string>
+ <string name="none_label">Aucun</string>
+ <string name="deselected_all_label">Désélectionné tous les épisodes</string>
+ <string name="played_label">Joués</string>
+ <string name="selected_played_label">Sélectionné tous les épisodes joués</string>
+ <string name="unplayed_label">Non joués</string>
+ <string name="selected_unplayed_label">Sélectionné tous les épisodes non joués</string>
+ <string name="downloaded_label">Téléchargés</string>
+ <string name="selected_downloaded_label">Sélectionné tous les épisodes téléchargés</string>
+ <string name="not_downloaded_label">Non téléchargés</string>
+ <string name="selected_not_downloaded_label">Sélectionné tous les épisodes non téléchargés</string>
+ <string name="sort_title"><b>Trier par ...</b></string>
+ <string name="sort_title_a_z">Titre (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Titre (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Date (Nouveau \u2192 Ancien)</string>
+ <string name="sort_date_old_new">Date (Ancien \u2192 Nouveau)</string>
+ <string name="sort_duration_short_long">Durée (Courte \u2192 Longue)</string>
+ <string name="sort_duration_long_short">Durée (Longue \u2192 Courte)</string>
</resources>
diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml
index f32c7c02f..13ef6d489 100644
--- a/core/src/main/res/values-hi-rIN/strings.xml
+++ b/core/src/main/res/values-hi-rIN/strings.xml
@@ -57,7 +57,6 @@
<string name="remove_feed_label">पॉडकास्ट हटाएँ
</string>
<string name="share_link_label">शेयर वेबसाइट लिंक</string>
- <string name="share_source_label">शेयर फ़ीड लिंक</string>
<string name="feed_delete_confirmation_msg">इसकी पुष्टि करें कि आप इस फ़ीड और इस फ़ीड के सभी प्रकरणों को हटाना चाहते हैं जिन्हें आपने डाउनलोड किया है.</string>
<string name="feed_remover_msg">फ़ीड निकाल रहा है</string>
<!--actions on feeditems-->
@@ -158,8 +157,6 @@
<string name="pref_followQueue_sum">प्लेबैक के पूरा होने पर अगली पंक्ति आइटम के लिए जाएँ</string>
<string name="playback_pref">प्लेबैक</string>
<string name="network_pref">संजाल</string>
- <string name="pref_autoUpdateIntervall_title">अंतराल अद्यतन</string>
- <string name="pref_autoUpdateIntervall_sum">फ़ीड स्वचालित रूप से ताजा कर रहे हैं जिसमें एक अंतराल निर्दिष्ट करें या उसे निष्क्रिय करें </string>
<string name="pref_downloadMediaOnWifiOnly_sum">केवल वाईफ़ाई पर मीडिया फ़ाइलें डाउनलोड करें</string>
<string name="pref_followQueue_title">सतत प्लेबैक</string>
<string name="pref_downloadMediaOnWifiOnly_title">वाईफाई मीडिया डाउनलोड करें</string>
@@ -274,5 +271,6 @@
<string name="downloading_label">डाउनलोड कर रहा है ...</string>
<!--Content descriptions for image buttons-->
<!--Feed information screen-->
+ <!--Progress information-->
<!--AntennaPodSP-->
</resources>
diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml
index b81e3f2ce..a7ddf81d3 100644
--- a/core/src/main/res/values-it-rIT/strings.xml
+++ b/core/src/main/res/values-it-rIT/strings.xml
@@ -26,6 +26,11 @@
<!--Main activity-->
<string name="drawer_open">Apri il menù</string>
<string name="drawer_close">Chiudi il menù</string>
+ <string name="drawer_feed_order_alphabetical">Ordina alfabeticamente</string>
+ <string name="drawer_feed_counter_new_unplayed">Numero di episodi nuovi e non riprodotti</string>
+ <string name="drawer_feed_counter_new">Numero di episodi nuovi</string>
+ <string name="drawer_feed_counter_unplayed">Numero di episodi non riprodotti</string>
+ <string name="drawer_feed_counter_none">Nessuno</string>
<!--Webview actions-->
<string name="open_in_browser_label">Apri nel browser</string>
<string name="copy_url_label">Copia URL</string>
@@ -37,6 +42,8 @@
<!--Other-->
<string name="confirm_label">Conferma</string>
<string name="cancel_label">Annulla</string>
+ <string name="yes">Sì</string>
+ <string name="no">No</string>
<string name="author_label">Autore</string>
<string name="language_label">Lingua</string>
<string name="url_label">URL</string>
@@ -59,7 +66,11 @@
<string name="close_label">Chiudi</string>
<string name="retry_label">Riprova</string>
<string name="auto_download_label">Includi nei download automatici</string>
+ <string name="auto_download_apply_to_items_title">Applica ai Precedenti Episodi</string>
<string name="parallel_downloads_suffix">\u0020download paralleli</string>
+ <string name="feed_auto_download_global">Globale</string>
+ <string name="feed_auto_download_always">Sempre</string>
+ <string name="feed_auto_download_never">Mai</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL del feed</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
@@ -70,10 +81,13 @@
<!--Actions on feeds-->
<string name="mark_all_read_label">Segna tutti come riprodotti</string>
<string name="mark_all_read_msg">Segnati tutti gli episodi come riprodotti</string>
+ <string name="mark_all_seen_label">Segna tutti come visti</string>
<string name="show_info_label">Informazioni</string>
<string name="remove_feed_label">Rimuovi un podcast</string>
+ <string name="share_label">Condividi...</string>
<string name="share_link_label">Condividi il link al sito</string>
- <string name="share_source_label">Condividi il link al feed</string>
+ <string name="share_feed_url_label">Condividi URL del Feed</string>
+ <string name="share_item_url_label">Condividi URL dell\'Episodio</string>
<string name="feed_delete_confirmation_msg">Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati.</string>
<string name="feed_remover_msg">Rimozione feed</string>
<string name="load_complete_feed">Ricarica il feed completo</string>
@@ -96,8 +110,8 @@
<string name="remove_label">Rimuovi</string>
<string name="remove_episode_lable">Rimuovi l\'episodio</string>
<string name="mark_read_label">Segna come riprodotto</string>
- <string name="mark_unread_label">Segna come non riprodotto</string>
<string name="marked_as_read_label">Segnato come riprodotto</string>
+ <string name="mark_unread_label">Segna come non riprodotto</string>
<string name="add_to_queue_label">Aggiungi alla coda</string>
<string name="added_to_queue_label">Aggiunto alla coda</string>
<string name="remove_from_queue_label">Rimuovi dalla coda</string>
@@ -126,6 +140,7 @@
<string name="download_error_unauthorized">Errore di autenticazione</string>
<string name="cancel_all_downloads_label">Annulla tutti i download</string>
<string name="download_canceled_msg">Download annullato</string>
+ <string name="download_report_title">Download completato con un errore (o errori)</string>
<string name="download_report_content_title">Rapporto del downoad</string>
<string name="download_error_malformed_url">URL malformato</string>
<string name="download_error_io_error">Errore IO</string>
@@ -219,8 +234,7 @@
<string name="pref_auto_delete_title">Elimina automaticamente</string>
<string name="playback_pref">Riproduzione</string>
<string name="network_pref">Rete</string>
- <string name="pref_autoUpdateIntervall_title">Intervallo di update</string>
- <string name="pref_autoUpdateIntervall_sum">Specifica un intervallo per l\'aggiornamento automatico dei feed o disabilitalo</string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Disabilita</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Abilita il download dei media solo tramite WiFi</string>
<string name="pref_followQueue_title">Playback continuo</string>
<string name="pref_downloadMediaOnWifiOnly_title">Download dei media su WiFi</string>
@@ -269,6 +283,7 @@
<string name="pref_expandNotify_sum">Espandi sempre le notifiche per mostrare i pulsanti di riproduzione.</string>
<string name="pref_persistNotify_title">Controlli di riproduzione persistenti</string>
<string name="pref_persistNotify_sum">Mantieni le notifiche e i controlli del blocco dello schermo quando la riproduzione è in pausa.</string>
+ <string name="pref_showDownloadReport_title">Mostra il Rapporto del Download</string>
<string name="pref_expand_notify_unsupport_toast">Le versioni di Android prima della 4.1 non supportano le notifiche estese.</string>
<string name="pref_smart_mark_as_played_disabled">Disabilitato</string>
<!--Auto-Flattr dialog-->
@@ -307,9 +322,21 @@
<string name="sleep_timer_label">Timer di spegnimento</string>
<string name="time_left_label">Tempo residuo:\u0020</string>
<string name="time_dialog_invalid_input">Input non valido, il campo deve essere un numero intero.</string>
- <string name="time_unit_seconds">secondi</string>
- <string name="time_unit_minutes">minuti</string>
- <string name="time_unit_hours">ore</string>
+ <string name="time_seconds">secondi</string>
+ <string name="time_minutes">minuti</string>
+ <string name="time_hours">ore</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 secondo</item>
+ <item quantity="other">%d secondi</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minuto</item>
+ <item quantity="other">%d minuti</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 ora</item>
+ <item quantity="other">%d ore</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">CATEGORIE</string>
<string name="gpodnet_toplist_header">TOP PODCAST</string>
@@ -379,7 +406,21 @@
<!--Feed information screen-->
<string name="authentication_label">Autenticazione</string>
<string name="authentication_descr">Cambia il tuo nome utente e la tua password per questo podcast e i suoi episodi.</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importazione di sottoscrizioni da applicazioni monouso in corso...</string>
<string name="search_itunes_label">Cerca su iTunes</string>
+ <string name="select_label"><b>Seleziona ...</b></string>
+ <string name="all_label">Tutti</string>
+ <string name="selected_all_label">Tutti gli Episodi Selezionati</string>
+ <string name="none_label">Nessuno</string>
+ <string name="deselected_all_label">Tutti gli Episodi Deselezionati</string>
+ <string name="played_label">Riprodotto</string>
+ <string name="unplayed_label">Non riprodotto</string>
+ <string name="sort_title_a_z">Titolo (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Titolo (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Data (New \u2192 Old)</string>
+ <string name="sort_date_old_new">Data (Old \u2192 New)</string>
+ <string name="sort_duration_short_long">Durata (Short \u2192 Long)</string>
+ <string name="sort_duration_long_short">Durata (Long \u2192 Short)</string>
</resources>
diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml
index 9e9c0e6bc..07f3602ff 100644
--- a/core/src/main/res/values-iw-rIL/strings.xml
+++ b/core/src/main/res/values-iw-rIL/strings.xml
@@ -58,7 +58,11 @@
<string name="close_label">סגור</string>
<string name="retry_label">נסה שוב</string>
<string name="auto_download_label">כלול בהורדות אוטומטיות</string>
+ <string name="auto_delete_label">מחק לאחר ההשמעה\n(גובר על ההגדרה הגלובלית)</string>
<string name="parallel_downloads_suffix">\u0020הורדות במקביל</string>
+ <string name="feed_auto_download_global">לפי הגדרה גלובלית</string>
+ <string name="feed_auto_download_always">תמיד</string>
+ <string name="feed_auto_download_never">אף פעם</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">כתובת הזנה</string>
<string name="etxtFeedurlHint">כתובת של הזנה או אתר אינטרנט</string>
@@ -74,7 +78,6 @@
<string name="show_info_label">הצג מידע</string>
<string name="remove_feed_label">הסר פודקאסט</string>
<string name="share_link_label">שתף קישור אתר</string>
- <string name="share_source_label">שתף קישור הזנה</string>
<string name="feed_delete_confirmation_msg">אשר מחיקת הזנה זו ואת כל פרקי ההזנה שהורדת.</string>
<string name="feed_remover_msg">הסר הזנה</string>
<string name="load_complete_feed">רענן את כל ההזנה</string>
@@ -87,8 +90,8 @@
<string name="remove_label">הסר</string>
<string name="remove_episode_lable">הסר פרק</string>
<string name="mark_read_label">סמן כנקרא</string>
- <string name="mark_unread_label">סמן כלא נקרא</string>
<string name="marked_as_read_label">סומן כנקרא</string>
+ <string name="mark_unread_label">סמן כלא נקרא</string>
<string name="add_to_queue_label">הוסף לתור</string>
<string name="remove_from_queue_label">הסר מהתור</string>
<string name="visit_website_label">בקר באתר</string>
@@ -203,8 +206,6 @@
<string name="pref_auto_delete_title">מחיקה אוטומטית</string>
<string name="playback_pref">ניגון</string>
<string name="network_pref">רשת</string>
- <string name="pref_autoUpdateIntervall_title">זמן בין עידכונים</string>
- <string name="pref_autoUpdateIntervall_sum">ציין פרק זמן שבו ההזנות עוברות רענון באופן אוטומטי או לבטל ריענון</string>
<string name="pref_downloadMediaOnWifiOnly_sum">הורד קבצי מדיה רק דרך חיבור אינטרנט אלחוטי</string>
<string name="pref_followQueue_title">ניגון מתמשך</string>
<string name="pref_downloadMediaOnWifiOnly_title">הורדת מדיה דרך אינטרנט אלחוטי</string>
@@ -247,8 +248,6 @@
<string name="pref_gpodnet_setlogin_information_sum">שנה פרטי התחברות של חשבון gpodder.net.</string>
<string name="pref_playback_speed_title">מהירויות ניגון</string>
<string name="pref_playback_speed_sum">התאמת המהיריות הזמינות לניגון במהירות משתנה</string>
- <string name="pref_seek_delta_title">זמן דילוג</string>
- <string name="pref_seek_delta_sum">דלג מספר שניות זה בדילוג לאחור או קדימה</string>
<string name="pref_gpodnet_sethostname_title">הגדר שם שרת</string>
<string name="pref_gpodnet_sethostname_use_default_host">השתמש בשרת ברירת מידל</string>
<string name="pref_expandNotify_title">הרחב הודעה</string>
@@ -297,9 +296,6 @@
<string name="sleep_timer_label">טיימר שינה</string>
<string name="time_left_label">זמן נותר:\u0020</string>
<string name="time_dialog_invalid_input">קלט לא חוקי, זמן חייב להיות מספר שלם</string>
- <string name="time_unit_seconds">שניות</string>
- <string name="time_unit_minutes">דקות</string>
- <string name="time_unit_hours">שעות</string>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">קטגוריות</string>
<string name="gpodnet_toplist_header">פודקאסטים בכירים</string>
@@ -368,6 +364,7 @@
<!--Feed information screen-->
<string name="authentication_label">אימות</string>
<string name="authentication_descr">שנה את שם המשתמש והסיסמה שלך לפודקאסט ופרקים שלו.</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">מייבא רישום מאפליקציות יעודיות...</string>
<string name="search_itunes_label">חפש בiTunes</string>
diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml
index 79411ffc1..3a9e58d9a 100644
--- a/core/src/main/res/values-ja/strings.xml
+++ b/core/src/main/res/values-ja/strings.xml
@@ -27,6 +27,12 @@
<string name="drawer_open">メニューを開く</string>
<string name="drawer_close">メニューを閉じる</string>
<string name="drawer_preferences">ドロワー設定</string>
+ <string name="drawer_feed_order_unplayed_episodes">カウンターで並び替え</string>
+ <string name="drawer_feed_order_alphabetical">アルファベット順に並び替え</string>
+ <string name="drawer_feed_counter_new_unplayed">新しい未再生のエピソードの数</string>
+ <string name="drawer_feed_counter_new">新しいエピソードの数</string>
+ <string name="drawer_feed_counter_unplayed">未再生のエピソードの数</string>
+ <string name="drawer_feed_counter_none">なし</string>
<!--Webview actions-->
<string name="open_in_browser_label">ブラウザーで開く</string>
<string name="copy_url_label">URLをコピー</string>
@@ -38,6 +44,8 @@
<!--Other-->
<string name="confirm_label">確認</string>
<string name="cancel_label">キャンセル</string>
+ <string name="yes">はい</string>
+ <string name="no">いいえ</string>
<string name="author_label">作者</string>
<string name="language_label">言語</string>
<string name="url_label">URL</string>
@@ -60,7 +68,13 @@
<string name="close_label">閉じる</string>
<string name="retry_label">再試行</string>
<string name="auto_download_label">自動ダウンロードに含む</string>
+ <string name="auto_download_apply_to_items_title">前のエピソードに適用</string>
+ <string name="auto_download_apply_to_items_message">新しい <i>自動ダウンロード</i> の設定は、新しいエピソードに自動的に適用されます。\n前のエピソードにも適用しますか?</string>
+ <string name="auto_delete_label">エピソードの自動削除\n(全般のデフォルトを上書きします)</string>
<string name="parallel_downloads_suffix">\u0020パラレル ダウンロード</string>
+ <string name="feed_auto_download_global">全般</string>
+ <string name="feed_auto_download_always">常に</string>
+ <string name="feed_auto_download_never">しない</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">フィードURL</string>
<string name="etxtFeedurlHint">フィードまたはWebサイトのURL</string>
@@ -73,14 +87,20 @@
<string name="mark_all_read_msg">すべてのエピソードを再生済にしました</string>
<string name="mark_all_read_confirmation_msg">再生済としてマークするすべてのエピソードを確認してください。</string>
<string name="mark_all_read_feed_confirmation_msg">再生済としてマークするこのフィードのすべてのエピソードを確認してください。</string>
+ <string name="mark_all_seen_label">参照済としてマーク</string>
<string name="show_info_label">情報を表示</string>
<string name="remove_feed_label">ポッドキャストを削除</string>
+ <string name="share_label">共有...</string>
<string name="share_link_label">Webサイトのリンクを共有</string>
- <string name="share_source_label">フィードのリンクを共有</string>
+ <string name="share_link_with_position_label">場所とリンクを共有</string>
+ <string name="share_feed_url_label">フィード URLを共有</string>
+ <string name="share_item_url_label">エピソード URLを共有</string>
+ <string name="share_item_url_with_position_label">場所とエピソード URL を共有</string>
<string name="feed_delete_confirmation_msg">このフィードと、このフィードのダウンロードしたすべてのエピソードを削除することを確認してください。</string>
<string name="feed_remover_msg">フィードの削除中</string>
<string name="load_complete_feed">フィードをすべて更新</string>
<string name="hide_episodes_title">エピソードを非表示にする</string>
+ <string name="episode_actions">操作を適用</string>
<string name="hide_unplayed_episodes_label">未再生</string>
<string name="hide_paused_episodes_label">一時停止しました</string>
<string name="hide_played_episodes_label">再生しました</string>
@@ -99,8 +119,8 @@
<string name="remove_label">削除</string>
<string name="remove_episode_lable">エピソードを削除</string>
<string name="mark_read_label">再生済としてマーク</string>
- <string name="mark_unread_label">未再生としてマーク</string>
<string name="marked_as_read_label">再生済としてマークしました</string>
+ <string name="mark_unread_label">未再生としてマーク</string>
<string name="add_to_queue_label">キューに追加</string>
<string name="added_to_queue_label">キューに追加しました</string>
<string name="remove_from_queue_label">キューから削除</string>
@@ -229,8 +249,12 @@
<string name="pref_smart_mark_as_played_title">再生済としてスマートマーク</string>
<string name="playback_pref">再生</string>
<string name="network_pref">ネットワーク</string>
- <string name="pref_autoUpdateIntervall_title">更新間隔</string>
- <string name="pref_autoUpdateIntervall_sum">フィードが自動的に更新される間隔を指定するか、または無効にしてください</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">間隔または時間を更新</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">自動的にフィードを更新する間隔または時間を指定してください</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">\"2 時間ごと\" のような <i>間隔</i> 、\"7:00 AM\" のような特定の <i>時間</i> 、または自動更新を完全に <i>無効</i> にセットすることができます。\n\n<small>ご注意ください: 更新時間は正確ではありません。少し遅延が発生する可能性があります。</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">無効</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">間隔をセット</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">時間をセット</string>
<string name="pref_downloadMediaOnWifiOnly_sum">WiFi接続時のみメディアファイルをダウンロードします</string>
<string name="pref_followQueue_title">連続再生</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFiメディアダウンロード</string>
@@ -250,8 +274,14 @@
<string name="pref_auto_flattr_sum">自動Flattrを構成</string>
<string name="user_interface_label">インターフェース</string>
<string name="pref_set_theme_title">テーマを選択</string>
+ <string name="pref_nav_drawer_title">ナビゲーションドロワーをカスタマイズ</string>
+ <string name="pref_nav_drawer_sum">ナビゲーションドロワーの外観をカスタマイズします。</string>
<string name="pref_nav_drawer_items_title">ナビゲーションドロワーを変更</string>
<string name="pref_nav_drawer_items_sum">ナビゲーションドロワーに表示するアイテムを変更します。</string>
+ <string name="pref_nav_drawer_feed_order_title">購読注文をセット</string>
+ <string name="pref_nav_drawer_feed_order_sum">購読の注文を変更します</string>
+ <string name="pref_nav_drawer_feed_counter_title">購読カウンターをセット</string>
+ <string name="pref_nav_drawer_feed_counter_sum">購読カウンターで表示される情報を変更します</string>
<string name="pref_set_theme_sum">AntennaPodの外観を変更します。</string>
<string name="pref_automatic_download_title">自動ダウンロード</string>
<string name="pref_automatic_download_sum">エピソードの自動ダウンロードを構成します。</string>
@@ -283,10 +313,14 @@
<string name="pref_expandNotify_sum">常に再生ボタンを表示するように通知を展開します。</string>
<string name="pref_persistNotify_title">永続再生コントロール</string>
<string name="pref_persistNotify_sum">再生が一時停止された時に、通知およびロック画面のコントロールを保持します。</string>
+ <string name="pref_showDownloadReport_title">ダウンロード レポートを表示</string>
+ <string name="pref_showDownloadReport_sum">ダウンロードが失敗した場合、失敗の詳細を表示するレポートを生成します。</string>
<string name="pref_expand_notify_unsupport_toast">Androidバージョン4.1以前では、拡張通知をサポートしていません。</string>
<string name="pref_queueAddToFront_sum">新しいエピソードをキューの先頭に追加します。</string>
<string name="pref_queueAddToFront_title">キューの先頭に入れる</string>
<string name="pref_smart_mark_as_played_disabled">無効</string>
+ <string name="pref_image_cache_size_title">画像キャッシュサイズ</string>
+ <string name="pref_image_cache_size_sum">画像のディスクキャッシュのサイズ。</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">自動Flattrを有効にする</string>
<string name="auto_flattr_after_percent">%d %再生したらエピソードをFlattr </string>
@@ -312,6 +346,7 @@
<string name="opml_import_error_dir_empty">インポートディレクトリが空です。</string>
<string name="select_all_label">すべてを選択</string>
<string name="deselect_all_label">選択解除</string>
+ <string name="select_options_label">選択 ...</string>
<string name="choose_file_from_filesystem">ローカル ファイルシステムから</string>
<string name="choose_file_from_external_application">外部アプリケーションを使用する</string>
<string name="opml_export_label">OPMLエクスポート</string>
@@ -326,9 +361,18 @@
<string name="sleep_timer_label">スリープタイマー</string>
<string name="time_left_label">残り時間:\u0020</string>
<string name="time_dialog_invalid_input">入力が正しくありません、時間は数字で入力してください</string>
- <string name="time_unit_seconds">秒</string>
- <string name="time_unit_minutes">分</string>
- <string name="time_unit_hours">時</string>
+ <string name="time_seconds">秒</string>
+ <string name="time_minutes">分</string>
+ <string name="time_hours">時間</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="other">%d 秒</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="other">%d 分</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="other">%d 時間</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">カテゴリー</string>
<string name="gpodnet_toplist_header">トップ ボッドキャスト</string>
@@ -373,6 +417,7 @@
<string name="pref_pausePlaybackForFocusLoss_title">割り込み時に一時停止</string>
<string name="pref_resumeAfterCall_sum">着信が完了した後に再生を再開します</string>
<string name="pref_resumeAfterCall_title">着信後に再開</string>
+ <string name="pref_restart_required">この変更を有効にするには AntennaPod を再起動する必要があります。</string>
<!--Online feed view-->
<string name="subscribe_label">購読</string>
<string name="subscribed_label">購読しました</string>
@@ -399,7 +444,29 @@
<!--Feed information screen-->
<string name="authentication_label">認証</string>
<string name="authentication_descr">このポッドキャストとそのエピソード用のあなたのユーザー名とパスワードを変更します。</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">データベースをアップグレードしています</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">単一目的のアプリから購読をインポート中…</string>
<string name="search_itunes_label">iTunes を検索</string>
+ <string name="select_label"><b>選択 ...</b></string>
+ <string name="all_label">すべて</string>
+ <string name="selected_all_label">すべてのエピソードを選択しました</string>
+ <string name="none_label">なし</string>
+ <string name="deselected_all_label">すべてのエピソードの選択を解除しました</string>
+ <string name="played_label">再生しました</string>
+ <string name="selected_played_label">再生済のエピソードを選択しました</string>
+ <string name="unplayed_label">未再生</string>
+ <string name="selected_unplayed_label">未再生のエピソードを選択しました</string>
+ <string name="downloaded_label">ダウンロードしました</string>
+ <string name="selected_downloaded_label">ダウンロード済のエピソードを選択しました</string>
+ <string name="not_downloaded_label">ダウンロードしていません</string>
+ <string name="selected_not_downloaded_label">ダウンロードしていないエピソードを選択しました</string>
+ <string name="sort_title"><b>並び替え順 ...</b></string>
+ <string name="sort_title_a_z">タイトル (A \u2192 Z)</string>
+ <string name="sort_title_z_a">タイトル (Z \u2192 A)</string>
+ <string name="sort_date_new_old">日付 (新 \u2192 旧)</string>
+ <string name="sort_date_old_new">日付 (旧 \u2192 新)</string>
+ <string name="sort_duration_short_long">期間 (短 \u2192 長)</string>
+ <string name="sort_duration_long_short">期間 (長 \u2192 短)</string>
</resources>
diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml
index 148010050..7c9f76fcf 100644
--- a/core/src/main/res/values-ko/strings.xml
+++ b/core/src/main/res/values-ko/strings.xml
@@ -27,6 +27,12 @@
<string name="drawer_open">메뉴 열기</string>
<string name="drawer_close">메뉴 닫기</string>
<string name="drawer_preferences">드로어 기본 설정</string>
+ <string name="drawer_feed_order_unplayed_episodes">카운터로 정렬</string>
+ <string name="drawer_feed_order_alphabetical">사전 순서로 정렬</string>
+ <string name="drawer_feed_counter_new_unplayed">새로운 에피소드와 재생하지 않은 에피소드 수</string>
+ <string name="drawer_feed_counter_new">새로운 에피소드 수</string>
+ <string name="drawer_feed_counter_unplayed">재생하지 않은 에피소드 수</string>
+ <string name="drawer_feed_counter_none">없음</string>
<!--Webview actions-->
<string name="open_in_browser_label">브라우저에서 열기</string>
<string name="copy_url_label">URL 복사</string>
@@ -38,6 +44,8 @@
<!--Other-->
<string name="confirm_label">확인</string>
<string name="cancel_label">취소</string>
+ <string name="yes">예</string>
+ <string name="no">아니요</string>
<string name="author_label">저자</string>
<string name="language_label">언어</string>
<string name="url_label">URL</string>
@@ -60,7 +68,13 @@
<string name="close_label">닫기</string>
<string name="retry_label">다시 시도</string>
<string name="auto_download_label">자동 다운로드에 포함</string>
+ <string name="auto_download_apply_to_items_title">예전 에피소드에 적용</string>
+ <string name="auto_download_apply_to_items_message">새로운 &lt;i&gt;자동 다운로드&lt;/I&gt; 설정은 자동으로 새로운 에피소드에 적용됩니다. 예전 에피소드에도 적용하시겠습니까?</string>
+ <string name="auto_delete_label">에피소드 자동 삭제\n(전체 설정보다 우선)</string>
<string name="parallel_downloads_suffix">\u0020동시 다운로드</string>
+ <string name="feed_auto_download_global">전체 설정</string>
+ <string name="feed_auto_download_always">항상</string>
+ <string name="feed_auto_download_never">안 함</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">피드 URL</string>
<string name="etxtFeedurlHint">피드의 URL 또는 홈페이지</string>
@@ -73,14 +87,20 @@
<string name="mark_all_read_msg">모든 에피소드를 재생했다고 표시했습니다</string>
<string name="mark_all_read_confirmation_msg">모든 에피소드를 재생했다고 표시할지 확인하십시오.</string>
<string name="mark_all_read_feed_confirmation_msg">이 피드에 들어 있는 모든 에피소드를 재생했다고 표시할지 확인하십시오.</string>
+ <string name="mark_all_seen_label">모두 봤다고 표시</string>
<string name="show_info_label">정보 표시</string>
<string name="remove_feed_label">팟캐스트 제거</string>
+ <string name="share_label">공유...</string>
<string name="share_link_label">홈페이지 링크 공유</string>
- <string name="share_source_label">피드 링크 공유</string>
+ <string name="share_link_with_position_label">위치와 같이 링크 공유</string>
+ <string name="share_feed_url_label">피드 URL 공유</string>
+ <string name="share_item_url_label">에피소드 URL 공유</string>
+ <string name="share_item_url_with_position_label">위치와 같이 에피소드 URL 공유</string>
<string name="feed_delete_confirmation_msg">이 피드와 이 피드에서 다운로드한 모든 에피소드를 삭제하시려면 확인을 누르십시오.</string>
<string name="feed_remover_msg">피드 삭제하는 중</string>
<string name="load_complete_feed">전체 피드 새로고침</string>
<string name="hide_episodes_title">에피소드 감추기</string>
+ <string name="episode_actions">동작 적용</string>
<string name="hide_unplayed_episodes_label">재생 안 함</string>
<string name="hide_paused_episodes_label">일시 중지</string>
<string name="hide_played_episodes_label">재생함</string>
@@ -99,8 +119,8 @@
<string name="remove_label">제거</string>
<string name="remove_episode_lable">에피소드 제거</string>
<string name="mark_read_label">재생했다고 표시</string>
- <string name="mark_unread_label">재생하지 않음으로 표시</string>
<string name="marked_as_read_label">재생했다고 표시함</string>
+ <string name="mark_unread_label">재생하지 않음으로 표시</string>
<string name="add_to_queue_label">대기열에 추가</string>
<string name="added_to_queue_label">대기열에 추가함</string>
<string name="remove_from_queue_label">대기열에서 제거</string>
@@ -229,8 +249,12 @@
<string name="pref_smart_mark_as_played_title">똑똑하게 재생한 것으로 표시</string>
<string name="playback_pref">재생</string>
<string name="network_pref">네트워크</string>
- <string name="pref_autoUpdateIntervall_title">업데이트 주기</string>
- <string name="pref_autoUpdateIntervall_sum">피드를 새로 고칠 주기를 지정하거나 새로 고침을 하지 않음</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">업데이트 주기 또는 하루 중 시각</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">피드를 자동으로 새로 고칠 주기 또는 하루 중 특정 시각을 지정하십시오</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">\"매 2시간\"과 같이 <i>주기</i>를 지정할 수도 있고, \"오전 7:00\"와 같이 <i>하루 중 시각</i>을 지정할 수도 있고, 자동 업데이트를 모두 <i>사용 안 할</i> 수도 있습니다.\n\n<small>안내: 업데이트 시간은 정확하지 않습니다. 약간 늦게 업데이트할 수 있습니다.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">사용 안 함</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">주기 지정</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">하루 중 시각 지정</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Wi-Fi를 통해서만 미디어 파일 다운로드</string>
<string name="pref_followQueue_title">연속 재생</string>
<string name="pref_downloadMediaOnWifiOnly_title">Wi-Fi 미디어 다운로드</string>
@@ -250,8 +274,14 @@
<string name="pref_auto_flattr_sum">자동 flattr 설정</string>
<string name="user_interface_label">사용자 인터페이스</string>
<string name="pref_set_theme_title">테마 선택</string>
+ <string name="pref_nav_drawer_title">네비게이션 드로어 사용자 설정</string>
+ <string name="pref_nav_drawer_sum">네비게이션 드로어의 모양을 사용자 설정합니다.</string>
<string name="pref_nav_drawer_items_title">네비게이션 드로어 바꾸기</string>
<string name="pref_nav_drawer_items_sum">네비게이션 드로어에 어떤 항목을 표시할지 바꿉니다.</string>
+ <string name="pref_nav_drawer_feed_order_title">구독 순서 설정</string>
+ <string name="pref_nav_drawer_feed_order_sum">구독 순서를 바꿉니다</string>
+ <string name="pref_nav_drawer_feed_counter_title">구독 카운터 설정</string>
+ <string name="pref_nav_drawer_feed_counter_sum">구독 카운터에 따라 표시되는 정보를 바꿉니다</string>
<string name="pref_set_theme_sum">안테나팟의 겉모양을 바꿉니다.</string>
<string name="pref_automatic_download_title">자동 다운로드</string>
<string name="pref_automatic_download_sum">에피소드 자동 다운로드를 설정합니다.</string>
@@ -283,10 +313,14 @@
<string name="pref_expandNotify_sum">항상 알림에서 재생 버튼이 표시되도록 확장</string>
<string name="pref_persistNotify_title">재생 조작 고정</string>
<string name="pref_persistNotify_sum">재생이 일시 중지했을 때에도 알림과 잠금 화면의 조작 기능 유지</string>
+ <string name="pref_showDownloadReport_title">다운로드 보고서 보기</string>
+ <string name="pref_showDownloadReport_sum">다운로드가 실패하면, 실패를 자세히 표시하는 보고서를 만듭니다.</string>
<string name="pref_expand_notify_unsupport_toast">안드로이드 4.1 전 버전에서는 알림 확장을 지원하지 않습니다.</string>
<string name="pref_queueAddToFront_sum">새 에피소드를 대기열 앞에 추가합니다.</string>
<string name="pref_queueAddToFront_title">대기열 앞에 추가</string>
<string name="pref_smart_mark_as_played_disabled">사용 안 함</string>
+ <string name="pref_image_cache_size_title">이미지 캐시 크기</string>
+ <string name="pref_image_cache_size_sum">이미지에 사용할 디스크 캐시 크기</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">자동 flattr 사용</string>
<string name="auto_flattr_after_percent">%d 퍼센트를 재생하면 에피소드에 flattr합니다</string>
@@ -312,6 +346,7 @@
<string name="opml_import_error_dir_empty">가져오기 디렉터리가 비어 있습니다.</string>
<string name="select_all_label">모두 선택</string>
<string name="deselect_all_label">모두 선택 해제</string>
+ <string name="select_options_label">선택...</string>
<string name="choose_file_from_filesystem">로컬 파일시스템에서</string>
<string name="choose_file_from_external_application">외부 앱 사용</string>
<string name="opml_export_label">OPML 내보내기</string>
@@ -326,9 +361,18 @@
<string name="sleep_timer_label">취침 타이머</string>
<string name="time_left_label">남은 시간:\u0020</string>
<string name="time_dialog_invalid_input">입력이 잘못되었습니다. 시간으로 숫자를 입력해야 합니다.</string>
- <string name="time_unit_seconds">초</string>
- <string name="time_unit_minutes">분</string>
- <string name="time_unit_hours">시간</string>
+ <string name="time_seconds">초</string>
+ <string name="time_minutes">분</string>
+ <string name="time_hours">시간</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="other">%d초</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="other">%d분</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="other">%d시간</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">분류</string>
<string name="gpodnet_toplist_header">상위 팟캐스트</string>
@@ -373,6 +417,7 @@
<string name="pref_pausePlaybackForFocusLoss_title">끼어들면 일시 중지</string>
<string name="pref_resumeAfterCall_sum">전화 통화가 끝난 후에 재생 다시 시작</string>
<string name="pref_resumeAfterCall_title">통화 후에 다시 시작</string>
+ <string name="pref_restart_required">이 변경 사항을 적용하려면 안테나팟을 다시 시작해야 합니다.</string>
<!--Online feed view-->
<string name="subscribe_label">구독</string>
<string name="subscribed_label">구독함</string>
@@ -399,7 +444,29 @@
<!--Feed information screen-->
<string name="authentication_label">인증</string>
<string name="authentication_descr">이 팟캐스트와 에피소드에 대한 사용자 이름과 비밀번호를 바꿉니다.</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">데이터베이스 업그레이드 중</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">단일 용도 앱에서 구독 정보를 가져옵니다...</string>
<string name="search_itunes_label">iTunes 검색</string>
+ <string name="select_label"><b>선택 ...</b></string>
+ <string name="all_label">모두</string>
+ <string name="selected_all_label">모든 에피소드 선택</string>
+ <string name="none_label">없음</string>
+ <string name="deselected_all_label">모든 에피소드 선택 해제</string>
+ <string name="played_label">재생함</string>
+ <string name="selected_played_label">재생 에피소드 선택</string>
+ <string name="unplayed_label">재생 안 함</string>
+ <string name="selected_unplayed_label">재생 안 한 에피소드 선택</string>
+ <string name="downloaded_label">다운로드함</string>
+ <string name="selected_downloaded_label">다운로드한 에피소드 선택</string>
+ <string name="not_downloaded_label">다운로드 안 함</string>
+ <string name="selected_not_downloaded_label">다운로드 안 한 에피소드 선택</string>
+ <string name="sort_title"><b>정렬 ...</b></string>
+ <string name="sort_title_a_z">제목 (A \u2192 Z)</string>
+ <string name="sort_title_z_a">제목 (Z \u2192 A)</string>
+ <string name="sort_date_new_old">시각 (최근 \u2192 과거)</string>
+ <string name="sort_date_old_new">시각 (과거 \u2192 최근)</string>
+ <string name="sort_duration_short_long">길이 (짧은 \u2192 긴)</string>
+ <string name="sort_duration_long_short">길이 (긴 \u2192 짧은)</string>
</resources>
diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml
index 0f447d54a..4ef43ecaf 100644
--- a/core/src/main/res/values-nl/strings.xml
+++ b/core/src/main/res/values-nl/strings.xml
@@ -54,7 +54,6 @@
<string name="mark_all_read_label">Alles als gelezen markeren</string>
<string name="show_info_label">Toon informatie</string>
<string name="share_link_label">Website link delen</string>
- <string name="share_source_label">Feed link delen</string>
<string name="feed_delete_confirmation_msg">Bevestig dat u deze feed en ALLE afleveringen van deze feed die u hebt gedownload wilt verwijderen.</string>
<string name="feed_remover_msg">Feed verwijderen</string>
<!--actions on feeditems-->
@@ -162,8 +161,6 @@
<string name="pref_followQueue_sum">Volgende wachtrij item afspelen als de episode voltooid is</string>
<string name="playback_pref">Afspelen</string>
<string name="network_pref">Netwerk</string>
- <string name="pref_autoUpdateIntervall_title">Update interval</string>
- <string name="pref_autoUpdateIntervall_sum">Voer een tijdsinterval in waarin de feeds automatisch worden vernieuwd, of schakel het uit</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Download mediabestanden alleen via WiFi</string>
<string name="pref_followQueue_title">Continu afspelen</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi download van media</string>
@@ -295,6 +292,7 @@
<string name="new_episodes_count_label">Aantal nieuwe afleveringen</string>
<string name="in_progress_episodes_count_label">Aantal afleveringen dat begonnen te luisteren zijn</string>
<!--Feed information screen-->
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Abonnementen aan het importeren vanuit single-purpose apps...</string>
</resources>
diff --git a/core/src/main/res/values-no/strings.xml b/core/src/main/res/values-no/strings.xml
new file mode 100644
index 000000000..645d576a4
--- /dev/null
+++ b/core/src/main/res/values-no/strings.xml
@@ -0,0 +1,31 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <!--Activitiy and fragment titles-->
+ <!--New episodes fragment-->
+ <!--Main activity-->
+ <!--Webview actions-->
+ <!--Playback history-->
+ <!--Other-->
+ <!--'Add Feed' Activity labels-->
+ <!--Actions on feeds-->
+ <!--actions on feeditems-->
+ <!--Download messages and labels-->
+ <!--Mediaplayer messages-->
+ <!--Queue operations-->
+ <!--Flattr-->
+ <!--Flattr-->
+ <!--Variable Speed-->
+ <!--Empty list labels-->
+ <!--Preferences-->
+ <!--Auto-Flattr dialog-->
+ <!--Search-->
+ <!--OPML import and export-->
+ <!--Sleep timer-->
+ <!--gpodder.net-->
+ <!--Directory chooser-->
+ <!--Online feed view-->
+ <!--Content descriptions for image buttons-->
+ <!--Feed information screen-->
+ <!--Progress information-->
+ <!--AntennaPodSP-->
+</resources>
diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml
index ba1a0bb91..a43ce7722 100644
--- a/core/src/main/res/values-pl-rPL/strings.xml
+++ b/core/src/main/res/values-pl-rPL/strings.xml
@@ -71,7 +71,6 @@
<string name="show_info_label">Pokaż informacje</string>
<string name="remove_feed_label">Usuń podcast</string>
<string name="share_link_label">Udostępnij stronę</string>
- <string name="share_source_label">Udostępnij kanał</string>
<string name="feed_delete_confirmation_msg">Potwierdź chęć usunięcia tego kanału wraz ze WSZYSTKIMI odcinkami, które zostały pobrane.</string>
<string name="feed_remover_msg">Usuwanie kanału</string>
<string name="load_complete_feed">Odśwież cały kanał</string>
@@ -197,8 +196,6 @@
<string name="pref_auto_delete_title">Automatyczne usuwanie</string>
<string name="playback_pref">Odtwarzanie</string>
<string name="network_pref">Sieć</string>
- <string name="pref_autoUpdateIntervall_title">Częstość aktualizacji</string>
- <string name="pref_autoUpdateIntervall_sum">Określ częstotliwość automatycznego odświeżania lub je wyłącz</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Pobieraj pliki tylko przez WiFi</string>
<string name="pref_followQueue_title">Odtwarzanie ciągłe</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi media pobrane</string>
@@ -238,8 +235,6 @@
<string name="pref_gpodnet_setlogin_information_sum">Zmień dane logowania konta gpodder.net.</string>
<string name="pref_playback_speed_title">Prędkość odtwarzania</string>
<string name="pref_playback_speed_sum">Dostosuj prędkości dostępne dla odtwarzania audio o zmiennej prędkości</string>
- <string name="pref_seek_delta_title">Seek time</string>
- <string name="pref_seek_delta_sum">Przeskocz o tyle sekund przewijając</string>
<string name="pref_gpodnet_sethostname_title">Ustaw nazwę hosta</string>
<string name="pref_gpodnet_sethostname_use_default_host">Użyj domyślnego hosta</string>
<string name="pref_expandNotify_title">Rozwiń Powiadomienia</string>
@@ -281,9 +276,6 @@
<string name="sleep_timer_label">Wyłącznik czasowy</string>
<string name="time_left_label">Pozostały czas:\u0020</string>
<string name="time_dialog_invalid_input">Błąd wpisu, czas musi być liczbą całkowitą</string>
- <string name="time_unit_seconds">sekundy</string>
- <string name="time_unit_minutes">minuty</string>
- <string name="time_unit_hours">godziny</string>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">KATEGORIE</string>
<string name="gpodnet_toplist_header">TOP PODCASTY</string>
@@ -353,6 +345,7 @@ https://gpodder.net/register/</string>
<!--Feed information screen-->
<string name="authentication_label">Autoryzacja</string>
<string name="authentication_descr">Zmień swoją nazwę użytkownika oraz hasło dla tego podcastu i jego odcinków</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importowanie subskrybcji z jednozadaniowych aplikacji</string>
</resources>
diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml
index c3523acfb..3d421fdb2 100644
--- a/core/src/main/res/values-pt-rBR/strings.xml
+++ b/core/src/main/res/values-pt-rBR/strings.xml
@@ -54,7 +54,6 @@
<string name="mark_all_read_label">Marcar todos como lido</string>
<string name="show_info_label">Mostrar informação</string>
<string name="share_link_label">Compartilhar link do site</string>
- <string name="share_source_label">Compartilhar link do feed</string>
<string name="feed_delete_confirmation_msg">Por favor confirme que você deseja apagar este feed e TODOS os episódios que você fez download deste feed.</string>
<string name="feed_remover_msg">Removendo feed</string>
<!--actions on feeditems-->
@@ -148,8 +147,6 @@
<string name="pref_followQueue_sum">Pular para próximo item da fila quando a reprodução terminar</string>
<string name="playback_pref">Reprodução</string>
<string name="network_pref">Rede</string>
- <string name="pref_autoUpdateIntervall_title">Intervalo de atualização</string>
- <string name="pref_autoUpdateIntervall_sum">Especifica o intervalo com que os feeds serão atualizados automaticamente ou desabilita esta funcionalidade</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Fazer download dos arquivos apenas via rede WiFi</string>
<string name="pref_followQueue_title">Reprodução contínua</string>
<string name="pref_downloadMediaOnWifiOnly_title">Download de mídia via WiFi</string>
@@ -271,5 +268,6 @@
<string name="in_queue_label">Episódio está na fila</string>
<string name="new_episodes_count_label">Numero de novos episódios</string>
<!--Feed information screen-->
+ <!--Progress information-->
<!--AntennaPodSP-->
</resources>
diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml
index abbf97de6..f02cd629e 100644
--- a/core/src/main/res/values-pt/strings.xml
+++ b/core/src/main/res/values-pt/strings.xml
@@ -16,7 +16,7 @@
<string name="downloads_running_label">Em curso</string>
<string name="downloads_completed_label">Terminadas</string>
<string name="downloads_log_label">Registo</string>
- <string name="cancel_download_label">Cancelar transferência</string>
+ <string name="cancel_download_label">Cancelar\ntransferência</string>
<string name="playback_history_label">Histórico de reprodução</string>
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_auth_label">Dados gpodder.net</string>
@@ -27,6 +27,12 @@
<string name="drawer_open">Abrir menu</string>
<string name="drawer_close">Fechar menu</string>
<string name="drawer_preferences">Preferências do menu</string>
+ <string name="drawer_feed_order_unplayed_episodes">Ordenar por contador</string>
+ <string name="drawer_feed_order_alphabetical">Ordenar alfabeticamente</string>
+ <string name="drawer_feed_counter_new_unplayed">Número de episódios novos ou por reproduzir</string>
+ <string name="drawer_feed_counter_new">Número de novos episódios</string>
+ <string name="drawer_feed_counter_unplayed">Número de episódios por reproduzir</string>
+ <string name="drawer_feed_counter_none">Nenhum</string>
<!--Webview actions-->
<string name="open_in_browser_label">Abrir no navegador</string>
<string name="copy_url_label">Copiar URL</string>
@@ -38,6 +44,8 @@
<!--Other-->
<string name="confirm_label">Confirmar</string>
<string name="cancel_label">Cancelar</string>
+ <string name="yes">Sim</string>
+ <string name="no">Não</string>
<string name="author_label">Autor</string>
<string name="language_label">Idioma</string>
<string name="url_label">URL</string>
@@ -60,7 +68,13 @@
<string name="close_label">Fechar</string>
<string name="retry_label">Tentar novamente</string>
<string name="auto_download_label">Incluir nas transferências automáticas</string>
+ <string name="auto_download_apply_to_items_title">Aplicar aos episódios anteriores</string>
+ <string name="auto_download_apply_to_items_message">A definição <i>Transferência automática</i> será aplicada a todos os novos episódios.\nGostaria de também a aplicar aos episódios anteriores?</string>
+ <string name="auto_delete_label">Apagar episódio automáticamente\n(altera a definição global)</string>
<string name="parallel_downloads_suffix">\u0020transferências simultâneas</string>
+ <string name="feed_auto_download_global">Global</string>
+ <string name="feed_auto_download_always">Sempre</string>
+ <string name="feed_auto_download_never">Nunca</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL da fonte</string>
<string name="etxtFeedurlHint">URL da fonte ou sítio web</string>
@@ -73,14 +87,20 @@
<string name="mark_all_read_msg">Marcar todos os episódios como reproduzidos</string>
<string name="mark_all_read_confirmation_msg">Por favor confirme que deseja marcar todos os episódios como reproduzidos</string>
<string name="mark_all_read_feed_confirmation_msg">Por favor confirme que deseja marcar todos os episódios desta fonte como reproduzidos</string>
+ <string name="mark_all_seen_label">Marcar tudo como visto</string>
<string name="show_info_label">Mostrar informações</string>
<string name="remove_feed_label">Remover podcast</string>
- <string name="share_link_label">Partilhar ligação do sítio web</string>
- <string name="share_source_label">Partilhar ligação da fonte</string>
- <string name="feed_delete_confirmation_msg">Confirme a eliminação desta fonte e de todos os episódios a ela pertencentes</string>
+ <string name="share_label">Partilhar...</string>
+ <string name="share_link_label">Partilhar ligação</string>
+ <string name="share_link_with_position_label">Partilhar ligação com posição</string>
+ <string name="share_feed_url_label">Partilhar URL da fonte</string>
+ <string name="share_item_url_label">Partilhar URL do episódio</string>
+ <string name="share_item_url_with_position_label">Partilhar URL do episódio com posição</string>
+ <string name="feed_delete_confirmation_msg">Por favor confirme que deseja apagar esta fonte e todos os episódios transferidos</string>
<string name="feed_remover_msg">Remover fonte</string>
<string name="load_complete_feed">Atualizar todas as páginas da fonte</string>
<string name="hide_episodes_title">Ocultar episódios</string>
+ <string name="episode_actions">Aplicar ações</string>
<string name="hide_unplayed_episodes_label">Não reproduzidos</string>
<string name="hide_paused_episodes_label">Em pausa</string>
<string name="hide_played_episodes_label">Reproduzidos</string>
@@ -99,8 +119,8 @@
<string name="remove_label">Remover</string>
<string name="remove_episode_lable">Remover episódio</string>
<string name="mark_read_label">Marcar como reproduzido</string>
- <string name="mark_unread_label">Marcar como não reproduzido</string>
<string name="marked_as_read_label">Marcado como reproduzido</string>
+ <string name="mark_unread_label">Marcar como não reproduzido</string>
<string name="add_to_queue_label">Adicionar à fila</string>
<string name="added_to_queue_label">Adicionado à fila</string>
<string name="remove_from_queue_label">Remover da fila</string>
@@ -138,7 +158,7 @@
<string name="download_error_db_access">Erro de acesso à base de dados</string>
<string name="downloads_left">\u0020Transferências em falta</string>
<string name="downloads_processing">Processamento de transferências</string>
- <string name="download_notification_title">A transferir dados...</string>
+ <string name="download_notification_title">A transferir dados do podcast</string>
<string name="download_report_content">%1$d transferências efetuadas, %2$d falhadas</string>
<string name="download_log_title_unknown">Título desconhecido</string>
<string name="download_type_feed">Fonte</string>
@@ -209,7 +229,7 @@
<!--Variable Speed-->
<string name="download_plugin_label">Transferir extra</string>
<string name="no_playback_plugin_title">Extra não instalado</string>
- <string name="no_playback_plugin_msg">Para que a velocidade de reprodução variável funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer problemas que ocorram na utilização do extra devem ser reportados diretamente ao seu programador.</string>
+ <string name="no_playback_plugin_msg">Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador.</string>
<string name="set_playback_speed_label">Velocidades de reprodução</string>
<!--Empty list labels-->
<string name="no_items_label">Não existem itens nesta lista</string>
@@ -223,19 +243,23 @@
<string name="pref_pauseOnHeadsetDisconnect_sum">Pausa na reprodução ao remover os auscultadores</string>
<string name="pref_unpauseOnHeadsetReconnect_sum">Continuar reprodução ao ligar os auscultadores</string>
<string name="pref_followQueue_sum">Ir para a faixa seguinte ao terminar a reprodução</string>
- <string name="pref_auto_delete_sum">Eliminar episódio ao terminar a reprodução</string>
+ <string name="pref_auto_delete_sum">Apagar episódio ao terminar a reprodução</string>
<string name="pref_auto_delete_title">Eliminação automática</string>
<string name="pref_smart_mark_as_played_sum">Marcar episódios como reproduzidos mesmo que restem alguns segundos de reprodução</string>
<string name="pref_smart_mark_as_played_title">Marcar como reproduzido (inteligente)</string>
<string name="playback_pref">Reprodução</string>
<string name="network_pref">Rede</string>
- <string name="pref_autoUpdateIntervall_title">Intervalo entre atualizações</string>
- <string name="pref_autoUpdateIntervall_sum">Indique o intervalo de tempo entre as atualizações de fontes ou desative a opção</string>
- <string name="pref_downloadMediaOnWifiOnly_sum">Apenas transferir pelas redes sem fios</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Intervalo de atualização ou hora do dia</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Define um intervalo de atualização ou hora para atualizar automaticamente a fonte</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">Pode definir um <i>intervalo</i>, ex.: \"a cada 2 horas\", definir uma <i>hora do dia</i>, ex.: \"7:00 AM\" ou <i>desativar</i> as atualizações automáticas.\n\n<small>Tenha em conta que a hora de atualização não é precisa. Pode existir um pouco de atraso.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Desativar</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Definir intervalo</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Definir hora do dia</string>
+ <string name="pref_downloadMediaOnWifiOnly_sum">Apenas transferir através de redes sem fios</string>
<string name="pref_followQueue_title">Reprodução contínua</string>
- <string name="pref_downloadMediaOnWifiOnly_title">Transferência Wi-Fi</string>
+ <string name="pref_downloadMediaOnWifiOnly_title">Transferir por Wi-Fi</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Auscultadores removidos</string>
- <string name="pref_unpauseOnHeadsetReconnect_title">Auscultadores ligados</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Auscultadores inseridos</string>
<string name="pref_mobileUpdate_title">Atualizações móveis</string>
<string name="pref_mobileUpdate_sum">Permitir atualizações através da rede de dados móveis</string>
<string name="refreshing_label">A atualizar</string>
@@ -250,14 +274,20 @@
<string name="pref_auto_flattr_sum">Configurar flattr automático</string>
<string name="user_interface_label">Interface</string>
<string name="pref_set_theme_title">Tema</string>
- <string name="pref_nav_drawer_items_title">Alterar itens do menu</string>
+ <string name="pref_nav_drawer_title">Personalizar menu de navegação</string>
+ <string name="pref_nav_drawer_sum">Personaliza a aparência do menu de navegação</string>
+ <string name="pref_nav_drawer_items_title">Alterar elementos do menu</string>
<string name="pref_nav_drawer_items_sum">Alterar os itens que aparecem no menu de navegação</string>
+ <string name="pref_nav_drawer_feed_order_title">Definir ordem de subscrição</string>
+ <string name="pref_nav_drawer_feed_order_sum">Alterar a ordem das suas subscrições</string>
+ <string name="pref_nav_drawer_feed_counter_title">Definir contador de subsrições</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Mudar informação mostrada no contador de subscrições</string>
<string name="pref_set_theme_sum">Mudar o aspeto do AntennaPod</string>
<string name="pref_automatic_download_title">Transferência automática</string>
<string name="pref_automatic_download_sum">Configure a transferência automática dos episódios</string>
<string name="pref_autodl_wifi_filter_title">Ativar filtro Wi-Fi</string>
<string name="pref_autodl_wifi_filter_sum">Apenas permitir transferências automáticas através de redes sem fios</string>
- <string name="pref_automatic_download_on_battery_title">Transferência se não estiver a carregar</string>
+ <string name="pref_automatic_download_on_battery_title">Transferir se não estiver a carregar</string>
<string name="pref_automatic_download_on_battery_sum">Permitir transferência automática se a bateria não estiver a ser carregada</string>
<string name="pref_parallel_downloads_title">Transferências simultâneas</string>
<string name="pref_episode_cache_title">Cache de episódios</string>
@@ -283,10 +313,14 @@
<string name="pref_expandNotify_sum">Expandir sempre a notificação para mostrar os botões de reprodução</string>
<string name="pref_persistNotify_title">Controlos de reprodução persistentes</string>
<string name="pref_persistNotify_sum">Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa</string>
+ <string name="pref_showDownloadReport_title">Mostrar relatório de erros</string>
+ <string name="pref_showDownloadReport_sum">Se a transferência falhar, gera um relatório que mostra os detalhes do erro</string>
<string name="pref_expand_notify_unsupport_toast">As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações</string>
<string name="pref_queueAddToFront_sum">Colocar novos episódios no inicio da fila</string>
<string name="pref_queueAddToFront_title">Novos episódios no inicio</string>
<string name="pref_smart_mark_as_played_disabled">Desativada</string>
+ <string name="pref_image_cache_size_title">Cache de imagens</string>
+ <string name="pref_image_cache_size_sum">O tamanho da cache de imagens</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Ativar flattr automático</string>
<string name="auto_flattr_after_percent">Flattr de episódios ao atingir %d porcento de reprodução</string>
@@ -312,6 +346,7 @@
<string name="opml_import_error_dir_empty">O diretório de importação está vazio</string>
<string name="select_all_label">Marcar tudo</string>
<string name="deselect_all_label">Desmarcar tudo</string>
+ <string name="select_options_label">Selecionar...</string>
<string name="choose_file_from_filesystem">Do sistema local de ficheiros</string>
<string name="choose_file_from_external_application">Utilizar aplicação externa</string>
<string name="opml_export_label">Exportação OPML</string>
@@ -326,9 +361,21 @@
<string name="sleep_timer_label">Temporizador</string>
<string name="time_left_label">Tempo restante:\u0020</string>
<string name="time_dialog_invalid_input">Tem que introduzir um número inteiro</string>
- <string name="time_unit_seconds">segundos</string>
- <string name="time_unit_minutes">minutos</string>
- <string name="time_unit_hours">horas</string>
+ <string name="time_seconds">segundos</string>
+ <string name="time_minutes">minutos</string>
+ <string name="time_hours">horas</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 segundo</item>
+ <item quantity="other">%d segundos</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minuto</item>
+ <item quantity="other">%d minutos</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 hora</item>
+ <item quantity="other">%d horas</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">Categorias</string>
<string name="gpodnet_toplist_header">Melhores</string>
@@ -373,6 +420,7 @@
<string name="pref_pausePlaybackForFocusLoss_title">Pausa nas interrupções</string>
<string name="pref_resumeAfterCall_sum">Continuar reprodução ao terminar a chamada</string>
<string name="pref_resumeAfterCall_title">Continuar após a chamada</string>
+ <string name="pref_restart_required">Tem que reiniciar o AntennaPod para aplicar as alterações</string>
<!--Online feed view-->
<string name="subscribe_label">Subscrever</string>
<string name="subscribed_label">Subscrito</string>
@@ -399,7 +447,29 @@
<!--Feed information screen-->
<string name="authentication_label">Autenticação</string>
<string name="authentication_descr">Altere o seu nome de utilizador e senha para este podcast e seus episódios</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">Atualizando base de dados</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importar subscrições de aplicações single-purpose...</string>
<string name="search_itunes_label">Procurar no iTunes</string>
+ <string name="select_label"><b>Selecionar...</b></string>
+ <string name="all_label">Todos</string>
+ <string name="selected_all_label">Marcar todos os episódios</string>
+ <string name="none_label">Nenhum</string>
+ <string name="deselected_all_label">Desmarcar todos os episódios</string>
+ <string name="played_label">Reproduzidos</string>
+ <string name="selected_played_label">Selecionar episódios reproduzidos</string>
+ <string name="unplayed_label">Não reproduzidos</string>
+ <string name="selected_unplayed_label">Selecionar episódios não reproduzidos</string>
+ <string name="downloaded_label">Transferidos</string>
+ <string name="selected_downloaded_label">Selecionar episódios transferidos</string>
+ <string name="not_downloaded_label">Não transferidos</string>
+ <string name="selected_not_downloaded_label">Selecionar episódios não transferidos</string>
+ <string name="sort_title"><b>Ordenar por...</b></string>
+ <string name="sort_title_a_z">Título (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Título (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Data (Recente \u2192 Antiga)</string>
+ <string name="sort_date_old_new">Data (Antiga \u2192 Recente)</string>
+ <string name="sort_duration_short_long">Duração (Curta \u2192 Longa)</string>
+ <string name="sort_duration_long_short">Duração (Longa \u2192 Curta)</string>
</resources>
diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml
index 390f50767..ce82dec1e 100644
--- a/core/src/main/res/values-ro-rRO/strings.xml
+++ b/core/src/main/res/values-ro-rRO/strings.xml
@@ -50,7 +50,6 @@
<string name="mark_all_read_label">Marchează toate ca citite</string>
<string name="show_info_label">Arată informații</string>
<string name="share_link_label">Împarte adresă website</string>
- <string name="share_source_label">Împarte adresă feed</string>
<string name="feed_delete_confirmation_msg">Confirmați ștergerea feedului și a TUTUROR episoadelor pe care le-ați descărcat.</string>
<!--actions on feeditems-->
<string name="download_label">Descarcă</string>
@@ -140,8 +139,6 @@
<string name="pref_followQueue_sum">Sari la următorul element din coadă cand se termină ascultarea</string>
<string name="playback_pref">Ascultare</string>
<string name="network_pref">Rețea</string>
- <string name="pref_autoUpdateIntervall_title">Interval actualizare</string>
- <string name="pref_autoUpdateIntervall_sum">Specifică un interval în care feedurile sunt actualizate automat sau oprește funcția</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Descarcă fișiere media doar pe WiFi</string>
<string name="pref_followQueue_title">Ascultare continuă</string>
<string name="pref_downloadMediaOnWifiOnly_title">Descărcare media pe WiFi</string>
@@ -237,5 +234,6 @@
<string name="downloading_label">Se descarcă...</string>
<!--Content descriptions for image buttons-->
<!--Feed information screen-->
+ <!--Progress information-->
<!--AntennaPodSP-->
</resources>
diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml
index ae10b314f..c2c27484a 100644
--- a/core/src/main/res/values-ru/strings.xml
+++ b/core/src/main/res/values-ru/strings.xml
@@ -17,7 +17,7 @@
<string name="downloads_completed_label">Завершено</string>
<string name="downloads_log_label">Журнал</string>
<string name="cancel_download_label">Отменить загрузку</string>
- <string name="playback_history_label">История воспроизведения</string>
+ <string name="playback_history_label">Журнал</string>
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_auth_label">Войти на gpodder.net</string>
<!--New episodes fragment-->
@@ -26,6 +26,12 @@
<!--Main activity-->
<string name="drawer_open">Открыть меню</string>
<string name="drawer_close">Закрыть меню</string>
+ <string name="drawer_feed_order_unplayed_episodes">Сортировать по количеству</string>
+ <string name="drawer_feed_order_alphabetical">Сортировать по алфавиту</string>
+ <string name="drawer_feed_counter_new_unplayed">Количество новых и непрослушанных выпусков</string>
+ <string name="drawer_feed_counter_new">Количество новых выпусков</string>
+ <string name="drawer_feed_counter_unplayed">Количество непрослушанных выпусков</string>
+ <string name="drawer_feed_counter_none">Ничего</string>
<!--Webview actions-->
<string name="open_in_browser_label">Открыть в браузере</string>
<string name="copy_url_label">Скопировать ссылку</string>
@@ -37,8 +43,11 @@
<!--Other-->
<string name="confirm_label">Подтвердить</string>
<string name="cancel_label">Отмена</string>
+ <string name="yes">Да</string>
+ <string name="no">Нет</string>
<string name="author_label">Автор</string>
<string name="language_label">Язык</string>
+ <string name="url_label">Адрес</string>
<string name="podcast_settings_label">Настройки</string>
<string name="cover_label">Обложка</string>
<string name="error_label">Ошибка</string>
@@ -58,6 +67,7 @@
<string name="close_label">Закрыть</string>
<string name="retry_label">Повторить</string>
<string name="auto_download_label">Добавить в автозагрузки</string>
+ <string name="auto_download_apply_to_items_title">Применить к предыдущим выпускам</string>
<string name="parallel_downloads_suffix">\u0020одновременных загрузок</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL канала</string>
@@ -73,8 +83,8 @@
<string name="mark_all_read_feed_confirmation_msg">Подтвердите, что хотите пометить все эпизоды в этом канале как прослушанные.</string>
<string name="show_info_label">Показать информацию</string>
<string name="remove_feed_label">Удалить подкаст</string>
- <string name="share_link_label">Поделиться ссылкой на сайт</string>
- <string name="share_source_label">Ссылка на канал</string>
+ <string name="share_label">Поделиться...</string>
+ <string name="share_link_label">Поделиться ссылкой</string>
<string name="feed_delete_confirmation_msg">Подтвердите удаление канала и всех выпусков, загруженных с этого канала.</string>
<string name="feed_remover_msg">Удаление канала</string>
<string name="load_complete_feed">Обновить весь канал</string>
@@ -85,11 +95,12 @@
<string name="stop_label">Остановить</string>
<string name="stream_label">Воспроизвести из сети</string>
<string name="remove_label">Удалить</string>
- <string name="remove_episode_lable">Удалить</string>
- <string name="mark_read_label">Отметить как прочитанное</string>
- <string name="mark_unread_label">Отметить как непрочитанное</string>
+ <string name="remove_episode_lable">Удалить выпуск</string>
+ <string name="mark_read_label">Отметить как прослушанное</string>
<string name="marked_as_read_label">Помечено как прослушанное</string>
+ <string name="mark_unread_label">Отметить как непрослушанное</string>
<string name="add_to_queue_label">Добавить в очередь</string>
+ <string name="added_to_queue_label">Добавлено в очередь</string>
<string name="remove_from_queue_label">Удалить из очереди</string>
<string name="visit_website_label">Посетить сайт</string>
<string name="support_label">Поддержать через Flattr</string>
@@ -202,8 +213,6 @@
<string name="pref_auto_delete_title">Автоматическое удаление</string>
<string name="playback_pref">Воспроизведение</string>
<string name="network_pref">Сеть</string>
- <string name="pref_autoUpdateIntervall_title">Интервал обновлений</string>
- <string name="pref_autoUpdateIntervall_sum">Укажите интервал через который каналы обновляются автоматически, или отключите его</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Загружать файлы только через Wi-Fi</string>
<string name="pref_followQueue_title">Непрерывное воспроизведение</string>
<string name="pref_downloadMediaOnWifiOnly_title">Загрузка по Wi-Fi</string>
@@ -270,7 +279,7 @@
<!--OPML import and export-->
<string name="opml_import_txtv_button_lable">OPML файлы позволяют перемещать ваши подкасты из одного менеджера подкастов в другой.</string>
<string name="opml_import_explanation_1">Укажите путь к файлу на устройстве</string>
- <string name="opml_import_explanation_2">Откройте OPML-файл с помощью внешних приложений: Dropbox, Google Drive или любой файловый менеджер.</string>
+ <string name="opml_import_explanation_2">Откройте OPML-файл с помощью внешних приложений: Dropbox, Google Drive или любого файлового менеджера.</string>
<string name="opml_import_explanation_3">Множество приложений умеют <i>открывать</i> OPML-файлы <i>в</i> AntennaPod, например: Google Mail, Dropbox, Google Drive и большинство файловых менеджеров.</string>
<string name="start_import_label">Начать импорт</string>
<string name="opml_import_label">Импорт OPML</string>
@@ -294,9 +303,6 @@
<string name="sleep_timer_label">Таймер сна</string>
<string name="time_left_label">Осталось времени:\u0020</string>
<string name="time_dialog_invalid_input">Неправильный ввод, время должно быть в виде числа</string>
- <string name="time_unit_seconds">с</string>
- <string name="time_unit_minutes">м</string>
- <string name="time_unit_hours">ч</string>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">Категории</string>
<string name="gpodnet_toplist_header">Лучшее</string>
@@ -365,6 +371,7 @@
<!--Feed information screen-->
<string name="authentication_label">Авторизация</string>
<string name="authentication_descr">Изменить имя пользователя и пароль для этого подкаста и его выпусков.</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Импорт подписок из одноцелевых приложений…</string>
<string name="search_itunes_label">Поиск в iTunes</string>
diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml
index c0c49ca7d..ad970e521 100644
--- a/core/src/main/res/values-sv-rSE/strings.xml
+++ b/core/src/main/res/values-sv-rSE/strings.xml
@@ -3,41 +3,49 @@
<!--Activitiy and fragment titles-->
<string name="app_name">AntennaPod</string>
<string name="feeds_label">Flöden</string>
- <string name="add_feed_label">Lägg till podcast</string>
+ <string name="add_feed_label">Lägg till Podcast</string>
<string name="podcasts_label">PODCASTS</string>
<string name="episodes_label">EPISODER</string>
- <string name="new_episodes_label">Nya episoder</string>
- <string name="all_episodes_label">Alla episoder</string>
+ <string name="new_episodes_label">Nya Episoder</string>
+ <string name="all_episodes_label">Alla Episoder</string>
<string name="new_label">Ny</string>
<string name="waiting_list_label">Väntelista</string>
<string name="settings_label">Inställningar</string>
- <string name="add_new_feed_label">Lägg till podcast</string>
+ <string name="add_new_feed_label">Lägg till Podcast</string>
<string name="downloads_label">Nedladdningar</string>
<string name="downloads_running_label">Körs</string>
<string name="downloads_completed_label">Färdiga</string>
<string name="downloads_log_label">Logg</string>
- <string name="cancel_download_label">Avbryt nedladdning</string>
+ <string name="cancel_download_label">Avbryt\nNedladdning</string>
<string name="playback_history_label">Uppspelningshistorik</string>
<string name="gpodnet_main_label">gpodder.net</string>
- <string name="gpodnet_auth_label">gpodder.net login</string>
+ <string name="gpodnet_auth_label">Inloggning till gpodder.net</string>
<!--New episodes fragment-->
<string name="recently_published_episodes_label">Nyligen publicerade</string>
- <string name="episode_filter_label">Visa bara nya episoder</string>
+ <string name="episode_filter_label">Visa bara nya Episoder</string>
<!--Main activity-->
<string name="drawer_open">Öppna meny</string>
<string name="drawer_close">Stäng meny</string>
<string name="drawer_preferences">Lådinställningar</string>
+ <string name="drawer_feed_order_unplayed_episodes">Sortera efter räknare</string>
+ <string name="drawer_feed_order_alphabetical">Sortera alfabetiskt</string>
+ <string name="drawer_feed_counter_new_unplayed">Antal nya och ospelade episoder</string>
+ <string name="drawer_feed_counter_new">Antal nya episoder</string>
+ <string name="drawer_feed_counter_unplayed">Antal ospelade episoder</string>
+ <string name="drawer_feed_counter_none">Inga</string>
<!--Webview actions-->
- <string name="open_in_browser_label">Öppna i webbläsare</string>
+ <string name="open_in_browser_label">Öppna i Webbläsare</string>
<string name="copy_url_label">Kopiera URL</string>
<string name="share_url_label">Dela URL</string>
- <string name="copied_url_msg">Kopierade URL till clipboard.</string>
- <string name="go_to_position_label">Gå hit</string>
+ <string name="copied_url_msg">Kopierade URL:en till Urklipp</string>
+ <string name="go_to_position_label">Gå till denna Position</string>
<!--Playback history-->
- <string name="clear_history_label">Rensa historik</string>
+ <string name="clear_history_label">Rensa Historiken</string>
<!--Other-->
<string name="confirm_label">Bekräfta</string>
<string name="cancel_label">Avbryt</string>
+ <string name="yes">Ja</string>
+ <string name="no">Nej</string>
<string name="author_label">Skapare</string>
<string name="language_label">Språk</string>
<string name="url_label">URL</string>
@@ -60,27 +68,39 @@
<string name="close_label">Stäng</string>
<string name="retry_label">Försök igen</string>
<string name="auto_download_label">Inkludera i automatiska nedladdningar</string>
+ <string name="auto_download_apply_to_items_title">Applicera på Föregående Episoder</string>
+ <string name="auto_download_apply_to_items_message">Den nya inställningen <i>Automatisk Nedladdning</i> kommer automatiskt att appliceras på nya episoder.\nVill du också applicera det på tidigare episoder?</string>
+ <string name="auto_delete_label">Ta automatiskt bort episod\n(åsidosätter global standardinställning)</string>
<string name="parallel_downloads_suffix">\u0020parallella nedladdningar</string>
+ <string name="feed_auto_download_global">Global</string>
+ <string name="feed_auto_download_always">Alltid</string>
+ <string name="feed_auto_download_never">Aldrig</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">Flödets URL</string>
<string name="etxtFeedurlHint">URL till flöde eller webbsida</string>
<string name="txtvfeedurl_label">Lägg till podcast via URL</string>
- <string name="podcastdirectories_label">Hitta podcast i mapp</string>
+ <string name="podcastdirectories_label">Hitta Podcast i Biblioteket</string>
<string name="podcastdirectories_descr">Du kan söka efter podcasts baserat på namn, kategori eller populäritet med tjänsten gpodder.net eller på iTunes Store.</string>
<string name="browse_gpoddernet_label">Bläddra på gpodder.net</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Markera alla som spelade</string>
- <string name="mark_all_read_msg">Markera alla episoder som spelade</string>
+ <string name="mark_all_read_msg">Markera alla Episoder som spelade</string>
<string name="mark_all_read_confirmation_msg">Bekräfta att du verkligen vill markera alla episoder som spelade.</string>
<string name="mark_all_read_feed_confirmation_msg">Bekräfta att du verkligen vill markera alla episoder i detta flöde som spelade.</string>
+ <string name="mark_all_seen_label">Markera alla som sedda</string>
<string name="show_info_label">Visa information</string>
- <string name="remove_feed_label">Ta bort podcast</string>
- <string name="share_link_label">Dela hemsidans länk</string>
- <string name="share_source_label">Dela flödeslänk</string>
+ <string name="remove_feed_label">Ta bort Podcast</string>
+ <string name="share_label">Dela...</string>
+ <string name="share_link_label">Dela Länk</string>
+ <string name="share_link_with_position_label">Dela Länk med Position</string>
+ <string name="share_feed_url_label">Dela Flödets URL</string>
+ <string name="share_item_url_label">Dela Episodens URL</string>
+ <string name="share_item_url_with_position_label">Dela Episodens URL med Position</string>
<string name="feed_delete_confirmation_msg">Bekräfta att du vill ta bort denna feed och ALLA avsnitt av denna feed som du har hämtat.</string>
- <string name="feed_remover_msg">Tar bort flöde</string>
- <string name="load_complete_feed">Uppdatera hela flödet</string>
- <string name="hide_episodes_title">Dölj episoder</string>
+ <string name="feed_remover_msg">Tar bort Flöde</string>
+ <string name="load_complete_feed">Uppdatera hela Flödet</string>
+ <string name="hide_episodes_title">Dölj Episoder</string>
+ <string name="episode_actions">Applicera åtgärder</string>
<string name="hide_unplayed_episodes_label">Ospelade</string>
<string name="hide_paused_episodes_label">Pausad</string>
<string name="hide_played_episodes_label">Spelad</string>
@@ -97,10 +117,10 @@
<string name="stop_label">Stopp</string>
<string name="stream_label">Strömma</string>
<string name="remove_label">Ta bort</string>
- <string name="remove_episode_lable">Ta bort episod</string>
+ <string name="remove_episode_lable">Ta bort Episod</string>
<string name="mark_read_label">Markera som spelad</string>
- <string name="mark_unread_label">Markera som ospelad</string>
<string name="marked_as_read_label">Markera som spelad</string>
+ <string name="mark_unread_label">Markera som ospelad</string>
<string name="add_to_queue_label">Lägg till i kön</string>
<string name="added_to_queue_label">Lägg till i Kö</string>
<string name="remove_from_queue_label">Ta bort från Kön</string>
@@ -109,24 +129,24 @@
<string name="enqueue_all_new">Lägg till alla i kön</string>
<string name="download_all">Ladda ner alla</string>
<string name="skip_episode_label">Hoppa över episod</string>
- <string name="activate_auto_download">Aktivera automatisk nedladdning</string>
- <string name="deactivate_auto_download">Avaktivera automatisk nedladdning</string>
- <string name="reset_position">Nollställ uppspelningsposition</string>
+ <string name="activate_auto_download">Aktivera Automatisk Nedladdning</string>
+ <string name="deactivate_auto_download">Avaktivera Automatisk Nedladdning</string>
+ <string name="reset_position">Nollställ Uppspelningspositionen</string>
<!--Download messages and labels-->
<string name="download_successful">lyckades</string>
<string name="download_failed">misslyckades</string>
<string name="download_pending">Avvaktar nedladdning</string>
<string name="download_running">Nedladdning pågår</string>
- <string name="download_error_device_not_found">Lagringsenhet hittades inte</string>
- <string name="download_error_insufficient_space">Otillräckligt utrymme</string>
+ <string name="download_error_device_not_found">Hittade ingen lagringsenhet</string>
+ <string name="download_error_insufficient_space">Otillräckligt Utrymme</string>
<string name="download_error_file_error">Filfel</string>
<string name="download_error_http_data_error">HTTP data fel</string>
<string name="download_error_error_unknown">Okänt fel</string>
<string name="download_error_parser_exception">Tolkningsfel</string>
- <string name="download_error_unsupported_type">Flödestyp utan stöd</string>
+ <string name="download_error_unsupported_type">Flödestypen stöds inte</string>
<string name="download_error_connection_error">Anslutningsfel</string>
- <string name="download_error_unknown_host">Okänd värd</string>
- <string name="download_error_unauthorized">Autentiseringsproblem</string>
+ <string name="download_error_unknown_host">Okänd Värd</string>
+ <string name="download_error_unauthorized">Autentiseringsfel</string>
<string name="cancel_all_downloads_label">Avbryt alla nedladdningar</string>
<string name="download_canceled_msg">Nedladdning avbruten</string>
<string name="download_canceled_autodownload_enabled_msg">Nedladdning avbruten\nStängde av <i>Automatisk nedladdning</i> för denna sak</string>
@@ -134,13 +154,13 @@
<string name="download_report_content_title">Nedladdningsrapport</string>
<string name="download_error_malformed_url">Felaktig webbadress</string>
<string name="download_error_io_error">IO fel</string>
- <string name="download_error_request_error">Request fel</string>
- <string name="download_error_db_access">Ingen tillgång till databasen</string>
+ <string name="download_error_request_error">Förfrågningsfel</string>
+ <string name="download_error_db_access">Åtkomstfel till databasen</string>
<string name="downloads_left">\u0020Nedladdningar kvar</string>
<string name="downloads_processing">Bearbetar nedladdningar</string>
<string name="download_notification_title">Laddar ner podcastdata</string>
<string name="download_report_content">%1$d nedladdningar lyckades, %2$d misslyckades</string>
- <string name="download_log_title_unknown">Okänd titel</string>
+ <string name="download_log_title_unknown">Okänd Titel</string>
<string name="download_type_feed">Flöde</string>
<string name="download_type_media">Mediafil</string>
<string name="download_type_image">Bild</string>
@@ -148,10 +168,10 @@
<string name="authentication_notification_title">Autentisering krävs</string>
<string name="authentication_notification_msg">Resursen du begärde kräver ett användarnamn och ett lösenord</string>
<string name="confirm_mobile_download_dialog_title">Bekräfta mobil nedladdning</string>
- <string name="confirm_mobile_download_dialog_message_not_in_queue">Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nAktivera tillfälligt eller bara lägg till i kön?\n\n<small>Ditt val gäller i 10 minuter.</small></string>
- <string name="confirm_mobile_download_dialog_message">Nedladdning över mobil dataanslutning är avstängt i inställningarna.\n\nAktivera tillfälligt?\n\n<small>Ditt val gäller i 10 minuter.</small></string>
- <string name="confirm_mobile_download_dialog_only_add_to_queue">Lägg bara till i kön</string>
- <string name="confirm_mobile_download_dialog_enable_temporarily">Aktivera tillfälligt</string>
+ <string name="confirm_mobile_download_dialog_message_not_in_queue">Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nDu kan välja att antingen bara lägga till episoden i kön eller att tillfälligt tillåta nedladdning.\n\n<small>Ditt val gäller i 10 minuter.</small></string>
+ <string name="confirm_mobile_download_dialog_message">Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nVill du tillfälligt tillåta nedladdning?\n\n<small>Ditt val gäller i 10 minuter.</small></string>
+ <string name="confirm_mobile_download_dialog_only_add_to_queue">Köa</string>
+ <string name="confirm_mobile_download_dialog_enable_temporarily">Tillåt tillfälligt</string>
<!--Mediaplayer messages-->
<string name="player_error_msg">Fel! </string>
<string name="player_stopped_msg">Inget media spelar</string>
@@ -166,9 +186,9 @@
<string name="playbackservice_notification_title">Spelar podcast</string>
<string name="unknown_media_key">AntannaPod - Okänd mediaknapp: %1$d</string>
<!--Queue operations-->
- <string name="lock_queue">Lås kön</string>
- <string name="unlock_queue">Lås upp kön</string>
- <string name="clear_queue_label">Rensa kön</string>
+ <string name="lock_queue">Lås Kön</string>
+ <string name="unlock_queue">Lås upp Kön</string>
+ <string name="clear_queue_label">Rensa Kön</string>
<string name="undo">Ångra</string>
<string name="removed_from_queue">Föremålet avlägsnades</string>
<string name="move_to_top_label">Flytta längst upp</string>
@@ -229,37 +249,47 @@
<string name="pref_smart_mark_as_played_title">Smart markering av uppspelat innehåll</string>
<string name="playback_pref">Uppspelning</string>
<string name="network_pref">Nätverk </string>
- <string name="pref_autoUpdateIntervall_title">Uppdateringsintervall</string>
- <string name="pref_autoUpdateIntervall_sum">Ange ett intervall för att automatiskt uppdatera flödet eller avaktivera det</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Uppdateringsintervall eller Tid på Dagen</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Ange ett intervall eller specifik tid på dagen för att uppdatera flödena automatisk.</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">Du kan välja ett <i>intervall</i> som \"var 2 timmar\", en specifik <i>tid på dagen</i> som \"07:00\" eller <i>avaktivera</i> automatiska uppdateringar helt.\n\n<small>Notera: Uppdateringstiderna är inte exakta. Korta fördröjningar kan uppstå.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Avaktivera</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Sätt intervall</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Sätt Tid på Dagen</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Hämta mediefiler endast över WiFi</string>
- <string name="pref_followQueue_title">Kontinuerlig uppspelning</string>
+ <string name="pref_followQueue_title">Kontinuerlig Uppspelning</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi nedladdning</string>
- <string name="pref_pauseOnHeadsetDisconnect_title">Hörlurar bortkopplade</string>
- <string name="pref_unpauseOnHeadsetReconnect_title">Hörlurar återanslutna</string>
- <string name="pref_mobileUpdate_title">Mobila uppdateringar</string>
+ <string name="pref_pauseOnHeadsetDisconnect_title">Hörlurar Bortkopplade</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Hörlurar Återanslutna</string>
+ <string name="pref_mobileUpdate_title">Mobila Uppdateringar</string>
<string name="pref_mobileUpdate_sum">Tillåt uppdateringar via mobil dataanslutning</string>
<string name="refreshing_label">Uppdaterar</string>
<string name="flattr_settings_label">Flattr inställningar</string>
<string name="pref_flattr_auth_title">Flattr inloggning</string>
<string name="pref_flattr_auth_sum">För att Flattra saker direkt från appen, logga in på ditt Flattr-konto.</string>
- <string name="pref_flattr_this_app_title">Flattra den här appen</string>
+ <string name="pref_flattr_this_app_title">Flattra denna App</string>
<string name="pref_flattr_this_app_sum">Stöd utvecklingen av AntennaPod genom att flattra den. Tack!</string>
<string name="pref_revokeAccess_title">Återkalla åtkomst</string>
<string name="pref_revokeAccess_sum">Återkalla behörigheten till ditt Flattr-konto för denna app.</string>
<string name="pref_auto_flattr_title">Automatisk Flattring</string>
<string name="pref_auto_flattr_sum">Konfigurerar automatisk Flattring</string>
<string name="user_interface_label">Användargränssnitt</string>
- <string name="pref_set_theme_title">Välj tema</string>
- <string name="pref_nav_drawer_items_title">Ändra navigationslådan</string>
+ <string name="pref_set_theme_title">Välj Tema</string>
+ <string name="pref_nav_drawer_title">Anpassa Navigeringsrutan</string>
+ <string name="pref_nav_drawer_sum">Anpassa utseendet på navigeringsrutan.</string>
+ <string name="pref_nav_drawer_items_title">Välj saker i Navigeringsrutan</string>
<string name="pref_nav_drawer_items_sum">Ändra vilka saker som visas i navigationslådan.</string>
+ <string name="pref_nav_drawer_feed_order_title">Välj Prenumerationsordning</string>
+ <string name="pref_nav_drawer_feed_order_sum">Ändra ordningen på dina prenumerationer</string>
+ <string name="pref_nav_drawer_feed_counter_title">Välj Prenumerationsräknaren</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Ändra informationen som visas av prenumerationsräknaren</string>
<string name="pref_set_theme_sum">Ändra utseendet på AntennaPod.</string>
- <string name="pref_automatic_download_title">Automatisk nedladdning</string>
+ <string name="pref_automatic_download_title">Automatisk Nedladdning</string>
<string name="pref_automatic_download_sum">Konfigurera automatisk nedladdning av episoder.</string>
<string name="pref_autodl_wifi_filter_title">Aktivera WiFi filtrering</string>
<string name="pref_autodl_wifi_filter_sum">Tillåt automatisk nedladdning endast för utvalda WiFi-nätverk.</string>
<string name="pref_automatic_download_on_battery_title">Nedladdning vid batteridrift</string>
<string name="pref_automatic_download_on_battery_sum">Tillåt automatisk nedladdning när batteriet inte laddas</string>
- <string name="pref_parallel_downloads_title">Parallella nedladdningar</string>
+ <string name="pref_parallel_downloads_title">Parallella Nedladdningar</string>
<string name="pref_episode_cache_title">Episodcache</string>
<string name="pref_theme_title_light">Ljust</string>
<string name="pref_theme_title_dark">Mörkt</string>
@@ -281,12 +311,16 @@
<string name="pref_gpodnet_sethostname_use_default_host">Använd standardvärden</string>
<string name="pref_expandNotify_title">Expandera notifieringar</string>
<string name="pref_expandNotify_sum">Expandera alltid notifieringen för att visa uppspelningskontrollerna.</string>
- <string name="pref_persistNotify_title">Bestående uppspelningskontroller</string>
+ <string name="pref_persistNotify_title">Bestående Uppspelningskontroller</string>
<string name="pref_persistNotify_sum">Behåll notifiering och kontroller på låsskärmen när uppspelningen pausas.</string>
+ <string name="pref_showDownloadReport_title">Visa Nedladdningsrapport</string>
+ <string name="pref_showDownloadReport_sum">Visa en rapport med detaljer om felet när nedladdningar misslyckas.</string>
<string name="pref_expand_notify_unsupport_toast">Androidversioner före 4.1 har inte stöd för expanderade notifieringar.</string>
<string name="pref_queueAddToFront_sum">Lägg till episoder först i kön.</string>
- <string name="pref_queueAddToFront_title">Köa först.</string>
+ <string name="pref_queueAddToFront_title">Köa Först</string>
<string name="pref_smart_mark_as_played_disabled">Avaktiverad</string>
+ <string name="pref_image_cache_size_title">Bildcachestorlek</string>
+ <string name="pref_image_cache_size_sum">Storleken på bildcachen på disken.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Aktivera automatisk Flattring</string>
<string name="auto_flattr_after_percent">Flattra episoden så snart %d procent har spelats</string>
@@ -305,19 +339,20 @@
<string name="opml_import_explanation_2">Använd en extern applikation som Dropbox, Google Drive eller ditt favoritval av filhanterare för att öppna en OPML fil.</string>
<string name="opml_import_explanation_3">Flera applikationer som Google Mail, Dropbox, Google Drive och de flesta filhanterare kan <i>öppna</i> OPML filer <i>med</i> AntennaPod.</string>
<string name="start_import_label">Påbörja importering</string>
- <string name="opml_import_label">Importera OPML-fil</string>
+ <string name="opml_import_label">OPML Importering</string>
<string name="opml_directory_error">FEL! </string>
<string name="reading_opml_label">Läser OPML-fil</string>
<string name="opml_reader_error">Ett fel har skett vid iläsning av opml dokumentet:</string>
<string name="opml_import_error_dir_empty">Katalogen är tom.</string>
<string name="select_all_label">Välj alla</string>
<string name="deselect_all_label">Avmarkera alla</string>
+ <string name="select_options_label">Välj ...</string>
<string name="choose_file_from_filesystem">Från lokalt filsystem</string>
<string name="choose_file_from_external_application">Använd extern applikation</string>
<string name="opml_export_label">OPML export</string>
<string name="exporting_label">Exporterar...</string>
<string name="export_error_label">Exporteringsfel</string>
- <string name="opml_export_success_title">OPML export lyckades</string>
+ <string name="opml_export_success_title">OPML Exportering lyckades.</string>
<string name="opml_export_success_sum">.opml filen skrevs till:\u0020</string>
<!--Sleep timer-->
<string name="set_sleeptimer_label">Ställ in sömntimer</string>
@@ -326,9 +361,21 @@
<string name="sleep_timer_label">Sömntimer</string>
<string name="time_left_label">Återstående tid:\u0020</string>
<string name="time_dialog_invalid_input">Ogiltigt tal, tiden måste vara ett heltal</string>
- <string name="time_unit_seconds">sekunder</string>
- <string name="time_unit_minutes">minuter</string>
- <string name="time_unit_hours">timmar</string>
+ <string name="time_seconds">sekunder</string>
+ <string name="time_minutes">minuter</string>
+ <string name="time_hours">timmar</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 sekund</item>
+ <item quantity="other">%d sekunder</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minut</item>
+ <item quantity="other">%d minuter</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 timme</item>
+ <item quantity="other">%d timmar</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">KATEGORIER</string>
<string name="gpodnet_toplist_header">BÄSTA PODCASTS</string>
@@ -360,7 +407,7 @@
<!--Directory chooser-->
<string name="selected_folder_label">Vald mapp:</string>
<string name="create_folder_label">Skapa mapp</string>
- <string name="choose_data_directory">Välj mapp</string>
+ <string name="choose_data_directory">Välj Datakatalog</string>
<string name="create_folder_msg">Skapa ny mapp med namnet \"%1$s\"?</string>
<string name="create_folder_success">Skapade ny mapp</string>
<string name="create_folder_error_no_write_access">Kan inte skriva till den här mappen</string>
@@ -370,9 +417,10 @@
<string name="folder_not_empty_dialog_msg">Den mapp du har valt är inte tom. Filer kommer att placeras direkt i denna mapp. Fortsätt ändå?</string>
<string name="set_to_default_folder">Välj standardmapp</string>
<string name="pref_pausePlaybackForFocusLoss_sum">Pausa uppspelning istället för att sänka volymen när en annan app vill spela ljud</string>
- <string name="pref_pausePlaybackForFocusLoss_title">Pausa för avbrott</string>
+ <string name="pref_pausePlaybackForFocusLoss_title">Pausa för Avbrott</string>
<string name="pref_resumeAfterCall_sum">Återuppta uppspelning när ett telefonsamtal avslutas</string>
- <string name="pref_resumeAfterCall_title">Återuppta efter samtal</string>
+ <string name="pref_resumeAfterCall_title">Fortsätt efter Samtal</string>
+ <string name="pref_restart_required">AntennaPod behöver startas om för att denna inställning ska gälla.</string>
<!--Online feed view-->
<string name="subscribe_label">Prenumerera</string>
<string name="subscribed_label">Prenumererar</string>
@@ -399,7 +447,29 @@
<!--Feed information screen-->
<string name="authentication_label">Autentisering</string>
<string name="authentication_descr">Byt ditt användarnamn och lösenord för den här podcasten och dess episoder.</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">Uppgraderar databasen</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Importerar prenumerationer från appar gjorda för ett enda syfte...</string>
<string name="search_itunes_label">Leta i iTunes</string>
+ <string name="select_label"><b>Välj ...</b></string>
+ <string name="all_label">Alla</string>
+ <string name="selected_all_label">Välj alla Episoder</string>
+ <string name="none_label">Inga</string>
+ <string name="deselected_all_label">Avmarkera alla Episoder</string>
+ <string name="played_label">Spelade</string>
+ <string name="selected_played_label">Valde spelade Episoder</string>
+ <string name="unplayed_label">Ospelade</string>
+ <string name="selected_unplayed_label">Valde ospelade Episoder</string>
+ <string name="downloaded_label">Nedladdade</string>
+ <string name="selected_downloaded_label">Valde nedladdade Episoder</string>
+ <string name="not_downloaded_label">Ej nedladdade</string>
+ <string name="selected_not_downloaded_label">Valde ej nedladdade Episoder</string>
+ <string name="sort_title"><b>Sortera efter ...</b></string>
+ <string name="sort_title_a_z">Titel (A \u2192 Ö)</string>
+ <string name="sort_title_z_a">Titel (Ö \u2192 A)</string>
+ <string name="sort_date_new_old">Datum (Ny \u2192 Gammal)</string>
+ <string name="sort_date_old_new">Datum (Gammal \u2192 Ny)</string>
+ <string name="sort_duration_short_long">Längd (Kort \u2192 Lång)</string>
+ <string name="sort_duration_long_short">Längd (Lång \u2192 Kort)</string>
</resources>
diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml
index e83c9b48e..d202bc67c 100644
--- a/core/src/main/res/values-tr/strings.xml
+++ b/core/src/main/res/values-tr/strings.xml
@@ -26,6 +26,7 @@
<!--Main activity-->
<string name="drawer_open">Münüyü aç</string>
<string name="drawer_close">Menüyü kapat</string>
+ <string name="drawer_preferences">Çekmece Seçenekleri</string>
<!--Webview actions-->
<string name="open_in_browser_label">Tarayıcıda aç</string>
<string name="copy_url_label">URL\'yi kopyala</string>
@@ -39,6 +40,7 @@
<string name="cancel_label">İptal</string>
<string name="author_label">Yayıncı</string>
<string name="language_label">Dil</string>
+ <string name="url_label">URL</string>
<string name="podcast_settings_label">Ayarlar</string>
<string name="cover_label">Resim</string>
<string name="error_label">Hata</string>
@@ -67,17 +69,26 @@
<string name="podcastdirectories_descr">gdpodder.net dizininde yeni cep yayınlarını isme, kategoriye veya popülerliğe göre arayabilirsiniz veya iTunes mağazasında arama yapabilirsiniz.</string>
<string name="browse_gpoddernet_label">gpodder.net\'e gözat</string>
<!--Actions on feeds-->
- <string name="mark_all_read_label">Hepsini okundu olarak işaretle</string>
- <string name="mark_all_read_msg">Tüm bölümler okundu olarak işaretlendi</string>
- <string name="mark_all_read_confirmation_msg">Lütfen tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın.</string>
- <string name="mark_all_read_feed_confirmation_msg">Lütfen bu besleme içindeki tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın.</string>
+ <string name="mark_all_read_label">Hepsini oynatıldı olarak işaretle</string>
+ <string name="mark_all_read_msg">Tüm bölümleri oynatıldı olarak işaretle</string>
+ <string name="mark_all_read_confirmation_msg">Lütfen tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın.</string>
+ <string name="mark_all_read_feed_confirmation_msg">Lütfen bu besleme içindeki tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın.</string>
<string name="show_info_label">Bilgiyi göster</string>
<string name="remove_feed_label">Cep yayını kaldır</string>
<string name="share_link_label">Web sayfası bağlantısı paylaş</string>
- <string name="share_source_label">Besleme bağlantısını paylaş</string>
<string name="feed_delete_confirmation_msg">Lütfen bu beslemeyi ve bu beslemeye ait indirilmiş BÜTÜN bölümleri silme isteğinizi onaylayın.</string>
<string name="feed_remover_msg">Besleme kaldırılıyor</string>
<string name="load_complete_feed">Tüm beslemeyi yenile</string>
+ <string name="hide_episodes_title">Bölümleri gizle</string>
+ <string name="hide_unplayed_episodes_label">Oynatılmadı</string>
+ <string name="hide_paused_episodes_label">Duraklatıldı</string>
+ <string name="hide_played_episodes_label">Oynatıldı</string>
+ <string name="hide_queued_episodes_label">Kuyrukta</string>
+ <string name="hide_not_queued_episodes_label">Kuyrukta değil</string>
+ <string name="hide_downloaded_episodes_label">İndirildi</string>
+ <string name="hide_not_downloaded_episodes_label">İndirilmedi</string>
+ <string name="filtered_label">Filtrelendi</string>
+ <string name="refresh_failed_msg">{fa-exclamation-circle} Son yenileme başarısız oldu</string>
<!--actions on feeditems-->
<string name="download_label">İndir</string>
<string name="play_label">Oynat</string>
@@ -86,16 +97,20 @@
<string name="stream_label">Akış</string>
<string name="remove_label">Kaldır</string>
<string name="remove_episode_lable">Bölümü kaldır</string>
- <string name="mark_read_label">Okundu olarak işaretle</string>
- <string name="mark_unread_label">Okunmadı olarak işaretle</string>
- <string name="marked_as_read_label">Okundu olarak işaretlendi</string>
+ <string name="mark_read_label">Oynatıldı olarak işaretle</string>
+ <string name="marked_as_read_label">Oynatıldı olarak işaretlendi</string>
+ <string name="mark_unread_label">Oynatılmadı olarak işaretle</string>
<string name="add_to_queue_label">Kuyruğa Ekle</string>
+ <string name="added_to_queue_label">Kuyruğa Eklendi</string>
<string name="remove_from_queue_label">Kuyruktan Kaldır</string>
<string name="visit_website_label">Siteyi Ziyaret Et</string>
<string name="support_label">Flattr ile destekle</string>
<string name="enqueue_all_new">Hepsini kuyruğa ekle</string>
<string name="download_all">Hepsini indir</string>
<string name="skip_episode_label">Bölümü atla</string>
+ <string name="activate_auto_download">Otomatik indirmeyi etkinleştir</string>
+ <string name="deactivate_auto_download">Otomatik indirmeyi devre dışı bırak</string>
+ <string name="reset_position">Çalme konumunu sıfırla</string>
<!--Download messages and labels-->
<string name="download_successful">başarılı</string>
<string name="download_failed">başarısız</string>
@@ -113,7 +128,9 @@
<string name="download_error_unauthorized">Yetkilendirme hatası</string>
<string name="cancel_all_downloads_label">Bütün indirmeleri iptal et</string>
<string name="download_canceled_msg">İndirme iptal edildi</string>
- <string name="download_report_title">İndirme tamamlandı</string>
+ <string name="download_canceled_autodownload_enabled_msg">İndirme iptal edildi\nBu öğe için <i>Otomatik İndirme</i> devre dışı</string>
+ <string name="download_report_title">İndirme hata(lar) ile tamamlandı</string>
+ <string name="download_report_content_title">İndirme raporu</string>
<string name="download_error_malformed_url">Bozuk URL</string>
<string name="download_error_io_error">G/Ç Hatası</string>
<string name="download_error_request_error">İstek hatası</string>
@@ -129,6 +146,11 @@
<string name="download_request_error_dialog_message_prefix">Dosyayı indirmeye çalışırken bir hata oluştu:\u0020</string>
<string name="authentication_notification_title">Yetkilendirme gerekiyor</string>
<string name="authentication_notification_msg">İstediğiniz kaynak kullanıcı adı ve şifre istiyor</string>
+ <string name="confirm_mobile_download_dialog_title">Mobil İndirmeyi Onaylayın</string>
+ <string name="confirm_mobile_download_dialog_message_not_in_queue">Mobil veri ile indirme ayarlarda devre dışıdır.\n\nGeçici olarak açılsın mı yoksa sadece kuyruğa mı eklensin?\n\n<small>Bu tercihiniz 10 dakika boyunca hatırlanacak.</small></string>
+ <string name="confirm_mobile_download_dialog_message">Mobil veri ile indirme ayarlarda devre dışıdır.\n\nGeçici olarak açılsın mı?\n\n<small>Bu tercihiniz 10 dakika boyunca hatırlanacak.</small></string>
+ <string name="confirm_mobile_download_dialog_only_add_to_queue">Sadece Kuyruğa ekle</string>
+ <string name="confirm_mobile_download_dialog_enable_temporarily">Geçici olarak aç</string>
<!--Mediaplayer messages-->
<string name="player_error_msg">Hata!</string>
<string name="player_stopped_msg">Çalınan medya yok</string>
@@ -143,6 +165,8 @@
<string name="playbackservice_notification_title">Cep yayını çalınıyor</string>
<string name="unknown_media_key">AntennaPod - Bilinmeyen medya anahtarı: %1$d</string>
<!--Queue operations-->
+ <string name="lock_queue">Kuyruğu kilitle</string>
+ <string name="unlock_queue">Kuyruğun kilidini aç</string>
<string name="clear_queue_label">Kuyruğu temizle</string>
<string name="undo">Geri al</string>
<string name="removed_from_queue">Öge kaldırıldı</string>
@@ -202,8 +226,6 @@
<string name="pref_auto_delete_title">Otomatik Silme</string>
<string name="playback_pref">Çalma</string>
<string name="network_pref">Ağ</string>
- <string name="pref_autoUpdateIntervall_title">Güncelleme aralığı</string>
- <string name="pref_autoUpdateIntervall_sum">Beslemeleri yenilemek için bir aralık belirtin veya devre dışı bırakın.</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Medya dosyalarını sadece kablosuz bağlantı üzerinden indir</string>
<string name="pref_followQueue_title">Devamlı çalma</string>
<string name="pref_downloadMediaOnWifiOnly_title">Kablosuz medya indirmesi</string>
@@ -246,8 +268,8 @@
<string name="pref_gpodnet_setlogin_information_sum">gpodder.net hesabınız için giriş bilgisini değiştirin.</string>
<string name="pref_playback_speed_title">Çalma hızları</string>
<string name="pref_playback_speed_sum">Değişken hızlı ses yürütmesi için kullanılabilir hızları özelleştirin</string>
- <string name="pref_seek_delta_title">Arama zamanı</string>
- <string name="pref_seek_delta_sum">Geri veya ileri sararken bu kadar saniye atla</string>
+ <string name="pref_fast_forward">İleri sarma süresi</string>
+ <string name="pref_rewind">Geri sarma süresi</string>
<string name="pref_gpodnet_sethostname_title">Sunucu ismini ayarla</string>
<string name="pref_gpodnet_sethostname_use_default_host">Varsayılan sunucuyu kullan</string>
<string name="pref_expandNotify_title">Bildirimi Genişlet</string>
@@ -257,6 +279,7 @@
<string name="pref_expand_notify_unsupport_toast">Android 4.1 öncesi sürümler genişletilmiş bildirimleri desteklememektedir.</string>
<string name="pref_queueAddToFront_sum">Yeni bölümleri kuyruğun önüne ekle.</string>
<string name="pref_queueAddToFront_title">Kuyruğun önüne ekle.</string>
+ <string name="pref_smart_mark_as_played_disabled">Devre dışı</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Otomatik Flattr\'lamayı etkinleştir</string>
<string name="auto_flattr_after_percent">Bölümün yüzde %d kısmı oynatıldığında Flattr\'la</string>
@@ -296,9 +319,6 @@
<string name="sleep_timer_label">Zamanlayıcı</string>
<string name="time_left_label">Kalan süre:\u0020</string>
<string name="time_dialog_invalid_input">Geçersiz giriş, zaman bir tam sayı olmalıdır</string>
- <string name="time_unit_seconds">saniye</string>
- <string name="time_unit_minutes">dakika</string>
- <string name="time_unit_hours">saat</string>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">KATEGORİLER</string>
<string name="gpodnet_toplist_header">POPÜLER CEP YAYINLARI</string>
@@ -341,6 +361,8 @@
<string name="set_to_default_folder">Vaysayılan dizini seç</string>
<string name="pref_pausePlaybackForFocusLoss_sum">Başka bir uygulama ses çalmak istediğinde sesi kısmak yerine yürütmeyi duraklat</string>
<string name="pref_pausePlaybackForFocusLoss_title">Kesintiler için duraklat</string>
+ <string name="pref_resumeAfterCall_sum">Bir telefon konuşması tamamlandıktan sonra çalmaya kaldığı yerden devam et</string>
+ <string name="pref_resumeAfterCall_title">Konuşmadan sonra devam et</string>
<!--Online feed view-->
<string name="subscribe_label">Üye ol</string>
<string name="subscribed_label">Üye olundu</string>
@@ -367,6 +389,7 @@
<!--Feed information screen-->
<string name="authentication_label">Yetkilendirme</string>
<string name="authentication_descr">Bu cep yayını ve içerdiği bölümler için kullanıcı adı şifreyi değiştir.</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Üyelikler tek-amaçlı uygulamalardan içe aktarılıyor...</string>
<string name="search_itunes_label">iTunes\'da Arama</string>
diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml
index b6cd8ca98..9715e40c3 100644
--- a/core/src/main/res/values-uk-rUA/strings.xml
+++ b/core/src/main/res/values-uk-rUA/strings.xml
@@ -27,6 +27,12 @@
<string name="drawer_open">Показати меню</string>
<string name="drawer_close">Сховати меню</string>
<string name="drawer_preferences">Настройки навігації</string>
+ <string name="drawer_feed_order_unplayed_episodes">Сортувати за лічильником</string>
+ <string name="drawer_feed_order_alphabetical">Сортування за абеткою</string>
+ <string name="drawer_feed_counter_new_unplayed">Кількість нових та непрослуханих епізодів</string>
+ <string name="drawer_feed_counter_new">Кількість нових епізодів</string>
+ <string name="drawer_feed_counter_unplayed">Кількість непрослуханих епізодів</string>
+ <string name="drawer_feed_counter_none">Жодних</string>
<!--Webview actions-->
<string name="open_in_browser_label">Відкрити в браузері</string>
<string name="copy_url_label">Копіювати URL</string>
@@ -38,6 +44,8 @@
<!--Other-->
<string name="confirm_label"> Підтвердити</string>
<string name="cancel_label">Скасувати</string>
+ <string name="yes">Так</string>
+ <string name="no">Ні</string>
<string name="author_label">Автор</string>
<string name="language_label">Мова</string>
<string name="url_label">URL</string>
@@ -60,7 +68,13 @@
<string name="close_label">Закрити</string>
<string name="retry_label">Повторити знову</string>
<string name="auto_download_label">Включити до автозавантаження</string>
+ <string name="auto_download_apply_to_items_title">Застосувати до попередніх епізодів</string>
+ <string name="auto_download_apply_to_items_message">Нове налаштування <i>Автозавантаження</i> буде автоматично застосоване до нових епізодів.\nБажаєте також застосувати його до попередніх епізодів?</string>
+ <string name="auto_delete_label">Автоматичне видалення епізода\n(перевизначити глобальне налаштування за замовчуванням)</string>
<string name="parallel_downloads_suffix">\u0020паралельні завантаження</string>
+ <string name="feed_auto_download_global">Для всіх</string>
+ <string name="feed_auto_download_always">Завжди</string>
+ <string name="feed_auto_download_never">Ніколи</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">Посилання на канал</string>
<string name="etxtFeedurlHint">URL канала або сайта</string>
@@ -73,14 +87,20 @@
<string name="mark_all_read_msg">Позначено всі епізоди як грані</string>
<string name="mark_all_read_confirmation_msg">Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди як грані.</string>
<string name="mark_all_read_feed_confirmation_msg">Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди цього канала як грані.</string>
+ <string name="mark_all_seen_label">Позначити всі як переглянуті</string>
<string name="show_info_label">Інформація</string>
<string name="remove_feed_label">Видалити подкаст</string>
+ <string name="share_label">Поділитись...</string>
<string name="share_link_label">Поділитися URL сайту</string>
- <string name="share_source_label">Поділитися URL каналу</string>
+ <string name="share_link_with_position_label">Поділитись посиланням на позицію</string>
+ <string name="share_feed_url_label">Поділитись посиланням на канал</string>
+ <string name="share_item_url_label">Поділитись посиланням на епізод</string>
+ <string name="share_item_url_with_position_label">Поділитись посиланням на епізод з позицією</string>
<string name="feed_delete_confirmation_msg">Ви впенені що хочете видаліти канал та всі завантажені епізоди</string>
<string name="feed_remover_msg">Удаляю канал</string>
<string name="load_complete_feed">Оновити канал цілком</string>
<string name="hide_episodes_title">Приховати епізоди</string>
+ <string name="episode_actions">Застосувати дії</string>
<string name="hide_unplayed_episodes_label">Неграні</string>
<string name="hide_paused_episodes_label">На паузі</string>
<string name="hide_played_episodes_label">Грані</string>
@@ -99,8 +119,8 @@
<string name="remove_label">Видалити</string>
<string name="remove_episode_lable">Видалити епізод</string>
<string name="mark_read_label">Позначити як граний</string>
- <string name="mark_unread_label">Позначити як не граний</string>
<string name="marked_as_read_label">Позначено як граний</string>
+ <string name="mark_unread_label">Позначити як не граний</string>
<string name="add_to_queue_label">Додати до черги</string>
<string name="added_to_queue_label">Додано до черги</string>
<string name="remove_from_queue_label">Видалити з черги</string>
@@ -229,8 +249,12 @@
<string name="pref_smart_mark_as_played_title">Розумне позначення граних епізодів</string>
<string name="playback_pref">Відтворення</string>
<string name="network_pref">Мережа</string>
- <string name="pref_autoUpdateIntervall_title">Частота оновлень</string>
- <string name="pref_autoUpdateIntervall_sum">Визначити інтервал часу для автооновлювання або відключити автооновлення</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Частота оновлень або оновлення в зазначений час</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Визначити інтервал часу або визначити час щодня для автооновлення</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">Можливо встановити <i>інтервал</i> як то \"кожні 2 години\", встановити <i>час щодня</i> як то \"7:00\" або <i>відклюсити</i> автоматичне оновлення взагалі.\n\n<small>Зверніть увагу: Час оновлення не є точним. Можливі короткі затримки.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Вимкнути</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Встановити інтервал</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Встановити час щодня</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Завантажувати тільки через Wifi</string>
<string name="pref_followQueue_title">Грати безперервно</string>
<string name="pref_downloadMediaOnWifiOnly_title">Завантаження через Wifi</string>
@@ -250,8 +274,14 @@
<string name="pref_auto_flattr_sum">Налаштування автоматичного заохочення авторів через сервіс flattr</string>
<string name="user_interface_label">Вигляд</string>
<string name="pref_set_theme_title">Обрати тему</string>
+ <string name="pref_nav_drawer_title">Налаштувати панель навігації</string>
+ <string name="pref_nav_drawer_sum">Налаштувати вигляд панелі навігації</string>
<string name="pref_nav_drawer_items_title">Змінити настройки навігації</string>
<string name="pref_nav_drawer_items_sum">Вибрати елементи для використання у навігації</string>
+ <string name="pref_nav_drawer_feed_order_title">Встановити порядок підписок</string>
+ <string name="pref_nav_drawer_feed_order_sum">Змінити порядок ваших підписок</string>
+ <string name="pref_nav_drawer_feed_counter_title">Встановити лічильник підписок</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Змінити інформацію яку відображає лічильник підписок</string>
<string name="pref_set_theme_sum">Змінити вигляд AntennaPod</string>
<string name="pref_automatic_download_title">Автоматичне завантаження</string>
<string name="pref_automatic_download_sum">Налаштування автоматичного завантаження епізодів</string>
@@ -283,10 +313,14 @@
<string name="pref_expandNotify_sum">Завжди розгортати повідомлення, щоб показати кнопки керування.</string>
<string name="pref_persistNotify_title">Завжди показувати елементи керування відтворенням</string>
<string name="pref_persistNotify_sum">Показувати повідомлення та елементи керування на lockscreen в режимі паузи.</string>
+ <string name="pref_showDownloadReport_title">Показати звіт про завантаження</string>
+ <string name="pref_showDownloadReport_sum">У разі помилки при завантаженні створити детальний звіт про помилку.</string>
<string name="pref_expand_notify_unsupport_toast">Android до версії 4.1 не підтримує розширені повідомлення.</string>
<string name="pref_queueAddToFront_sum">Додавати нові епізоди до початку черги.</string>
<string name="pref_queueAddToFront_title">Додавати в початок черги.</string>
<string name="pref_smart_mark_as_played_disabled">Вимкнено</string>
+ <string name="pref_image_cache_size_title">Розмір кеша зображень</string>
+ <string name="pref_image_cache_size_sum">Розмір дискового кеша для зображень.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Включити автоматичне заохочення авторів через сервіс flattr</string>
<string name="auto_flattr_after_percent">Заохотити автора через Flattr щойно %d відсотків епізода було відтворено</string>
@@ -312,6 +346,7 @@
<string name="opml_import_error_dir_empty">Директорія імпорту пуста</string>
<string name="select_all_label">Обрати все</string>
<string name="deselect_all_label">Убрати виділення</string>
+ <string name="select_options_label">Обрати ...</string>
<string name="choose_file_from_filesystem">З локальної файлової системи</string>
<string name="choose_file_from_external_application">За допомогою додатка</string>
<string name="opml_export_label">OPML экспорт</string>
@@ -326,9 +361,24 @@
<string name="sleep_timer_label">Таймер сну</string>
<string name="time_left_label">Залишилось:\u0020</string>
<string name="time_dialog_invalid_input">Помилка вводу, час повинен бути цілим</string>
- <string name="time_unit_seconds">секунд</string>
- <string name="time_unit_minutes">хвилин</string>
- <string name="time_unit_hours">годин</string>
+ <string name="time_seconds">секунд</string>
+ <string name="time_minutes">хвилин</string>
+ <string name="time_hours">годин</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 секунда</item>
+ <item quantity="few">%d секунди</item>
+ <item quantity="other">%d секунд</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 хвилина</item>
+ <item quantity="few">%d хвилини</item>
+ <item quantity="other">%d хвилин</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 година</item>
+ <item quantity="few">%d години</item>
+ <item quantity="other">%d годин</item>
+ </plurals>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">КАТЕГОРІЇ</string>
<string name="gpodnet_toplist_header">ТОП ПОДКАСТІВ</string>
@@ -373,6 +423,7 @@
<string name="pref_pausePlaybackForFocusLoss_title">Пауза в разі переривання</string>
<string name="pref_resumeAfterCall_sum">Відновити відтворення після закінчення дзвінка</string>
<string name="pref_resumeAfterCall_title">Відновити після дзвінка</string>
+ <string name="pref_restart_required">Для застосування змін потрібно перезапустити AntennaPod</string>
<!--Online feed view-->
<string name="subscribe_label">Підписатися</string>
<string name="subscribed_label">Підписано</string>
@@ -399,7 +450,29 @@
<!--Feed information screen-->
<string name="authentication_label">Автентикація</string>
<string name="authentication_descr">Змінити ваші логін та пароль для подкаста та епізодів</string>
+ <!--Progress information-->
+ <string name="progress_upgrading_database">Оновлення бази даних</string>
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">Імпорт подкастів з інших програм...</string>
<string name="search_itunes_label">Пошук в iTunes</string>
+ <string name="select_label"><b>Обрати ...</b></string>
+ <string name="all_label">Всі</string>
+ <string name="selected_all_label">Обрано всі епізоди</string>
+ <string name="none_label">Жодного</string>
+ <string name="deselected_all_label">Жодного епізода обрано</string>
+ <string name="played_label">Переглянуті</string>
+ <string name="selected_played_label">Обрано переглянуті епізоди</string>
+ <string name="unplayed_label">Непереглянуті</string>
+ <string name="selected_unplayed_label">Обрано непереглянуті епізоди</string>
+ <string name="downloaded_label">Завантажені</string>
+ <string name="selected_downloaded_label">Обрано завантажені епізоди</string>
+ <string name="not_downloaded_label">Незавантажені</string>
+ <string name="selected_not_downloaded_label">Обрано незавантажені епізоди</string>
+ <string name="sort_title"><b>Сортувати за ...</b></string>
+ <string name="sort_title_a_z">Назва (А \u2192 Я)</string>
+ <string name="sort_title_z_a">Назва (Я \u2192 А)</string>
+ <string name="sort_date_new_old">Дата (Нові \u2192 Старі)</string>
+ <string name="sort_date_old_new">Дата (Старі \u2192 Нові)</string>
+ <string name="sort_duration_short_long">Тривалість (Короткі \u2192 Довгі)</string>
+ <string name="sort_duration_long_short">Тривалість (Довгі \u2192 Короткі)</string>
</resources>
diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml
index 594249a31..332c8ed4c 100644
--- a/core/src/main/res/values-zh-rCN/strings.xml
+++ b/core/src/main/res/values-zh-rCN/strings.xml
@@ -72,7 +72,6 @@
<string name="show_info_label">查看信息</string>
<string name="remove_feed_label">删除播客</string>
<string name="share_link_label">分享网站链接</string>
- <string name="share_source_label">分享订阅链接</string>
<string name="feed_delete_confirmation_msg">确认要删除这些订阅吗? 该订阅所有已经下载的曲目将一并删除. </string>
<string name="feed_remover_msg">删除订阅</string>
<string name="load_complete_feed">刷新全部订阅</string>
@@ -199,8 +198,6 @@
<string name="pref_auto_delete_title">自动删除</string>
<string name="playback_pref">播放</string>
<string name="network_pref">网络</string>
- <string name="pref_autoUpdateIntervall_title">更新周期</string>
- <string name="pref_autoUpdateIntervall_sum">设置订阅自动刷新周期</string>
<string name="pref_downloadMediaOnWifiOnly_sum">仅在 WIFI 情况下载媒体文件</string>
<string name="pref_followQueue_title">连续播放</string>
<string name="pref_downloadMediaOnWifiOnly_title">仅在 WIFI 情况下载</string>
@@ -292,9 +289,6 @@
<string name="sleep_timer_label">休眠计时器</string>
<string name="time_left_label">计时剩余:\u0020</string>
<string name="time_dialog_invalid_input">无效的输入, 时间是一个整数</string>
- <string name="time_unit_seconds">秒</string>
- <string name="time_unit_minutes">分钟</string>
- <string name="time_unit_hours">小时</string>
<!--gpodder.net-->
<string name="gpodnet_taglist_header">目录</string>
<string name="gpodnet_toplist_header">头条播客</string>
@@ -363,6 +357,7 @@
<!--Feed information screen-->
<string name="authentication_label">验证</string>
<string name="authentication_descr">给本播客及曲目变更用户名及密码</string>
+ <!--Progress information-->
<!--AntennaPodSP-->
<string name="sp_apps_importing_feeds_msg">正在从选定的应用中导入订阅...</string>
<string name="search_itunes_label">搜索 iTunes</string>
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 4ecf2cf61..8f1268993 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
+ <string-array name="spnAutoDeleteItems">
+ <item>@string/feed_auto_download_global</item>
+ <item>@string/feed_auto_download_always</item>
+ <item>@string/feed_auto_download_never</item>
+ </string-array>
+
<string-array name="smart_mark_as_played_values">
<item>0</item>
<item>15</item>
@@ -20,18 +26,7 @@
<item>60</item>
</integer-array>
- <string-array name="update_intervall_options">
- <item>Manual</item>
- <item>1 hour</item>
- <item>2 hours</item>
- <item>4 hours</item>
- <item>8 hours</item>
- <item>12 hours</item>
- <item>24 hours</item>
- </string-array>
-
<string-array name="update_intervall_values">
- <item>0</item>
<item>1</item>
<item>2</item>
<item>4</item>
@@ -39,30 +34,24 @@
<item>12</item>
<item>24</item>
</string-array>
+
<string-array name="episode_cache_size_entries">
- <item>@string/pref_episode_cache_unlimited</item>
- <item>1</item>
- <item>2</item>
<item>5</item>
<item>10</item>
- <item>20</item>
- <item>40</item>
- <item>60</item>
- <item>80</item>
+ <item>25</item>
+ <item>50</item>
<item>100</item>
+ <item>@string/pref_episode_cache_unlimited</item>
</string-array>
<string-array name="episode_cache_size_values">
- <item>-1</item>
- <item>1</item>
- <item>2</item>
<item>5</item>
<item>10</item>
- <item>20</item>
- <item>40</item>
- <item>60</item>
- <item>80</item>
+ <item>25</item>
+ <item>50</item>
<item>100</item>
+ <item>-1</item>
</string-array>
+
<string-array name="playback_speed_values">
<item>0.5</item>
<item>0.6</item>
@@ -137,6 +126,28 @@
<item>@string/add_feed_label</item>
</string-array>
+ <string-array name="nav_drawer_feed_order_options">
+ <item>@string/drawer_feed_order_unplayed_episodes</item>
+ <item>@string/drawer_feed_order_alphabetical</item>
+ </string-array>
+ <string-array name="nav_drawer_feed_order_values">
+ <item>0</item>
+ <item>1</item>
+ </string-array>
+
+ <string-array name="nav_drawer_feed_counter_options">
+ <item>@string/drawer_feed_counter_new_unplayed</item>
+ <item>@string/drawer_feed_counter_new</item>
+ <item>@string/drawer_feed_counter_unplayed</item>
+ <item>@string/drawer_feed_counter_none</item>
+ </string-array>
+ <string-array name="nav_drawer_feed_counter_values">
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+
<string-array name="episode_hide_options">
<item>@string/hide_unplayed_episodes_label</item>
<item>@string/hide_paused_episodes_label</item>
@@ -157,4 +168,20 @@
<item>not_downloaded</item>
</string-array>
+ <string-array name="image_cache_size_options">
+ <item>20 MiB</item>
+ <item>50 MiB</item>
+ <item>100 MiB</item>
+ <item>250 MiB</item>
+ <item>500 MiB</item>
+ </string-array>
+
+ <string-array name="image_cache_size_values">
+ <item>20</item>
+ <item>50</item>
+ <item>100</item>
+ <item>250</item>
+ <item>500</item>
+ </string-array>
+
</resources>
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index e558a5c4e..bc0521dcd 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -3,6 +3,7 @@
<color name="white">#FFFFFF</color>
<color name="gray">#808080</color>
+ <color name="light_gray">#bfbfbf</color>
<color name="black">#000000</color>
<color name="bright_blue">#33B5E5</color>
<color name="ics_gray">#858585</color>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 3cedfb8e5..00bc077e8 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -7,46 +7,54 @@
<!-- Activitiy and fragment titles -->
<string name="app_name">AntennaPod</string>
<string name="feeds_label">Feeds</string>
- <string name="add_feed_label">Add podcast</string>
+ <string name="add_feed_label">Add Podcast</string>
<string name="podcasts_label">PODCASTS</string>
<string name="episodes_label">EPISODES</string>
- <string name="new_episodes_label">New episodes</string>
- <string name="all_episodes_label">All episodes</string>
+ <string name="new_episodes_label">New Episodes</string>
+ <string name="all_episodes_label">All Episodes</string>
<string name="new_label">New</string>
- <string name="waiting_list_label">Waiting list</string>
+ <string name="waiting_list_label">Waiting List</string>
<string name="settings_label">Settings</string>
- <string name="add_new_feed_label">Add podcast</string>
+ <string name="add_new_feed_label">Add Podcast</string>
<string name="downloads_label">Downloads</string>
<string name="downloads_running_label">Running</string>
<string name="downloads_completed_label">Completed</string>
<string name="downloads_log_label">Log</string>
- <string name="cancel_download_label">Cancel Download</string>
- <string name="playback_history_label">Playback history</string>
+ <string name="cancel_download_label">Cancel\nDownload</string>
+ <string name="playback_history_label">Playback History</string>
<string name="gpodnet_main_label">gpodder.net</string>
- <string name="gpodnet_auth_label">gpodder.net login</string>
+ <string name="gpodnet_auth_label">gpodder.net Login</string>
<!-- New episodes fragment -->
<string name="recently_published_episodes_label">Recently published</string>
- <string name="episode_filter_label">Show only new episodes</string>
+ <string name="episode_filter_label">Show only new Episodes</string>
<!-- Main activity -->
<string name="drawer_open">Open menu</string>
<string name="drawer_close">Close menu</string>
<string name="drawer_preferences">Drawer Preferences</string>
+ <string name="drawer_feed_order_unplayed_episodes">Sort by counter</string>
+ <string name="drawer_feed_order_alphabetical">Sort alphabetically</string>
+ <string name="drawer_feed_counter_new_unplayed">Number of new and unplayed episodes</string>
+ <string name="drawer_feed_counter_new">Number of new episodes</string>
+ <string name="drawer_feed_counter_unplayed">Number of unplayed episodes</string>
+ <string name="drawer_feed_counter_none">None</string>
<!-- Webview actions -->
- <string name="open_in_browser_label">Open in browser</string>
+ <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>
- <string name="go_to_position_label">Go to this position</string>
+ <string name="copied_url_msg">Copied URL to Clipboard</string>
+ <string name="go_to_position_label">Go to this Position</string>
<!-- Playback history -->
- <string name="clear_history_label">Clear history</string>
+ <string name="clear_history_label">Clear History</string>
<!-- Other -->
<string name="confirm_label">Confirm</string>
<string name="cancel_label">Cancel</string>
+ <string name="yes">Yes</string>
+ <string name="no">No</string>
<string name="author_label">Author</string>
<string name="language_label">Language</string>
<string name="url_label">URL</string>
@@ -59,7 +67,7 @@
<string name="chapters_label">Chapters</string>
<string name="shownotes_label">Shownotes</string>
<string name="description_label">Description</string>
- <string name="most_recent_prefix">Most Recent Episode:\u0020</string>
+ <string name="most_recent_prefix">Most recent episode:\u0020</string>
<string name="episodes_suffix">\u0020episodes</string>
<string name="length_prefix">Length:\u0020</string>
<string name="size_prefix">Size:\u0020</string>
@@ -69,29 +77,41 @@
<string name="close_label">Close</string>
<string name="retry_label">Retry</string>
<string name="auto_download_label">Include in auto downloads</string>
+ <string name="auto_download_apply_to_items_title">Apply to Previous Episodes</string>
+ <string name="auto_download_apply_to_items_message">The new <i>Auto Download</i> setting will automatically be applied to new episodes.\nDo you also want to apply it to previous episodes?</string>
+ <string name="auto_delete_label">Auto Delete Episode\n(override global default)</string>
<string name="parallel_downloads_suffix">\u0020parallel downloads</string>
+ <string name="feed_auto_download_global">Global</string>
+ <string name="feed_auto_download_always">Always</string>
+ <string name="feed_auto_download_never">Never</string>
<!-- 'Add Feed' Activity labels -->
<string name="feedurl_label">Feed URL</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
<string name="txtvfeedurl_label">Add Podcast by URL</string>
- <string name="podcastdirectories_label">Find podcast in directory</string>
+ <string name="podcastdirectories_label">Find Podcast in Directory</string>
<string name="podcastdirectories_descr">You can search for new podcasts by name, category or popularity in the gpodder.net directory, or search the iTunes store.</string>
<string name="browse_gpoddernet_label">Browse gpodder.net</string>
<!-- Actions on feeds -->
<string name="mark_all_read_label">Mark all as played</string>
- <string name="mark_all_read_msg">Marked all episodes as played</string>
+ <string name="mark_all_read_msg">Marked all Episodes as played</string>
<string name="mark_all_read_confirmation_msg">Please confirm that you want to mark all episodes as being played.</string>
<string name="mark_all_read_feed_confirmation_msg">Please confirm that you want to mark all episodes in this feed as being played.</string>
+ <string name="mark_all_seen_label">Mark all as seen</string>
<string name="show_info_label">Show information</string>
- <string name="remove_feed_label">Remove podcast</string>
- <string name="share_link_label">Share website link</string>
- <string name="share_source_label">Share feed link</string>
+ <string name="remove_feed_label">Remove Podcast</string>
+ <string name="share_label">Share...</string>
+ <string name="share_link_label">Share Link</string>
+ <string name="share_link_with_position_label">Share Link with Position</string>
+ <string name="share_feed_url_label">Share Feed URL</string>
+ <string name="share_item_url_label">Share Episode URL</string>
+ <string name="share_item_url_with_position_label">Share Episode URL with Position</string>
<string name="feed_delete_confirmation_msg">Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded.</string>
- <string name="feed_remover_msg">Removing feed</string>
- <string name="load_complete_feed">Refresh complete feed</string>
- <string name="hide_episodes_title">Hide episodes</string>
+ <string name="feed_remover_msg">Removing Feed</string>
+ <string name="load_complete_feed">Refresh complete Feed</string>
+ <string name="hide_episodes_title">Hide Episodes</string>
+ <string name="episode_actions">Apply actions</string>
<string name="hide_unplayed_episodes_label">Unplayed</string>
<string name="hide_paused_episodes_label">Paused</string>
<string name="hide_played_episodes_label">Played</string>
@@ -100,7 +120,7 @@
<string name="hide_downloaded_episodes_label">Downloaded</string>
<string name="hide_not_downloaded_episodes_label">Not downloaded</string>
<string name="filtered_label">Filtered</string>
- <string name="refresh_failed_msg">{fa-exclamation-circle} Last refresh failed</string>
+ <string name="refresh_failed_msg">{fa-exclamation-circle} Last Refresh failed</string>
<!-- actions on feeditems -->
<string name="download_label">Download</string>
@@ -109,10 +129,10 @@
<string name="stop_label">Stop</string>
<string name="stream_label">Stream</string>
<string name="remove_label">Remove</string>
- <string name="remove_episode_lable">Remove episode</string>
+ <string name="remove_episode_lable">Remove Episode</string>
<string name="mark_read_label">Mark as played</string>
- <string name="mark_unread_label">Mark as unplayed</string>
<string name="marked_as_read_label">Marked as played</string>
+ <string name="mark_unread_label">Mark as unplayed</string>
<string name="add_to_queue_label">Add to Queue</string>
<string name="added_to_queue_label">Added to Queue</string>
<string name="remove_from_queue_label">Remove from Queue</string>
@@ -121,39 +141,39 @@
<string name="enqueue_all_new">Enqueue all</string>
<string name="download_all">Download all</string>
<string name="skip_episode_label">Skip episode</string>
- <string name="activate_auto_download">Activate auto download</string>
- <string name="deactivate_auto_download">Deactivate auto download</string>
- <string name="reset_position">Reset playback position</string>
+ <string name="activate_auto_download">Activate Auto Download</string>
+ <string name="deactivate_auto_download">Deactivate Auto Download</string>
+ <string name="reset_position">Reset Playback Position</string>
<!-- Download messages and labels -->
<string name="download_successful">successful</string>
<string name="download_failed">failed</string>
<string name="download_pending">Download pending</string>
<string name="download_running">Download running</string>
- <string name="download_error_device_not_found">Storage device not found</string>
- <string name="download_error_insufficient_space">Insufficient space</string>
- <string name="download_error_file_error">File error</string>
+ <string name="download_error_device_not_found">Storage Device not found</string>
+ <string name="download_error_insufficient_space">Insufficient Space</string>
+ <string name="download_error_file_error">File Error</string>
<string name="download_error_http_data_error">HTTP Data Error</string>
<string name="download_error_error_unknown">Unknown Error</string>
<string name="download_error_parser_exception">Parser Exception</string>
- <string name="download_error_unsupported_type">Unsupported Feed type</string>
- <string name="download_error_connection_error">Connection error</string>
- <string name="download_error_unknown_host">Unknown host</string>
- <string name="download_error_unauthorized">Authentication error</string>
+ <string name="download_error_unsupported_type">Unsupported Feed Type</string>
+ <string name="download_error_connection_error">Connection Error</string>
+ <string name="download_error_unknown_host">Unknown Host</string>
+ <string name="download_error_unauthorized">Authentication Error</string>
<string name="cancel_all_downloads_label">Cancel all downloads</string>
<string name="download_canceled_msg">Download canceled</string>
<string name="download_canceled_autodownload_enabled_msg">Download canceled\nDisabled <i>Auto Download</i> for this item</string>
<string name="download_report_title">Downloads completed with error(s)</string>
- <string name="download_report_content_title">Download report</string>
+ <string name="download_report_content_title">Download Report</string>
<string name="download_error_malformed_url">Malformed URL</string>
<string name="download_error_io_error">IO Error</string>
- <string name="download_error_request_error">Request error</string>
- <string name="download_error_db_access">Database access error</string>
+ <string name="download_error_request_error">Request Error</string>
+ <string name="download_error_db_access">Database Access Error</string>
<string name="downloads_left">\u0020Downloads left</string>
<string name="downloads_processing">Processing downloads</string>
<string name="download_notification_title">Downloading podcast data</string>
<string name="download_report_content">%1$d downloads succeeded, %2$d failed</string>
- <string name="download_log_title_unknown">Unknown title</string>
+ <string name="download_log_title_unknown">Unknown Title</string>
<string name="download_type_feed">Feed</string>
<string name="download_type_media">Media file</string>
<string name="download_type_image">Image</string>
@@ -181,9 +201,9 @@
<string name="unknown_media_key">AntennaPod - Unknown media key: %1$d</string>
<!-- Queue operations -->
- <string name="lock_queue">Lock queue</string>
- <string name="unlock_queue">Unlock queue</string>
- <string name="clear_queue_label">Clear queue</string>
+ <string name="lock_queue">Lock Queue</string>
+ <string name="unlock_queue">Unlock Queue</string>
+ <string name="clear_queue_label">Clear Queue</string>
<string name="undo">Undo</string>
<string name="removed_from_queue">Item removed</string>
<string name="move_to_top_label">Move to top</string>
@@ -249,38 +269,48 @@
<string name="pref_smart_mark_as_played_title">Smart mark as played</string>
<string name="playback_pref">Playback</string>
<string name="network_pref">Network</string>
- <string name="pref_autoUpdateIntervall_title">Update interval</string>
- <string name="pref_autoUpdateIntervall_sum">Specify an interval in which the feeds are refreshed automatically or disable it</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Update Interval or Time of Day</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Specify an interval or a specific time of day to refresh the feeds automatically</string>
+ <string name="pref_autoUpdateIntervallOrTime_message">You can set an <i>interval</i> like \"every 2 hours\", set a specific <i>time of day</i> like \"7:00 AM\" or <i>disable</i> automatic updates altogether.\n\n<small>Please note: Update times are inexact. You may encounter a short delay.</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_Disable">Disable</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Set Interval</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Set Time of Day</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Download media files only over WiFi</string>
- <string name="pref_followQueue_title">Continuous playback</string>
+ <string name="pref_followQueue_title">Continuous Playback</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi media download</string>
- <string name="pref_pauseOnHeadsetDisconnect_title">Headphones disconnect</string>
- <string name="pref_unpauseOnHeadsetReconnect_title">Headphones reconnect</string>
- <string name="pref_mobileUpdate_title">Mobile updates</string>
+ <string name="pref_pauseOnHeadsetDisconnect_title">Headphones Disconnect</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Headphones Reconnect</string>
+ <string name="pref_mobileUpdate_title">Mobile Updates</string>
<string name="pref_mobileUpdate_sum">Allow updates over the mobile data connection</string>
<string name="refreshing_label">Refreshing</string>
<string name="flattr_settings_label">Flattr settings</string>
<string name="pref_flattr_auth_title">Flattr sign-in</string>
<string name="pref_flattr_auth_sum">Sign in to your flattr account to flattr things directly from the app.</string>
- <string name="pref_flattr_this_app_title">Flattr this app</string>
+ <string name="pref_flattr_this_app_title">Flattr this App</string>
<string name="pref_flattr_this_app_sum">Support the development of AntennaPod by flattring it. Thanks!</string>
<string name="pref_revokeAccess_title">Revoke access</string>
<string name="pref_revokeAccess_sum">Revoke the access permission to your flattr account for this app.</string>
<string name="pref_auto_flattr_title">Automatic Flattr</string>
<string name="pref_auto_flattr_sum">Configure automatic flattring</string>
<string name="user_interface_label">User Interface</string>
- <string name="pref_set_theme_title">Select theme</string>
- <string name="pref_nav_drawer_items_title">Change navigation drawer</string>
+ <string name="pref_set_theme_title">Select Theme</string>
+ <string name="pref_nav_drawer_title">Customize Navigation Drawer</string>
+ <string name="pref_nav_drawer_sum">Customize the appearance of the navigation drawer.</string>
+ <string name="pref_nav_drawer_items_title">Set Navigation Drawer items</string>
<string name="pref_nav_drawer_items_sum">Change which items appear in the navigation drawer.</string>
+ <string name="pref_nav_drawer_feed_order_title">Set Subscription Order</string>
+ <string name="pref_nav_drawer_feed_order_sum">Change the order of your subscriptions</string>
+ <string name="pref_nav_drawer_feed_counter_title">Set Subscription Counter</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Change the information displayed by the subscription counter</string>
<string name="pref_set_theme_sum">Change the appearance of AntennaPod.</string>
- <string name="pref_automatic_download_title">Automatic download</string>
+ <string name="pref_automatic_download_title">Automatic Download</string>
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
<string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string>
<string name="pref_autodl_wifi_filter_sum">Allow automatic download only for selected Wi-Fi networks.</string>
<string name="pref_automatic_download_on_battery_title">Download when not charging</string>
<string name="pref_automatic_download_on_battery_sum">Allow automatic download when the battery is not charging</string>
- <string name="pref_parallel_downloads_title">Parallel downloads</string>
- <string name="pref_episode_cache_title">Episode cache</string>
+ <string name="pref_parallel_downloads_title">Parallel Downloads</string>
+ <string name="pref_episode_cache_title">Episode Cache</string>
<string name="pref_theme_title_light">Light</string>
<string name="pref_theme_title_dark">Dark</string>
<string name="pref_episode_cache_unlimited">Unlimited</string>
@@ -301,13 +331,16 @@
<string name="pref_gpodnet_sethostname_use_default_host">Use default host</string>
<string name="pref_expandNotify_title">Expand Notification</string>
<string name="pref_expandNotify_sum">Always expand the notification to show playback buttons.</string>
- <string name="pref_persistNotify_title">Persistent playback controls</string>
+ <string name="pref_persistNotify_title">Persistent Playback Controls</string>
<string name="pref_persistNotify_sum">Keep notification and lockscreen controls when playback is paused.</string>
+ <string name="pref_showDownloadReport_title">Show Download Report</string>
+ <string name="pref_showDownloadReport_sum">If downloads fail, generate a report that shows the details of the failure.</string>
<string name="pref_expand_notify_unsupport_toast">Android versions before 4.1 do not support expanded notifications.</string>
<string name="pref_queueAddToFront_sum">Add new episodes to the front of the queue.</string>
- <string name="pref_queueAddToFront_title">Enqueue at front.</string>
+ <string name="pref_queueAddToFront_title">Enqueue at Front</string>
<string name="pref_smart_mark_as_played_disabled">Disabled</string>
-
+ <string name="pref_image_cache_size_title">Image Cache Size</string>
+ <string name="pref_image_cache_size_sum">Size of the disk cache for images.</string>
<!-- Auto-Flattr dialog -->
<string name="auto_flattr_enable">Enable automatic flattring</string>
@@ -328,19 +361,20 @@
<string name="opml_import_explanation_1">Choose a specific file path from the local filesystem.</string>
<string name="opml_import_explanation_2">Use an external applications like Dropbox, Google Drive or your favourite file manager to open an OPML file.</string>
<string name="opml_import_explanation_3">Many applications like Google Mail, Dropbox, Google Drive and most file managers can <i>open</i> OPML files <i>with</i> AntennaPod.</string> <string name="start_import_label">Start import</string>
- <string name="opml_import_label">OPML import</string>
+ <string name="opml_import_label">OPML Import</string>
<string name="opml_directory_error">ERROR!</string>
<string name="reading_opml_label">Reading OPML file</string>
<string name="opml_reader_error">An error has occurred while reading the opml document:</string>
<string name="opml_import_error_dir_empty">The import directory is empty.</string>
<string name="select_all_label">Select all</string>
<string name="deselect_all_label">Deselect all</string>
+ <string name="select_options_label">Select ...</string>
<string name="choose_file_from_filesystem">From local filesystem</string>
<string name="choose_file_from_external_application">Use external application</string>
<string name="opml_export_label">OPML export</string>
<string name="exporting_label">Exporting...</string>
<string name="export_error_label">Export error</string>
- <string name="opml_export_success_title">OPML export successful.</string>
+ <string name="opml_export_success_title">OPML Export successful.</string>
<string name="opml_export_success_sum">The .opml file was written to:\u0020</string>
<!-- Sleep timer -->
@@ -350,9 +384,21 @@
<string name="sleep_timer_label">Sleep timer</string>
<string name="time_left_label">Time left:\u0020</string>
<string name="time_dialog_invalid_input">Invalid input, time has to be an integer</string>
- <string name="time_unit_seconds">seconds</string>
- <string name="time_unit_minutes">minutes</string>
- <string name="time_unit_hours">hours</string>
+ <string name="time_seconds">seconds</string>
+ <string name="time_minutes">minutes</string>
+ <string name="time_hours">hours</string>
+ <plurals name="time_seconds_quantified">
+ <item quantity="one">1 second</item>
+ <item quantity="other">%d seconds</item>
+ </plurals>
+ <plurals name="time_minutes_quantified">
+ <item quantity="one">1 minute</item>
+ <item quantity="other">%d minutes</item>
+ </plurals>
+ <plurals name="time_hours_quantified">
+ <item quantity="one">1 hour</item>
+ <item quantity="other">%d hours</item>
+ </plurals>
<!-- gpodder.net -->
<string name="gpodnet_taglist_header">CATEGORIES</string>
@@ -388,7 +434,7 @@
<!-- Directory chooser -->
<string name="selected_folder_label">Selected folder:</string>
<string name="create_folder_label">Create folder</string>
- <string name="choose_data_directory">Choose data folder</string>
+ <string name="choose_data_directory">Choose Data Folder</string>
<string name="create_folder_msg">Create new folder with name "%1$s"?</string>
<string name="create_folder_success">Created new folder</string>
<string name="create_folder_error_no_write_access">Cannot write to this folder</string>
@@ -398,9 +444,10 @@
<string name="folder_not_empty_dialog_msg">The folder you have selected is not empty. Media downloads and other files will be placed directly in this folder. Continue anyway?</string>
<string name="set_to_default_folder">Choose default folder</string>
<string name="pref_pausePlaybackForFocusLoss_sum">Pause playback instead of lowering volume when another app wants to play sounds</string>
- <string name="pref_pausePlaybackForFocusLoss_title">Pause for interruptions</string>
+ <string name="pref_pausePlaybackForFocusLoss_title">Pause for Interruptions</string>
<string name="pref_resumeAfterCall_sum">Resume playback after a phone call completes</string>
- <string name="pref_resumeAfterCall_title">Resume after call</string>
+ <string name="pref_resumeAfterCall_title">Resume after Call</string>
+ <string name="pref_restart_required">AntennaPod has to be restarted for this change to take effect.</string>
<!-- Online feed view -->
<string name="subscribe_label">Subscribe</string>
@@ -431,8 +478,33 @@
<string name="authentication_label">Authentication</string>
<string name="authentication_descr">Change your username and password for this podcast and its episodes.</string>
+
+ <!-- Progress information -->
+ <string name="progress_upgrading_database">Upgrading the database</string>
+
<!-- AntennaPodSP -->
<string name="sp_apps_importing_feeds_msg">Importing subscriptions from single-purpose apps&#8230;</string>
<string name="search_itunes_label">Search iTunes</string>
+
+ <string name="select_label"><b>Select ...</b></string>
+ <string name="all_label">All</string>
+ <string name="selected_all_label">Selected all Episodes</string>
+ <string name="none_label">None</string>
+ <string name="deselected_all_label">Deselected all Episodes</string>
+ <string name="played_label">Played</string>
+ <string name="selected_played_label">Selected played Episodes</string>
+ <string name="unplayed_label">Unplayed</string>
+ <string name="selected_unplayed_label">Selected unplayed Episodes</string>
+ <string name="downloaded_label">Downloaded</string>
+ <string name="selected_downloaded_label">Selected downloaded Episodes</string>
+ <string name="not_downloaded_label">Not downloaded</string>
+ <string name="selected_not_downloaded_label">Selected not downloaded Episodes</string>
+ <string name="sort_title"><b>Sort by ...</b></string>
+ <string name="sort_title_a_z">Title (A \u2192 Z)</string>
+ <string name="sort_title_z_a">Title (Z \u2192 A)</string>
+ <string name="sort_date_new_old">Date (New \u2192 Old)</string>
+ <string name="sort_date_old_new">Date (Old \u2192 New)</string>
+ <string name="sort_duration_short_long">Duration (Short \u2192 Long)</string>
+ <string name="sort_duration_long_short">Duration (Long \u2192 Short)</string>
</resources>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index 8619869c8..85c908f64 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -263,7 +263,9 @@
<style name="BigBlurryBackground">
<item name="android:scaleType">centerCrop</item>
- <item name="android:tint">@color/image_readability_tint</item>
+ <!-- <item name="android:tint">@color/image_readability_tint</item> -->
+ <!-- Reactivate when Glide's tinting has been fixed for Android 5.x
+ Remove color filter from ItemlistFragment -->
</style>