Merge pull request #3796 from ByteHamster/html-export-design

Updated html export design
This commit is contained in:
H. Lehmann 2020-01-28 18:46:52 +01:00 committed by GitHub
commit 8ed2102c85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 170 additions and 145 deletions

View File

@ -45,7 +45,7 @@ public class DocumentFileExportWorker {
throw new IOException();
}
writer = new OutputStreamWriter(outputStream, LangUtils.UTF_8);
exportWriter.writeDocument(DBReader.getFeedList(), writer);
exportWriter.writeDocument(DBReader.getFeedList(), writer, context);
subscriber.onNext(output);
} catch (IOException e) {
subscriber.onError(e);

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.asynctask;
import android.content.Context;
import androidx.annotation.NonNull;
import android.util.Log;
@ -25,15 +26,17 @@ public class ExportWorker {
private final @NonNull ExportWriter exportWriter;
private final @NonNull File output;
private final Context context;
public ExportWorker(@NonNull ExportWriter exportWriter) {
public ExportWorker(@NonNull ExportWriter exportWriter, Context context) {
this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR),
DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension()));
DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension()), context);
}
private ExportWorker(@NonNull ExportWriter exportWriter, @NonNull File output) {
private ExportWorker(@NonNull ExportWriter exportWriter, @NonNull File output, Context context) {
this.exportWriter = exportWriter;
this.output = output;
this.context = context;
}
public Observable<File> exportObservable() {
@ -45,7 +48,7 @@ public class ExportWorker {
OutputStreamWriter writer = null;
try {
writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
exportWriter.writeDocument(DBReader.getFeedList(), writer);
exportWriter.writeDocument(DBReader.getFeedList(), writer, context);
subscriber.onNext(output);
} catch (IOException e) {
subscriber.onError(e);

View File

@ -171,7 +171,7 @@ public class StoragePreferencesFragment extends PreferenceFragmentCompat {
progressDialog.setIndeterminate(true);
progressDialog.show();
if (uri == null) {
Observable<File> observable = new ExportWorker(exportWriter).exportObservable();
Observable<File> observable = new ExportWorker(exportWriter, getContext()).exportObservable();
disposable = observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(output -> {

View File

@ -0,0 +1,85 @@
<?xml version='1.0' encoding='UTF-8' standalone='no' ?>
<html>
<head>
<title>AntennaPod Subscriptions</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
font-family: 'Lato', sans-serif;
font-weight: 300;
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
background: #3498db;
text-align: center;
padding: 10px;
}
h1 {
color: #fff;
font-weight: 300;
display: inline-block;
margin-top: 40px;
margin-bottom: 20px;
vertical-align: top;
}
ul {
text-align: center;
}
li {
width: 100%;
max-width: 500px;
display: block;
display: inline-flex;
padding: 10px;
}
li > div {
background: #fefefe;
padding: 10px;
display: inline-block;
width: 100%;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
text-align: left;
}
li span {
margin-top: 10px;
display: block;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
span a {
color: #3498db;
}
img {
width: 100px;
height: 100px;
margin-right: 10px;
}
li > div > img {
float: left;
}
li > div > p {
width: 100%;
}
body > a {
color: #ffffff;
display: inline-block;
margin-top: 10px;
clear:left;
}
</style>
</head>
<body>
<img src="https://antennapod.org/assets/img/antennapod-logo.png" />
<h1>AntennaPod Subscriptions</h1>
<ul>
{FEEDS}
</ul>
<a href="https://play.google.com/store/apps/details?id=de.danoeh.antennapod" target="_blank">Get AntennaPod</a>
</body>
</html>

View File

@ -93,7 +93,7 @@ public class OpmlBackupAgent extends BackupAgentHelper {
try {
// Write OPML
new OpmlWriter().writeDocument(DBReader.getFeedList(), writer);
new OpmlWriter().writeDocument(DBReader.getFeedList(), writer, mContext);
// Compare checksum of new and old file to see if we need to perform a backup at all
if (digester != null) {

View File

@ -11,8 +11,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.danoeh.antennapod.core.export;
import android.content.Context;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
@ -21,9 +23,9 @@ import de.danoeh.antennapod.core.feed.Feed;
public interface ExportWriter {
void writeDocument(List<Feed> feeds, Writer writer)
throws IllegalArgumentException, IllegalStateException, IOException;
void writeDocument(List<Feed> feeds, Writer writer, Context context)
throws IllegalArgumentException, IllegalStateException, IOException;
String fileExtension();
String fileExtension();
}

View File

@ -1,30 +0,0 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.danoeh.antennapod.core.export.html;
import de.danoeh.antennapod.core.export.CommonSymbols;
class HtmlSymbols extends CommonSymbols {
static final String HTML = "html";
static final String ORDERED_LIST = "ol";
static final String LIST_ITEM = "li";
static final String HEADING = "h1";
static final String LINK = "a";
static final String LINK_DESTINATION = "href";
}

View File

@ -1,77 +1,45 @@
package de.danoeh.antennapod.core.export.html;
import android.text.TextUtils;
import android.content.Context;
import android.util.Log;
import android.util.Xml;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import de.danoeh.antennapod.core.export.ExportWriter;
import de.danoeh.antennapod.core.feed.Feed;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.List;
import org.apache.commons.io.IOUtils;
/** Writes HTML documents. */
public class HtmlWriter implements ExportWriter {
private static final String TAG = "HtmlWriter";
private static final String ENCODING = "UTF-8";
private static final String HTML_TITLE = "AntennaPod Subscriptions";
/**
* Takes a list of feeds and a writer and writes those into an HTML
* document.
*
* @throws IOException
* @throws IllegalStateException
* @throws IllegalArgumentException
*/
@Override
public void writeDocument(List<Feed> feeds, Writer writer)
public void writeDocument(List<Feed> feeds, Writer writer, Context context)
throws IllegalArgumentException, IllegalStateException, IOException {
Log.d(TAG, "Starting to write document");
XmlSerializer xs = Xml.newSerializer();
xs.setFeature(HtmlSymbols.XML_FEATURE_INDENT_OUTPUT, true);
xs.setOutput(writer);
xs.startDocument(ENCODING, false);
xs.startTag(null, HtmlSymbols.HTML);
xs.startTag(null, HtmlSymbols.HEAD);
xs.startTag(null, HtmlSymbols.TITLE);
xs.text(HTML_TITLE);
xs.endTag(null, HtmlSymbols.TITLE);
xs.endTag(null, HtmlSymbols.HEAD);
InputStream templateStream = context.getAssets().open("html-export-template.html");
String template = IOUtils.toString(templateStream, "UTF-8");
String[] templateParts = template.split("\\{FEEDS\\}");
xs.startTag(null, HtmlSymbols.BODY);
xs.startTag(null, HtmlSymbols.HEADING);
xs.text(HTML_TITLE);
xs.endTag(null, HtmlSymbols.HEADING);
xs.startTag(null, HtmlSymbols.ORDERED_LIST);
writer.append(templateParts[0]);
for (Feed feed : feeds) {
xs.startTag(null, HtmlSymbols.LIST_ITEM);
xs.text(feed.getTitle());
if (!TextUtils.isEmpty(feed.getLink())) {
xs.text(" [");
xs.startTag(null, HtmlSymbols.LINK);
xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getLink());
xs.text("Website");
xs.endTag(null, HtmlSymbols.LINK);
xs.text("]");
}
xs.text(" [");
xs.startTag(null, HtmlSymbols.LINK);
xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getDownload_url());
xs.text("Feed");
xs.endTag(null, HtmlSymbols.LINK);
xs.text("]");
xs.endTag(null, HtmlSymbols.LIST_ITEM);
writer.append("<li><div><img src=\"");
writer.append(feed.getImageUrl());
writer.append("\" /><p>");
writer.append(feed.getTitle());
writer.append(" <span><a href=\"");
writer.append(feed.getLink());
writer.append("\">Website</a> • <a href=\"");
writer.append(feed.getDownload_url());
writer.append("\">Feed</a></span></p></div></li>\n");
}
xs.endTag(null, HtmlSymbols.ORDERED_LIST);
xs.endTag(null, HtmlSymbols.BODY);
xs.endTag(null, HtmlSymbols.HTML);
xs.endDocument();
writer.append(templateParts[1]);
Log.d(TAG, "Finished writing document");
}

View File

@ -1,5 +1,6 @@
package de.danoeh.antennapod.core.export.opml;
import android.content.Context;
import android.util.Log;
import android.util.Xml;
@ -17,62 +18,58 @@ import de.danoeh.antennapod.core.util.DateUtils;
/** Writes OPML documents. */
public class OpmlWriter implements ExportWriter {
private static final String TAG = "OpmlWriter";
private static final String ENCODING = "UTF-8";
private static final String OPML_VERSION = "2.0";
private static final String OPML_TITLE = "AntennaPod Subscriptions";
private static final String TAG = "OpmlWriter";
private static final String ENCODING = "UTF-8";
private static final String OPML_VERSION = "2.0";
private static final String OPML_TITLE = "AntennaPod Subscriptions";
/**
* Takes a list of feeds and a writer and writes those into an OPML
* document.
*
* @throws IOException
* @throws IllegalStateException
* @throws IllegalArgumentException
*/
@Override
public void writeDocument(List<Feed> feeds, Writer writer)
throws IllegalArgumentException, IllegalStateException, IOException {
Log.d(TAG, "Starting to write document");
XmlSerializer xs = Xml.newSerializer();
xs.setFeature(OpmlSymbols.XML_FEATURE_INDENT_OUTPUT, true);
xs.setOutput(writer);
/**
* Takes a list of feeds and a writer and writes those into an OPML
* document.
*/
@Override
public void writeDocument(List<Feed> feeds, Writer writer, Context context)
throws IllegalArgumentException, IllegalStateException, IOException {
Log.d(TAG, "Starting to write document");
XmlSerializer xs = Xml.newSerializer();
xs.setFeature(OpmlSymbols.XML_FEATURE_INDENT_OUTPUT, true);
xs.setOutput(writer);
xs.startDocument(ENCODING, false);
xs.startTag(null, OpmlSymbols.OPML);
xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION);
xs.startDocument(ENCODING, false);
xs.startTag(null, OpmlSymbols.OPML);
xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION);
xs.startTag(null, OpmlSymbols.HEAD);
xs.startTag(null, OpmlSymbols.TITLE);
xs.text(OPML_TITLE);
xs.endTag(null, OpmlSymbols.TITLE);
xs.startTag(null, OpmlSymbols.DATE_CREATED);
xs.text(DateUtils.formatRFC822Date(new Date()));
xs.endTag(null, OpmlSymbols.DATE_CREATED);
xs.endTag(null, OpmlSymbols.HEAD);
xs.startTag(null, OpmlSymbols.HEAD);
xs.startTag(null, OpmlSymbols.TITLE);
xs.text(OPML_TITLE);
xs.endTag(null, OpmlSymbols.TITLE);
xs.startTag(null, OpmlSymbols.DATE_CREATED);
xs.text(DateUtils.formatRFC822Date(new Date()));
xs.endTag(null, OpmlSymbols.DATE_CREATED);
xs.endTag(null, OpmlSymbols.HEAD);
xs.startTag(null, OpmlSymbols.BODY);
for (Feed feed : feeds) {
xs.startTag(null, OpmlSymbols.OUTLINE);
xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle());
xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle());
if (feed.getType() != null) {
xs.attribute(null, OpmlSymbols.TYPE, feed.getType());
}
xs.attribute(null, OpmlSymbols.XMLURL, feed.getDownload_url());
if (feed.getLink() != null) {
xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink());
}
xs.endTag(null, OpmlSymbols.OUTLINE);
}
xs.endTag(null, OpmlSymbols.BODY);
xs.endTag(null, OpmlSymbols.OPML);
xs.endDocument();
Log.d(TAG, "Finished writing document");
}
xs.startTag(null, OpmlSymbols.BODY);
for (Feed feed : feeds) {
xs.startTag(null, OpmlSymbols.OUTLINE);
xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle());
xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle());
if (feed.getType() != null) {
xs.attribute(null, OpmlSymbols.TYPE, feed.getType());
}
xs.attribute(null, OpmlSymbols.XMLURL, feed.getDownload_url());
if (feed.getLink() != null) {
xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink());
}
xs.endTag(null, OpmlSymbols.OUTLINE);
}
xs.endTag(null, OpmlSymbols.BODY);
xs.endTag(null, OpmlSymbols.OPML);
xs.endDocument();
Log.d(TAG, "Finished writing document");
}
public String fileExtension() {
return "opml";
}
public String fileExtension() {
return "opml";
}
}