mirror of
https://git.nadeko.net/Fijxu/invidious.git
synced 2025-12-19 11:28:51 +00:00
Add support for custom playlists
This commit is contained in:
56
src/invidious/views/add_playlist_items.ecr
Normal file
56
src/invidious/views/add_playlist_items.ecr
Normal file
@@ -0,0 +1,56 @@
|
||||
<% content_for "header" do %>
|
||||
<title><%= playlist.title %> - Invidious</title>
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/playlist/<%= plid %>" />
|
||||
<% end %>
|
||||
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-lg-1-5"></div>
|
||||
<div class="pure-u-1 pure-u-lg-3-5">
|
||||
<div class="h-box">
|
||||
<form class="pure-form pure-form-aligned" action="/add_playlist_items" method="get">
|
||||
<legend><a href="/playlist?list=<%= playlist.id %>"><%= translate(locale, "Editing playlist `x`", %|"#{HTML.escape(playlist.title)}"|) %></a></legend>
|
||||
|
||||
<fieldset>
|
||||
<input class="pure-input-1" type="search" name="q" <% if query %>value="<%= HTML.escape(query) %>"<% else %>placeholder="<%= translate(locale, "Search for videos") %>"<% end %>>
|
||||
<input type="hidden" name="list" value="<%= plid %>">
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<script src="/js/playlist_widget.js"></script>
|
||||
|
||||
<div class="pure-g">
|
||||
<% videos.each_slice(4) do |slice| %>
|
||||
<% slice.each do |item| %>
|
||||
<%= rendered "components/item" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if query %>
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-1 pure-u-lg-1-5">
|
||||
<% if page > 1 %>
|
||||
<a href="/add_playlist_items?list=<%= plid %>&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="/add_playlist_items?list=<%= plid %>&q=<%= HTML.escape(query.not_nil!) %>&page=<%= page + 1 %>">
|
||||
<%= translate(locale, "Next page") %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -13,7 +13,7 @@
|
||||
<p><%= translate(locale, "`x` subscribers", number_with_separator(item.subscriber_count)) %></p>
|
||||
<% if !item.auto_generated %><p><%= translate(locale, "`x` videos", number_with_separator(item.video_count)) %></p><% end %>
|
||||
<h5><%= item.description_html %></h5>
|
||||
<% when SearchPlaylist %>
|
||||
<% when SearchPlaylist, InvidiousPlaylist %>
|
||||
<% if item.id.starts_with? "RD" %>
|
||||
<% url = "/mix?list=#{item.id}&continuation=#{URI.parse(item.thumbnail || "/vi/-----------").full_path.split("/")[2]}" %>
|
||||
<% else %>
|
||||
@@ -56,6 +56,19 @@
|
||||
<% if !env.get("preferences").as(Preferences).thin_mode %>
|
||||
<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">
|
||||
<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)">
|
||||
<button type="submit" style="all:unset">
|
||||
<i class="icon ion-md-trash"></i>
|
||||
</button>
|
||||
</a>
|
||||
</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 %>
|
||||
@@ -63,7 +76,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<p><%= item.title %></p>
|
||||
<p><a href="/watch?v=<%= item.id %>"><%= item.title %></a></p>
|
||||
</a>
|
||||
<p>
|
||||
<b>
|
||||
@@ -103,6 +116,17 @@
|
||||
</a>
|
||||
</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">
|
||||
<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)">
|
||||
<button type="submit" style="all:unset">
|
||||
<i class="icon ion-md-add"></i>
|
||||
</button>
|
||||
</a>
|
||||
</p>
|
||||
</form>
|
||||
<% end %>
|
||||
|
||||
<% if item.responds_to?(:live_now) && item.live_now %>
|
||||
|
||||
39
src/invidious/views/create_playlist.ecr
Normal file
39
src/invidious/views/create_playlist.ecr
Normal file
@@ -0,0 +1,39 @@
|
||||
<% content_for "header" do %>
|
||||
<title><%= translate(locale, "Create playlist") %> - Invidious</title>
|
||||
<% end %>
|
||||
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1 pure-u-lg-1-5"></div>
|
||||
<div class="pure-u-1 pure-u-lg-3-5">
|
||||
<div class="h-box">
|
||||
<form class="pure-form pure-form-aligned" action="/create_playlist?referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||
<fieldset>
|
||||
<legend><%= translate(locale, "Create playlist") %></legend>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="title"><%= translate(locale, "Title") %> :</label>
|
||||
<input required name="title" type="text" placeholder="<%= translate(locale, "Title") %>">
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="privacy"><%= translate(locale, "Playlist privacy") %> :</label>
|
||||
<select name="privacy" id="privacy">
|
||||
<% PlaylistPrivacy.names.each do |option| %>
|
||||
<option value="<%= option %>" <% if option == "Public" %> selected <% end %>><%= translate(locale, option) %></option>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="pure-controls">
|
||||
<button type="submit" name="action" value="create_playlist" class="pure-button pure-button-primary">
|
||||
<%= translate(locale, "Create playlist") %>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(csrf_token) %>">
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1 pure-u-lg-1-5"></div>
|
||||
</div>
|
||||
24
src/invidious/views/delete_playlist.ecr
Normal file
24
src/invidious/views/delete_playlist.ecr
Normal file
@@ -0,0 +1,24 @@
|
||||
<% content_for "header" do %>
|
||||
<title><%= translate(locale, "Delete playlist") %> - Invidious</title>
|
||||
<% end %>
|
||||
|
||||
<div class="h-box">
|
||||
<form class="pure-form pure-form-aligned" action="/delete_playlist?list=<%= plid %>&referer=<%= URI.encode_www_form(referer) %>" method="post">
|
||||
<legend><%= translate(locale, "Delete playlist `x`?", %|"#{HTML.escape(playlist.title)}"|) %></legend>
|
||||
|
||||
<div class="pure-g">
|
||||
<div class="pure-u-1-2">
|
||||
<button type="submit" name="submit" value="delete_playlist" class="pure-button pure-button-primary">
|
||||
<%= translate(locale, "Yes") %>
|
||||
</button>
|
||||
</div>
|
||||
<div class="pure-u-1-2">
|
||||
<a class="pure-button" href="/playlist?list=<%= plid %>">
|
||||
<%= translate(locale, "No") %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(csrf_token) %>">
|
||||
</form>
|
||||
</div>
|
||||
81
src/invidious/views/edit_playlist.ecr
Normal file
81
src/invidious/views/edit_playlist.ecr
Normal file
@@ -0,0 +1,81 @@
|
||||
<% content_for "header" do %>
|
||||
<title><%= playlist.title %> - Invidious</title>
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/playlist/<%= plid %>" />
|
||||
<% end %>
|
||||
|
||||
<form class="pure-form" action="/edit_playlist?list=<%= plid %>" method="post">
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-2-3">
|
||||
<h3><input class="pure-input-1" maxlength="150" name="title" type="text" value="<%= playlist.title %>"></h3>
|
||||
<b>
|
||||
<%= playlist.author %> |
|
||||
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> |
|
||||
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> |
|
||||
<i class="icon <%= {"ion-md-globe", "ion-ios-unlock", "ion-ios-lock"}[playlist.privacy.value] %>"></i>
|
||||
<select name="privacy">
|
||||
<% {"Public", "Unlisted", "Private"}.each do |option| %>
|
||||
<option value="<%= option %>" <% if option == playlist.privacy.to_s %>selected<% end %>><%= translate(locale, option) %></option>
|
||||
<% end %>
|
||||
</select>
|
||||
</b>
|
||||
</div>
|
||||
<div class="pure-u-1-3" style="text-align:right">
|
||||
<h3>
|
||||
<div class="pure-g user-field">
|
||||
<div class="pure-u-1-3">
|
||||
<a href="javascript:void(0)">
|
||||
<button type="submit" style="all:unset">
|
||||
<i class="icon ion-md-save"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pure-u-1-3"><a href="/delete_playlist?list=<%= plid %>"><i class="icon ion-md-trash"></i></a></div>
|
||||
<div class="pure-u-1-3"><a href="/feed/playlist/<%= plid %>"><i class="icon ion-logo-rss"></i></a></div>
|
||||
</div>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h-box">
|
||||
<textarea maxlength="5000" name="description" style="margin-top:10px;max-width:100%;height:20vh" class="pure-input-1"><%= playlist.description %></textarea>
|
||||
</div>
|
||||
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(csrf_token) %>">
|
||||
</form>
|
||||
|
||||
<% if playlist.is_a?(InvidiousPlaylist) && playlist.author == user.try &.email %>
|
||||
<div class="h-box" style="text-align:right">
|
||||
<h3>
|
||||
<a href="/add_playlist_items?list=<%= plid %>"><i class="icon ion-md-add"></i></a>
|
||||
</h3>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="h-box">
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="pure-g">
|
||||
<% videos.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 pure-u-lg-1-5">
|
||||
<% if page > 1 %>
|
||||
<a href="/playlist?list=<%= playlist.id %>&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 videos.size == 100 %>
|
||||
<a href="/playlist?list=<%= playlist.id %>&page=<%= page + 1 %>">
|
||||
<%= translate(locale, "Next page") %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,6 +29,7 @@
|
||||
<script>
|
||||
var video_data = {
|
||||
id: '<%= video.id %>',
|
||||
index: '<%= continuation %>',
|
||||
plid: '<%= plid %>',
|
||||
length_seconds: '<%= video.length_seconds.to_f %>',
|
||||
video_series: <%= video_series.to_json %>,
|
||||
|
||||
@@ -6,36 +6,77 @@
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-2-3">
|
||||
<h3><%= playlist.title %></h3>
|
||||
<% if playlist.is_a? InvidiousPlaylist %>
|
||||
<b>
|
||||
<% if playlist.author == user.try &.email %>
|
||||
<a href="/view_all_playlists"><%= playlist.author %></a> |
|
||||
<% else %>
|
||||
<%= playlist.author %> |
|
||||
<% end %>
|
||||
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> |
|
||||
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %> |
|
||||
<% case playlist.as(InvidiousPlaylist).privacy when %>
|
||||
<% when PlaylistPrivacy::Public %>
|
||||
<i class="icon ion-md-globe"></i> <%= translate(locale, "Public") %>
|
||||
<% when PlaylistPrivacy::Unlisted %>
|
||||
<i class="icon ion-ios-unlock"></i> <%= translate(locale, "Unlisted") %>
|
||||
<% when PlaylistPrivacy::Private %>
|
||||
<i class="icon ion-ios-lock"></i> <%= translate(locale, "Private") %>
|
||||
<% end %>
|
||||
</b>
|
||||
<% else %>
|
||||
<b>
|
||||
<a href="/channel/<%= playlist.ucid %>"><%= playlist.author %></a> |
|
||||
<%= translate(locale, "`x` videos", "#{playlist.video_count}") %> |
|
||||
<%= translate(locale, "Updated `x` ago", recode_date(playlist.updated, locale)) %>
|
||||
</b>
|
||||
<% end %>
|
||||
<% if !playlist.is_a? InvidiousPlaylist %>
|
||||
<div class="pure-u-2-3">
|
||||
<a href="https://www.youtube.com/playlist?list=<%= playlist.id %>">
|
||||
<%= translate(locale, "View playlist on YouTube") %>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="pure-u-1-3" style="text-align:right">
|
||||
<h3>
|
||||
<a href="/feed/playlist/<%= plid %>"><i class="icon ion-logo-rss"></i></a>
|
||||
<div class="pure-g user-field">
|
||||
<% 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>
|
||||
<% end %>
|
||||
<div class="pure-u-1-3"><a href="/feed/playlist/<%= plid %>"><i class="icon ion-logo-rss"></i></a></div>
|
||||
</div>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-1-3">
|
||||
<a href="https://www.youtube.com/playlist?list=<%= playlist.id %>">
|
||||
<%= translate(locale, "View playlist on YouTube") %>
|
||||
</a>
|
||||
<div class="pure-u-1 pure-md-1-3">
|
||||
<a href="/channel/<%= playlist.ucid %>">
|
||||
<b><%= playlist.author %></b>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1-2"></div>
|
||||
</div>
|
||||
|
||||
<div class="h-box">
|
||||
<p><%= playlist.description_html %></p>
|
||||
</div>
|
||||
|
||||
<% if playlist.is_a?(InvidiousPlaylist) && playlist.author == user.try &.email %>
|
||||
<div class="h-box" style="text-align:right">
|
||||
<h3>
|
||||
<a href="/add_playlist_items?list=<%= plid %>"><i class="icon ion-md-add"></i></a>
|
||||
</h3>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="h-box">
|
||||
<hr>
|
||||
</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>
|
||||
<script src="/js/playlist_widget.js"></script>
|
||||
<% end %>
|
||||
|
||||
<div class="pure-g">
|
||||
<% videos.each_slice(4) do |slice| %>
|
||||
<% slice.each do |item| %>
|
||||
|
||||
@@ -261,6 +261,10 @@ function update_value(element) {
|
||||
<a href="/token_manager"><%= translate(locale, "Manage tokens") %></a>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<a href="/view_all_playlists"><%= translate(locale, "View all playlists") %></a>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<a href="/feed/history"><%= translate(locale, "Watch history") %></a>
|
||||
</div>
|
||||
|
||||
22
src/invidious/views/view_all_playlists.ecr
Normal file
22
src/invidious/views/view_all_playlists.ecr
Normal file
@@ -0,0 +1,22 @@
|
||||
<% content_for "header" do %>
|
||||
<title><%= translate(locale, "Playlists") %> - Invidious</title>
|
||||
<% end %>
|
||||
|
||||
<div class="pure-g h-box">
|
||||
<div class="pure-u-2-3">
|
||||
<h3><%= translate(locale, "`x` playlists", %(<span id="count">#{items.size}</span>)) %></h3>
|
||||
</div>
|
||||
<div class="pure-u-1-3" style="text-align:right">
|
||||
<h3>
|
||||
<a href="/create_playlist?referer=<%= URI.encode_www_form(referer) %>"><%= translate(locale, "Create playlist") %></a>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g">
|
||||
<% items.each_slice(4) do |slice| %>
|
||||
<% slice.each do |item| %>
|
||||
<%= rendered "components/item" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -29,6 +29,7 @@
|
||||
<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 %>,
|
||||
|
||||
Reference in New Issue
Block a user