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}
    + WebsiteMedia +
  • 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} + + WebsiteFeed + +

    \ 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