Compare commits
7 commits
aa75ab9496
...
2a0b28960a
Author | SHA1 | Date | |
---|---|---|---|
|
2a0b28960a | ||
|
b9687b1fb2 | ||
|
4046c992f9 | ||
|
96d48efbaf | ||
|
803831917c | ||
|
5c19637715 | ||
|
a16e15eaef |
|
@ -1,92 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\ServiceAPI;
|
||||
use openvk\Web\Models\Entities\User;
|
||||
use openvk\Web\Models\Repositories\{Photos as PhotosRepo, Albums, Clubs};
|
||||
|
||||
class Photos implements Handler
|
||||
{
|
||||
protected $user;
|
||||
protected $photos;
|
||||
|
||||
function __construct(?User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->photos = new PhotosRepo;
|
||||
}
|
||||
|
||||
function getPhotos(int $page = 1, int $album = 0, callable $resolve, callable $reject)
|
||||
{
|
||||
if($album == 0) {
|
||||
$photos = $this->photos->getEveryUserPhoto($this->user, $page, 24);
|
||||
$count = $this->photos->getUserPhotosCount($this->user);
|
||||
} else {
|
||||
$album = (new Albums)->get($album);
|
||||
|
||||
if(!$album || $album->isDeleted())
|
||||
$reject(55, "Invalid .");
|
||||
|
||||
if($album->getOwner() instanceof User) {
|
||||
if($album->getOwner()->getId() != $this->user->getId())
|
||||
$reject(555, "Access to album denied");
|
||||
} else {
|
||||
if(!$album->getOwner()->canBeModifiedBy($this->user))
|
||||
$reject(555, "Access to album denied");
|
||||
}
|
||||
|
||||
$photos = $album->getPhotos($page, 24);
|
||||
$count = $album->size();
|
||||
}
|
||||
|
||||
$arr = [
|
||||
"count" => $count,
|
||||
"items" => [],
|
||||
];
|
||||
|
||||
foreach($photos as $photo) {
|
||||
$res = json_decode(json_encode($photo->toVkApiStruct()), true);
|
||||
|
||||
$arr["items"][] = $res;
|
||||
}
|
||||
|
||||
$resolve($arr);
|
||||
}
|
||||
|
||||
function getAlbums(int $club, callable $resolve, callable $reject)
|
||||
{
|
||||
$albumsRepo = (new Albums);
|
||||
|
||||
$count = $albumsRepo->getUserAlbumsCount($this->user);
|
||||
$albums = $albumsRepo->getUserAlbums($this->user, 1, $count);
|
||||
|
||||
$arr = [
|
||||
"count" => $count,
|
||||
"items" => [],
|
||||
];
|
||||
|
||||
foreach($albums as $album) {
|
||||
$res = ["id" => $album->getId(), "name" => $album->getName()];
|
||||
|
||||
$arr["items"][] = $res;
|
||||
}
|
||||
|
||||
if($club > 0) {
|
||||
$cluber = (new Clubs)->get($club);
|
||||
|
||||
if(!$cluber || !$cluber->canBeModifiedBy($this->user))
|
||||
$reject(1337, "Invalid (club), or you can't modify him");
|
||||
|
||||
$clubCount = (new Albums)->getClubAlbumsCount($cluber);
|
||||
$clubAlbums = (new Albums)->getClubAlbums($cluber, 1, $clubCount);
|
||||
|
||||
foreach($clubAlbums as $albumr) {
|
||||
$res = ["id" => $albumr->getId(), "name" => $albumr->getName()];
|
||||
|
||||
$arr["items"][] = $res;
|
||||
}
|
||||
|
||||
$arr["count"] = $arr["count"] + $clubCount;
|
||||
}
|
||||
|
||||
$resolve($arr);
|
||||
}
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\ServiceAPI;
|
||||
|
||||
use openvk\Web\Models\Entities\{User, Post};
|
||||
use openvk\Web\Models\Repositories\{Videos, Comments, Clubs};
|
||||
use Chandler\MVC\Routing\Router;
|
||||
|
||||
class Video implements Handler
|
||||
{
|
||||
protected $user;
|
||||
protected $videos;
|
||||
protected $comments;
|
||||
protected $groups;
|
||||
|
||||
function __construct(?User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->videos = new Videos;
|
||||
$this->comments = new Comments;
|
||||
$this->groups = new Clubs;
|
||||
}
|
||||
|
||||
function getVideo(int $id, callable $resolve, callable $reject)
|
||||
{
|
||||
$video = $this->videos->get($id);
|
||||
|
||||
if(!$video || $video->isDeleted()) {
|
||||
$reject(2, "Video does not exists");
|
||||
}
|
||||
|
||||
if(method_exists($video, "canBeViewedBy") && !$video->canBeViewedBy($this->user)) {
|
||||
$reject(4, "Access to video denied");
|
||||
}
|
||||
|
||||
if(!$video->getOwner()->getPrivacyPermission('videos.read', $this->user)) {
|
||||
$reject(8, "Access to video denied: this user chose to hide his videos");
|
||||
}
|
||||
|
||||
$prevVideo = NULL;
|
||||
$nextVideo = NULL;
|
||||
$lastVideo = $this->videos->getLastVideo($video->getOwner());
|
||||
|
||||
if($video->getVirtualId() - 1 != 0) {
|
||||
for($i = $video->getVirtualId(); $i != 0; $i--) {
|
||||
$maybeVideo = (new Videos)->getByOwnerAndVID($video->getOwner()->getId(), $i);
|
||||
|
||||
if(!is_null($maybeVideo) && !$maybeVideo->isDeleted() && $maybeVideo->getId() != $video->getId()) {
|
||||
if(method_exists($maybeVideo, "canBeViewedBy") && !$maybeVideo->canBeViewedBy($this->user)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$prevVideo = $maybeVideo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(is_null($lastVideo) || $lastVideo->getId() == $video->getId()) {
|
||||
$nextVideo = NULL;
|
||||
} else {
|
||||
for($i = $video->getVirtualId(); $i <= $lastVideo->getVirtualId(); $i++) {
|
||||
$maybeVideo = (new Videos)->getByOwnerAndVID($video->getOwner()->getId(), $i);
|
||||
|
||||
if(!is_null($maybeVideo) && !$maybeVideo->isDeleted() && $maybeVideo->getId() != $video->getId()) {
|
||||
if(method_exists($maybeVideo, "canBeViewedBy") && !$maybeVideo->canBeViewedBy($this->user)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nextVideo = $maybeVideo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$res = [
|
||||
"id" => $video->getId(),
|
||||
"title" => $video->getName(),
|
||||
"owner" => $video->getOwner()->getId(),
|
||||
"commentsCount" => $video->getCommentsCount(),
|
||||
"description" => $video->getDescription(),
|
||||
"type" => $video->getType(),
|
||||
"name" => $video->getOwner()->getCanonicalName(),
|
||||
"pretty_id" => $video->getPrettyId(),
|
||||
"virtual_id" => $video->getVirtualId(),
|
||||
"published" => (string)$video->getPublicationTime(),
|
||||
"likes" => $video->getLikesCount(),
|
||||
"has_like" => $video->hasLikeFrom($this->user),
|
||||
"author" => $video->getOwner()->getCanonicalName(),
|
||||
"canBeEdited" => $video->getOwner()->getId() == $this->user->getId(),
|
||||
"isProcessing" => $video->getType() == 0 && $video->getURL() == "/assets/packages/static/openvk/video/rendering.mp4",
|
||||
"prevVideo" => !is_null($prevVideo) ? $prevVideo->getId() : null,
|
||||
"nextVideo" => !is_null($nextVideo) ? $nextVideo->getId() : null,
|
||||
];
|
||||
|
||||
if($video->getType() == 1) {
|
||||
$res["embed"] = $video->getVideoDriver()->getEmbed();
|
||||
} else {
|
||||
$res["url"] = $video->getURL();
|
||||
}
|
||||
|
||||
$resolve($res);
|
||||
}
|
||||
|
||||
function shareVideo(int $owner, int $vid, int $type, string $message, int $club, bool $signed, bool $asGroup, callable $resolve, callable $reject)
|
||||
{
|
||||
$video = $this->videos->getByOwnerAndVID($owner, $vid);
|
||||
|
||||
if(!$video || $video->isDeleted()) {
|
||||
$reject(16, "Video does not exists");
|
||||
}
|
||||
|
||||
if(method_exists($video, "canBeViewedBy") && !$video->canBeViewedBy($this->user)) {
|
||||
$reject(32, "Access to video denied");
|
||||
}
|
||||
|
||||
if(!$video->getOwner()->getPrivacyPermission('videos.read', $this->user)) {
|
||||
$reject(8, "Access to video denied: this user chose to hide his videos");
|
||||
}
|
||||
|
||||
$flags = 0;
|
||||
|
||||
$nPost = new Post;
|
||||
$nPost->setOwner($this->user->getId());
|
||||
|
||||
if($type == 0) {
|
||||
$nPost->setWall($this->user->getId());
|
||||
} else {
|
||||
$club = $this->groups->get($club);
|
||||
|
||||
if(!$club || $club->isDeleted() || !$club->canBeModifiedBy($this->user)) {
|
||||
$reject(64, "Can't do repost to this club");
|
||||
}
|
||||
|
||||
if($asGroup)
|
||||
$flags |= 0b10000000;
|
||||
|
||||
if($signed)
|
||||
$flags |= 0b01000000;
|
||||
|
||||
$nPost->setWall($club->getId() * -1);
|
||||
}
|
||||
|
||||
$nPost->setContent($message);
|
||||
$nPost->setFlags($flags);
|
||||
$nPost->save();
|
||||
|
||||
$nPost->attach($video);
|
||||
|
||||
$res = [
|
||||
"id" => $nPost->getId(),
|
||||
"pretty_id" => $nPost->getPrettyId(),
|
||||
];
|
||||
|
||||
$resolve($res);
|
||||
}
|
||||
}
|
|
@ -80,67 +80,4 @@ class Wall implements Handler
|
|||
|
||||
$resolve($post->getId());
|
||||
}
|
||||
|
||||
function getMyNotes(callable $resolve, callable $reject)
|
||||
{
|
||||
$count = $this->notes->getUserNotesCount($this->user);
|
||||
$myNotes = $this->notes->getUserNotes($this->user, 1, $count);
|
||||
|
||||
$arr = [
|
||||
"count" => $count,
|
||||
"closed" => $this->user->getPrivacySetting("notes.read"),
|
||||
"items" => [],
|
||||
];
|
||||
|
||||
foreach($myNotes as $note) {
|
||||
$arr["items"][] = [
|
||||
"id" => $note->getId(),
|
||||
"name" => ovk_proc_strtr($note->getName(), 30),
|
||||
#"preview" => $note->getPreview()
|
||||
];
|
||||
}
|
||||
|
||||
$resolve($arr);
|
||||
}
|
||||
|
||||
function getVideos(int $page = 1, callable $resolve, callable $reject)
|
||||
{
|
||||
$videos = $this->videos->getByUser($this->user, $page, 8);
|
||||
$count = $this->videos->getUserVideosCount($this->user);
|
||||
|
||||
$arr = [
|
||||
"count" => $count,
|
||||
"items" => [],
|
||||
];
|
||||
|
||||
foreach($videos as $video) {
|
||||
$res = json_decode(json_encode($video->toVkApiStruct($this->user)), true);
|
||||
$res["video"]["author_name"] = $video->getOwner()->getCanonicalName();
|
||||
|
||||
$arr["items"][] = $res;
|
||||
}
|
||||
|
||||
$resolve($arr);
|
||||
}
|
||||
|
||||
function searchVideos(int $page = 1, string $query, callable $resolve, callable $reject)
|
||||
{
|
||||
$dbc = $this->videos->find($query);
|
||||
$videos = $dbc->page($page, 8);
|
||||
$count = $dbc->size();
|
||||
|
||||
$arr = [
|
||||
"count" => $count,
|
||||
"items" => [],
|
||||
];
|
||||
|
||||
foreach($videos as $video) {
|
||||
$res = json_decode(json_encode($video->toVkApiStruct($this->user)), true);
|
||||
$res["video"]["author_name"] = $video->getOwner()->getCanonicalName();
|
||||
|
||||
$arr["items"][] = $res;
|
||||
}
|
||||
|
||||
$resolve($arr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,4 +190,42 @@ final class Account extends VKAPIRequestHandler
|
|||
|
||||
return $settings_list;
|
||||
}
|
||||
|
||||
function sendVotes(int $receiver, int $value, string $message = ""): object
|
||||
{
|
||||
$this->requireUser();
|
||||
$this->willExecuteWriteAction();
|
||||
|
||||
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
|
||||
$this->fail(-105, "Commerce is disabled on this instance");
|
||||
|
||||
if($receiver < 0)
|
||||
$this->fail(-248, "Invalid receiver id");
|
||||
|
||||
if($value < 1)
|
||||
$this->fail(-248, "Invalid value");
|
||||
|
||||
if(iconv_strlen($message) > 255)
|
||||
$this->fail(-249, "Message is too long");
|
||||
|
||||
if($this->getUser()->getCoins() < $value)
|
||||
$this->fail(-252, "Not enough votes");
|
||||
|
||||
$receiver_entity = (new \openvk\Web\Models\Repositories\Users)->get($receiver);
|
||||
if(!$receiver_entity || $receiver_entity->isDeleted())
|
||||
$this->fail(-250, "Invalid receiver");
|
||||
|
||||
if($receiver_entity->getId() === $this->getUser()->getId())
|
||||
$this->fail(-251, "Can't transfer votes to yourself");
|
||||
|
||||
$this->getUser()->setCoins($this->getUser()->getCoins() - $value);
|
||||
$this->getUser()->save();
|
||||
|
||||
$receiver_entity->setCoins($receiver_entity->getCoins() + $value);
|
||||
$receiver_entity->save();
|
||||
|
||||
(new \openvk\Web\Models\Entities\Notifications\CoinsTransferNotification($receiver_entity, $this->getUser(), $value, $message))->emit();
|
||||
|
||||
return (object) ['votes' => $this->getUser()->getCoins()];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,12 @@ final class Groups extends VKAPIRequestHandler
|
|||
{
|
||||
$this->requireUser();
|
||||
|
||||
# InfoApp fix
|
||||
if($filter == "admin" && ($user_id != 0 && $user_id != $this->getUser()->getId())) {
|
||||
$this->fail(15, 'Access denied: filter admin is available only for current user');
|
||||
}
|
||||
|
||||
$clbs = [];
|
||||
if($user_id == 0) {
|
||||
foreach($this->getUser()->getClubs($offset, $filter == "admin", $count, true) as $club)
|
||||
$clbs[] = $club;
|
||||
|
|
|
@ -48,7 +48,7 @@ final class Newsfeed extends VKAPIRequestHandler
|
|||
return $response;
|
||||
}
|
||||
|
||||
function getGlobal(string $fields = "", int $start_from = 0, int $start_time = 0, int $end_time = 0, int $offset = 0, int $count = 30, int $extended = 0)
|
||||
function getGlobal(string $fields = "", int $start_from = 0, int $start_time = 0, int $end_time = 0, int $offset = 0, int $count = 30, int $extended = 0, int $rss = 0)
|
||||
{
|
||||
$this->requireUser();
|
||||
|
||||
|
@ -74,6 +74,25 @@ final class Newsfeed extends VKAPIRequestHandler
|
|||
|
||||
$rposts = [];
|
||||
$ids = [];
|
||||
if($rss == 1) {
|
||||
$channel = new \Bhaktaraz\RSSGenerator\Channel();
|
||||
$channel->title("Global Feed — " . OPENVK_ROOT_CONF['openvk']['appearance']['name'])
|
||||
->description('OVK Global feed')
|
||||
->url(ovk_scheme(true) . $_SERVER["HTTP_HOST"] . "/feed/all");
|
||||
|
||||
foreach($posts as $item) {
|
||||
$post = (new PostsRepo)->get($item->id);
|
||||
if(!$post || $post->isDeleted()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$output = $post->toRss();
|
||||
$output->appendTo($channel);
|
||||
}
|
||||
|
||||
return $channel;
|
||||
}
|
||||
|
||||
foreach($posts as $post) {
|
||||
$rposts[] = (new PostsRepo)->get($post->id)->getPrettyId();
|
||||
$ids[] = $post->id;
|
||||
|
|
|
@ -427,7 +427,7 @@ final class Photos extends VKAPIRequestHandler
|
|||
$this->fail(15, "Access denied");
|
||||
|
||||
$photos = array_slice(iterator_to_array($album->getPhotos(1, $count + $offset)), $offset);
|
||||
$res["count"] = sizeof($photos);
|
||||
$res["count"] = $album->size();
|
||||
|
||||
foreach($photos as $photo) {
|
||||
if(!$photo || $photo->isDeleted()) continue;
|
||||
|
@ -638,15 +638,15 @@ final class Photos extends VKAPIRequestHandler
|
|||
$this->fail(4, "This method doesn't works with clubs");
|
||||
|
||||
$user = (new UsersRepo)->get($owner_id);
|
||||
|
||||
if(!$user)
|
||||
$this->fail(4, "Invalid user");
|
||||
|
||||
if(!$user->getPrivacyPermission('photos.read', $this->getUser()))
|
||||
$this->fail(21, "This user chose to hide his albums.");
|
||||
|
||||
$photos = array_slice(iterator_to_array((new PhotosRepo)->getEveryUserPhoto($user, 1, $count + $offset)), $offset);
|
||||
$photos = (new PhotosRepo)->getEveryUserPhoto($user, $offset, $count);
|
||||
$res = [
|
||||
"count" => (new PhotosRepo)->getUserPhotosCount($user),
|
||||
"items" => [],
|
||||
];
|
||||
|
||||
|
|
|
@ -11,24 +11,55 @@ use openvk\Web\Models\Repositories\Comments as CommentsRepo;
|
|||
|
||||
final class Video extends VKAPIRequestHandler
|
||||
{
|
||||
function get(int $owner_id, string $videos = "", int $offset = 0, int $count = 30, int $extended = 0): object
|
||||
function get(int $owner_id = 0, string $videos = "", string $fields = "", int $offset = 0, int $count = 30, int $extended = 0): object
|
||||
{
|
||||
$this->requireUser();
|
||||
|
||||
if(!empty($videos)) {
|
||||
$vids = explode(',', $videos);
|
||||
|
||||
foreach($vids as $vid)
|
||||
{
|
||||
$profiles = [];
|
||||
$groups = [];
|
||||
foreach($vids as $vid) {
|
||||
$id = explode("_", $vid);
|
||||
|
||||
$items = [];
|
||||
|
||||
$video = (new VideosRepo)->getByOwnerAndVID(intval($id[0]), intval($id[1]));
|
||||
if($video) {
|
||||
$items[] = $video->getApiStructure($this->getUser());
|
||||
if($video && !$video->isDeleted()) {
|
||||
$out_video = $video->getApiStructure($this->getUser())->video;
|
||||
$items[] = $out_video;
|
||||
if($out_video['owner_id']) {
|
||||
if($out_video['owner_id'] > 0)
|
||||
$profiles[] = $out_video['owner_id'];
|
||||
else
|
||||
$groups[] = abs($out_video['owner_id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($extended == 1) {
|
||||
$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" => sizeof($items),
|
||||
"items" => $items,
|
||||
"profiles" => $profilesFormatted,
|
||||
"groups" => $groupsFormatted,
|
||||
];
|
||||
}
|
||||
|
||||
return (object) [
|
||||
"count" => count($items),
|
||||
|
@ -46,12 +77,46 @@ final class Video extends VKAPIRequestHandler
|
|||
if(!$user->getPrivacyPermission('videos.read', $this->getUser()))
|
||||
$this->fail(21, "This user chose to hide his videos.");
|
||||
|
||||
$videos = (new VideosRepo)->getByUser($user, $offset + 1, $count);
|
||||
$videos = (new VideosRepo)->getByUserLimit($user, $offset, $count);
|
||||
$videosCount = (new VideosRepo)->getUserVideosCount($user);
|
||||
|
||||
$items = [];
|
||||
foreach ($videos as $video) {
|
||||
$items[] = $video->getApiStructure($this->getUser());
|
||||
$profiles = [];
|
||||
$groups = [];
|
||||
foreach($videos as $video) {
|
||||
$video = $video->getApiStructure($this->getUser())->video;
|
||||
$items[] = $video;
|
||||
if($video['owner_id']) {
|
||||
if($video['owner_id'] > 0)
|
||||
$profiles[] = $video['owner_id'];
|
||||
else
|
||||
$groups[] = abs($video['owner_id']);
|
||||
}
|
||||
}
|
||||
|
||||
if($extended == 1) {
|
||||
$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" => $videosCount,
|
||||
"items" => $items,
|
||||
"profiles" => $profilesFormatted,
|
||||
"groups" => $groupsFormatted,
|
||||
];
|
||||
}
|
||||
|
||||
return (object) [
|
||||
|
|
|
@ -20,7 +20,7 @@ use openvk\Web\Models\Repositories\Audios as AudiosRepo;
|
|||
|
||||
final class Wall extends VKAPIRequestHandler
|
||||
{
|
||||
function get(int $owner_id, string $domain = "", int $offset = 0, int $count = 30, int $extended = 0, string $filter = "all"): object
|
||||
function get(int $owner_id, string $domain = "", int $offset = 0, int $count = 30, int $extended = 0, string $filter = "all", int $rss = 0): object
|
||||
{
|
||||
$this->requireUser();
|
||||
|
||||
|
@ -86,6 +86,8 @@ final class Wall extends VKAPIRequestHandler
|
|||
break;
|
||||
}
|
||||
|
||||
$iteratorv = iterator_to_array($iteratorv);
|
||||
|
||||
foreach($iteratorv as $post) {
|
||||
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||
|
||||
|
@ -217,6 +219,20 @@ final class Wall extends VKAPIRequestHandler
|
|||
$attachments = NULL; # free attachments so it will not clone everythingg
|
||||
}
|
||||
|
||||
if($rss == 1) {
|
||||
$channel = new \Bhaktaraz\RSSGenerator\Channel();
|
||||
$channel->title($wallOnwer->getCanonicalName() . " — " . OPENVK_ROOT_CONF['openvk']['appearance']['name'])
|
||||
->description('Wall of ' . $wallOnwer->getCanonicalName())
|
||||
->url(ovk_scheme(true) . $_SERVER["HTTP_HOST"] . "/wall" . $wallOnwer->getRealId());
|
||||
|
||||
foreach($iteratorv as $item) {
|
||||
$output = $item->toRss();
|
||||
$output->appendTo($channel);
|
||||
}
|
||||
|
||||
return $channel;
|
||||
}
|
||||
|
||||
if($extended == 1) {
|
||||
$profiles = array_unique($profiles);
|
||||
$groups = array_unique($groups);
|
||||
|
@ -284,12 +300,16 @@ final class Wall extends VKAPIRequestHandler
|
|||
|
||||
foreach($psts as $pst) {
|
||||
$id = explode("_", $pst);
|
||||
$post = (new PostsRepo)->getPostById(intval($id[0]), intval($id[1]));
|
||||
$post = (new PostsRepo)->getPostById(intval($id[0]), intval($id[1]), true);
|
||||
|
||||
if($post && !$post->isDeleted()) {
|
||||
if(!$post->canBeViewedBy($this->getUser()))
|
||||
continue;
|
||||
|
||||
if($post->getSuggestionType() != 0 && !$post->canBeEditedBy($this->getUser())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||
$attachments = [];
|
||||
$repost = []; // чел высрал семь сигарет 😳 помянем 🕯
|
||||
|
@ -473,7 +493,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
];
|
||||
}
|
||||
|
||||
function post(string $owner_id, string $message = "", int $from_group = 0, int $signed = 0, string $attachments = "", int $post_id = 0): object
|
||||
function post(string $owner_id, string $message = "", string $copyright = "", int $from_group = 0, int $signed = 0, string $attachments = "", int $post_id = 0): object
|
||||
{
|
||||
$this->requireUser();
|
||||
$this->willExecuteWriteAction();
|
||||
|
@ -551,7 +571,17 @@ final class Wall extends VKAPIRequestHandler
|
|||
if($signed == 1)
|
||||
$flags |= 0b01000000;
|
||||
|
||||
if(empty($message) && empty($attachments))
|
||||
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'poll', 'audio']);
|
||||
$final_attachments = [];
|
||||
$should_be_suggested = $owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2;
|
||||
foreach($parsed_attachments as $attachment) {
|
||||
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
|
||||
!(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) {
|
||||
$final_attachments[] = $attachment;
|
||||
}
|
||||
}
|
||||
|
||||
if((empty($message) && (empty($attachments) || sizeof($final_attachments) < 1)))
|
||||
$this->fail(100, "Required parameter 'message' missing.");
|
||||
|
||||
try {
|
||||
|
@ -569,7 +599,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
} catch(\Throwable) {}
|
||||
}
|
||||
|
||||
if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2)
|
||||
if($should_be_suggested)
|
||||
$post->setSuggested(1);
|
||||
|
||||
$post->save();
|
||||
|
@ -577,121 +607,49 @@ final class Wall extends VKAPIRequestHandler
|
|||
$this->fail(100, "One of the parameters specified was missing or invalid");
|
||||
}
|
||||
|
||||
# TODO use parseAttachments
|
||||
if(!empty($attachments)) {
|
||||
$attachmentsArr = explode(",", $attachments);
|
||||
# Аттачи такого вида: [тип][id владельца]_[id вложения]
|
||||
# Пример: photo1_1
|
||||
|
||||
if(sizeof($attachmentsArr) > 10)
|
||||
$this->fail(50, "Too many attachments");
|
||||
|
||||
preg_match_all("/poll/m", $attachments, $matches, PREG_SET_ORDER, 0);
|
||||
if(sizeof($matches) > 1)
|
||||
$this->fail(85, "Too many polls");
|
||||
|
||||
foreach($attachmentsArr as $attac) {
|
||||
$attachmentType = NULL;
|
||||
|
||||
if(str_contains($attac, "photo"))
|
||||
$attachmentType = "photo";
|
||||
elseif(str_contains($attac, "video"))
|
||||
$attachmentType = "video";
|
||||
elseif(str_contains($attac, "note"))
|
||||
$attachmentType = "note";
|
||||
elseif(str_contains($attac, "poll"))
|
||||
$attachmentType = "poll";
|
||||
elseif(str_contains($attac, "audio"))
|
||||
$attachmentType = "audio";
|
||||
|
||||
else
|
||||
$this->fail(205, "Unknown attachment type");
|
||||
|
||||
$attachment = str_replace($attachmentType, "", $attac);
|
||||
|
||||
$attachmentOwner = (int)explode("_", $attachment)[0];
|
||||
$attachmentId = (int)end(explode("_", $attachment));
|
||||
|
||||
$attacc = NULL;
|
||||
|
||||
if($attachmentType == "photo") {
|
||||
$attacc = (new PhotosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Invalid photo");
|
||||
if(!$attacc->getOwner()->getPrivacyPermission('photos.read', $this->getUser()))
|
||||
$this->fail(43, "Access to photo denied");
|
||||
|
||||
$post->attach($attacc);
|
||||
} elseif($attachmentType == "video") {
|
||||
$attacc = (new VideosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Video does not exists");
|
||||
if(!$attacc->getOwner()->getPrivacyPermission('videos.read', $this->getUser()))
|
||||
$this->fail(43, "Access to video denied");
|
||||
|
||||
$post->attach($attacc);
|
||||
} elseif($attachmentType == "note") {
|
||||
$attacc = (new NotesRepo)->getNoteById($attachmentOwner, $attachmentId);
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Note does not exist");
|
||||
if(!$attacc->getOwner()->getPrivacyPermission('notes.read', $this->getUser()))
|
||||
$this->fail(11, "Access to note denied");
|
||||
|
||||
$post->attach($attacc);
|
||||
} elseif($attachmentType == "poll") {
|
||||
$attacc = (new PollsRepo)->get($attachmentId);
|
||||
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Poll does not exist");
|
||||
if($attacc->getOwner()->getId() != $this->getUser()->getId())
|
||||
$this->fail(43, "You do not have access to this poll");
|
||||
|
||||
$post->attach($attacc);
|
||||
} elseif($attachmentType == "audio") {
|
||||
$attacc = (new AudiosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Audio does not exist");
|
||||
|
||||
$post->attach($attacc);
|
||||
}
|
||||
}
|
||||
foreach($final_attachments as $attachment) {
|
||||
$post->attach($attachment);
|
||||
}
|
||||
|
||||
if($wall > 0 && $wall !== $this->user->identity->getId())
|
||||
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
||||
|
||||
if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2) {
|
||||
$suggsCount = (new PostsRepo)->getSuggestedPostsCount($wallOwner->getId());
|
||||
|
||||
if($suggsCount % 10 == 0) {
|
||||
$managers = $wallOwner->getManagers();
|
||||
$owner = $wallOwner->getOwner();
|
||||
(new NewSuggestedPostsNotification($owner, $wallOwner))->emit();
|
||||
|
||||
foreach($managers as $manager) {
|
||||
(new NewSuggestedPostsNotification($manager->getUser(), $wallOwner))->emit();
|
||||
}
|
||||
}
|
||||
|
||||
return (object)["post_id" => "on_view"];
|
||||
}
|
||||
|
||||
return (object)["post_id" => $post->getVirtualId()];
|
||||
}
|
||||
|
||||
function repost(string $object, string $message = "", int $group_id = 0) {
|
||||
function repost(string $object, string $message = "", string $attachments = "", int $group_id = 0, int $as_group = 0, int $signed = 0) {
|
||||
$this->requireUser();
|
||||
$this->willExecuteWriteAction();
|
||||
|
||||
$postArray;
|
||||
if(preg_match('/wall((?:-?)[0-9]+)_([0-9]+)/', $object, $postArray) == 0)
|
||||
if(preg_match('/(wall|video|photo)((?:-?)[0-9]+)_([0-9]+)/', $object, $postArray) == 0)
|
||||
$this->fail(100, "One of the parameters specified was missing or invalid: object is incorrect");
|
||||
|
||||
$post = (new PostsRepo)->getPostById((int) $postArray[1], (int) $postArray[2]);
|
||||
if(!$post || $post->isDeleted()) $this->fail(100, "One of the parameters specified was missing or invalid");
|
||||
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']);
|
||||
$final_attachments = [];
|
||||
foreach($parsed_attachments as $attachment) {
|
||||
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
|
||||
!(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) {
|
||||
$final_attachments[] = $attachment;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$post->canBeViewedBy($this->getUser()))
|
||||
$this->fail(15, "Access denied");
|
||||
$repost_entity = NULL;
|
||||
$repost_type = $postArray[1];
|
||||
switch($repost_type) {
|
||||
default:
|
||||
case 'wall':
|
||||
$repost_entity = (new PostsRepo)->getPostById((int) $postArray[2], (int) $postArray[3]);
|
||||
break;
|
||||
case 'photo':
|
||||
$repost_entity = (new PhotosRepo)->getByOwnerAndVID((int) $postArray[2], (int) $postArray[3]);
|
||||
break;
|
||||
case 'video':
|
||||
$repost_entity = (new VideosRepo)->getByOwnerAndVID((int) $postArray[2], (int) $postArray[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!$repost_entity || $repost_entity->isDeleted() || !$repost_entity->canBeViewedBy($this->getUser())) $this->fail(100, "One of the parameters specified was missing or invalid");
|
||||
|
||||
$nPost = new Post;
|
||||
$nPost->setOwner($this->user->getId());
|
||||
|
@ -704,7 +662,15 @@ final class Wall extends VKAPIRequestHandler
|
|||
if(!$club->canBeModifiedBy($this->user))
|
||||
$this->fail(16, "Access to group denied");
|
||||
|
||||
$nPost->setWall($group_id * -1);
|
||||
$nPost->setWall($club->getRealId());
|
||||
$flags = 0;
|
||||
if($as_group === 1 || $signed === 1)
|
||||
$flags |= 0b10000000;
|
||||
|
||||
if($signed === 1)
|
||||
$flags |= 0b01000000;
|
||||
|
||||
$nPost->setFlags($flags);
|
||||
} else {
|
||||
$nPost->setWall($this->user->getId());
|
||||
}
|
||||
|
@ -712,16 +678,27 @@ final class Wall extends VKAPIRequestHandler
|
|||
$nPost->setContent($message);
|
||||
$nPost->setApi_Source_Name($this->getPlatform());
|
||||
$nPost->save();
|
||||
$nPost->attach($post);
|
||||
|
||||
if($post->getOwner(false)->getId() !== $this->user->getId() && !($post->getOwner() instanceof Club))
|
||||
(new RepostNotification($post->getOwner(false), $post, $this->user))->emit();
|
||||
$nPost->attach($repost_entity);
|
||||
|
||||
foreach($parsed_attachments as $attachment) {
|
||||
$nPost->attach($attachment);
|
||||
}
|
||||
|
||||
if($repost_type == 'wall' && $repost_entity->getOwner(false)->getId() !== $this->user->getId() && !($repost_entity->getOwner() instanceof Club))
|
||||
(new RepostNotification($repost_entity->getOwner(false), $repost_entity, $this->user))->emit();
|
||||
|
||||
$repost_count = 1;
|
||||
if($repost_type == 'wall') {
|
||||
$repost_count = $repost_entity->getRepostCount();
|
||||
}
|
||||
|
||||
return (object) [
|
||||
"success" => 1, // 👍
|
||||
"post_id" => $nPost->getVirtualId(),
|
||||
"reposts_count" => $post->getRepostCount(),
|
||||
"likes_count" => $post->getLikesCount()
|
||||
"pretty_id" => $nPost->getPrettyId(),
|
||||
"reposts_count" => $repost_count,
|
||||
"likes_count" => $repost_entity->getLikesCount()
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -767,7 +744,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
"date" => $comment->getPublicationTime()->timestamp(),
|
||||
"text" => $comment->getText(false),
|
||||
"post_id" => $post->getVirtualId(),
|
||||
"owner_id" => $post->isPostedOnBehalfOfGroup() ? $post->getOwner()->getId() * -1 : $post->getOwner()->getId(),
|
||||
"owner_id" => method_exists($post, 'isPostedOnBehalfOfGroup') && $post->isPostedOnBehalfOfGroup() ? $post->getOwner()->getId() * -1 : $post->getOwner()->getId(),
|
||||
"parents_stack" => [],
|
||||
"attachments" => $attachments,
|
||||
"thread" => [
|
||||
|
@ -833,6 +810,13 @@ final class Wall extends VKAPIRequestHandler
|
|||
foreach($comment->getChildren() as $attachment) {
|
||||
if($attachment instanceof \openvk\Web\Models\Entities\Photo) {
|
||||
$attachments[] = $this->getApiPhoto($attachment);
|
||||
} elseif($attachment instanceof \openvk\Web\Models\Entities\Video) {
|
||||
$attachments[] = $attachment->getApiStructure();
|
||||
} elseif($attachment instanceof \openvk\Web\Models\Entities\Note) {
|
||||
$attachments[] = [
|
||||
'type' => 'note',
|
||||
'note' => $attachment->toVkApiStruct()
|
||||
];
|
||||
} elseif($attachment instanceof \openvk\Web\Models\Entities\Audio) {
|
||||
$attachments[] = [
|
||||
"type" => "audio",
|
||||
|
@ -847,7 +831,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
"date" => $comment->getPublicationTime()->timestamp(),
|
||||
"text" => $comment->getText(false),
|
||||
"post_id" => $comment->getTarget()->getVirtualId(),
|
||||
"owner_id" => $comment->getTarget()->isPostedOnBehalfOfGroup() ? $comment->getTarget()->getOwner()->getId() * -1 : $comment->getTarget()->getOwner()->getId(),
|
||||
"owner_id" => method_exists($comment->getTarget(), 'isPostedOnBehalfOfGroup') && $comment->getTarget()->isPostedOnBehalfOfGroup() ? $comment->getTarget()->getOwner()->getId() * -1 : $comment->getTarget()->getOwner()->getId(),
|
||||
"parents_stack" => [],
|
||||
"attachments" => $attachments,
|
||||
"likes" => [
|
||||
|
@ -899,7 +883,16 @@ final class Wall extends VKAPIRequestHandler
|
|||
if($post->getTargetWall() < 0)
|
||||
$club = (new ClubsRepo)->get(abs($post->getTargetWall()));
|
||||
|
||||
if(empty($message) && empty($attachments)) {
|
||||
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']);
|
||||
$final_attachments = [];
|
||||
foreach($parsed_attachments as $attachment) {
|
||||
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
|
||||
!(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) {
|
||||
$final_attachments[] = $attachment;
|
||||
}
|
||||
}
|
||||
|
||||
if((empty($message) && (empty($attachments) || sizeof($final_attachments) < 1))) {
|
||||
$this->fail(100, "Required parameter 'message' missing.");
|
||||
}
|
||||
|
||||
|
@ -920,55 +913,8 @@ final class Wall extends VKAPIRequestHandler
|
|||
$this->fail(1, "ошибка про то что коммент большой слишком");
|
||||
}
|
||||
|
||||
if(!empty($attachments)) {
|
||||
$attachmentsArr = explode(",", $attachments);
|
||||
|
||||
if(sizeof($attachmentsArr) > 10)
|
||||
$this->fail(50, "Error: too many attachments");
|
||||
|
||||
foreach($attachmentsArr as $attac) {
|
||||
$attachmentType = NULL;
|
||||
|
||||
if(str_contains($attac, "photo"))
|
||||
$attachmentType = "photo";
|
||||
elseif(str_contains($attac, "video"))
|
||||
$attachmentType = "video";
|
||||
elseif(str_contains($attac, "audio"))
|
||||
$attachmentType = "audio";
|
||||
else
|
||||
$this->fail(205, "Unknown attachment type");
|
||||
|
||||
$attachment = str_replace($attachmentType, "", $attac);
|
||||
|
||||
$attachmentOwner = (int)explode("_", $attachment)[0];
|
||||
$attachmentId = (int)end(explode("_", $attachment));
|
||||
|
||||
$attacc = NULL;
|
||||
|
||||
if($attachmentType == "photo") {
|
||||
$attacc = (new PhotosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Photo does not exists");
|
||||
if(!$attacc->getOwner()->getPrivacyPermission('photos.read', $this->getUser()))
|
||||
$this->fail(11, "Access to photo denied");
|
||||
|
||||
$comment->attach($attacc);
|
||||
} elseif($attachmentType == "video") {
|
||||
$attacc = (new VideosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Video does not exists");
|
||||
if(!$attacc->getOwner()->getPrivacyPermission('videos.read', $this->getUser()))
|
||||
$this->fail(11, "Access to video denied");
|
||||
|
||||
$comment->attach($attacc);
|
||||
} elseif($attachmentType == "audio") {
|
||||
$attacc = (new AudiosRepo)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
if(!$attacc || $attacc->isDeleted())
|
||||
$this->fail(100, "Audio does not exist");
|
||||
|
||||
$comment->attach($attacc);
|
||||
}
|
||||
}
|
||||
foreach($final_attachments as $attachment) {
|
||||
$comment->attach($attachment);
|
||||
}
|
||||
|
||||
if($post->getOwner()->getId() !== $this->user->getId())
|
||||
|
@ -1019,11 +965,24 @@ final class Wall extends VKAPIRequestHandler
|
|||
}
|
||||
}
|
||||
|
||||
function edit(int $owner_id, int $post_id, string $message = "", string $attachments = "", string $copyright = NULL) {
|
||||
function edit(int $owner_id, int $post_id, string $message = "", string $attachments = "", string $copyright = NULL, int $explicit = -1, int $from_group = 0, int $signed = 0) {
|
||||
$this->requireUser();
|
||||
$this->willExecuteWriteAction();
|
||||
|
||||
$post = (new PostsRepo)->getPostById($owner_id, $post_id);
|
||||
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio', 'poll']);
|
||||
$final_attachments = [];
|
||||
foreach($parsed_attachments as $attachment) {
|
||||
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
|
||||
!(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) {
|
||||
$final_attachments[] = $attachment;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($message) && sizeof($final_attachments) < 1) {
|
||||
$this->fail(-66, "Post will be empty, don't saving.");
|
||||
}
|
||||
|
||||
$post = (new PostsRepo)->getPostById($owner_id, $post_id, true);
|
||||
|
||||
if(!$post || $post->isDeleted())
|
||||
$this->fail(102, "Invalid post");
|
||||
|
@ -1031,36 +990,43 @@ final class Wall extends VKAPIRequestHandler
|
|||
if(!$post->canBeEditedBy($this->getUser()))
|
||||
$this->fail(7, "Access to editing denied");
|
||||
|
||||
if(!empty($message))
|
||||
if(!empty($message) || (empty($message) && sizeof($final_attachments) > 0))
|
||||
$post->setContent($message);
|
||||
|
||||
$post->setEdited(time());
|
||||
if(!is_null($copyright) && !empty($copyright)) {
|
||||
if($copyright == 'remove') {
|
||||
$post->resetSource();
|
||||
} else {
|
||||
try {
|
||||
$post->setSource($copyright);
|
||||
} catch(\Throwable) {}
|
||||
}
|
||||
}
|
||||
|
||||
if($explicit != -1) {
|
||||
$post->setNsfw($explicit == 1);
|
||||
}
|
||||
|
||||
$wallOwner = ($owner_id > 0 ? (new UsersRepo)->get($owner_id) : (new ClubsRepo)->get($owner_id * -1));
|
||||
$flags = 0;
|
||||
if($from_group == 1 && $wallOwner instanceof Club && $wallOwner->canBeModifiedBy($this->getUser()))
|
||||
$flags |= 0b10000000;
|
||||
/*if($signed == 1)
|
||||
$flags |= 0b01000000;*/
|
||||
|
||||
$post->setFlags($flags);
|
||||
$post->save(true);
|
||||
|
||||
# todo добавить такое в веб версию
|
||||
if(!empty($attachments)) {
|
||||
$attachs = parseAttachments($attachments);
|
||||
$newAttachmentsCount = sizeof($attachs);
|
||||
if($attachments == 'remove' || sizeof($final_attachments) > 0) {
|
||||
foreach($post->getChildren() as $att) {
|
||||
if(!($att instanceof Post)) {
|
||||
$post->detach($att);
|
||||
}
|
||||
}
|
||||
|
||||
$postsAttachments = iterator_to_array($post->getChildren());
|
||||
|
||||
if(sizeof($postsAttachments) >= 10)
|
||||
$this->fail(15, "Post have too many attachments");
|
||||
|
||||
if(($newAttachmentsCount + sizeof($postsAttachments)) > 10)
|
||||
$this->fail(158, "Post will have too many attachments");
|
||||
|
||||
foreach($attachs as $attach) {
|
||||
if($attach && !$attach->isDeleted())
|
||||
$post->attach($attach);
|
||||
else
|
||||
$this->fail(52, "One of the attachments is invalid");
|
||||
foreach($final_attachments as $attachment) {
|
||||
$post->attach($attachment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1072,8 +1038,16 @@ final class Wall extends VKAPIRequestHandler
|
|||
$this->willExecuteWriteAction();
|
||||
|
||||
$comment = (new CommentsRepo)->get($comment_id);
|
||||
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']);
|
||||
$final_attachments = [];
|
||||
foreach($parsed_attachments as $attachment) {
|
||||
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
|
||||
!(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) {
|
||||
$final_attachments[] = $attachment;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($message) && empty($attachments))
|
||||
if(empty($message) && sizeof($final_attachments) < 1)
|
||||
$this->fail(100, "Required parameter 'message' missing.");
|
||||
|
||||
if(!$comment || $comment->isDeleted())
|
||||
|
@ -1082,29 +1056,16 @@ final class Wall extends VKAPIRequestHandler
|
|||
if(!$comment->canBeEditedBy($this->getUser()))
|
||||
$this->fail(15, "Access to editing comment denied");
|
||||
|
||||
if(!empty($message))
|
||||
if(!empty($message) || (empty($message) && sizeof($final_attachments) > 0))
|
||||
$comment->setContent($message);
|
||||
|
||||
$comment->setEdited(time());
|
||||
$comment->save(true);
|
||||
|
||||
if(!empty($attachments)) {
|
||||
$attachs = parseAttachments($attachments);
|
||||
$newAttachmentsCount = sizeof($attachs);
|
||||
|
||||
$postsAttachments = iterator_to_array($comment->getChildren());
|
||||
|
||||
if(sizeof($postsAttachments) >= 10)
|
||||
$this->fail(15, "Post have too many attachments");
|
||||
|
||||
if(($newAttachmentsCount + sizeof($postsAttachments)) > 10)
|
||||
$this->fail(158, "Post will have too many attachments");
|
||||
|
||||
foreach($attachs as $attach) {
|
||||
if($attach && !$attach->isDeleted())
|
||||
$comment->attach($attach);
|
||||
else
|
||||
$this->fail(52, "One of the attachments is invalid");
|
||||
if(sizeof($final_attachments) > 0) {
|
||||
$comment->unwire();
|
||||
foreach($final_attachments as $attachment) {
|
||||
$comment->attach($attachment);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ class Album extends MediaCollection
|
|||
$res = (object) [];
|
||||
|
||||
$res->id = $this->getPrettyId();
|
||||
$res->vid = $this->getId();
|
||||
$res->thumb_id = !is_null($this->getCoverPhoto()) ? $this->getCoverPhoto()->getPrettyId() : 0;
|
||||
$res->owner_id = $this->getOwner()->getId();
|
||||
$res->title = $this->getName();
|
||||
|
|
|
@ -39,7 +39,7 @@ class BannedLink extends RowModel
|
|||
|
||||
function getRegexpRule(): string
|
||||
{
|
||||
return addslashes("/" . $this->getDomain() . $this->getRawRegexp() . "/");
|
||||
return "/^" . $this->getDomain() . "\/" . $this->getRawRegexp() . "$/i";
|
||||
}
|
||||
|
||||
function getRawRegexp(): string
|
||||
|
|
|
@ -308,7 +308,7 @@ class Photo extends Media
|
|||
$res->date = $res->created = $this->getPublicationTime()->timestamp();
|
||||
|
||||
if($photo_sizes) {
|
||||
$res->sizes = $this->getVkApiSizes();
|
||||
$res->sizes = array_values($this->getVkApiSizes());
|
||||
$res->src_small = $res->photo_75 = $this->getURLBySizeId("miniscule");
|
||||
$res->src = $res->photo_130 = $this->getURLBySizeId("tiny");
|
||||
$res->src_big = $res->photo_604 = $this->getURLBySizeId("normal");
|
||||
|
|
|
@ -103,6 +103,11 @@ class Post extends Postable
|
|||
$this->stateChanges("source", $source);
|
||||
}
|
||||
|
||||
function resetSource()
|
||||
{
|
||||
$this->stateChanges("source", NULL);
|
||||
}
|
||||
|
||||
function getVkApiCopyright(): object
|
||||
{
|
||||
return (object)[
|
||||
|
@ -369,5 +374,46 @@ class Post extends Postable
|
|||
return $user->getId() == $this->getOwner(false)->getId();
|
||||
}
|
||||
|
||||
function toRss(): \Bhaktaraz\RSSGenerator\Item
|
||||
{
|
||||
$domain = ovk_scheme(true).$_SERVER["HTTP_HOST"];
|
||||
$description = $this->getText(false);
|
||||
$description_html = $description;
|
||||
$url = $domain."/wall".$this->getPrettyId();
|
||||
|
||||
$author = $this->getOwner();
|
||||
$author_name = htmlspecialchars($author->getCanonicalName(), ENT_DISALLOWED | ENT_XHTML);
|
||||
if($this->isExplicit())
|
||||
$description_html .= "<br /><b>".tr('contains_nsfw').".</b><br />";
|
||||
|
||||
foreach($this->getChildren() as $child) {
|
||||
if($child instanceof Photo) {
|
||||
$child_page = $domain.$child->getPageURL();
|
||||
$child_url = $child->getURLBySizeId('large');
|
||||
$description_html .= "<br /><a href='$child_page'><img src='$child_url'></a>";
|
||||
} elseif($child instanceof Video) {
|
||||
$child_page = $domain.'/video'.$child->getPrettyId();
|
||||
$description_html .= "<br /><a href='$child_page'>Video</a>";
|
||||
} elseif($child instanceof Audio) {
|
||||
$description_html .= "<br />Audio";
|
||||
}
|
||||
}
|
||||
|
||||
$description_html .= "<br />".tr('author').": <img width='15px' src='".$author->getAvatarURL()."'><a href='".$author->getURL()."'>" . $author_name . "</a>";
|
||||
if($this->hasSource()) {
|
||||
$description_html .= "<br />".tr('source').": ".htmlspecialchars($this->getSource(), ENT_DISALLOWED | ENT_XHTML);
|
||||
}
|
||||
|
||||
$item = new \Bhaktaraz\RSSGenerator\Item();
|
||||
$item->title(str_replace("\n", "", ovk_proc_strtr($description, 79)))
|
||||
->url($url)
|
||||
->guid($url)
|
||||
->creator($author_name)
|
||||
->pubDate($this->getPublicationTime()->timestamp())
|
||||
->content(str_replace("\n", "<br />", $description_html));
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
use Traits\TRichText;
|
||||
}
|
||||
|
|
|
@ -134,8 +134,13 @@ class Report extends RowModel
|
|||
|
||||
function getContentName(): string
|
||||
{
|
||||
if (method_exists($this->getContentObject(), "getCanonicalName"))
|
||||
return $this->getContentObject()->getCanonicalName();
|
||||
$content_object = $this->getContentObject();
|
||||
if(!$content_object) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
if (method_exists($content_object, "getCanonicalName"))
|
||||
return $content_object->getCanonicalName();
|
||||
|
||||
return $this->getContentType() . " #" . $this->getContentId();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities\Traits;
|
||||
use openvk\Web\Models\Entities\{Attachable, Photo};
|
||||
use openvk\Web\Models\Entities\{Attachable, Photo, Video};
|
||||
use openvk\Web\Util\Makima\Makima;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
||||
|
@ -36,10 +36,10 @@ trait TAttachmentHost
|
|||
if($h < 0)
|
||||
$h = $w;
|
||||
|
||||
$children = $this->getChildren();
|
||||
$children = iterator_to_array($this->getChildren());
|
||||
$skipped = $photos = $result = [];
|
||||
foreach($children as $child) {
|
||||
if($child instanceof Photo) {
|
||||
if($child instanceof Photo || $child instanceof Video && $child->getDimensions()) {
|
||||
$photos[] = $child;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -34,9 +34,23 @@ class Video extends Media
|
|||
if(sizeof($durations[1]) === 0)
|
||||
throw new \DomainException("$filename does not contain any meaningful video streams");
|
||||
|
||||
foreach($durations[1] as $duration)
|
||||
if(floatval($duration) < 1.0)
|
||||
$length = 0;
|
||||
foreach($durations[1] as $duration) {
|
||||
$duration = floatval($duration);
|
||||
if($duration < 1.0)
|
||||
throw new \DomainException("$filename does not contain any meaningful video streams");
|
||||
else
|
||||
$length = max($length, $duration);
|
||||
}
|
||||
|
||||
$this->stateChanges("length", (int) round($length, 0, PHP_ROUND_HALF_EVEN));
|
||||
|
||||
preg_match('%width=([0-9\.]++)%', $streams, $width);
|
||||
preg_match('%height=([0-9\.]++)%', $streams, $height);
|
||||
if(!empty($width) && !empty($height)) {
|
||||
$this->stateChanges("width", $width[1]);
|
||||
$this->stateChanges("height", $height[1]);
|
||||
}
|
||||
|
||||
try {
|
||||
if(!is_dir($dirId = dirname($this->pathFromHash($hash))))
|
||||
|
@ -118,6 +132,7 @@ class Video extends Media
|
|||
function getApiStructure(?User $user = NULL): object
|
||||
{
|
||||
$fromYoutube = $this->getType() == Video::TYPE_EMBED;
|
||||
$dimensions = $this->getDimensions();
|
||||
$res = (object)[
|
||||
"type" => "video",
|
||||
"video" => [
|
||||
|
@ -130,7 +145,7 @@ class Video extends Media
|
|||
"comments" => $this->getCommentsCount(),
|
||||
"date" => $this->getPublicationTime()->timestamp(),
|
||||
"description" => $this->getDescription(),
|
||||
"duration" => 0, // я хуй знает как получить длину видео
|
||||
"duration" => $this->getLength(),
|
||||
"image" => [
|
||||
[
|
||||
"url" => $this->getThumbnailURL(),
|
||||
|
@ -139,8 +154,8 @@ class Video extends Media
|
|||
"with_padding" => 1
|
||||
]
|
||||
],
|
||||
"width" => 640,
|
||||
"height" => 480,
|
||||
"width" => $dimensions ? $dimensions[0] : 640,
|
||||
"height" => $dimensions ? $dimensions[1] : 480,
|
||||
"id" => $this->getVirtualId(),
|
||||
"owner_id" => $this->getOwner()->getId(),
|
||||
"user_id" => $this->getOwner()->getId(),
|
||||
|
@ -155,6 +170,7 @@ class Video extends Media
|
|||
"repeat" => 0,
|
||||
"type" => "video",
|
||||
"views" => 0,
|
||||
"is_processed" => $this->isProcessed(),
|
||||
"reposts" => [
|
||||
"count" => 0,
|
||||
"user_reposted" => 0
|
||||
|
@ -225,6 +241,74 @@ class Video extends Media
|
|||
return $video;
|
||||
}
|
||||
|
||||
function fillDimensions()
|
||||
{
|
||||
$hash = $this->getRecord()->hash;
|
||||
$path = $this->pathFromHash($hash);
|
||||
if(!file_exists($path)) {
|
||||
$this->stateChanges("width", 0);
|
||||
$this->stateChanges("height", 0);
|
||||
$this->stateChanges("length", 0);
|
||||
$this->save();
|
||||
return false;
|
||||
}
|
||||
|
||||
$streams = Shell::ffprobe("-i", $path, "-show_streams", "-select_streams v", "-loglevel error")->execute($error);
|
||||
$durations = [];
|
||||
preg_match_all('%duration=([0-9\.]++)%', $streams, $durations);
|
||||
|
||||
$length = 0;
|
||||
foreach($durations[1] as $duration) {
|
||||
$duration = floatval($duration);
|
||||
if($duration < 1.0)
|
||||
continue;
|
||||
else
|
||||
$length = max($length, $duration);
|
||||
}
|
||||
$this->stateChanges("length", (int) round($length, 0, PHP_ROUND_HALF_EVEN));
|
||||
|
||||
preg_match('%width=([0-9\.]++)%', $streams, $width);
|
||||
preg_match('%height=([0-9\.]++)%', $streams, $height);
|
||||
|
||||
if(!empty($width) && !empty($height)) {
|
||||
$this->stateChanges("width", $width[1]);
|
||||
$this->stateChanges("height", $height[1]);
|
||||
}
|
||||
|
||||
$this->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getDimensions()
|
||||
{
|
||||
if($this->getType() == Video::TYPE_EMBED) return [320, 180];
|
||||
|
||||
$width = $this->getRecord()->width;
|
||||
$height = $this->getRecord()->height;
|
||||
|
||||
if(!$width) return NULL;
|
||||
return $width != 0 ? [$width, $height] : NULL;
|
||||
}
|
||||
|
||||
function getLength()
|
||||
{
|
||||
return $this->getRecord()->length;
|
||||
}
|
||||
|
||||
function getFormattedLength(): string
|
||||
{
|
||||
$len = $this->getLength();
|
||||
if(!$len) return "00:00";
|
||||
$mins = floor($len / 60);
|
||||
$secs = $len - ($mins * 60);
|
||||
return (
|
||||
str_pad((string) $mins, 2, "0", STR_PAD_LEFT)
|
||||
. ":" .
|
||||
str_pad((string) $secs, 2, "0", STR_PAD_LEFT)
|
||||
);
|
||||
}
|
||||
|
||||
function canBeViewedBy(?User $user = NULL): bool
|
||||
{
|
||||
if($this->isDeleted() || $this->getOwner()->isDeleted()) {
|
||||
|
@ -248,7 +332,7 @@ class Video extends Media
|
|||
$res->owner_id = $this->getOwner()->getId();
|
||||
$res->title = $this->getName();
|
||||
$res->description = $this->getDescription();
|
||||
$res->duration = "22";
|
||||
$res->duration = $this->getLength();
|
||||
$res->link = "/video".$this->getOwner()->getId()."_".$this->getVirtualId();
|
||||
$res->image = $this->getThumbnailURL();
|
||||
$res->date = $this->getPublicationTime()->timestamp();
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace openvk\Web\Models\Repositories;
|
|||
use Chandler\Database\DatabaseConnection as DB;
|
||||
use Nette\Database\Table\{ActiveRow, Selection};
|
||||
use openvk\Web\Models\Entities\BannedLink;
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
class BannedLinks
|
||||
{
|
||||
|
@ -43,7 +44,7 @@ class BannedLinks
|
|||
|
||||
function isDomainBanned(string $domain): bool
|
||||
{
|
||||
return sizeof($this->bannedLinks->where(["link" => $domain, "regexp_rule" => ""])) > 0;
|
||||
return sizeof($this->bannedLinks->where(["domain" => $domain, "regexp_rule" => ""])) > 0;
|
||||
}
|
||||
|
||||
function genLinks($rules): \Traversable
|
||||
|
@ -57,12 +58,14 @@ class BannedLinks
|
|||
foreach($links as $link)
|
||||
if (preg_match($link->getRegexpRule(), $uri))
|
||||
yield $link->getId();
|
||||
else if ($this->isDomainBanned($link->getDomain()))
|
||||
yield $link->getId();
|
||||
}
|
||||
|
||||
function check(string $url): ?array
|
||||
{
|
||||
$uri = strstr(str_replace(["https://", "http://"], "", $url), "/", true);
|
||||
$domain = str_replace("www.", "", $uri);
|
||||
$uri = str_replace(["https://", "http://"], "", $url);
|
||||
$domain = explode("/", str_replace("www.", "", $uri))[0];
|
||||
$rules = $this->getByDomain($domain);
|
||||
|
||||
if (is_null($rules))
|
||||
|
|
|
@ -33,7 +33,7 @@ class Photos
|
|||
return new Photo($photo);
|
||||
}
|
||||
|
||||
function getEveryUserPhoto(User $user, int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
function getEveryUserPhoto(User $user, int $offset = 0, int $limit = 10): \Traversable
|
||||
{
|
||||
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
||||
$photos = $this->photos->where([
|
||||
|
@ -41,7 +41,7 @@ class Photos
|
|||
"deleted" => 0
|
||||
])->order("id DESC");
|
||||
|
||||
foreach($photos->page($page, $perPage) as $photo) {
|
||||
foreach($photos->limit($limit, $offset) as $photo) {
|
||||
yield new Photo($photo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,13 @@ class Videos
|
|||
yield new Video($video);
|
||||
}
|
||||
|
||||
function getByUserLimit(User $user, int $offset = 0, int $limit = 10): \Traversable
|
||||
{
|
||||
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
||||
foreach($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0])->limit($limit, $offset)->order("created DESC") as $video)
|
||||
yield new Video($video);
|
||||
}
|
||||
|
||||
function getUserVideosCount(User $user): int
|
||||
{
|
||||
return sizeof($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0]));
|
||||
|
@ -49,7 +56,7 @@ class Videos
|
|||
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||
{
|
||||
$query = "%$query%";
|
||||
$result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0);
|
||||
$result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0)->where("unlisted", 0);
|
||||
$order_str = 'id';
|
||||
|
||||
switch($order['type']) {
|
||||
|
|
|
@ -481,7 +481,7 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
if ($link) {
|
||||
$link->setDomain($new_domain ?? $this->postParam("link"));
|
||||
$link->setReason($new_reason);
|
||||
$link->setRegexp_rule($this->postParam("regexp"));
|
||||
$link->setRegexp_rule(mb_strlen(trim($this->postParam("regexp"))) > 0 ? $this->postParam("regexp") : "");
|
||||
$link->save();
|
||||
} else {
|
||||
if (!$new_domain)
|
||||
|
@ -490,7 +490,7 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
$link = new BannedLink;
|
||||
$link->setDomain($new_domain);
|
||||
$link->setReason($new_reason);
|
||||
$link->setRegexp_rule($this->postParam("regexp"));
|
||||
$link->setRegexp_rule(mb_strlen(trim($this->postParam("regexp"))) > 0 ? $this->postParam("regexp") : "");
|
||||
$link->setInitiator($this->user->identity->getId());
|
||||
$link->save();
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
|
||||
function renderList(?int $owner = NULL, ?string $mode = "list"): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
$this->template->_template = "Audio/List.xml";
|
||||
$page = (int)($this->queryParam("p") ?? 1);
|
||||
$audios = [];
|
||||
|
@ -501,6 +502,7 @@ final class AudioPresenter extends OpenVKPresenter
|
|||
|
||||
function renderPlaylist(int $owner_id, int $virtual_id): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
$playlist = $this->audios->getPlaylistByOwnerAndVID($owner_id, $virtual_id);
|
||||
$page = (int)($this->queryParam("p") ?? 1);
|
||||
if (!$playlist || $playlist->isDeleted())
|
||||
|
|
|
@ -7,7 +7,7 @@ final class AwayPresenter extends OpenVKPresenter
|
|||
{
|
||||
function renderAway(): void
|
||||
{
|
||||
$checkBanEntries = (new BannedLinks)->check($this->queryParam("to") . "/");
|
||||
$checkBanEntries = (new BannedLinks)->check($this->queryParam("to"));
|
||||
if (OPENVK_ROOT_CONF["openvk"]["preferences"]["susLinks"]["warnings"])
|
||||
if (sizeof($checkBanEntries) > 0)
|
||||
$this->pass("openvk!Away->view", $checkBanEntries[0]);
|
||||
|
|
|
@ -27,6 +27,11 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("error"), tr("forbidden"));
|
||||
|
||||
if(!is_null($this->user)) $comment->toggleLike($this->user->identity);
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$this->returnJson([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->redirect($_SERVER["HTTP_REFERER"]);
|
||||
}
|
||||
|
@ -71,63 +76,23 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
}
|
||||
}
|
||||
|
||||
$photos = [];
|
||||
if(!empty($this->postParam("photos"))) {
|
||||
$un = rtrim($this->postParam("photos"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
if(sizeof($arr) < 11) {
|
||||
foreach($arr as $dat) {
|
||||
$ids = explode("_", $dat);
|
||||
$photo = (new Photos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
||||
|
||||
if(!$photo || $photo->isDeleted())
|
||||
continue;
|
||||
|
||||
$photos[] = $photo;
|
||||
}
|
||||
$horizontal_attachments = [];
|
||||
$vertical_attachments = [];
|
||||
if(!empty($this->postParam("horizontal_attachments"))) {
|
||||
$horizontal_attachments_array = array_slice(explode(",", $this->postParam("horizontal_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]);
|
||||
if(sizeof($horizontal_attachments_array) > 0) {
|
||||
$horizontal_attachments = parseAttachments($horizontal_attachments_array, ['photo', 'video']);
|
||||
}
|
||||
}
|
||||
|
||||
$videos = [];
|
||||
|
||||
if(!empty($this->postParam("videos"))) {
|
||||
$un = rtrim($this->postParam("videos"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
if(sizeof($arr) < 11) {
|
||||
foreach($arr as $dat) {
|
||||
$ids = explode("_", $dat);
|
||||
$video = (new Videos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
||||
|
||||
if(!$video || $video->isDeleted())
|
||||
continue;
|
||||
|
||||
$videos[] = $video;
|
||||
}
|
||||
if(!empty($this->postParam("vertical_attachments"))) {
|
||||
$vertical_attachments_array = array_slice(explode(",", $this->postParam("vertical_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]);
|
||||
if(sizeof($vertical_attachments_array) > 0) {
|
||||
$vertical_attachments = parseAttachments($vertical_attachments_array, ['audio', 'note']);
|
||||
}
|
||||
}
|
||||
|
||||
$audios = [];
|
||||
|
||||
if(!empty($this->postParam("audios"))) {
|
||||
$un = rtrim($this->postParam("audios"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
if(sizeof($arr) < 11) {
|
||||
foreach($arr as $dat) {
|
||||
$ids = explode("_", $dat);
|
||||
$audio = (new Audios)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
||||
|
||||
if(!$audio || $audio->isDeleted())
|
||||
continue;
|
||||
|
||||
$audios[] = $audio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($this->postParam("text")) && sizeof($photos) < 1 && sizeof($videos) < 1 && sizeof($audios) < 1)
|
||||
if(empty($this->postParam("text")) && sizeof($horizontal_attachments) < 1 && sizeof($vertical_attachments) < 1)
|
||||
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_empty"));
|
||||
|
||||
try {
|
||||
|
@ -143,15 +108,21 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_too_big"));
|
||||
}
|
||||
|
||||
foreach($photos as $photo)
|
||||
$comment->attach($photo);
|
||||
foreach($horizontal_attachments as $horizontal_attachment) {
|
||||
if(!$horizontal_attachment || $horizontal_attachment->isDeleted() || !$horizontal_attachment->canBeViewedBy($this->user->identity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sizeof($videos) > 0)
|
||||
foreach($videos as $vid)
|
||||
$comment->attach($vid);
|
||||
$comment->attach($horizontal_attachment);
|
||||
}
|
||||
|
||||
foreach($audios as $audio)
|
||||
$comment->attach($audio);
|
||||
foreach($vertical_attachments as $vertical_attachment) {
|
||||
if(!$vertical_attachment || $vertical_attachment->isDeleted() || !$vertical_attachment->canBeViewedBy($this->user->identity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$comment->attach($vertical_attachment);
|
||||
}
|
||||
|
||||
if($entity->getOwner()->getId() !== $this->user->identity->getId())
|
||||
if(($owner = $entity->getOwner()) instanceof User)
|
||||
|
|
|
@ -121,9 +121,9 @@ final class InternalAPIPresenter extends OpenVKPresenter
|
|||
{
|
||||
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
|
||||
{
|
||||
$response[] = [
|
||||
"url" => $attachment->getURLBySizeId('normal'),
|
||||
"id" => $attachment->getPrettyId()
|
||||
$response[$attachment->getPrettyId()] = [
|
||||
"url" => $attachment->getURLBySizeId('larger'),
|
||||
"id" => $attachment->getPrettyId(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -133,4 +133,35 @@ final class InternalAPIPresenter extends OpenVKPresenter
|
|||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function renderGetPostTemplate(int $owner_id, int $post_id) {
|
||||
if($_SERVER["REQUEST_METHOD"] !== "POST") {
|
||||
header("HTTP/1.1 405 Method Not Allowed");
|
||||
exit("ты не по адресу");
|
||||
}
|
||||
|
||||
$type = $this->queryParam("type", false);
|
||||
if($type == "post") {
|
||||
$post = (new Posts)->getPostById($owner_id, $post_id, true);
|
||||
} else {
|
||||
$post = (new Comments)->get($post_id);
|
||||
}
|
||||
|
||||
if(!$post || !$post->canBeEditedBy($this->user->identity)) {
|
||||
exit('');
|
||||
}
|
||||
|
||||
header("Content-Type: text/plain");
|
||||
|
||||
if($type == 'post') {
|
||||
$this->template->_template = 'components/post.xml';
|
||||
$this->template->post = $post;
|
||||
$this->template->commentSection = false;
|
||||
} elseif($type == 'comment') {
|
||||
$this->template->_template = 'components/comment.xml';
|
||||
$this->template->comment = $post;
|
||||
} else {
|
||||
exit('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ abstract class OpenVKPresenter extends SimplePresenter
|
|||
|
||||
$userValidated = 1;
|
||||
$cacheTime = 0; # Force no cache
|
||||
if($this->user->identity->onlineStatus() == 0 && !($this->user->identity->isDeleted() || $this->user->identity->isBanned())) {
|
||||
if(!property_exists($this, 'silent') && $this->user->identity->onlineStatus() == 0 && !($this->user->identity->isDeleted() || $this->user->identity->isBanned())) {
|
||||
$this->user->identity->setOnline(time());
|
||||
$this->user->identity->setClient_name(NULL);
|
||||
$this->user->identity->save(false);
|
||||
|
|
|
@ -176,6 +176,7 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
$this->template->cCount = $photo->getCommentsCount();
|
||||
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);
|
||||
$this->template->comments = iterator_to_array($photo->getComments($this->template->cPage));
|
||||
$this->template->owner = $photo->getOwner();
|
||||
}
|
||||
|
||||
function renderAbsolutePhoto($id): void
|
||||
|
@ -287,7 +288,8 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
"id" => $photo->getId(),
|
||||
"vid" => $photo->getVirtualId(),
|
||||
"owner" => $photo->getOwner()->getId(),
|
||||
"link" => $photo->getURL()
|
||||
"link" => $photo->getURL(),
|
||||
"pretty_id" => $photo->getPrettyId(),
|
||||
];
|
||||
} catch(ISE $ex) {
|
||||
$name = $album->getName();
|
||||
|
@ -354,4 +356,26 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
$this->flash("succ", tr("photo_is_deleted"), tr("photo_is_deleted_desc"));
|
||||
$this->redirect($redirect);
|
||||
}
|
||||
|
||||
function renderLike(int $wall, int $post_id): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
$this->willExecuteWriteAction();
|
||||
$this->assertNoCSRF();
|
||||
|
||||
$photo = $this->photos->getByOwnerAndVID($wall, $post_id);
|
||||
if(!$photo || $photo->isDeleted() || !$photo->canBeViewedBy($this->user->identity)) $this->notFound();
|
||||
|
||||
if(!is_null($this->user)) {
|
||||
$photo->toggleLike($this->user->identity);
|
||||
}
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$this->returnJson([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->redirect("$_SERVER[HTTP_REFERER]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use WhichBrowser;
|
|||
|
||||
final class VKAPIPresenter extends OpenVKPresenter
|
||||
{
|
||||
protected $silent = true;
|
||||
private function logRequest(string $object, string $method): void
|
||||
{
|
||||
$date = date(DATE_COOKIE);
|
||||
|
@ -222,9 +223,13 @@ final class VKAPIPresenter extends OpenVKPresenter
|
|||
if(!is_callable([$handler, $method]))
|
||||
$this->badMethod($object, $method);
|
||||
|
||||
$has_rss = false;
|
||||
$route = new \ReflectionMethod($handler, $method);
|
||||
$params = [];
|
||||
foreach($route->getParameters() as $parameter) {
|
||||
if($parameter->getName() == 'rss')
|
||||
$has_rss = true;
|
||||
|
||||
$val = $this->requestParam($parameter->getName());
|
||||
if(is_null($val)) {
|
||||
if($parameter->allowsNull())
|
||||
|
@ -260,6 +265,16 @@ final class VKAPIPresenter extends OpenVKPresenter
|
|||
$this->fail($ex->getCode(), $ex->getMessage(), $object, $method);
|
||||
}
|
||||
|
||||
$result = NULL;
|
||||
|
||||
if($this->queryParam("rss") == '1' && $has_rss) {
|
||||
$feed = new \Bhaktaraz\RSSGenerator\Feed();
|
||||
$res->appendTo($feed);
|
||||
|
||||
$result = strval($feed);
|
||||
|
||||
header("Content-Type: application/rss+xml;charset=UTF-8");
|
||||
} else {
|
||||
$result = json_encode([
|
||||
"response" => $res,
|
||||
]);
|
||||
|
@ -267,8 +282,10 @@ final class VKAPIPresenter extends OpenVKPresenter
|
|||
if($callback) {
|
||||
$result = $callback . '(' . $result . ')';
|
||||
header('Content-Type: application/javascript');
|
||||
} else
|
||||
} else {
|
||||
header("Content-Type: application/json");
|
||||
}
|
||||
}
|
||||
|
||||
$size = strlen($result);
|
||||
header("Content-Length: $size");
|
||||
|
|
|
@ -62,6 +62,7 @@ final class VideosPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("error"), tr("video_uploads_disabled"));
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$is_ajax = (int)($this->postParam('ajax') ?? '0') == 1;
|
||||
if(!empty($this->postParam("name"))) {
|
||||
$video = new Video;
|
||||
$video->setOwner($this->user->id);
|
||||
|
@ -75,18 +76,29 @@ final class VideosPresenter extends OpenVKPresenter
|
|||
else if(!empty($this->postParam("link")))
|
||||
$video->setLink($this->postParam("link"));
|
||||
else
|
||||
$this->flashFail("err", tr("no_video_error"), tr("no_video_description"));
|
||||
$this->flashFail("err", tr("no_video_error"), tr("no_video_description"), 10, $is_ajax);
|
||||
} catch(\DomainException $ex) {
|
||||
$this->flashFail("err", tr("error_video"), tr("file_corrupted"));
|
||||
$this->flashFail("err", tr("error_video"), tr("file_corrupted"), 10, $is_ajax);
|
||||
} catch(ISE $ex) {
|
||||
$this->flashFail("err", tr("error_video"), tr("link_incorrect"));
|
||||
$this->flashFail("err", tr("error_video"), tr("link_incorrect"), 10, $is_ajax);
|
||||
}
|
||||
|
||||
if((int)($this->postParam("unlisted") ?? '0') == 1) {
|
||||
$video->setUnlisted(true);
|
||||
}
|
||||
|
||||
$video->save();
|
||||
|
||||
if($is_ajax) {
|
||||
$object = $video->getApiStructure();
|
||||
$this->returnJson([
|
||||
'payload' => $object->video,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->redirect("/video" . $video->getPrettyId());
|
||||
} else {
|
||||
$this->flashFail("err", tr("error_video"), tr("no_name_error"));
|
||||
$this->flashFail("err", tr("error_video"), tr("no_name_error"), 10, $is_ajax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +164,12 @@ final class VideosPresenter extends OpenVKPresenter
|
|||
$video->toggleLike($this->user->identity);
|
||||
}
|
||||
|
||||
$this->returnJson(["success" => true]);
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$this->returnJson([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->redirect("$_SERVER[HTTP_REFERER]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -282,23 +282,20 @@ final class WallPresenter extends OpenVKPresenter
|
|||
if($this->postParam("force_sign") === "on")
|
||||
$flags |= 0b01000000;
|
||||
|
||||
$photos = [];
|
||||
|
||||
if(!empty($this->postParam("photos"))) {
|
||||
$un = rtrim($this->postParam("photos"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
if(sizeof($arr) < 11) {
|
||||
foreach($arr as $dat) {
|
||||
$ids = explode("_", $dat);
|
||||
$photo = (new Photos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
||||
|
||||
if(!$photo || $photo->isDeleted())
|
||||
continue;
|
||||
|
||||
$photos[] = $photo;
|
||||
$horizontal_attachments = [];
|
||||
$vertical_attachments = [];
|
||||
if(!empty($this->postParam("horizontal_attachments"))) {
|
||||
$horizontal_attachments_array = array_slice(explode(",", $this->postParam("horizontal_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]);
|
||||
if(sizeof($horizontal_attachments_array) > 0) {
|
||||
$horizontal_attachments = parseAttachments($horizontal_attachments_array, ['photo', 'video']);
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($this->postParam("vertical_attachments"))) {
|
||||
$vertical_attachments_array = array_slice(explode(",", $this->postParam("vertical_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]);
|
||||
if(sizeof($vertical_attachments_array) > 0) {
|
||||
$vertical_attachments = parseAttachments($vertical_attachments_array, ['audio', 'note']);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -312,61 +309,10 @@ final class WallPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("failed_to_publish_post"), "Poll format invalid");
|
||||
}
|
||||
|
||||
$note = NULL;
|
||||
|
||||
if(!is_null($this->postParam("note")) && $this->postParam("note") != "none") {
|
||||
$note = (new Notes)->get((int)$this->postParam("note"));
|
||||
|
||||
if(!$note || $note->isDeleted() || $note->getOwner()->getId() != $this->user->id) {
|
||||
$this->flashFail("err", tr("error"), tr("error_attaching_note"));
|
||||
}
|
||||
|
||||
if($note->getOwner()->getPrivacySetting("notes.read") < 1) {
|
||||
$this->flashFail("err", " ");
|
||||
}
|
||||
}
|
||||
|
||||
$videos = [];
|
||||
|
||||
if(!empty($this->postParam("videos"))) {
|
||||
$un = rtrim($this->postParam("videos"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
if(sizeof($arr) < 11) {
|
||||
foreach($arr as $dat) {
|
||||
$ids = explode("_", $dat);
|
||||
$video = (new Videos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
||||
|
||||
if(!$video || $video->isDeleted())
|
||||
continue;
|
||||
|
||||
$videos[] = $video;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$audios = [];
|
||||
|
||||
if(!empty($this->postParam("audios"))) {
|
||||
$un = rtrim($this->postParam("audios"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
if(sizeof($arr) < 11) {
|
||||
foreach($arr as $dat) {
|
||||
$ids = explode("_", $dat);
|
||||
$audio = (new Audios)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
||||
|
||||
if(!$audio || $audio->isDeleted())
|
||||
continue;
|
||||
|
||||
$audios[] = $audio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($this->postParam("text")) && sizeof($photos) < 1 && sizeof($videos) < 1 && sizeof($audios) < 1 && !$poll && !$note)
|
||||
if(empty($this->postParam("text")) && sizeof($horizontal_attachments) < 1 && sizeof($vertical_attachments) < 1 && !$poll)
|
||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big"));
|
||||
|
||||
$should_be_suggested = $wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2;
|
||||
try {
|
||||
$post = new Post;
|
||||
$post->setOwner($this->user->id);
|
||||
|
@ -383,7 +329,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
} catch(\Throwable) {}
|
||||
}
|
||||
|
||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2)
|
||||
if($should_be_suggested)
|
||||
$post->setSuggested(1);
|
||||
|
||||
$post->save();
|
||||
|
@ -391,22 +337,25 @@ final class WallPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_too_big"));
|
||||
}
|
||||
|
||||
foreach($photos as $photo)
|
||||
$post->attach($photo);
|
||||
foreach($horizontal_attachments as $horizontal_attachment) {
|
||||
if(!$horizontal_attachment || $horizontal_attachment->isDeleted() || !$horizontal_attachment->canBeViewedBy($this->user->identity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sizeof($videos) > 0)
|
||||
foreach($videos as $vid)
|
||||
$post->attach($vid);
|
||||
$post->attach($horizontal_attachment);
|
||||
}
|
||||
|
||||
foreach($vertical_attachments as $vertical_attachment) {
|
||||
if(!$vertical_attachment || $vertical_attachment->isDeleted() || !$vertical_attachment->canBeViewedBy($this->user->identity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$post->attach($vertical_attachment);
|
||||
}
|
||||
|
||||
if(!is_null($poll))
|
||||
$post->attach($poll);
|
||||
|
||||
if(!is_null($note))
|
||||
$post->attach($note);
|
||||
|
||||
foreach($audios as $audio)
|
||||
$post->attach($audio);
|
||||
|
||||
if($wall > 0 && $wall !== $this->user->identity->getId())
|
||||
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
||||
|
||||
|
@ -414,9 +363,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
if($wall > 0)
|
||||
$excludeMentions[] = $wall;
|
||||
|
||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) {
|
||||
# Чтобы не было упоминаний из предложки
|
||||
} else {
|
||||
if(!$should_be_suggested) {
|
||||
$mentions = iterator_to_array($post->resolveMentions($excludeMentions));
|
||||
|
||||
foreach($mentions as $mentionee)
|
||||
|
@ -424,18 +371,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
(new MentionNotification($mentionee, $post, $post->getOwner(), strip_tags($post->getText())))->emit();
|
||||
}
|
||||
|
||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) {
|
||||
$suggsCount = $this->posts->getSuggestedPostsCount($wallOwner->getId());
|
||||
|
||||
if($suggsCount % 10 == 0) {
|
||||
$managers = $wallOwner->getManagers();
|
||||
$owner = $wallOwner->getOwner();
|
||||
(new NewSuggestedPostsNotification($owner, $wallOwner))->emit();
|
||||
|
||||
foreach($managers as $manager)
|
||||
(new NewSuggestedPostsNotification($manager->getUser(), $wallOwner))->emit();
|
||||
}
|
||||
|
||||
if($should_be_suggested) {
|
||||
$this->redirect("/club".$wallOwner->getId()."/suggested");
|
||||
} else {
|
||||
$this->redirect($wallOwner->getURL());
|
||||
|
@ -487,6 +423,12 @@ final class WallPresenter extends OpenVKPresenter
|
|||
$post->toggleLike($this->user->identity);
|
||||
}
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$this->returnJson([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->redirect("$_SERVER[HTTP_REFERER]#postGarter=" . $post->getId());
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
{script "js/node_modules/umbrellajs/umbrella.min.js"}
|
||||
{script "js/l10n.js"}
|
||||
{script "js/openvk.cls.js"}
|
||||
{script "js/utils.js"}
|
||||
{script "js/node_modules/dashjs/dist/dash.all.min.js"}
|
||||
<script src="/assets/packages/static/openvk/js/node_modules/cropperjs/dist/cropper.js" type="module"></script>
|
||||
{script "js/al_music.js"}
|
||||
|
@ -26,6 +27,7 @@
|
|||
{css "js/node_modules/tippy.js/dist/border.css"}
|
||||
{css "js/node_modules/tippy.js/dist/svg-arrow.css"}
|
||||
{css "js/node_modules/tippy.js/themes/light.css"}
|
||||
{css "js/node_modules/jquery-ui/themes/base/resizable.css"}
|
||||
{script "js/node_modules/@popperjs/core/dist/umd/popper.min.js"}
|
||||
{script "js/node_modules/tippy.js/dist/tippy-bundle.umd.min.js"}
|
||||
{script "js/node_modules/handlebars/dist/handlebars.min.js"}
|
||||
|
@ -51,7 +53,10 @@
|
|||
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['testLabel']" id="test-label">FOR TESTING PURPOSES ONLY</div>
|
||||
|
||||
<div class="notifications_global_wrap"></div>
|
||||
<div class="dimmer"></div>
|
||||
<div class="dimmer">
|
||||
<div id='absolute_territory'></div>
|
||||
</div>
|
||||
<div class="upLeftErrors"></div>
|
||||
|
||||
<div class="articleView">
|
||||
<a id="articleCloseButton" class="button" href="javascript:void(u('body').removeClass('article'));">{_close}</a>
|
||||
|
@ -361,7 +366,7 @@
|
|||
</div>
|
||||
|
||||
<div id="ajloader" class="loader">
|
||||
<img src="/assets/packages/static/openvk/img/loading_mini.gif" style="width: 40px;">
|
||||
<img src="/assets/packages/static/openvk/img/loading_mini.gif">
|
||||
</div>
|
||||
|
||||
{include "components/cookies.xml"}
|
||||
|
@ -424,6 +429,9 @@
|
|||
window.openvk = {
|
||||
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres},
|
||||
"at_search": {$atSearch ?? false},
|
||||
"max_attachments": {\OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"] ?? 10},
|
||||
"max_filesize_mb": 5,
|
||||
"current_id": {$thisUser ? $thisUser->getId() : 0},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
<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;">
|
||||
<div style="display: flex;">
|
||||
<div id="miniplayer" class="audioEntry">
|
||||
<div class='audioEntryWrapper' style="display: flex;" draggable='true'>
|
||||
<div class="playerButton">
|
||||
<div class="playIcon"></div>
|
||||
</div>
|
||||
|
||||
<div class="status" style="margin-top: 12px;">
|
||||
<div class="status" draggable='false'>
|
||||
<div class="mediaInfo noOverflow">
|
||||
<div class="info">
|
||||
<strong class="performer">
|
||||
<a href="/search?query=§ion=audios&order=listens&only_performers=on&q={$audio->getPerformer()}">{$audio->getPerformer()}</a>
|
||||
<a href="/search?section=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>
|
||||
|
@ -27,8 +27,8 @@
|
|||
</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="volume">
|
||||
<span class="nobold {if !$hideButtons}hideOnHover{/if}" data-unformatted="{$audio->getLength()}">{$audio->getFormattedLength()}</span>
|
||||
<div class="buttons">
|
||||
{php $hasAudio = isset($thisUser) && $audio->isInLibraryOf($thisUser)}
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subTracks">
|
||||
<div class="subTracks" draggable='false'>
|
||||
<div class="lengthTrackWrapper">
|
||||
<div class="track lengthTrack">
|
||||
<div class="selectableTrack" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||
|
|
|
@ -168,10 +168,10 @@
|
|||
{/if}
|
||||
{var $canReport = $thisUser->getId() != $club->getOwner()->getId()}
|
||||
{if $canReport}
|
||||
<a class="profile_link" style="display:block;" href="javascript:reportVideo()">{_report}</a>
|
||||
<a class="profile_link" style="display:block;" href="javascript:reportClub()">{_report}</a>
|
||||
|
||||
<script>
|
||||
function reportVideo() {
|
||||
function reportClub() {
|
||||
uReportMsgTxt = tr("going_to_report_club");
|
||||
uReportMsgTxt += "<br/>"+tr("report_question_text");
|
||||
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
|
||||
|
|
|
@ -4,76 +4,72 @@
|
|||
|
||||
{block header}
|
||||
{ifset $album}
|
||||
<a href="{$album->getOwner()->getURL()}">
|
||||
{$album->getOwner()->getCanonicalName()}
|
||||
{var $album_owner = $album->getOwner()}
|
||||
<a href="{$album_owner->getURL()}">
|
||||
{$album_owner->getCanonicalName()}
|
||||
</a>
|
||||
{if ($album->getOwner() instanceof openvk\Web\Models\Entities\Club)}
|
||||
» <a href="/albums{$album->getOwner()->getId() * -1}">{_albums}</a>
|
||||
{if ($album_owner instanceof openvk\Web\Models\Entities\Club)}
|
||||
» <a href="/albums{$album_owner->getId() * -1}">{_albums}</a>
|
||||
{else}
|
||||
» <a href="/albums{$album->getOwner()->getId()}">{_albums}</a>
|
||||
» <a href="/albums{$album_owner->getId()}">{_albums}</a>
|
||||
{/if}
|
||||
» <a href="/album{$album->getPrettyId()}">{$album->getName()}</a>
|
||||
{else}
|
||||
<a href="{$photo->getOwner()->getURL()}">{$photo->getOwner()->getCanonicalName()}</a>
|
||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||
{/ifset}
|
||||
» {_photo}
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
<center style="margin-bottom: 8pt;">
|
||||
<img src="{$photo->getURLBySizeId('large')}" style="max-width: 80%; max-height: 60vh;" />
|
||||
</center>
|
||||
<div class='media-page-wrapper photo-page-wrapper'>
|
||||
<div class='photo-page-wrapper-photo'>
|
||||
<img src="{$photo->getURLBySizeId('large')}" />
|
||||
</div>
|
||||
|
||||
<div class='ovk-photo-details'>
|
||||
<div class='media-page-wrapper-description'>
|
||||
<p n:if='!empty($photo->getDescription())'>{$photo->getDescription()}</p>
|
||||
<div class='upload_time'>
|
||||
{_info_upload_date}: {$photo->getPublicationTime()}
|
||||
{if isset($thisUser)}
|
||||
|
|
||||
{var $liked = $photo->hasLikeFrom($thisUser)}
|
||||
{var $likesCount = $photo->getLikesCount()}
|
||||
<div class='like_wrap tidy'>
|
||||
<a href="/photo{$photo->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$likesCount}">
|
||||
<div class="heart" id="{if $liked}liked{/if}"></div>
|
||||
<span class="likeCnt">{if $likesCount > 0}{$likesCount}{/if}</span>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div style="width: 100%; min-height: 100px;" class="ovk-photo-details">
|
||||
<div style="float: left; min-height: 100px; width: 68%;margin-left: 3px;">
|
||||
<div class="media-page-wrapper-details">
|
||||
<div class='media-page-wrapper-comments'>
|
||||
{include "../components/comments.xml", comments => $comments, count => $cCount, page => $cPage, model => "photos", parent => $photo, custom_id => 999}
|
||||
</div>
|
||||
<div style="float:right;min-height: 100px;width: 30%;margin-left: 1px;">
|
||||
<div>
|
||||
<h4>{_information}</h4>
|
||||
<span style="color: grey;">{_info_description}:</span>
|
||||
{$photo->getDescription() ?? "(" . tr("none") . ")"}<br/>
|
||||
<span style="color: grey;">{_info_uploaded_by}:</span>
|
||||
<a href="{$photo->getOwner()->getURL()}">{$photo->getOwner()->getFullName()}</a><br/>
|
||||
<span style="color: grey;">{_info_upload_date}:</span>
|
||||
{$photo->getPublicationTime()}
|
||||
<div class='media-page-wrapper-actions'>
|
||||
<a href="{$owner->getURL()}" class='media-page-author-block'>
|
||||
<img class='cCompactAvatars' src="{$owner->getAvatarURL('miniscule')}">
|
||||
|
||||
<div class='media-page-author-block-name'>
|
||||
<b>{$owner->getCanonicalName()}</b>
|
||||
</div>
|
||||
<br/>
|
||||
<h4>{_actions}</h4>
|
||||
{if isset($thisUser) && $thisUser->getId() != $photo->getOwner()->getId()}
|
||||
{var canReport = true}
|
||||
{/if}
|
||||
</a>
|
||||
<div n:if="isset($thisUser) && $thisUser->getId() === $photo->getOwner()->getId()">
|
||||
<a href="/photo{$photo->getPrettyId()}/edit" class="profile_link" style="display:block;width:96%;">{_edit}</a>
|
||||
<a id="_photoDelete" href="/photo{$photo->getPrettyId()}/delete" class="profile_link" style="display:block;width:96%;">{_delete}</a>
|
||||
</div>
|
||||
<a href="{$photo->getURL()}" class="profile_link" target="_blank" style="display:block;width:96%;">{_"open_original"}</a>
|
||||
<a n:if="$canReport ?? false" class="profile_link" style="display:block;width:96%;" href="javascript:reportPhoto()">{_report}</a>
|
||||
<script n:if="$canReport ?? false">
|
||||
function reportPhoto() {
|
||||
uReportMsgTxt = tr("going_to_report_photo");
|
||||
uReportMsgTxt += "<br/>"+tr("report_question_text");
|
||||
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
|
||||
|
||||
MessageBox(tr("report_question"), uReportMsgTxt, [tr("confirm_m"), tr("cancel")], [
|
||||
(function() {
|
||||
res = document.querySelector("#uReportMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/report/" + {$photo->getId()} + "?reason=" + res + "&type=photo", true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("reason") === -1)
|
||||
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
</script>
|
||||
<a n:if="isset($thisUser) && $thisUser->getId() != $photo->getOwner()->getId()" class="profile_link" style="display:block;width:96%;" href="javascript:reportPhoto({$photo->getId()})">{_report}</a>
|
||||
<a n:if="isset($thisUser)" onclick="javascript:repost({$photo->getPrettyId()}, 'photo')" class="profile_link" style="display:block;width:96%;">
|
||||
{_share}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -325,13 +325,13 @@
|
|||
</div>
|
||||
<div style="padding: 5px;">
|
||||
<div class="ovk-video" n:foreach="$videos as $video">
|
||||
<a href="/video{$video->getPrettyId()}" class="preview" align="center" id="videoOpen" data-id="{$video->getId()}">
|
||||
<a href="/video{$video->getPrettyId()}" class="preview" align="center" id="videoOpen" data-id="{$video->getPrettyId()}">
|
||||
<img
|
||||
src="{$video->getThumbnailURL()}"
|
||||
style="max-width: 170px; max-height: 127px; margin: auto;" />
|
||||
</a>
|
||||
<div>
|
||||
<b><a href="/video{$video->getPrettyId()}" id="videoOpen" data-id="{$video->getId()}">{ovk_proc_strtr($video->getName(), 30)}</a></b><br>
|
||||
<b><a href="/video{$video->getPrettyId()}" id="videoOpen" data-id="{$video->getPrettyId()}">{ovk_proc_strtr($video->getName(), 30)}</a></b><br>
|
||||
<span style="font-size: 10px;">{$video->getPublicationTime()} | {_comments} ({$video->getCommentsCount()})</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
{/block}
|
||||
|
||||
{block content}
|
||||
<center style="margin-bottom: 8pt;">
|
||||
<div class='media-page-wrapper video-page-wrapper'>
|
||||
<div class='video-page-wrapper-video'>
|
||||
{if $video->getType() === 0}
|
||||
<div class="bsdn" data-name="{$video->getName()}" data-author="{$user->getCanonicalName()}">
|
||||
<video src="{$video->getURL()}"></video>
|
||||
|
@ -24,12 +25,32 @@
|
|||
{$driver->getEmbed()|noescape}
|
||||
{/if}
|
||||
{/if}
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<div class='ovk-vid-details'>
|
||||
<div class='media-page-wrapper-description'>
|
||||
<p><b>{$video->getName()}</b></p>
|
||||
<p n:if='!empty($video->getDescription())'>{$video->getDescription()}</p>
|
||||
<div class='upload_time'>
|
||||
{_info_upload_date}: {$video->getPublicationTime()}
|
||||
{if isset($thisUser)}
|
||||
|
|
||||
{var $liked = $video->hasLikeFrom($thisUser)}
|
||||
{var $likesCount = $video->getLikesCount()}
|
||||
<div class='like_wrap tidy'>
|
||||
<a href="/video{$video->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$likesCount}">
|
||||
<div class="heart" id="{if $liked}liked{/if}"></div>
|
||||
<span class="likeCnt">{if $likesCount > 0}{$likesCount}{/if}</span>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div style="width: 100%; min-height: 100px;">
|
||||
<div style="float: left; min-height: 100px; width: 68%; margin-right: 2%;" id="comments">
|
||||
<div class="media-page-wrapper-details">
|
||||
<div class='media-page-wrapper-comments' id="comments">
|
||||
{include "../components/comments.xml",
|
||||
comments => $comments,
|
||||
count => $cCount,
|
||||
|
@ -37,31 +58,26 @@
|
|||
model => "videos",
|
||||
parent => $video}
|
||||
</div>
|
||||
<div style="float: left; min-height: 100px; width: 30%; overflow: hidden; overflow-wrap: break-word;">
|
||||
<div>
|
||||
<h4>{_information}</h4>
|
||||
<span style="color: grey;">{_info_name}:</span>
|
||||
{$video->getName()}<br/>
|
||||
<span style="color: grey;">{_info_description}:</span>
|
||||
{$video->getDescription() ?? "(" . tr("none") . ")"}<br/>
|
||||
<span style="color: grey;">{_info_uploaded_by}:</span>
|
||||
<a href="{$user->getURL()}">{$user->getFullName()}</a><br/>
|
||||
<span style="color: grey;">{_info_upload_date}:</span>
|
||||
{$video->getPublicationTime()}
|
||||
<div class='media-page-wrapper-actions'>
|
||||
<a href="{$user->getURL()}" class='media-page-author-block'>
|
||||
<img class='cCompactAvatars' src="{$user->getAvatarURL('miniscule')}">
|
||||
|
||||
<div class='media-page-author-block-name'>
|
||||
<b>{$user->getCanonicalName()}</b>
|
||||
</div>
|
||||
<br/>
|
||||
</a>
|
||||
|
||||
<div>
|
||||
<div n:if="isset($thisUser) && $thisUser->getId() === $user->getId()">
|
||||
<h4>{_actions}</h4>
|
||||
<a href="/video{$video->getPrettyId()}/edit" class="profile_link" style="display:block;width:96%;">
|
||||
{_edit}
|
||||
</a>
|
||||
<a href="/video{$video->getPrettyId()}/remove" class="profile_link" style="display:block;width:96%;">
|
||||
<a id='_videoDelete' href="/video{$video->getPrettyId()}/remove" class="profile_link" style="display:block;width:96%;">
|
||||
{_delete}
|
||||
</a>
|
||||
</div>
|
||||
<a href="/video{$video->getPrettyId()}" class="profile_link" id="videoOpen" data-id="{$video->getId()}" style="display:block;width:96%;">
|
||||
{_watch_in_window}
|
||||
<a n:if="isset($thisUser)" onclick="javascript:repost({$video->getPrettyId()}, 'video')" class="profile_link" style="display:block;width:96%;">
|
||||
{_share}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
@ -71,31 +87,12 @@
|
|||
{/if}
|
||||
{/if}
|
||||
|
||||
<a n:if="$canReport ?? false" class="profile_link" style="display:block;width:96%;" href="javascript:reportVideo()">{_report}</a>
|
||||
|
||||
<script n:if="$canReport ?? false">
|
||||
function reportVideo() {
|
||||
uReportMsgTxt = tr("going_to_report_video");
|
||||
uReportMsgTxt += "<br/>"+tr("report_question_text");
|
||||
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
|
||||
|
||||
MessageBox(tr("report_question"), uReportMsgTxt, [tr("confirm_m"), tr("cancel")], [
|
||||
(function() {
|
||||
res = document.querySelector("#uReportMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/report/" + {$video->getId()} + "?reason=" + res + "&type=video", true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("reason") === -1)
|
||||
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
</script>
|
||||
<a n:if="$canReport ?? false" class="profile_link" style="display:block;width:96%;" href="javascript:reportVideo({$video->getId()})">{_report}</a>
|
||||
<a n:if="$video->getType() == 0" href="{$video->getURL()}" download="" class="profile_link" style="display:block;width:96%;">{_download_video}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{if $attachment instanceof \openvk\Web\Models\Entities\Photo}
|
||||
{if !$attachment->isDeleted()}
|
||||
{var $link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
||||
<a href="{$link}" onclick="OpenMiniature(event, {$attachment->getURLBySizeId('normal')}, {$parent->getPrettyId()}, {$attachment->getPrettyId()}, {$parentType})">
|
||||
<a href="{$link}" onclick="OpenMiniature(event, {$attachment->getURLBySizeId('larger')}, {$parent->getPrettyId()}, {$attachment->getPrettyId()}, {$parentType})">
|
||||
<img class="media media_makima" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" loading=lazy />
|
||||
</a>
|
||||
{else}
|
||||
|
@ -10,6 +10,7 @@
|
|||
</a>
|
||||
{/if}
|
||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
|
||||
{if $tilesCount <= 1}
|
||||
{if $attachment->getType() === 0}
|
||||
<div class="bsdn media" data-name="{$attachment->getName()}" data-author="{$attachment->getOwner()->getCanonicalName()}">
|
||||
<video class="media" src="{$attachment->getURL()}"></video>
|
||||
|
@ -24,25 +25,35 @@
|
|||
{/if}
|
||||
|
||||
<div class="video-wowzer">
|
||||
<img src="/assets/packages/static/openvk/img/videoico.png" />
|
||||
<a href="/video{$attachment->getPrettyId()}" id="videoOpen" data-id="{$attachment->getId()}">{$attachment->getName()}</a>
|
||||
<div class="small-video-ico"></div>
|
||||
<a href="/video{$attachment->getPrettyId()}" id="videoOpen" data-id="{$attachment->getPrettyId()}">{$attachment->getName()}</a>
|
||||
<span class="video-wowzer-length" n:if="$attachment->getLength() != NULL">({$attachment->getFormattedLength()})</span>
|
||||
</div>
|
||||
{else}
|
||||
<a class='compact_video' id='videoOpen' data-id='{$attachment->getPrettyId()}' href="/video{$attachment->getPrettyId()}">
|
||||
<div class='play-button'>
|
||||
<div class='play-button-ico'></div>
|
||||
</div>
|
||||
<div class='video-length' n:if="$attachment->getLength() != NULL">
|
||||
{$attachment->getFormattedLength()}
|
||||
</div>
|
||||
|
||||
<img class="media media_makima" src="{$attachment->getThumbnailURL()}" loading=lazy />
|
||||
</a>
|
||||
{/if}
|
||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll}
|
||||
{presenter "openvk!Poll->view", $attachment->getId()}
|
||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Note}
|
||||
{if !$attachment->isDeleted()}
|
||||
<div data-att_type='note' data-att_id="{$attachment->getPrettyId()}">
|
||||
<div class="attachment_note">
|
||||
<img class="attachment_note_icon" src="/assets/packages/static/openvk/img/note.svg">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 10"><polygon points="0 0 0 10 8 10 8 4 4 4 4 0 0 0"/><polygon points="5 0 5 3 8 3 5 0"/></svg>
|
||||
|
||||
<div class='attachment_note_content'>
|
||||
<span class="attachment_note_text">{_note}</span>
|
||||
<span class="attachment_note_name"><a href="javascript:void(showArticle({$attachment->getId()}));">{ovk_proc_strtr($attachment->getName(), 66)}</a></span>
|
||||
</div>
|
||||
{else}
|
||||
<div class="attachment_note">
|
||||
<img class="attachment_note_icon" src="/assets/packages/static/openvk/img/note.svg">
|
||||
<span class="attachment_note_text">{_note}</span>
|
||||
<span class="attachment_note_name">{_deleted}</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Post}
|
||||
{php $GLOBALS["_nesAttGloCou"] = (isset($GLOBALS["_nesAttGloCou"]) ? $GLOBALS["_nesAttGloCou"] : 0) + 1}
|
||||
{if $GLOBALS["_nesAttGloCou"] > 2}
|
||||
|
@ -51,7 +62,7 @@
|
|||
{include "post.xml", post => $attachment, compact => true}
|
||||
{/if}
|
||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Audio}
|
||||
<div style="width:100%;">
|
||||
<div style="width:100%;" data-att_type='audio' data-att_id="{$attachment->getPrettyId()}">
|
||||
{include "../Audio/player.xml", audio => $attachment}
|
||||
</div>
|
||||
{else}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{var $postId = $target instanceof \openvk\Web\Models\Entities\Post ? $target->getId() : NULL}
|
||||
|
||||
<a name="cid={$comment->getId()}"></a>
|
||||
<table border="0" style="font-size: 11px;" class="post comment" id="_comment{$comment->getId()}" data-comment-id="{$comment->getId()}" data-owner-id="{$author->getId()}" data-from-group="{$author instanceof $Club}" n:attr="data-post-id => $postId">
|
||||
<table data-id="1_{$comment->getId()}" border="0" style="font-size: 11px;" class="post comment" id="_comment{$comment->getId()}" data-comment-id="{$comment->getId()}" data-owner-id="{$author->getId()}" data-from-group="{$author instanceof $Club}" n:attr="data-post-id => $postId">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="30" valign="top">
|
||||
|
@ -22,12 +22,12 @@
|
|||
</div>
|
||||
<div class="post-content" id="{$comment->getId()}">
|
||||
<div class="text" id="text{$comment->getId()}">
|
||||
<span data-text="{$comment->getText(false)}" class="really_text">{$comment->getText()|noescape}</span>
|
||||
<span class="really_text">{$comment->getText()|noescape}</span>
|
||||
|
||||
{var $attachmentsLayout = $comment->getChildrenWithLayout(288)}
|
||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
{include "attachment.xml", attachment => $attachment[2], parent => $comment, parentType => "comment"}
|
||||
{include "attachment.xml", attachment => $attachment[2], parent => $comment, parentType => "comment", tilesCount => sizeof($attachmentsLayout->tiles)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -77,6 +77,7 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='post-edit'></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
{var $commentTextAreaId = $post === NULL ? rand(1,300) : $post->getId()}
|
||||
|
||||
<table border="0" style="font-size: 11px;" n:class="post, !$compact ? post-divider, $post->isExplicit() ? post-nsfw">
|
||||
<table border="0" style="font-size: 11px;" data-id="{$post->getPrettyId()}" n:class="post, !$compact ? post-divider, $post->isExplicit() ? post-nsfw">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="54" valign="top">
|
||||
|
@ -68,13 +68,10 @@
|
|||
{/if}
|
||||
|
||||
{if $post->canBeEditedBy($thisUser) && !($forceNoEditLink ?? false) && $compact == false}
|
||||
<a class="edit" id="editPost"
|
||||
data-id="{$post->getId()}"
|
||||
data-nsfw="{(int)$post->isExplicit()}"
|
||||
{if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}></a>
|
||||
<a class="edit" id="editPost"></a>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="post-content" id="{$post->getPrettyId()}">
|
||||
<div class="post-content" id="{$post->getPrettyId()}" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
<div class="text" id="text{$post->getPrettyId()}">
|
||||
<span data-text="{$post->getText(false)}" class="really_text">{$post->getText()|noescape}</span>
|
||||
|
||||
|
@ -84,8 +81,8 @@
|
|||
{/if}
|
||||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post"}
|
||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};">
|
||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post", tilesCount => sizeof($attachmentsLayout->tiles)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -112,6 +109,7 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='post-edit' n:if='!$compact'></div>
|
||||
<div class="post-menu" n:if="$compact == false">
|
||||
<a href="{if !$suggestion}/wall{$post->getPrettyId()}{else}javascript:void(0){/if}" class="date">{$post->getPublicationTime()}
|
||||
<span n:if="$post->getEditTime()" class="edited editedMark">({_edited_short})</span>
|
||||
|
@ -126,7 +124,7 @@
|
|||
<a n:if="!($forceNoCommentsLink ?? false) && $commentsCount == 0" href="javascript:expand_comment_textarea({$commentTextAreaId})">{_comment}</a>
|
||||
|
||||
<div class="like_wrap">
|
||||
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
|
||||
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" href="javascript:repost('{$post->getPrettyId()}', 'post')">
|
||||
<div class="repost-icon" style="opacity: 0.4;"></div>
|
||||
<span class="likeCnt" id="repostsCount{$post->getPrettyId()}">{if $repostsCount > 0}{$repostsCount}{/if}</span>
|
||||
</a>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
|
||||
|
||||
<table border="0" style="font-size: 11px;" n:class="post, $post->isExplicit() ? post-nsfw">
|
||||
<table border="0" style="font-size: 11px;" data-id="{$post->getPrettyId()}" n:class="post, $post->isExplicit() ? post-nsfw">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="54" valign="top">
|
||||
|
@ -67,7 +67,7 @@
|
|||
</a>
|
||||
</a>
|
||||
</div>
|
||||
<div class="post-content" id="{$post->getPrettyId()}">
|
||||
<div class="post-content" id="{$post->getPrettyId()}" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
<div class="text" id="text{$post->getPrettyId()}">
|
||||
{var $owner = $author->getId()}
|
||||
|
||||
|
@ -79,8 +79,8 @@
|
|||
{/if}
|
||||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post"}
|
||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};">
|
||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post", tilesCount => sizeof($attachmentsLayout->tiles)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -111,6 +111,7 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='post-edit' n:if='!$compact'></div>
|
||||
<div n:if="!($compact ?? false)" class="post-menu">
|
||||
{if is_null($thisUser)}
|
||||
{var $forceNoDeleteLink = true}
|
||||
|
@ -119,9 +120,7 @@
|
|||
|
||||
{if !($forceNoEditLink ?? false) && $post->canBeEditedBy($thisUser)}
|
||||
<a id="editPost"
|
||||
data-id="{$post->getId()}"
|
||||
data-nsfw="{(int)$post->isExplicit()}"
|
||||
{if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}>{_edit}</a> |
|
||||
data-id="{$post->getPrettyId()}">{_edit}</a> |
|
||||
{/if}
|
||||
|
||||
{if !($forceNoDeleteLink ?? false) && $canBeDeleted}
|
||||
|
@ -148,7 +147,7 @@
|
|||
|
|
||||
{/if}
|
||||
|
||||
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}>
|
||||
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repost('{$post->getPrettyId()}', 'post')"{/ifset}>
|
||||
{_share}
|
||||
{if $repostsCount > 0}
|
||||
(<b id="repostsCount{$post->getPrettyId()}">{$repostsCount}</b>)
|
||||
|
|
|
@ -2,26 +2,18 @@
|
|||
{var $textAreaId = ($post ?? NULL) === NULL ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
||||
{var $textAreaId = ($custom_id ?? NULL) === NULL ? $textAreaId : $custom_id}
|
||||
|
||||
<div id="write" style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
|
||||
<div id="write" class='model_content_textarea' style="padding: 5px 0;">
|
||||
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
|
||||
<textarea id="wall-post-input{$textAreaId}" placeholder="{_write}" name="text" style="width: 100%;resize: none;" class="small-textarea"></textarea>
|
||||
<div>
|
||||
<!-- padding to fix <br/> bug -->
|
||||
</div>
|
||||
<div id="post-buttons{$textAreaId}" style="display: none;">
|
||||
<div class="upload">
|
||||
|
||||
</div>
|
||||
<div class="post-upload">
|
||||
<span style="color: inherit;"></span>
|
||||
</div>
|
||||
<div id="post-buttons{$textAreaId}" class='post-buttons' style="display: none;">
|
||||
<div class="post-horizontal"></div>
|
||||
<div class="post-vertical"></div>
|
||||
<div class="post-has-poll">
|
||||
{_poll}
|
||||
</div>
|
||||
<div class="post-has-note"></div>
|
||||
|
||||
<div class="post-has-videos"></div>
|
||||
<div class="post-has-audios"></div>
|
||||
<div class="post-source"></div>
|
||||
|
||||
<div n:if="$postOpts ?? true" class="post-opts">
|
||||
|
@ -62,42 +54,44 @@
|
|||
<input type="checkbox" name="as_group" /> {_comment_as_group}
|
||||
</label>
|
||||
</div>
|
||||
<input type="hidden" name="photos" value="" />
|
||||
<input type="hidden" name="videos" value="" />
|
||||
<input type="hidden" name="audios" value="" />
|
||||
<input type="hidden" name="horizontal_attachments" value="" />
|
||||
<input type="hidden" name="vertical_attachments" value="" />
|
||||
<input type="hidden" name="poll" value="none" />
|
||||
<input type="hidden" id="note" name="note" value="none" />
|
||||
<input type="hidden" id="source" name="source" value="none" />
|
||||
<input type="hidden" name="type" value="1" />
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<br/>
|
||||
<input type="submit" value="{_write}" class="button" />
|
||||
<div style="float: right; display: flex; flex-direction: column;">
|
||||
<a href="javascript:toggleMenu({$textAreaId});">
|
||||
<a class='menu_toggler'>
|
||||
{_attach}
|
||||
</a>
|
||||
|
||||
<div id="wallAttachmentMenu" class="hidden">
|
||||
<a class="header" href="javascript:toggleMenu({$textAreaId});">
|
||||
<a class="header menu_toggler">
|
||||
{_attach}
|
||||
</a>
|
||||
<a id="photosAttachments" {if !is_null($club ?? NULL) && $club->canBeModifiedBy($thisUser)}data-club="{$club->getId()}"{/if}>
|
||||
<a id="__photoAttachment" {if !is_null($club ?? NULL) && $club->canBeModifiedBy($thisUser)}data-club="{$club->getId()}"{/if}>
|
||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-x-egon.png" />
|
||||
{_photo}
|
||||
</a>
|
||||
<a id="videoAttachment">
|
||||
<a id="__videoAttachment">
|
||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-vnd.rn-realmedia.png" />
|
||||
{_video}
|
||||
</a>
|
||||
<a id="_audioAttachment">
|
||||
<a id="__audioAttachment">
|
||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/audio-ac3.png" />
|
||||
{_audio}
|
||||
</a>
|
||||
<a n:if="$graffiti ?? false" href="javascript:initGraffiti({$textAreaId});">
|
||||
<a n:if="$notes ?? false" id="__notesAttachment">
|
||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-x-srt.png" />
|
||||
{_note}
|
||||
</a>
|
||||
<a n:if="$graffiti ?? false" onclick="initGraffiti(event);">
|
||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" />
|
||||
{_graffiti}
|
||||
</a>
|
||||
<a n:if="$polls ?? false" href="javascript:initPoll({$textAreaId})">
|
||||
<a n:if="$polls ?? false" onclick="initPoll(event);">
|
||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/office-chart-bar-stacked.png" />
|
||||
{_poll}
|
||||
</a>
|
||||
|
@ -112,13 +106,8 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(() => {
|
||||
setupWallPostInputHandlers({$textAreaId});
|
||||
});
|
||||
|
||||
u("#post-buttons{$textAreaId} input[name='videos']")["nodes"].at(0).value = ""
|
||||
u("#post-buttons{$textAreaId} input[name='photos']")["nodes"].at(0).value = ""
|
||||
u("#post-buttons{$textAreaId} input[name='audios']")["nodes"].at(0).value = ""
|
||||
u("#post-buttons{$textAreaId} input[name='horizontal_attachments']")["nodes"].at(0).value = ""
|
||||
u("#post-buttons{$textAreaId} input[name='vertical_attachments']")["nodes"].at(0).value = ""
|
||||
</script>
|
||||
|
||||
{if $graffiti}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="/video{$video->getPrettyId()}" data-id="{$video->getId()}">
|
||||
<a href="/video{$video->getPrettyId()}" id='videoOpen' data-id="{$video->getPrettyId()}">
|
||||
<div class="video-preview">
|
||||
<img src="{$video->getThumbnailURL()}"
|
||||
style="max-width: 170px; max-height: 127px; margin: auto;" >
|
||||
|
@ -15,10 +15,13 @@
|
|||
{include infotable, x => $dat}
|
||||
{else}
|
||||
<a href="/video{$video->getPrettyId()}">
|
||||
<b class='video_name' {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">
|
||||
<b class='video_name' id='videoOpen' data-id="{$video->getPrettyId()}">
|
||||
{$video->getName()}
|
||||
</b>
|
||||
</a>
|
||||
{if $video->getLength()}
|
||||
({$video->getFormattedLength()})
|
||||
{/if}
|
||||
<br/>
|
||||
<p>
|
||||
<span class='video_description'>{$video->getDescription() ?? ""}</span>
|
||||
|
@ -26,7 +29,7 @@
|
|||
<span style="color: grey;">{_video_uploaded} {$video->getPublicationTime()}</span><br/>
|
||||
|
||||
<p>
|
||||
<a href="/video{$video->getPrettyId()}" {$videoModal ? "id='videoOpen'" : ''} data-id="{$video->getId()}">{_view_video}</a>
|
||||
<a href="/video{$video->getPrettyId()}" id='videoOpen' data-id="{$video->getPrettyId()}">{_view_video}</a>
|
||||
{if $video->getCommentsCount() > 0}| <a href="/video{$video->getPrettyId()}#comments">{_comments} ({$video->getCommentsCount()})</a>{/if}
|
||||
</p>
|
||||
{/ifset}
|
||||
|
|
|
@ -18,7 +18,7 @@ class Makima
|
|||
$this->photos = $photos;
|
||||
}
|
||||
|
||||
private function getOrientation(Photo $photo, &$ratio): int
|
||||
private function getOrientation($photo, &$ratio): int
|
||||
{
|
||||
[$width, $height] = $photo->getDimensions();
|
||||
$ratio = $width / $height;
|
||||
|
|
|
@ -129,8 +129,6 @@ routes:
|
|||
handler: "Wall->rss"
|
||||
- url: "/wall{num}/makePost"
|
||||
handler: "Wall->makePost"
|
||||
- url: "/wall/edit"
|
||||
handler: "Wall->edit"
|
||||
- url: "/wall{num}_{num}"
|
||||
handler: "Wall->post"
|
||||
- url: "/wall{num}_{num}/like"
|
||||
|
@ -171,6 +169,8 @@ routes:
|
|||
handler: "Photos->uploadPhoto"
|
||||
- url: "/photo{num}_{num}"
|
||||
handler: "Photos->photo"
|
||||
- url: "/photo{num}_{num}/like"
|
||||
handler: "Photos->like"
|
||||
- url: "/photos/thumbnails/{num}_{text}.jpeg"
|
||||
handler: "Photos->thumbnail"
|
||||
- url: "/photos/{text}"
|
||||
|
@ -403,6 +403,8 @@ routes:
|
|||
handler: "About->dev"
|
||||
- url: "/iapi/getPhotosFromPost/{num}_{num}"
|
||||
handler: "InternalAPI->getPhotosFromPost"
|
||||
- url: "/iapi/getPostTemplate/{num}_{num}"
|
||||
handler: "InternalAPI->getPostTemplate"
|
||||
- url: "/tour"
|
||||
handler: "About->tour"
|
||||
- url: "/{?shortCode}"
|
||||
|
|
|
@ -267,6 +267,17 @@
|
|||
color: white;
|
||||
}
|
||||
|
||||
.audioEntry .volume {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 14%;
|
||||
}
|
||||
|
||||
.audioEntry .nobold {
|
||||
text-align: center;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.audioEntry.nowPlaying .volume .nobold {
|
||||
color: white !important;
|
||||
}
|
||||
|
@ -303,6 +314,7 @@
|
|||
height: 100%;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 39px;
|
||||
}
|
||||
|
||||
.audioEntry .playerButton {
|
||||
|
@ -341,6 +353,7 @@
|
|||
grid-template-columns: 1fr;
|
||||
width: 85%;
|
||||
height: 23px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.audioEntry .status .mediaInfo {
|
||||
|
@ -588,7 +601,6 @@
|
|||
}
|
||||
|
||||
.attachAudio {
|
||||
float: left;
|
||||
width: 28%;
|
||||
height: 26px;
|
||||
padding-top: 11px;
|
||||
|
@ -771,6 +783,7 @@
|
|||
|
||||
.addToPlaylist {
|
||||
width: 22%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#_addAudioAdditional {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
gap: 6px;
|
||||
z-index: 2;
|
||||
opacity: 0;
|
||||
height: 43px;
|
||||
}
|
||||
|
||||
.bsdn-player.bsdn-dirty > .bsdn_controls {
|
||||
|
|
|
@ -7,6 +7,11 @@ body.dimmed > .dimmer {
|
|||
opacity: .5;
|
||||
}
|
||||
|
||||
body.dimmed > .dimmer #absolute_territory {
|
||||
margin: 100px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ovk-diag-cont {
|
||||
z-index: 1024;
|
||||
position: fixed;
|
||||
|
@ -59,243 +64,147 @@ body.dimmed > .dimmer {
|
|||
margin-left: 10px;
|
||||
}
|
||||
|
||||
/* Modal player */
|
||||
|
||||
/* fullscreen player */
|
||||
|
||||
.ovk-fullscreen-player {
|
||||
top: 9%;
|
||||
left: 50%;
|
||||
margin-right: -50%;
|
||||
transform: translate(-50%, 0%);
|
||||
z-index: 6667;
|
||||
position: absolute;
|
||||
.ovk-modal-player-window {
|
||||
box-shadow: 0px 0px 9px 2px rgba(0, 0, 0, 0.2);
|
||||
width: 823px;
|
||||
min-height: 400px;
|
||||
box-shadow: 0px 0px 9px 2px rgba(0, 0, 0, 0.2);
|
||||
margin: 9vh auto 0 auto;
|
||||
}
|
||||
|
||||
.top-part span {
|
||||
.ovk-modal-player-window #ovk-player-part {
|
||||
height: 70vh;
|
||||
background: black;
|
||||
padding: 15px 20px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.ovk-modal-player-window #ovk-player-part .top-part {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ovk-modal-player-window #ovk-player-part .top-part b {
|
||||
color: #515151;
|
||||
font-size: 13px;
|
||||
transition: color 200ms ease-in-out;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.top-part .clickable:hover {
|
||||
color: #ffffff;
|
||||
.ovk-modal-player-window #ovk-player-part .top-part .top-part-buttons, .ovk-modal-player-window #ovk-player-part .bottom-part {
|
||||
color: #515151;
|
||||
}
|
||||
|
||||
.ovk-fullscreen-player .bsdn_teaserTitleBox span {
|
||||
color: unset;
|
||||
font-size: unset;
|
||||
.ovk-modal-player-window #ovk-player-part .top-part .top-part-buttons a, .ovk-modal-player-window #ovk-player-part .bottom-part a {
|
||||
color: #515151;
|
||||
}
|
||||
|
||||
.ovk-fullscreen-player .bsdn-player {
|
||||
max-width: 80%;
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
.inner-player {
|
||||
background: #000000;
|
||||
min-height: 438px;
|
||||
max-height: 439px;
|
||||
position: relative;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
.top-part-name {
|
||||
font-size: 15px;
|
||||
font-weight: bolder;
|
||||
margin-left: 20px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.top-part-buttons {
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.top-part-buttons span {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.fplayer {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.top-part-bottom-buttons {
|
||||
position: absolute;
|
||||
margin-left: 20px;
|
||||
bottom: 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.top-part-bottom-buttons span {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.top-part .clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bottom-part {
|
||||
.ovk-modal-player-window #ovk-player-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ovk-modal-player-window #ovk-player-info.shown {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ovk-modal-player-window #ovk-player-info {
|
||||
background: white;
|
||||
padding-bottom: 20px;
|
||||
padding-top: 30px;
|
||||
min-height: 200px;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
|
||||
.left_block {
|
||||
padding-left: 20px;
|
||||
/*padding-top: 20px;*/
|
||||
width: 75%;
|
||||
float: left;
|
||||
background: white;
|
||||
padding-right: 6px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
.ovk-modal-player-window .media-page-wrapper-comments {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.right_block {
|
||||
padding-left: 10px;
|
||||
/*padding-top: 20px;*/
|
||||
width: 20%;
|
||||
border-left: 1px solid gray;
|
||||
float: right;
|
||||
.ovk-modal-player-window .center-part {
|
||||
text-align: center;
|
||||
height: 90%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.bottom-part span {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.bottom-part .gray {
|
||||
.ovk-modal-player-window .center-part .gray {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.ovk-fullscreen-dimmer {
|
||||
/* спижжено у пулла с несколькими картинками там где просмотрщик фоток */
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
overflow: auto;
|
||||
padding-bottom: 20px;
|
||||
z-index: 300;
|
||||
}
|
||||
|
||||
.v_author {
|
||||
margin-top: 20px;
|
||||
.ovk-modal-player-window .center-part .bsdn, .ovk-modal-player-window .center-part .bsdn-player {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.miniplayer {
|
||||
position: absolute;
|
||||
top:0;
|
||||
background: rgba(54, 54, 54, 0.9);
|
||||
background: rgba(54, 54, 54, 0.95);
|
||||
border-radius: 3px;
|
||||
min-width: 299px;
|
||||
min-height: 192px;
|
||||
padding-top: 3px;
|
||||
z-index: 9999;
|
||||
z-index: 7777;
|
||||
padding: 2px 7px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.miniplayer .bsdn-player {
|
||||
max-height: 150px;
|
||||
.miniplayer .miniplayer-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.miniplayer .fplayer {
|
||||
max-width: 286px;
|
||||
margin-left: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.miniplayer-actions {
|
||||
float: right;
|
||||
margin-right: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.miniplayer-name {
|
||||
color: #8a8a8a;
|
||||
font-size: 14px;
|
||||
margin-left: 7px;
|
||||
margin-top: -6px;
|
||||
font-weight: bolder;
|
||||
.miniplayer .miniplayer-head b {
|
||||
color: white;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ui-draggable {
|
||||
position:fixed !important;
|
||||
.miniplayer .miniplayer-head .miniplayer-head-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.miniplayer-actions img {
|
||||
max-width: 11px;
|
||||
.miniplayer .miniplayer-head .miniplayer-head-buttons div {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(/assets/packages/static/openvk/img/wall.png) no-repeat 1px 0;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
transition: opacity 200ms ease-in-out;
|
||||
opacity: 70%;
|
||||
}
|
||||
|
||||
.miniplayer .fplayer iframe {
|
||||
max-width: 260px;
|
||||
max-height: 160px;
|
||||
.miniplayer .miniplayer-head .miniplayer-head-buttons div:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.miniplayer-actions img:hover {
|
||||
opacity: 100%;
|
||||
.miniplayer .miniplayer-head .miniplayer-head-buttons #__miniplayer_return {
|
||||
background-position: -28px 0px;
|
||||
}
|
||||
|
||||
#vidComments {
|
||||
margin-top: 10px;
|
||||
.miniplayer .miniplayer-head .miniplayer-head-buttons #__miniplayer_close {
|
||||
background-position: -12px 0px;
|
||||
}
|
||||
|
||||
.showMoreComments {
|
||||
background: #eaeaea;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
user-select: none;
|
||||
margin-top: 10px;
|
||||
.miniplayer .miniplayer-head-buttons {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.loader {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: -10%;
|
||||
background: rgba(26, 26, 26, 0.9);;
|
||||
padding-top: 12px;
|
||||
width: 91px;
|
||||
height: 25px;
|
||||
text-align: center;
|
||||
border-radius: 1px;
|
||||
margin: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 5555;
|
||||
.miniplayer .miniplayer-body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.right-arrow, .left-arrow {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
transition: all 200ms ease-in-out;
|
||||
margin-left: -50px;
|
||||
background: none;
|
||||
height: 449px;
|
||||
width: 57px;
|
||||
user-select: none;
|
||||
.miniplayer .miniplayer-body .bsdn {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.right-arrow img, .left-arrow img {
|
||||
user-select: none;
|
||||
opacity: 5%;
|
||||
transition: all 200ms ease-in-out;
|
||||
.miniplayer .miniplayer-body .bsdn .bsdn-player {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.right-arrow:hover, .left-arrow:hover {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.right-arrow img:hover, .left-arrow img:hover {
|
||||
opacity: 50%;
|
||||
.miniplayer .miniplayer-body iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ body {
|
|||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
body, .ovk-fullscreen-dimmer, .ovk-photo-view-dimmer {
|
||||
scrollbar-gutter: stable both-edges;
|
||||
}
|
||||
|
||||
.nobold,
|
||||
nobold {
|
||||
font-weight: normal;
|
||||
|
@ -41,6 +45,16 @@ h1 {
|
|||
margin-top: 0;
|
||||
}
|
||||
|
||||
.display_flex_column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.display_flex_row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.layout {
|
||||
width: 791px;
|
||||
margin: 0 auto;
|
||||
|
@ -254,6 +268,28 @@ h1 {
|
|||
width: calc(550px - 16px - 38px - 171px);
|
||||
}
|
||||
|
||||
.upLeftErrors {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 1025;
|
||||
}
|
||||
|
||||
.upLeftErrors .upLeftError {
|
||||
padding: 2px 2px 2px 2px;
|
||||
display: inline-block;
|
||||
border-radius: 0px 0px 5px 0px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.upLeftErrors .upLeftError.upLeftErrorRed {
|
||||
background: #ff7474;
|
||||
}
|
||||
|
||||
.upLeftErrors .upLeftError.upLeftErrorGreen {
|
||||
background: #74ff92;
|
||||
}
|
||||
|
||||
.page_body {
|
||||
width: 632px;
|
||||
float: right;
|
||||
|
@ -772,6 +808,14 @@ h4 {
|
|||
font-size: 9px;
|
||||
}
|
||||
|
||||
.editing .post-content, .post-edit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.editing .post-edit {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.post-content .text {
|
||||
padding: 4px;
|
||||
font-size: 11px;
|
||||
|
@ -1464,7 +1508,7 @@ body.scrolled .toTop:hover {
|
|||
color: #3c3c3c;
|
||||
}
|
||||
|
||||
.post-source #remove_source_button {
|
||||
.post-source #remove_source_button, #small_remove_button {
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
background: url('/assets/packages/static/openvk/img/arrows.png?v=2');
|
||||
|
@ -1478,7 +1522,7 @@ body.scrolled .toTop:hover {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.post-source #remove_source_button:hover {
|
||||
.post-source #remove_source_button:hover, #small_remove_button:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
|
@ -1548,6 +1592,15 @@ body.scrolled .toTop:hover {
|
|||
float: right;
|
||||
}
|
||||
|
||||
.like_wrap.tidy {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.like_wrap.tidy .post-like-button {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.heart {
|
||||
background: url('/assets/packages/static/openvk/img/like.gif') no-repeat 1px 0;
|
||||
height: 10px;
|
||||
|
@ -1557,12 +1610,22 @@ body.scrolled .toTop:hover {
|
|||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.like_wrap.tidy .heart {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.likeCnt {
|
||||
font-size: 10px;
|
||||
margin-right: 3px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.like_wrap.tidy .likeCnt {
|
||||
float: none;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.heart:hover {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
@ -1726,12 +1789,14 @@ body.scrolled .toTop:hover {
|
|||
|
||||
#wallAttachmentMenu {
|
||||
position: absolute;
|
||||
min-width: 94px;
|
||||
border: 1px solid darkgrey;
|
||||
background-color: white;
|
||||
z-index: 32;
|
||||
margin-top: -7px;
|
||||
margin-left: -16px;
|
||||
box-shadow: 0 1px 3px -1px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#wallAttachmentMenu>a {
|
||||
|
@ -2389,26 +2454,66 @@ a.poll-retract-vote {
|
|||
}
|
||||
}
|
||||
|
||||
.upload {
|
||||
margin-top: 8px;
|
||||
.post-horizontal, .post-vertical {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.upload .upload-item {
|
||||
width: 75px;
|
||||
height: 60px;
|
||||
.post-horizontal {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.post-vertical {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.post-horizontal .upload-item {
|
||||
/*width: 75px;
|
||||
height: 60px;*/
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
margin-right: 3px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
min-height: 63px;
|
||||
}
|
||||
|
||||
.upload-item .upload-delete {
|
||||
.post-horizontal .upload-item .play-button, .compact_video .play-button {
|
||||
position: absolute;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.post-horizontal .upload-item .play-button .play-button-ico, .compact_video .play-button .play-button-ico {
|
||||
background: url(/assets/packages/static/openvk/img/wall.png) no-repeat 1px 0;
|
||||
display: inline-block;
|
||||
height: 15px;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.upload-item.dragged {
|
||||
filter: contrast(0.5);
|
||||
}
|
||||
|
||||
.post-horizontal .upload-item .upload-delete {
|
||||
position: absolute;
|
||||
background: rgba(0,0,0,0.5);
|
||||
padding: 2px 5px;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
margin-left: 57px; /* мне лень переделывать :DDDD */
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
opacity: 0;
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
@ -2417,13 +2522,68 @@ a.poll-retract-vote {
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.upload-item img {
|
||||
.post-horizontal .upload-item img {
|
||||
width: 100%;
|
||||
max-height: 60px;
|
||||
object-fit: cover;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 0fr;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment:first-of-type {
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry {
|
||||
max-height: 28px;
|
||||
min-height: 18px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry:hover {
|
||||
background: unset !important;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry .playerButton {
|
||||
padding: 0px 3px 0px 0px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry .buttons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry .status {
|
||||
margin-top: 1px;
|
||||
margin-left: 2px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry .nobold {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry .subTracks {
|
||||
padding-bottom: 2px;
|
||||
padding-left: 3px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .audioEntry .audioEntryWrapper {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .vertical-attachment-content {
|
||||
max-height: 27px;
|
||||
}
|
||||
|
||||
.post-vertical .vertical-attachment .vertical-attachment-content .overflowedName {
|
||||
position: initial;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* https://imgur.com/a/ihB3JZ4 */
|
||||
|
||||
.ovk-photo-view-dimmer {
|
||||
|
@ -2441,21 +2601,33 @@ a.poll-retract-vote {
|
|||
position: relative;
|
||||
z-index: 999;
|
||||
background: #fff;
|
||||
width: 610px;
|
||||
padding: 20px;
|
||||
min-width: 600px;
|
||||
width: fit-content;
|
||||
padding: 25px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 10px;
|
||||
box-shadow: 0px 0px 3px 1px #222;
|
||||
margin: 15px auto 0 auto;
|
||||
margin: 10px auto 0 auto;
|
||||
}
|
||||
|
||||
.ovk-photo-details {
|
||||
overflow: auto;
|
||||
.ovk-photo-view .photo_viewer_wrapper {
|
||||
position: relative;
|
||||
height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ovk-photo-view #ovk-photo-img {
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.photo_com_title {
|
||||
font-weight: bold;
|
||||
padding-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.photo_com_title div {
|
||||
|
@ -2467,7 +2639,6 @@ a.poll-retract-vote {
|
|||
left: 0;
|
||||
width: 35%;
|
||||
height: 100%;
|
||||
max-height: 60vh;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -2476,11 +2647,27 @@ a.poll-retract-vote {
|
|||
right: 0;
|
||||
width: 35%;
|
||||
height: 100%;
|
||||
max-height: 60vh;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ovk-photo-view .media-page-wrapper-details {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.ovk-photo-view .media-page-wrapper-comments {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
min-height: 300px;
|
||||
width: 100%;
|
||||
padding: 0px 2px;
|
||||
}
|
||||
|
||||
.ovk-photo-view .ovk-photo-details {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.client_app > img {
|
||||
top: 3px;
|
||||
position: relative;
|
||||
|
@ -2538,12 +2725,13 @@ a.poll-retract-vote {
|
|||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.video-wowzer a::before {
|
||||
content: "b";
|
||||
color: transparent;
|
||||
width: 12px;
|
||||
background-image: url(/assets/packages/static/openvk/img/videoico.png);
|
||||
display: none;
|
||||
.video-wowzer .small-video-ico {
|
||||
vertical-align: bottom;
|
||||
display: inline-block;
|
||||
width: 11px;
|
||||
height: 14px;
|
||||
background: url(/assets/packages/static/openvk/img/wall.png?v=2);
|
||||
background-position: -87px 0px;
|
||||
}
|
||||
|
||||
/* Da search */
|
||||
|
@ -2889,17 +3077,33 @@ a.poll-retract-vote {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.attachment_note_icon {
|
||||
.attachment_note .attachment_note_icon {
|
||||
max-width: 9px;
|
||||
}
|
||||
|
||||
.attachment_note_text {
|
||||
.attachment_note .attachment_note_text {
|
||||
color: #605F63;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.attachment_note {
|
||||
user-select: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.attachment_note svg {
|
||||
width: 8px;
|
||||
height: 10px;
|
||||
fill: #605f63;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.attachment_note .attachment_note_content {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
#notesList
|
||||
|
@ -3124,10 +3328,81 @@ body.article .floating_sidebar, body.article .page_content {
|
|||
font-size: 11px;
|
||||
}
|
||||
|
||||
.topGrayBlock {
|
||||
.attachment_selector .topGrayBlock {
|
||||
background: #F0F0F0;
|
||||
height: 37px;
|
||||
border-bottom: 1px solid #C7C7C7;
|
||||
padding: 3px 10px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.attachment_selector .topGrayBlock #video_query {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.attachment_selector .topGrayBlock #albumSelect {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert {
|
||||
padding: 5px;
|
||||
height: 281px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert #attachment_insert_count {
|
||||
position: fixed;
|
||||
z-index: 1007;
|
||||
width: 92%;
|
||||
background: white;
|
||||
margin-top: -5px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
#show_more {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background: #f0f0f0;
|
||||
height: 22px;
|
||||
padding-top: 9px;
|
||||
cursor: pointer;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
#show_more:hover {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert .photosList {
|
||||
margin-top: 20px;
|
||||
gap: 3px 6px;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert .photosList .album-photo.selected img {
|
||||
background-color: #646464;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert .photosList .album-photo {
|
||||
width: 15.8%;
|
||||
margin: unset;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert .videosInsert .video_list .video-preview {
|
||||
height: 75px;
|
||||
width: 133px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert .videosInsert .video_list .video-preview img {
|
||||
max-width: 133px;
|
||||
height: 75px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.attachment_selector #attachment_insert .videosInsert .video_list .action_links {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.edited {
|
||||
|
@ -3145,16 +3420,20 @@ body.article .floating_sidebar, body.article .page_content {
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.editMenu.loading {
|
||||
.edit_menu.loading {
|
||||
filter: opacity(0.5);
|
||||
cursor: progress;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.editMenu.loading * {
|
||||
.edit_menu.loading * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.edit_menu .edit_menu_buttons {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.lagged *, .lagged {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@ -3316,6 +3595,129 @@ hr {
|
|||
height: 7px;
|
||||
}
|
||||
|
||||
.compact_video {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
position: relative;
|
||||
margin-left: -2px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.compact_video .video-length {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
width: 34px;
|
||||
height: 14px;
|
||||
bottom: 5px;
|
||||
right: 5px;
|
||||
background: rgba(0,0,0,0.5);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.media-page-wrapper .photo-page-wrapper-photo {
|
||||
margin-bottom: 8pt;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.media-page-wrapper .video-page-wrapper-video iframe {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.media-page-wrapper .photo-page-wrapper-photo img {
|
||||
max-width: 85%;
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
.media-page-wrapper-details {
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.media-page-wrapper-comments {
|
||||
min-height: 100px;
|
||||
width: 68%;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.media-page-wrapper-actions {
|
||||
min-height: 100px;
|
||||
width: 30%;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.media-page-wrapper-description p {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.media-page-wrapper-description .upload_time {
|
||||
color: gray;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.media-page-author-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.media-page-author-block img {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.media-page-author-block .media-page-author-block-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.media-page-author-block .media-page-author-block-name b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.media-page-author-block .media-page-author-block-name span {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
#ajloader {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: -10%;
|
||||
background: rgba(26, 26, 26, 0.9);;
|
||||
padding-top: 12px;
|
||||
width: 91px;
|
||||
height: 25px;
|
||||
text-align: center;
|
||||
border-radius: 1px;
|
||||
margin: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 5555;
|
||||
}
|
||||
|
||||
#ajloader.shown {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hoverable_color {
|
||||
transition: all 0.17s ease-in-out;
|
||||
}
|
||||
|
||||
.hoverable_color:hover {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
#__feed_settings_link {
|
||||
float: right;
|
||||
margin-right: 3px;
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
.post-nsfw .post-content .media {
|
||||
filter: saturate(0.8) blur(15px);
|
||||
}
|
||||
|
||||
.post-nsfw .post-content .attachment {
|
||||
overflow: hidden;
|
||||
.post-nsfw .post-content {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.post-nsfw .post-content .attachment:active .media {
|
||||
filter: none;
|
||||
.post-nsfw .post-content .text {
|
||||
filter: saturate(0.8) blur(28px);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.post-nsfw .post-content .attachment::after {
|
||||
.post-nsfw .post-content::after {
|
||||
position: absolute;
|
||||
top: calc(50% - 16px);
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: 8px 0;
|
||||
background-color: hsla(0, 0%, 0%, .5);
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
background-color: hsla(0, 0%, 0%, .7);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
content: attr(data-localized-nsfw-text);
|
||||
}
|
||||
|
||||
.post-nsfw .post-content .attachment:active::after {
|
||||
display: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 560 B |
Before Width: | Height: | Size: 932 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 932 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 153 B |
|
@ -1 +0,0 @@
|
|||
<svg id="note" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 40"><defs><style>.cls-1{fill:#a0a0a0;}</style></defs><title>note</title><polygon class="cls-1" points="0 0 0 40 35 40 35 20 17.5 20 17.5 0 0 0"/><polygon id="block" class="cls-1" points="20.26 1 35 18 20.26 18 20.26 1"/></svg>
|
Before Width: | Height: | Size: 292 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 510 B |
Before Width: | Height: | Size: 130 B |
BIN
Web/static/img/wall.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
|
@ -35,3 +35,21 @@ window.API.Types = {};
|
|||
window.API.Types.Message = (class Message {
|
||||
|
||||
});
|
||||
|
||||
window.OVKAPI = new class {
|
||||
async call(method, params) {
|
||||
if(!method) {
|
||||
return
|
||||
}
|
||||
|
||||
const url = `/method/${method}?auth_mechanism=roaming&${new URLSearchParams(params).toString()}&v=5.200`
|
||||
const res = await fetch(url)
|
||||
const json_response = await res.json()
|
||||
|
||||
if(json_response.response) {
|
||||
return json_response.response
|
||||
} else {
|
||||
throw new Error(json_response.error_msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,3 @@
|
|||
function fmtTime(time) {
|
||||
const mins = String(Math.floor(time / 60)).padStart(2, '0');
|
||||
const secs = String(Math.floor(time % 60)).padStart(2, '0');
|
||||
return `${ mins}:${ secs}`;
|
||||
}
|
||||
|
||||
function fastError(message) {
|
||||
MessageBox(tr("error"), message, [tr("ok")], [Function.noop])
|
||||
}
|
||||
|
||||
// elapsed это вроде прошедшие, а оставшееся это remaining но ладно уже
|
||||
function getElapsedTime(fullTime, time) {
|
||||
let timer = fullTime - time
|
||||
|
@ -1325,8 +1315,8 @@ $(document).on("click", "#_deletePlaylist", (e) => {
|
|||
}, Function.noop])
|
||||
})
|
||||
|
||||
$(document).on("click", "#_audioAttachment", (e) => {
|
||||
let form = e.currentTarget.closest("form")
|
||||
$(document).on("click", "#__audioAttachment", (e) => {
|
||||
const form = e.target.closest("form")
|
||||
let body = `
|
||||
<div class="searchBox">
|
||||
<input name="query" type="text" maxlength="50" placeholder="${tr("header_search")}">
|
||||
|
@ -1338,7 +1328,7 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
|||
|
||||
<div class="audiosInsert"></div>
|
||||
`
|
||||
MessageBox(tr("select_audio"), body, [tr("ok")], [Function.noop])
|
||||
MessageBox(tr("select_audio"), body, [tr("close")], [Function.noop])
|
||||
|
||||
document.querySelector(".ovk-diag-body").style.padding = "0"
|
||||
document.querySelector(".ovk-diag-cont").style.width = "580px"
|
||||
|
@ -1359,23 +1349,24 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
|||
|
||||
result.querySelectorAll(".audioEmbed").forEach(el => {
|
||||
let id = el.dataset.prettyid
|
||||
let name = el.dataset.name
|
||||
let isAttached = (form.querySelector("input[name='audios']").value.includes(`${id},`))
|
||||
const is_attached = (u(form).find(`.post-vertical .vertical-attachment[data-id='${id}']`)).length > 0
|
||||
|
||||
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
|
||||
<div style="display: table;width: 100%;clear: both;">
|
||||
<div style="width: 72%;float: left;">${el.outerHTML}</div>
|
||||
<div class="attachAudio" data-attachmentdata="${id}" data-name="${name}">
|
||||
<span>${isAttached ? tr("detach_audio") : tr("attach_audio")}</span>
|
||||
<div class='audio_attachment_header' style="display: flex;width: 100%;">
|
||||
<div class='player_part' style="width: 72%;">${el.outerHTML}</div>
|
||||
<div class="attachAudio" data-attachmentdata="${id}">
|
||||
<span>${is_attached ? tr("detach_audio") : tr("attach_audio")}</span>
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
})
|
||||
|
||||
u("#loader").remove()
|
||||
u('#show_more').remove()
|
||||
|
||||
if(thisc.page < pagesCount) {
|
||||
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
|
||||
<div id="showMoreAudios" data-pagesCount="${pagesCount}" data-page="${thisc.page + 1}" class="showMore">
|
||||
<div id="show_more" data-pagesCount="${pagesCount}" data-page="${thisc.page + 1}" class="showMore">
|
||||
<span>${tr("show_more_audios")}</span>
|
||||
</div>`)
|
||||
}
|
||||
|
@ -1395,14 +1386,12 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
|||
|
||||
searcher.movePage(1)
|
||||
|
||||
$(".audiosInsert").on("click", "#showMoreAudios", (e) => {
|
||||
u(e.currentTarget).remove()
|
||||
u(".audiosInsert").on("click", "#show_more", async (e) => {
|
||||
u(e.target).closest('#show_more').addClass('lagged')
|
||||
searcher.movePage(Number(e.currentTarget.dataset.page))
|
||||
})
|
||||
|
||||
$(".searchBox input").on("change", async (e) => {
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
|
||||
if(e.currentTarget.value === document.querySelector(".searchBox input").value) {
|
||||
searcher.clearContainer()
|
||||
|
||||
|
@ -1433,44 +1422,34 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
|||
return;
|
||||
})
|
||||
|
||||
function insertAttachment(id) {
|
||||
let audios = form.querySelector("input[name='audios']")
|
||||
u(".audiosInsert").on("click", ".attachAudio", (ev) => {
|
||||
const id = ev.currentTarget.dataset.attachmentdata
|
||||
const is_attached = u(form).find(`.post-vertical .vertical-attachment[data-id='${id}']`).length > 0
|
||||
|
||||
if(!audios.value.includes(id + ",")) {
|
||||
if(audios.value.split(",").length > 10) {
|
||||
NewNotification(tr("error"), tr("max_attached_audios"))
|
||||
return false
|
||||
}
|
||||
|
||||
form.querySelector("input[name='audios']").value += (id + ",")
|
||||
|
||||
return true
|
||||
// 04.11.2024 19:03
|
||||
if(is_attached) {
|
||||
u(form).find(`.post-vertical .vertical-attachment[data-id='${id}']`).remove()
|
||||
u(ev.currentTarget).find("span").html(tr("attach_audio"))
|
||||
} else {
|
||||
form.querySelector("input[name='audios']").value = form.querySelector("input[name='audios']").value.replace(id + ",", "")
|
||||
|
||||
return false
|
||||
}
|
||||
if(u(form).find(`.upload-item`).length > window.openvk.max_attachments) {
|
||||
makeError(tr('too_many_attachments'), 'Red', 10000, 1)
|
||||
return
|
||||
}
|
||||
|
||||
$(".audiosInsert").on("click", ".attachAudio", (ev) => {
|
||||
if(!insertAttachment(ev.currentTarget.dataset.attachmentdata)) {
|
||||
u(`.post-has-audios .post-has-audio[data-id='${ev.currentTarget.dataset.attachmentdata}']`).remove()
|
||||
ev.currentTarget.querySelector("span").innerHTML = tr("attach_audio")
|
||||
} else {
|
||||
ev.currentTarget.querySelector("span").innerHTML = tr("detach_audio")
|
||||
u(ev.currentTarget).find("span").html(tr("detach_audio"))
|
||||
|
||||
form.querySelector(".post-has-audios").insertAdjacentHTML("beforeend", `
|
||||
<div class="post-has-audio" id="unattachAudio" data-id="${ev.currentTarget.dataset.attachmentdata}">
|
||||
<span>${ovk_proc_strtr(escapeHtml(ev.currentTarget.dataset.name), 40)}</span>
|
||||
const header = u(ev.currentTarget).closest('.audio_attachment_header')
|
||||
const player = header.find('.player_part')
|
||||
u(form).find(".post-vertical").append(`
|
||||
<div class="vertical-attachment upload-item" data-type='audio' data-id="${ev.currentTarget.dataset.attachmentdata}">
|
||||
<div class='vertical-attachment-content'>
|
||||
${player.html()}
|
||||
</div>
|
||||
<div class='vertical-attachment-remove'>
|
||||
<div id='small_remove_button'></div>
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
|
||||
u(`#unattachAudio[data-id='${ev.currentTarget.dataset.attachmentdata}']`).on("click", (e) => {
|
||||
let id = ev.currentTarget.dataset.attachmentdata
|
||||
form.querySelector("input[name='audios']").value = form.querySelector("input[name='audios']").value.replace(id + ",", "")
|
||||
|
||||
u(e.currentTarget).remove()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -1480,7 +1459,13 @@ $(document).on("click", ".audioEmbed.processed .playerButton", (e) => {
|
|||
})
|
||||
|
||||
$(document).on("click", ".audioEmbed.withdrawn", (e) => {
|
||||
MessageBox(tr("error"), tr("audio_embed_withdrawn"), [tr("ok")], [Function.noop])
|
||||
const msg = new CMessageBox({
|
||||
title: tr('error'),
|
||||
body: tr('audio_embed_withdrawn'),
|
||||
unique_name: 'withdrawn_notify',
|
||||
buttons: [tr('ok')],
|
||||
callbacks: [Function.noop]
|
||||
})
|
||||
})
|
||||
|
||||
$(document).on("click", ".musicIcon.report-icon", (e) => {
|
||||
|
|
|
@ -64,8 +64,9 @@ function pollRadioPressed(radio) {
|
|||
form.submit();
|
||||
}
|
||||
|
||||
function initPoll(id) {
|
||||
let form = $(`#wall-post-input${id}`).parent();
|
||||
function initPoll(event) {
|
||||
let form = $(event.target.closest('.post-buttons')).parent();
|
||||
const id = random_int(0, 100)
|
||||
|
||||
let mBody = `
|
||||
<div id="poll_editor${id}">
|
||||
|
@ -87,9 +88,9 @@ function initPoll(id) {
|
|||
</div>
|
||||
`;
|
||||
|
||||
MessageBox(tr("create_poll"), mBody, [tr("attach"), tr("cancel")], [
|
||||
const msg = MessageBox(tr("create_poll"), mBody, [tr("attach"), tr("cancel")], [
|
||||
function() {
|
||||
let dialog = $(this.$dialog().nodes[0]);
|
||||
let dialog = $(msg.getNode().nodes[0]);
|
||||
$("input", dialog).unbind();
|
||||
|
||||
let title = $("input[name=title]", dialog).val();
|
||||
|
@ -117,9 +118,9 @@ function initPoll(id) {
|
|||
$(".post-has-poll", form).show();
|
||||
},
|
||||
function() {
|
||||
$("input", $(this.$dialog().nodes[0])).unbind();
|
||||
$("input", $(msg.getNode())).unbind();
|
||||
}
|
||||
]);
|
||||
], true);
|
||||
|
||||
let editor = $(`#poll_editor${id}`);
|
||||
$("input[name=newOption]", editor).bind("focus", function() {
|
||||
|
|
|
@ -1,42 +1,177 @@
|
|||
Function.noop = () => {};
|
||||
|
||||
function MessageBox(title, body, buttons, callbacks) {
|
||||
if(u(".ovk-diag-cont").length > 0) return false;
|
||||
|
||||
document.querySelector("html").style.overflowY = "hidden"
|
||||
let dialog = u(
|
||||
`<div class="ovk-diag-cont">
|
||||
<div class="ovk-diag">
|
||||
<div class="ovk-diag-head">${title}</div>
|
||||
<div class="ovk-diag-body">${body}</div>
|
||||
<div class="ovk-diag-action"></div>
|
||||
</div>
|
||||
</div>`);
|
||||
u("body").addClass("dimmed").append(dialog);
|
||||
|
||||
buttons.forEach((text, callback) => {
|
||||
u(".ovk-diag-action").append(u(`<button class="button">${text}</button>`));
|
||||
let button = u(u(".ovk-diag-action > button.button").last());
|
||||
|
||||
button.on("click", function(e) {
|
||||
let __closeDialog = () => {
|
||||
|
||||
if(document.querySelector(".ovk-photo-view-dimmer") == null && document.querySelector(".ovk-fullscreen-player") == null) {
|
||||
u("body").removeClass("dimmed");
|
||||
document.querySelector("html").style.overflowY = "scroll"
|
||||
class CMessageBox {
|
||||
constructor(options = {}) {
|
||||
const title = options.title ?? 'Untitled'
|
||||
const body = options.body ?? '<hr>'
|
||||
const buttons = options.buttons ?? []
|
||||
const callbacks = options.callbacks ?? []
|
||||
const close_on_buttons = options.close_on_buttons ?? true
|
||||
const unique_name = options.unique_name ?? null
|
||||
const warn_on_exit = options.warn_on_exit ?? false
|
||||
const custom_template = options.custom_template ?? null
|
||||
if(unique_name && window.messagebox_stack.find(item => item.unique_name == unique_name) != null) {
|
||||
return
|
||||
}
|
||||
|
||||
u(".ovk-diag-cont").remove();
|
||||
};
|
||||
this.title = title
|
||||
this.body = body
|
||||
this.id = random_int(0, 10000)
|
||||
this.close_on_buttons = close_on_buttons
|
||||
this.unique_name = unique_name
|
||||
this.warn_on_exit = warn_on_exit
|
||||
|
||||
Reflect.apply(callbacks[callback], {
|
||||
closeDialog: () => __closeDialog(),
|
||||
$dialog: () => u(".ovk-diag-cont")
|
||||
}, [e]);
|
||||
if(!custom_template) {
|
||||
u('body').addClass('dimmed').append(this.__getTemplate())
|
||||
} else {
|
||||
custom_template.addClass('ovk-msg-all')
|
||||
custom_template.attr('data-id', this.id)
|
||||
u('body').addClass('dimmed').append(custom_template)
|
||||
}
|
||||
|
||||
__closeDialog();
|
||||
});
|
||||
});
|
||||
u('html').attr('style', 'overflow-y:hidden')
|
||||
|
||||
return u(".ovk-diag-cont");
|
||||
buttons.forEach((text, callback) => {
|
||||
this.getNode().find('.ovk-diag-action').append(u(`<button class="button">${text}</button>`))
|
||||
let button = u(this.getNode().find('.ovk-diag-action > button.button').last())
|
||||
button.on("click", (e) => {
|
||||
callbacks[callback]()
|
||||
|
||||
if(close_on_buttons) {
|
||||
this.close()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
window.messagebox_stack.push(this)
|
||||
}
|
||||
|
||||
__getTemplate() {
|
||||
return u(
|
||||
`<div class="ovk-diag-cont ovk-msg-all" data-id="${this.id}">
|
||||
<div class="ovk-diag">
|
||||
<div class="ovk-diag-head">${this.title}</div>
|
||||
<div class="ovk-diag-body">${this.body}</div>
|
||||
<div class="ovk-diag-action"></div>
|
||||
</div>
|
||||
</div>`)
|
||||
}
|
||||
|
||||
getNode() {
|
||||
return u(`.ovk-msg-all[data-id='${this.id}']`)
|
||||
}
|
||||
|
||||
async __showCloseConfirmationDialog() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const msg = new CMessageBox({
|
||||
title: tr('exit_noun'),
|
||||
body: tr('exit_confirmation'),
|
||||
warn_on_exit: false,
|
||||
unique_name: 'close_confirmation',
|
||||
buttons: [tr('no'), tr('yes')],
|
||||
callbacks: [() => {
|
||||
msg.close()
|
||||
resolve(false)
|
||||
}, () => {
|
||||
this.__exitDialog()
|
||||
resolve(true)
|
||||
}]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
__exitDialog() {
|
||||
this.getNode().remove()
|
||||
if(u('.ovk-msg-all').length < 1) {
|
||||
u('body').removeClass('dimmed')
|
||||
u('html').attr('style', 'overflow-y:scroll')
|
||||
}
|
||||
|
||||
const current_item = window.messagebox_stack.find(item => item.id == this.id)
|
||||
const index_of_item = window.messagebox_stack.indexOf(current_item)
|
||||
window.messagebox_stack = array_splice(window.messagebox_stack, index_of_item)
|
||||
|
||||
delete this
|
||||
}
|
||||
|
||||
close() {
|
||||
this.__exitDialog()
|
||||
}
|
||||
|
||||
hide() {
|
||||
u('body').removeClass('dimmed')
|
||||
u('html').attr('style', 'overflow-y:scroll')
|
||||
this.getNode().attr('style', 'display: none;')
|
||||
}
|
||||
|
||||
reveal() {
|
||||
u('body').addClass('dimmed')
|
||||
u('html').attr('style', 'overflow-y:hidden')
|
||||
this.getNode().attr('style', 'display: block;')
|
||||
}
|
||||
|
||||
static toggleLoader() {
|
||||
u('#ajloader').toggleClass('shown')
|
||||
}
|
||||
}
|
||||
|
||||
window.messagebox_stack = []
|
||||
|
||||
function MessageBox(title, body, buttons, callbacks, return_msg = false) {
|
||||
const msg = new CMessageBox({
|
||||
title: title,
|
||||
body: body,
|
||||
buttons: buttons,
|
||||
callbacks: callbacks,
|
||||
})
|
||||
|
||||
if(return_msg) {
|
||||
return msg
|
||||
}
|
||||
|
||||
return msg.getNode()
|
||||
}
|
||||
|
||||
// Close on 'Escape' key
|
||||
u(document).on('keyup', async (e) => {
|
||||
if(e.keyCode == 27 && window.messagebox_stack.length > 0) {
|
||||
const msg = window.messagebox_stack[window.messagebox_stack.length - 1]
|
||||
if(!msg) {
|
||||
return
|
||||
}
|
||||
|
||||
if(msg.close_on_buttons) {
|
||||
msg.close()
|
||||
return
|
||||
}
|
||||
|
||||
if(msg.warn_on_exit) {
|
||||
const res = await msg.__showCloseConfirmationDialog()
|
||||
if(res === true) {
|
||||
msg.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Close when clicking on shadow
|
||||
u(document).on('click', 'body.dimmed .dimmer', async (e) => {
|
||||
if(u(e.target).hasClass('dimmer')) {
|
||||
const msg = window.messagebox_stack[window.messagebox_stack.length - 1]
|
||||
if(!msg) {
|
||||
return
|
||||
}
|
||||
|
||||
if(msg.close_on_buttons) {
|
||||
msg.close()
|
||||
return
|
||||
}
|
||||
|
||||
if(msg.warn_on_exit) {
|
||||
const res = await msg.__showCloseConfirmationDialog()
|
||||
if(res === true) {
|
||||
msg.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
|
||||
function expand_wall_textarea(id) {
|
||||
var el = document.getElementById('post-buttons'+id);
|
||||
var wi = document.getElementById('wall-post-input'+id);
|
||||
el.style.display = "block";
|
||||
wi.className = "expanded-textarea";
|
||||
if(typeof u == 'undefined') {
|
||||
console.error('!!! You forgot to install NPM packages !!!')
|
||||
}
|
||||
|
||||
function expand_comment_textarea(id) {
|
||||
|
@ -13,19 +9,6 @@ function expand_comment_textarea(id) {
|
|||
wi.focus();
|
||||
}
|
||||
|
||||
function edit_post(id, wid) {
|
||||
var el = document.getElementById('text'+wid+'_'+id);
|
||||
var ed = document.getElementById('text_edit'+wid+'_'+id);
|
||||
if (el.style.display == "none") {
|
||||
el.style.display = "block";
|
||||
ed.style.display = "none";
|
||||
} else {
|
||||
el.style.display = "none";
|
||||
ed.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function hidePanel(panel, count = 0)
|
||||
{
|
||||
$(panel).toggleClass("content_title_expanded content_title_unexpanded");
|
||||
|
@ -56,19 +39,9 @@ function parseAjaxResponse(responseString) {
|
|||
}
|
||||
}
|
||||
|
||||
function toggleMenu(id) {
|
||||
if($(`#post-buttons${id} #wallAttachmentMenu`).is('.hidden')) {
|
||||
$(`#post-buttons${id} #wallAttachmentMenu`).css({ opacity: 0 });
|
||||
$(`#post-buttons${id} #wallAttachmentMenu`).toggleClass('hidden').fadeTo(250, 1);
|
||||
} else {
|
||||
$(`#post-buttons${id} #wallAttachmentMenu`).fadeTo(250, 0, function () {
|
||||
$(this).toggleClass('hidden');
|
||||
});
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", function() { //BEGIN
|
||||
|
||||
$(document).on("click", "#_photoDelete", function(e) {
|
||||
$(document).on("click", "#_photoDelete, #_videoDelete", function(e) {
|
||||
var formHtml = "<form id='tmpPhDelF' action='" + u(this).attr("href") + "' >";
|
||||
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
|
||||
formHtml += "</form>";
|
||||
|
@ -186,74 +159,6 @@ document.addEventListener("DOMContentLoaded", function() { //BEGIN
|
|||
})
|
||||
}); //END ONREADY DECLS
|
||||
|
||||
async function repostPost(id, hash) {
|
||||
uRepostMsgTxt = `
|
||||
<b>${tr('auditory')}:</b> <br/>
|
||||
<input type="radio" name="type" onchange="signs.setAttribute('hidden', 'hidden');document.getElementById('groupId').setAttribute('hidden', 'hidden')" value="wall" checked>${tr("in_wall")}<br/>
|
||||
<input type="radio" name="type" onchange="signs.removeAttribute('hidden');document.getElementById('groupId').removeAttribute('hidden')" value="group" id="group">${tr("in_group")}<br/>
|
||||
<select style="width:50%;" id="groupId" name="groupId" hidden>
|
||||
</select><br/>
|
||||
<b>${tr('your_comment')}:</b>
|
||||
<textarea id='uRepostMsgInput_${id}'></textarea>
|
||||
<div id="signs" hidden>
|
||||
<label><input onchange="signed.checked ? signed.checked = false : null" type="checkbox" id="asgroup" name="asGroup">${tr('post_as_group')}</label><br>
|
||||
<label><input onchange="asgroup.checked = true" type="checkbox" id="signed" name="signed">${tr('add_signature')}</label>
|
||||
</div>
|
||||
<br/><br/>`;
|
||||
let clubs = [];
|
||||
repostsCount = document.getElementById("repostsCount"+id)
|
||||
prevVal = repostsCount != null ? Number(repostsCount.innerHTML) : 0;
|
||||
|
||||
MessageBox(tr('share'), uRepostMsgTxt, [tr('send'), tr('cancel')], [
|
||||
(function() {
|
||||
text = document.querySelector("#uRepostMsgInput_"+id).value;
|
||||
type = "user";
|
||||
radios = document.querySelectorAll('input[name="type"]')
|
||||
for(const r of radios)
|
||||
{
|
||||
if(r.checked)
|
||||
{
|
||||
type = r.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
groupId = document.querySelector("#groupId").value;
|
||||
asGroup = asgroup.checked == true ? 1 : 0;
|
||||
signed = signed.checked == true ? 1 : 0;
|
||||
hash = encodeURIComponent(hash);
|
||||
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/wall"+id+"/repost?hash="+hash, true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("wall_owner") === -1)
|
||||
MessageBox(tr('error'), tr('error_repost_fail'), [tr('ok')], [Function.noop]);
|
||||
else {
|
||||
let jsonR = JSON.parse(xhr.responseText);
|
||||
NewNotification(tr('information_-1'), tr('shared_succ'), null, () => {window.location.href = "/wall" + jsonR.wall_owner});
|
||||
repostsCount != null ?
|
||||
repostsCount.innerHTML = prevVal+1 :
|
||||
document.getElementById("reposts"+id).insertAdjacentHTML("beforeend", "(<b id='repostsCount"+id+"'>1</b>)") //для старого вида постов
|
||||
}
|
||||
});
|
||||
xhr.send('text='+encodeURI(text) + '&type='+type + '&groupId='+groupId + "&asGroup="+asGroup + "&signed="+signed);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
|
||||
try
|
||||
{
|
||||
clubs = await API.Groups.getWriteableClubs();
|
||||
for(const el of clubs) {
|
||||
document.getElementById("groupId").insertAdjacentHTML("beforeend", `<option value="${el.id}">${escapeHtml(el.name)}</option>`)
|
||||
}
|
||||
|
||||
} catch(rejection) {
|
||||
console.error(rejection)
|
||||
document.getElementById("group").setAttribute("disabled", "disabled")
|
||||
}
|
||||
}
|
||||
|
||||
function setClubAdminComment(clubId, adminId, hash) {
|
||||
MessageBox("Изменить комментарий к администратору", `
|
||||
<form action="/club${clubId}/setAdmin" method="post" id="uClubAdminCommentForm_${clubId}_${adminId}">
|
||||
|
@ -319,17 +224,6 @@ function showCoinsTransferDialog(coinsCount, hash) {
|
|||
]);
|
||||
}
|
||||
|
||||
function chunkSubstr(string, size) {
|
||||
const numChunks = Math.ceil(string.length / size);
|
||||
const chunks = new Array(numChunks);
|
||||
|
||||
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
|
||||
chunks[i] = string.substr(o, size);
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
function autoTab(original, next, previous) {
|
||||
if(original.getAttribute && original.value.length == original.getAttribute("maxlength") && next !== undefined)
|
||||
next.focus();
|
||||
|
@ -361,11 +255,6 @@ function supportFastAnswerDialogOnClick(answer) {
|
|||
answerInput.focus();
|
||||
}
|
||||
|
||||
function ovk_proc_strtr(string, length = 0) {
|
||||
const newString = string.substring(0, length);
|
||||
return newString + (string !== newString ? "…" : "");
|
||||
}
|
||||
|
||||
function showProfileDeactivateDialog(hash) {
|
||||
MessageBox(tr("profile_deactivate"), `
|
||||
<div class="messagebox-content-header">
|
||||
|
@ -488,57 +377,6 @@ function showIncreaseRatingDialog(coinsCount, userUrl, hash) {
|
|||
};
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
var map = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
|
||||
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
}
|
||||
|
||||
function highlightText(searchText, container_selector, selectors = []) {
|
||||
const container = u(container_selector)
|
||||
const regexp = new RegExp(`(${searchText})`, 'gi')
|
||||
|
||||
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>`
|
||||
})
|
||||
|
||||
const tempDiv = document.createElement('div')
|
||||
tempDiv.innerHTML = newNode
|
||||
|
||||
while(tempDiv.firstChild) {
|
||||
node.parentNode.insertBefore(tempDiv.firstChild, node)
|
||||
}
|
||||
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", () => {
|
||||
if($(document).scrollTop() > $(".sidebar").height() + 50) {
|
||||
$(".floating_sidebar")[0].classList.add("show");
|
||||
|
|
175
Web/static/js/utils.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
function escapeHtml(text) {
|
||||
var map = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
|
||||
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
||||
}
|
||||
|
||||
function highlightText(searchText, container_selector, selectors = []) {
|
||||
const container = u(container_selector)
|
||||
const regexp = new RegExp(`(${searchText})`, 'gi')
|
||||
|
||||
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>`
|
||||
})
|
||||
|
||||
const tempDiv = document.createElement('div')
|
||||
tempDiv.innerHTML = newNode
|
||||
|
||||
while(tempDiv.firstChild) {
|
||||
node.parentNode.insertBefore(tempDiv.firstChild, node)
|
||||
}
|
||||
node.parentNode.removeChild(node)
|
||||
} else if(node.nodeType === 1 && node.tagName !== 'SCRIPT' && node.tagName !== 'BR' && node.tagName !== 'STYLE' && !node.classList.contains('highlight')) {
|
||||
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 ''
|
||||
}
|
||||
}
|
||||
|
||||
function fmtTime(time) {
|
||||
const mins = String(Math.floor(time / 60)).padStart(2, '0');
|
||||
const secs = String(Math.floor(time % 60)).padStart(2, '0');
|
||||
return `${ mins}:${ secs}`;
|
||||
}
|
||||
|
||||
function fastError(message) {
|
||||
MessageBox(tr("error"), message, [tr("ok")], [Function.noop])
|
||||
}
|
||||
|
||||
function humanFileSize(bytes, si) {
|
||||
var thresh = si ? 1000 : 1024;
|
||||
if(Math.abs(bytes) < thresh) {
|
||||
return bytes + ' B';
|
||||
}
|
||||
var units = si
|
||||
? ['kB','MB','GB','TB','PB','EB','ZB','YB']
|
||||
: ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
|
||||
var u = -1;
|
||||
do {
|
||||
bytes /= thresh;
|
||||
++u;
|
||||
} while(Math.abs(bytes) >= thresh && u < units.length - 1);
|
||||
return bytes.toFixed(1)+' '+units[u];
|
||||
}
|
||||
|
||||
function trim(string) {
|
||||
var newStr = string.substring(0, 10);
|
||||
if(newStr.length !== string.length)
|
||||
newStr += "…";
|
||||
|
||||
return newStr;
|
||||
}
|
||||
|
||||
function trimNum(string, num) {
|
||||
return ovk_proc_strtr(string, num);
|
||||
}
|
||||
|
||||
function ovk_proc_strtr(string, length = 0) {
|
||||
const newString = string.substring(0, length);
|
||||
return newString + (string !== newString ? "…" : "");
|
||||
}
|
||||
|
||||
function chunkSubstr(string, size) {
|
||||
const numChunks = Math.ceil(string.length / size);
|
||||
const chunks = new Array(numChunks);
|
||||
|
||||
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
|
||||
chunks[i] = string.substr(o, size);
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
function random_int(min, max) {
|
||||
return Math.round(Math.random() * (max - min) + min)
|
||||
}
|
||||
|
||||
function makeError(text, color = 'Red', timeout = 10000, uid = 0) {
|
||||
const rand_id = uid != 0 ? uid : random_int(0, 10000)
|
||||
|
||||
if(uid != 0 && u(`.upLeftErrors .upLeftError[data-id='${uid}']`).length > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
u('.upLeftErrors').append(`
|
||||
<div class='upLeftError upLeftError${color}' data-id='${rand_id}'>${escapeHtml(text)}</div>
|
||||
`)
|
||||
|
||||
setTimeout(() => {
|
||||
u(`.upLeftError[data-id='${rand_id}']`).remove()
|
||||
}, timeout)
|
||||
}
|
||||
|
||||
function array_splice(array, key)
|
||||
{
|
||||
let resultArray = [];
|
||||
|
||||
for(let i = 0; i < array.length; i++){
|
||||
if(i != key){
|
||||
resultArray.push(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
function strip_tags(text)
|
||||
{
|
||||
return text.replace(/(<([^>]+)>)/gi, "")
|
||||
}
|
||||
|
||||
function find_author(id, profiles, groups)
|
||||
{
|
||||
if(id > 0) {
|
||||
const profile = profiles.find(prof => prof.id == id)
|
||||
if(profile) {
|
||||
return profile
|
||||
}
|
||||
} else {
|
||||
const group = groups.find(grou => grou.id == Math.abs(id))
|
||||
if(group) {
|
||||
return group
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function collect_attachments(target) {
|
||||
const horizontal_array = []
|
||||
const horizontal_attachments = target.find(`.post-horizontal > a`)
|
||||
horizontal_attachments.nodes.forEach(_node => {
|
||||
horizontal_array.push(`${_node.dataset.type}${_node.dataset.id}`)
|
||||
})
|
||||
|
||||
const vertical_array = []
|
||||
const vertical_attachments = target.find(`.post-vertical > .vertical-attachment`)
|
||||
vertical_attachments.nodes.forEach(_node => {
|
||||
vertical_array.push(`${_node.dataset.type}${_node.dataset.id}`)
|
||||
})
|
||||
|
||||
return horizontal_array.concat(vertical_array)
|
||||
}
|
|
@ -232,49 +232,65 @@ function ovk_is_ssl(): bool
|
|||
return $GLOBALS["requestIsSSL"];
|
||||
}
|
||||
|
||||
function parseAttachments(string $attachments): array
|
||||
function parseAttachments($attachments, array $allow_types = ['photo', 'video', 'note', 'audio']): array
|
||||
{
|
||||
$attachmentsArr = explode(",", $attachments);
|
||||
$returnArr = [];
|
||||
$exploded_attachments = is_array($attachments) ? $attachments : explode(",", $attachments);
|
||||
$exploded_attachments = array_slice($exploded_attachments, 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"] ?? 10);
|
||||
$exploded_attachments = array_unique($exploded_attachments);
|
||||
$imploded_types = implode('|', $allow_types);
|
||||
$output_attachments = [];
|
||||
$repositories = [
|
||||
'photo' => [
|
||||
'repo' => 'openvk\Web\Models\Repositories\Photos',
|
||||
'method' => 'getByOwnerAndVID',
|
||||
],
|
||||
'video' => [
|
||||
'repo' => 'openvk\Web\Models\Repositories\Videos',
|
||||
'method' => 'getByOwnerAndVID',
|
||||
],
|
||||
'audio' => [
|
||||
'repo' => 'openvk\Web\Models\Repositories\Audios',
|
||||
'method' => 'getByOwnerAndVID',
|
||||
],
|
||||
'note' => [
|
||||
'repo' => 'openvk\Web\Models\Repositories\Notes',
|
||||
'method' => 'getNoteById',
|
||||
],
|
||||
'poll' => [
|
||||
'repo' => 'openvk\Web\Models\Repositories\Polls',
|
||||
'method' => 'get',
|
||||
'onlyId' => true,
|
||||
],
|
||||
];
|
||||
|
||||
foreach($attachmentsArr as $attachment) {
|
||||
$attachmentType = NULL;
|
||||
foreach($exploded_attachments as $attachment_string) {
|
||||
if(preg_match("/$imploded_types/", $attachment_string, $matches) == 1) {
|
||||
try {
|
||||
$attachment_type = $matches[0];
|
||||
if(!$repositories[$attachment_type])
|
||||
continue;
|
||||
|
||||
if(str_contains($attachment, "photo"))
|
||||
$attachmentType = "photo";
|
||||
elseif(str_contains($attachment, "video"))
|
||||
$attachmentType = "video";
|
||||
elseif(str_contains($attachment, "note"))
|
||||
$attachmentType = "note";
|
||||
elseif(str_contains($attachment, "audio"))
|
||||
$attachmentType = "audio";
|
||||
$attachment_ids = str_replace($attachment_type, '', $attachment_string);
|
||||
if($repositories[$attachment_type]['onlyId']) {
|
||||
[$attachment_id] = array_map('intval', explode('_', $attachment_ids));
|
||||
|
||||
$attachmentIds = str_replace($attachmentType, "", $attachment);
|
||||
$attachmentOwner = (int) explode("_", $attachmentIds)[0];
|
||||
$gatoExplotano = explode("_", $attachmentIds);
|
||||
$attachmentId = (int) end($gatoExplotano);
|
||||
$repository_class = $repositories[$attachment_type]['repo'];
|
||||
if(!$repository_class) continue;
|
||||
$attachment_model = (new $repository_class)->{$repositories[$attachment_type]['method']}($attachment_id);
|
||||
$output_attachments[] = $attachment_model;
|
||||
} else {
|
||||
[$attachment_owner, $attachment_id] = array_map('intval', explode('_', $attachment_ids));
|
||||
|
||||
switch($attachmentType) {
|
||||
case "photo":
|
||||
$attachmentObj = (new openvk\Web\Models\Repositories\Photos)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
$returnArr[] = $attachmentObj;
|
||||
break;
|
||||
case "video":
|
||||
$attachmentObj = (new openvk\Web\Models\Repositories\Videos)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
$returnArr[] = $attachmentObj;
|
||||
break;
|
||||
case "note":
|
||||
$attachmentObj = (new openvk\Web\Models\Repositories\Notes)->getNoteById($attachmentOwner, $attachmentId);
|
||||
$returnArr[] = $attachmentObj;
|
||||
break;
|
||||
case "audio":
|
||||
$attachmentObj = (new openvk\Web\Models\Repositories\Audios)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
||||
$returnArr[] = $attachmentObj;
|
||||
break;
|
||||
$repository_class = $repositories[$attachment_type]['repo'];
|
||||
if(!$repository_class) continue;
|
||||
$attachment_model = (new $repository_class)->{$repositories[$attachment_type]['method']}($attachment_owner, $attachment_id);
|
||||
$output_attachments[] = $attachment_model;
|
||||
}
|
||||
} catch(\Throwable) {continue;}
|
||||
}
|
||||
}
|
||||
|
||||
return $returnArr;
|
||||
return $output_attachments;
|
||||
}
|
||||
|
||||
function get_entity_by_id(int $id)
|
||||
|
|
|
@ -58,6 +58,7 @@ openvk:
|
|||
enable: false
|
||||
account: 100
|
||||
postSizes:
|
||||
maxAttachments: 10
|
||||
maxSize: 60000
|
||||
processingLimit: 3000
|
||||
emojiProcessingLimit: 1000
|
||||
|
|
2
install/sqls/00050-new-video-fields.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE `videos` ADD `length` SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER `name`, ADD INDEX `length` (`length`);
|
||||
ALTER TABLE `videos` ADD `height` SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER `length`, ADD `width` SMALLINT(5) UNSIGNED NULL DEFAULT NULL AFTER `height`;
|
|
@ -269,6 +269,7 @@
|
|||
"others_posts" = "Others posts";
|
||||
|
||||
"show_more" = "Show more";
|
||||
"has_repost" = "Has repost";
|
||||
|
||||
/* Friends */
|
||||
|
||||
|
@ -517,6 +518,7 @@
|
|||
"click_to_go_to_album" = "Click here to go to album.";
|
||||
"error_uploading_photo" = "Error when uploading photo";
|
||||
"too_many_pictures" = "No more than 10 pictures";
|
||||
"too_many_attachments" = "Too many attachments.";
|
||||
|
||||
"drag_files_here" = "Drag files here";
|
||||
"only_images_accepted" = "File \"$1\" is not an image";
|
||||
|
@ -848,6 +850,9 @@
|
|||
"no_videos" = "You don't have uploaded videos.";
|
||||
"no_videos_results" = "No results.";
|
||||
|
||||
"video_file_upload" = "Upload file";
|
||||
"video_youtube_upload" = "Add from YouTube";
|
||||
|
||||
"change_video" = "Change video";
|
||||
"unknown_video" = "This video is not supported in your version of OpenVK.";
|
||||
|
||||
|
@ -1777,6 +1782,8 @@
|
|||
"question_confirm" = "This action can't be undone. Do you really wanna do it?";
|
||||
"confirm_m" = "Confirm";
|
||||
"action_successfully" = "Success";
|
||||
"exit_noun" = "Exit";
|
||||
"exit_confirmation" = "Are you sure want to exit?";
|
||||
"apply" = "Apply";
|
||||
|
||||
/* User Alerts */
|
||||
|
|
|
@ -248,6 +248,7 @@
|
|||
"clubs_posts" = "Записи сообщества";
|
||||
"others_posts" = "Чужие записи";
|
||||
"show_more" = "Показать больше";
|
||||
"has_repost" = "Содержит репост";
|
||||
|
||||
/* Friends */
|
||||
|
||||
|
@ -500,9 +501,10 @@
|
|||
"click_to_go_to_album" = "Нажмите, чтобы перейти к альбому.";
|
||||
"error_uploading_photo" = "Не удалось загрузить фотографию";
|
||||
"too_many_pictures" = "Не больше 10 фотографий";
|
||||
"too_many_attachments" = "Слишком много вложений.";
|
||||
|
||||
"drag_files_here" = "Перетащите файлы сюда";
|
||||
"only_images_accepted" = "Файл \"$1\" не является изображением";
|
||||
"only_images_accepted" = "Файл \"$1\" не является изображением или видео.";
|
||||
"max_filesize" = "Максимальный размер файла — $1 мегабайт";
|
||||
|
||||
"uploading_photos_from_computer" = "Загрузка фотографий с Вашего компьютера";
|
||||
|
@ -807,6 +809,9 @@
|
|||
"no_videos" = "У вас нет видео.";
|
||||
"no_videos_results" = "Нет результатов.";
|
||||
|
||||
"video_file_upload" = "Загрузить файл";
|
||||
"video_youtube_upload" = "Добавить с YouTube";
|
||||
|
||||
/* Audios */
|
||||
|
||||
"my" = "Моё";
|
||||
|
@ -1481,7 +1486,7 @@
|
|||
|
||||
"error_adding_source_regex" = "Ошибка добавления источника: некорректная ссылка.";
|
||||
"error_adding_source_long" = "Ошибка добавления источника: слишком длинная ссылка.";
|
||||
"error_adding_source_sus" = "Ошибка добавления источника: подозрительная ссылка.";
|
||||
"error_adding_source_sus" = "Ошибка добавления источника: гиперссылка заблокирована.";
|
||||
|
||||
/* Admin actions */
|
||||
|
||||
|
@ -1669,6 +1674,8 @@
|
|||
"question_confirm" = "Это действие нельзя отменить. Вы действительно уверены в том что хотите сделать?";
|
||||
"confirm_m" = "Подтвердить";
|
||||
"action_successfully" = "Операция успешна";
|
||||
"exit_noun" = "Выход";
|
||||
"exit_confirmation" = "Уверены, что хотите выйти?";
|
||||
"apply" = "Применить";
|
||||
|
||||
/* User alerts */
|
||||
|
@ -2028,7 +2035,7 @@
|
|||
|
||||
/* Fullscreen player */
|
||||
|
||||
"hide_player" = "Скрыть";
|
||||
"hide_player" = "Свернуть";
|
||||
"close_player" = "Закрыть";
|
||||
"show_comments" = "Показать информацию";
|
||||
"close_comments" = "Скрыть информацию";
|
||||
|
|
|
@ -60,6 +60,7 @@ openvk:
|
|||
enable: false
|
||||
account: 100
|
||||
postSizes:
|
||||
maxAttachments: 10
|
||||
maxSize: 60000
|
||||
processingLimit: 3000
|
||||
emojiProcessingLimit: 1000
|
||||
|
|