mirror of
https://github.com/iv-org/invidious.git
synced 2024-10-01 01:25:56 -04:00
Improve accessibility (#3710)
This commit is contained in:
commit
961cae2b9a
@ -119,13 +119,16 @@ body a.pure-button {
|
|||||||
|
|
||||||
button.pure-button-primary,
|
button.pure-button-primary,
|
||||||
body a.pure-button-primary,
|
body a.pure-button-primary,
|
||||||
.channel-owner:hover {
|
.channel-owner:hover,
|
||||||
|
.channel-owner:focus {
|
||||||
background-color: #a0a0a0;
|
background-color: #a0a0a0;
|
||||||
color: rgba(35, 35, 35, 1);
|
color: rgba(35, 35, 35, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.pure-button-primary:hover,
|
button.pure-button-primary:hover,
|
||||||
body a.pure-button-primary:hover {
|
body a.pure-button-primary:hover,
|
||||||
|
button.pure-button-primary:focus,
|
||||||
|
body a.pure-button-primary:focus {
|
||||||
background-color: rgba(0, 182, 240, 1);
|
background-color: rgba(0, 182, 240, 1);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@ -227,6 +230,7 @@ div.watched-indicator {
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,11 +369,14 @@ span > select {
|
|||||||
|
|
||||||
.light-theme a:hover,
|
.light-theme a:hover,
|
||||||
.light-theme a:active,
|
.light-theme a:active,
|
||||||
.light-theme summary:hover {
|
.light-theme summary:hover,
|
||||||
|
.light-theme a:focus,
|
||||||
|
.light-theme summary:focus {
|
||||||
color: #075A9E !important;
|
color: #075A9E !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.light-theme a.pure-button-primary:hover {
|
.light-theme a.pure-button-primary:hover,
|
||||||
|
.light-theme a.pure-button-primary:focus {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,11 +399,14 @@ span > select {
|
|||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
.no-theme a:hover,
|
.no-theme a:hover,
|
||||||
.no-theme a:active,
|
.no-theme a:active,
|
||||||
.no-theme summary:hover {
|
.no-theme summary:hover,
|
||||||
|
.no-theme a:focus,
|
||||||
|
.no-theme summary:focus {
|
||||||
color: #075A9E !important;
|
color: #075A9E !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-theme a.pure-button-primary:hover {
|
.no-theme a.pure-button-primary:hover,
|
||||||
|
.no-theme a.pure-button-primary:focus {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +433,9 @@ span > select {
|
|||||||
|
|
||||||
.dark-theme a:hover,
|
.dark-theme a:hover,
|
||||||
.dark-theme a:active,
|
.dark-theme a:active,
|
||||||
.dark-theme summary:hover {
|
.dark-theme summary:hover,
|
||||||
|
.dark-theme a:focus,
|
||||||
|
.dark-theme summary:focus {
|
||||||
color: rgb(0, 182, 240);
|
color: rgb(0, 182, 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +474,8 @@ body.dark-theme {
|
|||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.no-theme a:hover,
|
.no-theme a:hover,
|
||||||
.no-theme a:active {
|
.no-theme a:active,
|
||||||
|
.no-theme a:focus {
|
||||||
color: rgb(0, 182, 240);
|
color: rgb(0, 182, 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.watch-on-invidious > a:hover {
|
.watch-on-invidious > a:hover,
|
||||||
|
.watch-on-invidious > a:focus {
|
||||||
color: rgba(0, 182, 240, 1);;
|
color: rgba(0, 182, 240, 1);;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
Array.prototype.find = Array.prototype.find || function (condition) {
|
Array.prototype.find = Array.prototype.find || function (condition) {
|
||||||
return this.filter(condition)[0];
|
return this.filter(condition)[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.from = Array.from || function (source) {
|
Array.from = Array.from || function (source) {
|
||||||
return Array.prototype.slice.call(source);
|
return Array.prototype.slice.call(source);
|
||||||
};
|
};
|
||||||
@ -201,15 +202,19 @@ window.helpers = window.helpers || {
|
|||||||
if (localStorageIsUsable) {
|
if (localStorageIsUsable) {
|
||||||
return {
|
return {
|
||||||
get: function (key) {
|
get: function (key) {
|
||||||
if (!localStorage[key]) return;
|
let storageItem = localStorage.getItem(key)
|
||||||
|
if (!storageItem) return;
|
||||||
try {
|
try {
|
||||||
return JSON.parse(decodeURIComponent(localStorage[key]));
|
return JSON.parse(decodeURIComponent(storageItem));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
// Erase non parsable value
|
// Erase non parsable value
|
||||||
helpers.storage.remove(key);
|
helpers.storage.remove(key);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
set: function (key, value) { localStorage[key] = encodeURIComponent(JSON.stringify(value)); },
|
set: function (key, value) {
|
||||||
|
let encoded_value = encodeURIComponent(JSON.stringify(value))
|
||||||
|
localStorage.setItem(key, encoded_value);
|
||||||
|
},
|
||||||
remove: function (key) { localStorage.removeItem(key); }
|
remove: function (key) { localStorage.removeItem(key); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@
|
|||||||
if (focused_tag === 'textarea') return;
|
if (focused_tag === 'textarea') return;
|
||||||
if (focused_tag === 'input') {
|
if (focused_tag === 'input') {
|
||||||
let focused_type = document.activeElement.type.toLowerCase();
|
let focused_type = document.activeElement.type.toLowerCase();
|
||||||
if (!focused_type.match(allowed)) return;
|
if (!allowed.test(focused_type)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus search bar on '/'
|
// Focus search bar on '/'
|
||||||
|
@ -261,7 +261,7 @@ function updateCookie(newVolume, newSpeed) {
|
|||||||
var date = new Date();
|
var date = new Date();
|
||||||
date.setFullYear(date.getFullYear() + 2);
|
date.setFullYear(date.getFullYear() + 2);
|
||||||
|
|
||||||
var ipRegex = /^((\d+\.){3}\d+|[A-Fa-f0-9]*:[A-Fa-f0-9:]*:[A-Fa-f0-9:]+)$/;
|
var ipRegex = /^((\d+\.){3}\d+|[\dA-Fa-f]*:[\d:A-Fa-f]*:[\d:A-Fa-f]+)$/;
|
||||||
var domainUsed = location.hostname;
|
var domainUsed = location.hostname;
|
||||||
|
|
||||||
// Fix for a bug in FF where the leading dot in the FQDN is not ignored
|
// Fix for a bug in FF where the leading dot in the FQDN is not ignored
|
||||||
|
@ -346,7 +346,7 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
|
|||||||
html << <<-END_HTML
|
html << <<-END_HTML
|
||||||
<div class="pure-g" style="width:100%">
|
<div class="pure-g" style="width:100%">
|
||||||
<div class="channel-profile pure-u-4-24 pure-u-md-2-24">
|
<div class="channel-profile pure-u-4-24 pure-u-md-2-24">
|
||||||
<img loading="lazy" style="margin-right:1em;margin-top:1em;width:90%" src="#{author_thumbnail}">
|
<img loading="lazy" style="margin-right:1em;margin-top:1em;width:90%" src="#{author_thumbnail}" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pure-u-20-24 pure-u-md-22-24">
|
<div class="pure-u-20-24 pure-u-md-22-24">
|
||||||
<p>
|
<p>
|
||||||
@ -367,7 +367,7 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
|
|||||||
html << <<-END_HTML
|
html << <<-END_HTML
|
||||||
<div class="pure-g">
|
<div class="pure-g">
|
||||||
<div class="pure-u-1 pure-u-md-1-2">
|
<div class="pure-u-1 pure-u-md-1-2">
|
||||||
<img loading="lazy" style="width:100%" src="/ggpht#{URI.parse(attachment["url"].as_s).request_target}">
|
<img loading="lazy" style="width:100%" src="/ggpht#{URI.parse(attachment["url"].as_s).request_target}" alt="" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
END_HTML
|
END_HTML
|
||||||
@ -428,7 +428,7 @@ def template_youtube_comments(comments, locale, thin_mode, is_replies = false)
|
|||||||
html << <<-END_HTML
|
html << <<-END_HTML
|
||||||
<span class="creator-heart-container" title="#{translate(locale, "`x` marked it with a ❤", child["creatorHeart"]["creatorName"].as_s)}">
|
<span class="creator-heart-container" title="#{translate(locale, "`x` marked it with a ❤", child["creatorHeart"]["creatorName"].as_s)}">
|
||||||
<div class="creator-heart">
|
<div class="creator-heart">
|
||||||
<img loading="lazy" class="creator-heart-background-hearted" src="#{creator_thumbnail}"></img>
|
<img loading="lazy" class="creator-heart-background-hearted" src="#{creator_thumbnail}" alt="" />
|
||||||
<div class="creator-heart-small-hearted">
|
<div class="creator-heart-small-hearted">
|
||||||
<div class="icon ion-ios-heart creator-heart-small-container"></div>
|
<div class="icon ion-ios-heart creator-heart-small-container"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -702,7 +702,7 @@ def content_to_comment_html(content, video_id : String? = "")
|
|||||||
str << %(title=") << emojiAlt << "\" "
|
str << %(title=") << emojiAlt << "\" "
|
||||||
str << %(width=") << emojiThumb["width"] << "\" "
|
str << %(width=") << emojiThumb["width"] << "\" "
|
||||||
str << %(height=") << emojiThumb["height"] << "\" "
|
str << %(height=") << emojiThumb["height"] << "\" "
|
||||||
str << %(class="channel-emoji"/>)
|
str << %(class="channel-emoji" />)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Hide deleted channel emoji
|
# Hide deleted channel emoji
|
||||||
|
@ -97,7 +97,7 @@ def template_mix(mix)
|
|||||||
<li class="pure-menu-item">
|
<li class="pure-menu-item">
|
||||||
<a href="/watch?v=#{video["videoId"]}&list=#{mix["mixId"]}">
|
<a href="/watch?v=#{video["videoId"]}&list=#{mix["mixId"]}">
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img loading="lazy" class="thumbnail" src="/vi/#{video["videoId"]}/mqdefault.jpg">
|
<img loading="lazy" class="thumbnail" src="/vi/#{video["videoId"]}/mqdefault.jpg" alt="" />
|
||||||
<p class="length">#{recode_length_seconds(video["lengthSeconds"].as_i)}</p>
|
<p class="length">#{recode_length_seconds(video["lengthSeconds"].as_i)}</p>
|
||||||
</div>
|
</div>
|
||||||
<p style="width:100%">#{video["title"]}</p>
|
<p style="width:100%">#{video["title"]}</p>
|
||||||
|
@ -507,7 +507,7 @@ def template_playlist(playlist)
|
|||||||
<li class="pure-menu-item" id="#{video["videoId"]}">
|
<li class="pure-menu-item" id="#{video["videoId"]}">
|
||||||
<a href="/watch?v=#{video["videoId"]}&list=#{playlist["playlistId"]}&index=#{video["index"]}">
|
<a href="/watch?v=#{video["videoId"]}&list=#{playlist["playlistId"]}&index=#{video["index"]}">
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img loading="lazy" class="thumbnail" src="/vi/#{video["videoId"]}/mqdefault.jpg">
|
<img loading="lazy" class="thumbnail" src="/vi/#{video["videoId"]}/mqdefault.jpg" alt="" />
|
||||||
<p class="length">#{recode_length_seconds(video["lengthSeconds"].as_i)}</p>
|
<p class="length">#{recode_length_seconds(video["lengthSeconds"].as_i)}</p>
|
||||||
</div>
|
</div>
|
||||||
<p style="width:100%">#{video["title"]}</p>
|
<p style="width:100%">#{video["title"]}</p>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<% if channel.banner %>
|
<% if channel.banner %>
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<img style="width:100%" src="/ggpht<%= URI.parse(channel.banner.not_nil!.gsub("=w1060-", "=w1280-")).request_target %>">
|
<img style="width:100%" src="/ggpht<%= URI.parse(channel.banner.not_nil!.gsub("=w1060-", "=w1280-")).request_target %>" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<div class="pure-g h-box">
|
<div class="pure-g h-box">
|
||||||
<div class="pure-u-2-3">
|
<div class="pure-u-2-3">
|
||||||
<div class="channel-profile">
|
<div class="channel-profile">
|
||||||
<img src="/ggpht<%= channel_profile_pic %>">
|
<img src="/ggpht<%= channel_profile_pic %>" alt="" />
|
||||||
<span><%= author %></span><% if !channel.verified.nil? && channel.verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %>
|
<span><%= author %></span><% if !channel.verified.nil? && channel.verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<a href="/channel/<%= item.ucid %>">
|
<a href="/channel/<%= item.ucid %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<center>
|
<center>
|
||||||
<img loading="lazy" tabindex="-1" style="width:56.25%" src="/ggpht<%= URI.parse(item.author_thumbnail).request_target.gsub(/=s\d+/, "=s176") %>"/>
|
<img loading="lazy" tabindex="-1" style="width:56.25%" src="/ggpht<%= URI.parse(item.author_thumbnail).request_target.gsub(/=s\d+/, "=s176") %>" alt="" />
|
||||||
</center>
|
</center>
|
||||||
<% end %>
|
<% end %>
|
||||||
<p dir="auto"><%= HTML.escape(item.author) %><% if !item.author_verified.nil? && item.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></p>
|
<p dir="auto"><%= HTML.escape(item.author) %><% if !item.author_verified.nil? && item.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></p>
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<a style="width:100%" href="<%= url %>">
|
<a style="width:100%" href="<%= url %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img loading="lazy" tabindex="-1" class="thumbnail" src="<%= URI.parse(item.thumbnail || "/").request_target %>"/>
|
<img loading="lazy" tabindex="-1" class="thumbnail" src="<%= URI.parse(item.thumbnail || "/").request_target %>" alt="" />
|
||||||
<p class="length"><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %></p>
|
<p class="length"><%= translate_count(locale, "generic_videos_count", item.video_count, NumberFormatting::Separator) %></p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -38,7 +38,7 @@
|
|||||||
<a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>">
|
<a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
<img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
|
||||||
<% if item.length_seconds != 0 %>
|
<% if item.length_seconds != 0 %>
|
||||||
<p class="length"><%= recode_length_seconds(item.length_seconds) %></p>
|
<p class="length"><%= recode_length_seconds(item.length_seconds) %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -58,7 +58,7 @@
|
|||||||
<a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.plid %>&index=<%= item.index %>">
|
<a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.plid %>&index=<%= item.index %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
<img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
|
||||||
|
|
||||||
<% if plid_form = env.get?("remove_playlist_items") %>
|
<% if plid_form = env.get?("remove_playlist_items") %>
|
||||||
<form data-onsubmit="return_false" action="/playlist_ajax?action_remove_video=1&set_video_id=<%= item.index %>&playlist_id=<%= plid_form %>&referer=<%= env.get("current_page") %>" method="post">
|
<form data-onsubmit="return_false" action="/playlist_ajax?action_remove_video=1&set_video_id=<%= item.index %>&playlist_id=<%= plid_form %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
@ -112,7 +112,7 @@
|
|||||||
<a style="width:100%" href="/watch?v=<%= item.id %>">
|
<a style="width:100%" href="/watch?v=<%= item.id %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
<img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
|
||||||
<% if env.get? "show_watched" %>
|
<% if env.get? "show_watched" %>
|
||||||
<form data-onsubmit="return_false" action="/watch_ajax?action_mark_watched=1&id=<%= item.id %>&referer=<%= env.get("current_page") %>" method="post">
|
<form data-onsubmit="return_false" action="/watch_ajax?action_mark_watched=1&id=<%= item.id %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<a style="width:100%" href="/watch?v=<%= item %>">
|
<a style="width:100%" href="/watch?v=<%= item %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/>
|
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg" alt="" />
|
||||||
<form data-onsubmit="return_false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
|
<form data-onsubmit="return_false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<p class="watched">
|
<p class="watched">
|
||||||
|
@ -208,7 +208,7 @@ we're going to need to do it here in order to allow for translations.
|
|||||||
<a href="/channel/<%= video.ucid %>" style="display:block;width:fit-content;width:-moz-fit-content">
|
<a href="/channel/<%= video.ucid %>" style="display:block;width:fit-content;width:-moz-fit-content">
|
||||||
<div class="channel-profile">
|
<div class="channel-profile">
|
||||||
<% if !video.author_thumbnail.empty? %>
|
<% if !video.author_thumbnail.empty? %>
|
||||||
<img src="/ggpht<%= URI.parse(video.author_thumbnail).request_target %>">
|
<img src="/ggpht<%= URI.parse(video.author_thumbnail).request_target %>" alt="" />
|
||||||
<% end %>
|
<% end %>
|
||||||
<span id="channel-name"><%= author %><% if !video.author_verified.nil? && video.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></span>
|
<span id="channel-name"><%= author %><% if !video.author_verified.nil? && video.author_verified %> <i class="icon ion ion-md-checkmark-circle"></i><% end %></span>
|
||||||
</div>
|
</div>
|
||||||
@ -298,7 +298,7 @@ we're going to need to do it here in order to allow for translations.
|
|||||||
<a href="/watch?v=<%= rv["id"] %>&listen=<%= params.listen %>">
|
<a href="/watch?v=<%= rv["id"] %>&listen=<%= params.listen %>">
|
||||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img loading="lazy" class="thumbnail" src="/vi/<%= rv["id"] %>/mqdefault.jpg">
|
<img loading="lazy" class="thumbnail" src="/vi/<%= rv["id"] %>/mqdefault.jpg" alt="" />
|
||||||
<p class="length"><%= recode_length_seconds(rv["length_seconds"]?.try &.to_i? || 0) %></p>
|
<p class="length"><%= recode_length_seconds(rv["length_seconds"]?.try &.to_i? || 0) %></p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
Loading…
Reference in New Issue
Block a user