mirror of
https://github.com/iv-org/invidious.git
synced 2024-12-02 11:41:08 +05:30
Use ion for arrow swap icons
This commit is contained in:
parent
a8c0023eb0
commit
890802481b
@ -46,3 +46,18 @@ function remove_compilation_item(target) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function move_compilation_video_before(target) {
|
||||||
|
var tile = target.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
|
tile.style.display = 'none';
|
||||||
|
|
||||||
|
var url = '/compilation_ajax?action_move_video_before=1&redirect=false' +
|
||||||
|
'&set_video_id=' + target.getAttribute('data-index') +
|
||||||
|
'&compilation_id=' + target.getAttribute('data-compid');
|
||||||
|
|
||||||
|
helpers.xhr('POST', url, {payload: payload}, {
|
||||||
|
onNon200: function (xhr) {
|
||||||
|
tile.style.display = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -179,7 +179,10 @@
|
|||||||
"Playlist privacy": "Playlist privacy",
|
"Playlist privacy": "Playlist privacy",
|
||||||
"Compilation privacy": "Compilation privacy",
|
"Compilation privacy": "Compilation privacy",
|
||||||
"Editing playlist `x`": "Editing playlist `x`",
|
"Editing playlist `x`": "Editing playlist `x`",
|
||||||
|
"Editing compilation `x`": "Editing compilation `x`",
|
||||||
"playlist_button_add_items": "Add videos",
|
"playlist_button_add_items": "Add videos",
|
||||||
|
"compilation_button_add_items": "Add videos",
|
||||||
|
"compilation_button_play": "Play",
|
||||||
"Show more": "Show more",
|
"Show more": "Show more",
|
||||||
"Show less": "Show less",
|
"Show less": "Show less",
|
||||||
"Watch on YouTube": "Watch on YouTube",
|
"Watch on YouTube": "Watch on YouTube",
|
||||||
|
@ -244,7 +244,7 @@ end
|
|||||||
|
|
||||||
def create_compilation(title, privacy, user)
|
def create_compilation(title, privacy, user)
|
||||||
LOGGER.info("2. create_compilation")
|
LOGGER.info("2. create_compilation")
|
||||||
compid = "IVPL#{Random::Secure.urlsafe_base64(24)[0, 31]}"
|
compid = "IVCMP#{Random::Secure.urlsafe_base64(24)[0, 31]}"
|
||||||
LOGGER.info("generated compilation id")
|
LOGGER.info("generated compilation id")
|
||||||
|
|
||||||
compilation = InvidiousCompilation.new({
|
compilation = InvidiousCompilation.new({
|
||||||
@ -320,7 +320,7 @@ def produce_compilation_continuation(id, index)
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get_compilation(compid : String)
|
def get_compilation(compid : String)
|
||||||
#if compid.starts_with? "IV"
|
#if compid.starts_with? "IVCMP"
|
||||||
if compilation = Invidious::Database::Compilations.select(id: compid)
|
if compilation = Invidious::Database::Compilations.select(id: compid)
|
||||||
return compilation
|
return compilation
|
||||||
else
|
else
|
||||||
|
@ -197,11 +197,31 @@ module Invidious::Routes::Compilations
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.adjust_timestamps(env)
|
def self.adjust_timestamps(env)
|
||||||
|
locale = env.get("preferences").as(Preferences).locale
|
||||||
LOGGER.info("Handle POST request for edit compilation")
|
LOGGER.info("Handle POST request for edit compilation")
|
||||||
env.response.content_type = "application/json"
|
env.response.content_type = "application/json"
|
||||||
user = env.get("user").as(User)
|
user = env.get("user")
|
||||||
|
sid = env.get? "sid"
|
||||||
|
|
||||||
|
referer = get_referer(env)
|
||||||
|
|
||||||
|
return env.redirect "/" if user.nil?
|
||||||
|
|
||||||
compid = env.params.query["list"]?
|
compid = env.params.query["list"]?
|
||||||
|
return env.redirect referer if compid.nil?
|
||||||
|
|
||||||
|
user = user.as(User)
|
||||||
|
|
||||||
|
sid = sid.as(String)
|
||||||
|
token = env.params.body["csrf_token"]?
|
||||||
|
|
||||||
|
begin
|
||||||
|
validate_request(token, sid, env.request, HMAC_KEY, locale)
|
||||||
|
rescue ex
|
||||||
|
return error_template(400, ex)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
if !compid || compid.empty?
|
if !compid || compid.empty?
|
||||||
return error_json(400, "A compilation ID is required")
|
return error_json(400, "A compilation ID is required")
|
||||||
end
|
end
|
||||||
@ -215,6 +235,9 @@ module Invidious::Routes::Compilations
|
|||||||
return error_json(403, "Invalid user")
|
return error_json(403, "Invalid user")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
title = env.params.body["title"]?.try &.delete("<>") || ""
|
||||||
|
privacy = CompilationPrivacy.parse(env.params.body["privacy"]? || "Private")
|
||||||
|
|
||||||
#title = env.params.json["title"].try &.as(String).delete("<>").byte_slice(0, 150) || compilation.title
|
#title = env.params.json["title"].try &.as(String).delete("<>").byte_slice(0, 150) || compilation.title
|
||||||
#privacy = env.params.json["privacy"]?.try { |p| CompilationPrivacy.parse(p.as(String).downcase) } || compilation.privacy
|
#privacy = env.params.json["privacy"]?.try { |p| CompilationPrivacy.parse(p.as(String).downcase) } || compilation.privacy
|
||||||
|
|
||||||
@ -225,6 +248,8 @@ module Invidious::Routes::Compilations
|
|||||||
# updated = compilation.updated
|
# updated = compilation.updated
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
Invidious::Database::Compilations.update(compid, title, privacy, "", compilation.updated)
|
||||||
|
|
||||||
#{1...Invidious::Database::Compilations.count_owned_by(user.email)}.each do |index|
|
#{1...Invidious::Database::Compilations.count_owned_by(user.email)}.each do |index|
|
||||||
# start_timestamp = env.params.json["_start_timestamp"]?.try &.as(String).byte_slice(0, 150) || compilation.title
|
# start_timestamp = env.params.json["_start_timestamp"]?.try &.as(String).byte_slice(0, 150) || compilation.title
|
||||||
compilation_video_cardinality = Invidious::Database::CompilationVideos.select_ids(compid, compilation.index).size
|
compilation_video_cardinality = Invidious::Database::CompilationVideos.select_ids(compid, compilation.index).size
|
||||||
@ -238,7 +263,7 @@ module Invidious::Routes::Compilations
|
|||||||
json_timestamp_query = index.to_s + "_start_timestamp"
|
json_timestamp_query = index.to_s + "_start_timestamp"
|
||||||
LOGGER.info("adjust #{json_timestamp_query} ")
|
LOGGER.info("adjust #{json_timestamp_query} ")
|
||||||
start_timestamp = env.params.body[json_timestamp_query]?.try &.as(String).byte_slice(0, 8)
|
start_timestamp = env.params.body[json_timestamp_query]?.try &.as(String).byte_slice(0, 8)
|
||||||
LOGGER.info("render #{env.params.body[json_timestamp_query]} ")
|
LOGGER.info("render #{env.params.body[json_timestamp_query]?} ")
|
||||||
if !start_timestamp.nil? && !compilation_video_id.nil?
|
if !start_timestamp.nil? && !compilation_video_id.nil?
|
||||||
LOGGER.info("adjust #{json_timestamp_query} which renders as #{start_timestamp}")
|
LOGGER.info("adjust #{json_timestamp_query} which renders as #{start_timestamp}")
|
||||||
start_timestamp_seconds = decode_length_seconds(start_timestamp)
|
start_timestamp_seconds = decode_length_seconds(start_timestamp)
|
||||||
@ -353,6 +378,8 @@ module Invidious::Routes::Compilations
|
|||||||
action = "action_remove_video"
|
action = "action_remove_video"
|
||||||
elsif env.params.query["action_move_video_before"]?
|
elsif env.params.query["action_move_video_before"]?
|
||||||
action = "action_move_video_before"
|
action = "action_move_video_before"
|
||||||
|
elsif env.params.query["action_move_video_after"]?
|
||||||
|
action = "action_move_video_after"
|
||||||
else
|
else
|
||||||
return env.redirect referer
|
return env.redirect referer
|
||||||
end
|
end
|
||||||
|
@ -6,9 +6,43 @@
|
|||||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/compilation/<%= compid %>" />
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/compilation/<%= compid %>" />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<div class="h-box flexible title">
|
||||||
|
<div class="flex-left"><h3><%= title %></h3></div>
|
||||||
|
|
||||||
|
<div class="flex-right button-container">
|
||||||
|
<%- if compilation.is_a?(InvidiousCompilation) && compilation.author == user.try &.email -%>
|
||||||
|
<div class="pure-u">
|
||||||
|
<a class="pure-button pure-button-secondary low-profile" dir="auto" href="/play_compilation?list=<%= compid %>">
|
||||||
|
<i class="icon ion-md-play"></i> <%= translate(locale, "compilation_button_play") %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="pure-u">
|
||||||
|
<a class="pure-button pure-button-secondary low-profile" dir="auto" href="/add_compilation_items?list=<%= compid %>">
|
||||||
|
<i class="icon ion-md-add"></i> <%= translate(locale, "compilation_button_add_items") %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="pure-u">
|
||||||
|
<a class="pure-button pure-button-secondary low-profile" dir="auto" href="/edit_compilation?list=<%= compid %>">
|
||||||
|
<i class="icon ion-md-create"></i> <%= translate(locale, "generic_button_edit") %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="pure-u">
|
||||||
|
<a class="pure-button pure-button-secondary low-profile" dir="auto" href="/delete_compilation?list=<%= compid %>">
|
||||||
|
<i class="icon ion-md-trash"></i> <%= translate(locale, "generic_button_delete") %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<div class="pure-u">
|
||||||
|
<a class="pure-button pure-button-secondary low-profile" dir="auto" href="/feed/compilation/<%= compid %>">
|
||||||
|
<i class="icon ion-logo-rss"></i> <%= translate(locale, "generic_button_rss") %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="pure-g h-box">
|
<div class="pure-g h-box">
|
||||||
<div class="pure-u-2-3">
|
<div class="pure-u-1-1">
|
||||||
<h3><%= title %></h3>
|
|
||||||
<% if compilation.is_a? InvidiousCompilation %>
|
<% if compilation.is_a? InvidiousCompilation %>
|
||||||
<b>
|
<b>
|
||||||
<% if compilation.author == user.try &.email %>
|
<% if compilation.author == user.try &.email %>
|
||||||
@ -33,35 +67,12 @@
|
|||||||
</b>
|
</b>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="pure-u-1-3" style="text-align:right">
|
|
||||||
<h3>
|
|
||||||
<div class="pure-g user-field">
|
|
||||||
<% if compilation.is_a?(InvidiousCompilation) && compilation.author == user.try &.email %>
|
|
||||||
<div class="pure-u-1-3"><a href="/edit_compilation?list=<%= compid %>"><i class="icon ion-md-create"></i></a></div>
|
|
||||||
<div class="pure-u-1-3"><a href="/delete_compilation?list=<%= compid %>"><i class="icon ion-md-trash"></i></a></div>
|
|
||||||
<% else %>
|
|
||||||
<% if !Invidious::Database::Compilations.exists?(compilation.id) %>
|
|
||||||
<div class="pure-u-1-3"><a href="/delete_compilation?list=<%= compid %>"><i class="icon ion-md-trash"></i></a></div>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
<div class="pure-u-1-3"><a href="/feed/compilation/<%= compid %>"><i class="icon ion-logo-rss"></i></a></div>
|
|
||||||
</div>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<div id="descriptionWrapper"><%= compilation.description_html %></div>
|
<div id="descriptionWrapper"><%= compilation.description_html %></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if compilation.is_a?(InvidiousCompilation) && compilation.author == user.try &.email %>
|
|
||||||
<div class="h-box" style="text-align:right">
|
|
||||||
<h3>
|
|
||||||
<a href="/add_compilation_items?list=<%= compid %>"><i class="icon ion-md-add"></i></a>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<hr>
|
<hr>
|
||||||
</div>
|
</div>
|
||||||
@ -82,23 +93,3 @@
|
|||||||
<%= rendered "components/compilation_video" %>
|
<%= rendered "components/compilation_video" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/watched_indicator.js"></script>
|
|
||||||
|
|
||||||
<div class="pure-g h-box">
|
|
||||||
<div class="pure-u-1 pure-u-lg-1-5">
|
|
||||||
<% if page > 1 %>
|
|
||||||
<a href="/compilation?complist=<%= compilation.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 page_count != 1 && page < page_count %>
|
|
||||||
<a href="/compilation?complist=<%= compilation.id %>&page=<%= page + 1 %>">
|
|
||||||
<%= translate(locale, "Next page") %>
|
|
||||||
</a>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -2,12 +2,25 @@
|
|||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<div class="compilation-video-panel">
|
<div class="compilation-video-panel">
|
||||||
<div class="compilation-order-swap-arrows">
|
<div class="compilation-order-swap-arrows">
|
||||||
<svg class="compilation-video-swap-arrow">
|
<%- form_parameters = "action_move_video_before=1&set_video_id=#{compilation_video.index}&compilation_id=#{compilation_video.compid}&referer=#{env.get("current_page")}" -%>
|
||||||
<path d="M7.41 15.41 12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path>
|
<form data-onsubmit="return_false" action="/compilation_ajax?<%= form_parameters %>" method="post">
|
||||||
</svg>
|
<input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
<svg class="compilation-video-swap-arrow">
|
<button type="submit" style="margin:10px" class="pure-button pure-button-secondary low-profile"
|
||||||
<path d="M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"></path>
|
data-onclick="move_compilation_video_before" data-index="<%= compilation_video.index %>" data-compid="<%= compilation_video.compid %>">
|
||||||
</svg>
|
<!-- <svg class="compilation-video-swap-arrow">
|
||||||
|
<path d="M7.41 15.41 12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path>
|
||||||
|
</svg> -->
|
||||||
|
<i class="icon ion-md-arrow-up"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<%- form_parameters = "action_move_video_after=1&set_video_id=#{compilation_video.index}&compilation_id=#{compilation_video.compid}&referer=#{env.get("current_page")}" -%>
|
||||||
|
<form data-onsubmit="return_false" action="/compilation_ajax?<%= form_parameters %>" method="post">
|
||||||
|
<input type="hidden" name="csrf_token" value="<%= HTML.escape(env.get?("csrf_token").try &.as(String) || "") %>">
|
||||||
|
<button type="submit" style="margin:10px" class="pure-button pure-button-secondary low-profile"
|
||||||
|
data-onclick="move_compilation_video_after" data-index="<%= compilation_video.index %>" data-compid="<%= compilation_video.compid %>">
|
||||||
|
<i class="icon ion-md-arrow-down"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<img loading="lazy" style="margin:10px;" src="/vi/<%= compilation_video.id %>/mqdefault.jpg" alt="" />
|
<img loading="lazy" style="margin:10px;" src="/vi/<%= compilation_video.id %>/mqdefault.jpg" alt="" />
|
||||||
<!-- <div class="compilation-video-thumbnail">
|
<!-- <div class="compilation-video-thumbnail">
|
||||||
|
@ -57,8 +57,10 @@
|
|||||||
<%-
|
<%-
|
||||||
if item.id.starts_with? "RD"
|
if item.id.starts_with? "RD"
|
||||||
link_url = "/mix?list=#{item.id}&continuation=#{URI.parse(item.thumbnail || "/vi/-----------").request_target.split("/")[2]}"
|
link_url = "/mix?list=#{item.id}&continuation=#{URI.parse(item.thumbnail || "/vi/-----------").request_target.split("/")[2]}"
|
||||||
else
|
elsif item.id.starts_with? "IVCMP"
|
||||||
link_url = "/compilation?list=#{item.id}"
|
link_url = "/compilation?list=#{item.id}"
|
||||||
|
else
|
||||||
|
link_url = "/playlist?list=#{item.id}"
|
||||||
end
|
end
|
||||||
-%>
|
-%>
|
||||||
|
|
||||||
|
@ -2,53 +2,52 @@
|
|||||||
|
|
||||||
<% content_for "header" do %>
|
<% content_for "header" do %>
|
||||||
<title><%= title %> - Invidious </title>
|
<title><%= title %> - Invidious </title>
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed/compilation/<%= compid %>" />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<form action="/edit_compilation?list=<%= compid %>" method="post">
|
<form action="/edit_compilation?list=<%= compid %>" method="post">
|
||||||
<div class="pure-g h-box">
|
<div class="h-box flexible">
|
||||||
<div class="pure-u-2-3">
|
<div class="flex-right button-container">
|
||||||
|
<div class="pure-u">
|
||||||
|
<a class="pure-button pure-button-secondary low-profile" dir="auto" href="/compilation?list=<%= compid %>">
|
||||||
|
<i class="icon ion-md-close"></i> <%= translate(locale, "generic_button_cancel") %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="pure-u">
|
||||||
|
<button class="pure-button pure-button-secondary low-profile" dir="auto" type="submit">
|
||||||
|
<i class="icon ion-md-save"></i> <%= translate(locale, "generic_button_save") %>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="pure-u">
|
||||||
|
<a class="pure-button pure-button-secondary low-profile" dir="auto" href="/delete_compilation?list=<%= compid %>">
|
||||||
|
<i class="icon ion-md-trash"></i> <%= translate(locale, "generic_button_delete") %>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="h-box flexible title">
|
||||||
|
<div>
|
||||||
<h3><input class="pure-input-1" maxlength="150" name="title" type="text" value="<%= title %>"></h3>
|
<h3><input class="pure-input-1" maxlength="150" name="title" type="text" value="<%= title %>"></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="h-box">
|
||||||
|
<div class="pure-u-1-1">
|
||||||
<b>
|
<b>
|
||||||
<%= HTML.escape(compilation.author) %> |
|
<%= HTML.escape(compilation.author) %> |
|
||||||
<%= translate_count(locale, "generic_videos_count", compilation.video_count) %> |
|
<%= translate_count(locale, "generic_videos_count", compilation.video_count) %> |
|
||||||
<%= translate(locale, "Updated `x` ago", recode_date(compilation.updated, locale)) %> |
|
|
||||||
<i class="icon <%= {"ion-md-globe", "ion-ios-unlock", "ion-ios-lock"}[compilation.privacy.value] %>"></i>
|
|
||||||
<select name="privacy">
|
|
||||||
<% {"Unlisted", "Private"}.each do |option| %>
|
|
||||||
<option value="<%= option %>" <% if option == compilation.privacy.to_s %>selected<% end %>><%= translate(locale, option) %></option>
|
|
||||||
<% end %>
|
|
||||||
</select>
|
|
||||||
</b>
|
</b>
|
||||||
</div>
|
<select name="privacy">
|
||||||
<div class="pure-u-1-3" style="text-align:right">
|
<%- {"Unlisted", "Private"}.each do |option| -%>
|
||||||
<h3>
|
<option value="<%= option %>" <% if option == compilation.privacy.to_s %>selected<% end %>><%= translate(locale, option) %></option>
|
||||||
<div class="pure-g user-field">
|
<%- end -%>
|
||||||
<div class="pure-u-1-3">
|
</select>
|
||||||
<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_compilation?list=<%= compid %>"><i class="icon ion-md-trash"></i></a></div>
|
|
||||||
</div>
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="h-box">
|
|
||||||
<textarea maxlength="5000" name="description" style="margin-top:10px;max-width:100%;height:20vh" class="pure-input-1"><%= compilation.description %></textarea>
|
|
||||||
</div> -->
|
|
||||||
<input type="hidden" name="csrf_token" value="<%= HTML.escape(csrf_token) %>">
|
<input type="hidden" name="csrf_token" value="<%= HTML.escape(csrf_token) %>">
|
||||||
|
|
||||||
<% if compilation.is_a?(InvidiousCompilation) && compilation.author == user.try &.email %>
|
|
||||||
<div class="h-box" style="text-align:right">
|
|
||||||
<h3>
|
|
||||||
<a href="/add_compilation_items?list=<%= compid %>"><i class="icon ion-md-add"></i></a>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<div class="h-box">
|
<div class="h-box">
|
||||||
<hr>
|
<hr>
|
||||||
</div>
|
</div>
|
||||||
@ -65,3 +64,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user