Repository: AntennaPod/AntennaPod (language: java)

Issue:
Add/play single episode without subscribing to podcast
# Checklist
<!-- Place an x in the boxes to tick them: [x] -->

- [x] I have used the search function to see if someone else has already submitted the same feature request.
- [x] I will only create one feature request per issue.
- [x] I will describe the problem with as much detail as possible.

# System info

**App version**: 2.0.3

**App source**:  F-Droid

# Feature description

**Problem you may be having, or feature you want**:

After recommending AntennaPod to a friend, the friend is really happy with the application and use it to listen to regular podcast shows, some of them in auto-download, some of them cherry picking the episodes according to the description and title. 

I recommend a particular episode of a podcast I enjoy, which she doesn't follow, she says "great, I'll listen to it, but not right now, I'll add it to AntennaPod", but then she had the following reaction "Hey, why can't I add a single episode without having to subscribe to the whole podcast ?". And I thought this would be a nice feature in AntennaPod : not having to subscribe to a podcast which you won't follow or have to unsubscribe to later, and benefit from the "Queue" feature that enables one to "Listen later" to a single episode. 


**Suggested solution**:

In the podcast "Subscribe" menu, when the user clicks on an episode there is a "Preview" link which is useful to listen to it straight away, there could be an other link / button with "Download to listen later (without subscribing)".  

**Screenshots / Drawings / Technical details**:
<!-- If your request is about (or includes) changing or extending the UI, describe what the UI would look like and how the user would interact with it. -->

