diff options
author | ByteHamster <ByteHamster@users.noreply.github.com> | 2022-10-15 11:06:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-15 11:06:06 +0200 |
commit | 8ff9dd829aa24ef7f0581dadcf3726a64f289955 (patch) | |
tree | 2397eac221f3ea0f6c957804d7c85ad635cd2f48 | |
parent | 5dc3699361fd438a127beeafd49aa2c9b5269574 (diff) | |
parent | 7d0b0e57eeee5d7d958ab6f85cd37fa7f85f66ec (diff) | |
download | AntennaPod-8ff9dd829aa24ef7f0581dadcf3726a64f289955.zip |
Merge pull request #6147 from ByteHamster/shownotes-cleaner
Remove text colors from shownotes
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java | 7 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java | 4 | ||||
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/view/ShownotesWebView.java | 14 | ||||
-rw-r--r-- | core/src/main/java/de/danoeh/antennapod/core/util/gui/ShownotesCleaner.java (renamed from core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java) | 34 | ||||
-rw-r--r-- | core/src/test/java/de/danoeh/antennapod/core/util/gui/ShownotesCleanerTest.java (renamed from core/src/test/java/de/danoeh/antennapod/core/util/playback/TimelineTest.java) | 79 |
5 files changed, 76 insertions, 62 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 518450f92..8a7d2432a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -14,7 +14,7 @@ import androidx.fragment.app.Fragment; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.playback.PlaybackController; -import de.danoeh.antennapod.core.util.playback.Timeline; +import de.danoeh.antennapod.core.util.gui.ShownotesCleaner; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.model.playback.Playable; import de.danoeh.antennapod.view.ShownotesWebView; @@ -99,8 +99,9 @@ public class ItemDescriptionFragment extends Fragment { } DBReader.loadDescriptionOfFeedItem(feedMedia.getItem()); } - Timeline timeline = new Timeline(getActivity(), media.getDescription(), media.getDuration()); - emitter.onSuccess(timeline.processShownotes()); + ShownotesCleaner shownotesCleaner = new ShownotesCleaner( + getActivity(), media.getDescription(), media.getDuration()); + emitter.onSuccess(shownotesCleaner.processShownotes()); }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index 04aeef1c5..c80545bb2 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -58,7 +58,7 @@ import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.ui.common.CircularProgressBar; import de.danoeh.antennapod.ui.common.ThemeUtils; import de.danoeh.antennapod.core.util.playback.PlaybackController; -import de.danoeh.antennapod.core.util.playback.Timeline; +import de.danoeh.antennapod.core.util.gui.ShownotesCleaner; import de.danoeh.antennapod.view.ShownotesWebView; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -438,7 +438,7 @@ public class ItemFragment extends Fragment { if (feedItem != null && context != null) { int duration = feedItem.getMedia() != null ? feedItem.getMedia().getDuration() : Integer.MAX_VALUE; DBReader.loadDescriptionOfFeedItem(feedItem); - Timeline t = new Timeline(context, feedItem.getDescription(), duration); + ShownotesCleaner t = new ShownotesCleaner(context, feedItem.getDescription(), duration); webviewData = t.processShownotes(); } return feedItem; diff --git a/app/src/main/java/de/danoeh/antennapod/view/ShownotesWebView.java b/app/src/main/java/de/danoeh/antennapod/view/ShownotesWebView.java index 3f4cc17ae..9dc4a76c6 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/ShownotesWebView.java +++ b/app/src/main/java/de/danoeh/antennapod/view/ShownotesWebView.java @@ -30,7 +30,7 @@ import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.ShareUtils; -import de.danoeh.antennapod.core.util.playback.Timeline; +import de.danoeh.antennapod.core.util.gui.ShownotesCleaner; public class ShownotesWebView extends WebView implements View.OnLongClickListener { private static final String TAG = "ShownotesWebView"; @@ -73,8 +73,8 @@ public class ShownotesWebView extends WebView implements View.OnLongClickListene setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - if (Timeline.isTimecodeLink(url) && timecodeSelectedListener != null) { - timecodeSelectedListener.accept(Timeline.getTimecodeLinkTime(url)); + if (ShownotesCleaner.isTimecodeLink(url) && timecodeSelectedListener != null) { + timecodeSelectedListener.accept(ShownotesCleaner.getTimecodeLinkTime(url)); } else { IntentUtils.openInBrowser(getContext(), url); } @@ -137,8 +137,8 @@ public class ShownotesWebView extends WebView implements View.OnLongClickListene ViewCompat.setElevation(s.getView(), 100); s.show(); } else if (itemId == R.id.go_to_position_item) { - if (Timeline.isTimecodeLink(selectedUrl) && timecodeSelectedListener != null) { - timecodeSelectedListener.accept(Timeline.getTimecodeLinkTime(selectedUrl)); + if (ShownotesCleaner.isTimecodeLink(selectedUrl) && timecodeSelectedListener != null) { + timecodeSelectedListener.accept(ShownotesCleaner.getTimecodeLinkTime(selectedUrl)); } else { Log.e(TAG, "Selected go_to_position_item, but URL was no timecode link: " + selectedUrl); } @@ -157,9 +157,9 @@ public class ShownotesWebView extends WebView implements View.OnLongClickListene return; } - if (Timeline.isTimecodeLink(selectedUrl)) { + if (ShownotesCleaner.isTimecodeLink(selectedUrl)) { menu.add(Menu.NONE, R.id.go_to_position_item, Menu.NONE, R.string.go_to_position_label); - menu.setHeaderTitle(Converter.getDurationStringLong(Timeline.getTimecodeLinkTime(selectedUrl))); + menu.setHeaderTitle(Converter.getDurationStringLong(ShownotesCleaner.getTimecodeLinkTime(selectedUrl))); } else { Uri uri = Uri.parse(selectedUrl); final Intent intent = new Intent(Intent.ACTION_VIEW, uri); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/ShownotesCleaner.java index e125c7e66..dbb2815e2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/gui/ShownotesCleaner.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.util.playback; +package de.danoeh.antennapod.core.util.gui; import android.content.Context; import android.content.res.TypedArray; @@ -26,27 +26,26 @@ import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.util.Converter; /** - * Connects chapter information and shownotes of a shownotesProvider, for example by making it possible to use the - * shownotes to navigate to another position in the podcast or by highlighting certain parts of the shownotesProvider's - * shownotes. - * <p/> - * A timeline object needs a shownotesProvider from which the chapter information - * is retrieved and shownotes are generated. + * Cleans up and prepares shownotes: + * - Guesses time stamps to make them clickable + * - Removes some formatting */ -public class Timeline { +public class ShownotesCleaner { private static final String TAG = "Timeline"; private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/(\\d+)"); private static final String TIMECODE_LINK = "<a class=\"timecode\" href=\"antennapod://timecode/%d\">%s</a>"; private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b((\\d+):)?(\\d+):(\\d{2})\\b"); private static final Pattern LINE_BREAK_REGEX = Pattern.compile("<br */?>"); + private static final String CSS_COLOR = "(?<=(\\s|;|^))color\\s*:([^;])*;"; + private static final String CSS_COMMENT = "/\\*.*?\\*/"; private final String rawShownotes; private final String noShownotesLabel; private final int playableDuration; private final String webviewStyle; - public Timeline(Context context, @Nullable String rawShownotes, int playableDuration) { + public ShownotesCleaner(Context context, @Nullable String rawShownotes, int playableDuration) { this.rawShownotes = rawShownotes; noShownotesLabel = context.getString(R.string.no_shownotes_label); @@ -98,9 +97,8 @@ public class Timeline { } Document document = Jsoup.parse(shownotes); + cleanCss(document); document.head().appendElement("style").attr("type", "text/css").text(webviewStyle); - - // apply timecode links addTimecodes(document); return document.toString(); } @@ -193,4 +191,18 @@ public class Timeline { element.html(buffer.toString()); } } + + private void cleanCss(Document document) { + for (Element element : document.getAllElements()) { + if (element.hasAttr("style")) { + element.attr("style", element.attr("style").replaceAll(CSS_COLOR, "")); + } else if (element.tagName().equals("style")) { + element.html(cleanStyleTag(element.html())); + } + } + } + + public static String cleanStyleTag(String oldCss) { + return oldCss.replaceAll(CSS_COMMENT, "").replaceAll(CSS_COLOR, ""); + } } diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/playback/TimelineTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/gui/ShownotesCleanerTest.java index 987a75981..527d0e0a3 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/util/playback/TimelineTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/util/gui/ShownotesCleanerTest.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.util.playback; +package de.danoeh.antennapod.core.util.gui; import android.content.Context; @@ -7,14 +7,10 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -import de.danoeh.antennapod.core.storage.DBReader; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockedStatic; -import org.mockito.Mockito; import org.robolectric.RobolectricTestRunner; import static org.junit.Assert.assertEquals; @@ -23,25 +19,16 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** - * Test class for {@link Timeline}. + * Test class for {@link ShownotesCleaner}. */ @RunWith(RobolectricTestRunner.class) -public class TimelineTest { +public class ShownotesCleanerTest { private Context context; - MockedStatic<DBReader> dbReaderMock; @Before public void setUp() { context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - // mock DBReader, because Timeline.processShownotes() calls FeedItem.loadShownotes() - // which calls DBReader.loadDescriptionOfFeedItem(), but we don't need the database here - dbReaderMock = Mockito.mockStatic(DBReader.class); - } - - @After - public void tearDown() { - dbReaderMock.close(); } @Test @@ -50,7 +37,7 @@ public class TimelineTest { final long time = 3600 * 1000 * 10 + 60 * 1000 * 11 + 12 * 1000; String shownotes = "<p> Some test text with a timecode " + timeStr + " here.</p>"; - Timeline t = new Timeline(context, shownotes, Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -61,7 +48,7 @@ public class TimelineTest { final long time = 25 * 60 * 60 * 1000; String shownotes = "<p> Some test text with a timecode " + timeStr + " here.</p>"; - Timeline t = new Timeline(context, shownotes, Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -72,7 +59,7 @@ public class TimelineTest { final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; String shownotes = "<p> Some test text with a timecode " + timeStr + " here.</p>"; - Timeline t = new Timeline(context, shownotes, Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -83,7 +70,7 @@ public class TimelineTest { final long time = 10 * 60 * 1000 + 11 * 1000; String shownotes = "<p> Some test text with a timecode " + timeStr + " here.</p>"; - Timeline t = new Timeline(context, shownotes, 11 * 60 * 1000); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, 11 * 60 * 1000); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -94,7 +81,7 @@ public class TimelineTest { final long time = 2 * 60 * 60 * 1000 + 11 * 60 * 1000 + 12 * 1000; String shownotes = "<p> Some test text with a timecode " + timeStr + " here.</p>"; - Timeline t = new Timeline(context, shownotes, Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -105,7 +92,7 @@ public class TimelineTest { final long time = 60 * 1000 + 12 * 1000; String shownotes = "<p> Some test text with a timecode " + timeStr + " here.</p>"; - Timeline t = new Timeline(context, shownotes, 2 * 60 * 1000); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, 2 * 60 * 1000); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -116,7 +103,7 @@ public class TimelineTest { final int time = 2 * 60 * 60 * 1000 + 11 * 60 * 1000 + 12 * 1000; String shownotes = "<p> Some test text with a timecode " + timeStr + " here.</p>"; - Timeline t = new Timeline(context, shownotes, time); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, time); String res = t.processShownotes(); Document d = Jsoup.parse(res); assertEquals("Should not parse time codes that equal duration", 0, d.body().getElementsByTag("a").size()); @@ -128,7 +115,7 @@ public class TimelineTest { String shownotes = "<p> Some test text with a timecode " + timeStrings[0] + " here. Hey look another one " + timeStrings[1] + " here!</p>"; - Timeline t = new Timeline(context, shownotes, 2 * 60 * 60 * 1000); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, 2 * 60 * 60 * 1000); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{10 * 60 * 1000 + 12 * 1000, 60 * 60 * 1000 + 10 * 60 * 1000 + 12 * 1000}, timeStrings); @@ -142,7 +129,7 @@ public class TimelineTest { String shownotes = "<p> Some test text with a timecode " + timeStrings[0] + " here. Hey look another one " + timeStrings[1] + " here!</p>"; - Timeline t = new Timeline(context, shownotes, 3 * 60 * 60 * 1000); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, 3 * 60 * 60 * 1000); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{10 * 60 * 1000 + 12 * 1000, 2 * 60 * 1000 + 12 * 1000}, timeStrings); } @@ -153,7 +140,7 @@ public class TimelineTest { final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; String shownotes = "<p> Some test text with a timecode (" + timeStr + ") here.</p>"; - Timeline t = new Timeline(context, shownotes, Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -164,7 +151,7 @@ public class TimelineTest { final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; String shownotes = "<p> Some test text with a timecode [" + timeStr + "] here.</p>"; - Timeline t = new Timeline(context, shownotes, Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -175,7 +162,7 @@ public class TimelineTest { final long time = 3600 * 1000 * 10 + 60 * 1000 * 11; String shownotes = "<p> Some test text with a timecode <" + timeStr + "> here.</p>"; - Timeline t = new Timeline(context, shownotes, Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes, Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[]{time}, new String[]{timeStr}); } @@ -190,7 +177,7 @@ public class TimelineTest { } shownotes.append("here.</p>"); - Timeline t = new Timeline(context, shownotes.toString(), Integer.MAX_VALUE); + ShownotesCleaner t = new ShownotesCleaner(context, shownotes.toString(), Integer.MAX_VALUE); String res = t.processShownotes(); checkLinkCorrect(res, new long[0], new String[0]); } @@ -216,20 +203,34 @@ public class TimelineTest { @Test public void testIsTimecodeLink() { - assertFalse(Timeline.isTimecodeLink(null)); - assertFalse(Timeline.isTimecodeLink("http://antennapod/timecode/123123")); - assertFalse(Timeline.isTimecodeLink("antennapod://timecode/")); - assertFalse(Timeline.isTimecodeLink("antennapod://123123")); - assertFalse(Timeline.isTimecodeLink("antennapod://timecode/123123a")); - assertTrue(Timeline.isTimecodeLink("antennapod://timecode/123")); - assertTrue(Timeline.isTimecodeLink("antennapod://timecode/1")); + assertFalse(ShownotesCleaner.isTimecodeLink(null)); + assertFalse(ShownotesCleaner.isTimecodeLink("http://antennapod/timecode/123123")); + assertFalse(ShownotesCleaner.isTimecodeLink("antennapod://timecode/")); + assertFalse(ShownotesCleaner.isTimecodeLink("antennapod://123123")); + assertFalse(ShownotesCleaner.isTimecodeLink("antennapod://timecode/123123a")); + assertTrue(ShownotesCleaner.isTimecodeLink("antennapod://timecode/123")); + assertTrue(ShownotesCleaner.isTimecodeLink("antennapod://timecode/1")); } @Test public void testGetTimecodeLinkTime() { - assertEquals(-1, Timeline.getTimecodeLinkTime(null)); - assertEquals(-1, Timeline.getTimecodeLinkTime("http://timecode/123")); - assertEquals(123, Timeline.getTimecodeLinkTime("antennapod://timecode/123")); + assertEquals(-1, ShownotesCleaner.getTimecodeLinkTime(null)); + assertEquals(-1, ShownotesCleaner.getTimecodeLinkTime("http://timecode/123")); + assertEquals(123, ShownotesCleaner.getTimecodeLinkTime("antennapod://timecode/123")); + } + @Test + public void testCleanupColors() { + final String input = "/* /* */ .foo { text-decoration: underline;color:#f00;font-weight:bold;}" + + "#bar { text-decoration: underline;color:#f00;font-weight:bold; }" + + "div {text-decoration: underline; color /* */ : /* */ #f00 /* */; font-weight:bold; }" + + "#foobar { /* color: */ text-decoration: underline; /* color: */font-weight:bold /* ; */; }" + + "baz { background-color:#f00;border: solid 2px;border-color:#0f0;text-decoration: underline; }"; + final String expected = " .foo { text-decoration: underline;font-weight:bold;}" + + "#bar { text-decoration: underline;font-weight:bold; }" + + "div {text-decoration: underline; font-weight:bold; }" + + "#foobar { text-decoration: underline; font-weight:bold ; }" + + "baz { background-color:#f00;border: solid 2px;border-color:#0f0;text-decoration: underline; }"; + assertEquals(expected, ShownotesCleaner.cleanStyleTag(input)); } } |