Introduce ability to hide shorts/livestreams in subscription feed

[config/config.example.yml]
- Introduce new default value for hide_shorts_and_live

[locales/en-US.json]
- Add translation label for hide_shorts_and_live

[src/invidious/config.cr]
- Add default value for hide_shorts_and_live to ConfigPreferences

[src/invidious/users.cr]
- Add filtering for shorts and listreams if hide_shorts_and_live is active

[src/invidious/routes/preferences.cr]
- Retrieve and convert hide_shorts_and_live option from preferences page
  to preferences object

[src/invidious/user/preferences.cr]
- Add hide_shorts_and_live property

[src/invidious/views/user/preferences.ecr]
- Add div, label and input for new hide_shorts_and_live option
This commit is contained in:
Harm 2026-01-23 18:45:50 +01:00
parent d51a7a44ad
commit 0bce7311c2
7 changed files with 25 additions and 0 deletions

View File

@ -939,6 +939,14 @@ default_user_preferences:
## ##
#sort: published #sort: published
##
## In the "Subscription" feed, Only show the videos, no shorts
## or livestreams.
##
## Accepted values: true, false
## Default: false
##
#hide_shorts_and_live: false
# ----------------------------- # -----------------------------
# Miscellaneous # Miscellaneous

View File

@ -133,6 +133,7 @@
"Only show latest video from channel: ": "Only show latest video from channel: ", "Only show latest video from channel: ": "Only show latest video from channel: ",
"Only show latest unwatched video from channel: ": "Only show latest unwatched video from channel: ", "Only show latest unwatched video from channel: ": "Only show latest unwatched video from channel: ",
"preferences_unseen_only_label": "Only show unwatched: ", "preferences_unseen_only_label": "Only show unwatched: ",
"preferences_hide_shorts_and_live_label": "Hide shorts and live streams: ",
"preferences_notifications_only_label": "Only show notifications (if there are any): ", "preferences_notifications_only_label": "Only show notifications (if there are any): ",
"Enable web notifications": "Enable web notifications", "Enable web notifications": "Enable web notifications",
"`x` uploaded a video": "`x` uploaded a video", "`x` uploaded a video": "`x` uploaded a video",

View File

@ -47,6 +47,7 @@ struct ConfigPreferences
property thin_mode : Bool = false property thin_mode : Bool = false
property unseen_only : Bool = false property unseen_only : Bool = false
property video_loop : Bool = false property video_loop : Bool = false
property hide_shorts_and_live : Bool = false
property extend_desc : Bool = false property extend_desc : Bool = false
property volume : Int32 = 100 property volume : Int32 = 100
property vr_mode : Bool = true property vr_mode : Bool = true

View File

@ -143,6 +143,10 @@ module Invidious::Routes::PreferencesRoute
notifications_only ||= "off" notifications_only ||= "off"
notifications_only = notifications_only == "on" notifications_only = notifications_only == "on"
hide_shorts_and_live = env.params.body["hide_shorts_and_live"]?.try &.as(String)
hide_shorts_and_live ||= "off"
hide_shorts_and_live = hide_shorts_and_live == "on"
default_playlist = env.params.body["default_playlist"]?.try &.as(String) default_playlist = env.params.body["default_playlist"]?.try &.as(String)
# Convert to JSON and back again to take advantage of converters used for compatibility # Convert to JSON and back again to take advantage of converters used for compatibility
@ -182,6 +186,7 @@ module Invidious::Routes::PreferencesRoute
show_nick: show_nick, show_nick: show_nick,
save_player_pos: save_player_pos, save_player_pos: save_player_pos,
default_playlist: default_playlist, default_playlist: default_playlist,
hide_shorts_and_live: hide_shorts_and_live,
}.to_json) }.to_json)
if user = env.get? "user" if user = env.get? "user"

View File

@ -57,6 +57,7 @@ struct Preferences
property volume : Int32 = CONFIG.default_user_preferences.volume property volume : Int32 = CONFIG.default_user_preferences.volume
property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos property save_player_pos : Bool = CONFIG.default_user_preferences.save_player_pos
property default_playlist : String? = nil property default_playlist : String? = nil
property hide_shorts_and_live : Bool = CONFIG.default_user_preferences.hide_shorts_and_live
module BoolToString module BoolToString
def self.to_json(value : String, json : JSON::Builder) def self.to_json(value : String, json : JSON::Builder)

View File

@ -83,6 +83,10 @@ def get_subscription_feed(user, max_results = 40, page = 1)
end end
end end
if user.preferences.hide_shorts_and_live
videos = videos.select { |v| v.length_seconds > 0 }
end
case user.preferences.sort case user.preferences.sort
when "published - reverse" when "published - reverse"
videos.sort_by!(&.published) videos.sort_by!(&.published)

View File

@ -229,6 +229,11 @@
<input name="watch_history" id="watch_history" type="checkbox" <% if preferences.watch_history %>checked<% end %>> <input name="watch_history" id="watch_history" type="checkbox" <% if preferences.watch_history %>checked<% end %>>
</div> </div>
<div class="pure-control-group">
<label for="hide_shorts_and_live"><%= translate(locale, "preferences_hide_shorts_and_live_label") %></label>
<input name="hide_shorts_and_live" id="hide_shorts_and_live" type="checkbox" <% if preferences.hide_shorts_and_live %>checked<% end %>>
</div>
<div class="pure-control-group"> <div class="pure-control-group">
<label for="annotations_subscribed"><%= translate(locale, "preferences_annotations_subscribed_label") %></label> <label for="annotations_subscribed"><%= translate(locale, "preferences_annotations_subscribed_label") %></label>
<input name="annotations_subscribed" id="annotations_subscribed" type="checkbox" <% if preferences.annotations_subscribed %>checked<% end %>> <input name="annotations_subscribed" id="annotations_subscribed" type="checkbox" <% if preferences.annotations_subscribed %>checked<% end %>>