mirror of
https://github.com/openvk/openvk
synced 2024-12-24 17:41:07 +03:00
Merge 3aafae1af3
into b3e57147b7
This commit is contained in:
commit
5b5de87068
55 changed files with 2491 additions and 1576 deletions
|
@ -1,76 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\ServiceAPI;
|
||||
use openvk\Web\Models\Entities\{User, Club};
|
||||
use openvk\Web\Models\Repositories\{Users, Clubs, Videos};
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
||||
class Search implements Handler
|
||||
{
|
||||
protected $user;
|
||||
private $users;
|
||||
private $clubs;
|
||||
private $videos;
|
||||
|
||||
function __construct(?User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->users = new Users;
|
||||
$this->clubs = new Clubs;
|
||||
$this->videos = new Videos;
|
||||
}
|
||||
|
||||
function fastSearch(string $query, string $type = "users", callable $resolve, callable $reject)
|
||||
{
|
||||
if($query == "" || strlen($query) < 3)
|
||||
$reject(12, "No input or input < 3");
|
||||
|
||||
$repo;
|
||||
$sort;
|
||||
|
||||
switch($type) {
|
||||
default:
|
||||
case "users":
|
||||
$repo = (new Users);
|
||||
$sort = "rating DESC";
|
||||
|
||||
break;
|
||||
case "groups":
|
||||
$repo = (new Clubs);
|
||||
$sort = "id ASC";
|
||||
|
||||
break;
|
||||
case "videos":
|
||||
$repo = (new Videos);
|
||||
$sort = "created ASC";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$res = $repo->find($query, ["doNotSearchMe" => $this->user->getId(), "doNotSearchPrivate" => true,], $sort);
|
||||
|
||||
$results = array_slice(iterator_to_array($res), 0, 5);
|
||||
|
||||
$count = sizeof($results);
|
||||
|
||||
$arr = [
|
||||
"count" => $count,
|
||||
"items" => []
|
||||
];
|
||||
|
||||
if(sizeof($results) < 1) {
|
||||
$reject(2, "No results");
|
||||
}
|
||||
|
||||
foreach($results as $res) {
|
||||
$arr["items"][] = [
|
||||
"id" => $res->getId(),
|
||||
"name" => $type == "users" ? $res->getCanonicalName() : $res->getName(),
|
||||
"avatar" => $type != "videos" ? $res->getAvatarUrl() : $res->getThumbnailURL(),
|
||||
"url" => $type != "videos" ? $res->getUrl() : "/video".$res->getPrettyId(),
|
||||
"description" => ovk_proc_strtr($res->getDescription() ?? "...", 40)
|
||||
];
|
||||
}
|
||||
|
||||
$resolve($arr);
|
||||
}
|
||||
}
|
|
@ -581,13 +581,31 @@ final class Audio extends VKAPIRequestHandler
|
|||
];
|
||||
}
|
||||
|
||||
function searchAlbums(string $query, int $offset = 0, int $limit = 25, int $drop_private = 0): object
|
||||
function searchAlbums(string $query = '', int $offset = 0, int $limit = 25, int $drop_private = 0, int $order = 0, int $from_me = 0): object
|
||||
{
|
||||
$this->requireUser();
|
||||
|
||||
$playlists = [];
|
||||
$search = (new Audios)->searchPlaylists($query)->offsetLimit($offset, $limit);
|
||||
foreach($search as $playlist) {
|
||||
$params = [];
|
||||
$order_str = 'id';
|
||||
switch($order) {
|
||||
default:
|
||||
case 0:
|
||||
$order_str = 'id';
|
||||
break;
|
||||
case 1:
|
||||
$order_str = 'length';
|
||||
break;
|
||||
case 2:
|
||||
$order_str = 'listens';
|
||||
break;
|
||||
}
|
||||
|
||||
if($from_me === 1)
|
||||
$params['from_me'] = $this->getUser()->getId();
|
||||
|
||||
$search = (new Audios)->findPlaylists($query, $params, ['type' => $order_str, 'invert' => false]);
|
||||
foreach($search->offsetLimit($offset, $limit) as $playlist) {
|
||||
if(!$playlist->canBeViewedBy($this->getUser())) {
|
||||
if($drop_private == 0)
|
||||
$playlists[] = NULL;
|
||||
|
@ -599,7 +617,7 @@ final class Audio extends VKAPIRequestHandler
|
|||
}
|
||||
|
||||
return (object) [
|
||||
"count" => sizeof($playlists),
|
||||
"count" => $search->size(),
|
||||
"items" => $playlists,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -252,23 +252,30 @@ final class Groups extends VKAPIRequestHandler
|
|||
return $response;
|
||||
}
|
||||
|
||||
function search(string $q, int $offset = 0, int $count = 100)
|
||||
function search(string $q, int $offset = 0, int $count = 100, string $fields = "screen_name,is_admin,is_member,is_advertiser,photo_50,photo_100,photo_200")
|
||||
{
|
||||
if($count > 100) {
|
||||
$this->fail(100, "One of the parameters specified was missing or invalid: count should be less or equal to 100");
|
||||
}
|
||||
|
||||
$clubs = new ClubsRepo;
|
||||
|
||||
$array = [];
|
||||
$find = $clubs->find($q);
|
||||
|
||||
foreach ($find as $group)
|
||||
foreach ($find->offsetLimit($offset, $count) as $group)
|
||||
$array[] = $group->getId();
|
||||
|
||||
if(!$array || sizeof($array) < 1) {
|
||||
return (object) [
|
||||
"count" => 0,
|
||||
"items" => [],
|
||||
];
|
||||
}
|
||||
|
||||
return (object) [
|
||||
"count" => $find->size(),
|
||||
"items" => $this->getById(implode(',', $array), "", "is_admin,is_member,is_advertiser,photo_50,photo_100,photo_200", $offset, $count)
|
||||
/*
|
||||
* As there is no thing as "fields" by the original documentation
|
||||
* i'll just bake this param by the example shown here: https://dev.vk.com/method/groups.search
|
||||
*/
|
||||
"items" => $this->getById(implode(',', $array), "", $fields)
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -263,6 +263,9 @@ final class Users extends VKAPIRequestHandler
|
|||
case 'is_dead':
|
||||
$response[$i]->is_dead = $usr->isDead();
|
||||
break;
|
||||
case 'nickname':
|
||||
$response[$i]->nickname = $usr->getPseudo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,89 +317,90 @@ final class Users extends VKAPIRequestHandler
|
|||
int $count = 100,
|
||||
string $city = "",
|
||||
string $hometown = "",
|
||||
int $sex = 2,
|
||||
int $status = 0, # это про marital status
|
||||
int $sex = 3,
|
||||
int $status = 0, # marital_status
|
||||
bool $online = false,
|
||||
# дальше идут параметры которых нету в vkapi но есть на сайте
|
||||
string $profileStatus = "", # а это уже нормальный статус
|
||||
# non standart params:
|
||||
int $sort = 0,
|
||||
int $before = 0,
|
||||
int $politViews = 0,
|
||||
int $after = 0,
|
||||
string $interests = "",
|
||||
int $polit_views = 0,
|
||||
string $fav_music = "",
|
||||
string $fav_films = "",
|
||||
string $fav_shows = "",
|
||||
string $fav_books = "",
|
||||
string $fav_quotes = ""
|
||||
string $fav_books = ""
|
||||
)
|
||||
{
|
||||
$users = new UsersRepo;
|
||||
|
||||
$sortg = "id ASC";
|
||||
if($count > 100) {
|
||||
$this->fail(100, "One of the parameters specified was missing or invalid: count should be less or equal to 100");
|
||||
}
|
||||
|
||||
$nfilds = $fields;
|
||||
$users = new UsersRepo;
|
||||
$output_sort = ['type' => 'id', 'invert' => false];
|
||||
$output_params = [
|
||||
"ignore_private" => true,
|
||||
];
|
||||
|
||||
switch($sort) {
|
||||
default:
|
||||
case 0:
|
||||
$sortg = "id DESC";
|
||||
$output_sort = ['type' => 'id', 'invert' => false];
|
||||
break;
|
||||
case 1:
|
||||
$sortg = "id ASC";
|
||||
break;
|
||||
case 2:
|
||||
$sortg = "first_name DESC";
|
||||
break;
|
||||
case 3:
|
||||
$sortg = "first_name ASC";
|
||||
$output_sort = ['type' => 'id', 'invert' => true];
|
||||
break;
|
||||
case 4:
|
||||
$sortg = "rating DESC";
|
||||
|
||||
if(!str_contains($nfilds, "rating")) {
|
||||
$nfilds .= "rating";
|
||||
}
|
||||
|
||||
break;
|
||||
case 5:
|
||||
$sortg = "rating DESC";
|
||||
|
||||
if(!str_contains($nfilds, "rating")) {
|
||||
$nfilds .= "rating";
|
||||
}
|
||||
|
||||
$output_sort = ['type' => 'rating', 'invert' => false];
|
||||
break;
|
||||
}
|
||||
|
||||
if(!empty($city))
|
||||
$output_params['city'] = $city;
|
||||
|
||||
if(!empty($hometown))
|
||||
$output_params['hometown'] = $hometown;
|
||||
|
||||
if($sex != 3)
|
||||
$output_params['gender'] = $sex;
|
||||
|
||||
if($status != 0)
|
||||
$output_params['marital_status'] = $status;
|
||||
|
||||
if($polit_views != 0)
|
||||
$output_params['polit_views'] = $polit_views;
|
||||
|
||||
if(!empty($interests))
|
||||
$output_params['interests'] = $interests;
|
||||
|
||||
if(!empty($fav_music))
|
||||
$output_params['fav_music'] = $fav_music;
|
||||
|
||||
if(!empty($fav_films))
|
||||
$output_params['fav_films'] = $fav_films;
|
||||
|
||||
if(!empty($fav_shows))
|
||||
$output_params['fav_shows'] = $fav_shows;
|
||||
|
||||
if(!empty($fav_books))
|
||||
$output_params['fav_books'] = $fav_books;
|
||||
|
||||
if($online)
|
||||
$output_params['is_online'] = 1;
|
||||
|
||||
$array = [];
|
||||
$find = $users->find($q, $output_params, $output_sort);
|
||||
|
||||
$parameters = [
|
||||
"city" => !empty($city) ? $city : NULL,
|
||||
"hometown" => !empty($hometown) ? $hometown : NULL,
|
||||
"gender" => $sex < 2 ? $sex : NULL,
|
||||
"maritalstatus" => (bool)$status ? $status : NULL,
|
||||
"politViews" => (bool)$politViews ? $politViews : NULL,
|
||||
"is_online" => $online ? 1 : NULL,
|
||||
"status" => !empty($profileStatus) ? $profileStatus : NULL,
|
||||
"before" => $before != 0 ? $before : NULL,
|
||||
"after" => $after != 0 ? $after : NULL,
|
||||
"interests" => !empty($interests) ? $interests : NULL,
|
||||
"fav_music" => !empty($fav_music) ? $fav_music : NULL,
|
||||
"fav_films" => !empty($fav_films) ? $fav_films : NULL,
|
||||
"fav_shows" => !empty($fav_shows) ? $fav_shows : NULL,
|
||||
"fav_books" => !empty($fav_books) ? $fav_books : NULL,
|
||||
"fav_quotes" => !empty($fav_quotes) ? $fav_quotes : NULL,
|
||||
"doNotSearchPrivate" => true,
|
||||
];
|
||||
|
||||
$find = $users->find($q, $parameters, $sortg);
|
||||
|
||||
foreach ($find as $user)
|
||||
foreach ($find->offsetLimit($offset, $count) as $user)
|
||||
$array[] = $user->getId();
|
||||
|
||||
if(!$array || sizeof($array) < 1) {
|
||||
return (object) [
|
||||
"count" => 0,
|
||||
"items" => [],
|
||||
];
|
||||
}
|
||||
|
||||
return (object) [
|
||||
"count" => $find->size(),
|
||||
"items" => $this->get(implode(',', $array), $nfilds, $offset, $count)
|
||||
"count" => $find->size(),
|
||||
"items" => $this->get(implode(',', $array), $fields)
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -60,4 +60,60 @@ final class Video extends VKAPIRequestHandler
|
|||
];
|
||||
}
|
||||
}
|
||||
|
||||
function search(string $q = '', int $sort = 0, int $offset = 0, int $count = 10, bool $extended = false, string $fields = ''): object
|
||||
{
|
||||
$this->requireUser();
|
||||
|
||||
$params = [];
|
||||
$db_sort = ['type' => 'id', 'invert' => false];
|
||||
$videos = (new VideosRepo)->find($q, $params, $db_sort);
|
||||
$items = iterator_to_array($videos->offsetLimit($offset, $count));
|
||||
$count = $videos->size();
|
||||
|
||||
$return_items = [];
|
||||
$profiles = [];
|
||||
$groups = [];
|
||||
foreach($items as $item)
|
||||
$return_item = $item->getApiStructure($this->getUser());
|
||||
$return_item = $return_item->video;
|
||||
$return_items[] = $return_item;
|
||||
|
||||
if($return_item['owner_id']) {
|
||||
if($return_item['owner_id'] > 0)
|
||||
$profiles[] = $return_item['owner_id'];
|
||||
else
|
||||
$groups[] = abs($return_item['owner_id']);
|
||||
}
|
||||
|
||||
if($extended) {
|
||||
$profiles = array_unique($profiles);
|
||||
$groups = array_unique($groups);
|
||||
|
||||
$profilesFormatted = [];
|
||||
$groupsFormatted = [];
|
||||
|
||||
foreach($profiles as $prof) {
|
||||
$profile = (new UsersRepo)->get($prof);
|
||||
$profilesFormatted[] = $profile->toVkApiStruct($this->getUser(), $fields);
|
||||
}
|
||||
|
||||
foreach($groups as $gr) {
|
||||
$group = (new ClubsRepo)->get($gr);
|
||||
$groupsFormatted[] = $group->toVkApiStruct($this->getUser(), $fields);
|
||||
}
|
||||
|
||||
return (object) [
|
||||
"count" => $count,
|
||||
"items" => $return_items,
|
||||
"profiles" => $profilesFormatted,
|
||||
"groups" => $groupsFormatted,
|
||||
];
|
||||
}
|
||||
|
||||
return (object) [
|
||||
"count" => $count,
|
||||
"items" => $return_items,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,6 +152,11 @@ class Audio extends Media
|
|||
return $this->getPerformer() . " — " . $this->getTitle();
|
||||
}
|
||||
|
||||
function getDownloadName(): string
|
||||
{
|
||||
return preg_replace('/[\\/:*?"<>|]/', '_', str_replace(' ', '_', $this->getName()));
|
||||
}
|
||||
|
||||
function getGenre(): ?string
|
||||
{
|
||||
return $this->getRecord()->genre;
|
||||
|
|
|
@ -437,7 +437,7 @@ class Club extends RowModel
|
|||
return (new \openvk\Web\Models\Repositories\Audios)->getClubCollectionSize($this);
|
||||
}
|
||||
|
||||
function toVkApiStruct(?User $user = NULL): object
|
||||
function toVkApiStruct(?User $user = NULL, string $fields = ''): object
|
||||
{
|
||||
$res = (object) [];
|
||||
|
||||
|
|
|
@ -140,4 +140,31 @@ class Comment extends Post
|
|||
|
||||
return $user->getId() == $this->getOwner(false)->getId();
|
||||
}
|
||||
|
||||
function getTargetURL(): string
|
||||
{
|
||||
$target = $this->getTarget();
|
||||
$target_name = 'wall';
|
||||
|
||||
if(!$target) {
|
||||
return '/404';
|
||||
}
|
||||
|
||||
switch(get_class($target)) {
|
||||
case 'openvk\Web\Models\Entities\Note':
|
||||
$target_name = 'note';
|
||||
break;
|
||||
case 'openvk\Web\Models\Entities\Photo':
|
||||
$target_name = 'photo';
|
||||
break;
|
||||
case 'openvk\Web\Models\Entities\Video':
|
||||
$target_name = 'video';
|
||||
break;
|
||||
case 'openvk\Web\Models\Entities\Topic':
|
||||
$target_name = 'topic';
|
||||
break;
|
||||
}
|
||||
|
||||
return $target_name . $target->getPrettyId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,21 @@ class Playlist extends MediaCollection
|
|||
{
|
||||
return $this->getRecord()->length;
|
||||
}
|
||||
|
||||
function fetchClassic(int $offset = 0, ?int $limit = NULL): \Traversable
|
||||
{
|
||||
$related = $this->getRecord()->related("$this->relTableName.collection")
|
||||
->limit($limit ?? OPENVK_DEFAULT_PER_PAGE, $offset)
|
||||
->order("index ASC");
|
||||
|
||||
foreach($related as $rel) {
|
||||
$media = $rel->ref($this->entityTableName, "media");
|
||||
if(!$media)
|
||||
continue;
|
||||
|
||||
yield new $this->entityClassName($media);
|
||||
}
|
||||
}
|
||||
|
||||
function getAudios(int $offset = 0, ?int $limit = NULL, ?int $shuffleSeed = NULL): \Traversable
|
||||
{
|
||||
|
@ -162,6 +177,7 @@ class Playlist extends MediaCollection
|
|||
"bookmarked" => $this->isBookmarkedBy($user),
|
||||
"listens" => $this->getListens(),
|
||||
"cover_url" => $this->getCoverURL(),
|
||||
"searchable" => !$this->isUnlisted(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -199,6 +215,11 @@ class Playlist extends MediaCollection
|
|||
{
|
||||
return $this->getRecord()->cover_photo_id;
|
||||
}
|
||||
|
||||
function getCoverPhoto(): ?Photo
|
||||
{
|
||||
return (new Photos)->get((int) $this->getRecord()->cover_photo_id);
|
||||
}
|
||||
|
||||
function canBeModifiedBy(User $user): bool
|
||||
{
|
||||
|
@ -253,4 +274,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);
|
||||
|
|
|
@ -1321,17 +1321,22 @@ class User extends RowModel
|
|||
return true;
|
||||
}
|
||||
|
||||
function isClosed()
|
||||
function isClosed(): bool
|
||||
{
|
||||
return (bool) $this->getProfileType();
|
||||
}
|
||||
|
||||
function isHideFromGlobalFeedEnabled(): bool
|
||||
{
|
||||
return $this->isClosed();
|
||||
}
|
||||
|
||||
function getRealId()
|
||||
{
|
||||
return $this->getId();
|
||||
}
|
||||
|
||||
function toVkApiStruct(?User $user = NULL): object
|
||||
function toVkApiStruct(?User $user = NULL, string $fields = ''): object
|
||||
{
|
||||
$res = (object) [];
|
||||
|
||||
|
@ -1349,8 +1354,16 @@ class User extends RowModel
|
|||
if(!is_null($user))
|
||||
$res->can_access_closed = (bool)$this->canBeViewedBy($user);
|
||||
|
||||
if($user->isDead())
|
||||
$res->is_dead = 1;
|
||||
if(!is_array($fields))
|
||||
$fields = explode(',', $fields);
|
||||
|
||||
foreach($fields as $field) {
|
||||
switch($field) {
|
||||
case 'is_dead':
|
||||
$res->is_dead = $user->isDead();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
|
|
@ -181,8 +181,8 @@ class Video extends Media
|
|||
{
|
||||
if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/youtube.txt"), $link, $matches)) {
|
||||
$pointer = "YouTube:$matches[1]";
|
||||
} else if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/vimeo.txt"), $link, $matches)) {
|
||||
$pointer = "Vimeo:$matches[1]";
|
||||
/*} else if(preg_match(file_get_contents(__DIR__ . "/../VideoDrivers/regex/vimeo.txt"), $link, $matches)) {
|
||||
$pointer = "Vimeo:$matches[1]";*/
|
||||
} else {
|
||||
throw new ISE("Invalid link");
|
||||
}
|
||||
|
|
|
@ -67,11 +67,21 @@ class Applications
|
|||
return sizeof($this->appRels->where("user", $user->getId()));
|
||||
}
|
||||
|
||||
function find(string $query, array $pars = [], string $sort = "id"): Util\EntityStream
|
||||
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||
{
|
||||
$query = "%$query%";
|
||||
$query = "%$query%";
|
||||
$result = $this->apps->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("enabled", 1);
|
||||
$order_str = 'id';
|
||||
|
||||
switch($order['type']) {
|
||||
case 'id':
|
||||
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
}
|
||||
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("Application", $result->order("$sort"));
|
||||
return new Util\EntityStream("Application", $result);
|
||||
}
|
||||
}
|
|
@ -208,7 +208,7 @@ class Audios
|
|||
$search = $this->audios->where([
|
||||
"unlisted" => 0,
|
||||
"deleted" => 0,
|
||||
])->where("MATCH ($columns) AGAINST (? WITH QUERY EXPANSION)", $query)->order($order);
|
||||
])->where("MATCH ($columns) AGAINST (? IN BOOLEAN MODE)", "%$query%")->order($order);
|
||||
|
||||
if($withLyrics)
|
||||
$search = $search->where("lyrics IS NOT NULL");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -243,53 +244,84 @@ class Audios
|
|||
])->fetch());
|
||||
}
|
||||
|
||||
function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false], int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
{
|
||||
$query = "%$query%";
|
||||
$query = "%$query%";
|
||||
$result = $this->audios->where([
|
||||
"unlisted" => 0,
|
||||
"deleted" => 0,
|
||||
]);
|
||||
$order_str = 'id';
|
||||
|
||||
$notNullParams = [];
|
||||
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;
|
||||
}
|
||||
|
||||
foreach($pars as $paramName => $paramValue)
|
||||
if($paramName != "before" && $paramName != "after" && $paramName != "only_performers")
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
||||
else
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
||||
|
||||
$nnparamsCount = sizeof($notNullParams);
|
||||
|
||||
if($notNullParams["only_performers"] == "1") {
|
||||
if($params["only_performers"] == "1") {
|
||||
$result->where("performer LIKE ?", $query);
|
||||
} else {
|
||||
$result->where("name LIKE ? OR performer LIKE ?", $query, $query);
|
||||
}
|
||||
|
||||
if($nnparamsCount > 0) {
|
||||
foreach($notNullParams as $paramName => $paramValue) {
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
case "with_lyrics":
|
||||
$result->where("lyrics IS NOT NULL");
|
||||
break;
|
||||
}
|
||||
foreach($params as $paramName => $paramValue) {
|
||||
if(is_null($paramValue) || $paramValue == '') continue;
|
||||
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
case "with_lyrics":
|
||||
$result->where("lyrics IS NOT NULL");
|
||||
break;
|
||||
case 'genre':
|
||||
if($paramValue == 'any') break;
|
||||
|
||||
$result->where("genre", $paramValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new Util\EntityStream("Audio", $result->order($sort));
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
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
|
||||
{
|
||||
$query = "%$query%";
|
||||
$result = $this->playlists->where("name LIKE ?", $query);
|
||||
$query = "%$query%";
|
||||
$result = $this->playlists->where([
|
||||
"deleted" => 0,
|
||||
])->where("CONCAT_WS(' ', name, description) LIKE ?", $query);
|
||||
$order_str = (['id', 'length', 'listens'][$order['type']] ?? 'id') . ' ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
|
||||
if(is_null($params['from_me']) || empty($params['from_me']))
|
||||
$result->where(["unlisted" => 0]);
|
||||
|
||||
foreach($params as $paramName => $paramValue) {
|
||||
if(is_null($paramValue) || $paramValue == '') continue;
|
||||
|
||||
switch($paramName) {
|
||||
# БУДЬ МАКСИМАЛЬНО АККУРАТЕН С ДАННЫМ ПАРАМЕТРОМ
|
||||
case "from_me":
|
||||
$result->where("owner", $paramValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("Playlist", $result);
|
||||
}
|
||||
|
|
|
@ -42,13 +42,25 @@ class Clubs
|
|||
{
|
||||
return $this->toClub($this->clubs->get($id));
|
||||
}
|
||||
|
||||
function find(string $query, array $pars = [], string $sort = "id DESC", int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
|
||||
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false], int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
{
|
||||
$query = "%$query%";
|
||||
$result = $this->clubs->where("name LIKE ? OR about LIKE ?", $query, $query);
|
||||
|
||||
return new Util\EntityStream("Club", $result->order($sort));
|
||||
$query = "%$query%";
|
||||
$result = $this->clubs;
|
||||
$order_str = 'id';
|
||||
|
||||
switch($order['type']) {
|
||||
case 'id':
|
||||
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
}
|
||||
|
||||
$result = $result->where("name LIKE ? OR about LIKE ?", $query, $query);
|
||||
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("Club", $result);
|
||||
}
|
||||
|
||||
function getCount(): int
|
||||
|
|
|
@ -60,34 +60,31 @@ class Comments
|
|||
]));
|
||||
}
|
||||
|
||||
function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream
|
||||
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||
{
|
||||
$query = "%$query%";
|
||||
$result = $this->comments->where("content LIKE ?", "%$query%")->where("deleted", 0);
|
||||
$order_str = 'id';
|
||||
|
||||
$notNullParams = [];
|
||||
switch($order['type']) {
|
||||
case 'id':
|
||||
$order_str = 'created ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
}
|
||||
|
||||
foreach($pars as $paramName => $paramValue)
|
||||
if($paramName != "before" && $paramName != "after")
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
||||
else
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
||||
|
||||
$result = $this->comments->where("content LIKE ?", $query)->where("deleted", 0);
|
||||
$nnparamsCount = sizeof($notNullParams);
|
||||
|
||||
if($nnparamsCount > 0) {
|
||||
foreach($notNullParams as $paramName => $paramValue) {
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
}
|
||||
foreach($params as $paramName => $paramValue) {
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new Util\EntityStream("Comment", $result->order("$sort"));
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("Comment", $result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,36 +154,45 @@ class Posts
|
|||
|
||||
}
|
||||
|
||||
function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream
|
||||
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||
{
|
||||
$query = "%$query%";
|
||||
|
||||
$notNullParams = [];
|
||||
|
||||
foreach($pars as $paramName => $paramValue)
|
||||
if($paramName != "before" && $paramName != "after")
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
||||
else
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
||||
|
||||
$query = "%$query%";
|
||||
$result = $this->posts->where("content LIKE ?", $query)->where("deleted", 0)->where("suggested", 0);
|
||||
$nnparamsCount = sizeof($notNullParams);
|
||||
$order_str = 'id';
|
||||
|
||||
if($nnparamsCount > 0) {
|
||||
foreach($notNullParams as $paramName => $paramValue) {
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
}
|
||||
switch($order['type']) {
|
||||
case 'id':
|
||||
$order_str = 'created ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
}
|
||||
|
||||
foreach($params as $paramName => $paramValue) {
|
||||
if(is_null($paramValue) || $paramValue == '') continue;
|
||||
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
/*case 'die_in_agony':
|
||||
$result->where("nsfw", 1);
|
||||
break;
|
||||
case 'ads':
|
||||
$result->where("ad", 1);
|
||||
break;*/
|
||||
# БУДЬ МАКСИМАЛЬНО АККУРАТЕН С ДАННЫМ ПАРАМЕТРОМ
|
||||
case 'from_me':
|
||||
$result->where("owner", $paramValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("Post", $result->order("$sort"));
|
||||
return new Util\EntityStream("Post", $result);
|
||||
}
|
||||
|
||||
function getPostCountOnUserWall(int $user): int
|
||||
|
|
|
@ -54,94 +54,76 @@ class Users
|
|||
return $user ? $this->getByChandlerUserId($user->getId()) : NULL;
|
||||
}
|
||||
|
||||
function find(string $query, array $pars = [], string $sort = "id DESC"): Util\EntityStream
|
||||
function find(string $query, array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||
{
|
||||
$query = "%$query%";
|
||||
$query = "%$query%";
|
||||
$result = $this->users->where("CONCAT_WS(' ', first_name, last_name, pseudo, shortcode) LIKE ?", $query)->where("deleted", 0);
|
||||
|
||||
$notNullParams = [];
|
||||
$nnparamsCount = 0;
|
||||
|
||||
foreach($pars as $paramName => $paramValue)
|
||||
if($paramName != "before" && $paramName != "after" && $paramName != "gender" && $paramName != "maritalstatus" && $paramName != "politViews" && $paramName != "doNotSearchMe")
|
||||
$paramValue != NULL ? $notNullParams += ["$paramName" => "%$paramValue%"] : NULL;
|
||||
else
|
||||
$paramValue != NULL ? $notNullParams += ["$paramName" => "$paramValue"] : NULL;
|
||||
$order_str = 'id';
|
||||
|
||||
$nnparamsCount = sizeof($notNullParams);
|
||||
switch($order['type']) {
|
||||
case 'id':
|
||||
case 'reg_date':
|
||||
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
case 'rating':
|
||||
$order_str = 'rating DESC';
|
||||
break;
|
||||
}
|
||||
|
||||
if($nnparamsCount > 0) {
|
||||
foreach($notNullParams as $paramName => $paramValue) {
|
||||
switch($paramName) {
|
||||
case "hometown":
|
||||
$result->where("hometown LIKE ?", $paramValue);
|
||||
break;
|
||||
case "city":
|
||||
$result->where("city LIKE ?", $paramValue);
|
||||
break;
|
||||
case "maritalstatus":
|
||||
$result->where("marital_status ?", $paramValue);
|
||||
break;
|
||||
case "status":
|
||||
$result->where("status LIKE ?", $paramValue);
|
||||
break;
|
||||
case "politViews":
|
||||
$result->where("polit_views ?", $paramValue);
|
||||
break;
|
||||
case "email":
|
||||
$result->where("email_contact LIKE ?", $paramValue);
|
||||
break;
|
||||
case "telegram":
|
||||
$result->where("telegram LIKE ?", $paramValue);
|
||||
break;
|
||||
case "site":
|
||||
$result->where("telegram LIKE ?", $paramValue);
|
||||
break;
|
||||
case "address":
|
||||
$result->where("address LIKE ?", $paramValue);
|
||||
break;
|
||||
case "is_online":
|
||||
$result->where("online >= ?", time() - 900);
|
||||
break;
|
||||
case "interests":
|
||||
$result->where("interests LIKE ?", $paramValue);
|
||||
break;
|
||||
case "fav_mus":
|
||||
$result->where("fav_music LIKE ?", $paramValue);
|
||||
break;
|
||||
case "fav_films":
|
||||
$result->where("fav_films LIKE ?", $paramValue);
|
||||
break;
|
||||
case "fav_shows":
|
||||
$result->where("fav_shows LIKE ?", $paramValue);
|
||||
break;
|
||||
case "fav_books":
|
||||
$result->where("fav_books LIKE ?", $paramValue);
|
||||
break;
|
||||
case "fav_quote":
|
||||
$result->where("fav_quote LIKE ?", $paramValue);
|
||||
break;
|
||||
case "before":
|
||||
$result->where("UNIX_TIMESTAMP(since) < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("UNIX_TIMESTAMP(since) > ?", $paramValue);
|
||||
break;
|
||||
case "gender":
|
||||
$result->where("sex ?", $paramValue);
|
||||
break;
|
||||
case "doNotSearchMe":
|
||||
$result->where("id !=", $paramValue);
|
||||
break;
|
||||
case "doNotSearchPrivate":
|
||||
$result->where("profile_type", 0);
|
||||
break;
|
||||
}
|
||||
foreach($params as $paramName => $paramValue) {
|
||||
if(is_null($paramValue) || $paramValue == '') continue;
|
||||
|
||||
switch($paramName) {
|
||||
case "hometown":
|
||||
$result->where("hometown LIKE ?", "%$paramValue%");
|
||||
break;
|
||||
case "city":
|
||||
$result->where("city LIKE ?", "%$paramValue%");
|
||||
break;
|
||||
case "marital_status":
|
||||
$result->where("marital_status ?", $paramValue);
|
||||
break;
|
||||
case "polit_views":
|
||||
$result->where("polit_views ?", $paramValue);
|
||||
break;
|
||||
case "is_online":
|
||||
$result->where("online >= ?", time() - 900);
|
||||
break;
|
||||
case "fav_mus":
|
||||
$result->where("fav_music LIKE ?", "%$paramValue%");
|
||||
break;
|
||||
case "fav_films":
|
||||
$result->where("fav_films LIKE ?", "%$paramValue%");
|
||||
break;
|
||||
case "fav_shows":
|
||||
$result->where("fav_shows LIKE ?", "%$paramValue%");
|
||||
break;
|
||||
case "fav_books":
|
||||
$result->where("fav_books LIKE ?", "%$paramValue%");
|
||||
break;
|
||||
case "before":
|
||||
$result->where("UNIX_TIMESTAMP(since) < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("UNIX_TIMESTAMP(since) > ?", $paramValue);
|
||||
break;
|
||||
case "gender":
|
||||
if((int) $paramValue == 3) break;
|
||||
$result->where("sex ?", (int) $paramValue);
|
||||
break;
|
||||
case "ignore_id":
|
||||
$result->where("id != ?", $paramValue);
|
||||
break;
|
||||
case "ignore_private":
|
||||
$result->where("profile_type", 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("User", $result->order($sort));
|
||||
return new Util\EntityStream("User", $result);
|
||||
}
|
||||
|
||||
function getStatistics(): object
|
||||
|
|
|
@ -46,36 +46,37 @@ class Videos
|
|||
return sizeof($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0]));
|
||||
}
|
||||
|
||||
function find(string $query = "", array $pars = [], string $sort = "id"): Util\EntityStream
|
||||
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||
{
|
||||
$query = "%$query%";
|
||||
|
||||
$notNullParams = [];
|
||||
|
||||
foreach($pars as $paramName => $paramValue)
|
||||
if($paramName != "before" && $paramName != "after")
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "%$paramValue%"] : NULL;
|
||||
else
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
||||
|
||||
$query = "%$query%";
|
||||
$result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0);
|
||||
$nnparamsCount = sizeof($notNullParams);
|
||||
$order_str = 'id';
|
||||
|
||||
if($nnparamsCount > 0) {
|
||||
foreach($notNullParams as $paramName => $paramValue) {
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
}
|
||||
switch($order['type']) {
|
||||
case 'id':
|
||||
$order_str = 'id ' . ($order['invert'] ? 'ASC' : 'DESC');
|
||||
break;
|
||||
}
|
||||
|
||||
foreach($params as $paramName => $paramValue) {
|
||||
switch($paramName) {
|
||||
case "before":
|
||||
$result->where("created < ?", $paramValue);
|
||||
break;
|
||||
case "after":
|
||||
$result->where("created > ?", $paramValue);
|
||||
break;
|
||||
case 'only_youtube':
|
||||
if((int) $paramValue != 1) break;
|
||||
$result->where("link != ?", 'NULL');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($order_str)
|
||||
$result->order($order_str);
|
||||
|
||||
return new Util\EntityStream("Video", $result->order("$sort"));
|
||||
return new Util\EntityStream("Video", $result);
|
||||
}
|
||||
|
||||
function getLastVideo(User $user)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,13 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$this->assertUserLoggedIn();
|
||||
|
||||
$group = NULL;
|
||||
$playlist = NULL;
|
||||
$isAjax = $this->postParam("ajax", false) == 1;
|
||||
|
||||
if(!is_null($this->queryParam("gid")) && !is_null($this->queryParam("playlist"))) {
|
||||
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||
}
|
||||
|
||||
if(!is_null($this->queryParam("gid"))) {
|
||||
$gid = (int) $this->queryParam("gid");
|
||||
$group = (new Clubs)->get($gid);
|
||||
|
@ -153,6 +159,19 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||
}
|
||||
|
||||
if(!is_null($this->queryParam("playlist"))) {
|
||||
$playlist_id = (int)$this->queryParam("playlist");
|
||||
$playlist = (new Audios)->getPlaylist($playlist_id);
|
||||
if(!$playlist || $playlist->isDeleted())
|
||||
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||
|
||||
if(!$playlist->canBeModifiedBy($this->user->identity))
|
||||
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||
|
||||
$this->template->playlist = $playlist;
|
||||
$this->template->owner = $playlist->getOwner();
|
||||
}
|
||||
|
||||
$this->template->group = $group;
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] !== "POST")
|
||||
|
@ -196,6 +215,8 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$lyrics = $this->postParam("lyrics");
|
||||
$genre = empty($this->postParam("genre")) ? "Other" : $this->postParam("genre");
|
||||
$nsfw = ($this->postParam("explicit") ?? "off") === "on";
|
||||
$is_unlisted = ($this->postParam("unlisted") ?? "off") === "on";
|
||||
|
||||
if(empty($performer) || empty($name) || iconv_strlen($performer . $name) > 128) # FQN of audio must not be more than 128 chars
|
||||
$this->flashFail("err", tr("error"), tr("error_insufficient_info"), null, $isAjax);
|
||||
|
||||
|
@ -206,6 +227,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$audio->setLyrics(empty($lyrics) ? NULL : $lyrics);
|
||||
$audio->setGenre($genre);
|
||||
$audio->setExplicit($nsfw);
|
||||
$audio->setUnlisted($is_unlisted);
|
||||
|
||||
try {
|
||||
$audio->setFile($upload);
|
||||
|
@ -215,13 +237,18 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
} catch(\RuntimeException $ex) {
|
||||
$this->flashFail("err", tr("error"), tr("ffmpeg_timeout"), null, $isAjax);
|
||||
} catch(\BadMethodCallException $ex) {
|
||||
$this->flashFail("err", tr("error"), "Загрузка аудио под Linux на данный момент не реализована. Следите за обновлениями: <a href='https://github.com/openvk/openvk/pull/512/commits'>https://github.com/openvk/openvk/pull/512/commits</a>", null, $isAjax);
|
||||
$this->flashFail("err", tr("error"), "хз", null, $isAjax);
|
||||
} catch(\Exception $ex) {
|
||||
$this->flashFail("err", tr("error"), tr("ffmpeg_not_installed"), null, $isAjax);
|
||||
}
|
||||
|
||||
$audio->save();
|
||||
$audio->add($group ?? $this->user->identity);
|
||||
|
||||
if($playlist) {
|
||||
$playlist->add($audio);
|
||||
} else {
|
||||
$audio->add($group ?? $this->user->identity);
|
||||
}
|
||||
|
||||
if(!$isAjax)
|
||||
$this->redirect(is_null($group) ? "/audios" . $this->user->id : "/audios-" . $group->getId());
|
||||
|
@ -233,9 +260,9 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
else
|
||||
$redirectLink .= $this->user->id;
|
||||
|
||||
$pagesCount = (int)ceil((new Audios)->getCollectionSizeByEntityId(isset($group) ? $group->getRealId() : $this->user->id) / 10);
|
||||
$redirectLink .= "?p=".$pagesCount;
|
||||
|
||||
if($playlist)
|
||||
$redirectLink = "/playlist" . $playlist->getPrettyId();
|
||||
|
||||
$this->returnJson([
|
||||
"success" => true,
|
||||
"redirect_link" => $redirectLink,
|
||||
|
@ -279,7 +306,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
|
||||
function renderSearch(): void
|
||||
{
|
||||
$this->redirect("/search?type=audios");
|
||||
$this->redirect("/search?section=audios");
|
||||
}
|
||||
|
||||
function renderNewPlaylist(): void
|
||||
|
@ -304,6 +331,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,7 +342,9 @@ 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"))
|
||||
$this->flashFail("err", tr("error"), tr("not_a_photo"));
|
||||
|
@ -427,6 +458,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 +468,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"))
|
||||
|
@ -475,12 +508,15 @@ 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->canEdit = $this->user->identity && $playlist->canBeModifiedBy($this->user->identity);
|
||||
$this->template->count = $playlist->size();
|
||||
}
|
||||
|
||||
function renderAction(int $audio_id): void
|
||||
|
@ -531,16 +567,65 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
|
||||
break;
|
||||
case "add_to_club":
|
||||
$club = (new Clubs)->get((int)$this->postParam("club"));
|
||||
|
||||
if(!$club || !$club->canBeModifiedBy($this->user->identity))
|
||||
$this->flashFail("err", "error", tr("access_denied"), null, true);
|
||||
|
||||
if(!$audio->isInLibraryOf($club))
|
||||
$audio->add($club);
|
||||
else
|
||||
$this->flashFail("err", "error", tr("group_has_audio"), null, true);
|
||||
|
||||
$detailed = [];
|
||||
if($audio->isWithdrawn())
|
||||
$this->flashFail("err", "error", tr("invalid_audio"), null, true);
|
||||
|
||||
if(empty($this->postParam("clubs")))
|
||||
$this->flashFail("err", "error", 'clubs not passed', null, true);
|
||||
|
||||
$clubs_arr = explode(',', $this->postParam("clubs"));
|
||||
$count = sizeof($clubs_arr);
|
||||
if($count < 1 || $count > 10) {
|
||||
$this->flashFail("err", "error", tr('too_many_or_to_lack'), null, true);
|
||||
}
|
||||
|
||||
foreach($clubs_arr as $club_id) {
|
||||
$club = (new Clubs)->get((int)$club_id);
|
||||
if(!$club || !$club->canBeModifiedBy($this->user->identity))
|
||||
continue;
|
||||
|
||||
if(!$audio->isInLibraryOf($club)) {
|
||||
$detailed[$club_id] = true;
|
||||
$audio->add($club);
|
||||
} else {
|
||||
$detailed[$club_id] = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$this->returnJson(["success" => true, 'detailed' => $detailed]);
|
||||
break;
|
||||
case "add_to_playlist":
|
||||
$detailed = [];
|
||||
if($audio->isWithdrawn())
|
||||
$this->flashFail("err", "error", tr("invalid_audio"), null, true);
|
||||
|
||||
if(empty($this->postParam("playlists")))
|
||||
$this->flashFail("err", "error", 'playlists not passed', null, true);
|
||||
|
||||
$playlists_arr = explode(',', $this->postParam("playlists"));
|
||||
$count = sizeof($playlists_arr);
|
||||
if($count < 1 || $count > 10) {
|
||||
$this->flashFail("err", "error", tr('too_many_or_to_lack'), null, true);
|
||||
}
|
||||
|
||||
foreach($playlists_arr as $playlist_id) {
|
||||
$pid = explode('_', $playlist_id);
|
||||
$playlist = (new Audios)->getPlaylistByOwnerAndVID((int)$pid[0], (int)$pid[1]);
|
||||
if(!$playlist || !$playlist->canBeModifiedBy($this->user->identity))
|
||||
continue;
|
||||
|
||||
if(!$playlist->hasAudio($audio)) {
|
||||
$playlist->add($audio);
|
||||
$detailed[$playlist_id] = true;
|
||||
} else {
|
||||
$detailed[$playlist_id] = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$this->returnJson(["success" => true, 'detailed' => $detailed]);
|
||||
break;
|
||||
case "delete":
|
||||
if($audio->canBeModifiedBy($this->user->identity))
|
||||
|
@ -653,6 +738,28 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
$audios = $stream->page($page, 10);
|
||||
$audiosCount = $stream->size();
|
||||
break;
|
||||
case "classic_search_context":
|
||||
$data = json_decode($this->postParam("context_entity"), true);
|
||||
|
||||
$params = [];
|
||||
$order = [
|
||||
"type" => $data['order'] ?? 'id',
|
||||
"invert" => (int)$data['invert'] == 1 ? true : false
|
||||
];
|
||||
|
||||
if($data['genre'] && $data['genre'] != 'any')
|
||||
$params['genre'] = $data['genre'];
|
||||
|
||||
if($data['only_performers'] && (int)$data['only_performers'] == 1)
|
||||
$params['only_performers'] = '1';
|
||||
|
||||
if($data['with_lyrics'] && (int)$data['with_lyrics'] == 1)
|
||||
$params['with_lyrics'] = '1';
|
||||
|
||||
$stream = $this->audios->find($data['query'], $params, $order);
|
||||
$audios = $stream->page($page, 10);
|
||||
$audiosCount = $stream->size();
|
||||
break;
|
||||
}
|
||||
|
||||
$pagesCount = ceil($audiosCount / $perPage);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Models\Entities\{User, Club};
|
||||
use openvk\Web\Models\Repositories\{Users, Clubs, Posts, Comments, Videos, Applications, Notes, Audios};
|
||||
use openvk\Web\Models\Repositories\{Users, Clubs, Posts, Videos, Applications, Audios};
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
||||
final class SearchPresenter extends OpenVKPresenter
|
||||
|
@ -9,21 +9,17 @@ final class SearchPresenter extends OpenVKPresenter
|
|||
private $users;
|
||||
private $clubs;
|
||||
private $posts;
|
||||
private $comments;
|
||||
private $videos;
|
||||
private $apps;
|
||||
private $notes;
|
||||
private $audios;
|
||||
|
||||
function __construct(Users $users, Clubs $clubs)
|
||||
function __construct()
|
||||
{
|
||||
$this->users = $users;
|
||||
$this->clubs = $clubs;
|
||||
$this->users = new Users;
|
||||
$this->clubs = new Clubs;
|
||||
$this->posts = new Posts;
|
||||
$this->comments = new Comments;
|
||||
$this->videos = new Videos;
|
||||
$this->apps = new Applications;
|
||||
$this->notes = new Notes;
|
||||
$this->audios = new Audios;
|
||||
|
||||
parent::__construct();
|
||||
|
@ -33,85 +29,101 @@ final class SearchPresenter extends OpenVKPresenter
|
|||
{
|
||||
$this->assertUserLoggedIn();
|
||||
|
||||
$query = $this->queryParam("query") ?? "";
|
||||
$type = $this->queryParam("type") ?? "users";
|
||||
$sorter = $this->queryParam("sort") ?? "id";
|
||||
$invert = $this->queryParam("invert") == 1 ? "ASC" : "DESC";
|
||||
$page = (int) ($this->queryParam("p") ?? 1);
|
||||
|
||||
$query = $this->queryParam("q") ?? "";
|
||||
$section = $this->queryParam("section") ?? "users";
|
||||
$order = $this->queryParam("order") ?? "id";
|
||||
$invert = (int) ($this->queryParam("invert") ?? 0) == 1;
|
||||
$page = (int) ($this->queryParam("p") ?? 1);
|
||||
|
||||
# https://youtu.be/pSAWM5YuXx8
|
||||
# https://youtu.be/FfNZRhIn2Vk
|
||||
|
||||
$repos = [
|
||||
"groups" => "clubs",
|
||||
"users" => "users",
|
||||
"posts" => "posts",
|
||||
"comments" => "comments",
|
||||
"videos" => "videos",
|
||||
"audios" => "audios",
|
||||
"apps" => "apps",
|
||||
"notes" => "notes"
|
||||
"audios_playlists" => "audios"
|
||||
];
|
||||
$parameters = [
|
||||
"ignore_private" => true,
|
||||
];
|
||||
|
||||
switch($sorter) {
|
||||
default:
|
||||
case "id":
|
||||
$sort = "id " . $invert;
|
||||
break;
|
||||
case "name":
|
||||
$sort = "first_name " . $invert;
|
||||
break;
|
||||
case "rating":
|
||||
$sort = "rating " . $invert;
|
||||
break;
|
||||
case "length":
|
||||
if($type != "audios") break;
|
||||
|
||||
$sort = "length " . $invert;
|
||||
break;
|
||||
case "listens":
|
||||
if($type != "audios") break;
|
||||
|
||||
$sort = "listens " . $invert;
|
||||
break;
|
||||
foreach($_REQUEST as $param_name => $param_value) {
|
||||
if(is_null($param_value)) continue;
|
||||
|
||||
switch($param_name) {
|
||||
default:
|
||||
$parameters[$param_name] = $param_value;
|
||||
break;
|
||||
case 'marital_status':
|
||||
case 'polit_views':
|
||||
if((int) $param_value == 0) continue;
|
||||
$parameters[$param_name] = $param_value;
|
||||
|
||||
break;
|
||||
case 'is_online':
|
||||
if((int) $param_value == 1)
|
||||
$parameters['is_online'] = 1;
|
||||
|
||||
break;
|
||||
case 'only_performers':
|
||||
if((int) $param_value == 1 || $param_value == 'on')
|
||||
$parameters['only_performers'] = true;
|
||||
|
||||
break;
|
||||
case 'with_lyrics':
|
||||
if($param_value == 'on' || $param_value == '1')
|
||||
$parameters['with_lyrics'] = true;
|
||||
|
||||
break;
|
||||
# дай бог работал этот case
|
||||
case 'from_me':
|
||||
if((int) $param_value != 1) continue;
|
||||
$parameters['from_me'] = $this->user->id;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$parameters = [
|
||||
"type" => $this->queryParam("type"),
|
||||
"city" => $this->queryParam("city") != "" ? $this->queryParam("city") : NULL,
|
||||
"maritalstatus" => $this->queryParam("maritalstatus") != 0 ? $this->queryParam("maritalstatus") : NULL,
|
||||
"with_photo" => $this->queryParam("with_photo"),
|
||||
"status" => $this->queryParam("status") != "" ? $this->queryParam("status") : NULL,
|
||||
"politViews" => $this->queryParam("politViews") != 0 ? $this->queryParam("politViews") : NULL,
|
||||
"email" => $this->queryParam("email"),
|
||||
"telegram" => $this->queryParam("telegram"),
|
||||
"site" => $this->queryParam("site") != "" ? "https://".$this->queryParam("site") : NULL,
|
||||
"address" => $this->queryParam("address"),
|
||||
"is_online" => $this->queryParam("is_online") == 1 ? 1 : NULL,
|
||||
"interests" => $this->queryParam("interests") != "" ? $this->queryParam("interests") : NULL,
|
||||
"fav_mus" => $this->queryParam("fav_mus") != "" ? $this->queryParam("fav_mus") : NULL,
|
||||
"fav_films" => $this->queryParam("fav_films") != "" ? $this->queryParam("fav_films") : NULL,
|
||||
"fav_shows" => $this->queryParam("fav_shows") != "" ? $this->queryParam("fav_shows") : NULL,
|
||||
"fav_books" => $this->queryParam("fav_books") != "" ? $this->queryParam("fav_books") : NULL,
|
||||
"fav_quote" => $this->queryParam("fav_quote") != "" ? $this->queryParam("fav_quote") : NULL,
|
||||
"hometown" => $this->queryParam("hometown") != "" ? $this->queryParam("hometown") : NULL,
|
||||
"before" => $this->queryParam("datebefore") != "" ? strtotime($this->queryParam("datebefore")) : NULL,
|
||||
"after" => $this->queryParam("dateafter") != "" ? strtotime($this->queryParam("dateafter")) : NULL,
|
||||
"gender" => $this->queryParam("gender") != "" && $this->queryParam("gender") != 2 ? $this->queryParam("gender") : NULL,
|
||||
"doNotSearchPrivate" => true,
|
||||
"only_performers" => $this->queryParam("only_performers") == "on" ? "1" : NULL,
|
||||
"with_lyrics" => $this->queryParam("with_lyrics") == "on" ? true : NULL,
|
||||
];
|
||||
|
||||
$repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type.");
|
||||
$repo = $repos[$section] or $this->throwError(400, "Bad Request", "Invalid search entity $section.");
|
||||
|
||||
$results = $this->{$repo}->find($query, $parameters, $sort);
|
||||
$iterator = $results->page($page, 14);
|
||||
$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();
|
||||
|
||||
$this->template->iterator = iterator_to_array($iterator);
|
||||
$this->template->order = $order;
|
||||
$this->template->invert = $invert;
|
||||
$this->template->data = $this->template->iterator = iterator_to_array($iterator);
|
||||
$this->template->count = $count;
|
||||
$this->template->type = $type;
|
||||
$this->template->section = $section;
|
||||
$this->template->page = $page;
|
||||
$this->template->perPage = 14;
|
||||
$this->template->perPage = OPENVK_DEFAULT_PER_PAGE;
|
||||
$this->template->query = $query;
|
||||
$this->template->atSearch = true;
|
||||
|
||||
$this->template->paginatorConf = (object) [
|
||||
"page" => $page,
|
||||
"count" => $count,
|
||||
"amount" => sizeof($this->template->data),
|
||||
"perPage" => $this->template->perPage,
|
||||
"atBottom" => false,
|
||||
"tidy" => true,
|
||||
"space" => 6,
|
||||
'pageCount' => ceil($count / $this->template->perPage),
|
||||
];
|
||||
$this->template->extendedPaginatorConf = clone $this->template->paginatorConf;
|
||||
$this->template->extendedPaginatorConf->space = 12;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
|
||||
<div class="layout">
|
||||
<div id="xhead" class="dm"></div>
|
||||
<div class="page_header{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} page_custom_header{/if}">
|
||||
<div class="page_header{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} page_custom_header{/if}{if $atSearch} search_expanded search_expanded_at_all{/if}">
|
||||
<a href="/" class="home_button{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME} home_button_custom{/if}" title="{$instance_name}">{if $instance_name != OPENVK_DEFAULT_INSTANCE_NAME}{$instance_name}{/if}</a>
|
||||
<div n:if="isset($thisUser) ? (!$thisUser->isBanned() XOR !$thisUser->isActivated()) : true" class="header_navigation">
|
||||
{ifset $thisUser}
|
||||
|
@ -96,67 +96,45 @@
|
|||
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
||||
</div>
|
||||
{else}
|
||||
<div class="link dec">
|
||||
<div class="link">
|
||||
<a href="/">{_header_home}</a>
|
||||
</div>
|
||||
<div class="link dec">
|
||||
<a href="/search?type=groups">{_header_groups}</a>
|
||||
<div class="link">
|
||||
<a href="/search?section=groups">{_header_groups}</a>
|
||||
</div>
|
||||
<div class="link dec">
|
||||
<a href="/search">{_header_search}</a>
|
||||
<div class="link">
|
||||
<a href="/search?q=§ion=users&order=rating">{_header_search}</a>
|
||||
</div>
|
||||
<div class="link dec">
|
||||
<div class="link">
|
||||
<a href="/invite">{_header_invite}</a>
|
||||
</div>
|
||||
<div class="link dec">
|
||||
<div class="link">
|
||||
<a href="/support">{_header_help} <b n:if="$ticketAnsweredCount > 0">({$ticketAnsweredCount})</b></a>
|
||||
</div>
|
||||
<div class="link dec">
|
||||
<div class="link">
|
||||
<a href="/logout?hash={urlencode($csrfToken)}">{_header_log_out}</a>
|
||||
</div>
|
||||
{var $atSearch = str_contains($_SERVER['REQUEST_URI'], "/search")}
|
||||
<div id="srch" class="{if $atSearch}nodivider{else}link{/if}">
|
||||
|
||||
{if !$atSearch}
|
||||
<form action="/search" method="get" id="searcher" style="position:relative;">
|
||||
<input autocomplete="off" id="searchInput" oninput="checkSearchTips()" onfocus="expandSearch()" onblur="decreaseSearch()" class="sr" type="search" name="query" placeholder="{_header_search}" style="height: 20px;background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px; background-color: #fff; padding-left: 18px;width: 120px;" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
||||
<select onchange="checkSearchTips()" id="typer" name="type" class="whatFind" style="display:none;top: 0px;">
|
||||
<option value="users">{_s_by_people}</option>
|
||||
<option value="groups">{_s_by_groups}</option>
|
||||
<option value="posts">{_s_by_posts}</option>
|
||||
<option value="comments">{_s_by_comments}</option>
|
||||
<option value="videos">{_s_by_videos}</option>
|
||||
<option value="apps">{_s_by_apps}</option>
|
||||
<option value="audios">{_s_by_audios}</option>
|
||||
</select>
|
||||
<div id="search_box" class='header_divider_stick'>
|
||||
<div id="search_box_fr">
|
||||
<form id='search_form' action="/search" method="get">
|
||||
<div id='search_and_one_more_wrapper'>
|
||||
<input n:attr="value => $_REQUEST['q'] ? $_REQUEST['q'] : NULL" autocomplete="off" type="search" maxlength="79" name="q" placeholder="{_header_search}" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
||||
<select name="section">
|
||||
<option n:attr="selected => $_REQUEST['section'] == 'users'" value="users">{_s_by_people}</option>
|
||||
<option n:attr="selected => $_REQUEST['section'] == 'groups'" value="groups">{_s_by_groups}</option>
|
||||
<option n:attr="selected => $_REQUEST['section'] == 'posts'" value="posts">{_s_by_posts}</option>
|
||||
<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'] == 'audios_playlists'" value="audios_playlists">{_s_by_audios_playlists}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="search_box_button">
|
||||
<span>{_header_search}</span>
|
||||
</button>
|
||||
</form>
|
||||
<div class="searchTips" id="srcht" hidden>
|
||||
<table style="border:none;border-spacing: 0;">
|
||||
<tbody id="srchrr">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{else}
|
||||
<form action="/search" method="get" id="searcher" style="margin-top: -1px;position:relative;">
|
||||
<input id="searchInput" value="{$_GET['query'] ?? ''}" type="search" class="sr" name="query" placeholder="{_header_search}" style="height: 20px; background-color: #fff; padding-left: 6px;width: 555px;" title="{_header_search} [Alt+Shift+F]" accesskey="f" />
|
||||
<select name="type" class="whatFind">
|
||||
<option value="users" {if str_contains($_SERVER['REQUEST_URI'], "type=users")}selected{/if}>{_s_by_people}</option>
|
||||
<option value="groups" {if str_contains($_SERVER['REQUEST_URI'], "type=groups")}selected{/if}>{_s_by_groups}</option>
|
||||
<option value="posts" {if str_contains($_SERVER['REQUEST_URI'], "type=posts")}selected{/if}>{_s_by_posts}</option>
|
||||
<option value="comments" {if str_contains($_SERVER['REQUEST_URI'], "type=comments")}selected{/if}>{_s_by_comments}</option>
|
||||
<option value="videos" {if str_contains($_SERVER['REQUEST_URI'], "type=videos")}selected{/if}>{_s_by_videos}</option>
|
||||
<option value="apps" {if str_contains($_SERVER['REQUEST_URI'], "type=apps")}selected{/if}>{_s_by_apps}</option>
|
||||
<option value="audios" {if str_contains($_SERVER['REQUEST_URI'], "type=audios")}selected{/if}>{_s_by_audios}</option>
|
||||
</select>
|
||||
<button class="searchBtn"><span style="color:white;font-weight: 600;font-size:12px;">{_header_search}</span></button>
|
||||
</form>
|
||||
<script>
|
||||
let els = document.querySelectorAll("div.dec")
|
||||
for(const element of els) {
|
||||
element.style.display = "none"
|
||||
}
|
||||
</script>
|
||||
{/if}
|
||||
</div>
|
||||
<div id="searchBoxFastTips"></div>
|
||||
</div>
|
||||
{/if}
|
||||
{else}
|
||||
|
@ -400,6 +378,7 @@
|
|||
{script "js/al_mentions.js"}
|
||||
{script "js/al_polls.js"}
|
||||
{script "js/al_suggestions.js"}
|
||||
{script "js/al_navigation.js"}
|
||||
|
||||
{ifset $thisUser}
|
||||
{script "js/al_notifs.js"}
|
||||
|
@ -442,7 +421,8 @@
|
|||
|
||||
<script>
|
||||
window.openvk = {
|
||||
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres}
|
||||
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres},
|
||||
"at_search": {$atSearch ?? false},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -59,66 +59,47 @@
|
|||
<input n:if="$mode == 'popular'" type="hidden" name="bigplayer_context" data-type="popular_audios" data-entity="0" data-page="1">
|
||||
<div class="bigPlayerDetector"></div>
|
||||
|
||||
<div style="width: 100%;display: flex;margin-bottom: -10px;" class="audiosDiv">
|
||||
<div style="width: 74%;" class="audiosContainer" n:if="$mode != 'playlists'">
|
||||
<div style="padding: 8px;">
|
||||
<div n:if="$audiosCount <= 0">
|
||||
{include "../components/error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_audios_thisuser") : tr("no_audios_user")) : tr("no_audios_club")}
|
||||
</div>
|
||||
<div n:if="$audiosCount > 0" class="infContainer">
|
||||
<div class="infObj" n:foreach="$audios as $audio">
|
||||
{include "player.xml", audio => $audio, club => $club}
|
||||
</div>
|
||||
<div class="audiosDiv">
|
||||
<div style="width: 74%;" class="audiosContainer audiosPaddingContainer" n:if="$mode != 'playlists'">
|
||||
<div n:if="$audiosCount <= 0" style='height: 50%;'>
|
||||
{include "../components/content_error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_audios_thisuser") : tr("no_audios_user")) : tr("no_audios_club")}
|
||||
</div>
|
||||
<div n:if="$audiosCount > 0" class="infContainer">
|
||||
<div class="infObj" n:foreach="$audios as $audio">
|
||||
{include "player.xml", audio => $audio, club => $club}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div n:if="$mode != 'new' && $mode != 'popular'">
|
||||
{include "../components/paginator.xml", conf => (object) [
|
||||
"page" => $page,
|
||||
"count" => $audiosCount,
|
||||
"amount" => sizeof($audios),
|
||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||
"atBottom" => true,
|
||||
]}
|
||||
</div>
|
||||
<div n:if="$mode != 'new' && $mode != 'popular'">
|
||||
{include "../components/paginator.xml", conf => (object) [
|
||||
"page" => $page,
|
||||
"count" => $audiosCount,
|
||||
"amount" => sizeof($audios),
|
||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||
"atBottom" => true,
|
||||
]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="width: 74%;" n:if="$mode == 'playlists'">
|
||||
<div style="padding: 8px;">
|
||||
<div n:if="$playlistsCount <= 0">
|
||||
{include "../components/error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_playlists_thisuser") : tr("no_playlists_user")) : tr("no_playlists_club")}
|
||||
</div>
|
||||
<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 class="infObj" n:foreach="$playlists as $playlist">
|
||||
<a href="/playlist{$playlist->getPrettyId()}">
|
||||
<div class="playlistCover">
|
||||
<img src="{$playlist->getCoverURL()}" alt="{_playlist_cover}">
|
||||
</div>
|
||||
</a>
|
||||
<div class="infContainer playlistContainer" n:if="$playlistsCount > 0">
|
||||
{foreach $playlists as $playlist}
|
||||
{include 'playlistListView.xml', playlist => $playlist}
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{include "../components/paginator.xml", conf => (object) [
|
||||
"page" => $page,
|
||||
"count" => $playlistsCount,
|
||||
"amount" => sizeof($playlists),
|
||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||
"atBottom" => true,
|
||||
]}
|
||||
</div>
|
||||
<div>
|
||||
{include "../components/paginator.xml", conf => (object) [
|
||||
"page" => $page,
|
||||
"count" => $playlistsCount,
|
||||
"amount" => sizeof($playlists),
|
||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||
"atBottom" => true,
|
||||
]}
|
||||
</div>
|
||||
</div>
|
||||
{include "tabs.xml"}
|
||||
|
|
|
@ -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,31 +25,36 @@
|
|||
{block header}
|
||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios{$ownerId}">{_audios}</a>
|
||||
<a href="/playlists{$ownerId}">{_playlists}</a>
|
||||
»
|
||||
{_playlist}
|
||||
{/block}
|
||||
|
||||
{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="{$playlist->getCoverURL()}" target="_blank">
|
||||
<img 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="/player/upload?playlist={$playlist->getId()}" n:if="$canEdit">{_upload_audio}</a>
|
||||
<a class="profile_link" href="/playlist{$playlist->getPrettyId()}/edit" n:if="$canEdit">{_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>
|
||||
|
||||
|
|
|
@ -5,14 +5,22 @@
|
|||
{/block}
|
||||
|
||||
{block header}
|
||||
{if !is_null($group)}
|
||||
<a href="{$group->getURL()}">{$group->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios-{$group->getId()}">{_audios}</a>
|
||||
{if !$playlist}
|
||||
{if !is_null($group)}
|
||||
<a href="{$group->getURL()}">{$group->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios-{$group->getId()}">{_audios}</a>
|
||||
{else}
|
||||
<a href="{$thisUser->getURL()}">{$thisUser->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios{$thisUser->getId()}">{_audios}</a>
|
||||
{/if}
|
||||
{else}
|
||||
<a href="{$thisUser->getURL()}">{$thisUser->getCanonicalName()}</a>
|
||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||
»
|
||||
<a href="/audios{$thisUser->getId()}">{_audios}</a>
|
||||
<a href="/playlists{$ownerId}">{_playlists}</a>
|
||||
»
|
||||
<a href="/playlist{$playlist->getPrettyId()}">{_playlist}</a>
|
||||
{/if}
|
||||
|
||||
»
|
||||
|
@ -36,6 +44,7 @@
|
|||
<input type="hidden" name="lyrics" />
|
||||
<input type="hidden" name="genre" />
|
||||
<input type="hidden" name="explicit" />
|
||||
<input type="hidden" name="unlisted" />
|
||||
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input id="audio_input" type="file" name="blob" accept="audio/*" style="display:none" />
|
||||
|
@ -43,20 +52,20 @@
|
|||
</form>
|
||||
</div><br/>
|
||||
|
||||
<span>{_you_can_also_add_audio_using} <b><a href="/search?type=audios">{_search_audio_inst}</a></b>.<span>
|
||||
<span>{_you_can_also_add_audio_using} <b><a href="/search?section=audios">{_search_audio_inst}</a></b>.<span>
|
||||
</div>
|
||||
|
||||
<div id="lastStep" style="display:none;">
|
||||
<table cellspacing="7" cellpadding="0" border="0" align="center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_audio_name}:</span></td>
|
||||
<td><input type="text" name="name" autocomplete="off" maxlength="80" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_performer}:</span></td>
|
||||
<td><input name="performer" type="text" autocomplete="off" maxlength="80" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_audio_name}:</span></td>
|
||||
<td><input type="text" name="name" autocomplete="off" maxlength="80" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_genre}:</span></td>
|
||||
<td>
|
||||
|
@ -74,7 +83,8 @@
|
|||
<tr>
|
||||
<td width="120" valign="top"></td>
|
||||
<td>
|
||||
<label><input type="checkbox" name="explicit">{_audios_explicit}</label>
|
||||
<label style='display:block'><input type="checkbox" name="explicit">{_audios_explicit}</label>
|
||||
<label><input type="checkbox" name="unlisted">{_audios_unlisted}</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -100,8 +110,24 @@
|
|||
|
||||
document.querySelector("#firstStep").style.display = "none"
|
||||
document.querySelector("#lastStep").style.display = "block"
|
||||
|
||||
function fallback() {
|
||||
console.info('Tags not found, setting default values.')
|
||||
|
||||
document.querySelector("#lastStep input[name=name]").value = files[0].name
|
||||
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||
document.querySelector("#lastStep input[name=performer]").value = tr("track_unknown");
|
||||
}
|
||||
|
||||
let tags = await id3.fromFile(files[0]);
|
||||
let tags = null
|
||||
|
||||
try {
|
||||
tags = await id3.fromFile(files[0]);
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
console.log(tags)
|
||||
if(tags != null) {
|
||||
console.log("ID" + tags.kind + " detected, setting values...");
|
||||
|
||||
|
@ -116,17 +142,31 @@
|
|||
document.querySelector("#lastStep input[name=performer]").value = tr("track_unknown");
|
||||
|
||||
if(tags.genre != null) {
|
||||
if(document.querySelector("#lastStep select[name=genre] > option[value='" + tags.genre + "']") != null) {
|
||||
document.querySelector("#lastStep select[name=genre]").value = tags.genre;
|
||||
// if there are more than one genre
|
||||
if(tags.genre.split(', ').length > 1) {
|
||||
const genres = tags.genre.split(', ')
|
||||
|
||||
genres.forEach(genre => {
|
||||
if(document.querySelector("#lastStep select[name=genre] > option[value='" + genre + "']") != null) {
|
||||
document.querySelector("#lastStep select[name=genre]").value = genre;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.warn("Unknown genre: " + tags.genre);
|
||||
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||
if(document.querySelector("#lastStep select[name=genre] > option[value='" + tags.genre + "']") != null) {
|
||||
document.querySelector("#lastStep select[name=genre]").value = tags.genre;
|
||||
} else {
|
||||
console.warn("Unknown genre: " + tags.genre);
|
||||
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||
}
|
||||
|
||||
if(tags.comments != null)
|
||||
document.querySelector("#lastStep textarea[name=lyrics]").value = tags.comments
|
||||
} else {
|
||||
document.querySelector("#lastStep input[name=name]").value = files[0].name
|
||||
document.querySelector("#lastStep select[name=genre]").value = "Other"
|
||||
document.querySelector("#lastStep input[name=performer]").value = tr("track_unknown");
|
||||
fallback()
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -147,12 +187,14 @@
|
|||
var genre_ = document.querySelector("#audio_upload input[name=genre]");
|
||||
var lyrics_ = document.querySelector("#audio_upload input[name=lyrics]");
|
||||
var explicit_ = document.querySelector("#audio_upload input[name=explicit]");
|
||||
var unlisted_ = document.querySelector("#audio_upload input[name=unlisted]");
|
||||
|
||||
name_.value = document.querySelector("#lastStep input[name=name]").value
|
||||
perf_.value = document.querySelector("#lastStep input[name=performer]").value
|
||||
genre_.value = document.querySelector("#lastStep select[name=genre]").value
|
||||
lyrics_.value = document.querySelector("#lastStep textarea[name=lyrics]").value
|
||||
explicit_.value = document.querySelector("#lastStep input[name=explicit]").checked ? "on" : "off"
|
||||
unlisted_.value = document.querySelector("#lastStep input[name=unlisted]").checked ? "on" : "off"
|
||||
|
||||
$("#audio_upload > form").trigger("submit");
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="bigPlayer">
|
||||
<div n:class="bigPlayer, $tidy ? tidy">
|
||||
<audio class="audio" />
|
||||
<div class="paddingLayer">
|
||||
<div class="playButtons">
|
||||
|
@ -25,14 +25,14 @@
|
|||
<div class="timer" style="float:right">
|
||||
<span class="time">00:00</span>
|
||||
<span>/</span>
|
||||
<span class="elapsedTime" style="cursor:pointer">-00:00</span>
|
||||
<span class="elapsedTime">-00:00</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="track" style="margin-top: -2px;">
|
||||
<div class="bigPlayerTip">00:00</div>
|
||||
<div class="selectableTrack">
|
||||
<div style="width: 95%;position: relative;">
|
||||
<div id='bigPlayerLengthSliderWrapper'>
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -41,7 +41,7 @@
|
|||
|
||||
<div class="volumePanel">
|
||||
<div class="selectableTrack">
|
||||
<div style="position: relative;width:72%">
|
||||
<div id='bigPlayerVolumeSliderWrapper'>
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{php $id = $audio->getId() . rand(0, 1000)}
|
||||
{php $isWithdrawn = $audio->isWithdrawn()}
|
||||
{php $isAvailable = $audio->isAvailable()}
|
||||
{php $editable = isset($thisUser) && $audio->canBeModifiedBy($thisUser)}
|
||||
<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" {if $hideButtons}data-prettyid="{$audio->getPrettyId()}" data-name="{$audio->getName()}"{/if} data-genre="{$audio->getGenre()}" class="audioEmbed {if !$audio->isAvailable()}processed{/if} {if $isWithdrawn}withdrawn{/if}" data-length="{$audio->getLength()}" data-keys="{json_encode($audio->getKeys())}" data-url="{$audio->getURL()}">
|
||||
<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" {if $hideButtons}data-prettyid="{$audio->getPrettyId()}" data-name="{$audio->getName()}"{/if} data-genre="{$audio->getGenre()}" class="audioEmbed {if !$isAvailable}processed{/if} {if $isWithdrawn}withdrawn{/if}" data-length="{$audio->getLength()}" data-keys="{json_encode($audio->getKeys())}" data-url="{$audio->getURL()}">
|
||||
<audio class="audio" />
|
||||
|
||||
<div id="miniplayer" class="audioEntry" style="min-height: 39px;">
|
||||
|
@ -11,29 +12,32 @@
|
|||
</div>
|
||||
|
||||
<div class="status" style="margin-top: 12px;">
|
||||
<div class="mediaInfo noOverflow" style="margin-bottom: -8px; cursor: pointer;display:flex;width: 85%;">
|
||||
<div class="mediaInfo noOverflow">
|
||||
<div class="info">
|
||||
<strong class="performer">
|
||||
<a href="/search?query=&type=audios&sort=id&only_performers=on&query={$audio->getPerformer()}">{$audio->getPerformer()}</a>
|
||||
<a href="/search?query=§ion=audios&order=listens&only_performers=on&q={$audio->getPerformer()}">{$audio->getPerformer()}</a>
|
||||
</strong>
|
||||
—
|
||||
<span class="title {if !empty($audio->getLyrics())}withLyrics{/if}">{$audio->getTitle()}</span>
|
||||
</div>
|
||||
|
||||
<div class="explicitMark" n:if="$audio->isExplicit()"></div>
|
||||
<svg n:if="$audio->isExplicit()" class="explicitMark" xmlns="http://www.w3.org/2000/svg" height="11" viewBox="0 0 11 11" width="11">
|
||||
<path d="m1 2.506v5.988a1.5 1.5 0 0 0 1.491 1.506h6.019c.827 0 1.49-.674 1.49-1.506v-5.988a1.5 1.5 0 0 0 -1.491-1.506h-6.019c-.827 0-1.49.674-1.49 1.506zm4 2.494v-1h2v-1h-3v5h3v-1h-2v-1h2v-1zm-5-2.494a2.496 2.496 0 0 1 2.491-2.506h6.019a2.5 2.5 0 0 1 2.49 2.506v5.988a2.496 2.496 0 0 1 -2.491 2.506h-6.019a2.5 2.5 0 0 1 -2.49-2.506z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="volume" style="display: flex; flex-direction: column;width:14%;">
|
||||
<span class="nobold {if !$hideButtons}hideOnHover{/if}" data-unformatted="{$audio->getLength()}" style="text-align: center;margin-top: 12px;">{$audio->getFormattedLength()}</span>
|
||||
<div class="buttons" style="margin-top: 8px;">
|
||||
<div class="buttons">
|
||||
{php $hasAudio = isset($thisUser) && $audio->isInLibraryOf($thisUser)}
|
||||
|
||||
{if !$hideButtons}
|
||||
<div class="remove-icon musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && $hasAudio" ></div>
|
||||
<div class="add-icon musicIcon hovermeicon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$hasAudio && !$isWithdrawn" ></div>
|
||||
<div class="remove-icon-group musicIcon" data-id="{$audio->getId()}" data-club="{$club->getId()}" n:if="isset($thisUser) && isset($club) && $club->canBeModifiedBy($thisUser)" ></div>
|
||||
<div class="add-icon-group musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$isWithdrawn" ></div>
|
||||
<div class="add-icon-group musicIcon hidden" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$isWithdrawn" ></div>
|
||||
<a class="download-icon musicIcon" n:if='isset($thisUser) && !$isWithdrawn && $isAvailable && OPENVK_ROOT_CONF["openvk"]["preferences"]["music"]["exposeOriginalURLs"]' href="{$audio->getOriginalURL()}" download="{$audio->getDownloadName()}"></a>
|
||||
<div class="edit-icon musicIcon" data-lyrics="{$audio->getLyrics()}" data-title="{$audio->getTitle()}" data-performer="{$audio->getPerformer()}" data-explicit="{(int)$audio->isExplicit()}" data-searchable="{(int)!$audio->isUnlisted()}" n:if="isset($thisUser) && $editable && !$isWithdrawn" ></div>
|
||||
<div class="report-icon musicIcon" data-id="{$audio->getId()}" n:if="isset($thisUser) && !$editable && !$isWithdrawn" ></div>
|
||||
{/if}
|
||||
|
@ -41,20 +45,20 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="subTracks">
|
||||
<div style="width: 100%;">
|
||||
<div class="track lengthTrack" style="margin-top: 3px;display:none">
|
||||
<div class="selectableTrack" style="width: 100%;" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||
<div style="position: relative;width: calc(100% - 18px);">
|
||||
<div class="lengthTrackWrapper">
|
||||
<div class="track lengthTrack">
|
||||
<div class="selectableTrack" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||
<div class="selectableTrackSlider">
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="width: 81px;margin-left: 16px;">
|
||||
<div class="track volumeTrack" style="margin-top: 3px;display:none">
|
||||
<div class="selectableTrack" style="width: 100%;" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||
<div style="position: relative;width: calc(100% - 18px);">
|
||||
<div class="volumeTrackWrapper">
|
||||
<div class="track volumeTrack">
|
||||
<div class="selectableTrack" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||
<div class="selectableTrackSlider">
|
||||
<div class="slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
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()}
|
||||
</span>
|
||||
<span n:if='!empty($playlist->getDescription())' class="playlistDesc noOverflow">
|
||||
{$playlist->getDescription()}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span class="playlistMeta">
|
||||
{$playlist->getMetaDescription()|noescape}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
|
@ -1,35 +1,36 @@
|
|||
<div class="searchOptions newer">
|
||||
<div class="searchList" style="margin-top:10px">
|
||||
<a n:attr="id => $mode === 'list' && $isMy ? 'used' : 'ki'" href="/audios{$thisUser->getId()}" n:if="isset($thisUser)">{_my_music}</a>
|
||||
<a href="/player/upload{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser)">{_upload_audio}</a>
|
||||
<a n:attr="id => $mode === 'new' ? 'used' : 'ki'" href="/audios/new">{_audio_new}</a>
|
||||
<a n:attr="id => $mode === 'popular' ? 'used' : 'ki'" href="/audios/popular">{_audio_popular}</a>
|
||||
<a href="/search?type=audios" n:if="isset($thisUser)">{_audio_search}</a>
|
||||
<div class='verticalGrayTabsWrapper'>
|
||||
<div class="verticalGrayTabs">
|
||||
<div class='with_padding'>
|
||||
<a n:attr="id => $mode === 'list' && $isMy ? 'used' : 'ki'" href="/audios{$thisUser->getId()}" n:if="isset($thisUser)">{_my_music}</a>
|
||||
<a href="/player/upload{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser)">{_upload_audio}</a>
|
||||
<a n:attr="id => $mode === 'new' ? 'used' : 'ki'" href="/audios/new">{_audio_new}</a>
|
||||
<a n:attr="id => $mode === 'popular' ? 'used' : 'ki'" href="/audios/popular">{_audio_popular}</a>
|
||||
<a href="/search?section=audios" n:if="isset($thisUser)">{_audio_search}</a>
|
||||
|
||||
<hr n:if="isset($thisUser)">
|
||||
<hr n:if="isset($thisUser)">
|
||||
|
||||
<a n:attr="id => $mode === 'playlists' && $ownerId == $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$thisUser->getId()}" n:if="isset($thisUser)">{_my_playlists}</a>
|
||||
<a n:attr="id => $mode === 'playlists' && $ownerId == $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$thisUser->getId()}" n:if="isset($thisUser)">{_my_playlists}</a>
|
||||
|
||||
<a n:if="isset($thisUser)" href="/audios/newPlaylist">{_new_playlist}</a>
|
||||
<a n:if="isset($thisUser)" href="/audios/newPlaylist">{_new_playlist}</a>
|
||||
|
||||
{if !$isMy && $mode !== 'popular' && $mode !== 'new'}
|
||||
<hr>
|
||||
|
||||
<a n:if="!$isMy" n:attr="id => $mode === 'list' ? 'used' : 'ki'" href="/audios{$ownerId}">{if $ownerId > 0}{_music_user}{else}{_music_club}{/if}</a>
|
||||
<a href="/player/upload?gid={abs($ownerId)}" n:if="isset($thisUser) && isset($club) && $club->canUploadAudio($thisUser)">{_upload_audio}</a>
|
||||
<a n:attr="id => $mode === 'playlists' && $ownerId != $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$ownerId}" n:if="isset($thisUser) && isset($ownerId) && !$isMy">{if $ownerId > 0}{_playlists_user}{else}{_playlists_club}{/if}</a>
|
||||
<a href="/audios/newPlaylist{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser) && $isMyClub">{_new_playlist}</a>
|
||||
{/if}
|
||||
{if !$isMy && $mode !== 'popular' && $mode !== 'new'}
|
||||
<hr>
|
||||
|
||||
<a n:if="!$isMy" n:attr="id => $mode === 'list' ? 'used' : 'ki'" href="/audios{$ownerId}">{if $ownerId > 0}{_music_user}{else}{_music_club}{/if}</a>
|
||||
<a href="/player/upload?gid={abs($ownerId)}" n:if="isset($thisUser) && isset($club) && $club->canUploadAudio($thisUser)">{_upload_audio}</a>
|
||||
<a n:attr="id => $mode === 'playlists' && $ownerId != $thisUser->getId() ? 'used' : 'ki'" href="/playlists{$ownerId}" n:if="isset($thisUser) && isset($ownerId) && !$isMy">{if $ownerId > 0}{_playlists_user}{else}{_playlists_club}{/if}</a>
|
||||
<a href="/audios/newPlaylist{if $isMyClub}?gid={abs($ownerId)}{/if}" n:if="isset($thisUser) && $isMyClub">{_new_playlist}</a>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{if $friendsAudios}
|
||||
<div class="friendsAudiosList">
|
||||
<a href="/audios{$fr->getRealId()}" style="width: 94%;padding-left: 10px;" n:foreach="$friendsAudios as $fr">
|
||||
<a href="/audios{$fr->getRealId()}" n:foreach="$friendsAudios as $fr">
|
||||
<div class="elem">
|
||||
<img src="{$fr->getAvatarURL()}" />
|
||||
|
||||
<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>
|
||||
|
|
|
@ -1,378 +1,405 @@
|
|||
{extends "../@layout.xml"}
|
||||
|
||||
{block title}
|
||||
{tr("search_for_$type")}
|
||||
{if $_GET['query']}
|
||||
- {$_GET['query']}
|
||||
{tr("search_for_$section")}
|
||||
{if $_REQUEST['q']}
|
||||
- {$_REQUEST['q']}
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block header}
|
||||
{=OPENVK_ROOT_CONF["openvk"]["appearance"]["name"]} »
|
||||
{tr("search_for_$type")}
|
||||
{tr("search_for_$section")}
|
||||
{/block}
|
||||
|
||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||
{block wrap}
|
||||
<div class="wrap2">
|
||||
<div class="wrap1">
|
||||
<div class="page_wrap">
|
||||
{if $section == 'audios' && $count > 1}
|
||||
{include "../Audio/bigplayer.xml", tidy => true}
|
||||
|
||||
{block link|strip|stripHtml}
|
||||
{if $type != "apps"}
|
||||
{$x->getURL()}
|
||||
{else}
|
||||
/app{$x->getId()}
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block preview}
|
||||
<img src="{$x->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" loading=lazy />
|
||||
{/block}
|
||||
|
||||
{block name}
|
||||
{if $type != "apps"}
|
||||
<text style="overflow: hidden;"> {$x->getCanonicalName()}
|
||||
{if $_GET['sort'] == "rating"}({$x->getRating()}%)
|
||||
{elseif $_GET['sort'] == "id"}(id{$x->getId()}){/if}</text>
|
||||
<img n:if="$x->isVerified()"
|
||||
class="name-checkmark"
|
||||
src="/assets/packages/static/openvk/img/checkmark.png"
|
||||
/>
|
||||
{else}
|
||||
{$x->getName()}
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block description}
|
||||
<table class="ugc-table">
|
||||
<tbody>
|
||||
{if $type === "users"}
|
||||
{if !is_null($_GET['status']) && $_GET['status'] != ""}
|
||||
<tr>
|
||||
<td><span class="nobold">{_status}:</span></td>
|
||||
<td>{$x->getStatus()}</td>
|
||||
</tr>
|
||||
<input type="hidden" name="bigplayer_context" data-type="classic_search_context" data-entity='{"order":"{$order}","query":"{$query}","invert":{$invert ? 1 : 0},"only_performers":{$_REQUEST['only_performers'] ? 1 : 0},"genre":"{$_REQUEST['genre']}","with_lyrics":"{$_REQUEST['with_lyrics'] ? 1 : 0}"}' data-page="{$page}">
|
||||
{/if}
|
||||
{if !is_null($_GET['city']) && $_GET['city'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_city}:</span></td>
|
||||
<td>{$x->getCity()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !is_null($_GET['city']) && $_GET['hometown'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_hometown}:</span></td>
|
||||
<td>{$x->getHometown()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !is_null($_GET['politViews']) && $_GET['politViews'] != 0 && $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_politViews}:</span></td>
|
||||
<td>{tr("politViews_".$x->getPoliticalViews())}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !is_null($_GET['email']) && $_GET['email'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_email}:</span></td>
|
||||
<td>{$x->getContactEmail()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !is_null($_GET['telegram']) && $_GET['telegram'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_telegram}:</span></td>
|
||||
<td><a href="tg://resolve?domain={$x->getTelegram()}">@{$x->getTelegram()}</a></td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !is_null($_GET['site']) && $_GET['site'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_personal_website}:</span></td>
|
||||
<td><a href="{$x->getWebsite()}">{$x->getWebsite()}</a></td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !is_null($_GET['address']) && $_GET['address'] != "" && $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_address}:</span></td>
|
||||
<td>{$x->getPhysicalAddress()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if $x->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_pronouns}: </span></td>
|
||||
<td>{$x->isFemale() ? tr("female") : ($x->isNeutral() ? tr("neutral") : tr("male"))}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="nobold">{_relationship}:</span></td>
|
||||
<td>{$x->getLocalizedMaritalStatus()}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="nobold">{_registration_date}: </span></td>
|
||||
<td>{$x->getRegistrationTime()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/if}
|
||||
<tr>
|
||||
{if !empty($x->getDescription())}
|
||||
{if $type != "apps"}
|
||||
<td>
|
||||
<span class="nobold">{_description}:</span>
|
||||
</td>
|
||||
{/if}
|
||||
<td {if $type == "apps"}style="width:400px"{/if}>
|
||||
{$x->getDescription() ?? '(' . tr("none") . ')'}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if $type == "groups"}
|
||||
<td>
|
||||
<span class="nobold">{_size}:</span>
|
||||
</td>
|
||||
<td>
|
||||
{tr("participants", $x->getFollowersCount())}
|
||||
</td>
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
<style>
|
||||
.comment, .post-divider
|
||||
{
|
||||
border:none;
|
||||
}
|
||||
</style>
|
||||
<div style="margin-top:-7px">
|
||||
{var $data = is_array($iterator) ? $iterator : iterator_to_array($iterator)}
|
||||
|
||||
{include "../components/paginator.xml", conf => (object) [
|
||||
"page" => $page,
|
||||
"count" => $count,
|
||||
"amount" => sizeof($data),
|
||||
"perPage" => $perPage ?? OPENVK_DEFAULT_PER_PAGE,
|
||||
"atBottom" => false,
|
||||
]}
|
||||
</div>
|
||||
<p style="margin-left: 15px; margin-top: 0;">
|
||||
<b>{tr("results", $count)}</b>
|
||||
</p>
|
||||
<div>
|
||||
{include searchOptions}
|
||||
|
||||
<div class="container_gray borderup" style="float:left;width:73.3%;">
|
||||
{if sizeof($data) > 0}
|
||||
{if $type == "users" || $type == "groups" || $type == "apps"}
|
||||
<div class="content" n:foreach="$data as $dat">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="{include link, x => $dat}">
|
||||
{include preview, x => $dat}
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
{ifset infotable}
|
||||
{include infotable, x => $dat}
|
||||
{else}
|
||||
<a href="{include link, x => $dat}">
|
||||
<b>
|
||||
{include name, x => $dat}
|
||||
</b>
|
||||
</a>
|
||||
<br/>
|
||||
{include description, x => $dat}
|
||||
{/ifset}
|
||||
</td>
|
||||
<td n:ifset="actions" valign="top" class="action_links" style="width: 150px;">
|
||||
{include actions, x => $dat}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{elseif $type == "posts"}
|
||||
<div n:foreach="$data as $dat" class="content">
|
||||
{if !$dat || $dat->getTargetWall() < 0 && $dat->getWallOwner()->isHideFromGlobalFeedEnabled() || !$dat->canBeViewedBy($thisUser)}
|
||||
{_closed_group_post}.
|
||||
{else}
|
||||
{include "../components/post.xml", post => $dat, commentSection => true, onWallOf => true}
|
||||
{/if}
|
||||
</div>
|
||||
{elseif $type == "comments"}
|
||||
<div n:foreach="$data as $dat" class="content">
|
||||
{if !$dat->getTarget() || $dat->getTarget()->isDeleted()}
|
||||
{_deleted_target_comment}.
|
||||
{else}
|
||||
{include "../components/comment.xml", comment => $dat, linkW => true}
|
||||
{/if}
|
||||
</div>
|
||||
{elseif $type == "videos"}
|
||||
{foreach $data as $dat}
|
||||
<div class="content">
|
||||
{include "../components/video.xml", video => $dat}
|
||||
<div class='summaryBar summaryBarFlex padding'>
|
||||
<div class='summary'>
|
||||
<b>{tr("results", $count)} {tr("showing_x_y", $page, $count)}</b>
|
||||
</div>
|
||||
{/foreach}
|
||||
{elseif $type == "audios"}
|
||||
{foreach $data as $dat}
|
||||
{include "../Audio/player.xml", audio => $dat}
|
||||
{/foreach}
|
||||
{/if}
|
||||
{else}
|
||||
{ifset customErrorMessage}
|
||||
{include customErrorMessage}
|
||||
{else}
|
||||
{include "../components/nothing.xml"}
|
||||
{/ifset}
|
||||
{/if}
|
||||
|
||||
{include "../components/paginator.xml", conf => $paginatorConf}
|
||||
</div>
|
||||
|
||||
<div class='page_wrap_content' id='search_page'>
|
||||
<div n:class='page_wrap_content_main, $section == "audios" && $count > 0 ? audios_padding'>
|
||||
{if $count > 0}
|
||||
{if $section === 'users'}
|
||||
<div class='search_content def_row_content' n:foreach="$data as $dat">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="{$dat->getURL()}">
|
||||
<img src="{$dat->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" loading='lazy' />
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<a href="{$dat->getURL()}">
|
||||
<b>
|
||||
<text style="overflow: hidden;"> {$dat->getCanonicalName()}
|
||||
{if $order == "rating"}
|
||||
({$dat->getProfileCompletenessReport()->total}%)
|
||||
{/if}
|
||||
</text>
|
||||
<img n:if="$dat->isVerified()"
|
||||
class="name-checkmark"
|
||||
src="/assets/packages/static/openvk/img/checkmark.png"
|
||||
/>
|
||||
</b>
|
||||
{if $dat->getId() == $thisUser->getId()}
|
||||
({_s_it_is_you})
|
||||
{/if}
|
||||
</a>
|
||||
|
||||
<table class="ugc-table">
|
||||
<tbody>
|
||||
{if $_REQUEST["order"] == "id"}
|
||||
<tr>
|
||||
<td><span class="nobold">ID:</span></td>
|
||||
<td>{$dat->getId()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if $dat->getPrivacySetting("page.info.read") > 1}
|
||||
<tr>
|
||||
<td><span class="nobold">{_pronouns}: </span></td>
|
||||
<td>{$dat->isFemale() ? tr("female") : ($dat->isNeutral() ? tr("neutral") : tr("male"))}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="nobold">{_relationship}:</span></td>
|
||||
<td>{$dat->getLocalizedMaritalStatus()}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="nobold">{_registration_date}: </span></td>
|
||||
<td>{$dat->getRegistrationTime()}</td>
|
||||
</tr>
|
||||
{if !empty($dat->getDescription())}
|
||||
<tr>
|
||||
<td>
|
||||
<span class="nobold">{_description}:</span>
|
||||
</td>
|
||||
<td>
|
||||
{$dat->getDescription() ?? '(' . tr("none") . ')'}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !empty($_REQUEST["fav_mus"])}
|
||||
<tr>
|
||||
<td><span class="nobold">{_favorite_music}:</span></td>
|
||||
<td>{$dat->getFavoriteMusic()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !empty($_REQUEST["fav_films"])}
|
||||
<tr>
|
||||
<td><span class="nobold">{_favorite_films}:</span></td>
|
||||
<td>{$dat->getFavoriteFilms()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !empty($_REQUEST["fav_shows"])}
|
||||
<tr>
|
||||
<td><span class="nobold">{_favorite_shows}:</span></td>
|
||||
<td>{$dat->getFavoriteShows()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{if !empty($_REQUEST["fav_books"])}
|
||||
<tr>
|
||||
<td><span class="nobold">{_favorite_books}:</span></td>
|
||||
<td>{$dat->getFavoriteBooks()}</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script n:if='$count > 0 && !empty($query)'>
|
||||
highlightText({$query}, '.page_wrap_content_main', ['text'])
|
||||
</script>
|
||||
{elseif $section === 'groups'}
|
||||
<div class='search_content def_row_content' n:foreach="$data as $dat">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="{$dat->getURL()}">
|
||||
<img src="{$dat->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" loading='lazy' />
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<a href="{$dat->getURL()}">
|
||||
<b>
|
||||
<text style="overflow: hidden;"> {$dat->getCanonicalName()}
|
||||
{if $order == "id"}
|
||||
(id{$dat->getId()})
|
||||
{/if}
|
||||
</text>
|
||||
<img n:if="$dat->isVerified()"
|
||||
class="name-checkmark"
|
||||
src="/assets/packages/static/openvk/img/checkmark.png"
|
||||
/>
|
||||
</b>
|
||||
</a>
|
||||
|
||||
<table class="ugc-table">
|
||||
<tbody>
|
||||
{if !empty($dat->getDescription())}
|
||||
<tr>
|
||||
<td>
|
||||
<span class="nobold">{_description}:</span>
|
||||
</td>
|
||||
<td data-highlight='_clubDesc'>
|
||||
{$dat->getDescription() ?? '(' . tr("none") . ')'}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
<td>
|
||||
<span class="nobold">{_size}:</span>
|
||||
</td>
|
||||
<td>
|
||||
{tr("participants", $dat->getFollowersCount())}
|
||||
</td>
|
||||
</tbody>
|
||||
</table>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script n:if='$count > 0 && !empty($query)'>
|
||||
highlightText({$query}, '.page_wrap_content_main', ['text', "td[data-highlight='_clubDesc']"])
|
||||
</script>
|
||||
{elseif $section === 'apps'}
|
||||
<div class='search_content def_row_content' n:foreach="$data as $dat">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="/app{$dat->getId()}">
|
||||
<img src="{$dat->getAvatarUrl('miniscule')}" width="75" alt="{_photo}" loading='lazy' />
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<a href="/app{$dat->getId()}">
|
||||
<b>
|
||||
<text style="overflow: hidden;">
|
||||
{$dat->getName()}
|
||||
</text>
|
||||
</b>
|
||||
</a><br/>
|
||||
<span style='margin-left: 2px;' data-highlight='_appDesc'>
|
||||
{$dat->getDescription() ?? '(' . tr("none") . ')'}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script n:if='$count > 0 && !empty($query)'>
|
||||
highlightText({$query}, '.page_wrap_content_main', ['text', "span[data-highlight='_appDesc']"])
|
||||
</script>
|
||||
{elseif $section === 'posts'}
|
||||
<div class='search_content' n:foreach="$data as $dat">
|
||||
{if !$dat || $dat->getWallOwner()->isHideFromGlobalFeedEnabled()}
|
||||
{_closed_group_post}.
|
||||
{else}
|
||||
{include "../components/post.xml", post => $dat, commentSection => true, onWallOf => true}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<script n:if='$count > 0 && !empty($query)'>
|
||||
highlightText({$query}, '.page_wrap_content_main', [".post:not(.comment) > tbody > tr > td > .post-content > .text .really_text"])
|
||||
</script>
|
||||
{elseif $section === 'videos'}
|
||||
<div class='search_content' n:foreach="$data as $dat">
|
||||
{include "../components/video.xml", video => $dat}
|
||||
</div>
|
||||
|
||||
<script n:if='$count > 0 && !empty($query)'>
|
||||
highlightText({$query}, '.page_wrap_content_main', [".video_name", ".video_description"])
|
||||
</script>
|
||||
{elseif $section === 'audios'}
|
||||
<div class='search_content' n:foreach="$data as $dat">
|
||||
{include "../Audio/player.xml", audio => $dat}
|
||||
</div>
|
||||
|
||||
<script n:if="$count > 0 && !empty($query) && empty($_REQUEST['only_performers'])">
|
||||
highlightText({$query}, '.page_wrap_content_main', [".mediaInfo .performer a", ".mediaInfo .title"])
|
||||
</script>
|
||||
{elseif $section === 'audios_playlists'}
|
||||
<div class='search_content' n:foreach="$data as $dat">
|
||||
{include "../Audio/playlistListView.xml", playlist => $dat}
|
||||
</div>
|
||||
|
||||
<script n:if="$count > 0 && !empty($query) && empty($_REQUEST['only_performers'])">
|
||||
highlightText({$query}, '.page_wrap_content_main', [".playlistName", ".playlistDesc"])
|
||||
</script>
|
||||
{/if}
|
||||
{else}
|
||||
{include "../components/content_error.xml", description => tr("no_results_by_this_query")}
|
||||
{/if}
|
||||
</div>
|
||||
<div class='page_wrap_content_options verticalGrayTabsWrapper'>
|
||||
<div class="page_wrap_content_options_list verticalGrayTabs with_padding">
|
||||
<a n:attr="id => $section === 'users' ? 'used'" href="/search?section=users&q={urlencode($query)}"> {_s_people}</a>
|
||||
<a n:attr="id => $section === 'groups' ? 'used'" href="/search?section=groups&q={urlencode($query)}"> {_s_groups}</a>
|
||||
<a n:attr="id => $section === 'posts' ? 'used'" href="/search?section=posts&q={urlencode($query)}"> {_s_posts}</a>
|
||||
<a n:attr="id => $section === 'videos' ? 'used'" href="/search?section=videos&q={urlencode($query)}"> {_s_videos}</a>
|
||||
<a n:attr="id => $section === 'apps' ? 'used'" href="/search?section=apps&q={urlencode($query)}"> {_s_apps}</a>
|
||||
<a n:attr="id => $section === 'audios' ? 'used'" href="/search?section=audios&q={urlencode($query)}"> {_s_audios}</a>
|
||||
<a n:attr="id => $section === 'audios_playlists' ? 'used'" href="/search?section=audios_playlists&q={urlencode($query)}">{_s_audios_playlists}</a>
|
||||
</div>
|
||||
|
||||
<div class='page_search_options'>
|
||||
{include searchOptions}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div n:if='$paginatorConf->pageCount > 1' class='page_content_paginator_bottom'>
|
||||
{include "../components/paginator.xml", conf => $extendedPaginatorConf}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
window.addEventListener("load", (event) => {
|
||||
document.getElementsByClassName("container_gray")[0].style.minHeight = document.getElementsByClassName("searchOptions")[0].clientHeight+"px";
|
||||
document.getElementsByClassName("searchOptions")[0].style.minHeight = document.getElementsByClassName("container_gray")[0].clientHeight-3+"px";
|
||||
})
|
||||
</script>
|
||||
{/block}
|
||||
|
||||
{block searchOptions}
|
||||
<div class="searchOptions">
|
||||
<ul class="searchList">
|
||||
<a {if $type === "users"} id="used"{/if} href="/search?type=users{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_people} {if $type === "users"} ({$count}){/if}</a>
|
||||
<a {if $type === "groups"} id="used"{/if} href="/search?type=groups{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_groups} {if $type === "groups"} ({$count}){/if}</a>
|
||||
<a {if $type === "comments"}id="used"{/if} href="/search?type=comments{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id">{_s_comments} {if $type === "comments"}({$count}){/if}</a>
|
||||
<a {if $type === "posts"} id="used"{/if} href="/search?type=posts{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_posts} {if $type === "posts"} ({$count}){/if}</a>
|
||||
<a {if $type === "videos"} id="used"{/if} href="/search?type=videos{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_videos} {if $type === "videos"} ({$count}){/if}</a>
|
||||
<a {if $type === "apps"} id="used"{/if} href="/search?type=apps{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_apps} {if $type === "apps"} ({$count}){/if}</a>
|
||||
<a {if $type === "audios"} id="used"{/if} href="/search?type=audios{if $_GET['query']}&query={urlencode($_GET['query'])}{/if}&sort=id"> {_s_audios} {if $type === "audios"} ({$count}){/if}</a>
|
||||
</ul>
|
||||
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_sort" onclick="hideParams('sort')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_s_order_by}</div>
|
||||
<div class="searchOptionBlock" id="s_sort">
|
||||
<select name="sort" form="searcher" id="sortyor">
|
||||
<option value="id" {if $_GET["sort"] == "name"}selected{/if}>{_s_order_by_id}</option>
|
||||
{if $type == "users"}
|
||||
<option value="name" {if $_GET["sort"] == "name"}selected{/if}>{_s_order_by_name}</option>
|
||||
{if OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"]}
|
||||
<option value="rating" {if $_GET["sort"] == "rating"}selected{/if}>{_s_order_by_rating}</option>
|
||||
{/if}
|
||||
<div class="search_option">
|
||||
<div class="search_option_name">
|
||||
<div class='search_option_name_ico'></div>
|
||||
{_s_order_by}
|
||||
</div>
|
||||
<div class="search_option_content">
|
||||
<select name="order" form="search_form" data-default='id'>
|
||||
{if $section == "users"}
|
||||
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_reg_date}</option>
|
||||
|
||||
{if OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"]}
|
||||
<option value="rating" n:attr="selected => $order == 'rating'">{_s_order_by_rating}</option>
|
||||
{/if}
|
||||
|
||||
{if $type == "audios"}
|
||||
<option value="length" n:attr="selected => $_GET['sort'] == 'length'">{_s_order_by_length}</option>
|
||||
<option value="listens" n:attr="selected => $_GET['sort'] == 'listens'">{_s_order_by_listens}</option>
|
||||
{/if}
|
||||
</select>
|
||||
<div id="invertor">
|
||||
<input type="checkbox" name="invert" value="1" form="searcher" {if !is_null($_GET['invert']) && $_GET['invert'] == "1"}checked{/if}>{_s_order_invert}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{if $type !== "groups" && $type !== "apps"} {* В OpenVK не сохраняется дата создания групп и приложений *}
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_dates" onclick="hideParams('dates')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_s_by_date}</div>
|
||||
<div class="searchOptionBlock" id="s_dates">
|
||||
{if $type != "users"}
|
||||
<p id="bydate">{_s_date_before}:<br>
|
||||
{elseif $section == "posts"}
|
||||
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_publishing_date}</option>
|
||||
{elseif $section == "audios"}
|
||||
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_upload_date}</option>
|
||||
{else}
|
||||
<p id="bydate">{_s_registered_before}:<br>
|
||||
<option value="id" n:attr="selected => $order == 'id'">{_s_order_by_creation_date}</option>
|
||||
{/if}
|
||||
<input type="date" name="datebefore"
|
||||
form="searcher"
|
||||
id="bydate"
|
||||
style="width:100%"
|
||||
value="{if !is_null($_GET['datebefore'])}{$_GET['datebefore']}{/if}"
|
||||
min="2019-11-19"
|
||||
max={date('Y-m-d')}></p>
|
||||
{if $type != "users"}
|
||||
<p id="bydate">{_s_date_after}:<br>
|
||||
{else}
|
||||
<p id="bydate">{_s_registered_after}:<br>
|
||||
|
||||
{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}
|
||||
<input type="date" name="dateafter"
|
||||
form="searcher"
|
||||
style="width:100%"
|
||||
id="bydate"
|
||||
value="{if !is_null($_GET['dateafter'])}{$_GET['dateafter']}{/if}"
|
||||
min="2019-11-18"
|
||||
max={date('Y-m-d')}></p>
|
||||
</div>
|
||||
</select>
|
||||
|
||||
<label n:if="$order != 'rating'">
|
||||
<input type="checkbox" name="invert" value="1" form="search_form" n:attr="checked => $_REQUEST['invert'] == '1'">
|
||||
{_s_order_invert}
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{if $type === "users"}
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_main" onclick="hideParams('main')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_main}</div>
|
||||
<div class="searchOptionBlock" id="s_main">
|
||||
<input type="text" value="{if !is_null($_GET['status'])}{$_GET['status']}{/if}" form="searcher" placeholder="{_status}" name="status">
|
||||
<input type="text" value="{if !is_null($_GET['city'])}{$_GET['city']}{/if}" form="searcher" placeholder="{_city}" name="city">
|
||||
<input type="text" value="{if !is_null($_GET['hometown'])}{$_GET['hometown']}{/if}" form="searcher" placeholder="{_hometown}" name="hometown">
|
||||
<input name="is_online" type="checkbox" {if !is_null($_GET['is_online']) && $_GET['is_online'] == "1"}checked{/if} form="searcher" value="1">{_s_now_on_site}
|
||||
</div>
|
||||
<div n:if="$section == 'users'" class="search_option">
|
||||
<div class="search_option_name">
|
||||
<div class='search_option_name_ico'></div>
|
||||
{_main}
|
||||
</div>
|
||||
|
||||
<!-- <div class="searchOption">
|
||||
<div class="searchOptionName" id="n_gender" onclick="hideParams('gender')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_gender}</div>
|
||||
<div class="searchOptionBlock" id="s_gender">
|
||||
<p><input type="radio" form="searcher" id="gend" {if $_GET['gender'] == 0}checked{/if} name="gender" value="0">{_male}</p>
|
||||
<p><input type="radio" form="searcher" id="gend1"{if $_GET['gender'] == 1}checked{/if} name="gender" value="1">{_female}</p>
|
||||
<p><input type="radio" form="searcher" id="gend2"{if $_GET['gender'] == 2 || is_null($_GET['gender'])}checked{/if} name="gender" value="2">{_s_any}</p>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_relationship" onclick="hideParams('relationship')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{ovk_proc_strtr(tr("relationship"), 14)}</div>
|
||||
<div class="searchOptionBlock" id="s_relationship">
|
||||
<select name="maritalstatus" form="searcher">
|
||||
<option n:foreach="range(0, 8) as $i" value="{$i}" {if $_GET['maritalstatus'] == $i}selected{/if} form="searcher">
|
||||
{tr("relationship_".$i)}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="search_option_content">
|
||||
<input type="text" n:attr="value => $_REQUEST['city']" form="search_form" placeholder="{_city}" name="city">
|
||||
<input type="text" n:attr="value => $_REQUEST['hometown']" form="search_form" placeholder="{_hometown}" name="hometown">
|
||||
|
||||
<label>
|
||||
<input name="is_online" type="checkbox" n:attr="checked => $_REQUEST['is_online'] == '1'" form="search_form" value="1">
|
||||
{_s_now_on_site}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_politViews" onclick="hideParams('politViews')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_politViews}</div>
|
||||
<div class="searchOptionBlock" id="s_politViews">
|
||||
<select name="politViews" form="searcher">
|
||||
<option n:foreach="range(0, 9) as $i" value="{$i}" {if $_GET['politViews'] == $i}selected{/if} form="searcher">
|
||||
<div n:if="$section == 'users'" class="search_option">
|
||||
<div class="search_option_name">
|
||||
<div class='search_option_name_ico'></div>
|
||||
{_pronouns}
|
||||
</div>
|
||||
<div class="search_option_content">
|
||||
<label><input type="radio" form="search_form" n:attr="checked => $_REQUEST['gender'] == 0" name="gender" value="0">{_male}</label>
|
||||
<label><input type="radio" form="search_form" n:attr="checked => $_REQUEST['gender'] == 1" name="gender" value="1">{_female}</label>
|
||||
<label><input type="radio" form="search_form" n:attr="checked => $_REQUEST['gender'] == 2" name="gender" value="2">{_neutral}</label>
|
||||
<label><input type="radio" form="search_form" n:attr="checked => is_null($_REQUEST['gender']) || $_REQUEST['gender'] == 3" name="gender" data-default='1' value="3">{_s_any}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div n:if="$section == 'users'" n:class="search_option, !isset($_REQUEST['polit_views']) && !isset($_REQUEST['marital_status']) ? search_option_hidden">
|
||||
<div class="search_option_name">
|
||||
<div class='search_option_name_ico'></div>
|
||||
{_s_additional}
|
||||
</div>
|
||||
<div class="search_option_content">
|
||||
<label>
|
||||
{_politViews}
|
||||
<select name="polit_views" form="search_form" data-default='0'>
|
||||
<option n:foreach="range(0, 9) as $i" value="{$i}" n:attr="selected => $_REQUEST['polit_views'] == $i">
|
||||
{tr("politViews_".$i)}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_contacts" onclick="hideParams('contacts')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_contacts}</div>
|
||||
<div class="searchOptionBlock" id="s_contacts">
|
||||
<input type="text" name="email" value="{if !is_null($_GET['email'])}{$_GET['email']}{/if}" form="searcher" placeholder="{_email}">
|
||||
<input type="text" name="telegram" value="{if !is_null($_GET['telegram'])}{$_GET['telegram']}{/if}" form="searcher" placeholder="{_telegram}"><br id="contacts">
|
||||
<input type="text" name="site" value="{if !is_null($_GET['site'])}{$_GET['site']}{/if}" form="searcher" placeholder="{_personal_website}"><br id="contacts">
|
||||
<input type="text" name="address" value="{if !is_null($_GET['address'])}{$_GET['address']}{/if}" form="searcher" placeholder="{_address}">
|
||||
</div>
|
||||
<label>
|
||||
{_relationship}
|
||||
<select name="marital_status" form="search_form" data-default='0'>
|
||||
<option n:foreach="range(0, 8) as $i" value="{$i}" n:attr="selected => $_REQUEST['marital_status'] == $i">
|
||||
{tr("relationship_".$i)}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_interests" onclick="hideParams('interests')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_interests}</div>
|
||||
<div class="searchOptionBlock" id="s_interests">
|
||||
<input type="text" value="{if !is_null($_GET['interests'])}{$_GET['interests']}{/if}" form="searcher" placeholder="{_interests}" name="interests">
|
||||
<input type="text" value="{if !is_null($_GET['fav_mus'])}{$_GET['fav_mus']}{/if}" form="searcher" placeholder="{_favorite_music}" name="fav_mus">
|
||||
<input type="text" value="{if !is_null($_GET['fav_films'])}{$_GET['fav_films']}{/if}" form="searcher" placeholder="{_favorite_films}" name="fav_films">
|
||||
<input type="text" value="{if !is_null($_GET['fav_shows'])}{$_GET['fav_shows']}{/if}" form="searcher" placeholder="{_favorite_shows}" name="fav_shows">
|
||||
<input type="text" value="{if !is_null($_GET['fav_books'])}{$_GET['fav_books']}{/if}" form="searcher" placeholder="{_favorite_books}" name="fav_books">
|
||||
<input type="text" value="{if !is_null($_GET['fav_quote'])}{$_GET['fav_quote']}{/if}" form="searcher" placeholder="{_favorite_quotes}" name="fav_quote">
|
||||
</div>
|
||||
</div>
|
||||
<div n:if="$section == 'videos'" class="search_option">
|
||||
<div class="search_option_name">
|
||||
<div class='search_option_name_ico'></div>
|
||||
{_s_main}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $type == "audios"}
|
||||
<div class="searchOption">
|
||||
<div class="searchOptionName" id="n_main_audio" onclick="hideParams('main_audio')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_s_main}</div>
|
||||
<div class="searchOptionBlock" id="s_main_audio">
|
||||
<label><input type="checkbox" name="only_performers" n:attr="checked => !empty($_GET['only_performers'])" form="searcher">{_s_only_performers}</label><br>
|
||||
<label><input type="checkbox" name="with_lyrics" n:attr="checked => !empty($_GET['with_lyrics'])" form="searcher">{_s_with_lyrics}</label>
|
||||
</div>
|
||||
<div class="search_option_content">
|
||||
<label>
|
||||
<input type="checkbox" value='1' name="only_youtube" n:attr="checked => !empty($_REQUEST['only_youtube'])" form="search_form">{_s_only_youtube}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div n:if="$section == 'audios'" class="search_option">
|
||||
<div class="search_option_name">
|
||||
<div class='search_option_name_ico'></div>
|
||||
{_s_main}
|
||||
</div>
|
||||
<div class="search_option_content">
|
||||
<label>
|
||||
<input type="checkbox" name="only_performers" n:attr="checked => !empty($_REQUEST['only_performers'])" form="search_form">{_s_only_performers}
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="with_lyrics" n:attr="checked => !empty($_REQUEST['with_lyrics'])" form="search_form">{_s_with_lyrics}
|
||||
</label>
|
||||
<label>
|
||||
{_genre}
|
||||
<select name='genre' form="search_form" data-default='any'>
|
||||
<option n:attr="selected: empty($_REQUEST['genre'])" value="any">{_s_any_single}</option>
|
||||
<option n:foreach='\openvk\Web\Models\Entities\Audio::genres as $genre' n:attr="selected: $_REQUEST['genre'] == $genre" value="{$genre}">
|
||||
{$genre}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<input class="button" type="button" id="dnt" value="{_reset}" onclick="resetSearch()">
|
||||
</div>
|
||||
|
||||
<input class="button" id="search_reset" type="button" value="{_reset}">
|
||||
{/block}
|
||||
|
|
|
@ -467,11 +467,11 @@
|
|||
</tr>
|
||||
<tr n:if="!is_null($user->getHometown())">
|
||||
<td class="label"><span class="nobold">{_hometown}:</span></td>
|
||||
<td class="data"><a href="/search?type=users&query=&hometown={urlencode($user->getHometown())}">{$user->getHometown()}</a></td>
|
||||
<td class="data"><a href="/search?section=users&q=&hometown={urlencode($user->getHometown())}">{$user->getHometown()}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><span class="nobold">{_politViews}:</span></td>
|
||||
<td class="data"><a {if $user->getPoliticalViews() != 0}href="/search?type=users&query=&politViews={$user->getPoliticalViews()}"{/if}>{var $pviews = $user->getPoliticalViews()}{_"politViews_$pviews"}</a></td>
|
||||
<td class="data">{var $pviews = $user->getPoliticalViews()}{_"politViews_$pviews"}</td>
|
||||
</tr>
|
||||
<tr n:if="!is_null($user->getBirthday())">
|
||||
<td class="label"><span class="nobold">{_birth_date}:</span></td>
|
||||
|
@ -517,7 +517,7 @@
|
|||
</tr>
|
||||
<tr n:if="!is_null($user->getCity())">
|
||||
<td class="label"><span class="nobold">{_city}:</span></td>
|
||||
<td class="data"><a href="/search?type=users&query=&city={$user->getCity()}">{$user->getCity()}</a></td>
|
||||
<td class="data"><a href="/search?type=section&q=&city={$user->getCity()}">{$user->getCity()}</a></td>
|
||||
</tr>
|
||||
<tr n:if="!is_null($user->getPhysicalAddress())">
|
||||
<td class="label"><span class="nobold">{_address}:</span></td>
|
||||
|
@ -535,7 +535,7 @@
|
|||
{var $interests = explode(", ", $user->getInterests())}
|
||||
|
||||
{foreach $interests as $interest}
|
||||
<a href="/search?type=users&query=&interests={urlencode($interest)}">{$interest}</a>{if $interest != end($interests)},{/if}
|
||||
<span>{$interest}</span>{if $interest != end($interests)},{/if}
|
||||
{/foreach}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -546,7 +546,7 @@
|
|||
{var $musics = explode(", ", $user->getFavoriteMusic())}
|
||||
|
||||
{foreach $musics as $music}
|
||||
<a href="/search?type=audios&query={urlencode($music)}">{$music}</a>{if $music != end($musics)},{/if}
|
||||
<a href="/search?section=audios&q={urlencode($music)}">{$music}</a>{if $music != end($musics)},{/if}
|
||||
{/foreach}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -556,7 +556,7 @@
|
|||
{var $films = explode(", ", $user->getFavoriteFilms())}
|
||||
|
||||
{foreach $films as $film}
|
||||
<a href="/search?type=users&query=&fav_films={urlencode($film)}">{$film}</a>{if $film != end($films)},{/if}
|
||||
<a href="/search?section=users&q=&fav_films={urlencode($film)}">{$film}</a>{if $film != end($films)},{/if}
|
||||
{/foreach}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -566,7 +566,7 @@
|
|||
{var $shows = explode(", ", $user->getFavoriteShows())}
|
||||
|
||||
{foreach $shows as $show}
|
||||
<a href="/search?type=users&query=&fav_shows={urlencode($show)}">{$show}</a>{if $show != end($shows)},{/if}
|
||||
<a href="/search?section=users&q=&fav_shows={urlencode($show)}">{$show}</a>{if $show != end($shows)},{/if}
|
||||
{/foreach}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -576,7 +576,7 @@
|
|||
{var $books = explode(", ", $user->getFavoriteBooks())}
|
||||
|
||||
{foreach $books as $book}
|
||||
<a href="/search?type=users&query=&fav_books={urlencode($book)}">{$book}</a>{if $book != end($books)},{/if}
|
||||
<a href="/search?section=users&q=&fav_books={urlencode($book)}">{$book}</a>{if $book != end($books)},{/if}
|
||||
{/foreach}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
{/block}
|
||||
|
||||
{block preview}
|
||||
<div class="video-preview" id="videoOpen" data-id="{$x->getId()}">
|
||||
<div class="video-preview" data-id="{$x->getId()}">
|
||||
<img src="{$x->getThumbnailURL()}"
|
||||
alt="{$x->getName()}"
|
||||
style="max-width: 170px; max-height: 127px; margin: auto;" />
|
||||
|
@ -41,7 +41,7 @@
|
|||
{/block}
|
||||
|
||||
{block name}
|
||||
<span id="videoOpen" data-id="{$x->getId()}" style="color:unset;">{$x->getName()}</span>
|
||||
<span data-id="{$x->getId()}" style="color:unset;">{$x->getName()}</span>
|
||||
{/block}
|
||||
|
||||
{block description}
|
||||
|
@ -51,7 +51,7 @@
|
|||
<span style="color: grey;">{_video_uploaded} {$x->getPublicationTime()}</span><br/>
|
||||
<span style="color: grey;">{_video_updated} {$x->getEditTime() ?? $x->getPublicationTime()}</span>
|
||||
<p>
|
||||
<a href="/video{$x->getPrettyId()}" id="videoOpen" data-id="{$x->getId()}">{_view_video}</a>
|
||||
<a href="/video{$x->getPrettyId()}" data-id="{$x->getId()}">{_view_video}</a>
|
||||
{if $x->getCommentsCount() > 0}| <a href="/video{$x->getPrettyId()}#comments">{_comments} ({$x->getCommentsCount()})</a>{/if}
|
||||
</p>
|
||||
{/block}
|
||||
|
|
|
@ -36,21 +36,26 @@
|
|||
</div>
|
||||
</div>
|
||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
||||
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}
|
||||
<a href="{if $correctLink}{$comment->getTargetURL()}{/if}#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}
|
||||
<span n:if="$comment->getEditTime()" class="edited editedMark">({_edited_short})</span>
|
||||
</a>
|
||||
{if !$timeOnly}
|
||||
|
|
||||
{if $comment->canBeDeletedBy($thisUser)}
|
||||
<a href="/comment{$comment->getId()}/delete">{_delete}</a> |
|
||||
<a href="/comment{$comment->getId()}/delete">{_delete}</a>
|
||||
{/if}
|
||||
{if $comment->canBeEditedBy($thisUser)}
|
||||
<a id="editPost" data-id="{$comment->getId()}">{_edit}</a> |
|
||||
|
|
||||
<a id="editPost" data-id="{$comment->getId()}">{_edit}</a>
|
||||
{/if}
|
||||
<a class="comment-reply">{_reply}</a>
|
||||
{if $thisUser->getId() != $comment->getOwner()->getId()}
|
||||
{if !$no_reply_button}
|
||||
|
|
||||
<a class="comment-reply">{_reply}</a>
|
||||
{/if}
|
||||
{if $thisUser->getId() != $author->getRealId()}
|
||||
|
|
||||
{var $canReport = true}
|
||||
| <a href="javascript:reportComment()">{_report}</a>
|
||||
<a href="javascript:reportComment()">{_report}</a>
|
||||
{/if}
|
||||
<div style="float: right; font-size: .7rem;">
|
||||
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
||||
|
@ -59,29 +64,11 @@
|
|||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
{var $target = "wall"}
|
||||
|
||||
{if get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Note"}
|
||||
{php $target = "note"}
|
||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Post"}
|
||||
{php $target = "wall"}
|
||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Photo"}
|
||||
{php $target = "photo"}
|
||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Video"}
|
||||
{php $target = "video"}
|
||||
{elseif get_class($comment->getTarget()) == "openvk\Web\Models\Entities\Topic"}
|
||||
{php $target = "topic"}
|
||||
{/if}
|
||||
|
||||
|
||||
<span n:if="$compact ?? false">
|
||||
|
||||
| <a
|
||||
{if is_null($linkW)}
|
||||
href="#_comment{$comment->getId()}"
|
||||
{else}
|
||||
href="{$target}{!is_null($comment->getTarget()) ? $comment->getTarget()->getPrettyId() : $comment->getOwner()->getId()}#_comment{$comment->getId()}"
|
||||
{/if}
|
||||
href="#_comment{$comment->getId()}"
|
||||
class="date"
|
||||
>{$comment->getPublicationTime()}</a>
|
||||
|
||||
|
|
6
Web/Presenters/templates/components/content_error.xml
Normal file
6
Web/Presenters/templates/components/content_error.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<div class='content_page_error'>
|
||||
<span>
|
||||
<b n:if="!empty($title)">{$title}<br><br></b>
|
||||
{$description}
|
||||
</span>
|
||||
</div>
|
|
@ -1,8 +1,8 @@
|
|||
{var $space = 3}
|
||||
{var $space = $conf->space ?? 3}
|
||||
{var $pageCount = ceil($conf->count / $conf->perPage)}
|
||||
|
||||
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" style="padding: 8px;">
|
||||
<div n:class="paginator, ($conf->atBottom ?? false) ? paginator-at-bottom">
|
||||
<div n:if="!($conf->page === 1 && $conf->count <= $conf->perPage)" n:attr="style => (!$conf->tidy ? 'padding: 8px;')">
|
||||
<div n:class="paginator, ($conf->atBottom ?? false) ? paginator-at-bottom, ($conf->tidy ? 'tidy')">
|
||||
<a n:if="$conf->page > $space" n:attr="class => ($conf->page === 1 ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => 1]), 'k', '&', PHP_QUERY_RFC3986)}">«</a>
|
||||
{for $j = $conf->page - ($space-1); $j <= $conf->page + ($space-1); $j++}
|
||||
<a n:if="$j > 0 && $j <= $pageCount" n:attr="class => ($conf->page === $j ? 'active')" href="?{http_build_query(array_merge($_GET, ['p' => $j]), 'k', '&', PHP_QUERY_RFC3986)}">{$j}</a>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<tr>
|
||||
<td valign="top">
|
||||
<div class="video-preview">
|
||||
<a href="/video{$video->getPrettyId()}" id="videoOpen" data-id="{$video->getId()}">
|
||||
<a href="/video{$video->getPrettyId()}" {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">
|
||||
<img src="{$video->getThumbnailURL()}"
|
||||
style="max-width: 170px; max-height: 127px; margin: auto;" >
|
||||
</a>
|
||||
|
@ -15,18 +15,18 @@
|
|||
{include infotable, x => $dat}
|
||||
{else}
|
||||
<a href="/video{$video->getPrettyId()}">
|
||||
<b id="videoOpen" data-id="{$video->getId()}">
|
||||
<b class='video_name' {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">
|
||||
{$video->getName()}
|
||||
</b>
|
||||
</a>
|
||||
<br/>
|
||||
<p>
|
||||
<span>{$video->getDescription() ?? ""}</span>
|
||||
<span class='video_description'>{$video->getDescription() ?? ""}</span>
|
||||
</p>
|
||||
<span style="color: grey;">{_video_uploaded} {$video->getPublicationTime()}</span><br/>
|
||||
|
||||
<p>
|
||||
<a href="/video{$video->getPrettyId()}" id="videoOpen" data-id="{$video->getId()}">{_view_video}</a>
|
||||
<a href="/video{$video->getPrettyId()}" {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">{_view_video}</a>
|
||||
{if $video->getCommentsCount() > 0}| <a href="/video{$video->getPrettyId()}#comments">{_comments} ({$video->getCommentsCount()})</a>{/if}
|
||||
</p>
|
||||
{/ifset}
|
||||
|
|
|
@ -162,7 +162,7 @@ class Makima
|
|||
$result->tiles = [
|
||||
new ThumbTile(1, 3, $wCover, $maxHeight), new ThumbTile(1, 1, $w, $h0),
|
||||
new ThumbTile(1, 1, $w, $h1),
|
||||
new ThumbTile(1, 1, $w, $h1),
|
||||
new ThumbTile(1, 1, $w, $h2),
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.overflowedName {
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
.audiosPaddingContainer {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.musicIcon {
|
||||
|
@ -15,10 +14,6 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.musicIcon:hover {
|
||||
filter: brightness(99%);
|
||||
}
|
||||
|
||||
.musicIcon.pressed {
|
||||
filter: brightness(150%);
|
||||
}
|
||||
|
@ -31,7 +26,15 @@
|
|||
height: 46px;
|
||||
border-bottom: 1px solid #d8d8d8;
|
||||
box-shadow: 1px 0px 8px 0px rgba(34, 60, 80, 0.2);
|
||||
position: relative;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.bigPlayer.tidy {
|
||||
width: 100%;
|
||||
margin-left: unset;
|
||||
margin-top: unset;
|
||||
}
|
||||
|
||||
.bigPlayer.floating {
|
||||
|
@ -171,11 +174,16 @@
|
|||
font-size: 10px;
|
||||
}
|
||||
|
||||
.bigPlayer .paddingLayer .trackInfo .timer .elapsedTime {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bigPlayer .paddingLayer .trackInfo .trackName {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 81%;
|
||||
height: 13px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
@ -188,6 +196,16 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bigPlayer .paddingLayer .trackPanel .track .selectableTrack > div {
|
||||
width: 95%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bigPlayer .paddingLayer .volumePanel .selectableTrack > div {
|
||||
position: relative;
|
||||
width:72%
|
||||
}
|
||||
|
||||
.audioEmbed .track > .selectableTrack, .bigPlayer .selectableTrack {
|
||||
margin-top: 3px;
|
||||
width: calc(100% - 8px);
|
||||
|
@ -214,7 +232,7 @@
|
|||
|
||||
.audioEntry.nowPlaying {
|
||||
background: #606060;
|
||||
border: 1px solid #4f4f4f;
|
||||
outline: 1px solid #4f4f4f;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
@ -224,6 +242,7 @@
|
|||
|
||||
.audioEntry.nowPlaying:hover {
|
||||
background: #4e4e4e !important;
|
||||
border-radius: inherit !important;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .performer a {
|
||||
|
@ -246,8 +265,32 @@
|
|||
color: white !important;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .buttons .musicIcon, .audioEntry.nowPlaying .explicitMark {
|
||||
filter: brightness(187%) opacity(72%);
|
||||
.audioEntry.nowPlaying .explicitMark path {
|
||||
fill: #ffffff;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .buttons .musicIcon.edit-icon {
|
||||
background-position: -152px -51px;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .buttons .musicIcon.download-icon {
|
||||
background-position: -151px -67px;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .buttons .musicIcon.add-icon {
|
||||
background-position: -94px -52px;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .buttons .musicIcon.report-icon {
|
||||
background-position: -66px -67px;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .buttons .musicIcon.remove-icon-group {
|
||||
background-position: -122px -67px;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .buttons .musicIcon.remove-icon {
|
||||
background-position: -108px -67px;
|
||||
}
|
||||
|
||||
.audioEntry {
|
||||
|
@ -264,12 +307,16 @@
|
|||
}
|
||||
|
||||
.audioEntry .subTracks {
|
||||
display: flex;
|
||||
display: none;
|
||||
padding-bottom: 5px;
|
||||
padding-left: 8px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.audioEntry .subTracks.shown {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.audioEntry .playerButton .playIcon {
|
||||
background-image: url('/assets/packages/static/openvk/img/play_buttons.gif');
|
||||
cursor: pointer;
|
||||
|
@ -290,16 +337,45 @@
|
|||
height: 23px;
|
||||
}
|
||||
|
||||
.audioEntry .status .mediaInfo {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.overflowedName {
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
width: 85% !important;
|
||||
}
|
||||
|
||||
.audioEntry .status strong {
|
||||
color: #4C4C4C;
|
||||
}
|
||||
|
||||
.audioEmbed .track {
|
||||
display: none;
|
||||
padding: 4px 0;
|
||||
padding: 0px 0;
|
||||
}
|
||||
|
||||
.audioEmbed .track, .audioEmbed.playing .track {
|
||||
.audioEmbed .track .selectableTrack {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.audioEmbed .track .selectableTrack .selectableTrackSlider {
|
||||
position: relative;
|
||||
width: calc(100% - 18px);
|
||||
}
|
||||
|
||||
.audioEmbed .subTracks .lengthTrackWrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.audioEmbed .subTracks .volumeTrackWrapper {
|
||||
width: 81px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.audioEmbed.playing .track {
|
||||
display: unset;
|
||||
}
|
||||
|
||||
|
@ -309,7 +385,7 @@
|
|||
}
|
||||
|
||||
.audioEntry:hover .buttons {
|
||||
display: block;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.audioEntry:hover .volume .hideOnHover {
|
||||
|
@ -318,11 +394,16 @@
|
|||
|
||||
.audioEntry .buttons {
|
||||
display: none;
|
||||
flex-direction: row-reverse;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: 62px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
right: 3%;
|
||||
top: 2px;
|
||||
margin-top: 7px;
|
||||
/* чтоб избежать заедания во время ховера кнопки добавления */
|
||||
clip-path: inset(0 0 0 0);
|
||||
}
|
||||
|
@ -331,18 +412,21 @@
|
|||
width: 11px;
|
||||
height: 11px;
|
||||
float: right;
|
||||
margin-right: 4px;
|
||||
margin-top: 3px;
|
||||
background-position: -137px -51px;
|
||||
}
|
||||
|
||||
.audioEntry .buttons .download-icon {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
float: right;
|
||||
background-position: -136px -67px;
|
||||
}
|
||||
|
||||
.audioEntry .buttons .add-icon {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
float: right;
|
||||
background-position: -80px -52px;
|
||||
margin-top: 3px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.audioEntry .buttons .add-icon-group {
|
||||
|
@ -350,7 +434,6 @@
|
|||
height: 11px;
|
||||
float: right;
|
||||
background-position: -94px -52px;
|
||||
margin-top: 3px;
|
||||
transition: margin-right 0.1s ease-out, opacity 0.1s ease-out;
|
||||
}
|
||||
|
||||
|
@ -358,9 +441,7 @@
|
|||
width: 12px;
|
||||
height: 11px;
|
||||
float: right;
|
||||
background-position: -67px -51px;
|
||||
margin-top: 3px;
|
||||
margin-right: 3px;
|
||||
background-position: -50px -67px;
|
||||
}
|
||||
|
||||
.add-icon-noaction {
|
||||
|
@ -374,22 +455,17 @@
|
|||
}
|
||||
|
||||
.audioEntry .buttons .remove-icon {
|
||||
margin-top: 3px;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
margin-left: 2px;
|
||||
float: right;
|
||||
background-position: -108px -52px;
|
||||
}
|
||||
|
||||
.audioEntry .buttons .remove-icon-group {
|
||||
margin-top: 3px;
|
||||
width: 13px;
|
||||
height: 11px;
|
||||
float: right;
|
||||
background-position: -122px -52px;
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.audioEmbed .lyrics {
|
||||
|
@ -410,12 +486,12 @@
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.audioEmbed.withdrawn .status > *, .audioEmbed.processed .status > *, .audioEmbed.withdrawn .playerButton > *, .audioEmbed.processed .playerButton > * {
|
||||
.audioEmbed.withdrawn .status > *, .audioEmbed.processed .playerButton > *, .audioEmbed.withdrawn .playerButton > * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.audioEmbed.withdrawn {
|
||||
filter: opacity(0.8);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.playlistCover img {
|
||||
|
@ -427,25 +503,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;
|
||||
|
@ -490,17 +596,16 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.playlistCover img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.explicitMark {
|
||||
margin-top: 2px;
|
||||
margin-left: 3px;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background: url('/assets/packages/static/openvk/img/explicit.svg');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.explicitMark path {
|
||||
fill: #828a99;
|
||||
fill-opacity: .7;
|
||||
}
|
||||
|
||||
.audioStatus span {
|
||||
|
@ -517,8 +622,14 @@
|
|||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.audiosDiv {
|
||||
width: 103.1%;
|
||||
display: flex;
|
||||
margin: 0px 0px -10px -12px;
|
||||
}
|
||||
|
||||
/* <center> 🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣*/
|
||||
.audiosDiv center span {
|
||||
.audiosDiv center span, .error_full_wrapper center span {
|
||||
color: #707070;
|
||||
margin: 120px 0px !important;
|
||||
display: block;
|
||||
|
@ -528,15 +639,6 @@
|
|||
margin-left: -10px;
|
||||
}
|
||||
|
||||
.playlistInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.playlistInfo .playlistName {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.searchList.floating {
|
||||
position: fixed;
|
||||
z-index: 199;
|
||||
|
@ -583,10 +685,13 @@
|
|||
}
|
||||
|
||||
.friendsAudiosList {
|
||||
margin-left: -7px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.friendsAudiosList > a {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.friendsAudiosList .elem {
|
||||
display: flex;
|
||||
padding: 1px 1px;
|
||||
|
@ -659,3 +764,27 @@
|
|||
.addToPlaylist {
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
#_addAudioAdditional {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
#_addAudioAdditional #_tabs {
|
||||
margin: 0px -6px;
|
||||
}
|
||||
|
||||
#_addAudioAdditional #_tabs .mb_tabs {
|
||||
background-color: unset;
|
||||
border-bottom: unset;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
#_addAudioAdditional #_tip {
|
||||
margin: 5px 0px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#_addAudioAdditional #_content {
|
||||
margin-top: 6px;
|
||||
padding: 1px;
|
||||
}
|
||||
|
|
|
@ -97,16 +97,15 @@ h1 {
|
|||
display: inline-block;
|
||||
height: 29px;
|
||||
padding: 11px 4px 0 7px;
|
||||
}
|
||||
|
||||
.header_navigation .link, .header_navigation .header_divider_stick {
|
||||
background: url('../img/divider.png') no-repeat;
|
||||
background-size: 1.5px 41px;
|
||||
}
|
||||
|
||||
.header_navigation .nodivider {
|
||||
display: inline-block;
|
||||
height: 29px;
|
||||
padding: 11px 4px 0 7px;
|
||||
background: none;
|
||||
background-size: 1.5px 41px;
|
||||
.page_header.search_expanded .header_navigation .header_divider_stick {
|
||||
background: unset;
|
||||
}
|
||||
|
||||
.header_navigation .link a {
|
||||
|
@ -1852,6 +1851,10 @@ body.scrolled .toTop:hover {
|
|||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.paginator.tidy {
|
||||
float: unset;
|
||||
}
|
||||
|
||||
.paginator-at-bottom {
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
@ -1995,6 +1998,18 @@ body.scrolled .toTop:hover {
|
|||
line-height: normal;
|
||||
}
|
||||
|
||||
.summaryBar.summaryBarFlex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.summaryBar.padding {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 8px;
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
.summaryBar .summary {
|
||||
color: #45688E;
|
||||
font-weight: bold;
|
||||
|
@ -2087,12 +2102,13 @@ table td[width="120"] {
|
|||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.mb_tab div {
|
||||
.mb_tab div, .mb_tab > a {
|
||||
padding: 5px 9px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mb_tab#active {
|
||||
background-color: #898989;
|
||||
background-color: #606060;
|
||||
}
|
||||
|
||||
.mb_tab#active a {
|
||||
|
@ -2498,159 +2514,332 @@ a.poll-retract-vote {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.searchOptions {
|
||||
overflow: hidden;
|
||||
width:25.5%;
|
||||
border-top:1px solid #E5E7E6;
|
||||
float:right;
|
||||
scrollbar-width: none;
|
||||
font-size:12px;
|
||||
background-color:#f7f7f7;
|
||||
margin-right: -7px;
|
||||
/* Da search */
|
||||
|
||||
/* Header part */
|
||||
|
||||
.header_navigation #search_box {
|
||||
display: inline-block;
|
||||
height: 29px;
|
||||
padding: 11px 4px 0 7px;
|
||||
}
|
||||
|
||||
.searchBtn {
|
||||
.header_navigation #search_box input[type='search'] {
|
||||
height: 20px;
|
||||
background: url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px;
|
||||
background-color: #fff;
|
||||
padding-left: 18px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.header_navigation #search_box input[type='search']::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header_navigation #search_box #search_box_fr form, .header_navigation #search_box #search_box_fr #search_and_one_more_wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header_navigation #search_box #searchBoxFastTips {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-top: unset;
|
||||
margin-top: -1px;
|
||||
box-shadow: 2px 3px 4px -1px rgba(34, 60, 80, 0.2);
|
||||
}
|
||||
|
||||
.header_navigation #search_box #searchBoxFastTips a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 6px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header_navigation #search_box #searchBoxFastTips a b, .header_navigation #search_box #searchBoxFastTips a span {
|
||||
display: block;
|
||||
text-transform: initial;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.header_navigation #search_box #searchBoxFastTips a:hover, .header_navigation #search_box #searchBoxFastTips a:focus {
|
||||
background: #f3f3f3;
|
||||
}
|
||||
|
||||
.header_navigation #search_box #searchBoxFastTips a .search_tip_info_block {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: baseline;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.header_navigation #search_box #searchBoxFastTips a img {
|
||||
width: 33px;
|
||||
height: 33px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.page_header.search_expanded .header_navigation #search_box #searchBoxFastTips.shown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.page_header.search_expanded .link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page_header.search_expanded #search_and_one_more_wrapper {
|
||||
width: 627px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* не говновёрстка, а пиксель-пёрфект) */
|
||||
.page_header.search_expanded.search_expanded_at_all #search_and_one_more_wrapper {
|
||||
width: 547px;
|
||||
}
|
||||
|
||||
.page_header.search_expanded #search_box input[type='search'] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header_navigation #search_box select[name='section'], .header_navigation #search_box .search_box_button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page_header.search_expanded select[name='section'] {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.page_header.search_expanded_at_all .search_box_button {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.page_header select[name='section'] {
|
||||
width: auto;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
padding: 0px 0px;
|
||||
right: 0;
|
||||
text-align: right;
|
||||
border-left: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.header_navigation #search_box .search_box_button {
|
||||
border: solid 1px #575757;
|
||||
background-color: #696969;
|
||||
color:white;
|
||||
margin-left: -11px;
|
||||
padding-bottom:2px;
|
||||
width:80px;
|
||||
color: #ffffff;
|
||||
padding: 1px 0px 1px 0px;
|
||||
width: 80px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 2px 0px 0px rgba(255, 255, 255, 0.18) inset;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.searchBtn:active {
|
||||
.header_navigation #search_box .search_box_button span {
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.header_navigation #search_box .search_box_button:active {
|
||||
border: solid 1px #666666;
|
||||
background-color: #696969;
|
||||
color:white;
|
||||
box-shadow: 0px -2px 0px 0px rgba(255, 255, 255, 0.18) inset;
|
||||
}
|
||||
|
||||
.searchList {
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
padding-left:0px;
|
||||
}
|
||||
|
||||
.searchList #used {
|
||||
margin-left:0px;
|
||||
color: white !important;
|
||||
padding:2px;
|
||||
padding-top:5px;
|
||||
padding-bottom:5px;
|
||||
border: solid 0.125rem #4F4F4F;
|
||||
background: #606060;
|
||||
margin-bottom:2px;
|
||||
padding-left:9px;
|
||||
width:87%;
|
||||
}
|
||||
|
||||
.searchList #used a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.sr:focus {
|
||||
outline:none;
|
||||
}
|
||||
|
||||
.searchHide {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.searchList li, .searchList a
|
||||
{
|
||||
/* Search layout */
|
||||
#search_page {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.page_content_paginator_bottom {
|
||||
background: #f7f7f7;
|
||||
border-top: 1px solid #d8d8d8;
|
||||
padding: 8px 8px;
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
.page_wrap_content_main {
|
||||
padding: 3px 3px;
|
||||
width: 74%;
|
||||
}
|
||||
|
||||
.page_wrap_content_main.audios_padding {
|
||||
padding: 8px 8px;
|
||||
}
|
||||
|
||||
.page_wrap_content_main .def_row_content {
|
||||
border-bottom: #ECECEC solid 1px;
|
||||
padding: 3px 1px;
|
||||
}
|
||||
|
||||
.page_wrap_content_main .def_row_content:first-of-type {
|
||||
padding: 0px 1px 3px 1px;
|
||||
}
|
||||
|
||||
.page_wrap_content_main .search_content:first-of-type .post {
|
||||
border-top: unset;
|
||||
padding-top: unset;
|
||||
}
|
||||
|
||||
.page_wrap_content_main .search_content:last-of-type .post, .page_wrap_content_main .def_row_content:last-of-type {
|
||||
border-bottom: unset;
|
||||
padding-bottom: unset;
|
||||
}
|
||||
|
||||
.verticalGrayTabsWrapper {
|
||||
width: 25.5%;
|
||||
border-top: 1px solid #E5E7E6;
|
||||
border-left: 1px solid #d8d8d8;
|
||||
scrollbar-width: none;
|
||||
font-size: 12px;
|
||||
background-color:#f7f7f7;
|
||||
}
|
||||
|
||||
.searchList, .verticalGrayTabs {
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
padding-left: 0px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.searchList hr, .verticalGrayTabs hr {
|
||||
width: 153px;
|
||||
margin-left: 0px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.verticalGrayTabs.with_padding, .verticalGrayTabs > .with_padding {
|
||||
padding: 4px 4px 4px 4px;
|
||||
}
|
||||
|
||||
.searchList #used, .verticalGrayTabs #used {
|
||||
color: #ffffff !important;
|
||||
padding: 5px 9px 5px 9px;
|
||||
border: solid 0.125rem #4F4F4F;
|
||||
background: #606060;
|
||||
}
|
||||
|
||||
.searchList #used a, .verticalGrayTabs #used a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.searchList li, .searchList a, .verticalGrayTabs a {
|
||||
display: block;
|
||||
margin-left:0px;
|
||||
font-size: 12px;
|
||||
color: #2B587A !important;
|
||||
cursor:pointer;
|
||||
padding:2px;
|
||||
padding-top:5px;
|
||||
padding-bottom:5px;
|
||||
margin-bottom:2px;
|
||||
padding-left:9px;
|
||||
cursor: pointer;
|
||||
padding: 5px 9px 5px 9px;
|
||||
}
|
||||
|
||||
.searchList li a {
|
||||
min-width:100%;
|
||||
}
|
||||
|
||||
.searchList a {
|
||||
min-width: 88%;
|
||||
}
|
||||
|
||||
.searchList a:hover {
|
||||
.searchList a:hover, .verticalGrayTabs a:hover {
|
||||
margin-left: 0px;
|
||||
color: #2B587A !important;
|
||||
background: #ebebeb;
|
||||
padding: 2px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
margin-bottom: 2px;
|
||||
padding-left: 9px;
|
||||
width: 89.9%;
|
||||
}
|
||||
|
||||
.whatFind {
|
||||
color:rgb(128, 128, 128);
|
||||
background:none;
|
||||
border:none;
|
||||
position:absolute;
|
||||
width:150px;
|
||||
cursor:pointer;
|
||||
right:80px;
|
||||
text-align:right;
|
||||
margin-top: 0.5px;
|
||||
.highlight {
|
||||
background: #ffea6d;
|
||||
border-bottom: 1px solid #c7c727;
|
||||
font-weight: bolder;
|
||||
padding: 0px 1px;
|
||||
}
|
||||
|
||||
.searchOptionName {
|
||||
cursor:pointer;
|
||||
background-color: #EAEAEA;
|
||||
padding-left:5px;
|
||||
padding-top:5px;
|
||||
padding-bottom:5px;
|
||||
width: 90%;
|
||||
font-weight: 600;
|
||||
color: #585858;
|
||||
border-bottom: 2px solid #E4E4E4;
|
||||
/* Options */
|
||||
|
||||
.page_wrap_content .page_search_options {
|
||||
padding: 0px 4px 4px 4px;
|
||||
}
|
||||
|
||||
.searchOption {
|
||||
.page_wrap_content .page_search_options .search_option {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.searchOptionBlock
|
||||
{
|
||||
.page_wrap_content .page_search_options .search_option .search_option_name_ico {
|
||||
width: 9px;
|
||||
height: 8px;
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
background: url('/assets/packages/static/openvk/img/arrows.png');
|
||||
}
|
||||
|
||||
.page_wrap_content .page_search_options .search_option.search_option_hidden .search_option_name_ico {
|
||||
background-position: -9px 0px;
|
||||
}
|
||||
|
||||
.page_wrap_content .page_search_options .search_option.search_option_hidden .search_option_content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page_wrap_content .page_search_options .search_option .search_option_name {
|
||||
cursor: pointer;
|
||||
background-color: #EAEAEA;
|
||||
padding: 5px 5px 5px 5px;
|
||||
font-weight: 600;
|
||||
color: #585858;
|
||||
border-bottom: 2px solid #E4E4E4;
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.page_wrap_content .page_search_options .search_option .search_option_content {
|
||||
margin-top: -5px;
|
||||
padding-top:10px;
|
||||
max-width:92%;
|
||||
padding-bottom:6px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.searchOptionBlock select
|
||||
{
|
||||
padding-left:7px;
|
||||
padding-top:3px;
|
||||
padding-bottom:3px;
|
||||
cursor:pointer;
|
||||
.page_wrap_content .page_search_options .search_option .search_option_content label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.searchOptionBlock input[type=text], input[type=date]
|
||||
{
|
||||
margin-bottom:5px;
|
||||
.page_wrap_content .page_search_options .search_option .search_option_content select {
|
||||
padding-left: 3px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.borderup
|
||||
{
|
||||
border-top:1px solid #E5E7E6;
|
||||
.page_wrap_content .page_search_options #search_reset {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#searchInput
|
||||
{
|
||||
transition: .3s linear;
|
||||
.page_wrap_content .page_search_options .search_option .search_option_content input[type=text], .page_wrap_content .page_search_options .search_option .search_option_content input[type=date] {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.content_page_error {
|
||||
background: white;
|
||||
border: #DEDEDE solid 1px;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content_page_error span {
|
||||
color: #707070;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Da search end. */
|
||||
|
||||
#standaloneCommentBox {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
@ -2668,52 +2857,6 @@ a.poll-retract-vote {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.searchTips
|
||||
{
|
||||
position: absolute;
|
||||
background: white;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
padding-bottom: 6px;
|
||||
border: 1px solid #C0CAD5;
|
||||
border-top: 0px;
|
||||
width: fit-content;
|
||||
z-index: 666666;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.searchTips td
|
||||
{
|
||||
color: black;
|
||||
padding: 3px;
|
||||
font-weight: lighter;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.searchTips td .desq
|
||||
{
|
||||
margin-top: -9px;
|
||||
}
|
||||
|
||||
.restip td a:hover
|
||||
{
|
||||
color: black;
|
||||
font-weight: lighter;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.searchTips .restip
|
||||
{
|
||||
padding-right: 10px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.searchTips .restip:hover
|
||||
{
|
||||
background: rgb(236, 235, 235);
|
||||
}
|
||||
|
||||
.attachment_note_icon {
|
||||
max-width: 9px;
|
||||
}
|
||||
|
@ -3045,26 +3188,12 @@ body.article .floating_sidebar, body.article .page_content {
|
|||
background: #E9F0F1 !important;
|
||||
}
|
||||
|
||||
.searchOptions.newer {
|
||||
padding-left: 6px;
|
||||
border-top: unset !important;
|
||||
height: unset !important;
|
||||
border-left: 1px solid #d8d8d8;
|
||||
width: 26% !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
background-color: #d8d8d8;
|
||||
border: none;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.searchList hr {
|
||||
width: 153px;
|
||||
margin-left: 0px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.showMore, .showMoreAudiosPlaylist {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
@ -3083,3 +3212,53 @@ hr {
|
|||
background-position: 50% !important;
|
||||
}
|
||||
|
||||
.entity_vertical_list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
height: 197px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.entity_vertical_list .entity_vertical_list_item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.entity_vertical_list .entity_vertical_list_item .first_column {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.entity_vertical_list .entity_vertical_list_item .avatar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.entity_vertical_list .entity_vertical_list_item img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.entity_vertical_list .entity_vertical_list_item .info {
|
||||
width: 300px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.entity_vertical_list.mini .entity_vertical_list_item img {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
#gif_loader {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
background-image: url('/assets/packages/static/openvk/img/loading_mini.gif');
|
||||
width: 30px;
|
||||
height: 7px;
|
||||
}
|
||||
|
|
BIN
Web/static/img/arrows.png
Normal file
BIN
Web/static/img/arrows.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 219 B |
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 184 B |
Binary file not shown.
Before Width: | Height: | Size: 169 B |
|
@ -313,10 +313,14 @@ class bigPlayer {
|
|||
})
|
||||
|
||||
u(".bigPlayer .trackInfo b").on("click", (e) => {
|
||||
window.location.assign(`/search?query=${e.currentTarget.innerHTML}&type=audios&only_performers=on`)
|
||||
window.location.assign(`/search?q=${e.currentTarget.innerHTML}§ion=audios&only_performers=on`)
|
||||
})
|
||||
|
||||
u(document).on("keydown", (e) => {
|
||||
if(document.activeElement.closest('.page_header')) {
|
||||
return
|
||||
}
|
||||
|
||||
if(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", " "].includes(e.key)) {
|
||||
if(document.querySelector(".ovk-diag-cont") != null)
|
||||
return
|
||||
|
@ -349,6 +353,10 @@ class bigPlayer {
|
|||
})
|
||||
|
||||
u(document).on("keyup", (e) => {
|
||||
if(document.activeElement.closest('.page_header')) {
|
||||
return
|
||||
}
|
||||
|
||||
if([87, 65, 83, 68, 82, 77].includes(e.keyCode)) {
|
||||
if(document.querySelector(".ovk-diag-cont") != null)
|
||||
return
|
||||
|
@ -644,34 +652,10 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
let type = context.dataset.type
|
||||
let entity = context.dataset.entity
|
||||
window.player = new bigPlayer(type, entity, context.dataset.page)
|
||||
|
||||
let bigplayer = document.querySelector('.bigPlayerDetector')
|
||||
|
||||
let bigPlayerObserver = new IntersectionObserver(entries => {
|
||||
entries.forEach(x => {
|
||||
if(x.isIntersecting) {
|
||||
document.querySelector('.bigPlayer').classList.remove("floating")
|
||||
//document.querySelector('.searchOptions .searchList').classList.remove("floating")
|
||||
document.querySelector('.bigPlayerDetector').style.marginTop = "0px"
|
||||
} else {
|
||||
//document.querySelector('.searchOptions .searchList').classList.add("floating")
|
||||
document.querySelector('.bigPlayer').classList.add("floating")
|
||||
document.querySelector('.bigPlayerDetector').style.marginTop = "46px"
|
||||
}
|
||||
});
|
||||
}, {
|
||||
root: null,
|
||||
rootMargin: "0px",
|
||||
threshold: 0
|
||||
});
|
||||
|
||||
if(bigplayer != null)
|
||||
bigPlayerObserver.observe(bigplayer);
|
||||
}
|
||||
|
||||
$(document).on("mouseover mouseleave", `.audioEntry .mediaInfo`, (e) => {
|
||||
const info = e.currentTarget.closest(".mediaInfo")
|
||||
const overfl = info.querySelector(".info")
|
||||
|
||||
if(e.originalEvent.type == "mouseleave" || e.originalEvent.type == "mouseout") {
|
||||
info.classList.add("noOverflow")
|
||||
|
@ -765,12 +749,15 @@ function initPlayer(id, keys, url, length) {
|
|||
playButton.removeClass("paused")
|
||||
document.querySelector('link[rel="icon"], link[rel="shortcut icon"]').setAttribute("href", "/assets/packages/static/openvk/img/favicons/favicon24_playing.png")
|
||||
}
|
||||
|
||||
|
||||
u('.subTracks').nodes.forEach(el => {
|
||||
el.classList.remove('shown')
|
||||
})
|
||||
|
||||
u(`#audioEmbed-${ id} .subTracks`).addClass('shown')
|
||||
if(!$(`#audioEmbed-${ id}`).hasClass("havePlayed")) {
|
||||
$(`#audioEmbed-${ id}`).addClass("havePlayed")
|
||||
|
||||
$(`#audioEmbed-${ id} .track`).toggle()
|
||||
|
||||
$.post(`/audio${playerObject.dataset.realid}/listen`, {
|
||||
hash: u("meta[name=csrf]").attr("value")
|
||||
});
|
||||
|
@ -778,14 +765,14 @@ function initPlayer(id, keys, url, length) {
|
|||
};
|
||||
|
||||
const hideTracks = () => {
|
||||
$(`#audioEmbed-${ id} .track`).toggle()
|
||||
$(`#audioEmbed-${ id} .track`).removeClass('shown')
|
||||
$(`#audioEmbed-${ id}`).removeClass("havePlayed")
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -795,6 +782,10 @@ function initPlayer(id, keys, url, length) {
|
|||
try {
|
||||
nextPlayer = thisPlayer.closest(".audio").nextElementSibling.querySelector(".audioEmbed")
|
||||
} catch(e) {return}
|
||||
} else if(thisPlayer.closest(".search_content") != null) {
|
||||
try {
|
||||
nextPlayer = thisPlayer.closest(".search_content").nextElementSibling.querySelector(".audioEmbed")
|
||||
} catch(e) {return}
|
||||
} else {
|
||||
nextPlayer = thisPlayer.nextElementSibling
|
||||
}
|
||||
|
@ -812,7 +803,13 @@ function initPlayer(id, keys, url, length) {
|
|||
hideTracks()
|
||||
})
|
||||
|
||||
u(`#audioEmbed-${ id} .lengthTrack > div`).on("click", (e) => {
|
||||
u(`#audioEmbed-${ id} .lengthTrack > div`).on("click mouseup mousemove", (e) => {
|
||||
if(e.type == "mousemove") {
|
||||
let buttonsPresseed = _bsdnUnwrapBitMask(e.buttons)
|
||||
if(!buttonsPresseed[0])
|
||||
return;
|
||||
}
|
||||
|
||||
let rect = document.querySelector("#audioEmbed-" + id + " .selectableTrack").getBoundingClientRect();
|
||||
const width = e.clientX - rect.left;
|
||||
const time = Math.ceil((width * length) / (rect.right - rect.left));
|
||||
|
@ -832,7 +829,7 @@ function initPlayer(id, keys, url, length) {
|
|||
const width = e.clientX - rect.left;
|
||||
const volume = (width * 1) / (rect.right - rect.left);
|
||||
|
||||
audio.volume = volume;
|
||||
audio.volume = Math.max(0, volume);
|
||||
});
|
||||
|
||||
audio.volume = localStorage.volume ?? 0.75
|
||||
|
@ -899,7 +896,7 @@ $(document).on("click", ".musicIcon.edit-icon", (e) => {
|
|||
if(response.success) {
|
||||
let perf = player.querySelector(".performer a")
|
||||
perf.innerHTML = escapeHtml(response.new_info.performer)
|
||||
perf.setAttribute("href", "/search?query=&type=audios&sort=id&only_performers=on&query="+response.new_info.performer)
|
||||
perf.setAttribute("href", "/search?q=§ion=audios&order=listens&only_performers=on&q="+response.new_info.performer)
|
||||
|
||||
e.target.setAttribute("data-performer", escapeHtml(response.new_info.performer))
|
||||
|
||||
|
@ -965,28 +962,29 @@ $(document).on("click", ".musicIcon.edit-icon", (e) => {
|
|||
|
||||
u(".ovk-diag-body #_fullyDeleteAudio").on("click", (e) => {
|
||||
u("body").removeClass("dimmed");
|
||||
u(".ovk-diag-cont").remove();
|
||||
document.querySelector("html").style.overflowY = "scroll"
|
||||
|
||||
u(".ovk-diag-cont").remove();
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: `/audio${id}/action?act=delete`,
|
||||
data: {
|
||||
hash: u("meta[name=csrf]").attr("value")
|
||||
},
|
||||
success: (response) => {
|
||||
if(response.success)
|
||||
u(player).remove()
|
||||
else
|
||||
fastError(response.flash.message)
|
||||
}
|
||||
});
|
||||
MessageBox(tr('confirm'), tr('confirm_deleting_audio'), [tr('yes'), tr('no')], [() => {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: `/audio${id}/action?act=delete`,
|
||||
data: {
|
||||
hash: u("meta[name=csrf]").attr("value")
|
||||
},
|
||||
success: (response) => {
|
||||
if(response.success)
|
||||
u(player).remove()
|
||||
else
|
||||
fastError(response.flash.message)
|
||||
}
|
||||
});
|
||||
}, () => {Function.noop}])
|
||||
})
|
||||
})
|
||||
|
||||
$(document).on("click", ".title.withLyrics", (e) => {
|
||||
let parent = e.currentTarget.closest(".audioEmbed")
|
||||
const parent = e.currentTarget.closest(".audioEmbed")
|
||||
|
||||
parent.querySelector(".lyrics").classList.toggle("showed")
|
||||
})
|
||||
|
@ -994,7 +992,12 @@ $(document).on("click", ".title.withLyrics", (e) => {
|
|||
$(document).on("click", ".musicIcon.remove-icon", (e) => {
|
||||
e.stopImmediatePropagation()
|
||||
|
||||
let id = e.currentTarget.dataset.id
|
||||
const id = e.currentTarget.dataset.id
|
||||
if(e.detail > 1 || e.altKey) {
|
||||
const player = e.target.closest('.audioEmbed')
|
||||
player.querySelector('.add-icon-group').click()
|
||||
return
|
||||
}
|
||||
|
||||
let formdata = new FormData()
|
||||
formdata.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
|
@ -1031,7 +1034,7 @@ $(document).on("click", ".musicIcon.remove-icon-group", (e) => {
|
|||
e.stopImmediatePropagation()
|
||||
|
||||
let id = e.currentTarget.dataset.id
|
||||
|
||||
|
||||
let formdata = new FormData()
|
||||
formdata.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
formdata.append("club", e.currentTarget.dataset.club)
|
||||
|
@ -1058,59 +1061,218 @@ $(document).on("click", ".musicIcon.remove-icon-group", (e) => {
|
|||
})
|
||||
|
||||
$(document).on("click", ".musicIcon.add-icon-group", async (ev) => {
|
||||
let body = `
|
||||
${tr("what_club_add")}
|
||||
<div style="margin-top: 4px;">
|
||||
<select id="addIconsWindow" style="width: 59%;"></select>
|
||||
<input name="addButton" type="button" class="button" value="${tr("add")}">
|
||||
let current_tab = 'club';
|
||||
const id = Number(ev.target.dataset.id)
|
||||
const body = `
|
||||
<div id='_addAudioAdditional'>
|
||||
<div id='_tabs'>
|
||||
<div class="mb_tabs">
|
||||
<div class="mb_tab" data-name='club'>
|
||||
<a>
|
||||
${tr('to_club')}
|
||||
</a>
|
||||
</div>
|
||||
<div class="mb_tab" data-name='playlist'>
|
||||
<a>
|
||||
${tr('to_playlist')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span id='_tip'>${tr('add_audio_limitations')}</span>
|
||||
<div id='_content'></div>
|
||||
</div>
|
||||
<span class="errorPlace"></span>
|
||||
`
|
||||
MessageBox(tr("add_audio_to_club"), body, [tr("close")], [Function.noop])
|
||||
|
||||
document.querySelector(".ovk-diag-body").style.padding = "11px"
|
||||
|
||||
if(window.openvk.writeableClubs == null) {
|
||||
try {
|
||||
window.openvk.writeableClubs = await API.Groups.getWriteableClubs()
|
||||
} catch (e) {
|
||||
document.querySelector(".errorPlace").innerHTML = tr("no_access_clubs")
|
||||
document.querySelector(".ovk-diag-body input[name='addButton']").classList.add("lagged")
|
||||
MessageBox(tr("add_audio"), body, [tr("cancel"), tr("add")], [Function.noop, () => {
|
||||
const ids = []
|
||||
u('#_content .entity_vertical_list_item').nodes.forEach(item => {
|
||||
const _checkbox = item.querySelector(`input[type='checkbox'][name='add_to']`)
|
||||
if(_checkbox.checked) {
|
||||
ids.push(item.dataset.id)
|
||||
}
|
||||
})
|
||||
|
||||
if(ids.length < 1 || ids.length > 10) {
|
||||
return
|
||||
}
|
||||
|
||||
console.log(ids)
|
||||
|
||||
switch(current_tab) {
|
||||
case 'club':
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: `/audio${id}/action?act=add_to_club`,
|
||||
data: {
|
||||
hash: u("meta[name=csrf]").attr("value"),
|
||||
clubs: ids.join(',')
|
||||
},
|
||||
success: (response) => {
|
||||
if(!response.success)
|
||||
fastError(response.flash.message)
|
||||
else
|
||||
NewNotification(tr("audio_was_successfully_added"), '')
|
||||
}
|
||||
})
|
||||
|
||||
break
|
||||
case 'playlist':
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: `/audio${id}/action?act=add_to_playlist`,
|
||||
data: {
|
||||
hash: u("meta[name=csrf]").attr("value"),
|
||||
playlists: ids.join(',')
|
||||
},
|
||||
success: (response) => {
|
||||
if(!response.success)
|
||||
fastError(response.flash.message)
|
||||
else
|
||||
NewNotification(tr("audio_was_successfully_added"), '')
|
||||
}
|
||||
})
|
||||
|
||||
break
|
||||
}
|
||||
}])
|
||||
|
||||
u(".ovk-diag-body").attr('style', 'padding:0px;height: 260px;')
|
||||
|
||||
async function switchTab(tab = 'club') {
|
||||
current_tab = tab
|
||||
u(`#_addAudioAdditional .mb_tab`).attr('id', 'ki')
|
||||
u(`#_addAudioAdditional .mb_tab[data-name='${tab}']`).attr('id', 'active')
|
||||
|
||||
switch(tab) {
|
||||
case 'club':
|
||||
u("#_content").html(`<div class='entity_vertical_list mini'></div>`)
|
||||
if(window.openvk.writeableClubs == null) {
|
||||
u('.entity_vertical_list').append(`<div id='gif_loader'></div>`)
|
||||
|
||||
try {
|
||||
window.openvk.writeableClubs = await API.Groups.getWriteableClubs()
|
||||
} catch (e) {
|
||||
u("#_content").html(tr("no_access_clubs"))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
u('.entity_vertical_list #gif_loader').remove()
|
||||
}
|
||||
|
||||
window.openvk.writeableClubs.forEach(el => {
|
||||
u("#_content .entity_vertical_list").append(`
|
||||
<label class='entity_vertical_list_item with_third_column' data-id='${el.id}'>
|
||||
<div class='first_column'>
|
||||
<a href='/club${el.id}' class='avatar'>
|
||||
<img src='${el.avatar}' alt='avatar'>
|
||||
</a>
|
||||
|
||||
<div class='info'>
|
||||
<b class='noOverflow' value="${el.id}">${ovk_proc_strtr(escapeHtml(el.name), 100)}</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='third_column'>
|
||||
<input type='checkbox' name='add_to'>
|
||||
</div>
|
||||
</label>
|
||||
`)
|
||||
})
|
||||
break
|
||||
case 'playlist':
|
||||
const per_page = 10
|
||||
let page = 0
|
||||
u("#_content").html(`<div class='entity_vertical_list mini'></div>`)
|
||||
|
||||
async function recievePlaylists(s_page) {
|
||||
res = await fetch(`/method/audio.searchAlbums?auth_mechanism=roaming&query=&limit=10&offset=${s_page * per_page}&from_me=1`)
|
||||
res = await res.json()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
function appendPlaylists(response) {
|
||||
response.items.forEach(el => {
|
||||
u("#_content .entity_vertical_list").append(`
|
||||
<label class='entity_vertical_list_item with_third_column' data-id='${el.owner_id}_${el.id}'>
|
||||
<div class='first_column'>
|
||||
<a href='/playlist${el.owner_id}_${el.id}' class='avatar'>
|
||||
<img src='${el.cover_url}' alt='cover'>
|
||||
</a>
|
||||
|
||||
<div class='info'>
|
||||
<b class='noOverflow' value="${el.owner_id}_${el.id}">${ovk_proc_strtr(escapeHtml(el.title), 100)}</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='third_column'>
|
||||
<input type='checkbox' name='add_to'>
|
||||
</div>
|
||||
</label>
|
||||
`)
|
||||
})
|
||||
|
||||
if(response.count > per_page * page) {
|
||||
u("#_content .entity_vertical_list").append(`<a id='_pladdwinshowmore'>${tr('show_more')}</a>`)
|
||||
}
|
||||
}
|
||||
|
||||
if(window.openvk.writeablePlaylists == null) {
|
||||
u('.entity_vertical_list').append(`<div id='gif_loader'></div>`)
|
||||
|
||||
try {
|
||||
res = await recievePlaylists(page)
|
||||
page += 1
|
||||
window.openvk.writeablePlaylists = res.response
|
||||
|
||||
if(!window.openvk.writeablePlaylists || window.openvk.writeablePlaylists.count < 1) {
|
||||
throw new Error
|
||||
}
|
||||
} catch (e) {
|
||||
u("#_content").html(tr("no_access_playlists"))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
u('.entity_vertical_list #gif_loader').remove()
|
||||
}
|
||||
|
||||
appendPlaylists(window.openvk.writeablePlaylists)
|
||||
|
||||
u('#_addAudioAdditional').on('click', '#_pladdwinshowmore', async (e) => {
|
||||
e.target.outerHTML = ''
|
||||
|
||||
res = await recievePlaylists(page)
|
||||
page += 1
|
||||
|
||||
appendPlaylists(res.response)
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
window.openvk.writeableClubs.forEach(el => {
|
||||
document.querySelector("#addIconsWindow").insertAdjacentHTML("beforeend", `
|
||||
<option value="${el.id}">${ovk_proc_strtr(el.name, 20)}</option>
|
||||
`)
|
||||
switchTab(current_tab)
|
||||
|
||||
u("#_addAudioAdditional").on("click", ".mb_tab a", async (e) => {
|
||||
await switchTab(u(e.target).closest('.mb_tab').attr('data-name'))
|
||||
})
|
||||
|
||||
$(".ovk-diag-body").on("click", "input[name='addButton']", (e) => {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: `/audio${ev.target.dataset.id}/action?act=add_to_club`,
|
||||
data: {
|
||||
hash: u("meta[name=csrf]").attr("value"),
|
||||
club: document.querySelector("#addIconsWindow").value
|
||||
},
|
||||
beforeSend: () => {
|
||||
e.target.classList.add("lagged")
|
||||
document.querySelector(".errorPlace").innerHTML = ""
|
||||
},
|
||||
success: (response) => {
|
||||
if(!response.success)
|
||||
document.querySelector(".errorPlace").innerHTML = response.flash.message
|
||||
|
||||
e.currentTarget.classList.remove("lagged")
|
||||
}
|
||||
})
|
||||
|
||||
u("#_addAudioAdditional").on("click", "input[name='add_to']", async (e) => {
|
||||
if(u(`input[name='add_to']:checked`).length > 10) {
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$(document).on("click", ".musicIcon.add-icon", (e) => {
|
||||
let id = e.currentTarget.dataset.id
|
||||
const id = e.currentTarget.dataset.id
|
||||
if(e.detail > 1 || e.altKey) {
|
||||
const player = e.target.closest('.audioEmbed')
|
||||
player.querySelector('.add-icon-group').click()
|
||||
return
|
||||
}
|
||||
|
||||
let formdata = new FormData()
|
||||
formdata.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
|
@ -1312,7 +1474,7 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
|||
})
|
||||
})
|
||||
|
||||
$(document).on("click", ".audioEmbed.processed", (e) => {
|
||||
$(document).on("click", ".audioEmbed.processed .playerButton", (e) => {
|
||||
MessageBox(tr("error"), tr("audio_embed_processing"), [tr("ok")], [Function.noop])
|
||||
})
|
||||
|
||||
|
|
190
Web/static/js/al_navigation.js
Normal file
190
Web/static/js/al_navigation.js
Normal file
|
@ -0,0 +1,190 @@
|
|||
u(`#search_box form input[type="search"]`).on('focus', (e) => {
|
||||
u('.page_header').addClass('search_expanded')
|
||||
})
|
||||
|
||||
u(`#search_box form input[type="search"]`).on('blur', (e) => {
|
||||
if(window.openvk.at_search) {
|
||||
return
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if(document.activeElement.closest('.page_header')) {
|
||||
return
|
||||
}
|
||||
|
||||
u('.page_header').removeClass('search_expanded')
|
||||
}, 4000)
|
||||
})
|
||||
|
||||
u(document).on('click', '.search_option_name', (e) => {
|
||||
const target = e.target.closest('.search_option')
|
||||
// 🤪
|
||||
$(target.querySelector('.search_option_content')).slideToggle(250, "swing");
|
||||
setTimeout(() => {
|
||||
u(target).toggleClass('search_option_hidden')
|
||||
}, 250)
|
||||
})
|
||||
|
||||
u(document).on('click', '#search_reset', (e) => {
|
||||
u(`.page_search_options input[type='text']`).nodes.forEach(inp => {
|
||||
inp.value = ''
|
||||
})
|
||||
|
||||
u(`.page_search_options input[type='checkbox']`).nodes.forEach(chk => {
|
||||
chk.checked = false
|
||||
})
|
||||
|
||||
u(`.page_search_options input[type='radio']`).nodes.forEach(rad => {
|
||||
if(rad.dataset.default) {
|
||||
rad.checked = true
|
||||
return
|
||||
}
|
||||
|
||||
rad.checked = false
|
||||
})
|
||||
|
||||
u(`.page_search_options select`).nodes.forEach(sel => {
|
||||
sel.value = sel.dataset.default
|
||||
})
|
||||
})
|
||||
|
||||
u(`#search_box input[type='search']`).on('input', async (e) => {
|
||||
if(window.openvk.at_search) {
|
||||
return
|
||||
}
|
||||
|
||||
const query = u(`#search_box input[type='search']`).nodes[0].value
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
const current_query = u(`#search_box input[type='search']`).nodes[0].value
|
||||
const section = u(`#search_box select[name='section']`).nodes[0].value
|
||||
let results = null
|
||||
if(/*query.length < 2 || */query != current_query || ['users', 'groups', 'videos', 'audios_playlists'].indexOf(section) == -1) {
|
||||
return
|
||||
}
|
||||
|
||||
console.info('Ok, getting tips.')
|
||||
|
||||
switch(section) {
|
||||
case 'users':
|
||||
results = await fetch(`/method/users.search?auth_mechanism=roaming&q=${query}&count=10&sort=4&fields=photo_50,status,nickname`)
|
||||
break
|
||||
case 'groups':
|
||||
results = await fetch(`/method/groups.search?auth_mechanism=roaming&q=${query}&count=10&sort=4&fields=photo_50,description`)
|
||||
break
|
||||
case 'videos':
|
||||
results = await fetch(`/method/video.search?auth_mechanism=roaming&q=${query}&count=10&sort=4&extended=1`)
|
||||
break
|
||||
case 'audios_playlists':
|
||||
results = await fetch(`/method/audio.searchAlbums?auth_mechanism=roaming&query=${query}&limit=10`)
|
||||
break
|
||||
}
|
||||
|
||||
json_result = await results.json()
|
||||
if(!json_result || json_result.error) {
|
||||
console.error(json_result.error)
|
||||
return
|
||||
}
|
||||
|
||||
json_result = json_result.response
|
||||
if(json_result.count < 1) {
|
||||
console.info('No tips available.')
|
||||
return
|
||||
}
|
||||
|
||||
switch(section) {
|
||||
case 'users':
|
||||
json_result['items'].forEach(item => {
|
||||
item['name'] = `${item['first_name']}${item['nickname'] ? ` (${item['nickname']})` : ''} ${item['last_name']}`
|
||||
item['description'] = item['status']
|
||||
item['url'] = '/id' + item['id']
|
||||
item['preview'] = item['photo_50']
|
||||
})
|
||||
break
|
||||
case 'groups':
|
||||
json_result['items'].forEach(item => {
|
||||
item['url'] = '/club' + item['id']
|
||||
item['preview'] = item['photo_50']
|
||||
})
|
||||
break
|
||||
case 'audios_playlists':
|
||||
json_result['items'].forEach(item => {
|
||||
item['name'] = item['title']
|
||||
item['url'] = '/playlist' + item['owner_id'] + '_' + item['id']
|
||||
item['preview'] = item['cover_url']
|
||||
})
|
||||
break
|
||||
case 'videos':
|
||||
const profiles = json_result['profiles']
|
||||
const groups = json_result['groups']
|
||||
json_result['items'].forEach(item => {
|
||||
item['name'] = item['title']
|
||||
item['url'] = `/video${item['owner_id']}_${item['id']}`
|
||||
item['preview'] = item['image'][0]['url']
|
||||
|
||||
if(item['owner_id'] > 0) {
|
||||
const profile = profiles.find(prof => prof.id == item['owner_id'])
|
||||
if(!profile) { return }
|
||||
item['description'] = profile['first_name'] + ' ' + profile['last_name']
|
||||
} else {
|
||||
const group = groups.find(grou => grou.id == Math.abs(item['owner_id']))
|
||||
if(!group) { return }
|
||||
item['description'] = group['name']
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
u('#searchBoxFastTips').addClass('shown')
|
||||
u('#searchBoxFastTips').html('')
|
||||
json_result.items.forEach(item => {
|
||||
u('#searchBoxFastTips').append(`
|
||||
<a href='${item['url']}'>
|
||||
<img src='${item['preview']}' class='search_tip_preview_block'>
|
||||
<div class='search_tip_info_block'>
|
||||
<b>${ovk_proc_strtr(item['name'].escapeHtml(), 50)}</b>
|
||||
<span>${ovk_proc_strtr((item['description'] ?? '').escapeHtml(), 60)}</span>
|
||||
</div>
|
||||
</a>
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
u(document).on('keydown', `#search_box input[type='search'], #searchBoxFastTips a`, (e) => {
|
||||
const u_tips = u('#searchBoxFastTips a')
|
||||
if(u_tips.length < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
const focused = u('#searchBoxFastTips a:focus').nodes[0]
|
||||
|
||||
// up
|
||||
switch(e.keyCode) {
|
||||
case 38:
|
||||
e.preventDefault()
|
||||
if(!focused) {
|
||||
u_tips.nodes[0].focus()
|
||||
return
|
||||
}
|
||||
|
||||
if(focused.previousSibling) {
|
||||
focused.previousSibling.focus()
|
||||
}
|
||||
|
||||
break
|
||||
// down
|
||||
case 40:
|
||||
e.preventDefault()
|
||||
if(!focused) {
|
||||
u_tips.nodes[0].focus()
|
||||
return
|
||||
}
|
||||
|
||||
if(focused.nextSibling) {
|
||||
focused.nextSibling.focus()
|
||||
} else {
|
||||
u_tips.nodes[0].focus()
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
})
|
|
@ -279,7 +279,7 @@ function OpenMiniature(e, photo, post, photo_id, type = "post") {
|
|||
tempDetailsSection[index] = element.innerHTML;
|
||||
|
||||
if(index == imagesIndex) {
|
||||
u(".ovk-photo-details").last().innerHTML = element.innerHTML;
|
||||
u(".ovk-photo-details").last().innerHTML = element.innerHTML ?? '';
|
||||
}
|
||||
|
||||
document.querySelectorAll(".ovk-photo-details .bsdn").forEach(bsdnInitElement)
|
||||
|
@ -342,31 +342,38 @@ function OpenMiniature(e, photo, post, photo_id, type = "post") {
|
|||
|
||||
let data = new FormData()
|
||||
data.append('parentType', type);
|
||||
ky.post("/iapi/getPhotosFromPost/" + (type == "post" ? post : "1_"+post), {
|
||||
hooks: {
|
||||
afterResponse: [
|
||||
async (_request, _options, response) => {
|
||||
json = await response.json();
|
||||
|
||||
imagesCount = json.body.length;
|
||||
imagesIndex = 0;
|
||||
// Это всё придётся правда на 1 прибавлять
|
||||
|
||||
json.body.every(element => {
|
||||
imagesIndex++;
|
||||
if(element.id == photo_id) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
__reloadTitleBar();
|
||||
__loadDetails(json.body[imagesIndex - 1].id, imagesIndex); }
|
||||
]
|
||||
},
|
||||
body: data
|
||||
});
|
||||
|
||||
if(type) {
|
||||
ky.post("/iapi/getPhotosFromPost/" + (type == "post" ? post : "1_"+post), {
|
||||
hooks: {
|
||||
afterResponse: [
|
||||
async (_request, _options, response) => {
|
||||
json = await response.json();
|
||||
|
||||
imagesCount = json.body.length;
|
||||
imagesIndex = 0;
|
||||
// Это всё придётся правда на 1 прибавлять
|
||||
|
||||
json.body.every(element => {
|
||||
imagesIndex++;
|
||||
if(element.id == photo_id) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
__reloadTitleBar();
|
||||
__loadDetails(json.body[imagesIndex - 1].id, imagesIndex); }
|
||||
]
|
||||
},
|
||||
body: data
|
||||
});
|
||||
} else {
|
||||
imagesCount = 1
|
||||
__reloadTitleBar()
|
||||
__loadDetails(photo_id, imagesIndex)
|
||||
}
|
||||
|
||||
return u(".ovk-photo-view-dimmer");
|
||||
}
|
||||
|
|
|
@ -500,117 +500,43 @@ function escapeHtml(text) {
|
|||
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
}
|
||||
|
||||
function expandSearch()
|
||||
{
|
||||
// console.log("search expanded")
|
||||
let els = document.querySelectorAll("div.dec")
|
||||
for(const element of els)
|
||||
{
|
||||
element.style.display = "none"
|
||||
}
|
||||
|
||||
document.querySelector(".whatFind").style.display = "block";
|
||||
document.querySelector(".whatFind").style.marginRight = "-80px";
|
||||
document.getElementById("searchInput").style.width = "627px";
|
||||
document.getElementById("searchInput").style.background = "none";
|
||||
document.getElementById("searchInput").style.backgroundColor = "#fff";
|
||||
document.getElementById("searchInput").style.paddingLeft = "6px";
|
||||
srch.classList.add("nodivider")
|
||||
}
|
||||
function highlightText(searchText, container_selector, selectors = []) {
|
||||
const container = u(container_selector)
|
||||
const regexp = new RegExp(`(${searchText})`, 'gi')
|
||||
|
||||
async function decreaseSearch()
|
||||
{
|
||||
// чтобы люди успели выбрать что искать и поиск не скрывался сразу
|
||||
await new Promise(r => setTimeout(r, 4000));
|
||||
|
||||
// console.log("search decreased")
|
||||
if(document.activeElement !== searchInput && document.activeElement !== typer)
|
||||
{
|
||||
srcht.setAttribute("hidden", "hidden")
|
||||
document.getElementById("searchInput").style.background = "url('/assets/packages/static/openvk/img/search_icon.png') no-repeat 3px 4px";
|
||||
document.getElementById("searchInput").style.backgroundColor = "#fff";
|
||||
document.getElementById("searchInput").style.paddingLeft = "18px";
|
||||
document.getElementById("searchInput").style.width = "120px";
|
||||
document.querySelector(".whatFind").style.display = "none";
|
||||
|
||||
await new Promise(r => setTimeout(r, 300));
|
||||
srch.classList.remove("nodivider")
|
||||
|
||||
let els = document.querySelectorAll("div.dec")
|
||||
for(const element of els)
|
||||
{
|
||||
element.style.display = "inline-block"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hideParams(name)
|
||||
{
|
||||
$("#s_"+name).slideToggle(250, "swing");
|
||||
|
||||
if($(`#n_${name} img`).attr("src") == "/assets/packages/static/openvk/img/hide.png")
|
||||
{
|
||||
$("#n_"+name+" img").attr("src", "/assets/packages/static/openvk/img/show.png");
|
||||
} else {
|
||||
$("#n_"+name+" img").attr("src", "/assets/packages/static/openvk/img/hide.png");
|
||||
}
|
||||
}
|
||||
|
||||
function resetSearch()
|
||||
{
|
||||
let inputs = document.querySelectorAll("input")
|
||||
let selects = document.querySelectorAll("select")
|
||||
|
||||
for(const input of inputs)
|
||||
{
|
||||
if(input != dnt && input != gend && input != gend1 && input != gend2) {
|
||||
input.value = ""
|
||||
}
|
||||
}
|
||||
|
||||
for(const select of selects)
|
||||
{
|
||||
if(select != sortyor && select != document.querySelector(".whatFind")) {
|
||||
select.value = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function checkSearchTips()
|
||||
{
|
||||
let query = searchInput.value;
|
||||
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
|
||||
let type = typer.value;
|
||||
let smt = type == "users" || type == "groups" || type == "videos";
|
||||
|
||||
if(query.length > 3 && query == searchInput.value && smt) {
|
||||
srcht.removeAttribute("hidden")
|
||||
let etype = type
|
||||
|
||||
try {
|
||||
let results = await API.Search.fastSearch(escapeHtml(query), etype)
|
||||
function highlightNode(node) {
|
||||
if(node.nodeType == 3) {
|
||||
let newNode = escapeHtml(node.nodeValue)
|
||||
newNode = newNode.replace(regexp, (match, ...args) => {
|
||||
return `<span class='highlight'>${escapeHtml(match)}</span>`
|
||||
})
|
||||
|
||||
srchrr.innerHTML = ""
|
||||
const tempDiv = document.createElement('div')
|
||||
tempDiv.innerHTML = newNode
|
||||
|
||||
for(const el of results["items"]) {
|
||||
srchrr.insertAdjacentHTML("beforeend", `
|
||||
<tr class="restip" onmouseup="if (event.which === 2) { window.open('${el.url}', '_blank'); } else {location.href='${el.url}'}">
|
||||
<td>
|
||||
<img src="${el.avatar}" width="30">
|
||||
</td>
|
||||
<td valign="top">
|
||||
<p class="nameq" style="margin-top: -2px;text-transform:none;">${escapeHtml(el.name)}</p>
|
||||
<p class="desq" style="text-transform:none;">${escapeHtml(el.description)}</p>
|
||||
</td>
|
||||
</tr>
|
||||
`)
|
||||
while(tempDiv.firstChild) {
|
||||
node.parentNode.insertBefore(tempDiv.firstChild, node)
|
||||
}
|
||||
} catch(rejection) {
|
||||
srchrr.innerHTML = tr("no_results")
|
||||
node.parentNode.removeChild(node)
|
||||
} else if(node.nodeType === 1 && node.tagName !== 'SCRIPT' && node.tagName !== 'BR' && node.tagName !== 'STYLE') {
|
||||
Array.from(node.childNodes).forEach(highlightNode);
|
||||
}
|
||||
}
|
||||
|
||||
selectors.forEach(selector => {
|
||||
elements = container.find(selector)
|
||||
if(!elements || elements.length < 1) return;
|
||||
|
||||
elements.nodes.forEach(highlightNode)
|
||||
})
|
||||
}
|
||||
|
||||
String.prototype.escapeHtml = function() {
|
||||
try {
|
||||
return escapeHtml(this)
|
||||
} catch(e) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on("scroll", () => {
|
||||
|
|
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`;
|
|
@ -250,6 +250,8 @@
|
|||
"clubs_posts" = "Group's posts";
|
||||
"others_posts" = "Others posts";
|
||||
|
||||
"show_more" = "Show more";
|
||||
|
||||
/* Friends */
|
||||
|
||||
"friends" = "Friends";
|
||||
|
@ -639,13 +641,14 @@
|
|||
"apply_style_for_this_device" = "Apply style only for this device";
|
||||
|
||||
"search_for_groups" = "Search for groups";
|
||||
"search_for_users" = "Search for people";
|
||||
"search_for_users" = "Search for users";
|
||||
"search_for_posts" = "Search for posts";
|
||||
"search_for_comments" = "Search for comments";
|
||||
"search_for_videos" = "Search for videos";
|
||||
"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";
|
||||
|
@ -877,6 +880,7 @@
|
|||
"my_playlists" = "My playlists";
|
||||
"playlists" = "Playlists";
|
||||
"audios_explicit" = "Contains obscene language";
|
||||
"audios_unlisted" = "Unlisted";
|
||||
"withdrawn" = "Withdrawn";
|
||||
"deleted" = "Deleted";
|
||||
"owner" = "Owner";
|
||||
|
@ -900,7 +904,7 @@
|
|||
"edit_playlist" = "Edit playlist";
|
||||
"unable_to_load_queue" = "Error when loading queue.";
|
||||
|
||||
"fully_delete_audio" = "Fully delete audio";
|
||||
"fully_delete_audio" = "Delete audio";
|
||||
"attach_audio" = "Attach audio";
|
||||
"detach_audio" = "Detach audio";
|
||||
|
||||
|
@ -928,6 +932,12 @@
|
|||
"listens_count_other" = "$1 listens";
|
||||
|
||||
"add_audio_to_club" = "Add audio to group";
|
||||
"add_audio" = "Adding audio";
|
||||
"add_audio_limitations" = "You can select up to 10 groups/playlists.";
|
||||
"to_club" = "To club";
|
||||
"to_playlist" = "To playlist";
|
||||
|
||||
"audio_was_successfully_added" = "Audios was successfully added.";
|
||||
"what_club_add" = "Which group do you want to add the song to?";
|
||||
"group_has_audio" = "This group already has this song.";
|
||||
"group_hasnt_audio" = "This group doesn't have this song.";
|
||||
|
@ -935,6 +945,7 @@
|
|||
"by_name" = "by name";
|
||||
"by_performer" = "by performer";
|
||||
"no_access_clubs" = "There are no groups where you are an administrator.";
|
||||
"no_access_playlists" = "You haven't created any playlists.";
|
||||
"audio_successfully_uploaded" = "Audio has been successfully uploaded and is currently being processed.";
|
||||
|
||||
"broadcast_audio" = "Broadcast audio to status";
|
||||
|
@ -947,6 +958,8 @@
|
|||
"repeat_tip" = "Repeat";
|
||||
"shuffle_tip" = "Shuffle";
|
||||
"mute_tip" = "Mute";
|
||||
"playlist_hide_from_search" = "Unlisted";
|
||||
"confirm_deleting_audio" = "Do you sure want to delete this audio?";
|
||||
|
||||
/* Notifications */
|
||||
|
||||
|
@ -1538,6 +1551,7 @@
|
|||
"error_code" = "Error code: $1.";
|
||||
"ffmpeg_timeout" = "Timed out waiting ffmpeg. Try to upload file again.";
|
||||
"ffmpeg_not_installed" = "Failed to proccess the file. It looks like ffmpeg is not installed on this server.";
|
||||
"too_many_or_to_lack" = "Too few or too many sources.";
|
||||
|
||||
/* Admin actions */
|
||||
|
||||
|
@ -1979,24 +1993,23 @@
|
|||
|
||||
/* Search */
|
||||
|
||||
"s_people" = "People";
|
||||
"s_people" = "Users";
|
||||
"s_groups" = "Clubs";
|
||||
"s_events" = "Events";
|
||||
"s_apps" = "Applications";
|
||||
"s_questions" = "Questions";
|
||||
"s_notes" = "Notes";
|
||||
"s_themes" = "Themes";
|
||||
"s_posts" = "Posts";
|
||||
"s_comments" = "Comments";
|
||||
"s_videos" = "Videos";
|
||||
"s_audios" = "Music";
|
||||
"s_by_people" = "for people";
|
||||
"s_audios_playlists" = "Playlists";
|
||||
|
||||
"s_by_people" = "for users";
|
||||
"s_by_groups" = "for groups";
|
||||
"s_by_posts" = "for posts";
|
||||
"s_by_comments" = "for comments";
|
||||
"s_by_videos" = "for videos";
|
||||
"s_by_apps" = "for apps";
|
||||
"s_by_audios" = "for musics";
|
||||
"s_by_audios" = "for audios";
|
||||
"s_by_audios_playlists" = "for playlists";
|
||||
|
||||
"s_order_by" = "Order by...";
|
||||
|
||||
|
@ -2007,6 +2020,10 @@
|
|||
"s_order_by_length" = "By length";
|
||||
"s_order_by_listens" = "By listens count";
|
||||
"s_order_invert" = "Invert";
|
||||
"s_order_by_reg_date" = "By reg date";
|
||||
"s_order_by_creation_date" = "By creation date";
|
||||
"s_order_by_publishing_date" = "By publication date";
|
||||
"s_order_by_upload_date" = "By upload date";
|
||||
|
||||
"s_by_date" = "By date";
|
||||
"s_registered_before" = "Registered before";
|
||||
|
@ -2019,17 +2036,24 @@
|
|||
"s_now_on_site" = "now on site";
|
||||
"s_with_photo" = "with photo";
|
||||
"s_only_in_names" = "only in names";
|
||||
"s_only_youtube" = "only from YouTube";
|
||||
|
||||
"s_any" = "any";
|
||||
"s_any_single" = "any";
|
||||
"reset" = "Reset";
|
||||
|
||||
"closed_group_post" = "This post was published in a private group";
|
||||
"deleted_target_comment" = "This comment belongs to deleted post";
|
||||
|
||||
"no_results" = "No results";
|
||||
"s_only_performers" = "Performers only";
|
||||
"s_only_performers" = "By performers";
|
||||
"s_with_lyrics" = "With lyrics";
|
||||
|
||||
"showing_x_y" = "(showing $1—$2)";
|
||||
"no_results_by_this_query" = "Nothing was found by this query.";
|
||||
"s_additional" = "Additional";
|
||||
"s_it_is_you" = "it is you";
|
||||
|
||||
/* BadBrowser */
|
||||
|
||||
"deprecated_browser" = "Deprecated Browser";
|
||||
|
|
|
@ -229,6 +229,7 @@
|
|||
"users_posts" = "Записи $1";
|
||||
"clubs_posts" = "Записи сообщества";
|
||||
"others_posts" = "Чужие записи";
|
||||
"show_more" = "Показать больше";
|
||||
|
||||
/* Friends */
|
||||
|
||||
|
@ -621,6 +622,7 @@
|
|||
"search_for_apps" = "Поиск приложений";
|
||||
"search_for_notes" = "Поиск записок";
|
||||
"search_for_audios" = "Поиск музыки";
|
||||
"search_for_audios_playlists" = "Поиск плейлистов";
|
||||
"search_button" = "Найти";
|
||||
"search_placeholder" = "Начните вводить любое имя, название или слово";
|
||||
"results_zero" = "Ни одного результата";
|
||||
|
@ -835,6 +837,7 @@
|
|||
"my_playlists" = "Мои плейлисты";
|
||||
"playlists" = "Плейлисты";
|
||||
"audios_explicit" = "Содержит нецензурную лексику";
|
||||
"audios_unlisted" = "Скрыто из поиска";
|
||||
"withdrawn" = "Изъято";
|
||||
"deleted" = "Удалено";
|
||||
"owner" = "Владелец";
|
||||
|
@ -885,6 +888,13 @@
|
|||
"listens_count_other" = "$1 прослушиваний";
|
||||
|
||||
"add_audio_to_club" = "Добавить аудио в группу";
|
||||
"add_audio" = "Добавление аудио";
|
||||
"add_audio_limitations" = "Можно выбрать до 10 групп/плейлистов.";
|
||||
"to_club" = "В группу";
|
||||
"to_playlist" = "В плейлист";
|
||||
|
||||
"audio_was_successfully_added" = "Аудио были успешно добавлены.";
|
||||
|
||||
"what_club_add" = "В какую группу вы хотите добавить песню?";
|
||||
"group_has_audio" = "У группы уже есть эта песня.";
|
||||
"group_hasnt_audio" = "У группы нет этой песни.";
|
||||
|
@ -892,6 +902,7 @@
|
|||
"by_name" = "по композициям";
|
||||
"by_performer" = "по исполнителю";
|
||||
"no_access_clubs" = "Нет групп, где вы являетесь администратором.";
|
||||
"no_access_playlists" = "Вы ещё не создавали плейлистов.";
|
||||
"audio_successfully_uploaded" = "Аудио успешно загружено и на данный момент обрабатывается.";
|
||||
|
||||
"broadcast_audio" = "Транслировать аудио в статус";
|
||||
|
@ -904,6 +915,8 @@
|
|||
"repeat_tip" = "Повторение";
|
||||
"shuffle_tip" = "Перемешать";
|
||||
"mute_tip" = "Заглушить";
|
||||
"playlist_hide_from_search" = "Не показывать в поиске";
|
||||
"confirm_deleting_audio" = "Вы действительно хотите полностью удалить аудиозапись?";
|
||||
|
||||
/* Notifications */
|
||||
|
||||
|
@ -1405,7 +1418,7 @@
|
|||
"no_video_desc" = "Выберите файл или укажите ссылку.";
|
||||
"error_occured" = "Произошла ошибка";
|
||||
"error_video_damaged_file" = "Файл повреждён или не содержит видео.";
|
||||
"error_video_incorrect_link" = "Возможно, ссылка некорректна.";
|
||||
"error_video_incorrect_link" = "Возможно, ссылка некорректна";
|
||||
"error_video_no_title" = "Видео не может быть опубликовано без названия.";
|
||||
|
||||
"new_data_video" = "Обновлённое описание появится на странице с видео.";
|
||||
|
@ -1440,6 +1453,7 @@
|
|||
"error_code" = "Код ошибки: $1.";
|
||||
"ffmpeg_timeout" = "Превышено время ожидания обработки ffmpeg. Попробуйте загрузить файл снова.";
|
||||
"ffmpeg_not_installed" = "Не удалось обработать файл. Похоже, на сервере не установлен ffmpeg.";
|
||||
"too_many_or_to_lack" = "Слишком мало либо слишком много источников.";
|
||||
|
||||
/* Admin actions */
|
||||
|
||||
|
@ -1869,24 +1883,23 @@
|
|||
|
||||
/* Search */
|
||||
|
||||
"s_people" = "Люди";
|
||||
"s_people" = "Пользователи";
|
||||
"s_groups" = "Группы";
|
||||
"s_events" = "События";
|
||||
"s_apps" = "Приложения";
|
||||
"s_questions" = "Вопросы";
|
||||
"s_notes" = "Заметки";
|
||||
"s_themes" = "Темы";
|
||||
"s_posts" = "Записи";
|
||||
"s_comments" = "Комментарии";
|
||||
"s_videos" = "Видео";
|
||||
"s_audios" = "Аудио";
|
||||
"s_by_people" = "по людям";
|
||||
"s_audios_playlists" = "Плейлисты";
|
||||
|
||||
"s_by_people" = "по пользователям";
|
||||
"s_by_groups" = "по группам";
|
||||
"s_by_posts" = "по записям";
|
||||
"s_by_comments" = "по комментариям";
|
||||
"s_by_videos" = "по видео";
|
||||
"s_by_apps" = "по приложениям";
|
||||
"s_by_audios" = "по музыке";
|
||||
"s_by_audios" = "по аудиозаписям";
|
||||
"s_by_audios_playlists" = "по плейлистам";
|
||||
|
||||
"s_order_by" = "Порядок";
|
||||
|
||||
|
@ -1897,6 +1910,10 @@
|
|||
"s_order_by_length" = "По длине";
|
||||
"s_order_by_listens" = "По числу прослушиваний";
|
||||
"s_order_invert" = "Инвертировать";
|
||||
"s_order_by_reg_date" = "По дате регистрации";
|
||||
"s_order_by_creation_date" = "По дате создания";
|
||||
"s_order_by_publishing_date" = "По дате публикации";
|
||||
"s_order_by_upload_date" = "По дате загрузки";
|
||||
|
||||
"s_by_date" = "По дате";
|
||||
"s_registered_before" = "Зарегистрирован до";
|
||||
|
@ -1909,17 +1926,24 @@
|
|||
"s_now_on_site" = "cейчас на сайте";
|
||||
"s_with_photo" = "с фото";
|
||||
"s_only_in_names" = "только в именах";
|
||||
"s_only_youtube" = "только с YouTube";
|
||||
|
||||
"s_any" = "любой";
|
||||
"s_any" = "любые";
|
||||
"s_any_single" = "любой";
|
||||
"reset" = "Сброс";
|
||||
|
||||
"closed_group_post" = "Эта запись из закрытой группы";
|
||||
"closed_group_post" = "Запись с закрытой стены";
|
||||
"deleted_target_comment" = "Этот комментарий принадлежит к удалённой записи";
|
||||
|
||||
"no_results" = "Результатов нет";
|
||||
"s_only_performers" = "Только исполнители";
|
||||
"s_only_performers" = "По исполнителям";
|
||||
"s_with_lyrics" = "С текстом";
|
||||
|
||||
"showing_x_y" = "(показывается $1—$2)";
|
||||
"no_results_by_this_query" = "По данному запросу ничего не найдено.";
|
||||
"s_additional" = "Дополнительно";
|
||||
"s_it_is_you" = "это вы";
|
||||
|
||||
/* BadBrowser */
|
||||
|
||||
"deprecated_browser" = "Устаревший браузер";
|
||||
|
@ -1997,7 +2021,7 @@
|
|||
|
||||
"error_video" = "Произошла ошибка";
|
||||
"file_corrupted" = "Файл повреждён или не содержит видео.";
|
||||
"link_incorrect" = "Возможно, ссылка некорректна.";
|
||||
"link_incorrect" = "Возможно, ссылка некорректна (попробуй убрать параметры по типу &t= или &si=)";
|
||||
|
||||
"no_name_error" = "Видео не может быть опубликовано без названия";
|
||||
"access_denied_error" = "Ошибка доступа";
|
||||
|
|
|
@ -1758,11 +1758,7 @@
|
|||
|
||||
"s_people" = "Люди";
|
||||
"s_groups" = "Спільноти";
|
||||
"s_events" = "Події";
|
||||
"s_apps" = "Застосунки";
|
||||
"s_questions" = "Запитання";
|
||||
"s_notes" = "Нотатки";
|
||||
"s_themes" = "Теми";
|
||||
"s_posts" = "Дописи";
|
||||
"s_comments" = "Коментарі";
|
||||
"s_videos" = "Відео";
|
||||
|
|
|
@ -124,14 +124,13 @@ th,
|
|||
.tippy-box[data-theme~="vk"],
|
||||
.poll,
|
||||
#standaloneCommentBox,
|
||||
.searchBtn,
|
||||
.searchList #used,
|
||||
.searchOptionName,
|
||||
#search_box_button,
|
||||
.verticalGrayTabs #used,
|
||||
.search_option_name,
|
||||
.borderup,
|
||||
#tour,
|
||||
#auth,
|
||||
.ovk-photo-view,
|
||||
.searchOptions {
|
||||
.ovk-photo-view {
|
||||
border-color: #2c2640 !important;
|
||||
}
|
||||
|
||||
|
@ -155,11 +154,15 @@ hr {
|
|||
.messagebox-content-header,
|
||||
.accent-box,
|
||||
.button_search,
|
||||
.searchBtn,
|
||||
.searchOptionName {
|
||||
.search_box_button {
|
||||
background-color: #383052;
|
||||
}
|
||||
|
||||
.search_option_name {
|
||||
background-color: #383052 !important;
|
||||
color: lightgrey !important;
|
||||
}
|
||||
|
||||
.tab:hover {
|
||||
background-color: #40375e;
|
||||
}
|
||||
|
@ -176,7 +179,7 @@ hr {
|
|||
}
|
||||
|
||||
.bsdn_contextMenuElement:hover,
|
||||
.searchList li:hover {
|
||||
.verticalGrayTabs li:hover {
|
||||
background-color: #29223a;
|
||||
}
|
||||
|
||||
|
@ -208,7 +211,7 @@ a,
|
|||
.paginator a:hover,
|
||||
.post-share-button:hover,
|
||||
.post-like-button:hover,
|
||||
.searchBtn:active {
|
||||
#search_box_button:active {
|
||||
background-color: #272138 !important;
|
||||
}
|
||||
|
||||
|
@ -261,7 +264,9 @@ center[style="background: white;border: #DEDEDE solid 1px;"],
|
|||
.album-photo img,
|
||||
#faqhead,
|
||||
td.e,
|
||||
tr.e {
|
||||
tr.e,
|
||||
.playlistListView:hover,
|
||||
.playlistListView .playlistCover {
|
||||
background-color: #231e33 !important;
|
||||
}
|
||||
|
||||
|
@ -376,7 +381,7 @@ input[type="radio"] {
|
|||
background-image: url("/themepack/midnight/0.0.2.9/resource/radio.png") !important;
|
||||
}
|
||||
|
||||
.header_navigation .link {
|
||||
.header_navigation .link, .header_navigation .header_divider_stick {
|
||||
background: unset;
|
||||
}
|
||||
|
||||
|
@ -403,15 +408,26 @@ input[type="radio"] {
|
|||
border-color: #514534;
|
||||
}
|
||||
|
||||
.searchBtn {
|
||||
#search_box_button {
|
||||
box-shadow: 0px 2px 0px 0px rgba(111, 111, 111, 0.18) inset;
|
||||
}
|
||||
|
||||
.searchBtn:active {
|
||||
#search_box_button:active {
|
||||
box-shadow: 0px -2px 0px 0px rgba(255, 255, 255, 0.18) inset;
|
||||
}
|
||||
|
||||
.searchList #used {
|
||||
.verticalGrayTabsWrapper {
|
||||
background: #1e1a2b;
|
||||
border-top: 1px solid #2c2640;
|
||||
border-left: 1px solid #2a2841;
|
||||
}
|
||||
|
||||
.page_content_paginator_bottom {
|
||||
background: #1e1a2b;
|
||||
border-top: 1px solid #2c2640;
|
||||
}
|
||||
|
||||
.verticalGrayTabs #used {
|
||||
background: #463f60 !important;
|
||||
}
|
||||
|
||||
|
@ -447,13 +463,9 @@ input[type="radio"] {
|
|||
background: #b9b9b9 !important;
|
||||
}
|
||||
|
||||
.musicIcon {
|
||||
filter: invert(81%) !important;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying {
|
||||
background: #463f60 !important;
|
||||
border: 1px solid #645a86 !important;
|
||||
outline: 1px solid #645a86 !important;
|
||||
}
|
||||
|
||||
.preformer {
|
||||
|
@ -485,11 +497,11 @@ input[type="radio"] {
|
|||
color: black !important;
|
||||
}
|
||||
|
||||
.searchList a {
|
||||
.verticalGrayTabs a {
|
||||
color: #bbb !important;
|
||||
}
|
||||
|
||||
.searchList a:hover {
|
||||
.verticalGrayTabs a:hover {
|
||||
color: #eeeeee !important;
|
||||
background: #332d46 !important;
|
||||
}
|
||||
|
@ -512,7 +524,7 @@ img[src$='/assets/packages/static/openvk/img/song.jpg'] {
|
|||
}
|
||||
|
||||
.audioEntry .withLyrics {
|
||||
color: #6f6497 !important;
|
||||
color: #9481d9 !important;
|
||||
}
|
||||
|
||||
#listensCount {
|
||||
|
@ -536,7 +548,8 @@ ul {
|
|||
|
||||
/* вот бы css в овк был бы написан на var()'ах( */
|
||||
#upload_container.uploading {
|
||||
background: #121017 url('/assets/packages/static/openvk/img/progressbar.gif') !important;
|
||||
background-color: #312b3f !important;
|
||||
background-image: url('/assets/packages/static/openvk/img/progressbar.gif') !important;
|
||||
}
|
||||
|
||||
.musicIcon.pressed {
|
||||
|
@ -573,3 +586,8 @@ ul {
|
|||
.add_image_text {
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.content_page_error {
|
||||
background: #28223a;
|
||||
border: #2c2640 solid 1px;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ body {
|
|||
text-shadow: none;
|
||||
}
|
||||
|
||||
.header_navigation .link {
|
||||
background: unset;
|
||||
.header_navigation .link, .header_navigation .header_divider_stick {
|
||||
background: unset !important;
|
||||
}
|
||||
|
||||
.header_navigation .link a:hover {
|
||||
|
@ -252,87 +252,30 @@ ul {
|
|||
background-color:#3c3c3c
|
||||
}
|
||||
|
||||
.searchOptions
|
||||
{
|
||||
overflow-y: hidden;
|
||||
overflow-x:hidden;
|
||||
width:25.5%;
|
||||
border-top:1px solid #2B2B2B;
|
||||
float:right;
|
||||
scrollbar-width: none;
|
||||
font-size:12px;
|
||||
background-color:#F6F6F6;
|
||||
margin-right: -7px;
|
||||
}
|
||||
|
||||
.searchBtn
|
||||
{
|
||||
border: none;
|
||||
background-color: #555555;
|
||||
color: #ffffff;
|
||||
margin-left: -3px;
|
||||
padding-bottom: 2px;
|
||||
width: 80px;
|
||||
cursor: pointer;
|
||||
.search_box_button {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.searchBtn:active
|
||||
{
|
||||
border: none;
|
||||
background-color: rgb(77, 77, 77);
|
||||
color: white;
|
||||
.search_box_button:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.searchList #used {
|
||||
.verticalGrayTabs #used {
|
||||
background: #3c3c3c !important;
|
||||
border: unset !important;
|
||||
border: 1px solid #3c3c3c;
|
||||
}
|
||||
|
||||
.searchList #used a
|
||||
{
|
||||
.verticalGrayTabs #used a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.searchHide
|
||||
{
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.searchList li:hover
|
||||
{
|
||||
margin-left: 0px;
|
||||
color: #2B587A !important;
|
||||
background: #eeeeee;
|
||||
padding: 2px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
margin-bottom: 2px;
|
||||
padding-left: 5px;
|
||||
width: 91%;
|
||||
}
|
||||
|
||||
.searchOptionName
|
||||
{
|
||||
cursor: pointer;
|
||||
.search_option_name {
|
||||
background-color: #a4a4a4;
|
||||
padding-left: 5px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
width: 90%;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
border-bottom: unset;
|
||||
}
|
||||
|
||||
.searchOptionName img
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.borderup
|
||||
{
|
||||
border-top: 1px solid #2f2f2f;
|
||||
.verticalGrayTabsWrapper {
|
||||
border-top: unset;
|
||||
}
|
||||
|
||||
.sugglist {
|
||||
|
@ -371,3 +314,8 @@ ul {
|
|||
.musicIcon.lagged {
|
||||
opacity: 50%;
|
||||
}
|
||||
|
||||
.bigPlayer {
|
||||
position: sticky;
|
||||
top: 42px;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue