mirror of
https://github.com/openvk/openvk
synced 2024-11-15 03:31:18 +03:00
search: a bit refactor 2
This commit is contained in:
parent
8286173ed3
commit
4e5bd6433f
19 changed files with 182 additions and 74 deletions
|
@ -162,6 +162,7 @@ class Playlist extends MediaCollection
|
|||
"bookmarked" => $this->isBookmarkedBy($user),
|
||||
"listens" => $this->getListens(),
|
||||
"cover_url" => $this->getCoverURL(),
|
||||
"searchable" => !$this->isUnlisted(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -258,4 +259,9 @@ class Playlist extends MediaCollection
|
|||
|
||||
return implode(" • ", $props);
|
||||
}
|
||||
|
||||
function isUnlisted(): bool
|
||||
{
|
||||
return (bool)$this->getRecord()->unlisted;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ trait TRichText
|
|||
$text = preg_replace_callback("%([\n\r\s]|^)(\#([\p{L}_0-9][\p{L}_0-9\(\)\-\']+[\p{L}_0-9\(\)]|[\p{L}_0-9]{1,2}))%Xu", function($m) {
|
||||
$slug = rawurlencode($m[3]);
|
||||
|
||||
return "$m[1]<a href='/feed/hashtag/$slug'>$m[2]</a>";
|
||||
return "$m[1]<a href='/search?section=posts&q=%23$slug'>$m[2]</a>";
|
||||
}, $text);
|
||||
|
||||
$text = $this->formatEmojis($text);
|
||||
|
|
|
@ -219,6 +219,7 @@ class Audios
|
|||
function searchPlaylists(string $query): EntityStream
|
||||
{
|
||||
$search = $this->playlists->where([
|
||||
"unlisted" => 0,
|
||||
"deleted" => 0,
|
||||
])->where("MATCH (`name`, `description`) AGAINST (? IN BOOLEAN MODE)", $query);
|
||||
|
||||
|
@ -296,9 +297,28 @@ class Audios
|
|||
return new Util\EntityStream("Audio", $result);
|
||||
}
|
||||
|
||||
function findPlaylists(string $query, int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
function findPlaylists(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): \Traversable
|
||||
{
|
||||
$result = $this->playlists->where("name LIKE ?", "%$query%");
|
||||
$result = $this->playlists->where([
|
||||
"unlisted" => 0,
|
||||
"deleted" => 0,
|
||||
])->where("CONCAT_WS(' ', name, description) LIKE ?", "%$query%");
|
||||
$order_str = 'id';
|
||||
|
||||
switch($order['type']) {
|
||||
case 'id':
|
||||
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
case 'length':
|
||||
$order_str = 'length ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
case 'listens':
|
||||
$order_str = 'listens ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
}
|
||||
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("Playlist", $result);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
if (!$entity || $entity->isBanned())
|
||||
$this->redirect("/playlists" . $this->user->id);
|
||||
|
||||
$playlists = $this->audios->getPlaylistsByClub($entity, $page, 10);
|
||||
$playlists = $this->audios->getPlaylistsByClub($entity, $page, OPENVK_DEFAULT_PER_PAGE);
|
||||
$playlistsCount = $this->audios->getClubPlaylistsCount($entity);
|
||||
} else {
|
||||
$entity = (new Users)->get($owner);
|
||||
|
@ -85,7 +85,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
if(!$entity->getPrivacyPermission("audios.read", $this->user->identity))
|
||||
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||
|
||||
$playlists = $this->audios->getPlaylistsByUser($entity, $page, 9);
|
||||
$playlists = $this->audios->getPlaylistsByUser($entity, $page, OPENVK_DEFAULT_PER_PAGE);
|
||||
$playlistsCount = $this->audios->getUserPlaylistsCount($entity);
|
||||
}
|
||||
|
||||
|
@ -304,6 +304,8 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$title = $this->postParam("title");
|
||||
$description = $this->postParam("description");
|
||||
$is_unlisted = (int)$this->postParam('is_unlisted');
|
||||
|
||||
$audios = !empty($this->postParam("audios")) ? array_slice(explode(",", $this->postParam("audios")), 0, 1000) : [];
|
||||
|
||||
if(empty($title) || iconv_strlen($title) < 1)
|
||||
|
@ -313,6 +315,8 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$playlist->setOwner($owner);
|
||||
$playlist->setName(substr($title, 0, 125));
|
||||
$playlist->setDescription(substr($description, 0, 2045));
|
||||
if($is_unlisted == 1)
|
||||
$playlist->setUnlisted(true);
|
||||
|
||||
if($_FILES["cover"]["error"] === UPLOAD_ERR_OK) {
|
||||
if(!str_starts_with($_FILES["cover"]["type"], "image"))
|
||||
|
@ -427,6 +431,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
|
||||
$title = $this->postParam("title");
|
||||
$description = $this->postParam("description");
|
||||
$is_unlisted = (int)$this->postParam('is_unlisted');
|
||||
$new_audios = !empty($this->postParam("audios")) ? explode(",", rtrim($this->postParam("audios"), ",")) : [];
|
||||
|
||||
if(empty($title) || iconv_strlen($title) < 1)
|
||||
|
@ -436,6 +441,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$playlist->setDescription(ovk_proc_strtr($description, 2045));
|
||||
$playlist->setEdited(time());
|
||||
$playlist->resetLength();
|
||||
$playlist->setUnlisted((bool)$is_unlisted);
|
||||
|
||||
if($_FILES["new_cover"]["error"] === UPLOAD_ERR_OK) {
|
||||
if(!str_starts_with($_FILES["new_cover"]["type"], "image"))
|
||||
|
@ -476,12 +482,14 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$this->template->playlist = $playlist;
|
||||
$this->template->page = $page;
|
||||
$this->template->cover = $playlist->getCoverPhoto();
|
||||
$this->template->cover_url = $this->template->cover ? $this->template->cover->getURL() : "/assets/packages/static/openvk/img/song.jpg";
|
||||
$this->template->audios = iterator_to_array($playlist->fetch($page, 10));
|
||||
$this->template->ownerId = $owner_id;
|
||||
$this->template->owner = $playlist->getOwner();
|
||||
$this->template->isBookmarked = $this->user->identity && $playlist->isBookmarkedBy($this->user->identity);
|
||||
$this->template->isMy = $this->user->identity && $playlist->getOwner()->getId() === $this->user->id;
|
||||
$this->template->canEdit = $this->user->identity && $playlist->canBeModifiedBy($this->user->identity);
|
||||
$this->template->count = $playlist->size();
|
||||
}
|
||||
|
||||
function renderAction(int $audio_id): void
|
||||
|
|
|
@ -48,7 +48,8 @@ final class SearchPresenter extends OpenVKPresenter
|
|||
"comments" => "comments",
|
||||
"videos" => "videos",
|
||||
"audios" => "audios",
|
||||
"apps" => "apps"
|
||||
"apps" => "apps",
|
||||
"audios_playlists" => "audios"
|
||||
];
|
||||
$parameters = [
|
||||
"ignore_private" => true,
|
||||
|
@ -92,7 +93,16 @@ final class SearchPresenter extends OpenVKPresenter
|
|||
|
||||
$repo = $repos[$section] or $this->throwError(400, "Bad Request", "Invalid search entity $section.");
|
||||
|
||||
$results = $this->{$repo}->find($query, $parameters, ['type' => $order, 'invert' => $invert]);
|
||||
$results = NULL;
|
||||
switch($section) {
|
||||
default:
|
||||
$results = $this->{$repo}->find($query, $parameters, ['type' => $order, 'invert' => $invert]);
|
||||
break;
|
||||
case 'audios_playlists':
|
||||
$results = $this->{$repo}->findPlaylists($query, $parameters, ['type' => $order, 'invert' => $invert]);
|
||||
break;
|
||||
}
|
||||
|
||||
$iterator = $results->page($page, OPENVK_DEFAULT_PER_PAGE);
|
||||
$count = $results->size();
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@
|
|||
<option n:attr="selected => $_REQUEST['section'] == 'videos'" value="videos">{_s_by_videos}</option>
|
||||
<option n:attr="selected => $_REQUEST['section'] == 'apps'" value="apps">{_s_by_apps}</option>
|
||||
<option n:attr="selected => $_REQUEST['section'] == 'audios'" value="audios">{_s_by_audios}</option>
|
||||
<option n:attr="selected => $_REQUEST['section'] == 'playlists'" value="playlists">{_s_by_audios_playlists}</option>
|
||||
<option n:attr="selected => $_REQUEST['section'] == 'audios_playlists'" value="audios_playlists">{_s_by_audios_playlists}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="search_box_button">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{block header}
|
||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios{$ownerId}">{_audios}</a>
|
||||
<a href="/playlists{$ownerId}">{_playlists}</a>
|
||||
»
|
||||
<a href="/playlist{$playlist->getPrettyId()}">{_playlist}</a>
|
||||
»
|
||||
|
@ -30,8 +30,13 @@
|
|||
</div>
|
||||
|
||||
<div class="moreInfo">
|
||||
<textarea name="description" maxlength="2045" style="margin-top: 11px;">{$playlist->getDescription()}</textarea>
|
||||
<textarea placeholder="{_description}" name="description" maxlength="2045" style="margin-top: 11px;">{$playlist->getDescription()}</textarea>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
<input type='checkbox' name='is_unlisted' n:attr='checked => $playlist->isUnlisted()'>
|
||||
{_playlist_hide_from_search}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -56,6 +61,7 @@
|
|||
<form method="post" id="editPlaylistForm" data-id="{$playlist->getId()}" enctype="multipart/form-data">
|
||||
<input type="hidden" name="title" maxlength="128" />
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input type="hidden" name="is_unlisted" value="0" />
|
||||
<textarea style="display:none;" name="description" maxlength="2048" />
|
||||
<input type="hidden" name="audios">
|
||||
<input type="file" style="display:none;" name="new_cover" accept=".jpg,.png">
|
||||
|
@ -71,6 +77,7 @@
|
|||
u("#editPlaylistForm").on("submit", (e) => {
|
||||
document.querySelector("#editPlaylistForm input[name='title']").value = document.querySelector(".playlistInfo input[name='title']").value
|
||||
document.querySelector("#editPlaylistForm textarea[name='description']").value = document.querySelector(".playlistBlock textarea[name='description']").value
|
||||
document.querySelector("#editPlaylistForm input[name='is_unlisted']").value = document.querySelector("input[name='is_unlisted']").checked ? 1 : 0
|
||||
})
|
||||
|
||||
u("#editPlaylistForm input[name='new_cover']").on("change", (e) => {
|
||||
|
|
|
@ -81,30 +81,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div style="width: 74%;" class="audiosPaddingContainer" n:if="$mode == 'playlists'">
|
||||
<div style="width: 71.8%;" class="audiosPaddingContainer audiosPaddingContainer" n:if="$mode == 'playlists'">
|
||||
<div n:if="$playlistsCount <= 0" style='height: 100%;'>
|
||||
{include "../components/content_error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_playlists_thisuser") : tr("no_playlists_user")) : tr("no_playlists_club")}
|
||||
</div>
|
||||
|
||||
<div class="infContainer playlistContainer" n:if="$playlistsCount > 0">
|
||||
<div n:foreach="$playlists as $playlist">
|
||||
<a href="/playlist{$playlist->getPrettyId()}">
|
||||
<div class="playlistCover">
|
||||
<img src="{$playlist->getCoverURL()}" alt="{_playlist_cover}">
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
<div class="playlistInfo">
|
||||
<a href="/playlist{$playlist->getPrettyId()}">
|
||||
<span style="font-size: 12px" class="playlistName">
|
||||
{ovk_proc_strtr($playlist->getName(), 15)}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a href="{$playlist->getOwner()->getURL()}">{ovk_proc_strtr($playlist->getOwner()->getCanonicalName(), 20)}</a>
|
||||
</div>
|
||||
</div>
|
||||
{foreach $playlists as $playlist}
|
||||
{include 'playlistListView.xml', playlist => $playlist}
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
{if !$_GET["gid"]}
|
||||
<a href="{$thisUser->getURL()}">{$thisUser->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios{$thisUser->getId()}">{_audios}</a>
|
||||
<a href="/playlists{$thisUser->getId()}">{_playlists}</a>
|
||||
{else}
|
||||
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios-{$club->getId()}">{_audios}</a>
|
||||
<a href="/playlists-{$club->getId()}">{_playlists}</a>
|
||||
{/if}
|
||||
»
|
||||
{_new_playlist}
|
||||
|
@ -44,6 +44,10 @@
|
|||
<div class="moreInfo" style="margin-top: 11px;">
|
||||
<textarea placeholder="{_description}" name="description" maxlength="2045" />
|
||||
</div>
|
||||
<label>
|
||||
<input type='checkbox' name='is_unlisted'>
|
||||
{_playlist_hide_from_search}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -68,6 +72,7 @@
|
|||
<form method="post" id="newPlaylistForm" enctype="multipart/form-data">
|
||||
<input type="hidden" name="title" maxlength="125" />
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input type="hidden" name="is_unlisted" value="0" />
|
||||
<textarea style="display:none;" name="description" maxlength="2045" />
|
||||
<input type="hidden" name="audios">
|
||||
<input type="file" style="display:none;" name="cover" accept=".jpg,.png">
|
||||
|
@ -83,6 +88,7 @@
|
|||
u("#newPlaylistForm").on("submit", (e) => {
|
||||
document.querySelector("#newPlaylistForm input[name='title']").value = document.querySelector(".plinfo input[name='title']").value
|
||||
document.querySelector("#newPlaylistForm textarea[name='description']").value = document.querySelector(".plinfo textarea[name='description']").value
|
||||
document.querySelector("#newPlaylistForm input[name='is_unlisted']").value = document.querySelector(".plinfo input[name='is_unlisted']").checked ? 1 : 0
|
||||
})
|
||||
|
||||
u("#newPlaylistForm input[name='cover']").on("change", (e) => {
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
{extends "../@layout.xml"}
|
||||
|
||||
{block title}{_playlist}{/block}
|
||||
{block title}
|
||||
{_playlist}
|
||||
{$playlist->getName()}
|
||||
{/block}
|
||||
|
||||
{block headIncludes}
|
||||
<meta property="og:type" content="music.album">
|
||||
<meta property="og:title" content="{$playlist->getName()}">
|
||||
<meta property="og:url" content="{$playlist->getURL()}">
|
||||
<meta property="og:description" content="{$playlist->getDescription()}">
|
||||
<meta property="og:image" content="{$playlist->getCoverURL()}">
|
||||
<meta property="og:image" content="{$cover_url}">
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
|
@ -22,7 +25,7 @@
|
|||
{block header}
|
||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios{$ownerId}">{_audios}</a>
|
||||
<a href="/playlists{$ownerId}">{_playlists}</a>
|
||||
»
|
||||
{_playlist}
|
||||
{/block}
|
||||
|
@ -30,23 +33,27 @@
|
|||
{block content}
|
||||
{include "bigplayer.xml"}
|
||||
|
||||
{php $count = $playlist->size()}
|
||||
|
||||
<input type="hidden" name="bigplayer_context" data-type="playlist_context" data-entity="{$playlist->getId()}" data-page="{$page}">
|
||||
<div class="playlistBlock">
|
||||
<div class="playlistCover" style="float: left;">
|
||||
<a href="{$cover->getURL()}" target="_blank">
|
||||
<img onclick="OpenMiniature(event, {$cover->getURL()}, null, {$cover->getPrettyId()}, null)" src="{$playlist->getCoverURL('normal')}" alt="{_playlist_cover}">
|
||||
{if $cover}
|
||||
<a href="{$cover_url}" target="_blank">
|
||||
<img onclick="OpenMiniature(event, {$cover_url}, null, {$cover->getPrettyId()}, null)" src="{$cover_url}" alt="{_playlist_cover}">
|
||||
</a>
|
||||
{else}
|
||||
<a>
|
||||
<img src="{$cover_url}" alt="{_playlist_cover}">
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
<div class="profile_links" style="width: 139px;" n:if="isset($thisUser)">
|
||||
<a class="profile_link" style="width: 98%;" href="/playlist{$playlist->getPrettyId()}/edit" n:if="$playlist->canBeModifiedBy($thisUser)">{_edit_playlist}</a>
|
||||
<a class="profile_link" style="width: 98%;" id="bookmarkPlaylist" data-id="{$playlist->getId()}" n:if="!$isBookmarked">{_bookmark}</a>
|
||||
<a class="profile_link" style="width: 98%;" id="unbookmarkPlaylist" data-id="{$playlist->getId()}" n:if="$isBookmarked">{_unbookmark}</a>
|
||||
<div class="profile_links" n:if="isset($thisUser)">
|
||||
<a class="profile_link" href="/playlist{$playlist->getPrettyId()}/edit" n:if="$playlist->canBeModifiedBy($thisUser)">{_edit_playlist}</a>
|
||||
<a class="profile_link" id="bookmarkPlaylist" data-id="{$playlist->getId()}" n:if="!$isBookmarked">{_bookmark}</a>
|
||||
<a class="profile_link" id="unbookmarkPlaylist" data-id="{$playlist->getId()}" n:if="$isBookmarked">{_unbookmark}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="float: left;padding-left: 13px;width:75%">
|
||||
<div class='playlistWrapper'>
|
||||
<div class="playlistInfo">
|
||||
<h4 style="border-bottom:unset;">{$playlist->getName()}</h4>
|
||||
|
||||
|
|
20
Web/Presenters/templates/Audio/playlistListView.xml
Normal file
20
Web/Presenters/templates/Audio/playlistListView.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<a href="/playlist{$playlist->getPrettyId()}" class='playlistListView'>
|
||||
<div class="playlistCover">
|
||||
<img src="{$playlist->getCoverURL('normal')}" alt="{_playlist_cover}">
|
||||
</div>
|
||||
|
||||
<div class="playlistInfo">
|
||||
<div class="playlistInfoTopPart">
|
||||
<span class="playlistName noOverflow">
|
||||
{$playlist->getName(), 15}
|
||||
</span>
|
||||
<span n:if='!empty($playlist->getDescription())' class="playlistDesc noOverflow">
|
||||
{$playlist->getDescription()}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span class="playlistMeta">
|
||||
{$playlist->getMetaDescription()|noescape}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
<div class="additionalInfo">
|
||||
{php $audioStatus = $fr->getCurrentAudioStatus()}
|
||||
<span class="name">{$fr->getCanonicalName()}</span>
|
||||
<span class="name noOverflow">{$fr->getCanonicalName()}</span>
|
||||
<span class="desc">{$audioStatus ? $audioStatus->getName() : tr("audios_count", $fr->getAudiosCollectionSize())}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -220,6 +220,10 @@
|
|||
<div class='search_content' n:foreach="$data as $dat">
|
||||
{include "../Audio/player.xml", audio => $dat}
|
||||
</div>
|
||||
{elseif $section === 'audios_playlists'}
|
||||
<div class='search_content' n:foreach="$data as $dat">
|
||||
{include "../Audio/playlistListView.xml", playlist => $dat}
|
||||
</div>
|
||||
{/if}
|
||||
{else}
|
||||
{include "../components/content_error.xml", description => tr("no_results_by_this_query")}
|
||||
|
@ -234,7 +238,7 @@
|
|||
<a n:attr="id => $section === 'videos' ? 'used'" href="/search?section=videos&q={$query}"> {_s_videos}</a>
|
||||
<a n:attr="id => $section === 'apps' ? 'used'" href="/search?section=apps&q={$query}"> {_s_apps}</a>
|
||||
<a n:attr="id => $section === 'audios' ? 'used'" href="/search?section=audios&q={$query}"> {_s_audios}</a>
|
||||
<a n:attr="id => $section === 'playlists' ? 'used'" href="/search?section=playlists&q={$query}">{_s_audios_playlists}</a>
|
||||
<a n:attr="id => $section === 'audios_playlists' ? 'used'" href="/search?section=audios_playlists&q={$query}">{_s_audios_playlists}</a>
|
||||
</div>
|
||||
|
||||
<div class='page_search_options'>
|
||||
|
@ -273,7 +277,7 @@
|
|||
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_creation_date}</option>
|
||||
{/if}
|
||||
|
||||
{if $section == "audios"}
|
||||
{if $section == "audios" || $section == "audios_playlists"}
|
||||
<option value="length" n:attr="selected => $order == 'length'">{_s_order_by_length}</option>
|
||||
<option value="listens" n:attr="selected => $order == 'listens'">{_s_order_by_listens}</option>
|
||||
{/if}
|
||||
|
|
|
@ -433,25 +433,55 @@
|
|||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.playlistContainer {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 146px);
|
||||
gap: 18px 10px;
|
||||
.playlistBlock .playlistWrapper {
|
||||
float: left;
|
||||
padding-left: 13px;
|
||||
width:75%
|
||||
}
|
||||
|
||||
.playlistContainer .playlistCover {
|
||||
width: 111px;
|
||||
height: 111px;
|
||||
.playlistCover .profile_links .profile_link {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* playlist listview */
|
||||
|
||||
.playlistListView {
|
||||
display: flex;
|
||||
background: #c4c4c4;
|
||||
padding: 7px;
|
||||
gap: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.playlistContainer .playlistCover img {
|
||||
max-width: 111px;
|
||||
max-height: 111px;
|
||||
margin: auto;
|
||||
.playlistListView:hover, .playlistListView .playlistCover {
|
||||
background: #ebebeb;
|
||||
}
|
||||
|
||||
.playlistListView .playlistCover img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.playlistListView .playlistInfo, .playlistListView .playlistInfo .playlistInfoTopPart {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.playlistListView .playlistInfo {
|
||||
gap: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.playlistListView .playlistInfo .playlistName {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.playlistListView .playlistInfo .playlistMeta, .playlistListView .playlistInfo .playlistMeta span {
|
||||
color: #676767;
|
||||
}
|
||||
|
||||
/* other */
|
||||
|
||||
.ovk-diag-body .searchBox {
|
||||
background: #e6e6e6;
|
||||
padding-top: 10px;
|
||||
|
@ -496,10 +526,6 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.playlistCover img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.explicitMark {
|
||||
margin-top: 2px;
|
||||
margin-left: 3px;
|
||||
|
@ -540,15 +566,6 @@
|
|||
margin-left: -10px;
|
||||
}
|
||||
|
||||
.playlistInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.playlistInfo .playlistName {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.searchList.floating {
|
||||
position: fixed;
|
||||
z-index: 199;
|
||||
|
|
|
@ -2625,6 +2625,7 @@ a.poll-retract-vote {
|
|||
right: 0;
|
||||
text-align: right;
|
||||
border-left: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.header_navigation #search_box .search_box_button {
|
||||
|
|
|
@ -747,6 +747,19 @@ function initPlayer(id, keys, url, length) {
|
|||
document.querySelector('link[rel="icon"], link[rel="shortcut icon"]').setAttribute("href", "/assets/packages/static/openvk/img/favicons/favicon24_playing.png")
|
||||
}
|
||||
|
||||
u('.subTracks .lengthTrack').nodes.forEach(el => {
|
||||
if(el && (el.style.display == 'block' || el.style.display == '')) {
|
||||
const audioEmbed = el.closest('.audioEmbed')
|
||||
|
||||
if(audioEmbed.dataset && Number(audioEmbed.dataset.realid) == Number(playerObject.dataset.realid)) {
|
||||
return
|
||||
}
|
||||
|
||||
el.style.display = 'none'
|
||||
audioEmbed.querySelector('.volumeTrack').style.display = 'none'
|
||||
}
|
||||
})
|
||||
|
||||
if(!$(`#audioEmbed-${ id}`).hasClass("havePlayed")) {
|
||||
$(`#audioEmbed-${ id}`).addClass("havePlayed")
|
||||
|
||||
|
@ -766,7 +779,7 @@ function initPlayer(id, keys, url, length) {
|
|||
u(audio).on("play", playButtonImageUpdate);
|
||||
u(audio).on(["pause", "suspended"], playButtonImageUpdate);
|
||||
u(audio).on("ended", (e) => {
|
||||
let thisPlayer = e.target.closest(".audioEmbed")
|
||||
let thisPlayer = playerObject
|
||||
let nextPlayer = null
|
||||
if(thisPlayer.closest(".attachment") != null) {
|
||||
try {
|
||||
|
|
1
install/sqls/00047-unlisted-playlists.sql
Normal file
1
install/sqls/00047-unlisted-playlists.sql
Normal file
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `playlists` ADD `unlisted` TINYINT(1) UNSIGNED DEFAULT '0' AFTER `deleted`;
|
|
@ -646,6 +646,7 @@
|
|||
"search_for_apps" = "Search for apps";
|
||||
"search_for_notes" = "Search for notes";
|
||||
"search_for_audios" = "Search for music";
|
||||
"search_for_audios_playlists" = "Search for playlists";
|
||||
"search_button" = "Find";
|
||||
"search_placeholder" = "Start typing any name, title or word";
|
||||
"results_zero" = "No results";
|
||||
|
|
|
@ -621,6 +621,7 @@
|
|||
"search_for_apps" = "Поиск приложений";
|
||||
"search_for_notes" = "Поиск записок";
|
||||
"search_for_audios" = "Поиск музыки";
|
||||
"search_for_audios_playlists" = "Поиск плейлистов";
|
||||
"search_button" = "Найти";
|
||||
"search_placeholder" = "Начните вводить любое имя, название или слово";
|
||||
"results_zero" = "Ни одного результата";
|
||||
|
@ -904,6 +905,7 @@
|
|||
"repeat_tip" = "Повторение";
|
||||
"shuffle_tip" = "Перемешать";
|
||||
"mute_tip" = "Заглушить";
|
||||
"playlist_hide_from_search" = "Не показывать в поиске";
|
||||
|
||||
/* Notifications */
|
||||
|
||||
|
|
Loading…
Reference in a new issue