<%= item.description_html %>
+ + <% ucid = contents.ucid %> + <% author = contents.author %> + <% sub_count_text = number_to_short_text(contents.subscriber_count) %> + <%= rendered "components/subscribe_widget" %> +diff --git a/assets/css/channel.css b/assets/css/channel.css index d4aefca8..85d66a68 100644 --- a/assets/css/channel.css +++ b/assets/css/channel.css @@ -50,3 +50,70 @@ #link-widget-primary a:hover { color: #e1e1e1 !important; } + +/* Featured channels page */ + +.channel-section details { + margin: 20px; +} + +.channel-section details summary { + margin-bottom: 20px; +} + +.channel-section details summary::marker { + font-size: 1.3em; +} + +.category-heading { + font-size: 1.2em; + user-select: none; + display: inline; +} + +.section-contents .channel-profile { + text-align: center; +} + +/* Due to space constraints we'll make the special large featured channel display +only show up when the screen is wide enough */ + +@media screen and (min-width: 600px) { + .large-featured-channel.channel-profile { + /* We don't want the following attribute for large featured channels*/ + text-align: initial; + margin: initial; + + display: flex; + } + + .large-featured-channel.channel-profile img { + margin: 20% 0; + } + + .large-featured-channel .featured-channel-about { + margin-left: 2em; + } + + .large-featured-channel .featured-channel-title { + font-size: 1.2em; + margin-bottom: 10px + } + + .large-featured-channel .featured-channel-description { + margin-top: 10px; + font-weight: normal; + } +} + +/* Replicate the look for a normal featured channel */ +@media screen and (max-width: 600px) { + .large-featured-channel .seperator, .large-featured-channel .featured-channel-description { + display: none + } + + .large-featured-channel .featured-channel-metadata:last-child { + display: block; + margin-top: 1em; + } +} diff --git a/assets/css/default.css b/assets/css/default.css index c46f221a..b82a03c6 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -359,7 +359,7 @@ span > select { .light-theme a:hover, .light-theme a:active, -.light-theme summary:hover { +.light-theme .simulated_a:hover { color: #075A9E !important; } @@ -386,7 +386,7 @@ span > select { @media (prefers-color-scheme: light) { .no-theme a:hover, .no-theme a:active, - .no-theme summary:hover { + .no-theme .simulated_a:hover { color: #075A9E !important; } @@ -417,7 +417,7 @@ span > select { .dark-theme a:hover, .dark-theme a:active, -.dark-theme summary:hover { +.dark-theme .simulated_a:hover { color: rgb(0, 182, 240); } diff --git a/locales/ar.json b/locales/ar.json index aca6c421..e588c9dd 100644 --- a/locales/ar.json +++ b/locales/ar.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/bn_BD.json b/locales/bn_BD.json index bf2cc0e4..905f0bab 100644 --- a/locales/bn_BD.json +++ b/locales/bn_BD.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/cs.json b/locales/cs.json index a07cf0ab..96a5997c 100644 --- a/locales/cs.json +++ b/locales/cs.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" -} \ No newline at end of file + "Links": "", + "This channel doesn't feature any other channels.": "" +} diff --git a/locales/da.json b/locales/da.json index 05789450..2ce0f2f5 100644 --- a/locales/da.json +++ b/locales/da.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } \ No newline at end of file diff --git a/locales/de.json b/locales/de.json index 6ede2001..3e1ed9a9 100644 --- a/locales/de.json +++ b/locales/de.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/el.json b/locales/el.json index 36ff4127..9e5ef8ae 100644 --- a/locales/el.json +++ b/locales/el.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/en-US.json b/locales/en-US.json index 95f44992..27b62373 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -429,5 +429,6 @@ "Country: ": "Country: ", "Stats": "Stats", "Joined": "Joined", - "Links": "Links" + "Links": "Links", + "This channel doesn't feature any other channels.": "This channel doesn't feature any other channels." } diff --git a/locales/eo.json b/locales/eo.json index aab40e9b..7bd28d2d 100644 --- a/locales/eo.json +++ b/locales/eo.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/es.json b/locales/es.json index ad30aa32..0c601bc2 100644 --- a/locales/es.json +++ b/locales/es.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/eu.json b/locales/eu.json index 94e97b03..b5707070 100644 --- a/locales/eu.json +++ b/locales/eu.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/fa.json b/locales/fa.json index 84866283..2f5b95bb 100644 --- a/locales/fa.json +++ b/locales/fa.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/fi.json b/locales/fi.json index 566f71fa..f595bc6a 100644 --- a/locales/fi.json +++ b/locales/fi.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/fr.json b/locales/fr.json index cb159f10..c22526c7 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/he.json b/locales/he.json index 13e42495..e35cdb42 100644 --- a/locales/he.json +++ b/locales/he.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/hr.json b/locales/hr.json index 381dd4f2..6dd2139f 100644 --- a/locales/hr.json +++ b/locales/hr.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/hu-HU.json b/locales/hu-HU.json index 3bad8f4d..72c4476c 100644 --- a/locales/hu-HU.json +++ b/locales/hu-HU.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/id.json b/locales/id.json index 9fc8decb..ceed0108 100644 --- a/locales/id.json +++ b/locales/id.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/is.json b/locales/is.json index 1e31887c..bf0468fa 100644 --- a/locales/is.json +++ b/locales/is.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/it.json b/locales/it.json index ee8b82c2..f39e1ae6 100644 --- a/locales/it.json +++ b/locales/it.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/ja.json b/locales/ja.json index a7e696ba..fe9e8b03 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/nb-NO.json b/locales/nb-NO.json index bf24eece..de3aa960 100644 --- a/locales/nb-NO.json +++ b/locales/nb-NO.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/nl.json b/locales/nl.json index 9c9269c9..721617c9 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/pl.json b/locales/pl.json index 1cf10ed7..35fde291 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/pt-BR.json b/locales/pt-BR.json index 694f9143..c2f98814 100644 --- a/locales/pt-BR.json +++ b/locales/pt-BR.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/pt-PT.json b/locales/pt-PT.json index a490dd8c..faf3c09b 100644 --- a/locales/pt-PT.json +++ b/locales/pt-PT.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/ro.json b/locales/ro.json index b673211f..c8b84312 100644 --- a/locales/ro.json +++ b/locales/ro.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/ru.json b/locales/ru.json index 4dea5acc..530699b4 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/si.json b/locales/si.json index 375bdcfb..000f4472 100644 --- a/locales/si.json +++ b/locales/si.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/sk.json b/locales/sk.json index 1560521e..d9428ed0 100644 --- a/locales/sk.json +++ b/locales/sk.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/sr.json b/locales/sr.json index 4539d2e8..b9ee3cae 100644 --- a/locales/sr.json +++ b/locales/sr.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/sr_Cyrl.json b/locales/sr_Cyrl.json index 49ed4f36..e9d6a8cc 100644 --- a/locales/sr_Cyrl.json +++ b/locales/sr_Cyrl.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/sv-SE.json b/locales/sv-SE.json index 9f823143..d13d84d1 100644 --- a/locales/sv-SE.json +++ b/locales/sv-SE.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/tr.json b/locales/tr.json index 7d8bbfcf..ad749eb1 100644 --- a/locales/tr.json +++ b/locales/tr.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/uk.json b/locales/uk.json index b3b17fdd..ca88b25c 100644 --- a/locales/uk.json +++ b/locales/uk.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 4cfc4530..3128535e 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 8f2ab47c..df5c13ce 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -429,5 +429,6 @@ "Country: ": "", "Stats": "", "Joined": "", - "Links": "" + "Links": "", + "This channel doesn't feature any other channels.": "" } diff --git a/src/invidious.cr b/src/invidious.cr index ac0be960..c771d406 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -322,6 +322,8 @@ end Invidious::Routing.get "/channel/:ucid/videos", Invidious::Routes::Channels, :videos Invidious::Routing.get "/channel/:ucid/playlists", Invidious::Routes::Channels, :playlists Invidious::Routing.get "/channel/:ucid/community", Invidious::Routes::Channels, :community + Invidious::Routing.get "/channel/:ucid/channels", Invidious::Routes::Channels, :channels + Invidious::Routing.get "/channel/:ucid/channels/:param", Invidious::Routes::Channels, :featured_channel_category Invidious::Routing.get "/channel/:ucid/about", Invidious::Routes::Channels, :about ["", "/videos", "/playlists", "/community", "/about"].each do |path| diff --git a/src/invidious/channels/about.cr b/src/invidious/channels/about.cr index 7477e736..27f77466 100644 --- a/src/invidious/channels/about.cr +++ b/src/invidious/channels/about.cr @@ -16,7 +16,7 @@ struct AboutChannel property is_family_friendly : Bool property allowed_regions : Array(String) property related_channels : Array(AboutRelatedChannel) - property tabs : Hash(String, String) + property tabs : Hash(String, Tuple(Int32, String)) # TabName => {TabiZZndex, browseEndpoint params} property links : Array(Tuple(String, String, String)) end @@ -124,10 +124,13 @@ def get_about_info(ucid, locale) country = "" total_views = 0_i64 joined = Time.unix(0) - tabs = {} of String => String # TabName => browseEndpoint params + tabs = {} of String => Tuple(Int32, String) # TabName => {TabiZZndex, browseEndpoint params} links = [] of {String, String, String} tabs_json = initdata["contents"]["twoColumnBrowseResultsRenderer"]["tabs"]?.try &.as_a? + tab_names = [] of String + tab_data = [] of Tuple(Int32, String) + if !tabs_json.nil? # Retrieve information from the tabs array. The index we are looking for varies between channels. tabs_json.each do |node| @@ -172,10 +175,14 @@ def get_about_info(ucid, locale) auto_generated = true end end + if node["tabRenderer"]? + tab_names << node["tabRenderer"]["title"].as_s.downcase + tab_data << {i, node["tabRenderer"]["endpoint"]["browseEndpoint"]["params"].as_s} + end + end - tab_names = tabs_json.reject { |node| node["tabRenderer"]?.nil? }.map { |node| node["tabRenderer"]["title"].as_s.downcase } - browse_endpoint_param = tabs_json.reject { |node| node["tabRenderer"]?.nil? }.map { |node| node["tabRenderer"]["endpoint"]["browseEndpoint"]["params"].as_s } - tabs = Hash.zip(tab_names, browse_endpoint_param) + + tabs = Hash.zip(tab_names, tab_data) end sub_count = initdata["header"]["c4TabbedHeaderRenderer"]?.try &.["subscriberCountText"]?.try &.["simpleText"]?.try &.as_s? diff --git a/src/invidious/featured_channels.cr b/src/invidious/featured_channels.cr new file mode 100644 index 00000000..0b44aeae --- /dev/null +++ b/src/invidious/featured_channels.cr @@ -0,0 +1,170 @@ +struct FeaturedChannel + include DB::Serializable + + property author : String + property ucid : String + property author_thumbnail : String + property subscriber_count : Int32 + property video_count : Int32 + property description_html : String? + + def to_json(locale, json : JSON::Builder) + json.object do + json.field "author", self.author + json.field "authorId", self.ucid + json.field "authorUrl", "/channel/#{self.ucid}" + json.field "authorThumbnails" do + json.array do + qualities = {32, 48, 76, 100, 176, 512} + + qualities.each do |quality| + json.object do + json.field "url", self.author_thumbnail.gsub(/=\d+/, "=s#{quality}") + json.field "width", quality + json.field "height", quality + end + end + end + end + + json.field "description", html_to_content(self.description_html) + json.field "descriptionHtml", self.description_html + json.field "subCount", self.subscriber_count + json.field "videoCount", self.video_count + json.field "badges", self.badges + end + end + + def to_json(locale, json : JSON::Builder | Nil = nil) + if json + to_json(locale, json) + else + JSON.build do |json| + to_json(locale, json) + end + end + end +end + +struct Category + include DB::Serializable + + property title : String + property contents : Array(FeaturedChannel) | FeaturedChannel + property browse_endpoint_param : String? + property continuation_token : String? + + def to_json(locale, json : JSON::Builder) + json.object do + json.field "title", self.title + json.field "contents", self.contents + end + end + + def to_json(locale, json : JSON::Builder | Nil = nil) + if json + to_json(locale, json) + else + JSON.build do |json| + to_json(locale, json) + end + end + end +end + +def _extract_channel_data(channel) + ucid = channel["channelId"].as_s + author = channel["title"]["simpleText"].as_s + author_thumbnail = channel["thumbnail"]["thumbnails"].as_a[0]["url"].as_s + subscriber_count = channel["subscriberCountText"]?.try &.["simpleText"]?.try &.as_s? + .try { |text| short_text_to_number(text.split(" ")[0]) } || 0 + + video_count = channel["videoCountText"]?.try &.["runs"][0]["text"].as_s.gsub(/\D/, "").to_i || 0 + + if channel["descriptionSnippet"]? + description = channel["descriptionSnippet"]["runs"][0]["text"].as_s + description_html = HTML.escape(description).gsub("\n", "") + else + description_html = nil + end + + FeaturedChannel.new({ + author: author, + ucid: ucid, + author_thumbnail: author_thumbnail, + subscriber_count: subscriber_count, + video_count: video_count, + description_html: description_html + }) +end + +def process_featured_channels(data, submenu_data, title=nil, continuation_items=false) + all_categories = [] of Category + + if submenu_data.is_a?(Bool) + return all_categories + end + + # Extraction process differs when there's more than one category + if data.size > 1 + data.each do |raw_category| + raw_category = raw_category["itemSectionRenderer"]["contents"].as_a[0]["shelfRenderer"] + + category_title = raw_category["title"]["runs"][0]["text"].as_s + browse_endpoint_param = raw_category["endpoint"]["browseEndpoint"]["params"].as_s + + # Category has multiple channels + if raw_category["content"].as_h.has_key?("horizontalListRenderer") + contents = [] of FeaturedChannel + raw_category["content"]["horizontalListRenderer"]["items"].as_a.each do |channel| + contents << _extract_channel_data(channel["gridChannelRenderer"]) + end + # Single channel + else + channel = raw_category["content"]["expandedShelfContentsRenderer"]["items"][0]["channelRenderer"] + contents = _extract_channel_data(channel) + end + + all_categories << Category.new({ + title: category_title, + contents: contents, + browse_endpoint_param: browse_endpoint_param, + continuation_token: nil + }) + end + else + if !continuation_items + raw_category_contents = data[0]["itemSectionRenderer"]["contents"].as_a[0]["gridRenderer"]["items"].as_a + else + raw_category_contents = data[0].as_a + end + + category_title = submenu_data.try &.[0]["title"].as_s || title || "" + + browse_endpoint_param = nil # Not needed + continuation_token = nil + + # If a continuation token is needed it'll always be after at least twelve channels + if raw_category_contents.size > 12 + continuation_token = raw_category_contents[-1]["continuationItemRenderer"]?.try &.["continuationEndpoint"]["continuationCommand"]["token"].as_s || nil + + if !continuation_token.nil? + raw_category_contents = raw_category_contents[0..-2] + end + end + + contents = [] of FeaturedChannel + raw_category_contents.each do |channel| + contents << _extract_channel_data(channel["gridChannelRenderer"]) + end + + all_categories << Category.new({ + title: category_title, + contents: contents, + browse_endpoint_param: browse_endpoint_param, + continuation_token: continuation_token + }) + end + + return all_categories +end diff --git a/src/invidious/routes/channels.cr b/src/invidious/routes/channels.cr index 0d4cc3c9..b6de7063 100644 --- a/src/invidious/routes/channels.cr +++ b/src/invidious/routes/channels.cr @@ -91,6 +91,69 @@ module Invidious::Routes::Channels templated "community" end + def self.channels(env) + data = self.fetch_basic_information(env) + if !data.is_a?(Tuple) + return data + end + locale, user, subscriptions, continuation, ucid, channel = data + + if !channel.tabs.has_key?("channels") + return env.redirect "/channel/#{channel.ucid}" + end + + # When a channel only has a single category it lacks the category param option so we'll handle it here. + if continuation + offset = env.params.query["offset"]? + if offset + offset = offset.to_i + else + offset = 0 + end + + # Previous continuation + previous_continuation = env.params.query["previous"]? + # Category title is not returned when using a continuation token. + title = env.params.query["title"]? + + featured_channel_categories = fetch_channel_featured_channels(ucid, channel.tabs["channels"], nil, continuation, title).not_nil! + else + previous_continuation = nil + category_param = nil + offset = 0 + title = nil + + featured_channel_categories = fetch_channel_featured_channels(ucid, channel.tabs["channels"], nil, nil).not_nil! + end + + templated "channels" + end + + def self.featured_channel_category(env) + # Used to check when the initial page is reached and redirect to /channel/:ucid/channels/:param when zero + offset = env.params.query["offset"]? + category_param = env.params.url["param"] + if offset + offset = offset.to_i + else + offset = 0 + end + + data = self.fetch_basic_information(env) + if !data.is_a?(Tuple) + return data + end + locale, user, subscriptions, continuation, ucid, channel = data + + # Previous continuation + previous_continuation = env.params.query["previous"]? + # Category title is not returned when using a continuation token. + title = env.params.query["title"]? + + featured_channel_categories = fetch_channel_featured_channels(ucid, channel.tabs["channels"], category_param, continuation, title).not_nil! + templated "channels" + end + def self.about(env) data = self.fetch_basic_information(env) if !data.is_a?(Tuple) @@ -112,6 +175,7 @@ module Invidious::Routes::Channels templated "channel_about" end # Redirects brand url channels to a normal /channel/:ucid route + def self.brand_redirect(env) locale = LOCALES[env.get("preferences").as(Preferences).locale]? diff --git a/src/invidious/views/channel_about.ecr b/src/invidious/views/channel_about.ecr index 6912244f..69e27648 100644 --- a/src/invidious/views/channel_about.ecr +++ b/src/invidious/views/channel_about.ecr @@ -3,7 +3,7 @@ <% end %> -<% content_type = 4 %> +<% content_type = 5 %> <% sort_options = Tuple.new %> <%= rendered "components/channel-information" %> diff --git a/src/invidious/views/channels.ecr b/src/invidious/views/channels.ecr new file mode 100644 index 00000000..6aeedc03 --- /dev/null +++ b/src/invidious/views/channels.ecr @@ -0,0 +1,115 @@ +<% content_for "header" do %> +
<%= item.description_html %>
+ + <% ucid = contents.ucid %> + <% author = contents.author %> + <% sub_count_text = number_to_short_text(contents.subscriber_count) %> + <%= rendered "components/subscribe_widget" %> +