diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
index d09947837f4685eac6dc2d80c50161e1f867c12c..16cc1a7befee658ae7139e8aae3d3c7db2f0523d 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/HomeFragment.kt
@@ -141,10 +141,9 @@ class HomeFragment : MainFragment() {
 
             val feedstyleChanged = recyclerData.loadedFeedStyle != feedStyle;
             val clientsChanged = lastClients == null || lastClients.size != clients.size || !lastClients.containsAll(clients);
-            val outdated = recyclerData.lastLoad.getNowDiffSeconds() > 60;
-            Logger.i(TAG, "onShown (recyclerData.loadedFeedStyle=${recyclerData.loadedFeedStyle}, recyclerData.lastLoad=${recyclerData.lastLoad}, feedstyleChanged=$feedstyleChanged, clientsChanged=$clientsChanged, outdated=$outdated)")
+            Logger.i(TAG, "onShown (recyclerData.loadedFeedStyle=${recyclerData.loadedFeedStyle}, recyclerData.lastLoad=${recyclerData.lastLoad}, feedstyleChanged=$feedstyleChanged, clientsChanged=$clientsChanged)")
 
-            if(feedstyleChanged || outdated || clientsChanged) {
+            if(feedstyleChanged || clientsChanged) {
                 recyclerData.lastLoad = OffsetDateTime.now();
                 recyclerData.loadedFeedStyle = feedStyle;
                 recyclerData.lastClients = clients;
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt
index 1c706c286b595b7052082704ed0c2c595ef2a69a..25e96e1b8fe0d3c9979e8de26f38215b73af91e8 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/PlaylistFragment.kt
@@ -156,6 +156,14 @@ class PlaylistFragment : MainFragment() {
                 };
         }
 
+        private fun copyPlaylist(playlist: Playlist) {
+            StatePlaylists.instance.playlistStore.save(playlist)
+            _fragment.topBar?.assume<NavigationTopBarFragment>()?.setMenuItems(
+                arrayListOf()
+            )
+            UIDialogs.toast("Playlist saved")
+        }
+
         fun onShown(parameter: Any?) {
             _taskLoadPlaylist.cancel()
 
@@ -170,14 +178,10 @@ class PlaylistFragment : MainFragment() {
                     setButtonDownloadVisible(true)
                     setButtonEditVisible(true)
 
-                    if (!StatePlaylists.instance.playlistStore.getItems().contains(parameter)) {
+                    if (!StatePlaylists.instance.playlistStore.hasItem { it.id == parameter.id }) {
                         _fragment.topBar?.assume<NavigationTopBarFragment>()
                             ?.setMenuItems(arrayListOf(Pair(R.drawable.ic_copy) {
-                                StatePlaylists.instance.playlistStore.save(parameter)
-                                _fragment.topBar?.assume<NavigationTopBarFragment>()?.setMenuItems(
-                                    arrayListOf()
-                                )
-                                UIDialogs.toast("Playlist saved")
+                                copyPlaylist(parameter)
                             }))
                     }
                 } else {
@@ -242,6 +246,15 @@ class PlaylistFragment : MainFragment() {
         }
 
         private fun download() {
+            val playlist = _playlist ?: return
+            if (!StatePlaylists.instance.playlistStore.hasItem { it.id == playlist.id }) {
+                UIDialogs.showConfirmationDialog(context, "Playlist must be saved to download", {
+                    copyPlaylist(playlist)
+                    download()
+                })
+                return
+            }
+
             _playlist?.let {
                 UISlideOverlays.showDownloadPlaylistOverlay(it, overlayContainer);
             }
@@ -266,6 +279,15 @@ class PlaylistFragment : MainFragment() {
         override fun canEdit(): Boolean { return _playlist != null; }
 
         override fun onEditClick() {
+            val playlist = _playlist ?: return
+            if (!StatePlaylists.instance.playlistStore.hasItem { it.id == playlist.id }) {
+                UIDialogs.showConfirmationDialog(context, "Playlist must be saved to edit the name", {
+                    copyPlaylist(playlist)
+                    onEditClick()
+                })
+                return
+            }
+
             _editPlaylistNameInput?.activate();
             _editPlaylistOverlay?.show();
         }
diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt
index f9c0e280b9414b0189653f67cd9a0ec0eca6eaf8..95a4c47b4114598ab7d1ca250c88805681f3eb5a 100644
--- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt
+++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailFragment.kt
@@ -93,22 +93,40 @@ class VideoDetailFragment : MainFragment {
     }
 
     private fun updateOrientation() {
+        val a = activity ?: return
         val isMaximized = state == State.MAXIMIZED
         val isFullScreenPortraitAllowed = Settings.instance.playback.fullscreenPortrait;
-        val currentOrientation = _currentOrientation
+        val bypassRotationPrevention = Settings.instance.other.bypassRotationPrevention;
+        val currentRequestedOrientation = a.requestedOrientation
+        val currentOrientation = if (_currentOrientation == -1) currentRequestedOrientation else _currentOrientation
+        val isAutoRotate = Settings.instance.playback.isAutoRotate()
         val isFs = isFullscreen
 
         if (isFs && isMaximized) {
             if (isFullScreenPortraitAllowed) {
-                activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
+                if (isAutoRotate) {
+                    a.requestedOrientation = currentOrientation
+                }
+            } else if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) {
+                if (isAutoRotate) {
+                    a.requestedOrientation = currentOrientation
+                }
             } else {
-                activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
+                a.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+            }
+        } else if (bypassRotationPrevention) {
+            if (isAutoRotate) {
+                a.requestedOrientation = currentOrientation
+            }
+        } else if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) {
+            if (isAutoRotate) {
+                a.requestedOrientation = currentOrientation
             }
         } else {
-            activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
+            a.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
         }
 
-        Log.i(TAG, "updateOrientation (isFs = ${isFs}, currentOrientation = ${currentOrientation}, isMaximized = ${isMaximized}, isFullScreenPortraitAllowed = ${isFullScreenPortraitAllowed}) resulted in requested orientation ${activity?.requestedOrientation}");
+        Log.i(TAG, "updateOrientation (isFs = ${isFs}, currentOrientation = ${currentOrientation}, currentRequestedOrientation = ${currentRequestedOrientation}, isMaximized = ${isMaximized}, isAutoRotate = ${isAutoRotate}, isFullScreenPortraitAllowed = ${isFullScreenPortraitAllowed}) resulted in requested orientation ${activity?.requestedOrientation}");
     }
 
     override fun onShownWithView(parameter: Any?, isBack: Boolean) {
@@ -269,6 +287,9 @@ class VideoDetailFragment : MainFragment {
         }
 
         _autoRotateChangeListener = AutoRotateChangeListener(requireContext(), Handler()) { _ ->
+            if (updateAutoFullscreen()) {
+                return@AutoRotateChangeListener
+            }
             updateOrientation()
         }
 
@@ -280,6 +301,9 @@ class VideoDetailFragment : MainFragment {
         }
 
         StatePlayer.instance.onRotationLockChanged.subscribe(this) {
+            if (updateAutoFullscreen()) {
+                return@subscribe
+            }
             updateOrientation()
         }
 
@@ -288,23 +312,29 @@ class VideoDetailFragment : MainFragment {
             _currentOrientation = it
             Logger.i(TAG, "Current orientation changed (_currentOrientation = ${_currentOrientation})")
 
-            if (Settings.instance.playback.isAutoRotate()) {
-                if (state == State.MAXIMIZED && !isFullscreen && (it == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || it == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE)) {
-                    _viewDetail?.setFullscreen(true)
-                    return@subscribe
-                }
-
-                if (state == State.MAXIMIZED && isFullscreen && !Settings.instance.playback.fullscreenPortrait && (it == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || it == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT)) {
-                    _viewDetail?.setFullscreen(false)
-                    return@subscribe
-                }
+            if (updateAutoFullscreen()) {
+                return@subscribe
             }
-
             updateOrientation()
         }
         return _view!!;
     }
 
+    private fun updateAutoFullscreen(): Boolean {
+        if (Settings.instance.playback.isAutoRotate()) {
+            if (state == State.MAXIMIZED && !isFullscreen && (_currentOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || _currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE)) {
+                _viewDetail?.setFullscreen(true)
+                return true
+            }
+
+            if (state == State.MAXIMIZED && isFullscreen && !Settings.instance.playback.fullscreenPortrait && (_currentOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || _currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT)) {
+                _viewDetail?.setFullscreen(false)
+                return true
+            }
+        }
+        return false
+    }
+
     fun onUserLeaveHint() {
         val viewDetail = _viewDetail;
         Logger.i(TAG, "onUserLeaveHint preventPictureInPicture=${viewDetail?.preventPictureInPicture} isCasting=${StateCasting.instance.isCasting} isBackgroundPictureInPicture=${Settings.instance.playback.isBackgroundPictureInPicture()} allowBackground=${viewDetail?.allowBackground}");
diff --git a/app/src/main/java/com/futo/platformplayer/states/StateApp.kt b/app/src/main/java/com/futo/platformplayer/states/StateApp.kt
index e44cdea71d86cbcc90bed5921ab3ed219b4b6ab7..6194bd6b7d39c0ce3edf4aa454d2d5f8654696b3 100644
--- a/app/src/main/java/com/futo/platformplayer/states/StateApp.kt
+++ b/app/src/main/java/com/futo/platformplayer/states/StateApp.kt
@@ -645,6 +645,7 @@ class StateApp {
                 wm.cancelAllWork();
         } catch (e: Throwable) {
             Logger.e(TAG, "Failed to schedule background subscription updates.", e)
+            UIDialogs.toast(context, "Background subscription update failed: " + e.message)
         }
     }