mirror of
https://git.nadeko.net/Fijxu/invidious.git
synced 2025-12-19 11:28:51 +00:00
Merge branch 'master' into patch-1
This commit is contained in:
@@ -20,12 +20,14 @@
|
||||
<div class="pure-u-1 pure-u-lg-1-5"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var playlist_data = {
|
||||
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||
}
|
||||
<script id="playlist_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"csrf_token" => URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "")
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/playlist_widget.js"></script>
|
||||
<script src="/js/playlist_widget.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
|
||||
<div class="pure-g">
|
||||
<% videos.each_slice(4) do |slice| %>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</div>
|
||||
|
||||
<div class="h-box">
|
||||
<p><span style="white-space:pre-wrap"><%= XML.parse_html(channel.description_html).xpath_node(%q(.//pre)).try &.content %></span></p>
|
||||
<p><span style="white-space:pre-wrap"><%= channel.description_html %></span></p>
|
||||
</div>
|
||||
|
||||
<div class="h-box">
|
||||
@@ -92,7 +92,7 @@
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-1 pure-u-lg-1-5">
|
||||
<% if page > 1 %>
|
||||
<a href="/channel/<%= channel.ucid %>?page=<%= page - 1 %><% if sort_by != "newest" %>&sort_by=<%= sort_by %><% end %>">
|
||||
<a href="/channel/<%= channel.ucid %>?page=<%= page - 1 %><% if sort_by != "newest" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>">
|
||||
<%= translate(locale, "Previous page") %>
|
||||
</a>
|
||||
<% end %>
|
||||
@@ -100,7 +100,7 @@
|
||||
<div class="pure-u-1 pure-u-lg-3-5"></div>
|
||||
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
|
||||
<% if count == 60 %>
|
||||
<a href="/channel/<%= channel.ucid %>?page=<%= page + 1 %><% if sort_by != "newest" %>&sort_by=<%= sort_by %><% end %>">
|
||||
<a href="/channel/<%= channel.ucid %>?page=<%= page + 1 %><% if sort_by != "newest" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>">
|
||||
<%= translate(locale, "Next page") %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
@@ -71,14 +71,16 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
var community_data = {
|
||||
ucid: '<%= channel.ucid %>',
|
||||
youtube_comments_text: '<%= HTML.escape(translate(locale, "View YouTube comments")) %>',
|
||||
comments_text: '<%= HTML.escape(translate(locale, "View `x` comments", "{commentCount}")) %>',
|
||||
hide_replies_text: '<%= HTML.escape(translate(locale, "Hide replies")) %>',
|
||||
show_replies_text: '<%= HTML.escape(translate(locale, "Show replies")) %>',
|
||||
preferences: <%= env.get("preferences").as(Preferences).to_json %>,
|
||||
}
|
||||
<script id="community_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"ucid" => channel.ucid,
|
||||
"youtube_comments_text" => HTML.escape(translate(locale, "View YouTube comments")),
|
||||
"comments_text" => HTML.escape(translate(locale, "View `x` comments", "{commentCount}")),
|
||||
"hide_replies_text" => HTML.escape(translate(locale, "Hide replies")),
|
||||
"show_replies_text" => HTML.escape(translate(locale, "Show replies")),
|
||||
"preferences" => env.get("preferences").as(Preferences)
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/community.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
<div class="h-box pure-g">
|
||||
<div class="pure-u-1 pure-u-md-1-4"></div>
|
||||
<div class="pure-u-1 pure-u-md-1-2">
|
||||
<div class="pure-g">
|
||||
<% feed_menu = env.get("preferences").as(Preferences).feed_menu.dup %>
|
||||
<% if !env.get?("user") %>
|
||||
<% feed_menu.reject! {|item| {"Subscriptions", "Playlists"}.includes? item} %>
|
||||
<% end %>
|
||||
<% feed_menu.each do |feed| %>
|
||||
<div class="pure-u-1-2 pure-u-md-1-<%= feed_menu.size %>">
|
||||
<a href="/feed/<%= feed.downcase %>" class="pure-menu-heading" style="text-align:center">
|
||||
<%= translate(locale, feed) %>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-4"></div>
|
||||
<div class="feed-menu">
|
||||
<% feed_menu = env.get("preferences").as(Preferences).feed_menu.dup %>
|
||||
<% if !env.get?("user") %>
|
||||
<% feed_menu.reject! {|item| {"Subscriptions", "Playlists"}.includes? item} %>
|
||||
<% end %>
|
||||
<% feed_menu.each do |feed| %>
|
||||
<a href="/feed/<%= feed.downcase %>" class="feed-menu-item pure-menu-heading">
|
||||
<%= translate(locale, feed) %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<p><%= item.title %></p>
|
||||
<p><%= HTML.escape(item.title) %></p>
|
||||
</a>
|
||||
<p>
|
||||
<b>
|
||||
@@ -57,10 +57,10 @@
|
||||
<div class="thumbnail">
|
||||
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
||||
<% if plid = env.get?("remove_playlist_items") %>
|
||||
<form onsubmit="return false" action="/playlist_ajax?action_remove_video=1&set_video_id=<%= item.index %>&playlist_id=<%= plid %>&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 %>&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">
|
||||
<a onclick="remove_playlist_item(this)" data-index="<%= item.index %>" data-plid="<%= plid %>" href="javascript:void(0)">
|
||||
<a data-onclick="remove_playlist_item" data-index="<%= item.index %>" data-plid="<%= plid %>" href="javascript:void(0)">
|
||||
<button type="submit" style="all:unset">
|
||||
<i class="icon ion-md-trash"></i>
|
||||
</button>
|
||||
@@ -76,7 +76,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<p><a href="/watch?v=<%= item.id %>"><%= item.title %></a></p>
|
||||
<p><a href="/watch?v=<%= item.id %>"><%= HTML.escape(item.title) %></a></p>
|
||||
</a>
|
||||
<p>
|
||||
<b>
|
||||
@@ -85,7 +85,7 @@
|
||||
</p>
|
||||
|
||||
<h5 class="pure-g">
|
||||
<% if item.responds_to?(:premiere_timestamp) && item.premiere_timestamp && item.premiere_timestamp.not_nil! > Time.utc %>
|
||||
<% if item.responds_to?(:premiere_timestamp) && item.premiere_timestamp.try &.> Time.utc %>
|
||||
<div class="pure-u-2-3"><%= translate(locale, "Premieres in `x`", recode_date((item.premiere_timestamp.as(Time) - Time.utc).ago, locale)) %></div>
|
||||
<% elsif Time.utc - item.published > 1.minute %>
|
||||
<div class="pure-u-2-3"><%= translate(locale, "Shared `x` ago", recode_date(item.published, locale)) %></div>
|
||||
@@ -103,13 +103,12 @@
|
||||
<div class="thumbnail">
|
||||
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
|
||||
<% if env.get? "show_watched" %>
|
||||
<form 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="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||
<p class="watched">
|
||||
<a onclick="mark_watched(this)" data-id="<%= item.id %>" href="javascript:void(0)">
|
||||
<a data-onclick="mark_watched" data-id="<%= item.id %>" href="javascript:void(0)">
|
||||
<button type="submit" style="all:unset">
|
||||
<i onmouseenter='this.setAttribute("class", "icon ion-ios-eye-off")'
|
||||
onmouseleave='this.setAttribute("class", "icon ion-ios-eye")'
|
||||
<i data-mouse="switch_classes" data-switch-classes="ion-ios-eye-off,ion-ios-eye"
|
||||
class="icon ion-ios-eye">
|
||||
</i>
|
||||
</button>
|
||||
@@ -117,10 +116,10 @@
|
||||
</p>
|
||||
</form>
|
||||
<% elsif plid = env.get? "add_playlist_items" %>
|
||||
<form onsubmit="return false" action="/playlist_ajax?action_add_video=1&video_id=<%= item.id %>&playlist_id=<%= plid %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<form data-onsubmit="return_false" action="/playlist_ajax?action_add_video=1&video_id=<%= item.id %>&playlist_id=<%= plid %>&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">
|
||||
<a onclick="add_playlist_item(this)" data-id="<%= item.id %>" data-plid="<%= plid %>" href="javascript:void(0)">
|
||||
<a data-onclick="add_playlist_item" data-id="<%= item.id %>" data-plid="<%= plid %>" href="javascript:void(0)">
|
||||
<button type="submit" style="all:unset">
|
||||
<i class="icon ion-md-add"></i>
|
||||
</button>
|
||||
@@ -137,7 +136,7 @@
|
||||
</div>
|
||||
</a>
|
||||
<% end %>
|
||||
<p><a href="/watch?v=<%= item.id %>"><%= item.title %></a></p>
|
||||
<p><a href="/watch?v=<%= item.id %>"><%= HTML.escape(item.title) %></a></p>
|
||||
<p style="display: flex;">
|
||||
<b style="flex: 1;">
|
||||
<a style="width:100%" href="/channel/<%= item.ucid %>"><%= item.author %></a>
|
||||
@@ -148,7 +147,7 @@
|
||||
</p>
|
||||
|
||||
<h5 class="pure-g">
|
||||
<% if item.responds_to?(:premiere_timestamp) && item.premiere_timestamp && item.premiere_timestamp.not_nil! > Time.utc %>
|
||||
<% if item.responds_to?(:premiere_timestamp) && item.premiere_timestamp.try &.> Time.utc %>
|
||||
<div class="pure-u-2-3"><%= translate(locale, "Premieres in `x`", recode_date((item.premiere_timestamp.as(Time) - Time.utc).ago, locale)) %></div>
|
||||
<% elsif Time.utc - item.published > 1.minute %>
|
||||
<div class="pure-u-2-3"><%= translate(locale, "Shared `x` ago", recode_date(item.published, locale)) %></div>
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
<video style="outline:none;width:100%;background-color:#000" playsinline poster="<%= thumbnail %>" title="<%= HTML.escape(video.title) %>"
|
||||
id="player" class="video-js player-style-<%= params.player_style %>"
|
||||
onmouseenter='this["data-title"]=this["title"];this["title"]=""'
|
||||
onmouseleave='this["title"]=this["data-title"];this["data-title"]=""'
|
||||
oncontextmenu='this["title"]=this["data-title"]'
|
||||
<video style="outline:none;width:100%;background-color:#000" playsinline poster="<%= thumbnail %>"
|
||||
id="player" class="on-video_player video-js player-style-<%= params.player_style %>"
|
||||
<% if params.autoplay %>autoplay<% end %>
|
||||
<% if params.video_loop %>loop<% end %>
|
||||
<% if params.controls %>controls<% end %>>
|
||||
<% if hlsvp && !CONFIG.disabled?("livestreams") %>
|
||||
<source src="<%= hlsvp %>?local=true" type="application/x-mpegURL" label="livestream">
|
||||
<% if (hlsvp = video.hls_manifest_url) && !CONFIG.disabled?("livestreams") %>
|
||||
<source src="<%= URI.parse(hlsvp).full_path %>?local=true" type="application/x-mpegURL" label="livestream">
|
||||
<% else %>
|
||||
<% if params.listen %>
|
||||
<% audio_streams.each_with_index do |fmt, i| %>
|
||||
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["type"] %>' label="<%= fmt["bitrate"] %>k" selected="<%= i == 0 ? true : false %>">
|
||||
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["bitrate"] %>k" selected="<%= i == 0 ? true : false %>">
|
||||
<% end %>
|
||||
<% else %>
|
||||
<% if params.quality == "dash" %>
|
||||
<source src="/api/manifest/dash/id/<%= video.id %>?local=true" type='application/dash+xml' label="dash">
|
||||
<source src="/api/manifest/dash/id/<%= video.id %>?local=true&unique_res=1" type='application/dash+xml' label="dash">
|
||||
<% end %>
|
||||
|
||||
<% fmt_stream.each_with_index do |fmt, i| %>
|
||||
<% if params.quality %>
|
||||
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["type"] %>' label="<%= fmt["label"] %>" selected="<%= params.quality == fmt["label"].split(" - ")[0] %>">
|
||||
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["quality"] %>" selected="<%= params.quality == fmt["quality"] %>">
|
||||
<% else %>
|
||||
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["type"] %>' label="<%= fmt["label"] %>" selected="<%= i == 0 ? true : false %>">
|
||||
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["quality"] %>" selected="<%= i == 0 ? true : false %>">
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -39,12 +36,14 @@
|
||||
<% end %>
|
||||
</video>
|
||||
|
||||
<script>
|
||||
var player_data = {
|
||||
aspect_ratio: '<%= aspect_ratio %>',
|
||||
title: "<%= video.title.dump_unquoted %>",
|
||||
description: "<%= HTML.escape(video.short_description) %>",
|
||||
thumbnail: "<%= thumbnail %>"
|
||||
}
|
||||
<script id="player_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"aspect_ratio" => aspect_ratio,
|
||||
"title" => video.title,
|
||||
"description" => HTML.escape(video.short_description),
|
||||
"thumbnail" => thumbnail
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/player.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<link rel="stylesheet" href="/css/videojs.markers.min.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/videojs-share.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/videojs-vtt-thumbnails.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/videojs-vtt-thumbnails-fix.css?v=<%= ASSET_COMMIT %>">
|
||||
<script src="/js/global.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<script src="/js/video.min.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<script src="/js/videojs-contrib-quality-levels.min.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<script src="/js/videojs-http-source-selector.min.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
|
||||
@@ -19,15 +19,17 @@
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
var subscribe_data = {
|
||||
ucid: '<%= ucid %>',
|
||||
author: '<%= HTML.escape(author) %>',
|
||||
sub_count_text: '<%= HTML.escape(sub_count_text) %>',
|
||||
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||
subscribe_text: '<%= HTML.escape(translate(locale, "Subscribe")) %>',
|
||||
unsubscribe_text: '<%= HTML.escape(translate(locale, "Unsubscribe")) %>'
|
||||
}
|
||||
<script id="subscribe_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"ucid" => ucid,
|
||||
"author" => HTML.escape(author),
|
||||
"sub_count_text" => HTML.escape(sub_count_text),
|
||||
"csrf_token" => URI.encode_www_form(env.get?("csrf_token").try &.as(String) || ""),
|
||||
"subscribe_text" => HTML.escape(translate(locale, "Subscribe")),
|
||||
"unsubscribe_text" => HTML.escape(translate(locale, "Unsubscribe"))
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/subscribe_widget.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<% else %>
|
||||
|
||||
@@ -10,33 +10,24 @@
|
||||
<script src="/js/videojs-overlay.min.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<link rel="stylesheet" href="/css/default.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/darktheme.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/embed.css?v=<%= ASSET_COMMIT %>">
|
||||
<title><%= HTML.escape(video.title) %> - Invidious</title>
|
||||
<style>
|
||||
#player {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
z-index: -100;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
var video_data = {
|
||||
id: '<%= video.id %>',
|
||||
index: '<%= continuation %>',
|
||||
plid: '<%= plid %>',
|
||||
length_seconds: '<%= video.length_seconds.to_f %>',
|
||||
video_series: <%= video_series.to_json %>,
|
||||
params: <%= params.to_json %>,
|
||||
preferences: <%= preferences.to_json %>,
|
||||
premiere_timestamp: <%= video.premiere_timestamp.try &.to_unix || "null" %>
|
||||
}
|
||||
<script id="video_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"id" => video.id,
|
||||
"index" => continuation,
|
||||
"plid" => plid,
|
||||
"length_seconds" => video.length_seconds.to_f,
|
||||
"video_series" => video_series,
|
||||
"params" => params,
|
||||
"preferences" => preferences,
|
||||
"premiere_timestamp" => video.premiere_timestamp.try &.to_unix
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
|
||||
<%= rendered "components/player" %>
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var watched_data = {
|
||||
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||
}
|
||||
<script id="watched_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"csrf_token" => URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "")
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/watched_widget.js"></script>
|
||||
|
||||
@@ -34,10 +36,10 @@ var watched_data = {
|
||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||
<div class="thumbnail">
|
||||
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/>
|
||||
<form 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) || "") %>">
|
||||
<p class="watched">
|
||||
<a onclick="mark_unwatched(this)" data-id="<%= item %>" href="javascript:void(0)">
|
||||
<a data-onclick="mark_unwatched" data-id="<%= item %>" href="javascript:void(0)">
|
||||
<button type="submit" style="all:unset">
|
||||
<i class="icon ion-md-trash"></i>
|
||||
</button>
|
||||
|
||||
@@ -22,69 +22,6 @@
|
||||
<hr>
|
||||
|
||||
<% case account_type when %>
|
||||
<% when "invidious" %>
|
||||
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=invidious" method="post">
|
||||
<fieldset>
|
||||
<% if email %>
|
||||
<input name="email" type="hidden" value="<%= email %>">
|
||||
<% else %>
|
||||
<label for="email"><%= translate(locale, "User ID") %> :</label>
|
||||
<input required class="pure-input-1" name="email" type="text" placeholder="<%= translate(locale, "User ID") %>">
|
||||
<% end %>
|
||||
|
||||
<% if password %>
|
||||
<input name="password" type="hidden" value="<%= HTML.escape(password) %>">
|
||||
<% else %>
|
||||
<label for="password"><%= translate(locale, "Password") %> :</label>
|
||||
<input required class="pure-input-1" name="password" type="password" placeholder="<%= translate(locale, "Password") %>">
|
||||
<% end %>
|
||||
|
||||
<% if captcha %>
|
||||
<% case captcha_type when %>
|
||||
<% when "image" %>
|
||||
<% captcha = captcha.not_nil! %>
|
||||
<img style="width:50%" src='<%= captcha[:question] %>'/>
|
||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.encode_www_form(token) %>">
|
||||
<% end %>
|
||||
<input type="hidden" name="captcha_type" value="image">
|
||||
<label for="answer"><%= translate(locale, "Time (h:mm:ss):") %></label>
|
||||
<input type="text" name="answer" type="text" placeholder="h:mm:ss">
|
||||
<% when "text" %>
|
||||
<% captcha = captcha.not_nil! %>
|
||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.encode_www_form(token) %>">
|
||||
<% end %>
|
||||
<input type="hidden" name="captcha_type" value="text">
|
||||
<label for="answer"><%= captcha[:question] %></label>
|
||||
<input type="text" name="answer" type="text" placeholder="<%= translate(locale, "Answer") %>">
|
||||
<% end %>
|
||||
|
||||
<button type="submit" name="action" value="signin" class="pure-button pure-button-primary">
|
||||
<%= translate(locale, "Register") %>
|
||||
</button>
|
||||
|
||||
<% case captcha_type when %>
|
||||
<% when "image" %>
|
||||
<label>
|
||||
<button type="submit" name="change_type" class="pure-button pure-button-primary" value="text">
|
||||
<%= translate(locale, "Text CAPTCHA") %>
|
||||
</button>
|
||||
</label>
|
||||
<% when "text" %>
|
||||
<label>
|
||||
<button type="submit" name="change_type" class="pure-button pure-button-primary" value="image">
|
||||
<%= translate(locale, "Image CAPTCHA") %>
|
||||
</button>
|
||||
</label>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<button type="submit" name="action" value="signin" class="pure-button pure-button-primary">
|
||||
<%= translate(locale, "Sign In") %>/<%= translate(locale, "Register") %>
|
||||
</button>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
</form>
|
||||
<% when "google" %>
|
||||
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=google" method="post">
|
||||
<fieldset>
|
||||
@@ -121,6 +58,69 @@
|
||||
<button type="submit" class="pure-button pure-button-primary"><%= translate(locale, "Sign In") %></button>
|
||||
</fieldset>
|
||||
</form>
|
||||
<% else # "invidious" %>
|
||||
<form class="pure-form pure-form-stacked" action="/login?referer=<%= URI.encode_www_form(referer) %>&type=invidious" method="post">
|
||||
<fieldset>
|
||||
<% if email %>
|
||||
<input name="email" type="hidden" value="<%= email %>">
|
||||
<% else %>
|
||||
<label for="email"><%= translate(locale, "User ID") %> :</label>
|
||||
<input required class="pure-input-1" name="email" type="text" placeholder="<%= translate(locale, "User ID") %>">
|
||||
<% end %>
|
||||
|
||||
<% if password %>
|
||||
<input name="password" type="hidden" value="<%= HTML.escape(password) %>">
|
||||
<% else %>
|
||||
<label for="password"><%= translate(locale, "Password") %> :</label>
|
||||
<input required class="pure-input-1" name="password" type="password" placeholder="<%= translate(locale, "Password") %>">
|
||||
<% end %>
|
||||
|
||||
<% if captcha %>
|
||||
<% case captcha_type when %>
|
||||
<% when "image" %>
|
||||
<% captcha = captcha.not_nil! %>
|
||||
<img style="width:50%" src='<%= captcha[:question] %>'/>
|
||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.encode_www_form(token) %>">
|
||||
<% end %>
|
||||
<input type="hidden" name="captcha_type" value="image">
|
||||
<label for="answer"><%= translate(locale, "Time (h:mm:ss):") %></label>
|
||||
<input type="text" name="answer" type="text" placeholder="h:mm:ss">
|
||||
<% else # "text" %>
|
||||
<% captcha = captcha.not_nil! %>
|
||||
<% captcha[:tokens].each_with_index do |token, i| %>
|
||||
<input type="hidden" name="token[<%= i %>]" value="<%= URI.encode_www_form(token) %>">
|
||||
<% end %>
|
||||
<input type="hidden" name="captcha_type" value="text">
|
||||
<label for="answer"><%= captcha[:question] %></label>
|
||||
<input type="text" name="answer" type="text" placeholder="<%= translate(locale, "Answer") %>">
|
||||
<% end %>
|
||||
|
||||
<button type="submit" name="action" value="signin" class="pure-button pure-button-primary">
|
||||
<%= translate(locale, "Register") %>
|
||||
</button>
|
||||
|
||||
<% case captcha_type when %>
|
||||
<% when "image" %>
|
||||
<label>
|
||||
<button type="submit" name="change_type" class="pure-button pure-button-primary" value="text">
|
||||
<%= translate(locale, "Text CAPTCHA") %>
|
||||
</button>
|
||||
</label>
|
||||
<% else # "text" %>
|
||||
<label>
|
||||
<button type="submit" name="change_type" class="pure-button pure-button-primary" value="image">
|
||||
<%= translate(locale, "Image CAPTCHA") %>
|
||||
</button>
|
||||
</label>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<button type="submit" name="action" value="signin" class="pure-button pure-button-primary">
|
||||
<%= translate(locale, "Sign In") %>/<%= translate(locale, "Register") %>
|
||||
</button>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
</form>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
<% if playlist.is_a?(InvidiousPlaylist) && playlist.author == user.try &.email %>
|
||||
<div class="pure-u-1-3"><a href="/edit_playlist?list=<%= plid %>"><i class="icon ion-md-create"></i></a></div>
|
||||
<div class="pure-u-1-3"><a href="/delete_playlist?list=<%= plid %>"><i class="icon ion-md-trash"></i></a></div>
|
||||
<% else %>
|
||||
<% if PG_DB.query_one?("SELECT id FROM playlists WHERE id = $1", playlist.id, as: String).nil? %>
|
||||
<div class="pure-u-1-3"><a href="/subscribe_playlist?list=<%= plid %>"><i class="icon ion-md-add"></i></a></div>
|
||||
<% else %>
|
||||
<div class="pure-u-1-3"><a href="/delete_playlist?list=<%= plid %>"><i class="icon ion-md-trash"></i></a></div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<div class="pure-u-1-3"><a href="/feed/playlist/<%= plid %>"><i class="icon ion-logo-rss"></i></a></div>
|
||||
</div>
|
||||
@@ -69,12 +75,14 @@
|
||||
</div>
|
||||
|
||||
<% if playlist.is_a?(InvidiousPlaylist) && playlist.author == user.try &.email %>
|
||||
<script>
|
||||
var playlist_data = {
|
||||
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||
}
|
||||
<script id="playlist_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"csrf_token" => URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "")
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/playlist_widget.js"></script>
|
||||
<script src="/js/playlist_widget.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<% end %>
|
||||
|
||||
<div class="pure-g">
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<div class="pure-u-1 pure-u-md-4-5"></div>
|
||||
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
|
||||
<% if continuation %>
|
||||
<a href="/channel/<%= channel.ucid %>/playlists?continuation=<%= continuation %><% if sort_by != "last" %>&sort_by=<%= sort_by %><% end %>">
|
||||
<a href="/channel/<%= channel.ucid %>/playlists?continuation=<%= continuation %><% if sort_by != "last" %>&sort_by=<%= HTML.escape(sort_by) %><% end %>">
|
||||
<%= translate(locale, "Next page") %>
|
||||
</a>
|
||||
<% end %>
|
||||
|
||||
@@ -2,12 +2,6 @@
|
||||
<title><%= translate(locale, "Preferences") %> - Invidious</title>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
function update_value(element) {
|
||||
document.getElementById('volume-value').innerText = element.value;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="h-box">
|
||||
<form class="pure-form pure-form-aligned" action="/preferences?referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||
<fieldset>
|
||||
@@ -65,7 +59,7 @@ function update_value(element) {
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="volume"><%= translate(locale, "Player volume: ") %></label>
|
||||
<input name="volume" id="volume" oninput="update_value(this);" type="range" min="0" max="100" step="5" value="<%= preferences.volume %>">
|
||||
<input name="volume" id="volume" data-onrange="update_volume_value" type="range" min="0" max="100" step="5" value="<%= preferences.volume %>">
|
||||
<span class="pure-form-message-inline" id="volume-value"><%= preferences.volume %></span>
|
||||
</div>
|
||||
|
||||
@@ -205,7 +199,7 @@ function update_value(element) {
|
||||
<% # Web notifications are only supported over HTTPS %>
|
||||
<% if Kemal.config.ssl || config.https_only %>
|
||||
<div class="pure-control-group">
|
||||
<a href="#" onclick="Notification.requestPermission()"><%= translate(locale, "Enable web notifications") %></a>
|
||||
<a href="#" data-onclick="notification_requestPermission"><%= translate(locale, "Enable web notifications") %></a>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -233,11 +227,6 @@ function update_value(element) {
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="top_enabled"><%= translate(locale, "Top enabled: ") %></label>
|
||||
<input name="top_enabled" id="top_enabled" type="checkbox" <% if config.top_enabled %>checked<% end %>>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="captcha_enabled"><%= translate(locale, "CAPTCHA enabled: ") %></label>
|
||||
<input name="captcha_enabled" id="captcha_enabled" type="checkbox" <% if config.captcha_enabled %>checked<% end %>>
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
<title><%= search_query.not_nil!.size > 30 ? HTML.escape(query.not_nil![0,30].rstrip(".") + "...") : HTML.escape(query.not_nil!) %> - Invidious</title>
|
||||
<% end %>
|
||||
|
||||
<div class="pure-g h-box v-box">
|
||||
<div class="pure-u-1 pure-u-lg-1-5">
|
||||
<% if page > 1 %>
|
||||
<a href="/search?q=<%= HTML.escape(query.not_nil!) %>&page=<%= page - 1 %>">
|
||||
<%= translate(locale, "Previous page") %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-lg-3-5"></div>
|
||||
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
|
||||
<% if count >= 20 %>
|
||||
<a href="/search?q=<%= HTML.escape(query.not_nil!) %>&page=<%= page + 1 %>">
|
||||
<%= translate(locale, "Next page") %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g">
|
||||
<% videos.each_slice(4) do |slice| %>
|
||||
<% slice.each do |item| %>
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
<div class="pure-u-2-5"></div>
|
||||
<div class="pure-u-1-5" style="text-align:right">
|
||||
<h3 style="padding-right:0.5em">
|
||||
<form onsubmit="return false" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<form data-onsubmit="return_false" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>&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) || "") %>">
|
||||
<a onclick="remove_subscription(this)" data-ucid="<%= channel.id %>" href="#">
|
||||
<a data-onclick="remove_subscription" data-ucid="<%= channel.id %>" href="#">
|
||||
<input style="all:unset" type="submit" value="<%= translate(locale, "unsubscribe") %>">
|
||||
</a>
|
||||
</form>
|
||||
@@ -52,32 +52,3 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
function remove_subscription(target) {
|
||||
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||
row.style.display = 'none';
|
||||
var count = document.getElementById('count');
|
||||
count.innerText = count.innerText - 1;
|
||||
|
||||
var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
|
||||
'&referer=<%= env.get("current_page") %>' +
|
||||
'&c=' + target.getAttribute('data-ucid');
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'json';
|
||||
xhr.timeout = 10000;
|
||||
xhr.open('POST', url, true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status != 200) {
|
||||
count.innerText = parseInt(count.innerText) + 1;
|
||||
row.style.display = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send('csrf_token=<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>');
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -45,10 +45,12 @@
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var watched_data = {
|
||||
csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
|
||||
}
|
||||
<script id="watched_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"csrf_token" => URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "")
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/watched_widget.js"></script>
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
<div class="footer">
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<a href="https://github.com/omarroth/invidious">
|
||||
<a href="https://github.com/iv-org/invidious">
|
||||
<%= translate(locale, "Released under the AGPLv3 by Omar Roth.") %>
|
||||
</a>
|
||||
</div>
|
||||
@@ -140,23 +140,24 @@
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-1-3">
|
||||
<i class="icon ion-logo-github"></i>
|
||||
<%= translate(locale, "Current version: ") %> <%= CURRENT_VERSION %>-<%= CURRENT_COMMIT %>
|
||||
<i class="icon ion-logo-github"></i>
|
||||
<%= CURRENT_BRANCH %>
|
||||
<%= translate(locale, "Current version: ") %> <%= CURRENT_VERSION %>-<%= CURRENT_COMMIT %> @ <%= CURRENT_BRANCH %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-md-2-24"></div>
|
||||
</div>
|
||||
<script src="/js/handlers.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<script src="/js/themes.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<% if env.get? "user" %>
|
||||
<script src="/js/sse.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<script>
|
||||
var notification_data = {
|
||||
upload_text: '<%= HTML.escape(translate(locale, "`x` uploaded a video")) %>',
|
||||
live_upload_text: '<%= HTML.escape(translate(locale, "`x` is live")) %>',
|
||||
}
|
||||
<script id="notification_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"upload_text" => HTML.escape(translate(locale, "`x` uploaded a video")),
|
||||
"live_upload_text" => HTML.escape(translate(locale, "`x` is live"))
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/notifications.js?v=<%= ASSET_COMMIT %>"></script>
|
||||
<% end %>
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
</div>
|
||||
<div class="pure-u-1-5" style="text-align:right">
|
||||
<h3 style="padding-right:0.5em">
|
||||
<form onsubmit="return false" action="/token_ajax?action_revoke_token=1&session=<%= token[:session] %>&referer=<%= env.get("current_page") %>" method="post">
|
||||
<form data-onsubmit="return_false" action="/token_ajax?action_revoke_token=1&session=<%= token[:session] %>&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) || "") %>">
|
||||
<a onclick="revoke_token(this)" data-session="<%= token[:session] %>" href="#">
|
||||
<a data-onclick="revoke_token" data-session="<%= token[:session] %>" href="#">
|
||||
<input style="all:unset" type="submit" value="<%= translate(locale, "revoke") %>">
|
||||
</a>
|
||||
</form>
|
||||
@@ -44,32 +44,3 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
function revoke_token(target) {
|
||||
var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||
row.style.display = 'none';
|
||||
var count = document.getElementById('count');
|
||||
count.innerText = count.innerText - 1;
|
||||
|
||||
var url = '/token_ajax?action_revoke_token=1&redirect=false' +
|
||||
'&referer=<%= env.get("current_page") %>' +
|
||||
'&session=' + target.getAttribute('data-session');
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'json';
|
||||
xhr.timeout = 10000;
|
||||
xhr.open('POST', url, true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status != 200) {
|
||||
count.innerText = parseInt(count.innerText) + 1;
|
||||
row.style.display = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send('csrf_token=<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>');
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<% content_for "header" do %>
|
||||
<meta name="description" content="<%= translate(locale, "An alternative front-end to YouTube") %>">
|
||||
<title>
|
||||
<% if env.get("preferences").as(Preferences).default_home != "Top" %>
|
||||
<%= translate(locale, "Top") %> - Invidious
|
||||
<% else %>
|
||||
Invidious
|
||||
<% end %>
|
||||
</title>
|
||||
<% end %>
|
||||
|
||||
<%= rendered "components/feed_menu" %>
|
||||
|
||||
<div class="pure-g">
|
||||
<% top_videos.each_slice(4) do |slice| %>
|
||||
<% slice.each do |item| %>
|
||||
<%= rendered "components/item" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-2-3">
|
||||
<h3><%= translate(locale, "`x` playlists", %(<span id="count">#{items.size}</span>)) %></h3>
|
||||
<h3><%= translate(locale, "`x` created playlists", %(<span id="count">#{items_created.size}</span>)) %></h3>
|
||||
</div>
|
||||
<div class="pure-u-1-3" style="text-align:right">
|
||||
<h3>
|
||||
@@ -16,7 +16,21 @@
|
||||
</div>
|
||||
|
||||
<div class="pure-g">
|
||||
<% items.each_slice(4) do |slice| %>
|
||||
<% items_created.each_slice(4) do |slice| %>
|
||||
<% slice.each do |item| %>
|
||||
<%= rendered "components/item" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-1">
|
||||
<h3><%= translate(locale, "`x` saved playlists", %(<span id="count">#{items_saved.size}</span>)) %></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g">
|
||||
<% items_saved.each_slice(4) do |slice| %>
|
||||
<% slice.each do |item| %>
|
||||
<%= rendered "components/item" %>
|
||||
<% end %>
|
||||
|
||||
@@ -3,47 +3,49 @@
|
||||
<meta name="description" content="<%= HTML.escape(video.short_description) %>">
|
||||
<meta name="keywords" content="<%= video.keywords.join(",") %>">
|
||||
<meta property="og:site_name" content="Invidious">
|
||||
<meta property="og:url" content="<%= host_url %>/watch?v=<%= video.id %>">
|
||||
<meta property="og:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>">
|
||||
<meta property="og:title" content="<%= HTML.escape(video.title) %>">
|
||||
<meta property="og:image" content="/vi/<%= video.id %>/maxres.jpg">
|
||||
<meta property="og:description" content="<%= HTML.escape(video.short_description) %>">
|
||||
<meta property="og:description" content="<%= video.short_description %>">
|
||||
<meta property="og:type" content="video.other">
|
||||
<meta property="og:video:url" content="<%= host_url %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:secure_url" content="<%= host_url %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:url" content="<%= HOST_URL %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:secure_url" content="<%= HOST_URL %>/embed/<%= video.id %>">
|
||||
<meta property="og:video:type" content="text/html">
|
||||
<meta property="og:video:width" content="1280">
|
||||
<meta property="og:video:height" content="720">
|
||||
<meta name="twitter:card" content="player">
|
||||
<meta name="twitter:site" content="@omarroth1">
|
||||
<meta name="twitter:url" content="<%= host_url %>/watch?v=<%= video.id %>">
|
||||
<meta name="twitter:url" content="<%= HOST_URL %>/watch?v=<%= video.id %>">
|
||||
<meta name="twitter:title" content="<%= HTML.escape(video.title) %>">
|
||||
<meta name="twitter:description" content="<%= HTML.escape(video.short_description) %>">
|
||||
<meta name="twitter:image" content="<%= host_url %>/vi/<%= video.id %>/maxres.jpg">
|
||||
<meta name="twitter:player" content="<%= host_url %>/embed/<%= video.id %>">
|
||||
<meta name="twitter:description" content="<%= video.short_description %>">
|
||||
<meta name="twitter:image" content="<%= HOST_URL %>/vi/<%= video.id %>/maxres.jpg">
|
||||
<meta name="twitter:player" content="<%= HOST_URL %>/embed/<%= video.id %>">
|
||||
<meta name="twitter:player:width" content="1280">
|
||||
<meta name="twitter:player:height" content="720">
|
||||
<%= rendered "components/player_sources" %>
|
||||
<title><%= HTML.escape(video.title) %> - Invidious</title>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
var video_data = {
|
||||
id: '<%= video.id %>',
|
||||
index: '<%= continuation %>',
|
||||
plid: '<%= plid %>',
|
||||
length_seconds: <%= video.length_seconds.to_f %>,
|
||||
play_next: <%= !rvs.empty? && !plid && params.continue %>,
|
||||
next_video: '<%= rvs.select { |rv| rv["id"]? }[0]?.try &.["id"] %>',
|
||||
youtube_comments_text: '<%= HTML.escape(translate(locale, "View YouTube comments")) %>',
|
||||
reddit_comments_text: '<%= HTML.escape(translate(locale, "View Reddit comments")) %>',
|
||||
reddit_permalink_text: '<%= HTML.escape(translate(locale, "View more comments on Reddit")) %>',
|
||||
comments_text: '<%= HTML.escape(translate(locale, "View `x` comments", "{commentCount}")) %>',
|
||||
hide_replies_text: '<%= HTML.escape(translate(locale, "Hide replies")) %>',
|
||||
show_replies_text: '<%= HTML.escape(translate(locale, "Show replies")) %>',
|
||||
params: <%= params.to_json %>,
|
||||
preferences: <%= preferences.to_json %>,
|
||||
premiere_timestamp: <%= video.premiere_timestamp.try &.to_unix || "null" %>
|
||||
}
|
||||
<script id="video_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"id" => video.id,
|
||||
"index" => continuation,
|
||||
"plid" => plid,
|
||||
"length_seconds" => video.length_seconds.to_f,
|
||||
"play_next" => !video.related_videos.empty? && !plid && params.continue,
|
||||
"next_video" => video.related_videos.select { |rv| rv["id"]? }[0]?.try &.["id"],
|
||||
"youtube_comments_text" => HTML.escape(translate(locale, "View YouTube comments")),
|
||||
"reddit_comments_text" => HTML.escape(translate(locale, "View Reddit comments")),
|
||||
"reddit_permalink_text" => HTML.escape(translate(locale, "View more comments on Reddit")),
|
||||
"comments_text" => HTML.escape(translate(locale, "View `x` comments", "{commentCount}")),
|
||||
"hide_replies_text" => HTML.escape(translate(locale, "Hide replies")),
|
||||
"show_replies_text" => HTML.escape(translate(locale, "Show replies")),
|
||||
"params" => params,
|
||||
"preferences" => preferences,
|
||||
"premiere_timestamp" => video.premiere_timestamp.try &.to_unix
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
|
||||
<div id="player-container" class="h-box">
|
||||
@@ -70,13 +72,13 @@ var video_data = {
|
||||
</h3>
|
||||
<% end %>
|
||||
|
||||
<% if !reason.empty? %>
|
||||
<% if video.reason %>
|
||||
<h3>
|
||||
<%= reason %>
|
||||
<%= video.reason %>
|
||||
</h3>
|
||||
<% elsif video.premiere_timestamp %>
|
||||
<% elsif video.premiere_timestamp.try &.> Time.utc %>
|
||||
<h3>
|
||||
<%= translate(locale, "Premieres in `x`", recode_date((video.premiere_timestamp.as(Time) - Time.utc).ago, locale)) %>
|
||||
<%= video.premiere_timestamp.try { |t| translate(locale, "Premieres in `x`", recode_date((t - Time.utc).ago, locale)) } %>
|
||||
</h3>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -84,10 +86,10 @@ var video_data = {
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-lg-1-5">
|
||||
<div class="h-box">
|
||||
<span>
|
||||
<span id="watch-on-youtube">
|
||||
<a href="https://www.youtube.com/watch?v=<%= video.id %>"><%= translate(locale, "Watch on YouTube") %></a>
|
||||
</span>
|
||||
<p>
|
||||
<p id="annotations">
|
||||
<% if params.annotations %>
|
||||
<a href="/watch?<%= env.params.query %>&iv_load_policy=3">
|
||||
<%= translate(locale, "Hide annotations") %>
|
||||
@@ -99,26 +101,54 @@ var video_data = {
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
<% if user %>
|
||||
<% playlists = PG_DB.query_all("SELECT id,title FROM playlists WHERE author = $1 AND id LIKE 'IV%'", user.email, as: {String, String}) %>
|
||||
<% if !playlists.empty? %>
|
||||
<form data-onsubmit="return_false" class="pure-form pure-form-stacked" action="/playlist_ajax" method="post">
|
||||
<div class="pure-control-group">
|
||||
<label for="playlist_id"><%= translate(locale, "Add to playlist: ") %></label>
|
||||
<select style="width:100%" name="playlist_id" id="playlist_id">
|
||||
<% playlists.each do |plid, title| %>
|
||||
<option data-plid="<%= plid %>" value="<%= plid %>"><%= title %></option>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button data-onclick="add_playlist_video" data-id="<%= video.id %>" type="submit" class="pure-button pure-button-primary">
|
||||
<b><%= translate(locale, "Add to playlist") %></b>
|
||||
</button>
|
||||
</form>
|
||||
<script id="playlist_data" type="application/json">
|
||||
<%=
|
||||
{
|
||||
"csrf_token" => URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "")
|
||||
}.to_pretty_json
|
||||
%>
|
||||
</script>
|
||||
<script src="/js/playlist_widget.js?v=<%= Time.utc.to_unix_ms %>"></script>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if CONFIG.dmca_content.includes?(video.id) || CONFIG.disabled?("downloads") %>
|
||||
<p><%= translate(locale, "Download is disabled.") %></p>
|
||||
<p id="download"><%= translate(locale, "Download is disabled.") %></p>
|
||||
<% else %>
|
||||
<form class="pure-form pure-form-stacked" action="/latest_version" method="get" rel="noopener" target="_blank">
|
||||
<div class="pure-control-group">
|
||||
<label for="download_widget"><%= translate(locale, "Download as: ") %></label>
|
||||
<select style="width:100%" name="download_widget" id="download_widget">
|
||||
<% fmt_stream.each do |option| %>
|
||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
||||
<%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["type"].split(";")[0] %>
|
||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["mimeType"].as_s.split(";")[0].split("/")[1] %>"}'>
|
||||
<%= itag_to_metadata?(option["itag"]).try &.["height"]? || "~240" %>p - <%= option["mimeType"].as_s.split(";")[0] %>
|
||||
</option>
|
||||
<% end %>
|
||||
<% video_streams.each do |option| %>
|
||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
||||
<%= option["quality_label"] %> - <%= option["type"].split(";")[0] %> @ <%= option["fps"] %>fps - video only
|
||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["mimeType"].as_s.split(";")[0].split("/")[1] %>"}'>
|
||||
<%= option["qualityLabel"] %> - <%= option["mimeType"].as_s.split(";")[0] %> @ <%= option["fps"] %>fps - video only
|
||||
</option>
|
||||
<% end %>
|
||||
<% audio_streams.each do |option| %>
|
||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["type"].split(";")[0].split("/")[1] %>"}'>
|
||||
<%= option["type"].split(";")[0] %> @ <%= option["bitrate"] %>k - audio only
|
||||
<option value='{"id":"<%= video.id %>","itag":"<%= option["itag"] %>","title":"<%= URI.encode_www_form(video.title) %>-<%= video.id %>.<%= option["mimeType"].as_s.split(";")[0].split("/")[1] %>"}'>
|
||||
<%= option["mimeType"].as_s.split(";")[0] %> @ <%= option["bitrate"]?.try &.as_i./ 1000 %>k - audio only
|
||||
</option>
|
||||
<% end %>
|
||||
<% captions.each do |caption| %>
|
||||
@@ -135,23 +165,23 @@ var video_data = {
|
||||
</form>
|
||||
<% end %>
|
||||
|
||||
<p><i class="icon ion-ios-eye"></i> <%= number_with_separator(video.views) %></p>
|
||||
<p><i class="icon ion-ios-thumbs-up"></i> <%= number_with_separator(video.likes) %></p>
|
||||
<p><i class="icon ion-ios-thumbs-down"></i> <%= number_with_separator(video.dislikes) %></p>
|
||||
<p id="views"><i class="icon ion-ios-eye"></i> <%= number_with_separator(video.views) %></p>
|
||||
<p id="likes"><i class="icon ion-ios-thumbs-up"></i> <%= number_with_separator(video.likes) %></p>
|
||||
<p id="dislikes"><i class="icon ion-ios-thumbs-down"></i> <%= number_with_separator(video.dislikes) %></p>
|
||||
<p id="genre"><%= translate(locale, "Genre: ") %>
|
||||
<% if video.genre_url.empty? %>
|
||||
<% if !video.genre_url %>
|
||||
<%= video.genre %>
|
||||
<% else %>
|
||||
<a href="<%= video.genre_url %>"><%= video.genre %></a>
|
||||
<% end %>
|
||||
</p>
|
||||
<% if !video.license.empty? %>
|
||||
<% if video.license %>
|
||||
<p id="license"><%= translate(locale, "License: ") %><%= video.license %></p>
|
||||
<% end %>
|
||||
<p id="family_friendly"><%= translate(locale, "Family friendly? ") %><%= translate_bool(locale, video.is_family_friendly) %></p>
|
||||
<p id="wilson"><%= translate(locale, "Wilson score: ") %><%= video.wilson_score.round(4) %></p>
|
||||
<p id="rating"><%= translate(locale, "Rating: ") %><%= rating.round(4) %> / 5</p>
|
||||
<p id="engagement"><%= translate(locale, "Engagement: ") %><%= engagement.round(2) %>%</p>
|
||||
<p id="wilson"><%= translate(locale, "Wilson score: ") %><%= video.wilson_score %></p>
|
||||
<p id="rating"><%= translate(locale, "Rating: ") %><%= video.average_rating %> / 5</p>
|
||||
<p id="engagement"><%= translate(locale, "Engagement: ") %><%= video.engagement %>%</p>
|
||||
<% if video.allowed_regions.size != REGIONS.size %>
|
||||
<p id="allowed_regions">
|
||||
<% if video.allowed_regions.size < REGIONS.size // 2 %>
|
||||
@@ -168,8 +198,10 @@ var video_data = {
|
||||
<div class="h-box">
|
||||
<a href="/channel/<%= video.ucid %>" style="display:block;width:fit-content;width:-moz-fit-content">
|
||||
<div class="channel-profile">
|
||||
<img src="/ggpht<%= URI.parse(video.author_thumbnail).full_path %>">
|
||||
<span><%= video.author %></span>
|
||||
<% if !video.author_thumbnail.empty? %>
|
||||
<img src="/ggpht<%= URI.parse(video.author_thumbnail).full_path %>">
|
||||
<% end %>
|
||||
<span id="channel-name"><%= video.author %></span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -178,9 +210,9 @@ var video_data = {
|
||||
<% sub_count_text = video.sub_count_text %>
|
||||
<%= rendered "components/subscribe_widget" %>
|
||||
|
||||
<p>
|
||||
<% if video.premiere_timestamp %>
|
||||
<b><%= translate(locale, "Premieres `x`", video.premiere_timestamp.not_nil!.to_s("%B %-d, %R UTC")) %></b>
|
||||
<p id="published-date">
|
||||
<% if video.premiere_timestamp.try &.> Time.utc %>
|
||||
<b><%= video.premiere_timestamp.try { |t| translate(locale, "Premieres `x`", t.to_s("%B %-d, %R UTC")) } %></b>
|
||||
<% else %>
|
||||
<b><%= translate(locale, "Shared `x`", video.published.to_s("%B %-d, %Y")) %></b>
|
||||
<% end %>
|
||||
@@ -214,7 +246,7 @@ var video_data = {
|
||||
|
||||
<% if params.related_videos %>
|
||||
<div class="h-box">
|
||||
<% if !rvs.empty? %>
|
||||
<% if !video.related_videos.empty? %>
|
||||
<div <% if plid %>style="display:none"<% end %>>
|
||||
<div class="pure-control-group">
|
||||
<label for="continue"><%= translate(locale, "Play next by default: ") %></label>
|
||||
@@ -224,7 +256,7 @@ var video_data = {
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% rvs.each do |rv| %>
|
||||
<% video.related_videos.each do |rv| %>
|
||||
<% if rv["id"]? %>
|
||||
<a href="/watch?v=<%= rv["id"] %>">
|
||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||
@@ -237,15 +269,17 @@ var video_data = {
|
||||
<h5 class="pure-g">
|
||||
<div class="pure-u-14-24">
|
||||
<% if rv["ucid"]? %>
|
||||
<b style="width:100%"><a href="/channel/<%= rv["ucid"] %>"><%= rv["author"] %></a></b>
|
||||
<b style="width:100%"><a href="/channel/<%= rv["ucid"] %>"><%= rv["author"]? %></a></b>
|
||||
<% else %>
|
||||
<b style="width:100%"><%= rv["author"] %></b>
|
||||
<b style="width:100%"><%= rv["author"]? %></b>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="pure-u-10-24" style="text-align:right">
|
||||
<% if views = rv["short_view_count_text"]?.try &.delete(", views watching") %>
|
||||
<b class="width:100%"><%= translate(locale, "`x` views", views) %></b>
|
||||
<% if !views.empty? %>
|
||||
<b class="width:100%"><%= translate(locale, "`x` views", views) %></b>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</h5>
|
||||
|
||||
Reference in New Issue
Block a user