diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java
index 5275f5f7e..761d6246e 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/ImportExportPreferencesFragment.java
@@ -5,7 +5,6 @@ import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -25,6 +24,7 @@ import de.danoeh.antennapod.activity.SplashActivity;
import de.danoeh.antennapod.asynctask.DocumentFileExportWorker;
import de.danoeh.antennapod.asynctask.ExportWorker;
import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.export.favorites.FavoritesWriter;
import de.danoeh.antennapod.core.export.html.HtmlWriter;
import de.danoeh.antennapod.core.export.opml.OpmlWriter;
import de.danoeh.antennapod.core.storage.DatabaseExporter;
@@ -47,15 +47,18 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat {
private static final String PREF_HTML_EXPORT = "prefHtmlExport";
private static final String PREF_DATABASE_IMPORT = "prefDatabaseImport";
private static final String PREF_DATABASE_EXPORT = "prefDatabaseExport";
+ private static final String PREF_FAVORITE_EXPORT = "prefFavoritesExport";
private static final String DEFAULT_OPML_OUTPUT_NAME = "antennapod-feeds-%s.opml";
private static final String CONTENT_TYPE_OPML = "text/x-opml";
private static final String DEFAULT_HTML_OUTPUT_NAME = "antennapod-feeds-%s.html";
private static final String CONTENT_TYPE_HTML = "text/html";
+ private static final String DEFAULT_FAVORITES_OUTPUT_NAME = "antennapod-favorites-%s.html";
private static final int REQUEST_CODE_CHOOSE_OPML_EXPORT_PATH = 1;
private static final int REQUEST_CODE_CHOOSE_OPML_IMPORT_PATH = 2;
private static final int REQUEST_CODE_CHOOSE_HTML_EXPORT_PATH = 3;
private static final int REQUEST_CODE_RESTORE_DATABASE = 4;
private static final int REQUEST_CODE_BACKUP_DATABASE = 5;
+ private static final int REQUEST_CODE_CHOOSE_FAVORITES_EXPORT_PATH = 6;
private static final String DATABASE_EXPORT_FILENAME = "AntennaPodBackup-%s.db";
private Disposable disposable;
private ProgressDialog progressDialog;
@@ -125,6 +128,12 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat {
exportDatabase();
return true;
});
+ findPreference(PREF_FAVORITE_EXPORT).setOnPreferenceClickListener(
+ preference -> {
+ openExportPathPicker(CONTENT_TYPE_HTML, dateStampFilename(DEFAULT_FAVORITES_OUTPUT_NAME),
+ REQUEST_CODE_CHOOSE_FAVORITES_EXPORT_PATH, new FavoritesWriter());
+ return true;
+ });
}
private void exportWithWriter(ExportWriter exportWriter, final Uri uri) {
@@ -257,6 +266,8 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat {
exportWithWriter(new OpmlWriter(), uri);
} else if (requestCode == REQUEST_CODE_CHOOSE_HTML_EXPORT_PATH) {
exportWithWriter(new HtmlWriter(), uri);
+ } else if (requestCode == REQUEST_CODE_CHOOSE_FAVORITES_EXPORT_PATH) {
+ exportWithWriter(new FavoritesWriter(), uri);
} else if (requestCode == REQUEST_CODE_RESTORE_DATABASE) {
progressDialog.show();
disposable = Completable.fromAction(() -> DatabaseExporter.importBackup(uri, getContext()))
diff --git a/app/src/main/res/xml/preferences_import_export.xml b/app/src/main/res/xml/preferences_import_export.xml
index 12e27236d..383bff117 100644
--- a/app/src/main/res/xml/preferences_import_export.xml
+++ b/app/src/main/res/xml/preferences_import_export.xml
@@ -32,5 +32,9 @@
android:key="prefHtmlExport"
android:title="@string/html_export_label"
android:summary="@string/html_export_summary"/>
+
diff --git a/core/src/main/assets/html-export-favorites-item-template.html b/core/src/main/assets/html-export-favorites-item-template.html
new file mode 100644
index 000000000..83f06a458
--- /dev/null
+++ b/core/src/main/assets/html-export-favorites-item-template.html
@@ -0,0 +1,4 @@
+
+ {FAV_TITLE}
+ Website • Media
+
diff --git a/core/src/main/assets/html-export-feed-template.html b/core/src/main/assets/html-export-feed-template.html
new file mode 100644
index 000000000..0646d5953
--- /dev/null
+++ b/core/src/main/assets/html-export-feed-template.html
@@ -0,0 +1,7 @@
+
+
+ {FEED_TITLE}
+
+ Website • Feed
+
+
\ No newline at end of file
diff --git a/core/src/main/assets/html-export-template.html b/core/src/main/assets/html-export-template.html
index ddab27a43..19d63f6ca 100644
--- a/core/src/main/assets/html-export-template.html
+++ b/core/src/main/assets/html-export-template.html
@@ -1,7 +1,7 @@
- AntennaPod Subscriptions
+ AntennaPod {TITLE}
- AntennaPod Subscriptions
+ AntennaPod {TITLE}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java
new file mode 100644
index 000000000..60c38a391
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java
@@ -0,0 +1,132 @@
+package de.danoeh.antennapod.core.export.favorites;
+
+import android.content.Context;
+import android.util.Log;
+
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import de.danoeh.antennapod.core.export.ExportWriter;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.storage.DBReader;
+
+/** Writes saved favorites to file. */
+public class FavoritesWriter implements ExportWriter {
+ private static final String TAG = "FavoritesWriter";
+
+ private static final int PAGE_LIMIT = 100;
+
+ private static final String FAVORITE_TEMPLATE = "html-export-favorites-item-template.html";
+ private static final String FEED_TEMPLATE = "html-export-feed-template.html";
+ private static final String UTF_8 = "UTF-8";
+
+ @Override
+ public void writeDocument(List feeds, Writer writer, Context context)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ Log.d(TAG, "Starting to write document");
+
+ InputStream templateStream = context.getAssets().open("html-export-template.html");
+ String template = IOUtils.toString(templateStream, UTF_8);
+ template = template.replaceAll("\\{TITLE\\}", "Favorites");
+ String[] templateParts = template.split("\\{FEEDS\\}");
+
+ InputStream favTemplateStream = context.getAssets().open(FAVORITE_TEMPLATE);
+ String favTemplate = IOUtils.toString(favTemplateStream, UTF_8);
+
+ InputStream feedTemplateStream = context.getAssets().open(FEED_TEMPLATE);
+ String feedTemplate = IOUtils.toString(feedTemplateStream, UTF_8);
+
+ Map> favoriteByFeed = getFeedMap(getFavorites());
+
+ writer.append(templateParts[0]);
+
+ for (Long feedId : favoriteByFeed.keySet()) {
+ List favorites = favoriteByFeed.get(feedId);
+ writer.append("\n");
+ writeFeed(writer, favorites.get(0).getFeed(), feedTemplate);
+
+ writer.append("
\n");
+ for (FeedItem item : favorites) {
+ writeFavoriteItem(writer, item, favTemplate);
+ }
+ writer.append("
\n");
+ }
+
+ writer.append(templateParts[1]);
+
+ Log.d(TAG, "Finished writing document");
+ }
+
+ private List getFavorites() {
+ int page = 0;
+
+ List favoritesList = new ArrayList<>();
+ List favoritesPage;
+ do {
+ favoritesPage = DBReader.getFavoriteItemsList(page * PAGE_LIMIT, PAGE_LIMIT);
+ favoritesList.addAll(favoritesPage);
+ ++page;
+ } while (!favoritesPage.isEmpty() && favoritesPage.size() == PAGE_LIMIT);
+
+ // sort in descending order
+ Collections.sort(favoritesList, (lhs, rhs) -> rhs.getPubDate().compareTo(lhs.getPubDate()));
+
+ return favoritesList;
+ }
+
+ /**
+ * Group favorite episodes by feed, sorting them by publishing date in descending order.
+ *
+ * @param favoritesList {@code List} of all favorite episodes.
+ * @return A {@code Map} favorite episodes, keyed by feed ID.
+ */
+ private Map> getFeedMap(List favoritesList) {
+ Map> feedMap = new TreeMap<>();
+
+ for (FeedItem item : favoritesList) {
+ List feedEpisodes = feedMap.get(item.getFeedId());
+
+ if (feedEpisodes == null) {
+ feedEpisodes = new ArrayList<>();
+ feedMap.put(item.getFeedId(), feedEpisodes);
+ }
+
+ feedEpisodes.add(item);
+ }
+
+ return feedMap;
+ }
+
+ private void writeFeed(Writer writer, Feed feed, String feedTemplate) throws IOException {
+ String feedInfo = feedTemplate
+ .replace("{FEED_IMG}", feed.getImageUrl())
+ .replace("{FEED_TITLE}", feed.getTitle())
+ .replace("{FEED_LINK}", feed.getLink())
+ .replace("{FEED_WEBSITE}", feed.getDownload_url());
+
+ writer.append(feedInfo);
+ }
+
+ private void writeFavoriteItem(Writer writer, FeedItem item, String favoriteTemplate) throws IOException {
+ String favItem = favoriteTemplate
+ .replace("{FAV_TITLE}", item.getTitle().trim())
+ .replace("{FAV_WEBSITE}", item.getLink())
+ .replace("{FAV_MEDIA}", item.getMedia().getDownload_url());
+
+ writer.append(favItem);
+ }
+
+ @Override
+ public String fileExtension() {
+ return "html";
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java
index 93b66daed..3f34343ee 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java
@@ -25,6 +25,7 @@ public class HtmlWriter implements ExportWriter {
InputStream templateStream = context.getAssets().open("html-export-template.html");
String template = IOUtils.toString(templateStream, "UTF-8");
+ template = template.replaceAll("\\{TITLE\\}", "Subscriptions");
String[] templateParts = template.split("\\{FEEDS\\}");
writer.append(templateParts[0]);
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 2827f666e..93a21ef13 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -580,6 +580,8 @@
Select file to import
Import successful.\n\nPlease press OK to restart AntennaPod
This database was exported with a newer version of AntennaPod. Your current installation does not yet know how to handle this file.
+ Favorites export
+ Export saved favorites to file
Set sleep timer