Repository: jellyfin/jellyfin-roku
Pull request #318: Add Autoplay Episode Limit setting and behaviour
Author: login: DavidBriglio
Created: 2025-05-02T16:21:35Z | Merged: 2025-05-02T23:02:51Z

<!--
Ensure your title is short, descriptive, and in the imperative mood (Fix X, Change Y, instead of Fixed X, Changed Y).
For a good inspiration of what to write in commit messages and PRs please review https://chris.beams.io/posts/git-commit/ and our https://jellyfin.readthedocs.io/en/latest/developer-docs/contributing/ page.
-->
<!-- markdownlint-disable MD041 first-line-heading -->
## Changes
- Add "Autoplay Episode Limit" setting to "Playback"
- Use this setting to control the number of episodes added to the queue when hitting play on an episode
<!-- Describe your changes here in 1-5 sentences. -->

## Issues
- Addresses the need for more granular control over the autoplay episodes feature, so that if used after falling asleep the number of episodes missed is minimized / user controlled
- Alleviates the need for an "Are you still watching" screen as requested [here](https://features.jellyfin.org/posts/814/are-you-still-watching-prompt), and could be enhanced to show that screen after the queue limit in the future
<!-- Tag any issues that this PR solves here.
ex. Fixes # -->

In a subsequent PR I would also like to add a "Next Episode" button to the episode details screen, so that when an episode stops playing you can use that instead of having to scroll down to the episode list, moving to the next episode, and hitting select.


Diff:
diff --git a/components/ItemGrid/LoadVideoContentTask.bs b/components/ItemGrid/LoadVideoContentTask.bs
index 6f220a9a9..a3b40aa74 100644
--- a/components/ItemGrid/LoadVideoContentTask.bs
+++ b/components/ItemGrid/LoadVideoContentTask.bs
@@ -184,10 +184,11 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
         end for
     end if
 
-    if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay
-        if isValid(video.showID)
-            addNextEpisodesToQueue(video.showID, additionalPartsCount)
-        end if
+    if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay and isValid(video.showID)
+        episodeQueueLimit = chainLookupReturn(m.global.session, "user.settings.episodeQueueLimit", "50")
+        episodeQueueLimit = episodeQueueLimit.ToInt()
+
+        addNextEpisodesToQueue(video.showID, additionalPartsCount, episodeQueueLimit)
     end if
 
     playbackPosition = 0!
@@ -542,7 +543,7 @@ function getContainerType(meta as object) as string
 end function
 
 ' Add next episodes to the playback queue
-sub addNextEpisodesToQueue(showID, additionalPartsCount as integer)
+sub addNextEpisodesToQueue(showID, additionalPartsCount as integer, queueLimit as integer)
     ' Don't queue next episodes if we already have a playback queue
     maxQueueCount = additionalPartsCount + 1
 
@@ -572,7 +573,7 @@ sub addNextEpisodesToQueue(showID, additionalPartsCount as integer)
     url = Substitute("Shows/{0}/Episodes", showID)
     urlParams = { "UserId": m.global.session.user.id }
     urlParams.Append({ "StartItemId": videoID })
-    urlParams.Append({ "Limit": 50 })
+    urlParams.Append({ "Limit": queueLimit + 1 })
     resp = APIRequest(url, urlParams)
     data = getJson(resp)
 
diff --git a/locale/en_US/translations.ts b/locale/en_US/translations.ts
index 39c64e577..5451c9169 100644
--- a/locale/en_US/translations.ts
+++ b/locale/en_US/translations.ts
@@ -1012,6 +1012,14 @@
             <source>Albums</source>
             <translation>Albums</translation>
         </message>
+        <message>
+            <source>Autoplay Episode Limit</source>
+            <translation>Autoplay Episode Limit</source>
+        </message>
+        <message>
+            <source>The number of episodes that will play automatically after the selected episode. Requires 'Play next episode automatically' server setting to be enabled.</source>
+            <translation>The number of episodes that will play automatically after the selected episode. Requires 'Play next episode automatically' server setting to be enabled.</translation>
+        </message>
         <message>
             <source>View All</source>
             <translation>View All</translation>
diff --git a/settings/settings.json b/settings/settings.json
index 04ee4dba3..080a7ae61 100644
--- a/settings/settings.json
+++ b/settings/settings.json
@@ -1,615 +1,622 @@
 [
-    {
-        "title": "Secret",
-        "description": "Settings that are not for public consumption. Do not get mad if these things change without notice.",
-        "visible": false,
+  {
+    "title": "Secret",
+    "description": "Settings that are not for public consumption. Do not get mad if these things change without notice.",
+    "visible": false,
+    "children": [
+      {
+        "title": "CJK Text",
+        "description": "Use CJK fallback font for text elements across the channel",
+        "settingName": "cjkText",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Channel Background Image",
+        "description": "Overlay a background image over your chosen background color",
+        "settingName": "imageBackground",
+        "type": "radio",
+        "default": "",
+        "options": [
+          {
+            "title": "None",
+            "id": ""
+          },
+          {
+            "title": "Circles",
+            "id": "pkg:/images/background/bg1.jpg"
+          },
+          {
+            "title": "Swoosh",
+            "id": "pkg:/images/background/bg2.jpg"
+          },
+          {
+            "title": "Splashscreen Image",
+            "id": "splash"
+          }
+        ]
+      },
+      {
+        "title": "Color Settings",
+        "description": "Change the colors of elements in the channel",
         "children": [
-            {
-                "title": "CJK Text",
-                "description": "Use CJK fallback font for text elements across the channel",
-                "settingName": "cjkText",
-                "type": "bool",
-                "default": "false"
-            },
-            {
-                "title": "Channel Background Image",
-                "description": "Overlay a background image over your chosen background color",
-                "settingName": "imageBackground",
-                "type": "radio",
-                "default": "",
-                "options": [
-                    {
-                        "title": "None",
-                        "id": ""
-                    },
-                    {
-                        "title": "Circles",
-                        "id": "pkg:/images/background/bg1.jpg"
-                    },
-                    {
-                        "title": "Swoosh",
-                        "id": "pkg:/images/background/bg2.jpg"
-                    },
-                    {
-                        "title": "Splashscreen Image",
-                        "id": "splash"
-                    }
-                ]
-            },
-            {
-                "title": "Color Settings",
-                "description": "Change the colors of elements in the channel",
-                "children": [
-                    {
-                        "title": "Background",
-                        "description": "The base background color for all screens in Jellyfin.",
-                        "settingName": "colorBackground",
-                        "type": "colorgrid",
-                        "default": "#000018"
-                    },
-                    {
-                        "title": "Primary Text",
-                        "description": "The primary text color for all screens in Jellyfin.",
-                        "settingName": "colorText",
-                        "type": "colorgrid",
-                        "default": "#FFFFFF"
-                    },
-                    {
-                        "title": "Secondary Text",
-                        "description": "The secondary text color for all screens in Jellyfin.",
-                        "settingName": "colorSubText",
-                        "type": "colorgrid",
-                        "default": "#777777FF"
-                    },
-                    {
-                        "title": "Cursor",
-                        "description": "The highlight color for the cursor showing where the user's focus is.",
-                        "settingName": "colorCursor",
-                        "type": "colorgrid",
-                        "default": "#FF6666"
-                    },
-                    {
-                        "title": "What's New Author",
-                        "description": "The text color for the author in the What's New popup.",
-                        "settingName": "colorWhatsNewAuthor",
-                        "type": "colorgrid",
-                        "default": "#FF6666"
-                    },
-                    {
-                        "title": "Watched Check Mark & Unplayed Count",
-                        "description": "Watched Check Mark & Unplayed Count color settings",
-                        "children": [
-                            {
-                                "title": "Background",
-                                "description": "The background color of the check mark & unplayed count shown in the top right corner of items.",
-                                "settingName": "colorPlayedCheckmarkBackground",
-                                "type": "colorgrid",
-                                "default": "#6666FF"
-                            },
-                            {
-                                "title": "Watched Check Mark",
-                                "description": "The color of the watched check mark.",
-                                "settingName": "colorPlayedCheckmarkIcon",
-                                "type": "colorgrid",
-                                "default": "#FFFFFF"
-                            },
-                            {
-                                "title": "Unplayed Count",
-                                "description": "The text color of the unplayed count number.",
-                                "settingName": "colorUnplayedCountTextColor",
-                                "type": "colorgrid",
-                                "default": "#FFFFFF"
-                            }
-                        ]
-                    }
-                ]
-            }
+          {
+            "title": "Background",
+            "description": "The base background color for all screens in Jellyfin.",
+            "settingName": "colorBackground",
+            "type": "colorgrid",
+            "default": "#000018"
+          },
+          {
+            "title": "Primary Text",
+            "description": "The primary text color for all screens in Jellyfin.",
+            "settingName": "colorText",
+            "type": "colorgrid",
+            "default": "#FFFFFF"
+          },
+          {
+            "title": "Secondary Text",
+            "description": "The secondary text color for all screens in Jellyfin.",
+            "settingName": "colorSubText",
+            "type": "colorgrid",
+            "default": "#777777FF"
+          },
+          {
+            "title": "Cursor",
+            "description": "The highlight color for the cursor showing where the user's focus is.",
+            "settingName": "colorCursor",
+            "type": "colorgrid",
+            "default": "#FF6666"
+          },
+          {
+            "title": "What's New Author",
+            "description": "The text color for the author in the What's New popup.",
+            "settingName": "colorWhatsNewAuthor",
+            "type": "colorgrid",
+            "default": "#FF6666"
+          },
+          {
+            "title": "Watched Check Mark & Unplayed Count",
+            "description": "Watched Check Mark & Unplayed Count color settings",
+            "children": [
+              {
+                "title": "Background",
+                "description": "The background color of the check mark & unplayed count shown in the top right corner of items.",
+                "settingName": "colorPlayedCheckmarkBackground",
+                "type": "colorgrid",
+                "default": "#6666FF"
+              },
+              {
+                "title": "Watched Check Mark",
+                "description": "The color of the watched check mark.",
+                "settingName": "colorPlayedCheckmarkIcon",
+                "type": "colorgrid",
+                "default": "#FFFFFF"
+              },
+              {
+                "title": "Unplayed Count",
+                "description": "The text color of the unplayed count number.",
+                "settingName": "colorUnplayedCountTextColor",
+                "type": "colorgrid",
+                "default": "#FFFFFF"
+              }
+            ]
+          }
         ]
-    },
-    {
-        "title": "Global",
-        "description": "Global settings that affect everyone that uses this Roku device.",
+      }
+    ]
+  },
+  {
+    "title": "Global",
+    "description": "Global settings that affect everyone that uses this Roku device.",
+    "children": [
+      {
+        "title": "Remember Me?",
+        "description": "Remember the currently logged in user and try to log them in again next time you start Jellyfin.",
+        "settingName": "global.rememberme",
+        "type": "bool",
+        "default": "true"
+      }
+    ]
+  },
+  {
+    "title": "Playback",
+    "description": "Settings relating to playback and supported codec and media types.",
+    "children": [
+      {
+        "title": "Autoplay Episode Limit",
+        "description": "The number of episodes that will play automatically after the selected episode. Requires 'Play next episode automatically' server setting to be enabled.",
+        "settingName": "episodeQueueLimit",
+        "type": "integer",
+        "default": "50"
+      },
+      {
+        "title": "Bitrate Limit",
+        "description": "Configure the maximum playback bitrate.",
         "children": [
-            {
-                "title": "Remember Me?",
-                "description": "Remember the currently logged in user and try to log them in again next time you start Jellyfin.",
-                "settingName": "global.rememberme",
-                "type": "bool",
-                "default": "true"
-            }
+          {
+            "title": "Enable Limit",
+            "description": "Enable or disable the 'Maximum Bitrate' setting.",
+            "settingName": "playback.bitrate.maxlimited",
+            "type": "bool",
+            "default": "true"
+          },
+          {
+            "title": "Maximum Bitrate",
+            "description": "Set the maximum bitrate in Mbps. Set to 0 to use Roku's specifications. This setting must be enabled to take effect.",
+            "settingName": "playback.bitrate.limit",
+            "type": "integer",
+            "default": "0"
+          }
         ]
-    },
-    {
-        "title": "Playback",
-        "description": "Settings relating to playback and supported codec and media types.",
+      },
+      {
+        "title": "Cinema Mode",
+        "description": "Bring the theater experience straight to your living room with the ability to play custom intros before the main feature.",
+        "settingName": "playback.cinemamode",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Compatibility",
+        "description": "Attempt to prevent playback failures.",
         "children": [
-            {
-                "title": "Bitrate Limit",
-                "description": "Configure the maximum playback bitrate.",
-                "children": [
-                    {
-                        "title": "Enable Limit",
-                        "description": "Enable or disable the 'Maximum Bitrate' setting.",
-                        "settingName": "playback.bitrate.maxlimited",
-                        "type": "bool",
-                        "default": "true"
-                    },
-                    {
-                        "title": "Maximum Bitrate",
-                        "description": "Set the maximum bitrate in Mbps. Set to 0 to use Roku's specifications. This setting must be enabled to take effect.",
-                        "settingName": "playback.bitrate.limit",
-                        "type": "integer",
-                        "default": "0"
-                    }
-                ]
-            },
-            {
-                "title": "Cinema Mode",
-                "description": "Bring the theater experience straight to your living room with the ability to play custom intros before the main feature.",
-                "settingName": "playback.cinemamode",
+          {
+            "title": "Disable HEVC",
+            "description": "Disable the HEVC codec on this device. This may improve playback for some devices (ultra).",
+            "settingName": "playback.compatibility.disablehevc",
+            "type": "bool",
+            "default": "false"
+          }
+        ]
+      },
+      {
+        "title": "Custom Subtitles",
+        "description": "Replace Roku's default subtitle functions with custom functions that support CJK fonts. Fallback fonts must be configured and enabled on the server for CJK rendering to work.",
+        "settingName": "playback.subs.custom",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Custom Trickplay",
+        "description": "Display custom trickplay images even if this Roku says it's displaying its own. This may cause the two images to overlay on top of each other.",
+        "settingName": "playback.trickplay.forcecustom",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Force Transcoding",
+        "description": "Force all playable media to be transcoded.",
+        "settingName": "playback.media.forceTranscode",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Maximum Resolution",
+        "description": "Configure the maximum resolution when playing video files on this device.",
+        "children": [
+          {
+            "title": "Mode",
+            "description": "Apply max resolution to all files or only transcoded files.",
+            "settingName": "playback.resolution.mode",
+            "type": "radio",
+            "default": "transcoding",
+            "options": [
+              {
+                "title": "All files",
+                "id": "everything"
+              },
+              {
+                "title": "Only transcoded files",
+                "id": "transcoding"
+              }
+            ]
+          },
+          {
+            "title": "Value",
+            "description": "Set the maximum resolution when playing video files on this device.",
+            "settingName": "playback.resolution.max",
+            "type": "radio",
+            "default": "auto",
+            "options": [
+              {
+                "title": "Off - Attempt to play all resolutions",
+                "id": "off"
+              },
+              {
+                "title": "Auto - Use TV resolution",
+                "id": "auto"
+              },
+              {
+                "title": "360p",
+                "id": "360"
+              },
+              {
+                "title": "480p",
+                "id": "480"
+              },
+              {
+                "title": "720p",
+                "id": "720"
+              },
+              {
+                "title": "1080p",
+                "id": "1080"
+              },
+              {
+                "title": "4k",
+                "id": "2160"
+              },
+              {
+                "title": "8k",
+                "id": "4320"
+              }
+            ]
+          }
+        ]
+      },
+      {
+        "title": "Media Segment Actions",
+        "description": "Settings relating to how Jellyfin should handle media segments.",
+        "children": [
+          {
+            "title": "Commercial Segments",
+            "description": "What action should Jellyfin take for commercial segments? ",
+            "settingName": "playback.mediasegments.commercial",
+            "type": "radio",
+            "default": "none",
+            "options": [
+              {
+                "title": "Ask To Skip",
+                "id": "asktoskip"
+              },
+              {
+                "title": "Skip",
+                "id": "skip"
+              },
+              {
+                "title": "None",
+                "id": "none"
+              }
+            ]
+          },
+          {
+            "title": "Intro Segments",
+            "description": "What action should Jellyfin take for intro segments? ",
+            "settingName": "playback.mediasegments.intro",
+            "type": "radio",
+            "default": "asktoskip",
+            "options": [
+              {
+                "title": "Ask To Skip",
+                "id": "asktoskip"
+              },
+              {
+                "title": "Skip",
+                "id": "skip"
+              },
+              {
+                "title": "None",
+                "id": "None"
+              }
+            ]
+          },
+          {
+            "title": "Outro Segments",
+            "description": "What action should Jellyfin take for outro segments? ",
+            "settingName": "playback.mediasegments.outro",
+            "type": "radio",
+            "default": "asktoskip",
+            "options": [
+              {
+                "title": "Ask To Skip",
+                "id": "asktoskip"
+              },
+              {
+                "title": "Skip",
+                "id": "skip"
+              },
+              {
+                "title": "None",
+                "id": "none"
+              }
+            ]
+          },
+          {
+            "title": "Preview Segments",
+            "description": "What action should Jellyfin take for preview segments? ",
+            "settingName": "playback.mediasegments.preview",
+            "type": "radio",
+            "default": "none",
+            "options": [
+              {
+                "title": "Ask To Skip",
+                "id": "asktoskip"
+              },
+              {
+                "title": "Skip",
+                "id": "skip"
+              },
+              {
+                "title": "None",
+                "id": "none"
+              }
+            ]
+          },
+          {
+            "title": "Recap Segments",
+            "description": "What action should Jellyfin take for recap segments? ",
+            "settingName": "playback.mediasegments.recap",
+            "type": "radio",
+            "default": "none",
+            "options": [
+              {
+                "title": "Ask To Skip",
+                "id": "asktoskip"
+              },
+              {
+                "title": "Skip",
+                "id": "skip"
+              },
+              {
+                "title": "None",
+                "id": "none"
+              }
+            ]
+          }
+        ]
+      },
+      {
+        "title": "Next Episode Button Time",
+        "description": "If no Outro media segment exists, set how many seconds before the end of an episode the Skip Outro button should appear. Set to 0 to disable.",
+        "settingName": "playback.nextupbuttonseconds",
+        "type": "integer",
+        "default": "30"
+      },
+      {
+        "title": "Preferred Audio Codec",
+        "description": "Use the selected audio codec for transcodes. If the device or stream does not support it, a fallback codec will be used.",
+        "settingName": "playback.preferredAudioCodec",
+        "type": "radio",
+        "default": "auto",
+        "options": [
+          {
+            "title": "Use system settings",
+            "id": "auto"
+          },
+          {
+            "title": "AAC",
+            "id": "aac"
+          },
+          {
+            "title": "DD (AC3)",
+            "id": "ac3"
+          },
+          {
+            "title": "DD+ (EAC3)",
+            "id": "eac3"
+          },
+          {
+            "title": "DTS",
+            "id": "dts"
+          }
+        ]
+      },
+      {
+        "title": "Text Subtitles Only",
+        "description": "Only display text subtitles to minimize transcoding.",
+        "settingName": "playback.subs.onlytext",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Video Codec Support",
+        "description": "Enable or disable Direct Play support for certain codecs.",
+        "children": [
+          {
+            "title": "MPEG-2",
+            "description": "Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.",
+            "settingName": "playback.mpeg2",
+            "type": "bool",
+            "default": "false"
+          },
+          {
+            "title": "MPEG-4",
+            "description": "Support Direct Play of MPEG-4 content. This may need to be disabled for playback of DIVX encoded video files.",
+            "settingName": "playback.mpeg4",
+            "type": "bool",
+            "default": "true"
+          }
+        ]
+      },
+      {
+        "title": "Video Profile Level Support",
+        "description": "Attempt Direct Play of potentially unsupported profile levels",
+        "children": [
+          {
+            "title": "H.264",
+            "description": "Attempt Direct Play for H.264 media with unsupported profile levels before falling back to transcoding if it fails.",
+            "settingName": "playback.tryDirect.h264ProfileLevel",
+            "type": "bool",
+            "default": "false"
+          },
+          {
+            "title": "HEVC",
+            "description": "Attempt Direct Play for HEVC media with unsupported profile levels before falling back to transcoding if it fails.",
+            "settingName": "playback.tryDirect.hevcProfileLevel",
+            "type": "bool",
+            "default": "false"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "title": "User Interface",
+    "description": "Settings relating to how the application looks.",
+    "children": [
+      {
+        "title": "General",
+        "description": "Settings relating to the appearance of the Home screen and the program in general.",
+        "children": [
+          {
+            "title": "Episode Images Next Up",
+            "description": "What type of images to use for Episodes shown in the 'Next Up' and 'Continue Watching' sections.",
+            "settingName": "ui-general-episodeimagesnextup",
+            "type": "radio",
+            "default": "webclient",
+            "options": [
+              {
+                "title": "Use Web Client Setting",
+                "id": "webclient"
+              },
+              {
+                "title": "Use Episode Image",
+                "id": "episode"
+              },
+              {
+                "title": "Use Show Image",
+                "id": "show"
+              }
+            ]
+          },
+          {
+            "title": "Hide Clock",
+            "description": "Hide all clocks in Jellyfin. Jellyfin will need to be closed and reopened for changes to take effect.",
+            "settingName": "ui.design.hideclock",
+            "type": "bool",
+            "default": "false"
+          },
+          {
+            "title": "Max Days Next Up",
+            "description": "Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.",
+            "settingName": "ui.details.maxdaysnextup",
+            "type": "integer",
+            "default": "365"
+          },
+          {
+            "title": "Rewatching Next Up",
+            "description": "Show already watched episodes in 'Next Up' sections.",
+            "settingName": "ui.details.enablerewatchingnextup",
+            "type": "bool",
+            "default": "false"
+          },
+          {
+            "title": "Show What's New Popup",
+            "description": "Show What's New popup when Jellyfin is updated to a new version.",
+            "settingName": "load.allowwhatsnew",
+            "type": "bool",
+            "default": "true"
+          },
+          {
+            "title": "Use Web Client's Home Section Arrangement",
+            "description": "Make the arrangement of the Roku home view sections match the web client's home screen. Jellyfin will need to be closed and reopened for change to take effect.",
+            "settingName": "ui.home.useWebSectionArrangement",
+            "type": "bool",
+            "default": "true"
+          }
+        ]
+      },
+      {
+        "title": "Item Detail Screen",
+        "description": "Settings relating to the appearance of the item detail screen.",
+        "children": [
+          {
+            "title": "Community and Critical Ratings",
+            "description": "Community and critic review ratings from Rotten Tomatoes.",
+            "settingName": "ui.itemdetail.showRatings",
+            "type": "bool",
+            "default": "true"
+          },
+          {
+            "title": "Overview Content",
+            "description": "A quick overview of the item selected - typically a short plot outline.",
+            "settingName": "ui.itemdetail.showoverviewcontent",
+            "type": "bool",
+            "default": "true"
+          }
+        ]
+      },
+      {
+        "title": "Libraries",
+        "description": "Settings relating to the appearance of Library pages.",
+        "children": [
+          {
+            "title": "General",
+            "description": "Settings relating to the appearance of pages in all Libraries.",
+            "children": [
+              {
+                "title": "Forget Filters",
+                "description": "Forget applied library filters when Jellyfin is closed.",
+                "settingName": "itemgrid.forgetFilters",
                 "type": "bool",
-                "default": "false"
-            },
-            {
-                "title": "Compatibility",
-                "description": "Attempt to prevent playback failures.",
+                "default": "true"
+              },
+              {
+                "title": "Grid View Settings",
+                "description": "Settings that apply when Grid views are enabled.",
                 "children": [
-                    {
-                        "title": "Disable HEVC",
-                        "description": "Disable the HEVC codec on this device. This may improve playback for some devices (ultra).",
-                        "settingName": "playback.compatibility.disablehevc",
-                        "type": "bool",
-                        "default": "false"
-                    }
+                  {
+                    "title": "Item Count",
+                    "description": "Show item count in the library and index of selected item.",
+                    "settingName": "itemgrid.showItemCount",
+                    "type": "bool",
+                    "default": "false"
+                  },
+                  {
+                    "title": "Item Titles",
+                    "description": "Select when to show titles.",
+                    "settingName": "itemgrid.gridTitles",
+                    "type": "radio",
+                    "default": "showonhover",
+                    "options": [
+                      {
+                        "title": "Show On Hover",
+                        "id": "showonhover"
+                      },
+                      {
+                        "title": "Always Show",
+                        "id": "showalways"
+                      },
+                      {
+                        "title": "Always Hide",
+                        "id": "hidealways"
+                      }
+                    ]
+                  }
                 ]
-            },
-            {
-                "title": "Custom Subtitles",
-                "description": "Replace Roku's default subtitle functions with custom functions that support CJK fonts. Fallback fonts must be configured and enabled on the server for CJK rendering to work.",
-                "settingName": "playback.subs.custom",
-                "type": "bool",
-                "default": "false"
-            },
-            {
-                "title": "Custom Trickplay",
-                "description": "Display custom trickplay images even if this Roku says it's displaying its own. This may cause the two images to overlay on top of each other.",
-                "settingName": "playback.trickplay.forcecustom",
+              }
+            ]
+          },
+          {
+            "title": "TV Shows",
+            "description": "Settings relating to the appearance of pages in TV Libraries.",
+            "children": [
+              {
+                "title": "Disable Community Rating for Episodes",
+                "description": "Hide the star and community rating for episodes of a TV show. This is to prevent spoilers of an upcoming good/bad episode.",
+                "settingName": "ui.itemdetail.showRatings",
                 "type": "bool",
                 "default": "false"
-            },
-            {
-                "title": "Force Transcoding",
-                "description": "Force all playable media to be transcoded.",
-                "settingName": "playback.media.forceTranscode",
+              },
+              {
+                "title": "Disable Unwatched Episode Count",
+                "description": "If enabled, the number of unwatched episodes in a series/season will be removed.",
+                "settingName": "ui.tvshows.disableUnwatchedEpisodeCount",
                 "type": "bool",
                 "default": "false"
-            },
-            {
-                "title": "Maximum Resolution",
-                "description": "Configure the maximum resolution when playing video files on this device.",
-                "children": [
-                    {
-                        "title": "Mode",
-                        "description": "Apply max resolution to all files or only transcoded files.",
-                        "settingName": "playback.resolution.mode",
-                        "type": "radio",
-                        "default": "transcoding",
-                        "options": [
-                            {
-                                "title": "All files",
-                                "id": "everything"
-                            },
-                            {
-                                "title": "Only transcoded files",
-                                "id": "transcoding"
-                            }
-                        ]
-                    },
-                    {
-                        "title": "Value",
-                        "description": "Set the maximum resolution when playing video files on this device.",
-                        "settingName": "playback.resolution.max",
-                        "type": "radio",
-                        "default": "auto",
-                        "options": [
-                            {
-                                "title": "Off - Attempt to play all resolutions",
-                                "id": "off"
-                            },
-                            {
-                                "title": "Auto - Use TV resolution",
-                                "id": "auto"
-                            },
-                            {
-                                "title": "360p",
-                                "id": "360"
-                            },
-                            {
-                                "title": "480p",
-                                "id": "480"
-                            },
-                            {
-                                "title": "720p",
-                                "id": "720"
-                            },
-                            {
-                                "title": "1080p",
-                                "id": "1080"
-                            },
-                            {
-                                "title": "4k",
-                                "id": "2160"
-                            },
-                            {
-                                "title": "8k",
-                                "id": "4320"
-                            }
-                        ]
-                    }
-                ]
-            },
-            {
-                "title": "Media Segment Actions",
-                "description": "Settings relating to how Jellyfin should handle media segments.",
-                "children": [
-                    {
-                        "title": "Commercial Segments",
-                        "description": "What action should Jellyfin take for commercial segments? ",
-                        "settingName": "playback.mediasegments.commercial",
-                        "type": "radio",
-                        "default": "none",
-                        "options": [
-                            {
-                                "title": "Ask To Skip",
-                                "id": "asktoskip"
-                            },
-                            {
-                                "title": "Skip",
-                                "id": "skip"
-                            },
-                            {
-                                "title": "None",
-                                "id": "none"
-                            }
-                        ]
-                    },
-                    {
-                        "title": "Intro Segments",
-                        "description": "What action should Jellyfin take for intro segments? ",
-                        "settingName": "playback.mediasegments.intro",
-                        "type": "radio",
-                        "default": "asktoskip",
-                        "options": [
-                            {
-                                "title": "Ask To Skip",
-                                "id": "asktoskip"
-                            },
-                            {
-                                "title": "Skip",
-                                "id": "skip"
-                            },
-                            {
-                                "title": "None",
-                                "id": "None"
-                            }
-                        ]
-                    },
-                    {
-                        "title": "Outro Segments",
-                        "description": "What action should Jellyfin take for outro segments? ",
-                        "settingName": "playback.mediasegments.outro",
-                        "type": "radio",
-                        "default": "asktoskip",
-                        "options": [
-                            {
-                                "title": "Ask To Skip",
-                                "id": "asktoskip"
-                            },
-                            {
-                                "title": "Skip",
-                                "id": "skip"
-                            },
-                            {
-                                "title": "None",
-                                "id": "none"
-                            }
-                        ]
-                    },
-                    {
-                        "title": "Preview Segments",
-                        "description": "What action should Jellyfin take for preview segments? ",
-                        "settingName": "playback.mediasegments.preview",
-                        "type": "radio",
-                        "default": "none",
-                        "options": [
-                            {
-                                "title": "Ask To Skip",
-                                "id": "asktoskip"
-                            },
-                            {
-                                "title": "Skip",
-                                "id": "skip"
-                            },
-                            {
-                                "title": "None",
-                                "id": "none"
-                            }
-                        ]
-                    },
-                    {
-                        "title": "Recap Segments",
-                        "description": "What action should Jellyfin take for recap segments? ",
-                        "settingName": "playback.mediasegments.recap",
-                        "type": "radio",
-                        "default": "none",
-                        "options": [
-                            {
-                                "title": "Ask To Skip",
-                                "id": "asktoskip"
-                            },
-                            {
-                                "title": "Skip",
-                                "id": "skip"
-                            },
-                            {
-                                "title": "None",
-                                "id": "none"
-                            }
-                        ]
-                    }
-                ]
-            },
-            {
-                "title": "Next Episode Button Time",
-                "description": "If no Outro media segment exists, set how many seconds before the end of an episode the Skip Outro button should appear. Set to 0 to disable.",
-                "settingName": "playback.nextupbuttonseconds",
-                "type": "integer",
-                "default": "30"
-            },
-            {
-                "title": "Preferred Audio Codec",
-                "description": "Use the selected audio codec for transcodes. If the device or stream does not support it, a fallback codec will be used.",
-                "settingName": "playback.preferredAudioCodec",
-                "type": "radio",
-                "default": "auto",
-                "options": [
-                    {
-                        "title": "Use system settings",
-                        "id": "auto"
-                    },
-                    {
-                        "title": "AAC",
-                        "id": "aac"
-                    },
-                    {
-                        "title": "DD (AC3)",
-                        "id": "ac3"
-                    },
-                    {
-                        "title": "DD+ (EAC3)",
-                        "id": "eac3"
-                    },
-                    {
-                        "title": "DTS",
-                        "id": "dts"
-                    }
-                ]
-            },
-            {
-                "title": "Text Subtitles Only",
-                "description": "Only display text subtitles to minimize transcoding.",
-                "settingName": "playback.subs.onlytext",
+              },
+              {
+                "title": "Skip Details for Single Seasons",
+                "description": "If enabled, selecting a TV series with only one season will go straight to the episode list rather than the show details and season list.",
+                "settingName": "ui.tvshows.goStraightToEpisodeListing",
                 "type": "bool",
                 "default": "false"
-            },
-            {
-                "title": "Video Codec Support",
-                "description": "Enable or disable Direct Play support for certain codecs.",
-                "children": [
-                    {
-                        "title": "MPEG-2",
-                        "description": "Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.",
-                        "settingName": "playback.mpeg2",
-                        "type": "bool",
-                        "default": "false"
-                    },
-                    {
-                        "title": "MPEG-4",
-                        "description": "Support Direct Play of MPEG-4 content. This may need to be disabled for playback of DIVX encoded video files.",
-                        "settingName": "playback.mpeg4",
-                        "type": "bool",
-                        "default": "true"
-                    }
-                ]
-            },
-            {
-                "title": "Video Profile Level Support",
-                "description": "Attempt Direct Play of potentially unsupported profile levels",
-                "children": [
-                    {
-                        "title": "H.264",
-                        "description": "Attempt Direct Play for H.264 media with unsupported profile levels before falling back to transcoding if it fails.",
-                        "settingName": "playback.tryDirect.h264ProfileLevel",
-                        "type": "bool",
-                        "default": "false"
-                    },
-                    {
-                        "title": "HEVC",
-                        "description": "Attempt Direct Play for HEVC media with unsupported profile levels before falling back to transcoding if it fails.",
-                        "settingName": "playback.tryDirect.hevcProfileLevel",
-                        "type": "bool",
-                        "default": "false"
-                    }
-                ]
-            }
-        ]
-    },
-    {
-        "title": "User Interface",
-        "description": "Settings relating to how the application looks.",
-        "children": [
-            {
-                "title": "General",
-                "description": "Settings relating to the appearance of the Home screen and the program in general.",
-                "children": [
-                    {
-                        "title": "Episode Images Next Up",
-                        "description": "What type of images to use for Episodes shown in the 'Next Up' and 'Continue Watching' sections.",
-                        "settingName": "ui-general-episodeimagesnextup",
-                        "type": "radio",
-                        "default": "webclient",
-                        "options": [
-                            {
-                                "title": "Use Web Client Setting",
-                                "id": "webclient"
-                            },
-                            {
-                                "title": "Use Episode Image",
-                                "id": "episode"
-                            },
-                            {
-                                "title": "Use Show Image",
-                                "id": "show"
-                            }
-                        ]
-                    },
-                    {
-                        "title": "Hide Clock",
-                        "description": "Hide all clocks in Jellyfin. Jellyfin will need to be closed and reopened for changes to take effect.",
-                        "settingName": "ui.design.hideclock",
-                        "type": "bool",
-                        "default": "false"
-                    },
-                    {
-                        "title": "Max Days Next Up",
-                        "description": "Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.",
-                        "settingName": "ui.details.maxdaysnextup",
-                        "type": "integer",
-                        "default": "365"
-                    },
-                    {
-                        "title": "Rewatching Next Up",
-                        "description": "Show already watched episodes in 'Next Up' sections.",
-                        "settingName": "ui.details.enablerewatchingnextup",
-                        "type": "bool",
-                        "default": "false"
-                    },
-                    {
-                        "title": "Show What's New Popup",
-                        "description": "Show What's New popup when Jellyfin is updated to a new version.",
-                        "settingName": "load.allowwhatsnew",
-                        "type": "bool",
-                        "default": "true"
-                    },
-                    {
-                        "title": "Use Web Client's Home Section Arrangement",
-                        "description": "Make the arrangement of the Roku home view sections match the web client's home screen. Jellyfin will need to be closed and reopened for change to take effect.",
-                        "settingName": "ui.home.useWebSectionArrangement",
-                        "type": "bool",
-                        "default": "true"
-                    }
-                ]
-            },
-            {
-                "title": "Item Detail Screen",
-                "description": "Settings relating to the appearance of the item detail screen.",
-                "children": [
-                    {
-                        "title": "Community and Critical Ratings",
-                        "description": "Community and critic review ratings from Rotten Tomatoes.",
-                        "settingName": "ui.itemdetail.showRatings",
-                        "type": "bool",
-                        "default": "true"
-                    },
-                    {
-                        "title": "Overview Content",
-                        "description": "A quick overview of the item selected - typically a short plot outline.",
-                        "settingName": "ui.itemdetail.showoverviewcontent",
-                        "type": "bool",
-                        "default": "true"
-                    }
-                ]
-            },
-            {
-                "title": "Libraries",
-                "description": "Settings relating to the appearance of Library pages.",
-                "children": [
-                    {
-                        "title": "General",
-                        "description": "Settings relating to the appearance of pages in all Libraries.",
-                        "children": [
-                            {
-                                "title": "Forget Filters",
-                                "description": "Forget applied library filters when Jellyfin is closed.",
-                                "settingName": "itemgrid.forgetFilters",
-                                "type": "bool",
-                                "default": "true"
-                            },
-                            {
-                                "title": "Grid View Settings",
-                                "description": "Settings that apply when Grid views are enabled.",
-                                "children": [
-                                    {
-                                        "title": "Item Count",
-                                        "description": "Show item count in the library and index of selected item.",
-                                        "settingName": "itemgrid.showItemCount",
-                                        "type": "bool",
-                                        "default": "false"
-                                    },
-                                    {
-                                        "title": "Item Titles",
-                                        "description": "Select when to show titles.",
-                                        "settingName": "itemgrid.gridTitles",
-                                        "type": "radio",
-                                        "default": "showonhover",
-                                        "options": [
-                                            {
-                                                "title": "Show On Hover",
-                                                "id": "showonhover"
-                                            },
-                                            {
-                                                "title": "Always Show",
-                                                "id": "showalways"
-                                            },
-                                            {
-                                                "title": "Always Hide",
-                                                "id": "hidealways"
-                                            }
-                                        ]
-                                    }
-                                ]
-                            }
-                        ]
-                    },
-                    {
-                        "title": "TV Shows",
-                        "description": "Settings relating to the appearance of pages in TV Libraries.",
-                        "children": [
-                            {
-                                "title": "Disable Community Rating for Episodes",
-                                "description": "Hide the star and community rating for episodes of a TV show. This is to prevent spoilers of an upcoming good/bad episode.",
-                                "settingName": "ui.itemdetail.showRatings",
-                                "type": "bool",
-                                "default": "false"
-                            },
-                            {
-                                "title": "Disable Unwatched Episode Count",
-                                "description": "If enabled, the number of unwatched episodes in a series/season will be removed.",
-                                "settingName": "ui.tvshows.disableUnwatchedEpisodeCount",
-                                "type": "bool",
-                                "default": "false"
-                            },
-                            {
-                                "title": "Skip Details for Single Seasons",
-                                "description": "If enabled, selecting a TV series with only one season will go straight to the episode list rather than the show details and season list.",
-                                "settingName": "ui.tvshows.goStraightToEpisodeListing",
-                                "type": "bool",
-                                "default": "false"
-                            }
-                        ]
-                    }
-                ]
-            }
+              }
+            ]
+          }
         ]
-    }
-]
\ No newline at end of file
+      }
+    ]
+  }
+]
diff --git a/source/static/whatsNew/3.0.3.json b/source/static/whatsNew/3.0.3.json
index 5dfbfa1d5..d79265b11 100644
--- a/source/static/whatsNew/3.0.3.json
+++ b/source/static/whatsNew/3.0.3.json
@@ -1,4 +1,8 @@
 [
+  {
+    "description": "Add playback \"Autoplay Episode Limit\" setting and behavior",
+    "author": "rookly"
+  },
   {
     "description": "Fix crash when watching a recording in progress",
     "author": "1hitsong"


Reviews:
user: login: DavidBriglio
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T16:27:47Z
user: login: 1hitsong
body: Quick code style review - I did this away from my dev machine, so I've not tested my suggestions yet.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-02T17:51:18Z
user: login: DavidBriglio
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T18:20:12Z
user: login: 1hitsong
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-02T18:35:40Z
user: login: 1hitsong
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-02T18:39:14Z
user: login: 1hitsong
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-02T20:30:45Z
user: login: DavidBriglio
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T21:00:57Z
user: login: DavidBriglio
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T21:09:12Z
user: login: 1hitsong
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-02T21:15:23Z
user: login: 1hitsong
body: Looks and works great. Good job!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-02T23:02:45Z

Review comments:
diff_hunk: @@ -1,615 +1,622 @@
 [
-    {
-        "title": "Secret",
-        "description": "Settings that are not for public consumption. Do not get mad if these things change without notice.",
-        "visible": false,
+  {
+    "title": "Secret",
+    "description": "Settings that are not for public consumption. Do not get mad if these things change without notice.",
+    "visible": false,
+    "children": [
+      {
+        "title": "CJK Text",
+        "description": "Use CJK fallback font for text elements across the channel",
+        "settingName": "cjkText",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Channel Background Image",
+        "description": "Overlay a background image over your chosen background color",
+        "settingName": "imageBackground",
+        "type": "radio",
+        "default": "",
+        "options": [
+          {
+            "title": "None",
+            "id": ""
+          },
+          {
+            "title": "Circles",
+            "id": "pkg:/images/background/bg1.jpg"
+          },
+          {
+            "title": "Swoosh",
+            "id": "pkg:/images/background/bg2.jpg"
+          },
+          {
+            "title": "Splashscreen Image",
+            "id": "splash"
+          }
+        ]
+      },
+      {
+        "title": "Color Settings",
+        "description": "Change the colors of elements in the channel",
         "children": [
-            {
-                "title": "CJK Text",
-                "description": "Use CJK fallback font for text elements across the channel",
-                "settingName": "cjkText",
-                "type": "bool",
-                "default": "false"
-            },
-            {
-                "title": "Channel Background Image",
-                "description": "Overlay a background image over your chosen background color",
-                "settingName": "imageBackground",
-                "type": "radio",
-                "default": "",
-                "options": [
-                    {
-                        "title": "None",
-                        "id": ""
-                    },
-                    {
-                        "title": "Circles",
-                        "id": "pkg:/images/background/bg1.jpg"
-                    },
-                    {
-                        "title": "Swoosh",
-                        "id": "pkg:/images/background/bg2.jpg"
-                    },
-                    {
-                        "title": "Splashscreen Image",
-                        "id": "splash"
-                    }
-                ]
-            },
-            {
-                "title": "Color Settings",
-                "description": "Change the colors of elements in the channel",
-                "children": [
-                    {
-                        "title": "Background",
-                        "description": "The base background color for all screens in Jellyfin.",
-                        "settingName": "colorBackground",
-                        "type": "colorgrid",
-                        "default": "#000018"
-                    },
-                    {
-                        "title": "Primary Text",
-                        "description": "The primary text color for all screens in Jellyfin.",
-                        "settingName": "colorText",
-                        "type": "colorgrid",
-                        "default": "#FFFFFF"
-                    },
-                    {
-                        "title": "Secondary Text",
-                        "description": "The secondary text color for all screens in Jellyfin.",
-                        "settingName": "colorSubText",
-                        "type": "colorgrid",
-                        "default": "#777777FF"
-                    },
-                    {
-                        "title": "Cursor",
-                        "description": "The highlight color for the cursor showing where the user's focus is.",
-                        "settingName": "colorCursor",
-                        "type": "colorgrid",
-                        "default": "#FF6666"
-                    },
-                    {
-                        "title": "What's New Author",
-                        "description": "The text color for the author in the What's New popup.",
-                        "settingName": "colorWhatsNewAuthor",
-                        "type": "colorgrid",
-                        "default": "#FF6666"
-                    },
-                    {
-                        "title": "Watched Check Mark & Unplayed Count",
-                        "description": "Watched Check Mark & Unplayed Count color settings",
-                        "children": [
-                            {
-                                "title": "Background",
-                                "description": "The background color of the check mark & unplayed count shown in the top right corner of items.",
-                                "settingName": "colorPlayedCheckmarkBackground",
-                                "type": "colorgrid",
-                                "default": "#6666FF"
-                            },
-                            {
-                                "title": "Watched Check Mark",
-                                "description": "The color of the watched check mark.",
-                                "settingName": "colorPlayedCheckmarkIcon",
-                                "type": "colorgrid",
-                                "default": "#FFFFFF"
-                            },
-                            {
-                                "title": "Unplayed Count",
-                                "description": "The text color of the unplayed count number.",
-                                "settingName": "colorUnplayedCountTextColor",
-                                "type": "colorgrid",
-                                "default": "#FFFFFF"
-                            }
-                        ]
-                    }
-                ]
-            }
+          {
+            "title": "Background",
+            "description": "The base background color for all screens in Jellyfin.",
+            "settingName": "colorBackground",
+            "type": "colorgrid",
+            "default": "#000018"
+          },
+          {
+            "title": "Primary Text",
+            "description": "The primary text color for all screens in Jellyfin.",
+            "settingName": "colorText",
+            "type": "colorgrid",
+            "default": "#FFFFFF"
+          },
+          {
+            "title": "Secondary Text",
+            "description": "The secondary text color for all screens in Jellyfin.",
+            "settingName": "colorSubText",
+            "type": "colorgrid",
+            "default": "#777777FF"
+          },
+          {
+            "title": "Cursor",
+            "description": "The highlight color for the cursor showing where the user's focus is.",
+            "settingName": "colorCursor",
+            "type": "colorgrid",
+            "default": "#FF6666"
+          },
+          {
+            "title": "What's New Author",
+            "description": "The text color for the author in the What's New popup.",
+            "settingName": "colorWhatsNewAuthor",
+            "type": "colorgrid",
+            "default": "#FF6666"
+          },
+          {
+            "title": "Watched Check Mark & Unplayed Count",
+            "description": "Watched Check Mark & Unplayed Count color settings",
+            "children": [
+              {
+                "title": "Background",
+                "description": "The background color of the check mark & unplayed count shown in the top right corner of items.",
+                "settingName": "colorPlayedCheckmarkBackground",
+                "type": "colorgrid",
+                "default": "#6666FF"
+              },
+              {
+                "title": "Watched Check Mark",
+                "description": "The color of the watched check mark.",
+                "settingName": "colorPlayedCheckmarkIcon",
+                "type": "colorgrid",
+                "default": "#FFFFFF"
+              },
+              {
+                "title": "Unplayed Count",
+                "description": "The text color of the unplayed count number.",
+                "settingName": "colorUnplayedCountTextColor",
+                "type": "colorgrid",
+                "default": "#FFFFFF"
+              }
+            ]
+          }
         ]
-    },
-    {
-        "title": "Global",
-        "description": "Global settings that affect everyone that uses this Roku device.",
+      }
+    ]
+  },
+  {
+    "title": "Global",
+    "description": "Global settings that affect everyone that uses this Roku device.",
+    "children": [
+      {
+        "title": "Remember Me?",
+        "description": "Remember the currently logged in user and try to log them in again next time you start Jellyfin.",
+        "settingName": "global.rememberme",
+        "type": "bool",
+        "default": "true"
+      }
+    ]
+  },
+  {
+    "title": "Playback",
+    "description": "Settings relating to playback and supported codec and media types.",
+    "children": [
+      {
+        "title": "Autoplay Episode Limit",
path: settings/settings.json
user: login: DavidBriglio
body: Inconsistent formatting in this file was fixed on auto-save formatting (fixed to 2 spaces). The only thing actually added was this setting.
created_at: 2025-05-02T16:27:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,615 +1,622 @@
 [
-    {
-        "title": "Secret",
-        "description": "Settings that are not for public consumption. Do not get mad if these things change without notice.",
-        "visible": false,
+  {
+    "title": "Secret",
+    "description": "Settings that are not for public consumption. Do not get mad if these things change without notice.",
+    "visible": false,
+    "children": [
+      {
+        "title": "CJK Text",
+        "description": "Use CJK fallback font for text elements across the channel",
+        "settingName": "cjkText",
+        "type": "bool",
+        "default": "false"
+      },
+      {
+        "title": "Channel Background Image",
+        "description": "Overlay a background image over your chosen background color",
+        "settingName": "imageBackground",
+        "type": "radio",
+        "default": "",
+        "options": [
+          {
+            "title": "None",
+            "id": ""
+          },
+          {
+            "title": "Circles",
+            "id": "pkg:/images/background/bg1.jpg"
+          },
+          {
+            "title": "Swoosh",
+            "id": "pkg:/images/background/bg2.jpg"
+          },
+          {
+            "title": "Splashscreen Image",
+            "id": "splash"
+          }
+        ]
+      },
+      {
+        "title": "Color Settings",
+        "description": "Change the colors of elements in the channel",
         "children": [
-            {
-                "title": "CJK Text",
-                "description": "Use CJK fallback font for text elements across the channel",
-                "settingName": "cjkText",
-                "type": "bool",
-                "default": "false"
-            },
-            {
-                "title": "Channel Background Image",
-                "description": "Overlay a background image over your chosen background color",
-                "settingName": "imageBackground",
-                "type": "radio",
-                "default": "",
-                "options": [
-                    {
-                        "title": "None",
-                        "id": ""
-                    },
-                    {
-                        "title": "Circles",
-                        "id": "pkg:/images/background/bg1.jpg"
-                    },
-                    {
-                        "title": "Swoosh",
-                        "id": "pkg:/images/background/bg2.jpg"
-                    },
-                    {
-                        "title": "Splashscreen Image",
-                        "id": "splash"
-                    }
-                ]
-            },
-            {
-                "title": "Color Settings",
-                "description": "Change the colors of elements in the channel",
-                "children": [
-                    {
-                        "title": "Background",
-                        "description": "The base background color for all screens in Jellyfin.",
-                        "settingName": "colorBackground",
-                        "type": "colorgrid",
-                        "default": "#000018"
-                    },
-                    {
-                        "title": "Primary Text",
-                        "description": "The primary text color for all screens in Jellyfin.",
-                        "settingName": "colorText",
-                        "type": "colorgrid",
-                        "default": "#FFFFFF"
-                    },
-                    {
-                        "title": "Secondary Text",
-                        "description": "The secondary text color for all screens in Jellyfin.",
-                        "settingName": "colorSubText",
-                        "type": "colorgrid",
-                        "default": "#777777FF"
-                    },
-                    {
-                        "title": "Cursor",
-                        "description": "The highlight color for the cursor showing where the user's focus is.",
-                        "settingName": "colorCursor",
-                        "type": "colorgrid",
-                        "default": "#FF6666"
-                    },
-                    {
-                        "title": "What's New Author",
-                        "description": "The text color for the author in the What's New popup.",
-                        "settingName": "colorWhatsNewAuthor",
-                        "type": "colorgrid",
-                        "default": "#FF6666"
-                    },
-                    {
-                        "title": "Watched Check Mark & Unplayed Count",
-                        "description": "Watched Check Mark & Unplayed Count color settings",
-                        "children": [
-                            {
-                                "title": "Background",
-                                "description": "The background color of the check mark & unplayed count shown in the top right corner of items.",
-                                "settingName": "colorPlayedCheckmarkBackground",
-                                "type": "colorgrid",
-                                "default": "#6666FF"
-                            },
-                            {
-                                "title": "Watched Check Mark",
-                                "description": "The color of the watched check mark.",
-                                "settingName": "colorPlayedCheckmarkIcon",
-                                "type": "colorgrid",
-                                "default": "#FFFFFF"
-                            },
-                            {
-                                "title": "Unplayed Count",
-                                "description": "The text color of the unplayed count number.",
-                                "settingName": "colorUnplayedCountTextColor",
-                                "type": "colorgrid",
-                                "default": "#FFFFFF"
-                            }
-                        ]
-                    }
-                ]
-            }
+          {
+            "title": "Background",
+            "description": "The base background color for all screens in Jellyfin.",
+            "settingName": "colorBackground",
+            "type": "colorgrid",
+            "default": "#000018"
+          },
+          {
+            "title": "Primary Text",
+            "description": "The primary text color for all screens in Jellyfin.",
+            "settingName": "colorText",
+            "type": "colorgrid",
+            "default": "#FFFFFF"
+          },
+          {
+            "title": "Secondary Text",
+            "description": "The secondary text color for all screens in Jellyfin.",
+            "settingName": "colorSubText",
+            "type": "colorgrid",
+            "default": "#777777FF"
+          },
+          {
+            "title": "Cursor",
+            "description": "The highlight color for the cursor showing where the user's focus is.",
+            "settingName": "colorCursor",
+            "type": "colorgrid",
+            "default": "#FF6666"
+          },
+          {
+            "title": "What's New Author",
+            "description": "The text color for the author in the What's New popup.",
+            "settingName": "colorWhatsNewAuthor",
+            "type": "colorgrid",
+            "default": "#FF6666"
+          },
+          {
+            "title": "Watched Check Mark & Unplayed Count",
+            "description": "Watched Check Mark & Unplayed Count color settings",
+            "children": [
+              {
+                "title": "Background",
+                "description": "The background color of the check mark & unplayed count shown in the top right corner of items.",
+                "settingName": "colorPlayedCheckmarkBackground",
+                "type": "colorgrid",
+                "default": "#6666FF"
+              },
+              {
+                "title": "Watched Check Mark",
+                "description": "The color of the watched check mark.",
+                "settingName": "colorPlayedCheckmarkIcon",
+                "type": "colorgrid",
+                "default": "#FFFFFF"
+              },
+              {
+                "title": "Unplayed Count",
+                "description": "The text color of the unplayed count number.",
+                "settingName": "colorUnplayedCountTextColor",
+                "type": "colorgrid",
+                "default": "#FFFFFF"
+              }
+            ]
+          }
         ]
-    },
-    {
-        "title": "Global",
-        "description": "Global settings that affect everyone that uses this Roku device.",
+      }
+    ]
+  },
+  {
+    "title": "Global",
+    "description": "Global settings that affect everyone that uses this Roku device.",
+    "children": [
+      {
+        "title": "Remember Me?",
+        "description": "Remember the currently logged in user and try to log them in again next time you start Jellyfin.",
+        "settingName": "global.rememberme",
+        "type": "bool",
+        "default": "true"
+      }
+    ]
+  },
+  {
+    "title": "Playback",
+    "description": "Settings relating to playback and supported codec and media types.",
+    "children": [
+      {
+        "title": "Autoplay Episode Limit",
+        "description": "The number of episodes that will play automatically before stopping. Requires 'Play next episode automatically' server setting to be enabled. Set to 0 to disable.",
+        "settingName": "playback.episodeQueueLimit",
+        "type": "integer",
+        "default": "0"
path: settings/settings.json
user: login: 1hitsong
body: Isn't the current, hard coded, default value 50?

We should just set this default 50 and remove the hard coded value in the task.

```suggestion
        "default": "50"
```
created_at: 2025-05-02T17:42:36Z
author_association: MEMBER
diff_hunk: @@ -185,8 +185,9 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
     end if
 
     if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay
+        episodeQueueLimit = m.global.session.user.settings.["playback.episodeQueueLimit"].ToInt()
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: 1hitsong
body: Our largest cause of channel crashes is from us assuming settings will return values. We really need to update every setting lookup to not make this assumption.

Let's go ahead and start the cleanup with your PR 😃 

```suggestion
        episodeQueueLimit = chainLookupReturn(m.global.session, "user.settings.playback.episodeQueueLimit", "50")
        episodeQueueLimit = episodeQueueLimit.ToInt()
```
created_at: 2025-05-02T17:48:38Z
author_association: MEMBER
diff_hunk: @@ -569,10 +570,17 @@ sub addNextEpisodesToQueue(showID, additionalPartsCount as integer)
         end if
     end if
 
+    limitParam = queueLimit
+
+    ' If the queue limit is set to 0 / disabled, default to 50
+    if limitParam = 0
+        limitParam = 50
+    end if
+
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: 1hitsong
body: Unneeded if other changes are implemented.
created_at: 2025-05-02T17:49:23Z
author_association: MEMBER
diff_hunk: @@ -185,8 +185,9 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
     end if
 
     if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay
+        episodeQueueLimit = m.global.session.user.settings.["playback.episodeQueueLimit"].ToInt()
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: DavidBriglio
body: Doing some testing, since the setting is actually the string "playback.episodeQueueLimit" and not a chain property, we wouldn't be able to use "chainLookupReturn". I'd like to create a "lookupReturn" that returns a default value if the property is not valid on the root, without the chain logic.

Is the issue that you are trying to avoid "user.settings" being invalid? Or just the setting itself?
created_at: 2025-05-02T18:20:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,8 +185,9 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
     end if
 
     if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay
+        episodeQueueLimit = m.global.session.user.settings.["playback.episodeQueueLimit"].ToInt()
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: 1hitsong
body: Oh, yeah. Then just name the setting "episodeQueueLimit" without the extra period in the name. Or, if you're wanting to keep "playback" in the name, replace the . with a -.
created_at: 2025-05-02T18:35:40Z
author_association: MEMBER
diff_hunk: @@ -185,8 +185,9 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
     end if
 
     if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay
+        episodeQueueLimit = m.global.session.user.settings.["playback.episodeQueueLimit"].ToInt()
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: 1hitsong
body: > I'd like to create a "lookupReturn" that returns a default value if the property is not valid on the root, without the chain logic.

Brighterscript already supplies that to us.

`thisWillEqualFifty = thisIsInvalid ?? 50`
created_at: 2025-05-02T18:39:14Z
author_association: MEMBER
diff_hunk: @@ -572,7 +574,7 @@ sub addNextEpisodesToQueue(showID, additionalPartsCount as integer)
     url = Substitute("Shows/{0}/Episodes", showID)
     urlParams = { "UserId": m.global.session.user.id }
     urlParams.Append({ "StartItemId": videoID })
-    urlParams.Append({ "Limit": 50 })
+    urlParams.Append({ "Limit": queueLimit })
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: 1hitsong
body: The API's limit param includes the current episode. So if the user sets their Autoplay Episode Limit to 0, that means no next episodes will be played.

That also means if the user sets their Autoplay Episode Limit to 1, that no next episodes will be played.

That's def confusing. I work in the code and at first I was confused when testing. 😆 

I think the queueLimit should be +1 here.

The basic idea is the setting is the user telling the channel how many more episodes they want to automatically play after the one they select.
created_at: 2025-05-02T20:30:38Z
author_association: MEMBER
diff_hunk: @@ -572,7 +574,7 @@ sub addNextEpisodesToQueue(showID, additionalPartsCount as integer)
     url = Substitute("Shows/{0}/Episodes", showID)
     urlParams = { "UserId": m.global.session.user.id }
     urlParams.Append({ "StartItemId": videoID })
-    urlParams.Append({ "Limit": 50 })
+    urlParams.Append({ "Limit": queueLimit })
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: DavidBriglio
body: Yeah during my testing I found the same thing and was on the fence 😛  I'll update the logic and the setting description so that's more clear
created_at: 2025-05-02T21:00:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -572,7 +574,7 @@ sub addNextEpisodesToQueue(showID, additionalPartsCount as integer)
     url = Substitute("Shows/{0}/Episodes", showID)
     urlParams = { "UserId": m.global.session.user.id }
     urlParams.Append({ "StartItemId": videoID })
-    urlParams.Append({ "Limit": 50 })
+    urlParams.Append({ "Limit": queueLimit })
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: DavidBriglio
body: I'll opt to keep the default setting 50 though, seems cleaner than showing 49 to the user
created_at: 2025-05-02T21:09:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,8 +185,10 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
     end if
 
     if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay
+        episodeQueueLimit = chainLookupReturn(m.global.session, "user.settings.episodeQueueLimit", "50")
+        episodeQueueLimit = episodeQueueLimit.ToInt()
path: components/ItemGrid/LoadVideoContentTask.bs
user: login: 1hitsong
body: Move these 2 lines into the isValid check under them. No need to get these values if we're never going to use them.
created_at: 2025-05-02T21:15:17Z
author_association: MEMBER

PR comments:
user: login: 1hitsong
created_at: 2025-05-02T21:22:44Z
body: Everything else is looking good.

If you would like to have credit in the What's New popup, add a new entry in `source\static\whatsNew\3.0.3.json` but note that you misspelled "behavior" in your PR title 😉 
author_association: MEMBER
user: login: DavidBriglio
created_at: 2025-05-03T02:57:40Z
body: Thanks! And thank you for the quick turn around time!
author_association: CONTRIBUTOR