Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ public PluginConfiguration()
jellyseerrServerUrl = new() { value = "Enter jellyseerr server url" },
searchEngine = new() { value = SearchEngine.Jellyfin },
marlinServerUrl = new() { value = "Enter marlin server url" },
libraryOptions = new() { value = new LibraryOptions() },
libraryOptions = new() { value = new LibraryOptions() },
tvSidebarLinks = new() { value = new SidebarLink[] { } },
Copy link
Preview

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using Array.Empty<SidebarLink>() instead of new SidebarLink[] { } for better performance and clarity when initializing empty arrays.

Suggested change
tvSidebarLinks = new() { value = new SidebarLink[] { } },
tvSidebarLinks = new() { value = Array.Empty<SidebarLink>() },

Copilot uses AI. Check for mistakes.

home = new()
{
value = new Home
Expand Down
7 changes: 7 additions & 0 deletions Jellyfin.Plugin.Streamyfin/Configuration/Settings/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ public enum DownloadQuality
High
}

[JsonConverter(typeof(StringEnumConverter))]
public enum SidebarLinkType
{
library,
collection
}

// Limit Int range. Don't use Converter for this since we want them to enter int value
public enum RemuxConcurrentLimit
{
Expand Down
25 changes: 25 additions & 0 deletions Jellyfin.Plugin.Streamyfin/Configuration/Settings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,27 @@ public class SuggestionsArgs
public BaseItemKind[]? type { get; set; }
}

public class SidebarLink
{
[NotNull]
[Display(Name = "Name", Description = "Display name for the link in the TV sidebar")]
public string name { get; set; } = default!;

[NotNull]
[Display(Name = "Type", Description = "The type of link this is (library or collection)")]
public SidebarLinkType type { get; set; }

[NotNull]
[Display(Name = "Id", Description = "The target id for the link (Library or Collection id)")]
public string id { get; set; } = default!;

[Display(Name = "Icon", Description = "Optional icon URL to display for the link")]
public string? icon { get; set; }

[Display(Name = "Sections", Description = "Optional content sections to display when this sidebar link is opened (same schema as home.sections)")]
public Section[]? sections { get; set; }
}

/// <summary>
/// Streamyfin application settings
/// </summary>
Expand Down Expand Up @@ -269,6 +290,10 @@ public class Settings
[NotNull]
[Display(Name = "Library options", Description = "Customize how you want streamfins library tab to look")]
public Lockable<LibraryOptions>? libraryOptions { get; set; }

[NotNull]
[Display(Name = "TV sidebar links", Description = "Custom links to show in the TV app sidebar")]
public Lockable<SidebarLink[]?>? tvSidebarLinks { get; set; }
Copy link
Preview

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nested nullable types Lockable<SidebarLink[]?>? create unnecessary complexity. Consider simplifying to Lockable<SidebarLink[]>? since the inner array can be empty instead of null.

Suggested change
public Lockable<SidebarLink[]?>? tvSidebarLinks { get; set; }
public Lockable<SidebarLink[]>? tvSidebarLinks { get; set; }

Copilot uses AI. Check for mistakes.


// TODO: These are used outside of settings. Review usages/delete any unused later.
// public Lockable<bool?>? forceLandscapeInVideoPlayer { get; set; }
Expand Down
34 changes: 34 additions & 0 deletions examples/full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,40 @@ settings:
showTitles: boolean
showStats: boolean

# TV app sidebar
tvSidebarLinks:
locked: false
value:
- name: Movies
type: library
id: <library id>
icon: https://example.com/movies.png
sections:
- title: Recently Added
orientation: vertical
items:
sortBy:
- DateCreated
sortOrder:
- Descending
includeItemTypes:
- Movie
limit: 25
- name: Netflix
type: collection
id: <collection id>
icon: https://example.com/netflix.png
sections:
- title: Continue Watching
orientation: horizontal
items:
filters:
- IsResumable
includeItemTypes:
- Episode
- Movie
limit: 20

# Home
home:
locked: true
Expand Down
Loading