summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamantaz Fox <coding@samantaz.fr>2023-04-22 12:58:46 +0200
committerSamantaz Fox <coding@samantaz.fr>2023-07-06 00:58:32 +0200
commitb6bbfb9b200fc920854ce91835026da0fd6552db (patch)
tree33d838ffcc9e08cc531087b988970daedfe56dde /src
parent7bd6d0ac4961e7f2433eb3268a45b78642229896 (diff)
downloadinvidious-b6bbfb9b200fc920854ce91835026da0fd6552db.tar.gz
invidious-b6bbfb9b200fc920854ce91835026da0fd6552db.tar.bz2
invidious-b6bbfb9b200fc920854ce91835026da0fd6552db.zip
HTML: Use new buttons for thumbnail overlays
In addition, this commit also heavily changes the structure of the generic "video card" item. Main benefits: * Improved accessibility for keyboard users * Many styling glitches were fixed * PlaylistVideos now use the same items as the rest * Elements all have distinct CSS classes * Design can be expanded to add more icons
Diffstat (limited to 'src')
-rw-r--r--src/invidious/views/components/item.ecr149
-rw-r--r--src/invidious/views/feeds/history.ecr8
2 files changed, 67 insertions, 90 deletions
diff --git a/src/invidious/views/components/item.ecr b/src/invidious/views/components/item.ecr
index 7cfd38db..f05e1338 100644
--- a/src/invidious/views/components/item.ecr
+++ b/src/invidious/views/components/item.ecr
@@ -7,7 +7,7 @@
<a href="/channel/<%= item.ucid %>">
<% if !env.get("preferences").as(Preferences).thin_mode %>
<center>
- <img loading="lazy" tabindex="-1" style="width:56.25%" src="/ggpht<%= URI.parse(item.author_thumbnail).request_target.gsub(/=s\d+/, "=s176") %>" alt="" />
+ <img loading="lazy" style="width:56.25%" src="/ggpht<%= URI.parse(item.author_thumbnail).request_target.gsub(/=s\d+/, "=s176") %>" alt="" />
</center>
<% 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>
@@ -25,7 +25,7 @@
<a style="width:100%" href="<%= url %>">
<% if !env.get("preferences").as(Preferences).thin_mode %>
<div class="thumbnail">
- <img loading="lazy" tabindex="-1" class="thumbnail" src="<%= URI.parse(item.thumbnail || "/").request_target %>" alt="" />
+ <img loading="lazy" 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>
</div>
<% end %>
@@ -38,7 +38,7 @@
<a href="/watch?v=<%= item.id %>&list=<%= item.rdid %>">
<% if !env.get("preferences").as(Preferences).thin_mode %>
<div class="thumbnail">
- <img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
+ <img loading="lazy" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
<% if item.length_seconds != 0 %>
<p class="length"><%= recode_length_seconds(item.length_seconds) %></p>
<% end %>
@@ -54,104 +54,79 @@
<a href="/channel/<%= item.ucid %>">
<p dir="auto"><b><%= HTML.escape(item.author) %></b></p>
</a>
- <% when PlaylistVideo %>
- <a style="width:100%" href="/watch?v=<%= item.id %>&list=<%= item.plid %>&index=<%= item.index %>">
- <% if !env.get("preferences").as(Preferences).thin_mode %>
- <div class="thumbnail">
- <img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
-
- <% 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">
- <input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
- <p class="watched">
- <button type="submit" style="all:unset" data-onclick="remove_playlist_item" data-index="<%= item.index %>" data-plid="<%= plid_form %>"><i class="icon ion-md-trash"></i></button>
- </p>
- </form>
- <% end %>
-
- <% if item.responds_to?(:live_now) && item.live_now %>
- <p class="length"><i class="icon ion-ios-play-circle"></i> <%= translate(locale, "LIVE") %></p>
- <% elsif item.length_seconds != 0 %>
- <p class="length"><%= recode_length_seconds(item.length_seconds) %></p>
- <% end %>
+ <% when Category %>
+ <% else %>
+ <%-
+ # `endpoint_params` is used for the "video-context-buttons" component
+ if item.is_a?(PlaylistVideo)
+ link_url = "/watch?v=#{item.id}&list=#{item.plid}&index=#{item.index}"
+ endpoint_params = "?v=#{item.id}&list=#{item.plid}"
+ else
+ link_url = "/watch?v=#{item.id}"
+ endpoint_params = "?v=#{item.id}"
+ end
+ -%>
- <% if item_watched %>
- <div class="watched-overlay"></div>
- <div class="watched-indicator" data-length="<%= item.length_seconds %>" data-id="<%= item.id %>"></div>
- <% end %>
- </div>
- <% end %>
- <p dir="auto"><%= HTML.escape(item.title) %></p>
- </a>
+ <div class="thumbnail">
+ <%- if !env.get("preferences").as(Preferences).thin_mode -%>
+ <a tabindex="-1" href="<%= link_url %>">
+ <img loading="lazy" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
+ </a>
+ <%- end -%>
- <div class="video-card-row flexible">
- <div class="flex-left"><a href="/channel/<%= item.ucid %>">
- <p class="channel-name" dir="auto"><%= HTML.escape(item.author) %></p>
- </a></div>
- <% endpoint_params = "?v=#{item.id}&list=#{item.plid}" %>
- <%= rendered "components/video-context-buttons" %>
- </div>
+ <div class="top-left-overlay">
+ <%- 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">
+ <input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
+ <button type="submit" class="pure-button pure-button-secondary low-profile"
+ data-onclick="mark_watched" data-id="<%= item.id %>">
+ <i data-mouse="switch_classes" data-switch-classes="ion-ios-eye-off,ion-ios-eye" class="icon ion-ios-eye"></i>
+ </button>
+ </form>
+ <%- end -%>
- <div class="video-card-row flexible">
- <div class="flex-left">
- <% if item.responds_to?(:premiere_timestamp) && item.premiere_timestamp.try &.> Time.utc %>
- <p dir="auto"><%= translate(locale, "Premieres in `x`", recode_date((item.premiere_timestamp.as(Time) - Time.utc).ago, locale)) %></p>
- <% elsif Time.utc - item.published > 1.minute %>
- <p dir="auto"><%= translate(locale, "Shared `x` ago", recode_date(item.published, locale)) %></p>
- <% end %>
+ <%- if plid_form = env.get?("add_playlist_items") -%>
+ <%- form_parameters = "action_add_video=1&video_id=#{item.id}&playlist_id=#{plid_form}&referer=#{env.get("current_page")}" -%>
+ <form data-onsubmit="return_false" action="/playlist_ajax?<%= form_parameters %>" method="post">
+ <input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
+ <button type="submit" class="pure-button pure-button-secondary low-profile"
+ data-onclick="add_playlist_item" data-id="<%= item.id %>" data-plid="<%= plid_form %>"><i class="icon ion-md-add"></i></button>
+ </form>
+ <%- elsif item.is_a?(PlaylistVideo) && (plid_form = env.get?("remove_playlist_items")) -%>
+ <%- form_parameters = "action_remove_video=1&set_video_id=#{item.index}&playlist_id=#{plid_form}&referer=#{env.get("current_page")}" -%>
+ <form data-onsubmit="return_false" action="/playlist_ajax?<%= form_parameters %>" method="post">
+ <input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
+ <button type="submit" class="pure-button pure-button-secondary low-profile"
+ data-onclick="remove_playlist_item" data-index="<%= item.index %>" data-plid="<%= plid_form %>"><i class="icon ion-md-trash"></i></button>
+ </form>
+ <%- end -%>
</div>
- <% if item.responds_to?(:views) && item.views %>
- <div class="flex-right">
- <p dir="auto"><%= translate_count(locale, "generic_views_count", item.views || 0, NumberFormatting::Short) %></p>
+ <div class="bottom-right-overlay">
+ <%- if item.responds_to?(:live_now) && item.live_now -%>
+ <p class="length" dir="auto"><i class="icon ion-ios-play-circle"></i>&nbsp;<%= translate(locale, "LIVE") %></p>
+ <%- elsif item.length_seconds != 0 -%>
+ <p class="length"><%= recode_length_seconds(item.length_seconds) %></p>
+ <%- end -%>
</div>
+
+ <% if item_watched %>
+ <div class="watched-overlay"></div>
+ <div class="watched-indicator" data-length="<%= item.length_seconds %>" data-id="<%= item.id %>"></div>
<% end %>
</div>
- <% when Category %>
- <% else %>
- <a style="width:100%" href="/watch?v=<%= item.id %>">
- <% if !env.get("preferences").as(Preferences).thin_mode %>
- <div class="thumbnail">
- <img loading="lazy" tabindex="-1" class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg" alt="" />
- <% 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">
- <input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
- <p class="watched">
- <button type="submit" style="all:unset" data-onclick="mark_watched" data-id="<%= item.id %>">
- <i data-mouse="switch_classes" data-switch-classes="ion-ios-eye-off,ion-ios-eye" class="icon ion-ios-eye"></i>
- </button>
- </p>
- </form>
- <% elsif plid_form = env.get? "add_playlist_items" %>
- <form data-onsubmit="return_false" action="/playlist_ajax?action_add_video=1&video_id=<%= item.id %>&playlist_id=<%= plid_form %>&referer=<%= env.get("current_page") %>" method="post">
- <input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
- <p class="watched">
- <button type="submit" style="all:unset" data-onclick="add_playlist_item" data-id="<%= item.id %>" data-plid="<%= plid_form %>"><i class="icon ion-md-add"></i></button>
- </p>
- </form>
- <% end %>
- <% if item.responds_to?(:live_now) && item.live_now %>
- <p class="length" dir="auto"><i class="icon ion-ios-play-circle"></i> <%= translate(locale, "LIVE") %></p>
- <% elsif item.length_seconds != 0 %>
- <p class="length"><%= recode_length_seconds(item.length_seconds) %></p>
- <% end %>
-
- <% if item_watched %>
- <div class="watched-overlay"></div>
- <div class="watched-indicator" data-length="<%= item.length_seconds %>" data-id="<%= item.id %>"></div>
- <% end %>
- </div>
- <% end %>
- <p dir="auto"><%= HTML.escape(item.title) %></p>
- </a>
+ <div class="video-card-row">
+ <a href="<%= link_url %>"><p dir="auto"><%= HTML.escape(item.title) %></p></a>
+ </div>
<div class="video-card-row flexible">
<div class="flex-left"><a href="/channel/<%= item.ucid %>">
- <p class="channel-name" dir="auto"><%= HTML.escape(item.author) %><% if !item.is_a?(ChannelVideo) && !item.author_verified.nil? && item.author_verified %>&nbsp;<i class="icon ion ion-md-checkmark-circle"></i><% end %></p>
+ <p class="channel-name" dir="auto"><%= HTML.escape(item.author) %>
+ <%- if item.responds_to?(:author_verified) && item.author_verified %>&nbsp;<i class="icon ion ion-md-checkmark-circle"></i><% end -%>
+ </p>
</a></div>
- <% endpoint_params = "?v=#{item.id}" %>
<%= rendered "components/video-context-buttons" %>
</div>
diff --git a/src/invidious/views/feeds/history.ecr b/src/invidious/views/feeds/history.ecr
index 2234b297..5301a232 100644
--- a/src/invidious/views/feeds/history.ecr
+++ b/src/invidious/views/feeds/history.ecr
@@ -35,12 +35,14 @@
<% if !env.get("preferences").as(Preferences).thin_mode %>
<div class="thumbnail">
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg" alt="" />
+
+ <div class="top-left-overlay"><div class="watched">
<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) || "") %>">
- <p class="watched">
- <button type="submit" style="all:unset" data-onclick="mark_unwatched" data-id="<%= item %>"><i class="icon ion-md-trash"></i></button>
- </p>
+ <button type="submit" class="pure-button pure-button-secondary low-profile"
+ data-onclick="mark_unwatched" data-id="<%= item %>"><i class="icon ion-md-trash"></i></button>
</form>
+ </div></div>
</div>
<p></p>
<% end %>