Improve accessibility (#3710)

This commit is contained in:
Samantaz Fox 2023-04-10 17:55:24 +02:00
commit 961cae2b9a
No known key found for this signature in database
GPG key ID: F42821059186176E
12 changed files with 49 additions and 30 deletions

View file

@ -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);
} }

View file

@ -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);;
} }

View file

@ -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); }
}; };
} }

View file

@ -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 '/'

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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 %>&nbsp;<i class="icon ion ion-md-checkmark-circle"></i><% end %> <span><%= author %></span><% if !channel.verified.nil? && channel.verified %>&nbsp;<i class="icon ion ion-md-checkmark-circle"></i><% end %>
</div> </div>
</div> </div>

View file

@ -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 %>&nbsp;<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 %>&nbsp;<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) || "") %>">

View file

@ -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">

View file

@ -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 %>&nbsp;<i class="icon ion ion-md-checkmark-circle"></i><% end %></span> <span id="channel-name"><%= author %><% if !video.author_verified.nil? && video.author_verified %>&nbsp;<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 %>