![Screenshot_20201123-094806](https://user-images.githubusercontent.com/108437/99943362-773d6a00-2d71-11eb-8b53-e739c724e6e6.png)




Discussion hints:
I suggest we don't work on this.    Without subscribing to a podcast, it's difficult to manage that 'dangling' episode in the app without the data structures behind the 'parent', which is the podcast. 

For example: for the episode that you download, we have to deal with the 'Open Podcast' menu because it has no where to go.

I suggest you 'share the episode' with your friend so they can use their email as a bookmarking feature
Now that support for virtual podcast from local folder is going to become possible maybe it could be used to allow this : 
- create a preview folder if it doesn't already exist and add it as a virtual podcast
- download the episode and put it in the preview local folder

Local folder for this would really be handy and I think could remove a lot of problem which were making this hard to do?
While that would work, it's not really good UX. Users could then not press the "open podcast" button to hear more from the same publishers. Also, deleting the downloaded file would also delete the listening status. In general, to store listening status, we always need the feed as well. I don't think we should add this as a half-working feature. (the reason why we can not really store state of individual episodes without a subscription is that AntennaPod is decentralized without a server that knows all episodes of all podcasts. You can read more about that on the forum: https://forum.antennapod.org/t/newbie-questions/84/2)

The easiest option is (as @tonytamsf wrote) to share the link to the episode file. In AntennaPod 2.1, you can add the downloads folder as a "virtual" podcast to have it directly in AntennaPod.

---

Why don't you just subscribe to the podcast and unsubscribe again when no longer interested? The number of clicks to delete a whole subscription is not much higher than the number of clicks to delete a download.
You can also just preview an episode without subscribing to it.
I vote that we close this issue @keunes ?
To be honest I find the use-case very relevant: it would be great if you could share a particular episode with a friend who could listen to it at a later point. Indeed temporarily subscribing is a workaround, but it doesn't feel great as a user (you have to remember to delete the feed afterwards, a cognitive burden).

I realise it's currently technically hardly possible to cater for this use-case elegantly, but I would opt to keep this feature request open.
Another idea to manage this :  
- wait for group folders to be implemented
- have a "no subscription" folder
- let user download episode without subscribing (instead of previewing) and add it to the queue
- behind the scenes subscribe to podcast, put it in "no subscription" folder
- make "no subscription" folder and podcasts in it invisible to user
- remove invisible subscriptions if there is no longer any related episodes in queue or in favorites
- like for normal subscriptions user can go to podcast screen from episode or player. When viewing podcast screen a subscribe button should be added so user can permanently subscribe. (Doing so, move subscription outside of "no subscription" folder)

Pros : 
- user can access to podcast normally from player or from episodes (but he won't be able to see it in subscriptions in lateral menu or in subscriptions screen)
- all information from podcast is available and accessible to AntennaPod like any other podcast
- It becomes easy for user to permanently subscribe
- apart from invisible group folder everything is the same

Cons : 
I fear that it could be complicated to manage an invisible folder group ☹️
@keunes thanks for this user centric approach. There is no rush for this feature. 
> behind the scenes subscribe to podcast, put it in "no subscription" folder

Yeah, I think that is the only good option we have. Would mean a lot of work, though (hide in episodes list, etc). Also, what happens if someone goes to the podcast page and downloads another episode of that podcast without subscribing? Do we delete the subscription only when no episode is marked as favorite? This feature sounds like it could lead to pretty big discussions about the behavior and quite a lot of confused users
Yes removing podcast should only happen when there is no more downloaded episode or episode in favorites.
Really all would be like any other podcasts for the user except he wouldn't be able to see it in subscriptions screen or in subscriptions list. As all others interaction will be exactly the same I don't think it will cause any confusion.
> what happens if someone goes to the podcast page and downloads another episode of that podcast without subscribing?

Either nothing special (episode gets added, nothing else changes), or - probably better - a dialog is shown saying that they're currently not subscribed and adding more episodes is not possible, offering to 'subscribe' (i.e. remove the 'not subscribed' tag).
This issue has been mentioned on **AntennaPod Forum**. There might be relevant details there:

https://forum.antennapod.org/t/is-there-a-way-to-download-podcasts-from-within-antennapod-without-subscribing/456/2

This issue has been mentioned on **AntennaPod Forum**. There might be relevant details there:

https://forum.antennapod.org/t/ability-to-download-queue-episodes-from-non-subscribed-podcast/691/2

This issue has been mentioned on **AntennaPod Forum**. There might be relevant details there:

https://forum.antennapod.org/t/downloading-just-one-episode-of-a-podcast/153/7

Play store review in favour of this:

[1](https://play.google.com/apps/publish?account=8008695526664634386#ReviewDetailsPlace:p=de.danoeh.antennapod&reviewid=gp:AOqpTOGmhirt-hw7-qwI6tNJ-UCLP3d0MMM8W7-bFNLP9wkA0PU6WGseoG-KnDQkuGGn7FZBKFarZr8PF0kaQvY)

> Browsing through podcasts that you have not yet subscribed to is very cumbersome. You would first have to subscribe to a podcast in order to watch the episodes normally and listen to them normally without this strange "rehearsal". Pictures / logos of the podcasts are only displayed if you have subscribed. So not to be used for me. 2 stars because it is open source..

[2](https://play.google.com/apps/publish?account=8008695526664634386#ReviewDetailsPlace:p=de.danoeh.antennapod&reviewid=gp:AOqpTOEcI_r2mtnsYsffAapPd9oNJx5s0vh4wdcoJszMUOhk1uYNjAYvfIPG2W1-NZwy_8iexwvaropY2JTEt4s)

> If I search for a podcast I see a list of the episodes but it won't let me sample one it seems like I have to subscribe first that doesn't work for me.

[3](https://play.google.com/apps/publish?account=8008695526664634386#ReviewDetailsPlace:p=de.danoeh.antennapod&reviewid=5fdaaa83-a0ec-492f-9e1a-e0a40183bec2)

> Would be nice to have backups via Google account and single episode download without subbing, but otherwise really nice..

[4](https://play.google.com/apps/publish?account=8008695526664634386#ReviewDetailsPlace:p=de.danoeh.antennapod&reviewid=fc78c156-b31b-4b81-bacb-ad276556336b)

> Could be perfect but missing a crucial feature; download episode(s) without having to subscribe to the whole podcast first...So annoying, why??.

[5](https://play.google.com/console/u/0/developers/8008695526664634386/app/4974638472012894302/user-feedback/review-details?reviewId=e5c79032-84ea-468d-b282-229a15264c0b&corpus=PUBLIC_REVIEWS)

> Good podcast app. Only issue is that it's unclear how to listen to podcasts that I'm not subscribed to.

[6](https://play.google.com/console/u/0/developers/8008695526664634386/app/4974638472012894302/user-feedback/review-details?reviewId=17fdf663-5922-451d-b74a-e019431e7082&corpus=PUBLIC_REVIEWS)
> I switched over to find a replacement for Google podcasts. tried several apps this one seems the most intuitive for Google Podcast users. I wish the queue was a little more prominent and I am still confused about how to download single episodes when not subscribed to a podcast. glad to have a new podcast player.
I really think that the only thing needed is triggering an invisible subscription for the user when he is adding an episode.

Podcast wouldn't show in subscriptions list but could be accessed through added episodes.
Unsubscribing should be automatic when there is no more episode in queue or starred / in favorites.

-> this way there would be minimum difference for AntennaPod and for user it would be as if subscribing for only an episode is not necessary

**Requested in #5643: ability to open a specific episode when it is shared (especially between AntennaPod users). Possible solutions are discussed there. Ideally support for this is implemented together with this issue.**
This issue has been mentioned on **AntennaPod Forum**. There might be relevant details there:

https://forum.antennapod.org/t/add-episode-from-podcasts-without-subscribing/1271/4

I recently started using this app and came across this issue, but I found a decent work-around. It is possible to subscribe to a podcast, download a single episode, and turn auto-refreshing off in the settings. I think that's good enough and similar to what other podcast applications do, what do you think of adding a shortcut for doing this?
Yeah, I think that's what the solution for this issue will look like. Internally, subscribe to it normally but disable auto-refreshing and put it in a folder called "not subscribed".
This issue has been mentioned on **AntennaPod Forum**. There might be relevant details there:

https://forum.antennapod.org/t/user-must-be-able-to-listen-to-the-podcast-without-subscribing/1853/2


Pull request: Add episodes without subscribing
### Description

Adding episodes to the queue without subscribing is a long running feature request. Doing this does not really make sense on a distributed podcast app. However, to make these people happy, subscribe to the feed internally anyway and just tell them that it is not subscribed.

Closes #4710

<img width="250" src="https://github.com/AntennaPod/AntennaPod/assets/5811634/1af5bcea-0c0a-4229-a0d8-3be904d61cfa" /> <img width="250" src="https://github.com/AntennaPod/AntennaPod/assets/5811634/16954398-ac84-4d9f-826b-3eefd84af00b" />

ToDo:
- [x] Do the "non-subscribed" feeds end up in opml/html exports?
- [x] Unsubscribe automatically after a while when no episode is queued or downloaded
- [x] Do the feeds end up on the sync server?
- [x] sync after subscribing
- [x] move subscribe code to dbwriter
- [x] searching on the podcast screen of a non subscribed one should work
- [x] use button "preview", not " view episodes"
- [x] show episodes list preview in online feed popup, not in normal app page. Then we can keep the buttons as they are and only display subscribe 
- [x] I think the current implementation might lead new users into never discovering the per podcast settings because there is no reason for them to ever subscribe. The app works just fine wirhout it. (Until at some point the playback states disappear, at which point they will blame AntennaPod) Show the settings button even for non subscribed podcasts but then refuse to open the settings ("Subscribe to change settings"). Maybe that is more of a nudge than simply not displaying the settings button 
- [x] With a very fast network connection, the non subscribed podcasts open almost immediately. That might make users think that the additional popup (old onlinefeedview) is just the way navigation works in AntennaPod. If a podcast is already in the database but not subscribe, delay loading the page such that they see that everything goes faster once subscribed. Something like 3 seconds could work (minus the time it takes to actually load)

Earlier ideas, maybe not for now
- [x] Maybe display some text like "the playback state of non-subscribed podcasts is removed after a while. Press "subscribe" to fully add the podcast to AntennaPod".

### Checklist
<!-- 
  To help us keep the issue tracker clean and work as efficient as possible,
  please make sure that you have done all of the following.
  You can tick the boxes below by placing an x inside the brackets like this: [x]
-->
- [x] I have read the contribution guidelines: https://github.com/AntennaPod/AntennaPod/blob/develop/CONTRIBUTING.md#submit-a-pull-request
- [x] I have performed a self-review of my code
- [x] I have run the automated code checks using `./gradlew checkstyle spotbugsPlayDebug spotbugsDebug :app:lintPlayDebug`
- [x] My code follows the style guidelines of the AntennaPod project: https://github.com/AntennaPod/AntennaPod/wiki/Code-style
- [x] I have mentioned the corresponding issue and the relevant keyword (e.g., "Closes: #xy") in the description (see https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
- [x] If it is a core feature, I have added automated tests


Test command: ./gradlew :storage:database:testFreeDebugUnitTest --tests "de.danoeh.antennapod.storage.database.NonSubscribedFeedsCleanerTest"

Fix patch:
diff --git a/app/src/main/java/de/danoeh/antennapod/actionbutton/ItemActionButton.java b/app/src/main/java/de/danoeh/antennapod/actionbutton/ItemActionButton.java
index 84b24616705..54714be3d17 100644
--- a/app/src/main/java/de/danoeh/antennapod/actionbutton/ItemActionButton.java
+++ b/app/src/main/java/de/danoeh/antennapod/actionbutton/ItemActionButton.java
@@ -7,6 +7,7 @@
 import androidx.annotation.StringRes;
 import android.view.View;
 
+import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.playback.service.PlaybackStatus;
 import de.danoeh.antennapod.model.feed.FeedItem;
 import de.danoeh.antennapod.model.feed.FeedMedia;
@@ -48,6 +49,8 @@ public static ItemActionButton forItem(@NonNull FeedItem item) {
             return new PlayActionButton(item);
         } else if (isDownloadingMedia) {
             return new CancelDownloadActionButton(item);
+        } else if (item.getFeed().getState() != Feed.STATE_SUBSCRIBED) {
+            return new StreamActionButton(item);
         } else if (UserPreferences.isStreamOverDownload()) {
             return new StreamActionButton(item);
         } else {
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemListAdapter.java b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemListAdapter.java
index 5082f25ffd3..db79912611f 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemListAdapter.java
@@ -12,6 +12,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
 import androidx.recyclerview.widget.RecyclerView;
 
 import de.danoeh.antennapod.ui.SelectableAdapter;
@@ -32,13 +33,13 @@
 public class EpisodeItemListAdapter extends SelectableAdapter<EpisodeItemViewHolder>
         implements View.OnCreateContextMenuListener {
 
-    private final WeakReference<MainActivity> mainActivityRef;
+    private final WeakReference<FragmentActivity> mainActivityRef;
     private List<FeedItem> episodes = new ArrayList<>();
     private FeedItem longPressedItem;
     int longPressedPosition = 0; // used to init actionMode
     private int dummyViews = 0;
 
-    public EpisodeItemListAdapter(MainActivity mainActivity) {
+    public EpisodeItemListAdapter(FragmentActivity mainActivity) {
         super(mainActivity);
         this.mainActivityRef = new WeakReference<>(mainActivity);
         setHasStableIds(true);
@@ -86,9 +87,18 @@ public final void onBindViewHolder(EpisodeItemViewHolder holder, int pos) {
         holder.bind(item);
 
         holder.itemView.setOnClickListener(v -> {
-            MainActivity activity = mainActivityRef.get();
-            if (activity != null && !inActionMode()) {
-                activity.loadChildFragment(ItemPagerFragment.newInstance(episodes, item));
+            if (!inActionMode()) {
+                if (mainActivityRef.get() instanceof MainActivity) {
+                    ((MainActivity) mainActivityRef.get())
+                            .loadChildFragment(ItemPagerFragment.newInstance(episodes, item));
+                } else {
+                    ItemPagerFragment fragment = ItemPagerFragment.newInstance(episodes, item);
+                    mainActivityRef.get().getSupportFragmentManager()
+                            .beginTransaction()
+                            .replace(R.id.fragmentContainer, fragment, "Items")
+                            .addToBackStack("Items")
+                            .commitAllowingStateLoss();
+                }
             } else {
                 toggleSelection(holder.getBindingAdapterPosition());
             }
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemViewHolder.java b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemViewHolder.java
index dd1a10450ce..c5868a945fd 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemViewHolder.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeItemViewHolder.java
@@ -1,5 +1,6 @@
 package de.danoeh.antennapod.ui.episodeslist;
 
+import android.app.Activity;
 import android.os.Build;
 import android.text.Layout;
 import android.text.format.Formatter;
@@ -17,7 +18,6 @@
 import com.google.android.material.elevation.SurfaceColors;
 
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
 import de.danoeh.antennapod.ui.CoverLoader;
 import de.danoeh.antennapod.actionbutton.ItemActionButton;
 import de.danoeh.antennapod.playback.service.PlaybackStatus;
@@ -62,10 +62,10 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder {
     private final View leftPadding;
     public final CardView coverHolder;
 
-    private final MainActivity activity;
+    private final Activity activity;
     private FeedItem item;
 
-    public EpisodeItemViewHolder(MainActivity activity, ViewGroup parent) {
+    public EpisodeItemViewHolder(Activity activity, ViewGroup parent) {
         super(LayoutInflater.from(activity).inflate(R.layout.feeditemlist_item, parent, false));
         this.activity = activity;
         container = itemView.findViewById(R.id.container);
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeMultiSelectActionHandler.java b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeMultiSelectActionHandler.java
index 76ed47de537..a655982cbb3 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeMultiSelectActionHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/EpisodeMultiSelectActionHandler.java
@@ -1,29 +1,28 @@
 package de.danoeh.antennapod.ui.episodeslist;
 
+import android.app.Activity;
 import android.util.Log;
 
 import androidx.annotation.PluralsRes;
 
-import com.google.android.material.snackbar.Snackbar;
-
 import java.util.List;
 
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.event.MessageEvent;
 import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
 import de.danoeh.antennapod.storage.database.DBWriter;
 import de.danoeh.antennapod.storage.database.LongList;
 import de.danoeh.antennapod.model.feed.FeedItem;
 import de.danoeh.antennapod.ui.view.LocalDeleteModal;
+import org.greenrobot.eventbus.EventBus;
 
 public class EpisodeMultiSelectActionHandler {
     private static final String TAG = "EpisodeSelectHandler";
-    private final MainActivity activity;
+    private final Activity activity;
     private final int actionId;
     private int totalNumItems = 0;
-    private Snackbar snackbar = null;
 
-    public EpisodeMultiSelectActionHandler(MainActivity activity, int actionId) {
+    public EpisodeMultiSelectActionHandler(Activity activity, int actionId) {
         this.activity = activity;
         this.actionId = actionId;
     }
@@ -116,12 +115,7 @@ private void showMessage(@PluralsRes int msgId, int numItems) {
         totalNumItems += numItems;
         activity.runOnUiThread(() -> {
             String text = activity.getResources().getQuantityString(msgId, totalNumItems, totalNumItems);
-            if (snackbar != null) {
-                snackbar.setText(text);
-                snackbar.show(); // Resets the timeout
-            } else {
-                snackbar = activity.showSnackbarAbovePlayer(text, Snackbar.LENGTH_LONG);
-            }
+            EventBus.getDefault().post(new MessageEvent(text));
         });
     }
 
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/FeedItemMenuHandler.java
index e1974940c18..720e0ccbcda 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/episodeslist/FeedItemMenuHandler.java
@@ -16,6 +16,7 @@
 
 import de.danoeh.antennapod.R;
 import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.net.sync.serviceinterface.SynchronizationQueueSink;
 import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
 import de.danoeh.antennapod.playback.service.PlaybackServiceInterface;
@@ -84,6 +85,10 @@ public static boolean onPrepareMenu(Menu menu, FeedItem selectedItem) {
         setItemVisibility(menu, R.id.add_to_favorites_item, !isFavorite);
         setItemVisibility(menu, R.id.remove_from_favorites_item, isFavorite);
         setItemVisibility(menu, R.id.remove_item, fileDownloaded || isLocalFile);
+
+        if (selectedItem.getFeed().getState() != Feed.STATE_SUBSCRIBED) {
+            setItemVisibility(menu, R.id.mark_read_item, false);
+        }
         return true;
     }
 
@@ -158,7 +163,8 @@ public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItem
         } else if (menuItemId == R.id.mark_read_item) {
             selectedItem.setPlayed(true);
             DBWriter.markItemPlayed(selectedItem, FeedItem.PLAYED, true);
-            if (!selectedItem.getFeed().isLocalFeed() && SynchronizationSettings.isProviderConnected()) {
+            if (!selectedItem.getFeed().isLocalFeed() && selectedItem.getFeed().getState() == Feed.STATE_SUBSCRIBED
+                    && SynchronizationSettings.isProviderConnected()) {
                 FeedMedia media = selectedItem.getMedia();
                 // not all items have media, Gpodder only cares about those that do
                 if (media != null) {
@@ -174,7 +180,8 @@ public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItem
         } else if (menuItemId == R.id.mark_unread_item) {
             selectedItem.setPlayed(false);
             DBWriter.markItemPlayed(selectedItem, FeedItem.UNPLAYED, false);
-            if (!selectedItem.getFeed().isLocalFeed() && selectedItem.getMedia() != null) {
+            if (!selectedItem.getFeed().isLocalFeed() && selectedItem.getMedia() != null
+                    && selectedItem.getFeed().getState() == Feed.STATE_SUBSCRIBED) {
                 EpisodeAction actionNew = new EpisodeAction.Builder(selectedItem, EpisodeAction.NEW)
                         .currentTimestamp()
                         .build();
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/AllEpisodesFragment.java
index eb49c94d93a..6e48ade3978 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/AllEpisodesFragment.java
@@ -66,7 +66,12 @@ protected int loadTotalItemCount() {
 
     @Override
     protected FeedItemFilter getFilter() {
-        return new FeedItemFilter(UserPreferences.getPrefFilterAllEpisodes());
+        FeedItemFilter filter = new FeedItemFilter(UserPreferences.getPrefFilterAllEpisodes());
+        if (filter.showIsFavorite) {
+            return new FeedItemFilter(filter, FeedItemFilter.INCLUDE_NOT_SUBSCRIBED);
+        } else {
+            return filter;
+        }
     }
 
     @Override
@@ -91,6 +96,7 @@ public boolean onMenuItemClick(MenuItem item) {
             ArrayList<String> filter = new ArrayList<>(getFilter().getValuesList());
             if (filter.contains(FeedItemFilter.IS_FAVORITE)) {
                 filter.remove(FeedItemFilter.IS_FAVORITE);
+                filter.remove(FeedItemFilter.INCLUDE_NOT_SUBSCRIBED);
             } else {
                 filter.add(FeedItemFilter.IS_FAVORITE);
             }
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/PlaybackHistoryFragment.java
index a02f86bd21a..abdf043b1ec 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/PlaybackHistoryFragment.java
@@ -23,7 +23,8 @@
 
 public class PlaybackHistoryFragment extends EpisodesListFragment {
     public static final String TAG = "PlaybackHistoryFragment";
-    private static final FeedItemFilter FILTER_HISTORY = new FeedItemFilter(FeedItemFilter.IS_IN_HISTORY);
+    private static final FeedItemFilter FILTER_HISTORY = new FeedItemFilter(
+            FeedItemFilter.IS_IN_HISTORY, FeedItemFilter.INCLUDE_NOT_SUBSCRIBED);
 
     @NonNull
     @Override
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/download/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/download/CompletedDownloadsFragment.java
index 001c2b4658a..0d82b713307 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/download/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/download/CompletedDownloadsFragment.java
@@ -285,7 +285,7 @@ private void loadItems() {
         disposable = Observable.fromCallable(() -> {
             SortOrder sortOrder = UserPreferences.getDownloadsSortedOrder();
             List<FeedItem> downloadedItems = DBReader.getEpisodes(0, Integer.MAX_VALUE,
-                        new FeedItemFilter(FeedItemFilter.DOWNLOADED), sortOrder);
+                    new FeedItemFilter(FeedItemFilter.DOWNLOADED, FeedItemFilter.INCLUDE_NOT_SUBSCRIBED), sortOrder);
 
             List<String> mediaUrls = new ArrayList<>();
             if (runningDownloads == null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemFragment.java
index e31004a57f7..a5ee78a58ca 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemFragment.java
@@ -38,6 +38,7 @@
 import de.danoeh.antennapod.actionbutton.StreamActionButton;
 import de.danoeh.antennapod.actionbutton.VisitWebsiteActionButton;
 import de.danoeh.antennapod.event.EpisodeDownloadEvent;
+import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.playback.service.PlaybackStatus;
 import de.danoeh.antennapod.event.FeedItemEvent;
 import de.danoeh.antennapod.event.PlayerStatusEvent;
@@ -49,6 +50,7 @@
 import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
 import de.danoeh.antennapod.storage.preferences.UserPreferences;
 import de.danoeh.antennapod.storage.database.DBReader;
+import de.danoeh.antennapod.ui.appstartintent.OnlineFeedviewActivityStarter;
 import de.danoeh.antennapod.ui.common.Converter;
 import de.danoeh.antennapod.ui.common.DateFormatter;
 import de.danoeh.antennapod.ui.common.CircularProgressBar;
@@ -114,6 +116,7 @@ public static ItemFragment newInstance(long feeditem) {
     private ItemActionButton actionButton1;
     private ItemActionButton actionButton2;
     private View noMediaLabel;
+    private View nonSubscribedWarningLabel;
 
     private Disposable disposable;
     private PlaybackController controller;
@@ -164,6 +167,7 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
         butAction1Text = layout.findViewById(R.id.butAction1Text);
         butAction2Text = layout.findViewById(R.id.butAction2Text);
         noMediaLabel = layout.findViewById(R.id.noMediaLabel);
+        nonSubscribedWarningLabel = layout.findViewById(R.id.nonSubscribedWarningLabel);
 
         butAction1.setOnClickListener(v -> {
             if (actionButton1 instanceof StreamActionButton && !UserPreferences.isStreamOverDownload()
@@ -287,6 +291,11 @@ private void updateAppearance() {
             txtvPublished.setContentDescription(DateFormatter.formatForAccessibility(item.getPubDate()));
         }
 
+        if (item.getFeed().getState() != Feed.STATE_SUBSCRIBED) {
+            nonSubscribedWarningLabel.setVisibility(View.VISIBLE);
+            nonSubscribedWarningLabel.setOnClickListener(v -> openPodcast());
+        }
+
         float radius = 8 * getResources().getDisplayMetrics().density;
         RequestOptions options = new RequestOptions()
                 .error(ImagePlaceholder.getDrawable(getContext(), radius))
@@ -366,8 +375,13 @@ private void openPodcast() {
         if (item == null) {
             return;
         }
-        Fragment fragment = FeedItemlistFragment.newInstance(item.getFeedId());
-        ((MainActivity) getActivity()).loadChildFragment(fragment);
+        if (item.getFeed().getState() == Feed.STATE_SUBSCRIBED) {
+            Fragment fragment = FeedItemlistFragment.newInstance(item.getFeedId());
+            ((MainActivity) getActivity()).loadChildFragment(fragment);
+        } else {
+            startActivity(new OnlineFeedviewActivityStarter(getContext(), item.getFeed().getDownloadUrl())
+                    .getIntent());
+        }
     }
 
     @Subscribe(threadMode = ThreadMode.MAIN)
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemPagerFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemPagerFragment.java
index e7f34561752..951e5affb59 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemPagerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/episode/ItemPagerFragment.java
@@ -1,5 +1,6 @@
 package de.danoeh.antennapod.ui.screen.episode;
 
+import android.content.Intent;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -13,7 +14,8 @@
 import androidx.viewpager2.adapter.FragmentStateAdapter;
 import androidx.viewpager2.widget.ViewPager2;
 
-import de.danoeh.antennapod.ui.screen.feed.FeedItemlistFragment;
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.ui.appstartintent.OnlineFeedviewActivityStarter;
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.Subscribe;
 import org.greenrobot.eventbus.ThreadMode;
@@ -173,8 +175,12 @@ private void openPodcast() {
         if (item == null) {
             return;
         }
-        Fragment fragment = FeedItemlistFragment.newInstance(item.getFeedId());
-        ((MainActivity) getActivity()).loadChildFragment(fragment);
+        if (item.getFeed().getState() == Feed.STATE_SUBSCRIBED) {
+            Intent intent = MainActivity.getIntentToOpenFeed(getContext(), item.getFeedId());
+            startActivity(intent);
+        } else {
+            startActivity(new OnlineFeedviewActivityStarter(getContext(), item.getFeed().getDownloadUrl()).getIntent());
+        }
     }
 
     private class ItemPagerAdapter extends FragmentStateAdapter {
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedInfoFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedInfoFragment.java
index aabb0852e26..f73b69d7529 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedInfoFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedInfoFragment.java
@@ -122,7 +122,6 @@ protected void doTint(Context themedContext) {
         viewBinding.header.butFilter.setVisibility(View.INVISIBLE);
         // https://github.com/bumptech/glide/issues/529
         viewBinding.imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
-
         viewBinding.urlLabel.setOnClickListener(copyUrlToClipboard);
 
         long feedId = getArguments().getLong(EXTRA_FEED_ID);
@@ -237,6 +236,25 @@ private void showFeed() {
             viewBinding.supportUrl.setText(str.toString());
         }
 
+        if (feed.getState() == Feed.STATE_SUBSCRIBED) {
+            long feedId = getArguments().getLong(EXTRA_FEED_ID);
+            getParentFragmentManager().beginTransaction().replace(R.id.statisticsFragmentContainer,
+                            FeedStatisticsFragment.newInstance(feedId, false), "feed_statistics_fragment")
+                    .commitAllowingStateLoss();
+
+            viewBinding.statisticsButton.setOnClickListener(view -> {
+                StatisticsFragment fragment = new StatisticsFragment();
+                ((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.SLIDE);
+            });
+        } else {
+            viewBinding.statisticsButton.setVisibility(View.GONE);
+            viewBinding.statisticsFragmentContainer.setVisibility(View.GONE);
+            viewBinding.statisticsHeadingLabel.setVisibility(View.GONE);
+            viewBinding.supportHeadingLabel.setVisibility(View.GONE);
+            viewBinding.supportUrl.setVisibility(View.GONE);
+            viewBinding.descriptionHeadingLabel.setVisibility(View.GONE);
+        }
+
         refreshToolbarState();
     }
 
@@ -249,13 +267,14 @@ public void onDestroy() {
     }
 
     private void refreshToolbarState() {
+        boolean isSubscribed = feed != null && feed.getState() == Feed.STATE_SUBSCRIBED;
         viewBinding.toolbar.getMenu().findItem(R.id.reconnect_local_folder).setVisible(
-                feed != null && feed.isLocalFeed());
-        viewBinding.toolbar.getMenu().findItem(R.id.share_item).setVisible(feed != null && !feed.isLocalFeed());
-        viewBinding.toolbar.getMenu().findItem(R.id.visit_website_item).setVisible(feed != null
+                isSubscribed && feed.isLocalFeed());
+        viewBinding.toolbar.getMenu().findItem(R.id.share_item).setVisible(isSubscribed && !feed.isLocalFeed());
+        viewBinding.toolbar.getMenu().findItem(R.id.visit_website_item).setVisible(isSubscribed
                 && feed.getLink() != null
                 && IntentUtils.isCallable(getContext(), new Intent(Intent.ACTION_VIEW, Uri.parse(feed.getLink()))));
-        viewBinding.toolbar.getMenu().findItem(R.id.edit_feed_url_item).setVisible(feed != null && !feed.isLocalFeed());
+        viewBinding.toolbar.getMenu().findItem(R.id.edit_feed_url_item).setVisible(isSubscribed && !feed.isLocalFeed());
     }
 
     @Override
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedItemlistFragment.java
index 9bc45a235f4..2167887d51c 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/feed/FeedItemlistFragment.java
@@ -12,52 +12,23 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
-import android.widget.Toast;
-
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.core.util.Pair;
 import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
 import androidx.recyclerview.widget.RecyclerView;
-
 import com.bumptech.glide.Glide;
 import com.bumptech.glide.request.RequestOptions;
 import com.google.android.material.appbar.MaterialToolbar;
 import com.google.android.material.snackbar.Snackbar;
-
-import de.danoeh.antennapod.ui.CoverLoader;
-import de.danoeh.antennapod.ui.screen.episode.ItemPagerFragment;
-import de.danoeh.antennapod.ui.screen.SearchFragment;
-import de.danoeh.antennapod.ui.TransitionEffect;
-import de.danoeh.antennapod.net.download.serviceinterface.FeedUpdateManager;
-import de.danoeh.antennapod.ui.screen.download.DownloadLogFragment;
-import de.danoeh.antennapod.ui.screen.feed.preferences.FeedSettingsFragment;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.Validate;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
 import de.danoeh.antennapod.R;
 import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.ui.episodeslist.EpisodeItemListAdapter;
-import de.danoeh.antennapod.event.FeedEvent;
-import de.danoeh.antennapod.ui.MenuItemUtils;
-import de.danoeh.antennapod.storage.database.DBReader;
-import de.danoeh.antennapod.storage.database.DBWriter;
-import de.danoeh.antennapod.ui.common.IntentUtils;
-import de.danoeh.antennapod.ui.share.ShareUtils;
-import de.danoeh.antennapod.ui.episodeslist.MoreContentListFooterUtil;
 import de.danoeh.antennapod.databinding.FeedItemListFragmentBinding;
-import de.danoeh.antennapod.ui.screen.download.DownloadLogDetailsDialog;
-import de.danoeh.antennapod.ui.FeedItemFilterDialog;
 import de.danoeh.antennapod.event.EpisodeDownloadEvent;
 import de.danoeh.antennapod.event.FavoritesEvent;
+import de.danoeh.antennapod.event.FeedEvent;
 import de.danoeh.antennapod.event.FeedItemEvent;
 import de.danoeh.antennapod.event.FeedListUpdateEvent;
 import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
@@ -65,21 +36,48 @@
 import de.danoeh.antennapod.event.QueueEvent;
 import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
 import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
-import de.danoeh.antennapod.ui.episodeslist.EpisodeMultiSelectActionHandler;
-import de.danoeh.antennapod.ui.swipeactions.SwipeActions;
-import de.danoeh.antennapod.ui.episodeslist.FeedItemMenuHandler;
 import de.danoeh.antennapod.model.download.DownloadResult;
 import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.model.feed.FeedItem;
 import de.danoeh.antennapod.model.feed.FeedItemFilter;
+import de.danoeh.antennapod.net.download.serviceinterface.FeedUpdateManager;
+import de.danoeh.antennapod.storage.database.DBReader;
+import de.danoeh.antennapod.storage.database.DBWriter;
 import de.danoeh.antennapod.storage.preferences.UserPreferences;
-import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
+import de.danoeh.antennapod.ui.CoverLoader;
+import de.danoeh.antennapod.ui.FeedItemFilterDialog;
+import de.danoeh.antennapod.ui.MenuItemUtils;
+import de.danoeh.antennapod.ui.TransitionEffect;
+import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
+import de.danoeh.antennapod.ui.cleaner.HtmlToPlainText;
+import de.danoeh.antennapod.ui.common.IntentUtils;
+import de.danoeh.antennapod.ui.episodeslist.EpisodeItemListAdapter;
 import de.danoeh.antennapod.ui.episodeslist.EpisodeItemViewHolder;
+import de.danoeh.antennapod.ui.episodeslist.EpisodeMultiSelectActionHandler;
+import de.danoeh.antennapod.ui.episodeslist.FeedItemMenuHandler;
+import de.danoeh.antennapod.ui.episodeslist.MoreContentListFooterUtil;
+import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
+import de.danoeh.antennapod.ui.screen.SearchFragment;
+import de.danoeh.antennapod.ui.screen.download.DownloadLogDetailsDialog;
+import de.danoeh.antennapod.ui.screen.download.DownloadLogFragment;
+import de.danoeh.antennapod.ui.screen.episode.ItemPagerFragment;
+import de.danoeh.antennapod.ui.screen.feed.preferences.FeedSettingsFragment;
+import de.danoeh.antennapod.ui.share.ShareUtils;
+import de.danoeh.antennapod.ui.swipeactions.SwipeActions;
 import io.reactivex.Maybe;
 import io.reactivex.Observable;
 import io.reactivex.android.schedulers.AndroidSchedulers;
 import io.reactivex.disposables.Disposable;
 import io.reactivex.schedulers.Schedulers;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
 
 /**
  * Displays a list of FeedItems.
@@ -100,7 +98,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
     private boolean displayUpArrow;
     private long feedID;
     private Feed feed;
-    private boolean headerCreated = false;
     private Disposable disposable;
     private FeedItemListFragmentBinding viewBinding;
 
@@ -145,12 +142,18 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
         if (savedInstanceState != null) {
             displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW);
         }
-        ((MainActivity) getActivity()).setupToolbarToggle(viewBinding.toolbar, displayUpArrow);
+        if (getActivity() instanceof MainActivity) {
+            ((MainActivity) getActivity()).setupToolbarToggle(viewBinding.toolbar, displayUpArrow);
+            viewBinding.recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
+        } else {
+            viewBinding.toolbar.setNavigationIcon(R.drawable.ic_close);
+            viewBinding.toolbar.setNavigationOnClickListener(view -> getActivity().finish());
+        }
         updateToolbar();
         setupLoadMoreScrollListener();
+        setupHeaderView();
 
-        viewBinding.recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool());
-        adapter = new FeedItemListAdapter((MainActivity) getActivity());
+        adapter = new FeedItemListAdapter(getActivity());
         adapter.setOnSelectModeListener(this);
         viewBinding.recyclerView.setAdapter(adapter);
         swipeActions = new SwipeActions(this, TAG).attachTo(viewBinding.recyclerView);
@@ -198,7 +201,7 @@ public void onScrolled(@NonNull RecyclerView view, int deltaX, int deltaY) {
                         Snackbar.LENGTH_SHORT);
                 return false;
             }
-            new EpisodeMultiSelectActionHandler(((MainActivity) getActivity()), menuItem.getItemId())
+            new EpisodeMultiSelectActionHandler(getActivity(), menuItem.getItemId())
                     .handleAction(adapter.getSelectedItems());
             adapter.endSelectMode();
             return true;
@@ -249,6 +252,13 @@ private void updateToolbar() {
         if (feed.isLocalFeed()) {
             viewBinding.toolbar.getMenu().findItem(R.id.share_item).setVisible(false);
         }
+        if (feed.getState() == Feed.STATE_NOT_SUBSCRIBED) {
+            viewBinding.toolbar.getMenu().findItem(R.id.sort_items).setVisible(false);
+            viewBinding.toolbar.getMenu().findItem(R.id.refresh_item).setVisible(false);
+            viewBinding.toolbar.getMenu().findItem(R.id.rename_item).setVisible(false);
+            viewBinding.toolbar.getMenu().findItem(R.id.remove_feed).setVisible(false);
+            viewBinding.toolbar.getMenu().findItem(R.id.action_search).setVisible(false);
+        }
     }
 
     @Override
@@ -263,8 +273,7 @@ public void onConfigurationChanged(@NonNull Configuration newConfig) {
     @Override
     public boolean onMenuItemClick(MenuItem item) {
         if (feed == null) {
-            ((MainActivity) getActivity()).showSnackbarAbovePlayer(
-                    R.string.please_wait_for_data, Toast.LENGTH_LONG);
+            EventBus.getDefault().post(getString(R.string.please_wait_for_data));
             return true;
         }
         if (item.getItemId() == R.id.visit_website_item) {
@@ -443,7 +452,6 @@ public void onEventMainThread(FeedUpdateRunningEvent event) {
     }
 
     private void refreshHeaderView() {
-        setupHeaderView();
         if (viewBinding == null || feed == null) {
             Log.e(TAG, "Unable to refresh header view");
             return;
@@ -454,7 +462,7 @@ private void refreshHeaderView() {
         } else {
             viewBinding.header.txtvFailure.setVisibility(View.GONE);
         }
-        if (!feed.getPreferences().getKeepUpdated()) {
+        if (!feed.getPreferences().getKeepUpdated() && feed.getState() == Feed.STATE_SUBSCRIBED) {
             viewBinding.header.txtvUpdatesDisabled.setText(R.string.updates_disabled_label);
             viewBinding.header.txtvUpdatesDisabled.setVisibility(View.VISIBLE);
         } else {
@@ -462,7 +470,11 @@ private void refreshHeaderView() {
         }
         viewBinding.header.txtvTitle.setText(feed.getTitle());
         viewBinding.header.txtvAuthor.setText(feed.getAuthor());
-        if (feed.getItemFilter() != null) {
+        viewBinding.header.descriptionContainer.setVisibility(View.GONE);
+        if (feed.getState() != Feed.STATE_SUBSCRIBED) {
+            viewBinding.header.descriptionContainer.setVisibility(View.VISIBLE);
+            viewBinding.header.headerDescriptionLabel.setText(HtmlToPlainText.getPlainText(feed.getDescription()));
+        } else if (feed.getItemFilter() != null) {
             FeedItemFilter filter = feed.getItemFilter();
             if (filter.getValues().length > 0) {
                 viewBinding.header.txtvInformation.setText(R.string.filtered_label);
@@ -475,17 +487,30 @@ private void refreshHeaderView() {
         } else {
             viewBinding.header.txtvInformation.setVisibility(View.GONE);
         }
-    }
+        boolean isSubscribed = feed.getState() == Feed.STATE_SUBSCRIBED;
+        viewBinding.header.butShowInfo.setVisibility(isSubscribed ? View.VISIBLE : View.GONE);
+        viewBinding.header.butFilter.setVisibility(isSubscribed ? View.VISIBLE : View.GONE);
+        viewBinding.header.butShowSettings.setVisibility(isSubscribed ? View.VISIBLE : View.GONE);
+        viewBinding.header.butSubscribe.setVisibility(isSubscribed ? View.GONE : View.VISIBLE);
 
-    private void setupHeaderView() {
-        if (feed == null || headerCreated) {
-            return;
+        if (!isSubscribed && feed.getLastRefreshAttempt() < System.currentTimeMillis() - 1000L * 3600 * 24) {
+            FeedUpdateManager.getInstance().runOnce(getContext(), feed, true);
         }
+    }
 
+    private void setupHeaderView() {
         // https://github.com/bumptech/glide/issues/529
         viewBinding.imgvBackground.setColorFilter(new LightingColorFilter(0xff666666, 0x000000));
         viewBinding.header.butShowInfo.setOnClickListener(v -> showFeedInfo());
         viewBinding.header.imgvCover.setOnClickListener(v -> showFeedInfo());
+        viewBinding.header.headerDescriptionLabel.setOnClickListener(v -> showFeedInfo());
+        viewBinding.header.butSubscribe.setOnClickListener(view -> {
+            DBWriter.setFeedState(getContext(), feed, Feed.STATE_SUBSCRIBED);
+            MainActivityStarter mainActivityStarter = new MainActivityStarter(getContext());
+            mainActivityStarter.withOpenFeed(feed.getId());
+            getActivity().finish();
+            startActivity(mainActivityStarter.getIntent());
+        });
         viewBinding.header.butShowSettings.setOnClickListener(v -> {
             if (feed != null) {
                 FeedSettingsFragment fragment = FeedSettingsFragment.newInstance(feed);
@@ -495,7 +520,6 @@ private void setupHeaderView() {
         viewBinding.header.butFilter.setOnClickListener(v ->
                 FeedItemFilterDialog.newInstance(feed).show(getChildFragmentManager(), null));
         viewBinding.header.txtvFailure.setOnClickListener(v -> showErrorDetails());
-        headerCreated = true;
     }
 
     private void showErrorDetails() {
@@ -516,9 +540,18 @@ private void showErrorDetails() {
     }
 
     private void showFeedInfo() {
-        if (feed != null) {
-            FeedInfoFragment fragment = FeedInfoFragment.newInstance(feed);
+        if (feed == null) {
+            return;
+        }
+        FeedInfoFragment fragment = FeedInfoFragment.newInstance(feed);
+        if (getActivity() instanceof MainActivity) {
             ((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.SLIDE);
+        } else {
+            getActivity().getSupportFragmentManager()
+                    .beginTransaction()
+                    .replace(R.id.fragmentContainer, fragment, "Info")
+                    .addToBackStack("Info")
+                    .commitAllowingStateLoss();
         }
     }
 
@@ -625,7 +658,7 @@ public void onKeyUp(KeyEvent event) {
     }
 
     private class FeedItemListAdapter extends EpisodeItemListAdapter {
-        public FeedItemListAdapter(MainActivity mainActivity) {
+        public FeedItemListAdapter(FragmentActivity mainActivity) {
             super(mainActivity);
         }
 
@@ -648,7 +681,7 @@ protected void afterBindViewHolder(EpisodeItemViewHolder holder, int pos) {
         @Override
         public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
             super.onCreateContextMenu(menu, v, menuInfo);
-            if (!inActionMode()) {
+            if (!inActionMode() && feed.getState() == Feed.STATE_SUBSCRIBED) {
                 menu.findItem(R.id.multi_select).setVisible(true);
             }
             MenuItemUtils.setOnClickListeners(menu, FeedItemlistFragment.this::onContextItemSelected);
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/home/sections/DownloadsSection.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/home/sections/DownloadsSection.java
index cc3288e2f27..06de7803a10 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/home/sections/DownloadsSection.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/home/sections/DownloadsSection.java
@@ -39,6 +39,8 @@
 public class DownloadsSection extends HomeSection {
     public static final String TAG = "DownloadsSection";
     private static final int NUM_EPISODES = 2;
+    private static final FeedItemFilter FILTER_DOWNLOADED = new FeedItemFilter(
+            FeedItemFilter.DOWNLOADED, FeedItemFilter.INCLUDE_NOT_SUBSCRIBED);
     private EpisodeItemListAdapter adapter;
     private List<FeedItem> items;
     private Disposable disposable;
@@ -52,7 +54,7 @@ public View onCreateView(@NonNull LayoutInflater inflater,
         viewBinding.recyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
         viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
         viewBinding.recyclerView.setRecycledViewPool(((MainActivity) requireActivity()).getRecycledViewPool());
-        adapter = new EpisodeItemListAdapter((MainActivity) requireActivity()) {
+        adapter = new EpisodeItemListAdapter(requireActivity()) {
             @Override
             public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
                 super.onCreateContextMenu(menu, v, menuInfo);
@@ -124,8 +126,7 @@ private void loadItems() {
             disposable.dispose();
         }
         SortOrder sortOrder = UserPreferences.getDownloadsSortedOrder();
-        disposable = Observable.fromCallable(() -> DBReader.getEpisodes(0, NUM_EPISODES,
-                        new FeedItemFilter(FeedItemFilter.DOWNLOADED), sortOrder))
+        disposable = Observable.fromCallable(() -> DBReader.getEpisodes(0, NUM_EPISODES, FILTER_DOWNLOADED, sortOrder))
                 .subscribeOn(Schedulers.io())
                 .observeOn(AndroidSchedulers.mainThread())
                 .subscribe(downloads -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/onlinefeedview/FeedItemlistDescriptionAdapter.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/onlinefeedview/FeedItemlistDescriptionAdapter.java
deleted file mode 100644
index f46d786cfe3..00000000000
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/onlinefeedview/FeedItemlistDescriptionAdapter.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package de.danoeh.antennapod.ui.screen.onlinefeedview;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.model.playback.MediaType;
-import de.danoeh.antennapod.net.common.NetworkUtils;
-import de.danoeh.antennapod.model.playback.RemoteMedia;
-import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.playback.service.PlaybackService;
-import de.danoeh.antennapod.playback.service.PlaybackServiceStarter;
-import de.danoeh.antennapod.ui.common.DateFormatter;
-import de.danoeh.antennapod.model.playback.Playable;
-import de.danoeh.antennapod.ui.cleaner.HtmlToPlainText;
-import de.danoeh.antennapod.ui.StreamingConfirmationDialog;
-
-import java.util.List;
-
-/**
- * List adapter for showing a list of FeedItems with their title and description.
- */
-public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
-    private static final int MAX_LINES_COLLAPSED = 2;
-
-    public FeedItemlistDescriptionAdapter(Context context, int resource, List<FeedItem> objects) {
-        super(context, resource, objects);
-    }
-
-    @NonNull
-    @Override
-    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
-        Holder holder;
-
-        FeedItem item = getItem(position);
-
-        // Inflate layout
-        if (convertView == null) {
-            holder = new Holder();
-            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            convertView = inflater.inflate(R.layout.itemdescription_listitem, parent, false);
-            holder.title = convertView.findViewById(R.id.txtvTitle);
-            holder.pubDate = convertView.findViewById(R.id.txtvPubDate);
-            holder.description = convertView.findViewById(R.id.txtvDescription);
-            holder.preview = convertView.findViewById(R.id.butPreview);
-
-            convertView.setTag(holder);
-        } else {
-            holder = (Holder) convertView.getTag();
-        }
-
-        holder.title.setText(item.getTitle());
-        holder.pubDate.setText(DateFormatter.formatAbbrev(getContext(), item.getPubDate()));
-        if (item.getDescription() != null) {
-            String description = HtmlToPlainText.getPlainText(item.getDescription())
-                    .replaceAll("\n", " ")
-                    .replaceAll("\\s+", " ")
-                    .trim();
-            holder.description.setText(description);
-            holder.description.setMaxLines(MAX_LINES_COLLAPSED);
-        }
-        holder.description.setTag(Boolean.FALSE); // not expanded
-        holder.preview.setVisibility(View.GONE);
-        holder.preview.setOnClickListener(v -> {
-            if (item.getMedia() == null) {
-                return;
-            }
-            Playable playable = new RemoteMedia(item);
-            if (!NetworkUtils.isStreamingAllowed()) {
-                new StreamingConfirmationDialog(getContext(), playable).show();
-                return;
-            }
-
-            new PlaybackServiceStarter(getContext(), playable)
-                    .callEvenIfRunning(true)
-                    .start();
-
-            if (playable.getMediaType() == MediaType.VIDEO) {
-                getContext().startActivity(PlaybackService.getPlayerActivityIntent(getContext(), playable));
-            }
-        });
-        convertView.setOnClickListener(v -> {
-            if (holder.description.getTag() == Boolean.TRUE) {
-                holder.description.setMaxLines(MAX_LINES_COLLAPSED);
-                holder.preview.setVisibility(View.GONE);
-                holder.description.setTag(Boolean.FALSE);
-            } else {
-                holder.description.setMaxLines(30);
-                holder.description.setTag(Boolean.TRUE);
-
-                holder.preview.setVisibility(item.getMedia() != null ? View.VISIBLE : View.GONE);
-                holder.preview.setText(R.string.preview_episode);
-            }
-        });
-        return convertView;
-    }
-
-    static class Holder {
-        TextView title;
-        TextView pubDate;
-        TextView description;
-        Button preview;
-    }
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/onlinefeedview/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/onlinefeedview/OnlineFeedViewActivity.java
index 7b8558c3d0c..be601027c0e 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/onlinefeedview/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/onlinefeedview/OnlineFeedViewActivity.java
@@ -4,8 +4,6 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.SharedPreferences;
-import android.graphics.LightingColorFilter;
 import android.os.Bundle;
 import android.text.Spannable;
 import android.text.SpannableString;
@@ -13,68 +11,45 @@
 import android.text.style.ForegroundColorSpan;
 import android.util.Log;
 import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Toast;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
 import androidx.appcompat.app.AppCompatActivity;
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.request.RequestOptions;
-import com.google.android.material.snackbar.Snackbar;
-
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.net.download.service.feed.remote.Downloader;
-import de.danoeh.antennapod.net.download.service.feed.remote.HttpDownloader;
-import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
-import de.danoeh.antennapod.ui.common.ThemeSwitcher;
-import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequestCreator;
-import de.danoeh.antennapod.net.discovery.FeedUrlNotFoundException;
-import de.danoeh.antennapod.storage.database.FeedDatabaseWriter;
-import de.danoeh.antennapod.playback.service.PlaybackServiceInterface;
-import de.danoeh.antennapod.ui.screen.download.DownloadErrorLabel;
 import de.danoeh.antennapod.databinding.EditTextDialogBinding;
-import de.danoeh.antennapod.databinding.OnlinefeedviewHeaderBinding;
-import de.danoeh.antennapod.event.EpisodeDownloadEvent;
-import de.danoeh.antennapod.event.FeedListUpdateEvent;
-import de.danoeh.antennapod.event.PlayerStatusEvent;
-import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
-import de.danoeh.antennapod.storage.preferences.UserPreferences;
+import de.danoeh.antennapod.databinding.OnlinefeedviewActivityBinding;
+import de.danoeh.antennapod.model.download.DownloadError;
 import de.danoeh.antennapod.model.download.DownloadRequest;
 import de.danoeh.antennapod.model.download.DownloadResult;
-import de.danoeh.antennapod.storage.database.DBReader;
-import de.danoeh.antennapod.storage.database.DBWriter;
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.net.common.UrlChecker;
 import de.danoeh.antennapod.net.discovery.CombinedSearcher;
+import de.danoeh.antennapod.net.discovery.FeedUrlNotFoundException;
 import de.danoeh.antennapod.net.discovery.PodcastSearchResult;
 import de.danoeh.antennapod.net.discovery.PodcastSearcherRegistry;
+import de.danoeh.antennapod.net.download.service.feed.remote.Downloader;
+import de.danoeh.antennapod.net.download.service.feed.remote.HttpDownloader;
+import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequestCreator;
 import de.danoeh.antennapod.parser.feed.FeedHandler;
 import de.danoeh.antennapod.parser.feed.FeedHandlerResult;
-import de.danoeh.antennapod.model.download.DownloadError;
-import de.danoeh.antennapod.ui.common.IntentUtils;
-import de.danoeh.antennapod.net.common.UrlChecker;
-import de.danoeh.antennapod.ui.cleaner.HtmlToPlainText;
-import de.danoeh.antennapod.databinding.OnlinefeedviewActivityBinding;
-import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.model.feed.FeedPreferences;
-import de.danoeh.antennapod.model.playback.RemoteMedia;
 import de.danoeh.antennapod.parser.feed.UnsupportedFeedtypeException;
+import de.danoeh.antennapod.storage.database.DBReader;
+import de.danoeh.antennapod.storage.database.DBWriter;
+import de.danoeh.antennapod.storage.database.FeedDatabaseWriter;
+import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
+import de.danoeh.antennapod.ui.common.ThemeSwitcher;
 import de.danoeh.antennapod.ui.common.ThemeUtils;
-import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
 import de.danoeh.antennapod.ui.preferences.screen.synchronization.AuthenticationDialog;
+import de.danoeh.antennapod.ui.screen.download.DownloadErrorLabel;
+import de.danoeh.antennapod.ui.screen.feed.FeedItemlistFragment;
 import io.reactivex.Maybe;
 import io.reactivex.Observable;
 import io.reactivex.android.schedulers.AndroidSchedulers;
 import io.reactivex.disposables.Disposable;
-import io.reactivex.observers.DisposableMaybeObserver;
 import io.reactivex.schedulers.Schedulers;
-import org.apache.commons.lang3.StringUtils;
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
 
 import java.io.File;
 import java.io.IOException;
@@ -95,30 +70,16 @@
  * and the activity will finish as soon as the error dialog is closed.
  */
 public class OnlineFeedViewActivity extends AppCompatActivity {
-
-    private static final int RESULT_ERROR = 2;
     private static final String TAG = "OnlineFeedViewActivity";
-    private static final String PREFS = "OnlineFeedViewActivityPreferences";
-    private static final String PREF_LAST_AUTO_DOWNLOAD = "lastAutoDownload";
-    private static final int DESCRIPTION_MAX_LINES_COLLAPSED = 4;
-
-    private volatile List<Feed> feeds;
     private String selectedDownloadUrl;
     private Downloader downloader;
     private String username = null;
     private String password = null;
-
     private boolean isPaused;
-    private boolean didPressSubscribe = false;
     private boolean isFeedFoundBySearch = false;
-
     private Dialog dialog;
-
     private Disposable download;
     private Disposable parser;
-    private Disposable updater;
-
-    private OnlinefeedviewHeaderBinding headerBinding;
     private OnlinefeedviewActivityBinding viewBinding;
 
     @Override
@@ -128,12 +89,9 @@ protected void onCreate(Bundle savedInstanceState) {
 
         viewBinding = OnlinefeedviewActivityBinding.inflate(getLayoutInflater());
         setContentView(viewBinding.getRoot());
-
         viewBinding.transparentBackground.setOnClickListener(v -> finish());
-        viewBinding.closeButton.setOnClickListener(view -> finish());
         viewBinding.card.setOnClickListener(null);
         viewBinding.card.setCardBackgroundColor(ThemeUtils.getColorFromAttr(this, R.attr.colorSurface));
-        headerBinding = OnlinefeedviewHeaderBinding.inflate(getLayoutInflater());
 
         String feedUrl = null;
         if (getIntent().hasExtra(ARG_FEEDURL)) {
@@ -149,7 +107,6 @@ protected void onCreate(Bundle savedInstanceState) {
             showNoPodcastFoundError();
         } else {
             Log.d(TAG, "Activity was started with url " + feedUrl);
-            setLoadingLayout();
             // Remove subscribeonandroid.com from feed URL in order to subscribe to the actual feed URL
             if (feedUrl.contains("subscribeonandroid.com")) {
                 feedUrl = feedUrl.replaceFirst("((www.)?(subscribeonandroid.com/))", "");
@@ -167,33 +124,20 @@ private void showNoPodcastFoundError() {
                 .setNeutralButton(android.R.string.ok, (dialog, which) -> finish())
                 .setTitle(R.string.error_label)
                 .setMessage(R.string.null_value_podcast_error)
-                .setOnDismissListener(dialog1 -> {
-                    setResult(RESULT_ERROR);
-                    finish();
-                })
+                .setOnDismissListener(dialog1 -> finish())
                 .show());
     }
 
-    /**
-     * Displays a progress indicator.
-     */
-    private void setLoadingLayout() {
-        viewBinding.progressBar.setVisibility(View.VISIBLE);
-        viewBinding.feedDisplayContainer.setVisibility(View.GONE);
-    }
-
     @Override
     protected void onStart() {
         super.onStart();
         isPaused = false;
-        EventBus.getDefault().register(this);
     }
 
     @Override
     protected void onStop() {
         super.onStop();
         isPaused = true;
-        EventBus.getDefault().unregister(this);
         if (downloader != null && !downloader.isFinished()) {
             downloader.cancel();
         }
@@ -205,9 +149,6 @@ protected void onStop() {
     @Override
     public void onDestroy() {
         super.onDestroy();
-        if(updater != null) {
-            updater.dispose();
-        }
         if(download != null) {
             download.dispose();
         }
@@ -239,7 +180,7 @@ private void lookupUrlAndDownload(String url) {
         download = PodcastSearcherRegistry.lookupUrl(url)
                 .subscribeOn(Schedulers.io())
                 .observeOn(Schedulers.io())
-                .subscribe(this::startFeedDownload,
+                .subscribe(this::downloadIfNotAlreadySubscribed,
                         error -> {
                             if (error instanceof FeedUrlNotFoundException) {
                                 tryToRetrieveFeedUrlBySearch((FeedUrlNotFoundException) error);
@@ -256,7 +197,7 @@ private void tryToRetrieveFeedUrlBySearch(FeedUrlNotFoundException error) {
         if (url != null) {
             Log.d(TAG, "Successfully retrieve feed url");
             isFeedFoundBySearch = true;
-            startFeedDownload(url);
+            downloadIfNotAlreadySubscribed(url);
         } else {
             showNoPodcastFoundError();
             Log.d(TAG, "Failed to retrieve feed url");
@@ -277,6 +218,28 @@ private String searchFeedUrlByTrackName(String trackName, String artistName) {
         return null;
     }
 
+    private Feed downloadIfNotAlreadySubscribed(String url) {
+        download = Maybe.fromCallable(() -> {
+            List<Feed> feeds = DBReader.getFeedList();
+            for (Feed f : feeds) {
+                if (f.getDownloadUrl().equals(url)) {
+                    return f;
+                }
+            }
+            return null;
+        })
+        .subscribeOn(Schedulers.io())
+        .observeOn(AndroidSchedulers.mainThread())
+        .subscribe(subscribedFeed -> {
+            if (subscribedFeed.getState() == Feed.STATE_SUBSCRIBED) {
+                openFeed(subscribedFeed.getId());
+            } else {
+                showFeedFragment(subscribedFeed.getId());
+            }
+        }, error -> Log.e(TAG, Log.getStackTraceString(error)), () -> startFeedDownload(url));
+        return null;
+    }
+
     private void startFeedDownload(String url) {
         Log.d(TAG, "Starting feed download");
         selectedDownloadUrl = UrlChecker.prepareUrl(url);
@@ -286,7 +249,6 @@ private void startFeedDownload(String url) {
                 .build();
 
         download = Observable.fromCallable(() -> {
-            feeds = DBReader.getFeedList();
             downloader = new HttpDownloader(request);
             downloader.call();
             return downloader.getResult();
@@ -315,46 +277,25 @@ private void checkDownloadResult(@NonNull DownloadResult status, String destinat
         }
     }
 
-    @Subscribe
-    public void onFeedListChanged(FeedListUpdateEvent event) {
-        updater = Observable.fromCallable(DBReader::getFeedList)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(
-                        feeds -> {
-                            OnlineFeedViewActivity.this.feeds = feeds;
-                            handleUpdatedFeedStatus();
-                        }, error -> Log.e(TAG, Log.getStackTraceString(error))
-                );
-    }
-
-    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
-    public void onEventMainThread(EpisodeDownloadEvent event) {
-        handleUpdatedFeedStatus();
-    }
-
     private void parseFeed(String destination) {
         Log.d(TAG, "Parsing feed");
-        parser = Maybe.fromCallable(() -> doParseFeed(destination))
-                .subscribeOn(Schedulers.computation())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribeWith(new DisposableMaybeObserver<FeedHandlerResult>() {
-                    @Override
-                    public void onSuccess(@NonNull FeedHandlerResult result) {
-                        showFeedInformation(result.feed, result.alternateFeedUrls);
-                    }
-
-                    @Override
-                    public void onComplete() {
-                        // Ignore null result: We showed the discovery dialog.
-                    }
-
-                    @Override
-                    public void onError(@NonNull Throwable error) {
-                        showErrorDialog(error.getMessage(), "");
-                        Log.d(TAG, "Feed parser exception: " + Log.getStackTraceString(error));
-                    }
-                });
+        parser = Observable.fromCallable(() -> {
+            FeedHandlerResult handlerResult = doParseFeed(destination);
+            Feed feed = handlerResult.feed;
+            feed.setState(Feed.STATE_NOT_SUBSCRIBED);
+            feed.setLastRefreshAttempt(System.currentTimeMillis());
+            FeedDatabaseWriter.updateFeed(this, feed, false);
+            Feed feedFromDb = DBReader.getFeed(feed.getId(), false, 0, Integer.MAX_VALUE);
+            feedFromDb.getPreferences().setKeepUpdated(false);
+            DBWriter.setFeedPreferences(feedFromDb.getPreferences());
+            return feed.getId();
+        })
+        .subscribeOn(Schedulers.computation())
+        .observeOn(AndroidSchedulers.mainThread())
+        .subscribe(this::showFeedFragment, error -> {
+            error.printStackTrace();
+            showErrorDialog(error.getMessage(), "");
+        });
     }
 
     /**
@@ -392,123 +333,23 @@ private FeedHandlerResult doParseFeed(String destination) throws Exception {
         }
     }
 
-    /**
-     * Called when feed parsed successfully.
-     * This method is executed on the GUI thread.
-     */
-    private void showFeedInformation(final Feed feed, Map<String, String> alternateFeedUrls) {
-        viewBinding.progressBar.setVisibility(View.GONE);
-        viewBinding.feedDisplayContainer.setVisibility(View.VISIBLE);
+    private void showFeedFragment(long id) {
         if (isFeedFoundBySearch) {
-            int resId = R.string.no_feed_url_podcast_found_by_search;
-            Snackbar.make(findViewById(android.R.id.content), resId, Snackbar.LENGTH_LONG).show();
-        }
-
-        viewBinding.backgroundImage.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
-
-        viewBinding.listView.addHeaderView(headerBinding.getRoot());
-        viewBinding.listView.setSelector(android.R.color.transparent);
-        viewBinding.listView.setAdapter(new FeedItemlistDescriptionAdapter(this, 0, feed.getItems()));
-
-        if (StringUtils.isNotBlank(feed.getImageUrl())) {
-            Glide.with(this)
-                    .load(feed.getImageUrl())
-                    .apply(new RequestOptions()
-                        .placeholder(R.color.light_gray)
-                        .error(R.color.light_gray)
-                        .fitCenter()
-                        .dontAnimate())
-                    .into(viewBinding.coverImage);
-            Glide.with(this)
-                    .load(feed.getImageUrl())
-                    .apply(new RequestOptions()
-                            .placeholder(R.color.image_readability_tint)
-                            .error(R.color.image_readability_tint)
-                            .transform(new FastBlurTransformation())
-                            .dontAnimate())
-                    .into(viewBinding.backgroundImage);
-        }
-
-        viewBinding.titleLabel.setText(feed.getTitle());
-        viewBinding.authorLabel.setText(feed.getAuthor());
-        headerBinding.txtvDescription.setText(HtmlToPlainText.getPlainText(feed.getDescription()));
-
-        viewBinding.subscribeButton.setOnClickListener(v -> {
-            if (feedInFeedlist()) {
-                openFeed();
-            } else {
-                FeedDatabaseWriter.updateFeed(this, feed, false);
-                didPressSubscribe = true;
-                handleUpdatedFeedStatus();
-            }
-        });
-
-        viewBinding.stopPreviewButton.setOnClickListener(v -> {
-            PlaybackPreferences.writeNoMediaPlaying();
-            IntentUtils.sendLocalBroadcast(this, PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
-        });
-
-        if (UserPreferences.isEnableAutodownload()) {
-            SharedPreferences preferences = getSharedPreferences(PREFS, MODE_PRIVATE);
-            viewBinding.autoDownloadCheckBox.setChecked(preferences.getBoolean(PREF_LAST_AUTO_DOWNLOAD, true));
+            Toast.makeText(this, R.string.no_feed_url_podcast_found_by_search, Toast.LENGTH_LONG).show();
         }
 
-        headerBinding.txtvDescription.setMaxLines(DESCRIPTION_MAX_LINES_COLLAPSED);
-        headerBinding.txtvDescription.setOnClickListener(v -> {
-            if (headerBinding.txtvDescription.getMaxLines() > DESCRIPTION_MAX_LINES_COLLAPSED) {
-                headerBinding.txtvDescription.setMaxLines(DESCRIPTION_MAX_LINES_COLLAPSED);
-            } else {
-                headerBinding.txtvDescription.setMaxLines(2000);
-            }
-        });
-
-        if (alternateFeedUrls.isEmpty()) {
-            viewBinding.alternateUrlsSpinner.setVisibility(View.GONE);
-        } else {
-            viewBinding.alternateUrlsSpinner.setVisibility(View.VISIBLE);
-
-            final List<String> alternateUrlsList = new ArrayList<>();
-            final List<String> alternateUrlsTitleList = new ArrayList<>();
-
-            alternateUrlsList.add(feed.getDownloadUrl());
-            alternateUrlsTitleList.add(feed.getTitle());
-
-
-            alternateUrlsList.addAll(alternateFeedUrls.keySet());
-            for (String url : alternateFeedUrls.keySet()) {
-                alternateUrlsTitleList.add(alternateFeedUrls.get(url));
-            }
-
-            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
-                    R.layout.alternate_urls_item, alternateUrlsTitleList) {
-                @Override
-                public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
-                    // reusing the old view causes a visual bug on Android <= 10
-                    return super.getDropDownView(position, null, parent);
-                }
-            };
-
-            adapter.setDropDownViewResource(R.layout.alternate_urls_dropdown_item);
-            viewBinding.alternateUrlsSpinner.setAdapter(adapter);
-            viewBinding.alternateUrlsSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
-                @Override
-                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-                    selectedDownloadUrl = alternateUrlsList.get(position);
-                }
-
-                @Override
-                public void onNothingSelected(AdapterView<?> parent) {
-
-                }
-            });
-        }
-        handleUpdatedFeedStatus();
+        viewBinding.progressBar.setVisibility(View.GONE);
+        FeedItemlistFragment fragment = FeedItemlistFragment.newInstance(id);
+        getSupportFragmentManager()
+                .beginTransaction()
+                .replace(R.id.fragmentContainer, fragment, FeedItemlistFragment.TAG)
+                .commitAllowingStateLoss();
     }
 
-    private void openFeed() {
+    private void openFeed(long feedId) {
         // feed.getId() is always 0, we have to retrieve the id from the feed list from the database
         MainActivityStarter mainActivityStarter = new MainActivityStarter(this);
-        mainActivityStarter.withOpenFeed(getFeedId());
+        mainActivityStarter.withOpenFeed(feedId);
         if (getIntent().getBooleanExtra(ARG_STARTED_FROM_SEARCH, false)) {
             mainActivityStarter.withAddToBackStack();
         }
@@ -516,60 +357,6 @@ private void openFeed() {
         startActivity(mainActivityStarter.getIntent());
     }
 
-    private void handleUpdatedFeedStatus() {
-        if (DownloadServiceInterface.get().isDownloadingEpisode(selectedDownloadUrl)) {
-            viewBinding.subscribeButton.setEnabled(false);
-            viewBinding.subscribeButton.setText(R.string.subscribing_label);
-        } else if (feedInFeedlist()) {
-            viewBinding.subscribeButton.setEnabled(true);
-            viewBinding.subscribeButton.setText(R.string.open_podcast);
-            if (didPressSubscribe) {
-                didPressSubscribe = false;
-
-                Feed feed1 = DBReader.getFeed(getFeedId(), false, 0, 0);
-                FeedPreferences feedPreferences = feed1.getPreferences();
-                if (UserPreferences.isEnableAutodownload()) {
-                    boolean autoDownload = viewBinding.autoDownloadCheckBox.isChecked();
-                    feedPreferences.setAutoDownload(autoDownload);
-
-                    SharedPreferences preferences = getSharedPreferences(PREFS, MODE_PRIVATE);
-                    SharedPreferences.Editor editor = preferences.edit();
-                    editor.putBoolean(PREF_LAST_AUTO_DOWNLOAD, autoDownload);
-                    editor.apply();
-                }
-                if (username != null) {
-                    feedPreferences.setUsername(username);
-                    feedPreferences.setPassword(password);
-                }
-                DBWriter.setFeedPreferences(feedPreferences);
-
-                openFeed();
-            }
-        } else {
-            viewBinding.subscribeButton.setEnabled(true);
-            viewBinding.subscribeButton.setText(R.string.subscribe_label);
-            if (UserPreferences.isEnableAutodownload()) {
-                viewBinding.autoDownloadCheckBox.setVisibility(View.VISIBLE);
-            }
-        }
-    }
-
-    private boolean feedInFeedlist() {
-        return getFeedId() != 0;
-    }
-
-    private long getFeedId() {
-        if (feeds == null) {
-            return 0;
-        }
-        for (Feed f : feeds) {
-            if (f.getDownloadUrl().equals(selectedDownloadUrl)) {
-                return f.getId();
-            }
-        }
-        return 0;
-    }
-
     @UiThread
     private void showErrorDialog(String errorMsg, String details) {
         if (!isFinishing() && !isPaused) {
@@ -589,7 +376,6 @@ private void showErrorDialog(String errorMsg, String details) {
                 builder.setNeutralButton(R.string.edit_url_menu, (dialog, which) -> editUrl());
             }
             builder.setOnCancelListener(dialog -> {
-                setResult(RESULT_ERROR);
                 finish();
             });
             if (dialog != null && dialog.isShowing()) {
@@ -608,24 +394,15 @@ private void editUrl() {
         }
         builder.setView(dialogBinding.getRoot());
         builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
-            setLoadingLayout();
             lookupUrlAndDownload(dialogBinding.urlEditText.getText().toString());
         });
         builder.setNegativeButton(R.string.cancel_label, (dialog1, which) -> dialog1.cancel());
         builder.setOnCancelListener(dialog1 -> {
-            setResult(RESULT_ERROR);
             finish();
         });
         builder.show();
     }
 
-    @Subscribe(threadMode = ThreadMode.MAIN)
-    public void playbackStateChanged(PlayerStatusEvent event) {
-        boolean isPlayingPreview =
-                PlaybackPreferences.getCurrentlyPlayingMediaType() == RemoteMedia.PLAYABLE_TYPE_REMOTE_MEDIA;
-        viewBinding.stopPreviewButton.setVisibility(isPlayingPreview ? View.VISIBLE : View.GONE);
-    }
-
     /**
      *
      * @return true if a FeedDiscoveryDialog is shown, false otherwise (e.g., due to no feed found).
@@ -657,7 +434,7 @@ private boolean showFeedDiscoveryDialog(File feedFile, String baseUrl) {
         if (urls.size() == 1) {
             // Skip dialog and display the item directly
             resetIntent(urls.get(0));
-            startFeedDownload(urls.get(0));
+            downloadIfNotAlreadySubscribed(urls.get(0));
             return true;
         }
 
@@ -667,7 +444,7 @@ private boolean showFeedDiscoveryDialog(File feedFile, String baseUrl) {
             String selectedUrl = urls.get(which);
             dialog.dismiss();
             resetIntent(selectedUrl);
-            startFeedDownload(selectedUrl);
+            downloadIfNotAlreadySubscribed(selectedUrl);
         };
 
         MaterialAlertDialogBuilder ab = new MaterialAlertDialogBuilder(OnlineFeedViewActivity.this)
@@ -704,7 +481,7 @@ protected void onCancelled() {
         protected void onConfirmed(String username, String password) {
             OnlineFeedViewActivity.this.username = username;
             OnlineFeedViewActivity.this.password = password;
-            startFeedDownload(feedUrl);
+            downloadIfNotAlreadySubscribed(feedUrl);
         }
     }
 
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/AudioPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/AudioPlayerFragment.java
index e66ed6d3eae..7aa9da50367 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/AudioPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/AudioPlayerFragment.java
@@ -25,8 +25,10 @@
 import com.google.android.material.bottomsheet.BottomSheetBehavior;
 import com.google.android.material.elevation.SurfaceColors;
 
+import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.playback.service.PlaybackController;
 import de.danoeh.antennapod.ui.appstartintent.MediaButtonStarter;
+import de.danoeh.antennapod.ui.appstartintent.OnlineFeedviewActivityStarter;
 import de.danoeh.antennapod.ui.chapters.ChapterUtils;
 import de.danoeh.antennapod.ui.episodes.PlaybackSpeedUtils;
 import de.danoeh.antennapod.ui.episodes.TimeSpeedConverter;
@@ -497,14 +499,25 @@ public boolean onMenuItemClick(MenuItem item) {
             return true;
         } else if (itemId == R.id.open_feed_item) {
             if (feedItem != null) {
-                Intent intent = MainActivity.getIntentToOpenFeed(getContext(), feedItem.getFeedId());
-                startActivity(intent);
+                openFeed(feedItem.getFeed());
             }
             return true;
         }
         return false;
     }
 
+    private void openFeed(Feed feed) {
+        if (feed == null) {
+            return;
+        }
+        if (feed.getState() == Feed.STATE_SUBSCRIBED) {
+            Intent intent = MainActivity.getIntentToOpenFeed(getContext(), feed.getId());
+            startActivity(intent);
+        } else {
+            startActivity(new OnlineFeedviewActivityStarter(getContext(), feed.getDownloadUrl()).getIntent());
+        }
+    }
+
     public void fadePlayerToToolbar(float slideOffset) {
         float playerFadeProgress = Math.max(0.0f, Math.min(0.2f, slideOffset - 0.2f)) / 0.2f;
         View player = getView().findViewById(R.id.playerFragment);
diff --git a/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/CoverFragment.java
index 073d5b0be36..d4931380ed3 100644
--- a/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/CoverFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/ui/screen/playback/audio/CoverFragment.java
@@ -32,6 +32,8 @@
 import com.google.android.material.snackbar.Snackbar;
 import de.danoeh.antennapod.R;
 import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.ui.appstartintent.OnlineFeedviewActivityStarter;
 import de.danoeh.antennapod.ui.chapters.ChapterUtils;
 import de.danoeh.antennapod.ui.screen.chapter.ChaptersFragment;
 import de.danoeh.antennapod.playback.service.PlaybackController;
@@ -122,9 +124,7 @@ private void displayMediaInfo(@NonNull Playable media) {
                 + "\u00A0"
                 + StringUtils.replace(StringUtils.stripToEmpty(pubDateStr), " ", "\u00A0"));
         if (media instanceof FeedMedia) {
-            Intent openFeed = MainActivity.getIntentToOpenFeed(requireContext(),
-                    ((FeedMedia) media).getItem().getFeedId());
-            viewBinding.txtvPodcastTitle.setOnClickListener(v -> startActivity(openFeed));
+            viewBinding.txtvPodcastTitle.setOnClickListener(v -> openFeed(((FeedMedia) media).getItem().getFeed()));
         } else {
             viewBinding.txtvPodcastTitle.setOnClickListener(null);
         }
@@ -164,6 +164,18 @@ public void onAnimationEnd(Animator animation) {
         updateChapterControlVisibility();
     }
 
+    private void openFeed(Feed feed) {
+        if (feed == null) {
+            return;
+        }
+        if (feed.getState() == Feed.STATE_SUBSCRIBED) {
+            Intent intent = MainActivity.getIntentToOpenFeed(getContext(), feed.getId());
+            startActivity(intent);
+        } else {
+            startActivity(new OnlineFeedviewActivityStarter(getContext(), feed.getDownloadUrl()).getIntent());
+        }
+    }
+
     private void updateChapterControlVisibility() {
         boolean chapterControlVisible = false;
         if (media.getChapters() != null) {
diff --git a/app/src/main/res/layout/alternate_urls_dropdown_item.xml b/app/src/main/res/layout/alternate_urls_dropdown_item.xml
deleted file mode 100644
index 3c4dcc7fc63..00000000000
--- a/app/src/main/res/layout/alternate_urls_dropdown_item.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<CheckedTextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingVertical="8dp"
-    style="?android:attr/spinnerDropDownItemStyle" />
diff --git a/app/src/main/res/layout/alternate_urls_item.xml b/app/src/main/res/layout/alternate_urls_item.xml
deleted file mode 100644
index 54e05b49d03..00000000000
--- a/app/src/main/res/layout/alternate_urls_item.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:maxLines="3"
-    android:textAlignment="inherit"
-    style="?android:attr/spinnerItemStyle" />
diff --git a/app/src/main/res/layout/feedinfo.xml b/app/src/main/res/layout/feedinfo.xml
index 1a6d8ce9312..ba121a8f345 100644
--- a/app/src/main/res/layout/feedinfo.xml
+++ b/app/src/main/res/layout/feedinfo.xml
@@ -66,13 +66,13 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
+            android:paddingTop="16dp"
             android:paddingHorizontal="@dimen/additional_horizontal_spacing">
 
             <TextView
                 android:id="@+id/statisticsHeadingLabel"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="16dp"
                 android:textSize="18sp"
                 android:layout_marginBottom="8dp"
                 android:text="@string/statistics_label"
@@ -90,6 +90,7 @@
                 android:layout_height="wrap_content"
                 android:minWidth="0dp"
                 android:minHeight="0dp"
+                android:layout_marginBottom="16dp"
                 android:text="@string/statistics_view_all"
                 style="@style/Widget.MaterialComponents.Button.TextButton" />
 
@@ -97,7 +98,6 @@
                 android:id="@+id/supportHeadingLabel"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="16dp"
                 android:layout_marginBottom="4dp"
                 android:text="@string/support_funding_label"
                 android:textColor="?android:attr/textColorPrimary"
@@ -120,7 +120,6 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:textSize="18sp"
-                android:layout_marginTop="16dp"
                 android:layout_marginBottom="4dp"
                 android:text="@string/description_label"
                 android:textColor="?android:attr/textColorPrimary"
@@ -130,7 +129,6 @@
                 android:id="@+id/descriptionLabel"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/design_time_lorem_ipsum"
                 android:textIsSelectable="true"
                 tools:background="@android:color/holo_green_dark" />
 
diff --git a/app/src/main/res/layout/feeditem_fragment.xml b/app/src/main/res/layout/feeditem_fragment.xml
index 37db9067c39..df95b8c1579 100644
--- a/app/src/main/res/layout/feeditem_fragment.xml
+++ b/app/src/main/res/layout/feeditem_fragment.xml
@@ -174,6 +174,20 @@
 
         </LinearLayout>
 
+        <TextView
+            android:id="@+id/nonSubscribedWarningLabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginVertical="8dp"
+            android:layout_marginBottom="8dp"
+            android:paddingHorizontal="16dp"
+            android:paddingVertical="8dp"
+            android:background="@drawable/bg_message_info"
+            android:textColor="?attr/colorAccent"
+            android:visibility="gone"
+            android:foreground="?attr/selectableItemBackground"
+            android:text="@string/state_deleted_not_subscribed" />
+
         <TextView
             android:id="@+id/noMediaLabel"
             android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/feeditemlist_header.xml b/app/src/main/res/layout/feeditemlist_header.xml
index 9b6d190a85a..857e44d599a 100644
--- a/app/src/main/res/layout/feeditemlist_header.xml
+++ b/app/src/main/res/layout/feeditemlist_header.xml
@@ -28,6 +28,14 @@
                 android:layout_width="148dp"
                 android:layout_height="match_parent" />
 
+            <Button
+                android:id="@+id/butSubscribe"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/subscribe_label"
+                android:visibility="gone"
+                tools:visibility="visible" />
+
             <ImageButton
                 android:id="@+id/butShowInfo"
                 android:layout_width="40dp"
@@ -178,4 +186,52 @@
         tools:visibility="visible"
         tools:text="Updates disabled" />
 
+    <LinearLayout
+        android:id="@+id/descriptionContainer"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingHorizontal="16dp"
+        android:background="?android:attr/colorBackground"
+        android:orientation="vertical"
+        android:visibility="gone">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="8dp"
+            android:layout_marginTop="16dp"
+            android:paddingHorizontal="16dp"
+            android:paddingVertical="8dp"
+            android:background="@drawable/bg_message_info"
+            android:textColor="?attr/colorAccent"
+            android:text="@string/state_deleted_not_subscribed" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="8dp"
+            android:text="@string/description_label"
+            style="@style/TextAppearance.Material3.TitleMedium" />
+
+        <TextView
+            android:id="@+id/headerDescriptionLabel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:lineHeight="20dp"
+            android:maxLines="3"
+            android:layout_marginBottom="16dp"
+            android:background="?android:attr/selectableItemBackground"
+            style="@style/AntennaPod.TextView.ListItemBody"
+            tools:text="@string/design_time_lorem_ipsum" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/preview_episodes"
+            android:layout_marginBottom="8dp"
+            style="@style/TextAppearance.Material3.TitleMedium" />
+
+    </LinearLayout>
+
 </LinearLayout>
diff --git a/app/src/main/res/layout/itemdescription_listitem.xml b/app/src/main/res/layout/itemdescription_listitem.xml
deleted file mode 100644
index c3f8c24b8dc..00000000000
--- a/app/src/main/res/layout/itemdescription_listitem.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingHorizontal="20dp"
-    android:paddingVertical="16dp">
-
-    <TextView
-        android:id="@+id/txtvPubDate"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:ellipsize="end"
-        android:lines="1"
-        style="@android:style/TextAppearance.Small"
-        tools:text="22 Jan 2016"
-        tools:background="@android:color/holo_green_dark" />
-
-    <TextView
-        android:id="@+id/txtvTitle"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginVertical="12dp"
-        android:ellipsize="end"
-        android:maxLines="2"
-        style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
-        tools:text="Feed item title"
-        tools:background="@android:color/holo_green_dark" />
-
-    <TextView
-        android:id="@+id/txtvDescription"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:ellipsize="end"
-        android:maxLines="2"
-        style="@style/AntennaPod.TextView.ListItemBody"
-        tools:text="Feed item description"
-        tools:background="@android:color/holo_green_dark" />
-
-    <Button
-        android:id="@+id/butPreview"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:text="@string/preview_episode"
-        android:layout_gravity="end|right"
-        style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/onlinefeedview_activity.xml b/app/src/main/res/layout/onlinefeedview_activity.xml
index 88b87da1aff..a121c9e0eda 100644
--- a/app/src/main/res/layout/onlinefeedview_activity.xml
+++ b/app/src/main/res/layout/onlinefeedview_activity.xml
@@ -2,7 +2,6 @@
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/transparentBackground"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -11,169 +10,22 @@
         android:id="@+id/card"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_margin="24dp"
+        android:layout_marginHorizontal="16dp"
+        android:layout_marginVertical="56dp"
         android:elevation="16dp"
         app:cardCornerRadius="8dp">
 
-        <FrameLayout
+        <androidx.fragment.app.FragmentContainerView
+            android:id="@+id/fragmentContainer"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="vertical">
-
-            <ProgressBar
-                android:id="@+id/progressBar"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                style="?android:attr/progressBarStyle" />
-
-            <LinearLayout
-                android:id="@+id/feed_display_container"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:orientation="vertical">
-
-                <RelativeLayout
-                    android:layout_width="match_parent"
-                    android:layout_height="@dimen/feeditemlist_header_height"
-                    android:layout_marginBottom="12dp"
-                    android:background="@color/feed_image_bg">
-
-                    <ImageView
-                        android:id="@+id/backgroundImage"
-                        android:layout_width="match_parent"
-                        android:layout_height="match_parent"
-                        android:scaleType="centerCrop" />
-
-                    <ImageView
-                        android:id="@+id/coverImage"
-                        android:layout_width="@dimen/thumbnail_length_onlinefeedview"
-                        android:layout_height="@dimen/thumbnail_length_onlinefeedview"
-                        android:layout_alignParentLeft="true"
-                        android:layout_alignParentStart="true"
-                        android:layout_alignParentTop="true"
-                        android:layout_centerVertical="true"
-                        android:layout_marginBottom="12dp"
-                        android:layout_marginLeft="16dp"
-                        android:layout_marginStart="16dp"
-                        android:layout_marginTop="24dp"
-                        android:background="@drawable/bg_rounded_corners"
-                        android:clipToOutline="true"
-                        android:importantForAccessibility="no"
-                        tools:src="@tools:sample/avatars" />
-
-                    <TextView
-                        android:id="@+id/titleLabel"
-                        android:layout_width="0dp"
-                        android:layout_height="wrap_content"
-                        android:layout_alignParentTop="true"
-                        android:layout_marginBottom="8dp"
-                        android:layout_marginLeft="16dp"
-                        android:layout_marginStart="16dp"
-                        android:layout_marginTop="24dp"
-                        android:layout_marginRight="24dp"
-                        android:layout_marginEnd="24dp"
-                        android:layout_alignParentEnd="true"
-                        android:layout_alignParentRight="true"
-                        android:layout_toRightOf="@id/coverImage"
-                        android:layout_toEndOf="@id/coverImage"
-                        android:ellipsize="end"
-                        android:maxLines="2"
-                        android:shadowColor="@color/black"
-                        android:shadowRadius="3"
-                        android:textColor="@color/white"
-                        android:textSize="20sp"
-                        android:textFontWeight="800"
-                        tools:text="Podcast title" />
-
-                    <TextView
-                        android:id="@+id/author_label"
-                        android:layout_width="0dip"
-                        android:layout_height="wrap_content"
-                        android:layout_below="@id/titleLabel"
-                        android:layout_marginBottom="16dp"
-                        android:layout_marginLeft="16dp"
-                        android:layout_marginStart="16dp"
-                        android:layout_marginRight="16dp"
-                        android:layout_marginEnd="16dp"
-                        android:layout_alignParentEnd="true"
-                        android:layout_alignParentRight="true"
-                        android:layout_toRightOf="@id/coverImage"
-                        android:layout_toEndOf="@id/coverImage"
-                        android:ellipsize="end"
-                        android:lines="1"
-                        android:shadowColor="@color/black"
-                        android:shadowRadius="3"
-                        android:textColor="@color/white"
-                        android:textSize="@dimen/text_size_small"
-                        tools:text="Podcast author" />
-
-                    <ImageButton
-                        android:id="@+id/closeButton"
-                        android:layout_width="16dp"
-                        android:layout_height="16dp"
-                        android:layout_alignParentRight="true"
-                        android:layout_marginTop="12dp"
-                        android:layout_marginRight="12dp"
-                        android:background="@android:color/transparent"
-                        android:src="@drawable/ic_close_white" />
-
-                </RelativeLayout>
-
-                <LinearLayout
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:paddingHorizontal="16dp"
-                    android:orientation="vertical">
-
-                    <Spinner
-                        android:id="@+id/alternate_urls_spinner"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:dropDownWidth="match_parent"
-                        android:padding="8dp"
-                        android:textColor="?android:attr/textColorPrimary"
-                        android:textSize="@dimen/text_size_micro" />
-
-                    <Button
-                        android:id="@+id/subscribeButton"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_marginTop="4dp"
-                        android:text="@string/subscribe_label" />
-
-                    <CheckBox
-                        android:id="@+id/autoDownloadCheckBox"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="left"
-                        android:checked="true"
-                        android:layout_marginTop="8dp"
-                        android:text="@string/auto_download_label"
-                        android:visibility="gone"
-                        tools:visibility="visible" />
-
-                    <Button
-                        android:id="@+id/stopPreviewButton"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_marginTop="4dp"
-                        android:text="@string/stop_preview"
-                        android:visibility="gone"
-                        tools:visibility="visible" />
-
-                </LinearLayout>
-
-                <ListView
-                    android:id="@+id/listView"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:paddingTop="16dp"
-                    android:clipToPadding="false" />
-
-            </LinearLayout>
-
-        </FrameLayout>
+            android:layout_height="match_parent" />
+
+        <ProgressBar
+            android:id="@+id/progressBar"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            style="?android:attr/progressBarStyle" />
 
     </androidx.cardview.widget.CardView>
 
diff --git a/app/src/main/res/layout/onlinefeedview_header.xml b/app/src/main/res/layout/onlinefeedview_header.xml
deleted file mode 100644
index 6d740c772bc..00000000000
--- a/app/src/main/res/layout/onlinefeedview_header.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingLeft="20dp"
-    android:paddingRight="20dp"
-    android:layout_marginBottom="8dp">
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="8dp"
-        android:text="@string/description_label"
-        style="@style/TextAppearance.Material3.TitleMedium" />
-
-    <TextView
-        android:id="@+id/txtvDescription"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="16dp"
-        android:ellipsize="end"
-        android:lineHeight="20dp"
-        style="@style/AntennaPod.TextView.ListItemBody"
-        tools:text="@string/design_time_lorem_ipsum" />
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="16dp"
-        android:text="@string/episodes_label"
-        style="@style/TextAppearance.Material3.TitleMedium" />
-
-</LinearLayout>
diff --git a/model/src/main/java/de/danoeh/antennapod/model/feed/Feed.java b/model/src/main/java/de/danoeh/antennapod/model/feed/Feed.java
index 15d256c244e..634d3440d72 100644
--- a/model/src/main/java/de/danoeh/antennapod/model/feed/Feed.java
+++ b/model/src/main/java/de/danoeh/antennapod/model/feed/Feed.java
@@ -15,6 +15,8 @@
 public class Feed {
 
     public static final int FEEDFILETYPE_FEED = 0;
+    public static final int STATE_SUBSCRIBED = 0;
+    public static final int STATE_NOT_SUBSCRIBED = 1;
     public static final String TYPE_RSS2 = "rss";
     public static final String TYPE_ATOM1 = "atom";
     public static final String PREFIX_LOCAL_FOLDER = "antennapod_local:";
@@ -101,6 +103,7 @@ public class Feed {
      */
     @Nullable
     private SortOrder sortOrder;
+    private int state;
 
     /**
      * This constructor is used for restoring a feed from the database.
@@ -109,7 +112,7 @@ public Feed(long id, String lastModified, String title, String customTitle, Stri
                 String description, String paymentLinks, String author, String language,
                 String type, String feedIdentifier, String imageUrl, String fileUrl,
                 String downloadUrl, long lastRefreshAttempt, boolean paged, String nextPageLink,
-                String filter, @Nullable SortOrder sortOrder, boolean lastUpdateFailed) {
+                String filter, @Nullable SortOrder sortOrder, boolean lastUpdateFailed, int state) {
         this.localFileUrl = fileUrl;
         this.downloadUrl = downloadUrl;
         this.lastRefreshAttempt = lastRefreshAttempt;
@@ -135,6 +138,7 @@ public Feed(long id, String lastModified, String title, String customTitle, Stri
         }
         setSortOrder(sortOrder);
         this.lastUpdateFailed = lastUpdateFailed;
+        this.state = state;
     }
 
     /**
@@ -144,7 +148,7 @@ public Feed(long id, String lastModified, String title, String link, String desc
                 String author, String language, String type, String feedIdentifier, String imageUrl, String fileUrl,
                 String downloadUrl, long lastRefreshAttempt) {
         this(id, lastModified, title, null, link, description, paymentLink, author, language, type, feedIdentifier,
-                imageUrl, fileUrl, downloadUrl, lastRefreshAttempt, false, null, null, null, false);
+                imageUrl, fileUrl, downloadUrl, lastRefreshAttempt, false, null, null, null, false, STATE_SUBSCRIBED);
     }
 
     /**
@@ -468,4 +472,12 @@ public void setLastUpdateFailed(boolean lastUpdateFailed) {
     public boolean isLocalFeed() {
         return downloadUrl.startsWith(PREFIX_LOCAL_FOLDER);
     }
+
+    public int getState() {
+        return state;
+    }
+
+    public void setState(int state) {
+        this.state = state;
+    }
 }
diff --git a/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java b/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java
index 95a7a611025..1faeda01220 100644
--- a/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java
+++ b/model/src/main/java/de/danoeh/antennapod/model/feed/FeedItemFilter.java
@@ -24,6 +24,7 @@ public class FeedItemFilter implements Serializable {
     public final boolean showIsFavorite;
     public final boolean showNotFavorite;
     public final boolean showInHistory;
+    public final boolean includeNotSubscribed;
 
     public static final String PLAYED = "played";
     public static final String UNPLAYED = "unplayed";
@@ -39,6 +40,7 @@ public class FeedItemFilter implements Serializable {
     public static final String DOWNLOADED = "downloaded";
     public static final String NOT_DOWNLOADED = "not_downloaded";
     public static final String IS_IN_HISTORY = "is_in_history";
+    public static final String INCLUDE_NOT_SUBSCRIBED = "include_not_subscribed";
 
     public static FeedItemFilter unfiltered() {
         return new FeedItemFilter("");
@@ -48,6 +50,10 @@ public FeedItemFilter(String properties) {
         this(TextUtils.split(properties, ","));
     }
 
+    public FeedItemFilter(FeedItemFilter filter, String... additionalProperties) {
+        this(TextUtils.join(",", filter.getValues()) + "," + TextUtils.join(",", additionalProperties));
+    }
+
     public FeedItemFilter(String... properties) {
         this.properties = properties;
 
@@ -66,6 +72,7 @@ public FeedItemFilter(String... properties) {
         showNotFavorite = hasProperty(NOT_FAVORITE);
         showNew = hasProperty(NEW);
         showInHistory = hasProperty(IS_IN_HISTORY);
+        includeNotSubscribed = hasProperty(INCLUDE_NOT_SUBSCRIBED);
     }
 
     private boolean hasProperty(String property) {
@@ -112,6 +119,9 @@ public boolean matches(FeedItem item) {
         } else if (showInHistory && item.getMedia() != null
                 && item.getMedia().getPlaybackCompletionDate().getTime() == 0) {
             return false;
+        } else if (!includeNotSubscribed && item.getFeed() != null
+                && item.getFeed().getState() != Feed.STATE_SUBSCRIBED) {
+            return false;
         }
         return true;
     }
diff --git a/model/src/main/java/de/danoeh/antennapod/model/feed/SubscriptionsFilter.java b/model/src/main/java/de/danoeh/antennapod/model/feed/SubscriptionsFilter.java
index 434d474a795..2d584adef85 100644
--- a/model/src/main/java/de/danoeh/antennapod/model/feed/SubscriptionsFilter.java
+++ b/model/src/main/java/de/danoeh/antennapod/model/feed/SubscriptionsFilter.java
@@ -12,6 +12,7 @@ public class SubscriptionsFilter {
     private final String[] properties;
 
     private boolean showIfCounterGreaterZero = false;
+    private boolean hideNonSubscribedFeeds = true;
 
     private boolean showAutoDownloadEnabled = false;
     private boolean showAutoDownloadDisabled = false;
@@ -67,10 +68,6 @@ public boolean isEnabled() {
      * Run a list of feed items through the filter.
      */
     public List<Feed> filter(List<Feed> items, Map<Long, Integer> feedCounters) {
-        if (properties.length == 0) {
-            return items;
-        }
-
         List<Feed> result = new ArrayList<>();
 
         for (Feed item : items) {
@@ -95,6 +92,10 @@ public List<Feed> filter(List<Feed> items, Map<Long, Integer> feedCounters) {
                 continue;
             }
 
+            if (hideNonSubscribedFeeds && item.getState() != Feed.STATE_SUBSCRIBED) {
+                continue;
+            }
+
             // If the item reaches here, it meets all criteria (except counter > 0)
             result.add(item);
         }
diff --git a/net/discovery/src/main/java/de/danoeh/antennapod/net/discovery/ItunesTopListLoader.java b/net/discovery/src/main/java/de/danoeh/antennapod/net/discovery/ItunesTopListLoader.java
index 128aad5939c..c837a14efc8 100644
--- a/net/discovery/src/main/java/de/danoeh/antennapod/net/discovery/ItunesTopListLoader.java
+++ b/net/discovery/src/main/java/de/danoeh/antennapod/net/discovery/ItunesTopListLoader.java
@@ -58,7 +58,8 @@ private static List<PodcastSearchResult> removeSubscribed(
             List<PodcastSearchResult> suggestedPodcasts, List<Feed> subscribedFeeds, int limit) {
         Set<String> subscribedPodcastsSet = new HashSet<>();
         for (Feed subscribedFeed : subscribedFeeds) {
-            if (subscribedFeed.getTitle() != null && subscribedFeed.getAuthor() != null) {
+            if (subscribedFeed.getTitle() != null && subscribedFeed.getAuthor() != null
+                    && subscribedFeed.getState() == Feed.STATE_SUBSCRIBED) {
                 subscribedPodcastsSet.add(subscribedFeed.getTitle().trim() + " - " + subscribedFeed.getAuthor().trim());
             }
         }
diff --git a/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/episode/MediaDownloadedHandler.java b/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/episode/MediaDownloadedHandler.java
index 96c1549e2a3..cf9ec17e19f 100644
--- a/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/episode/MediaDownloadedHandler.java
+++ b/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/episode/MediaDownloadedHandler.java
@@ -7,6 +7,7 @@
 import androidx.annotation.NonNull;
 
 import de.danoeh.antennapod.model.MediaMetadataRetrieverCompat;
+import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.net.sync.serviceinterface.SynchronizationQueueSink;
 import de.danoeh.antennapod.ui.chapters.ChapterUtils;
 import org.greenrobot.eventbus.EventBus;
@@ -104,7 +105,7 @@ public void run() {
                     FeedMedia.FEEDFILETYPE_FEEDMEDIA, false, DownloadError.ERROR_DB_ACCESS_ERROR, e.getMessage());
         }
 
-        if (item != null) {
+        if (item != null && item.getFeed().getState() == Feed.STATE_SUBSCRIBED) {
             EpisodeAction action = new EpisodeAction.Builder(item, EpisodeAction.DOWNLOAD)
                     .currentTimestamp()
                     .build();
diff --git a/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/feed/FeedUpdateWorker.java b/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/feed/FeedUpdateWorker.java
index 9e363b58524..b5174dfcb8d 100644
--- a/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/feed/FeedUpdateWorker.java
+++ b/net/download/service/src/main/java/de/danoeh/antennapod/net/download/service/feed/FeedUpdateWorker.java
@@ -35,6 +35,7 @@
 
 import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequestBuilder;
 import de.danoeh.antennapod.parser.feed.FeedHandlerResult;
+import de.danoeh.antennapod.storage.database.NonSubscribedFeedsCleaner;
 import de.danoeh.antennapod.ui.notifications.NotificationUtils;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -69,7 +70,7 @@ public Result doWork() {
             Iterator<Feed> itr = toUpdate.iterator();
             while (itr.hasNext()) {
                 Feed feed = itr.next();
-                if (!feed.getPreferences().getKeepUpdated()) {
+                if (!feed.getPreferences().getKeepUpdated() || feed.getState() != Feed.STATE_SUBSCRIBED) {
                     itr.remove();
                     continue;
                 }
@@ -99,8 +100,9 @@ public Result doWork() {
         }
         refreshFeeds(toUpdate,  force);
 
-        notificationManager.cancel(R.id.notification_updating_feeds);
+        NonSubscribedFeedsCleaner.deleteOldNonSubscribedFeeds(getApplicationContext());
         AutoDownloadManager.getInstance().autodownloadUndownloadedItems(getApplicationContext());
+        notificationManager.cancel(R.id.notification_updating_feeds);
         return Result.success();
     }
 
diff --git a/net/sync/service-interface/src/main/java/de/danoeh/antennapod/net/sync/serviceinterface/SynchronizationQueueSink.java b/net/sync/service-interface/src/main/java/de/danoeh/antennapod/net/sync/serviceinterface/SynchronizationQueueSink.java
index ad235130a2e..e617dfc7816 100644
--- a/net/sync/service-interface/src/main/java/de/danoeh/antennapod/net/sync/serviceinterface/SynchronizationQueueSink.java
+++ b/net/sync/service-interface/src/main/java/de/danoeh/antennapod/net/sync/serviceinterface/SynchronizationQueueSink.java
@@ -2,6 +2,7 @@
 
 import android.content.Context;
 
+import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.storage.preferences.SynchronizationSettings;
 import de.danoeh.antennapod.model.feed.FeedMedia;
 
@@ -62,7 +63,8 @@ public static void enqueueEpisodePlayedIfSynchronizationIsActive(Context context
         if (!SynchronizationSettings.isProviderConnected()) {
             return;
         }
-        if (media.getItem() == null || media.getItem().getFeed().isLocalFeed()) {
+        if (media.getItem() == null || media.getItem().getFeed().isLocalFeed()
+                || media.getItem().getFeed().getState() != Feed.STATE_SUBSCRIBED) {
             return;
         }
         if (media.getStartPosition() < 0 || (!completed && media.getStartPosition() >= media.getPosition())) {
diff --git a/playback/service/src/main/java/de/danoeh/antennapod/playback/service/PlaybackService.java b/playback/service/src/main/java/de/danoeh/antennapod/playback/service/PlaybackService.java
index 5fa89dd43d3..7d20124cf38 100644
--- a/playback/service/src/main/java/de/danoeh/antennapod/playback/service/PlaybackService.java
+++ b/playback/service/src/main/java/de/danoeh/antennapod/playback/service/PlaybackService.java
@@ -436,7 +436,9 @@ private List<MediaBrowserCompat.MediaItem> loadChildrenSynchronous(@NonNull Stri
                     DBReader.getTotalEpisodeCount(new FeedItemFilter(FeedItemFilter.UNPLAYED))));
             List<Feed> feeds = DBReader.getFeedList();
             for (Feed feed : feeds) {
-                mediaItems.add(createBrowsableMediaItemForFeed(feed));
+                if (feed.getState() == Feed.STATE_SUBSCRIBED) {
+                    mediaItems.add(createBrowsableMediaItemForFeed(feed));
+                }
             }
             return mediaItems;
         }
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBReader.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBReader.java
index 4329903796d..272df504886 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBReader.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBReader.java
@@ -356,7 +356,9 @@ public static Feed getFeed(final long feedId, boolean filtered, int offset, int
         try (FeedCursor cursor = new FeedCursor(adapter.getFeedCursor(feedId))) {
             if (cursor.moveToNext()) {
                 feed = cursor.getFeed();
-                FeedItemFilter filter = filtered ? feed.getItemFilter() : FeedItemFilter.unfiltered();
+                FeedItemFilter filter = (filtered && feed.getItemFilter() != null)
+                        ? feed.getItemFilter() : FeedItemFilter.unfiltered();
+                filter = new FeedItemFilter(filter, FeedItemFilter.INCLUDE_NOT_SUBSCRIBED);
                 List<FeedItem> items = getFeedItemList(feed, filter, feed.getSortOrder(), offset, limit);
                 for (FeedItem item : items) {
                     item.setFeed(feed);
@@ -668,9 +670,10 @@ public static NavDrawerData getNavDrawerData(@Nullable SubscriptionsFilter subsc
         final Map<Long, Integer> feedCounters = adapter.getFeedCounters(feedCounter);
         List<Feed> feeds = getFeedList();
 
-        if (subscriptionsFilter != null) {
-            feeds = subscriptionsFilter.filter(feeds, feedCounters);
+        if (subscriptionsFilter == null) {
+            subscriptionsFilter = new SubscriptionsFilter("");
         }
+        feeds = subscriptionsFilter.filter(feeds, feedCounters);
 
         Comparator<Feed> comparator;
         switch (feedOrder) {
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java
index 19a02972de8..be09a5132e8 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBUpgrader.java
@@ -6,6 +6,7 @@
 import android.media.MediaMetadataRetriever;
 import android.util.Log;
 
+import de.danoeh.antennapod.model.feed.Feed;
 import de.danoeh.antennapod.model.feed.FeedItem;
 
 import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL;
@@ -338,6 +339,10 @@ static void upgrade(final SQLiteDatabase db, final int oldVersion, final int new
             db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
                     + " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_SILENCE + " INTEGER");
         }
+        if (oldVersion < 3050000) {
+            db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+                    + " ADD COLUMN " + PodDBAdapter.KEY_STATE + " INTEGER DEFAULT " + Feed.STATE_SUBSCRIBED);
+        }
     }
 
 }
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBWriter.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBWriter.java
index 5f684b3985d..11e1ad75109 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBWriter.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/DBWriter.java
@@ -14,6 +14,7 @@
 import com.google.common.util.concurrent.Futures;
 import de.danoeh.antennapod.event.DownloadLogEvent;
 
+import de.danoeh.antennapod.model.feed.FeedItemFilter;
 import de.danoeh.antennapod.net.download.serviceinterface.AutoDownloadManager;
 import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
 import de.danoeh.antennapod.net.download.serviceinterface.FeedUpdateManager;
@@ -141,12 +142,13 @@ private static boolean deleteFeedMediaSynchronous(@NonNull Context context, @Non
             // Do full update of this feed to get rid of the item
             FeedUpdateManager.getInstance().runOnce(context, media.getItem().getFeed());
         } else {
-            // Gpodder: queue delete action for synchronization
-            FeedItem item = media.getItem();
-            EpisodeAction action = new EpisodeAction.Builder(item, EpisodeAction.DELETE)
-                    .currentTimestamp()
-                    .build();
-            SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, action);
+            if (media.getItem().getFeed().getState() == Feed.STATE_SUBSCRIBED) {
+                FeedItem item = media.getItem();
+                EpisodeAction action = new EpisodeAction.Builder(item, EpisodeAction.DELETE)
+                        .currentTimestamp()
+                        .build();
+                SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, action);
+            }
 
             EventBus.getDefault().post(FeedItemEvent.updated(media.getItem()));
         }
@@ -174,7 +176,7 @@ public static Future<?> deleteFeed(final Context context, final long feedId) {
             adapter.removeFeed(feed);
             adapter.close();
 
-            if (!feed.isLocalFeed()) {
+            if (!feed.isLocalFeed() && feed.getState() == Feed.STATE_SUBSCRIBED) {
                 SynchronizationQueueSink.enqueueFeedRemovedIfSynchronizationIsActive(context, feed.getDownloadUrl());
             }
             EventBus.getDefault().post(new FeedListUpdateEvent(feed));
@@ -786,7 +788,7 @@ static Future<?> addNewFeed(final Context context, final Feed... feeds) {
             adapter.close();
 
             for (Feed feed : feeds) {
-                if (!feed.isLocalFeed()) {
+                if (!feed.isLocalFeed() && feed.getState() == Feed.STATE_SUBSCRIBED) {
                     SynchronizationQueueSink.enqueueFeedAddedIfSynchronizationIsActive(context, feed.getDownloadUrl());
                 }
             }
@@ -928,6 +930,32 @@ public static Future<?> setFeedCustomTitle(Feed feed) {
         });
     }
 
+    public static Future<?> setFeedState(Context context, Feed feed, int newState) {
+        int oldState = feed.getState();
+        return runOnDbThread(() -> {
+            PodDBAdapter adapter = PodDBAdapter.getInstance();
+            adapter.open();
+            adapter.setFeedState(feed.getId(), newState);
+            feed.setState(newState);
+            if (oldState == Feed.STATE_NOT_SUBSCRIBED && newState == Feed.STATE_SUBSCRIBED) {
+                feed.getPreferences().setKeepUpdated(true);
+                DBWriter.setFeedPreferences(feed.getPreferences());
+                FeedUpdateManager.getInstance().runOnceOrAsk(context, feed);
+                SynchronizationQueueSink.enqueueFeedAddedIfSynchronizationIsActive(context, feed.getDownloadUrl());
+                DBReader.getFeedItemList(feed, FeedItemFilter.unfiltered(),
+                        SortOrder.DATE_NEW_OLD, 0, Integer.MAX_VALUE);
+                for (FeedItem item : feed.getItems()) {
+                    if (item.isPlayed()) {
+                        SynchronizationQueueSink.enqueueEpisodePlayedIfSynchronizationIsActive(
+                                context, item.getMedia(), true);
+                    }
+                }
+            }
+            adapter.close();
+            EventBus.getDefault().post(new FeedListUpdateEvent(feed));
+        });
+    }
+
     /**
      * Sort the FeedItems in the queue with the given the named sort order.
      *
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedDatabaseWriter.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedDatabaseWriter.java
index 7269fcd55f1..a62e18809ba 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedDatabaseWriter.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/FeedDatabaseWriter.java
@@ -157,7 +157,8 @@ public static synchronized Feed updateFeed(Context context, Feed newFeed, boolea
                                         + "\n\nNow the feed contains:\n" + duplicateEpisodeDetails(item)));
                         oldItem.setItemIdentifier(item.getItemIdentifier());
 
-                        if (oldItem.isPlayed() && oldItem.getMedia() != null) {
+                        if (oldItem.isPlayed() && oldItem.getMedia() != null
+                                && savedFeed.getState() == Feed.STATE_SUBSCRIBED) {
                             EpisodeAction action = new EpisodeAction.Builder(oldItem, EpisodeAction.PLAY)
                                     .currentTimestamp()
                                     .started(oldItem.getMedia().getDuration() / 1000)
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/NonSubscribedFeedsCleaner.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/NonSubscribedFeedsCleaner.java
new file mode 100644
index 00000000000..47a5a5aeef6
--- /dev/null
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/NonSubscribedFeedsCleaner.java
@@ -0,0 +1,46 @@
+package de.danoeh.antennapod.storage.database;
+
+import android.content.Context;
+import android.util.Log;
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.model.feed.FeedItem;
+import de.danoeh.antennapod.model.feed.FeedItemFilter;
+import de.danoeh.antennapod.model.feed.SortOrder;
+
+import java.util.List;
+
+public class NonSubscribedFeedsCleaner {
+    private static final String TAG = "NonSubscrFeedsCleaner";
+    private static final long TIME_TO_KEEP = 1000L * 3600 * 24 * 30; // 30 days
+
+    public static void deleteOldNonSubscribedFeeds(Context context) {
+        List<Feed> feeds = DBReader.getFeedList();
+        for (Feed feed : feeds) {
+            if (feed.getState() != Feed.STATE_NOT_SUBSCRIBED) {
+                continue;
+            }
+            DBReader.getFeedItemList(feed, FeedItemFilter.unfiltered(), SortOrder.DATE_NEW_OLD, 0, Integer.MAX_VALUE);
+            if (shouldDelete(feed)) {
+                Log.d(TAG, "Deleting unsubscribed feed " + feed.getTitle());
+                DBWriter.deleteFeed(context, feed.getId());
+            }
+            feed.setItems(null); // Let it be garbage collected
+        }
+    }
+
+    public static boolean shouldDelete(Feed feed) {
+        if (feed.getState() != Feed.STATE_NOT_SUBSCRIBED) {
+            return false;
+        } else if (feed.getItems() == null) {
+            return false;
+        }
+        for (FeedItem item : feed.getItems()) {
+            if (item.isTagged(FeedItem.TAG_FAVORITE)
+                    || item.isTagged(FeedItem.TAG_QUEUE)
+                    || item.isDownloaded()) {
+                return false;
+            }
+        }
+        return feed.getLastRefreshAttempt() < System.currentTimeMillis() - TIME_TO_KEEP;
+    }
+}
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java
index 2cbf275090e..aec136457d1 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/PodDBAdapter.java
@@ -52,7 +52,7 @@ public class PodDBAdapter {
 
     private static final String TAG = "PodDBAdapter";
     public static final String DATABASE_NAME = "Antennapod.db";
-    public static final int VERSION = 3040000;
+    public static final int VERSION = 3050000;
 
     /**
      * Maximum number of arguments for IN-operator.
@@ -121,6 +121,7 @@ public class PodDBAdapter {
     public static final String KEY_EPISODE_NOTIFICATION = "episode_notification";
     public static final String KEY_NEW_EPISODES_ACTION = "new_episodes_action";
     public static final String KEY_PODCASTINDEX_CHAPTER_URL = "podcastindex_chapter_url";
+    public static final String KEY_STATE = "state";
 
     // Table names
     public static final String TABLE_NAME_FEEDS = "Feeds";
@@ -171,6 +172,7 @@ public class PodDBAdapter {
             + KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0,"
             + KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0,"
             + KEY_EPISODE_NOTIFICATION + " INTEGER DEFAULT 0,"
+            + KEY_STATE + " INTEGER DEFAULT " + Feed.STATE_SUBSCRIBED + ","
             + KEY_NEW_EPISODES_ACTION + " INTEGER DEFAULT 0)";
 
     private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
@@ -323,6 +325,7 @@ public class PodDBAdapter {
             + TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_INTRO + ", "
             + TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_ENDING + ", "
             + TABLE_NAME_FEEDS + "." + KEY_EPISODE_NOTIFICATION + ", "
+            + TABLE_NAME_FEEDS + "." + KEY_STATE + ", "
             + TABLE_NAME_FEEDS + "." + KEY_NEW_EPISODES_ACTION;
 
     private static final String JOIN_FEED_ITEM_AND_MEDIA = " LEFT JOIN " + TABLE_NAME_FEED_MEDIA
@@ -337,6 +340,9 @@ public class PodDBAdapter {
             "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA
             + " FROM " + TABLE_NAME_FEED_ITEMS
             + JOIN_FEED_ITEM_AND_MEDIA;
+    public static final String SELECT_WHERE_FEED_IS_SUBSCRIBED = TABLE_NAME_FEED_ITEMS + "." + KEY_FEED
+            + " IN (SELECT " + KEY_ID + " FROM " + TABLE_NAME_FEEDS
+            + " WHERE " + KEY_STATE + "=" + Feed.STATE_SUBSCRIBED + ")";
 
     private static Context context;
     private static PodDBAdapter instance;
@@ -431,6 +437,7 @@ private long setFeed(Feed feed) {
         values.put(KEY_LASTUPDATE, feed.getLastModified());
         values.put(KEY_TYPE, feed.getType());
         values.put(KEY_FEED_IDENTIFIER, feed.getFeedIdentifier());
+        values.put(KEY_STATE, feed.getState());
 
         values.put(KEY_IS_PAGED, feed.isPaged());
         values.put(KEY_NEXT_PAGE_LINK, feed.getNextPageLink());
@@ -768,6 +775,12 @@ public void setFeedCustomTitle(long feedId, String customTitle) {
         db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
     }
 
+    public void setFeedState(long feedId, int state) {
+        ContentValues values = new ContentValues();
+        values.put(KEY_STATE, state);
+        db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
+    }
+
     /**
      * Inserts or updates a download status.
      */
@@ -1101,6 +1114,7 @@ public Cursor getRandomEpisodesCursor(int limit, int seed) {
                     // Hide episodes that have been played but not completed
                     + " AND (" + KEY_LAST_PLAYED_TIME + " == 0"
                         + " OR " + KEY_LAST_PLAYED_TIME + " > " + (System.currentTimeMillis() - 1000L * 3600L) + ")"
+                    + " AND " + SELECT_WHERE_FEED_IS_SUBSCRIBED
                 + " ORDER BY " + randomEpisodeNumber(seed);
         final String query = "SELECT * FROM (" + allItemsRandomOrder + ")"
                 + " GROUP BY " + KEY_FEED
@@ -1221,6 +1235,7 @@ public final Cursor getFeedStatisticsCursor(boolean includeMarkedAsPlayed, long
                 + JOIN_FEED_ITEM_AND_MEDIA
                 + " INNER JOIN " + TABLE_NAME_FEEDS
                 + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID
+                + " WHERE " + TABLE_NAME_FEEDS + "." + KEY_STATE + "=" + Feed.STATE_SUBSCRIBED
                 + " GROUP BY " + TABLE_NAME_FEEDS + "." + KEY_ID;
         return db.rawQuery(query, null);
     }
@@ -1372,7 +1387,7 @@ public Cursor searchItems(long feedID, String searchQuery) {
         }
 
         String queryStart = SELECT_FEED_ITEMS_AND_MEDIA_WITH_DESCRIPTION
-                + " WHERE " + queryFeedId + " AND (";
+                + " WHERE " + queryFeedId + " AND " + SELECT_WHERE_FEED_IS_SUBSCRIBED + " AND (";
         StringBuilder sb = new StringBuilder(queryStart);
 
         for (int i = 0; i < queryWords.length; i++) {
@@ -1401,12 +1416,13 @@ public Cursor searchItems(long feedID, String searchQuery) {
     public Cursor searchFeeds(String searchQuery) {
         String[] queryWords = prepareSearchQuery(searchQuery);
 
-        String queryStart = "SELECT " + KEYS_FEED + " FROM " + TABLE_NAME_FEEDS + " WHERE ";
+        String queryStart = "SELECT " + KEYS_FEED + " FROM " + TABLE_NAME_FEEDS
+                + " WHERE " + KEY_STATE + " = " + Feed.STATE_SUBSCRIBED;
         StringBuilder sb = new StringBuilder(queryStart);
 
         for (int i = 0; i < queryWords.length; i++) {
             sb
-                    .append("(")
+                    .append(" AND (")
                     .append(KEY_TITLE).append(" LIKE '%").append(queryWords[i])
                     .append("%' OR ")
                     .append(KEY_CUSTOM_TITLE).append(" LIKE '%").append(queryWords[i])
@@ -1415,13 +1431,9 @@ public Cursor searchFeeds(String searchQuery) {
                     .append("%' OR ")
                     .append(KEY_DESCRIPTION).append(" LIKE '%").append(queryWords[i])
                     .append("%') ");
-
-            if (i != queryWords.length - 1) {
-                sb.append("AND ");
-            }
         }
 
-        sb.append("ORDER BY " + KEY_TITLE + " ASC LIMIT 300");
+        sb.append(" ORDER BY " + KEY_TITLE + " ASC LIMIT 300");
 
         return db.rawQuery(sb.toString(), null);
     }
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedCursor.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedCursor.java
index 2707275caab..3aba6910635 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedCursor.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedCursor.java
@@ -34,6 +34,7 @@ public class FeedCursor extends CursorWrapper {
     private final int indexSortOrder;
     private final int indexLastUpdateFailed;
     private final int indexImageUrl;
+    private final int indexState;
 
     public FeedCursor(Cursor cursor) {
         super(new FeedPreferencesCursor(cursor));
@@ -58,6 +59,7 @@ public FeedCursor(Cursor cursor) {
         indexSortOrder = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_SORT_ORDER);
         indexLastUpdateFailed = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LAST_UPDATE_FAILED);
         indexImageUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_IMAGE_URL);
+        indexState = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_STATE);
     }
 
     /**
@@ -85,7 +87,8 @@ public Feed getFeed() {
                 getString(indexNextPageLink),
                 getString(indexHide),
                 SortOrder.fromCodeString(getString(indexSortOrder)),
-                getInt(indexLastUpdateFailed) > 0);
+                getInt(indexLastUpdateFailed) > 0,
+                getInt(indexState));
         feed.setPreferences(preferencesCursor.getFeedPreferences());
         return feed;
     }
diff --git a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedItemFilterQuery.java b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedItemFilterQuery.java
index a4794d324db..481107cfac2 100644
--- a/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedItemFilterQuery.java
+++ b/storage/database/src/main/java/de/danoeh/antennapod/storage/database/mapper/FeedItemFilterQuery.java
@@ -66,6 +66,9 @@ public static String generateFrom(FeedItemFilter filter) {
         if (filter.showInHistory) {
             statements.add(keyCompletionDate + " > 0 ");
         }
+        if (!filter.includeNotSubscribed) {
+            statements.add(PodDBAdapter.SELECT_WHERE_FEED_IS_SUBSCRIBED);
+        }
 
         if (statements.isEmpty()) {
             return "";
diff --git a/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/HtmlWriter.java b/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/HtmlWriter.java
index 0b162fab0f6..d259db43b10 100644
--- a/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/HtmlWriter.java
+++ b/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/HtmlWriter.java
@@ -28,6 +28,9 @@ public static void writeDocument(List<Feed> feeds, Writer writer, Context contex
 
         writer.append(templateParts[0]);
         for (Feed feed : feeds) {
+            if (feed.getState() != Feed.STATE_SUBSCRIBED) {
+                continue;
+            }
             writer.append("<li><div><img src=\"");
             writer.append(feed.getImageUrl());
             writer.append("\" /><p>");
diff --git a/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/OpmlWriter.java b/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/OpmlWriter.java
index 9701476f952..d06932a5e4b 100644
--- a/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/OpmlWriter.java
+++ b/storage/importexport/src/main/java/de/danoeh/antennapod/storage/importexport/OpmlWriter.java
@@ -48,6 +48,9 @@ public static void writeDocument(List<Feed> feeds, Writer writer)
 
         xs.startTag(null, OpmlSymbols.BODY);
         for (Feed feed : feeds) {
+            if (feed.getState() != Feed.STATE_SUBSCRIBED) {
+                continue;
+            }
             xs.startTag(null, OpmlSymbols.OUTLINE);
             xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle());
             xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle());
diff --git a/ui/common/src/main/res/drawable/bg_message_info.xml b/ui/common/src/main/res/drawable/bg_message_info.xml
new file mode 100644
index 00000000000..6543066cfdf
--- /dev/null
+++ b/ui/common/src/main/res/drawable/bg_message_info.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:aapt="http://schemas.android.com/aapt">
+    <stroke
+        android:width="2dp"
+        android:color="?attr/colorPrimary" />
+
+    <corners android:radius="8dp" />
+
+    <solid>
+        <aapt:attr name="android:color" >
+            <selector>
+                <item android:alpha="0.1" android:color="?attr/colorPrimary" />
+            </selector>
+        </aapt:attr>
+    </solid>
+</shape>
\ No newline at end of file
diff --git a/ui/common/src/main/res/drawable/bg_rounded_corners.xml b/ui/common/src/main/res/drawable/bg_rounded_corners.xml
deleted file mode 100644
index 11b7710c403..00000000000
--- a/ui/common/src/main/res/drawable/bg_rounded_corners.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <corners android:radius="8dp" />
-</shape>
diff --git a/ui/common/src/main/res/drawable/ic_close.xml b/ui/common/src/main/res/drawable/ic_close.xml
new file mode 100644
index 00000000000..ccba7f4a04f
--- /dev/null
+++ b/ui/common/src/main/res/drawable/ic_close.xml
@@ -0,0 +1,11 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M17.656,6.343L12,12M12,12L6.343,17.656M12,12L17.656,17.656M12,12L6.343,6.343"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="?attr/action_icon_color"/>
+</vector>
diff --git a/ui/common/src/main/res/values/colors.xml b/ui/common/src/main/res/values/colors.xml
index ad835faf470..55ba650e781 100644
--- a/ui/common/src/main/res/values/colors.xml
+++ b/ui/common/src/main/res/values/colors.xml
@@ -8,7 +8,6 @@
     <color name="medium_gray">#afafaf</color>
     <color name="black">#000000</color>
     <color name="image_readability_tint">#80000000</color>
-    <color name="feed_image_bg">#50000000</color>
     <color name="feed_text_bg">#55333333</color>
 
     <!-- Theme colors -->
diff --git a/ui/common/src/main/res/values/dimens.xml b/ui/common/src/main/res/values/dimens.xml
index 5cfcd68b62c..82c2b145176 100644
--- a/ui/common/src/main/res/values/dimens.xml
+++ b/ui/common/src/main/res/values/dimens.xml
@@ -7,8 +7,6 @@
     <dimen name="text_size_large">22sp</dimen>
     <dimen name="thumbnail_length_itemlist">56dp</dimen>
     <dimen name="thumbnail_length_queue_item">56dp</dimen>
-    <dimen name="thumbnail_length_onlinefeedview">92dp</dimen>
-    <dimen name="feeditemlist_header_height">132dp</dimen>
     <dimen name="thumbnail_length_navlist">40dp</dimen>
     <dimen name="listitem_iconwithtext_height">48dp</dimen>
     <dimen name="listitem_iconwithtext_textleftpadding">16dp</dimen>
diff --git a/ui/i18n/src/main/res/values/strings.xml b/ui/i18n/src/main/res/values/strings.xml
index a840a1abfe7..f5ac3c30646 100644
--- a/ui/i18n/src/main/res/values/strings.xml
+++ b/ui/i18n/src/main/res/values/strings.xml
@@ -681,9 +681,8 @@
 
     <!-- Online feed view -->
     <string name="subscribe_label">Subscribe</string>
-    <string name="subscribing_label">Subscribing&#8230;</string>
-    <string name="preview_episode">Preview</string>
-    <string name="stop_preview">Stop preview</string>
+    <string name="preview_episodes">Episodes preview</string>
+    <string name="state_deleted_not_subscribed">Playback state and history of non-subscribed podcasts are deleted after a while. Subscribe to keep them.</string>
 
     <!-- Content descriptions for image buttons -->
     <string name="toolbar_back_button_content_description">Back</string>


Test patch:
diff --git a/storage/database/src/test/java/de/danoeh/antennapod/storage/database/NonSubscribedFeedsCleanerTest.java b/storage/database/src/test/java/de/danoeh/antennapod/storage/database/NonSubscribedFeedsCleanerTest.java
new file mode 100644
index 00000000000..76bbfddc1a0
--- /dev/null
+++ b/storage/database/src/test/java/de/danoeh/antennapod/storage/database/NonSubscribedFeedsCleanerTest.java
@@ -0,0 +1,104 @@
+package de.danoeh.antennapod.storage.database;
+
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.model.feed.FeedItem;
+import de.danoeh.antennapod.model.feed.FeedMedia;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(RobolectricTestRunner.class)
+public class NonSubscribedFeedsCleanerTest {
+
+    @Test
+    public void testSubscribed() {
+        Feed feed = createFeed();
+        feed.setLastRefreshAttempt(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(200, TimeUnit.DAYS));
+        assertFalse(NonSubscribedFeedsCleaner.shouldDelete(feed));
+
+        feed.setState(Feed.STATE_NOT_SUBSCRIBED);
+        assertTrue(NonSubscribedFeedsCleaner.shouldDelete(feed));
+    }
+
+    @Test
+    public void testOldDate() {
+        Feed feed = createFeed();
+        feed.setState(Feed.STATE_NOT_SUBSCRIBED);
+        feed.setLastRefreshAttempt(System.currentTimeMillis());
+        assertFalse(NonSubscribedFeedsCleaner.shouldDelete(feed));
+
+        feed.setLastRefreshAttempt(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(10, TimeUnit.DAYS));
+        assertFalse(NonSubscribedFeedsCleaner.shouldDelete(feed));
+
+        feed.setLastRefreshAttempt(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(200, TimeUnit.DAYS));
+        assertTrue(NonSubscribedFeedsCleaner.shouldDelete(feed));
+
+        feed.setLastRefreshAttempt(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(200, TimeUnit.DAYS));
+        assertFalse(NonSubscribedFeedsCleaner.shouldDelete(feed));
+    }
+
+    @Test
+    public void testQueuedItem() {
+        Feed feed = createFeed();
+        feed.setState(Feed.STATE_NOT_SUBSCRIBED);
+        feed.setLastRefreshAttempt(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(200, TimeUnit.DAYS));
+        feed.getItems().add(createItem(feed));
+        assertTrue(NonSubscribedFeedsCleaner.shouldDelete(feed));
+
+        FeedItem queuedItem = createItem(feed);
+        queuedItem.addTag(FeedItem.TAG_QUEUE);
+        feed.getItems().add(queuedItem);
+        assertFalse(NonSubscribedFeedsCleaner.shouldDelete(feed));
+    }
+
+    @Test
+    public void testFavoriteItem() {
+        Feed feed = createFeed();
+        feed.setState(Feed.STATE_NOT_SUBSCRIBED);
+        feed.setLastRefreshAttempt(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(200, TimeUnit.DAYS));
+        feed.getItems().add(createItem(feed));
+        assertTrue(NonSubscribedFeedsCleaner.shouldDelete(feed));
+
+        FeedItem queuedItem = createItem(feed);
+        queuedItem.addTag(FeedItem.TAG_FAVORITE);
+        feed.getItems().add(queuedItem);
+        assertFalse(NonSubscribedFeedsCleaner.shouldDelete(feed));
+    }
+
+    @Test
+    public void testDownloadedItem() {
+        Feed feed = createFeed();
+        feed.setState(Feed.STATE_NOT_SUBSCRIBED);
+        feed.setLastRefreshAttempt(System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(200, TimeUnit.DAYS));
+        feed.getItems().add(createItem(feed));
+        assertTrue(NonSubscribedFeedsCleaner.shouldDelete(feed));
+
+        FeedItem queuedItem = createItem(feed);
+        queuedItem.getMedia().setDownloaded(true, System.currentTimeMillis());
+        feed.getItems().add(queuedItem);
+        assertFalse(NonSubscribedFeedsCleaner.shouldDelete(feed));
+    }
+
+    private Feed createFeed() {
+        Feed feed = new Feed(0, null, "title", "http://example.com", "This is the description",
+                "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed",
+                "http://example.com/image", null, "http://example.com/feed", System.currentTimeMillis());
+        feed.setItems(new ArrayList<>());
+        return feed;
+    }
+
+    private FeedItem createItem(Feed feed) {
+        FeedItem item = new FeedItem(0, "Item", "ItemId", "url", new Date(), FeedItem.PLAYED, feed);
+        FeedMedia media = new FeedMedia(item, "http://download.url.net/", 1234567, "audio/mpeg");
+        media.setId(item.getId());
+        item.setMedia(media);
+        return item;
+    }
+}