diff --git a/locales/en-US.json b/locales/en-US.json index 5554b9286..44b40c249 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -404,9 +404,7 @@ "`x` marked it with a ❤": "`x` marked it with a ❤", "Audio mode": "Audio mode", "Video mode": "Video mode", - "Videos": "Videos", "Playlists": "Playlists", - "Community": "Community", "search_filters_title": "Filters", "search_filters_date_label": "Upload date", "search_filters_date_option_none": "Any date", @@ -472,5 +470,10 @@ "crash_page_read_the_faq": "read the Frequently Asked Questions (FAQ)", "crash_page_search_issue": "searched for existing issues on GitHub", "crash_page_report_issue": "If none of the above helped, please open a new issue on GitHub (preferably in English) and include the following text in your message (do NOT translate that text):", - "error_video_not_in_playlist": "The requested video doesn't exist in this playlist. Click here for the playlist home page." + "error_video_not_in_playlist": "The requested video doesn't exist in this playlist. Click here for the playlist home page.", + "channel_tab_videos_label": "Videos", + "channel_tab_shorts_label": "Shorts", + "channel_tab_streams_label": "Livestreams", + "channel_tab_playlists_label": "Playlists", + "channel_tab_community_label": "Community" } diff --git a/src/invidious/channels/about.cr b/src/invidious/channels/about.cr index bb9bd8c71..09c3427a3 100644 --- a/src/invidious/channels/about.cr +++ b/src/invidious/channels/about.cr @@ -104,8 +104,14 @@ def get_about_info(ucid, locale) : AboutChannel if tabs_json = initdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"]? # Get the name of the tabs available on this channel - tab_names = tabs_json.as_a - .compact_map(&.dig?("tabRenderer", "title").try &.as_s.downcase) + tab_names = tabs_json.as_a.compact_map do |entry| + name = entry.dig?("tabRenderer", "title").try &.as_s.downcase + + # This is a small fix to not add extra code on the HTML side + # I.e, the URL for the "live" tab is .../streams, so use "streams" + # everywhere for the sake of simplicity + (name == "live") ? "streams" : name + end # Get the currently active tab ("About") about_tab = extract_selected_tab(tabs_json) diff --git a/src/invidious/frontend/channel_page.cr b/src/invidious/frontend/channel_page.cr new file mode 100644 index 000000000..7ac0e071c --- /dev/null +++ b/src/invidious/frontend/channel_page.cr @@ -0,0 +1,43 @@ +module Invidious::Frontend::ChannelPage + extend self + + enum TabsAvailable + Videos + Shorts + Streams + Playlists + Community + end + + def generate_tabs_links(locale : String, channel : AboutChannel, selected_tab : TabsAvailable) + return String.build(1500) do |str| + base_url = "/channel/#{channel.ucid}" + + TabsAvailable.each do |tab| + # Ignore playlists, as it is not supported for auto-generated channels yet + next if (tab.playlists? && channel.auto_generated) + + tab_name = tab.to_s.downcase + + if channel.tabs.includes? tab_name + str << %(
\n) + + if tab == selected_tab + str << "\t" + str << translate(locale, "channel_tab_#{tab_name}_label") + str << "\n" + else + # Video tab doesn't have the last path component + url = tab.videos? ? base_url : "#{base_url}/#{tab_name}" + + str << %(\t) + str << translate(locale, "channel_tab_#{tab_name}_label") + str << "\n" + end + + str << "
" + end + end + end + end +end diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr index 2773deb78..78b383419 100644 --- a/src/invidious/routes/channels.cr +++ b/src/invidious/routes/channels.cr @@ -18,7 +18,7 @@ module Invidious::Routes::Channels sort_options = {"last", "oldest", "newest"} sort_by ||= "last" - items, continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) + items, next_continuation = fetch_channel_playlists(channel.ucid, channel.author, continuation, sort_by) items.uniq! do |item| if item.responds_to?(:title) item.title @@ -32,11 +32,59 @@ module Invidious::Routes::Channels sort_options = {"newest", "oldest", "popular"} sort_by ||= "newest" - items, continuation = Channel::Tabs.get_60_videos( + # Fetch items and continuation token + items, next_continuation = Channel::Tabs.get_videos( channel, continuation: continuation, sort_by: sort_by ) end + selected_tab = Frontend::ChannelPage::TabsAvailable::Videos + templated "channel" + end + + def self.shorts(env) + data = self.fetch_basic_information(env) + return data if !data.is_a?(Tuple) + + locale, user, subscriptions, continuation, ucid, channel = data + + if !channel.tabs.includes? "shorts" + return env.redirect "/channel/#{channel.ucid}" + end + + # TODO: support sort option for shorts + sort_by = "" + sort_options = [] of String + + # Fetch items and continuation token + items, next_continuation = Channel::Tabs.get_shorts( + channel, continuation: continuation + ) + + selected_tab = Frontend::ChannelPage::TabsAvailable::Shorts + templated "channel" + end + + def self.streams(env) + data = self.fetch_basic_information(env) + return data if !data.is_a?(Tuple) + + locale, user, subscriptions, continuation, ucid, channel = data + + if !channel.tabs.includes? "streams" + return env.redirect "/channel/#{channel.ucid}" + end + + # TODO: support sort option for livestreams + sort_by = "" + sort_options = [] of String + + # Fetch items and continuation token + items, next_continuation = Channel::Tabs.get_60_livestreams( + channel, continuation: continuation + ) + + selected_tab = Frontend::ChannelPage::TabsAvailable::Streams templated "channel" end @@ -124,7 +172,7 @@ module Invidious::Routes::Channels end selected_tab = env.request.path.split("/")[-1] - if ["home", "videos", "playlists", "community", "channels", "about"].includes? selected_tab + if {"home", "videos", "shorts", "streams", "playlists", "community", "channels", "about"}.includes? selected_tab url = "/channel/#{ucid}/#{selected_tab}" else url = "/channel/#{ucid}" diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index f409f13c8..08739c3d3 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -115,6 +115,8 @@ module Invidious::Routing get "/channel/:ucid", Routes::Channels, :home get "/channel/:ucid/home", Routes::Channels, :home get "/channel/:ucid/videos", Routes::Channels, :videos + get "/channel/:ucid/shorts", Routes::Channels, :shorts + get "/channel/:ucid/streams", Routes::Channels, :streams get "/channel/:ucid/playlists", Routes::Channels, :playlists get "/channel/:ucid/community", Routes::Channels, :community get "/channel/:ucid/about", Routes::Channels, :about @@ -122,7 +124,7 @@ module Invidious::Routing get "/user/:user/live", Routes::Channels, :live get "/c/:user/live", Routes::Channels, :live - ["", "/videos", "/playlists", "/community", "/about"].each do |path| + {"", "/videos", "/shorts", "/streams", "/playlists", "/community", "/about"}.each do |path| # /c/LinusTechTips get "/c/:user#{path}", Routes::Channels, :brand_redirect # /user/linustechtips | Not always the same as /c/ diff --git a/src/invidious/views/channel.ecr b/src/invidious/views/channel.ecr index 878587d44..f6cc3340f 100644 --- a/src/invidious/views/channel.ecr +++ b/src/invidious/views/channel.ecr @@ -64,23 +64,8 @@ <%= translate(locale, "Switch Invidious Instance") %> <% end %> - <% if !channel.auto_generated %> -
- <%= translate(locale, "Videos") %> -
- <% end %> -
- <% if channel.auto_generated %> - <%= translate(locale, "Playlists") %> - <% else %> - <%= translate(locale, "Playlists") %> - <% end %> -
-
- <% if channel.tabs.includes? "community" %> - <%= translate(locale, "Community") %> - <% end %> -
+ + <%= Invidious::Frontend::ChannelPage.generate_tabs_links(locale, channel, selected_tab) %>
@@ -111,7 +96,12 @@
-
-
-
+
+
+ <% if next_continuation %> + &sort_by=<%= URI.encode_www_form(sort_by) %><% end %>"> + <%= translate(locale, "Next page") %> + + <% end %> +
diff --git a/src/invidious/views/community.ecr b/src/invidious/views/community.ecr index 3bc29e552..e467a679c 100644 --- a/src/invidious/views/community.ecr +++ b/src/invidious/views/community.ecr @@ -50,19 +50,8 @@ <%= translate(locale, "Switch Invidious Instance") %> <% end %> - <% if !channel.auto_generated %> -
- <%= translate(locale, "Videos") %> -
- <% end %> -
- <%= translate(locale, "Playlists") %> -
-
- <% if channel.tabs.includes? "community" %> - <%= translate(locale, "Community") %> - <% end %> -
+ + <%= Invidious::Frontend::ChannelPage.generate_tabs_links(locale, channel, Invidious::Frontend::ChannelPage::TabsAvailable::Community) %>
diff --git a/src/invidious/views/playlists.ecr b/src/invidious/views/playlists.ecr index c8718e7b7..56d25ef5d 100644 --- a/src/invidious/views/playlists.ecr +++ b/src/invidious/views/playlists.ecr @@ -54,19 +54,7 @@ <% end %> -
- <%= translate(locale, "Videos") %> -
-
- <% if !channel.auto_generated %> - <%= translate(locale, "Playlists") %> - <% end %> -
-
- <% if channel.tabs.includes? "community" %> - <%= translate(locale, "Community") %> - <% end %> -
+ <%= Invidious::Frontend::ChannelPage.generate_tabs_links(locale, channel, Invidious::Frontend::ChannelPage::TabsAvailable::Playlists) %>