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());
|
$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;
|
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();
|
$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) {
|
if($user_id == 0) {
|
||||||
foreach($this->getUser()->getClubs($offset, $filter == "admin", $count, true) as $club)
|
foreach($this->getUser()->getClubs($offset, $filter == "admin", $count, true) as $club)
|
||||||
$clbs[] = $club;
|
$clbs[] = $club;
|
||||||
|
|
|
@ -48,7 +48,7 @@ final class Newsfeed extends VKAPIRequestHandler
|
||||||
return $response;
|
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();
|
$this->requireUser();
|
||||||
|
|
||||||
|
@ -74,6 +74,25 @@ final class Newsfeed extends VKAPIRequestHandler
|
||||||
|
|
||||||
$rposts = [];
|
$rposts = [];
|
||||||
$ids = [];
|
$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) {
|
foreach($posts as $post) {
|
||||||
$rposts[] = (new PostsRepo)->get($post->id)->getPrettyId();
|
$rposts[] = (new PostsRepo)->get($post->id)->getPrettyId();
|
||||||
$ids[] = $post->id;
|
$ids[] = $post->id;
|
||||||
|
|
|
@ -427,7 +427,7 @@ final class Photos extends VKAPIRequestHandler
|
||||||
$this->fail(15, "Access denied");
|
$this->fail(15, "Access denied");
|
||||||
|
|
||||||
$photos = array_slice(iterator_to_array($album->getPhotos(1, $count + $offset)), $offset);
|
$photos = array_slice(iterator_to_array($album->getPhotos(1, $count + $offset)), $offset);
|
||||||
$res["count"] = sizeof($photos);
|
$res["count"] = $album->size();
|
||||||
|
|
||||||
foreach($photos as $photo) {
|
foreach($photos as $photo) {
|
||||||
if(!$photo || $photo->isDeleted()) continue;
|
if(!$photo || $photo->isDeleted()) continue;
|
||||||
|
@ -638,15 +638,15 @@ final class Photos extends VKAPIRequestHandler
|
||||||
$this->fail(4, "This method doesn't works with clubs");
|
$this->fail(4, "This method doesn't works with clubs");
|
||||||
|
|
||||||
$user = (new UsersRepo)->get($owner_id);
|
$user = (new UsersRepo)->get($owner_id);
|
||||||
|
|
||||||
if(!$user)
|
if(!$user)
|
||||||
$this->fail(4, "Invalid user");
|
$this->fail(4, "Invalid user");
|
||||||
|
|
||||||
if(!$user->getPrivacyPermission('photos.read', $this->getUser()))
|
if(!$user->getPrivacyPermission('photos.read', $this->getUser()))
|
||||||
$this->fail(21, "This user chose to hide his albums.");
|
$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 = [
|
$res = [
|
||||||
|
"count" => (new PhotosRepo)->getUserPhotosCount($user),
|
||||||
"items" => [],
|
"items" => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -11,24 +11,55 @@ use openvk\Web\Models\Repositories\Comments as CommentsRepo;
|
||||||
|
|
||||||
final class Video extends VKAPIRequestHandler
|
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();
|
$this->requireUser();
|
||||||
|
|
||||||
if(!empty($videos)) {
|
if(!empty($videos)) {
|
||||||
$vids = explode(',', $videos);
|
$vids = explode(',', $videos);
|
||||||
|
$profiles = [];
|
||||||
foreach($vids as $vid)
|
$groups = [];
|
||||||
{
|
foreach($vids as $vid) {
|
||||||
$id = explode("_", $vid);
|
$id = explode("_", $vid);
|
||||||
|
|
||||||
$items = [];
|
$items = [];
|
||||||
|
|
||||||
$video = (new VideosRepo)->getByOwnerAndVID(intval($id[0]), intval($id[1]));
|
$video = (new VideosRepo)->getByOwnerAndVID(intval($id[0]), intval($id[1]));
|
||||||
if($video) {
|
if($video && !$video->isDeleted()) {
|
||||||
$items[] = $video->getApiStructure($this->getUser());
|
$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) [
|
return (object) [
|
||||||
"count" => count($items),
|
"count" => count($items),
|
||||||
|
@ -46,12 +77,46 @@ final class Video extends VKAPIRequestHandler
|
||||||
if(!$user->getPrivacyPermission('videos.read', $this->getUser()))
|
if(!$user->getPrivacyPermission('videos.read', $this->getUser()))
|
||||||
$this->fail(21, "This user chose to hide his videos.");
|
$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);
|
$videosCount = (new VideosRepo)->getUserVideosCount($user);
|
||||||
|
|
||||||
$items = [];
|
$items = [];
|
||||||
foreach ($videos as $video) {
|
$profiles = [];
|
||||||
$items[] = $video->getApiStructure($this->getUser());
|
$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) [
|
return (object) [
|
||||||
|
|
|
@ -20,7 +20,7 @@ use openvk\Web\Models\Repositories\Audios as AudiosRepo;
|
||||||
|
|
||||||
final class Wall extends VKAPIRequestHandler
|
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();
|
$this->requireUser();
|
||||||
|
|
||||||
|
@ -86,6 +86,8 @@ final class Wall extends VKAPIRequestHandler
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$iteratorv = iterator_to_array($iteratorv);
|
||||||
|
|
||||||
foreach($iteratorv as $post) {
|
foreach($iteratorv as $post) {
|
||||||
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
$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
|
$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) {
|
if($extended == 1) {
|
||||||
$profiles = array_unique($profiles);
|
$profiles = array_unique($profiles);
|
||||||
$groups = array_unique($groups);
|
$groups = array_unique($groups);
|
||||||
|
@ -284,12 +300,16 @@ final class Wall extends VKAPIRequestHandler
|
||||||
|
|
||||||
foreach($psts as $pst) {
|
foreach($psts as $pst) {
|
||||||
$id = explode("_", $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 && !$post->isDeleted()) {
|
||||||
if(!$post->canBeViewedBy($this->getUser()))
|
if(!$post->canBeViewedBy($this->getUser()))
|
||||||
continue;
|
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();
|
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||||
$attachments = [];
|
$attachments = [];
|
||||||
$repost = []; // чел высрал семь сигарет 😳 помянем 🕯
|
$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->requireUser();
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
@ -551,7 +571,17 @@ final class Wall extends VKAPIRequestHandler
|
||||||
if($signed == 1)
|
if($signed == 1)
|
||||||
$flags |= 0b01000000;
|
$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.");
|
$this->fail(100, "Required parameter 'message' missing.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -569,7 +599,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
} catch(\Throwable) {}
|
} catch(\Throwable) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2)
|
if($should_be_suggested)
|
||||||
$post->setSuggested(1);
|
$post->setSuggested(1);
|
||||||
|
|
||||||
$post->save();
|
$post->save();
|
||||||
|
@ -577,134 +607,70 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$this->fail(100, "One of the parameters specified was missing or invalid");
|
$this->fail(100, "One of the parameters specified was missing or invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO use parseAttachments
|
foreach($final_attachments as $attachment) {
|
||||||
if(!empty($attachments)) {
|
$post->attach($attachment);
|
||||||
$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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($wall > 0 && $wall !== $this->user->identity->getId())
|
if($wall > 0 && $wall !== $this->user->identity->getId())
|
||||||
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
(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()];
|
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->requireUser();
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
$postArray;
|
$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");
|
$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]);
|
$parsed_attachments = parseAttachments($attachments, ['photo', 'video', 'note', 'audio']);
|
||||||
if(!$post || $post->isDeleted()) $this->fail(100, "One of the parameters specified was missing or invalid");
|
$final_attachments = [];
|
||||||
|
foreach($parsed_attachments as $attachment) {
|
||||||
if(!$post->canBeViewedBy($this->getUser()))
|
if($attachment && !$attachment->isDeleted() && $attachment->canBeViewedBy($this->getUser()) &&
|
||||||
$this->fail(15, "Access denied");
|
!(method_exists($attachment, 'getVoters') && $attachment->getOwner()->getId() != $this->getUser()->getId())) {
|
||||||
|
$final_attachments[] = $attachment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$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 = new Post;
|
||||||
$nPost->setOwner($this->user->getId());
|
$nPost->setOwner($this->user->getId());
|
||||||
|
|
||||||
if($group_id > 0) {
|
if($group_id > 0) {
|
||||||
$club = (new ClubsRepo)->get($group_id);
|
$club = (new ClubsRepo)->get($group_id);
|
||||||
if(!$club)
|
if(!$club)
|
||||||
$this->fail(42, "Invalid group");
|
$this->fail(42, "Invalid group");
|
||||||
|
|
||||||
if(!$club->canBeModifiedBy($this->user))
|
if(!$club->canBeModifiedBy($this->user))
|
||||||
$this->fail(16, "Access to group denied");
|
$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 {
|
} else {
|
||||||
$nPost->setWall($this->user->getId());
|
$nPost->setWall($this->user->getId());
|
||||||
}
|
}
|
||||||
|
@ -712,16 +678,27 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$nPost->setContent($message);
|
$nPost->setContent($message);
|
||||||
$nPost->setApi_Source_Name($this->getPlatform());
|
$nPost->setApi_Source_Name($this->getPlatform());
|
||||||
$nPost->save();
|
$nPost->save();
|
||||||
$nPost->attach($post);
|
|
||||||
|
$nPost->attach($repost_entity);
|
||||||
if($post->getOwner(false)->getId() !== $this->user->getId() && !($post->getOwner() instanceof Club))
|
|
||||||
(new RepostNotification($post->getOwner(false), $post, $this->user))->emit();
|
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) [
|
return (object) [
|
||||||
"success" => 1, // 👍
|
"success" => 1, // 👍
|
||||||
"post_id" => $nPost->getVirtualId(),
|
"post_id" => $nPost->getVirtualId(),
|
||||||
"reposts_count" => $post->getRepostCount(),
|
"pretty_id" => $nPost->getPrettyId(),
|
||||||
"likes_count" => $post->getLikesCount()
|
"reposts_count" => $repost_count,
|
||||||
|
"likes_count" => $repost_entity->getLikesCount()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,7 +744,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"date" => $comment->getPublicationTime()->timestamp(),
|
"date" => $comment->getPublicationTime()->timestamp(),
|
||||||
"text" => $comment->getText(false),
|
"text" => $comment->getText(false),
|
||||||
"post_id" => $post->getVirtualId(),
|
"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" => [],
|
"parents_stack" => [],
|
||||||
"attachments" => $attachments,
|
"attachments" => $attachments,
|
||||||
"thread" => [
|
"thread" => [
|
||||||
|
@ -833,6 +810,13 @@ final class Wall extends VKAPIRequestHandler
|
||||||
foreach($comment->getChildren() as $attachment) {
|
foreach($comment->getChildren() as $attachment) {
|
||||||
if($attachment instanceof \openvk\Web\Models\Entities\Photo) {
|
if($attachment instanceof \openvk\Web\Models\Entities\Photo) {
|
||||||
$attachments[] = $this->getApiPhoto($attachment);
|
$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) {
|
} elseif($attachment instanceof \openvk\Web\Models\Entities\Audio) {
|
||||||
$attachments[] = [
|
$attachments[] = [
|
||||||
"type" => "audio",
|
"type" => "audio",
|
||||||
|
@ -847,7 +831,7 @@ final class Wall extends VKAPIRequestHandler
|
||||||
"date" => $comment->getPublicationTime()->timestamp(),
|
"date" => $comment->getPublicationTime()->timestamp(),
|
||||||
"text" => $comment->getText(false),
|
"text" => $comment->getText(false),
|
||||||
"post_id" => $comment->getTarget()->getVirtualId(),
|
"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" => [],
|
"parents_stack" => [],
|
||||||
"attachments" => $attachments,
|
"attachments" => $attachments,
|
||||||
"likes" => [
|
"likes" => [
|
||||||
|
@ -899,7 +883,16 @@ final class Wall extends VKAPIRequestHandler
|
||||||
if($post->getTargetWall() < 0)
|
if($post->getTargetWall() < 0)
|
||||||
$club = (new ClubsRepo)->get(abs($post->getTargetWall()));
|
$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.");
|
$this->fail(100, "Required parameter 'message' missing.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -920,55 +913,8 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$this->fail(1, "ошибка про то что коммент большой слишком");
|
$this->fail(1, "ошибка про то что коммент большой слишком");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($attachments)) {
|
foreach($final_attachments as $attachment) {
|
||||||
$attachmentsArr = explode(",", $attachments);
|
$comment->attach($attachment);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($post->getOwner()->getId() !== $this->user->getId())
|
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->requireUser();
|
||||||
$this->willExecuteWriteAction();
|
$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())
|
if(!$post || $post->isDeleted())
|
||||||
$this->fail(102, "Invalid post");
|
$this->fail(102, "Invalid post");
|
||||||
|
@ -1031,36 +990,43 @@ final class Wall extends VKAPIRequestHandler
|
||||||
if(!$post->canBeEditedBy($this->getUser()))
|
if(!$post->canBeEditedBy($this->getUser()))
|
||||||
$this->fail(7, "Access to editing denied");
|
$this->fail(7, "Access to editing denied");
|
||||||
|
|
||||||
if(!empty($message))
|
if(!empty($message) || (empty($message) && sizeof($final_attachments) > 0))
|
||||||
$post->setContent($message);
|
$post->setContent($message);
|
||||||
|
|
||||||
$post->setEdited(time());
|
$post->setEdited(time());
|
||||||
if(!is_null($copyright) && !empty($copyright)) {
|
if(!is_null($copyright) && !empty($copyright)) {
|
||||||
try {
|
if($copyright == 'remove') {
|
||||||
$post->setSource($copyright);
|
$post->resetSource();
|
||||||
} catch(\Throwable) {}
|
} 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);
|
$post->save(true);
|
||||||
|
|
||||||
# todo добавить такое в веб версию
|
if($attachments == 'remove' || sizeof($final_attachments) > 0) {
|
||||||
if(!empty($attachments)) {
|
foreach($post->getChildren() as $att) {
|
||||||
$attachs = parseAttachments($attachments);
|
if(!($att instanceof Post)) {
|
||||||
$newAttachmentsCount = sizeof($attachs);
|
$post->detach($att);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$postsAttachments = iterator_to_array($post->getChildren());
|
foreach($final_attachments as $attachment) {
|
||||||
|
$post->attach($attachment);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1072,8 +1038,16 @@ final class Wall extends VKAPIRequestHandler
|
||||||
$this->willExecuteWriteAction();
|
$this->willExecuteWriteAction();
|
||||||
|
|
||||||
$comment = (new CommentsRepo)->get($comment_id);
|
$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.");
|
$this->fail(100, "Required parameter 'message' missing.");
|
||||||
|
|
||||||
if(!$comment || $comment->isDeleted())
|
if(!$comment || $comment->isDeleted())
|
||||||
|
@ -1082,29 +1056,16 @@ final class Wall extends VKAPIRequestHandler
|
||||||
if(!$comment->canBeEditedBy($this->getUser()))
|
if(!$comment->canBeEditedBy($this->getUser()))
|
||||||
$this->fail(15, "Access to editing comment denied");
|
$this->fail(15, "Access to editing comment denied");
|
||||||
|
|
||||||
if(!empty($message))
|
if(!empty($message) || (empty($message) && sizeof($final_attachments) > 0))
|
||||||
$comment->setContent($message);
|
$comment->setContent($message);
|
||||||
|
|
||||||
$comment->setEdited(time());
|
$comment->setEdited(time());
|
||||||
$comment->save(true);
|
$comment->save(true);
|
||||||
|
|
||||||
if(!empty($attachments)) {
|
|
||||||
$attachs = parseAttachments($attachments);
|
|
||||||
$newAttachmentsCount = sizeof($attachs);
|
|
||||||
|
|
||||||
$postsAttachments = iterator_to_array($comment->getChildren());
|
if(sizeof($final_attachments) > 0) {
|
||||||
|
$comment->unwire();
|
||||||
if(sizeof($postsAttachments) >= 10)
|
foreach($final_attachments as $attachment) {
|
||||||
$this->fail(15, "Post have too many attachments");
|
$comment->attach($attachment);
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ class Album extends MediaCollection
|
||||||
$res = (object) [];
|
$res = (object) [];
|
||||||
|
|
||||||
$res->id = $this->getPrettyId();
|
$res->id = $this->getPrettyId();
|
||||||
|
$res->vid = $this->getId();
|
||||||
$res->thumb_id = !is_null($this->getCoverPhoto()) ? $this->getCoverPhoto()->getPrettyId() : 0;
|
$res->thumb_id = !is_null($this->getCoverPhoto()) ? $this->getCoverPhoto()->getPrettyId() : 0;
|
||||||
$res->owner_id = $this->getOwner()->getId();
|
$res->owner_id = $this->getOwner()->getId();
|
||||||
$res->title = $this->getName();
|
$res->title = $this->getName();
|
||||||
|
|
|
@ -39,7 +39,7 @@ class BannedLink extends RowModel
|
||||||
|
|
||||||
function getRegexpRule(): string
|
function getRegexpRule(): string
|
||||||
{
|
{
|
||||||
return addslashes("/" . $this->getDomain() . $this->getRawRegexp() . "/");
|
return "/^" . $this->getDomain() . "\/" . $this->getRawRegexp() . "$/i";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRawRegexp(): string
|
function getRawRegexp(): string
|
||||||
|
|
|
@ -308,7 +308,7 @@ class Photo extends Media
|
||||||
$res->date = $res->created = $this->getPublicationTime()->timestamp();
|
$res->date = $res->created = $this->getPublicationTime()->timestamp();
|
||||||
|
|
||||||
if($photo_sizes) {
|
if($photo_sizes) {
|
||||||
$res->sizes = $this->getVkApiSizes();
|
$res->sizes = array_values($this->getVkApiSizes());
|
||||||
$res->src_small = $res->photo_75 = $this->getURLBySizeId("miniscule");
|
$res->src_small = $res->photo_75 = $this->getURLBySizeId("miniscule");
|
||||||
$res->src = $res->photo_130 = $this->getURLBySizeId("tiny");
|
$res->src = $res->photo_130 = $this->getURLBySizeId("tiny");
|
||||||
$res->src_big = $res->photo_604 = $this->getURLBySizeId("normal");
|
$res->src_big = $res->photo_604 = $this->getURLBySizeId("normal");
|
||||||
|
|
|
@ -103,6 +103,11 @@ class Post extends Postable
|
||||||
$this->stateChanges("source", $source);
|
$this->stateChanges("source", $source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetSource()
|
||||||
|
{
|
||||||
|
$this->stateChanges("source", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
function getVkApiCopyright(): object
|
function getVkApiCopyright(): object
|
||||||
{
|
{
|
||||||
return (object)[
|
return (object)[
|
||||||
|
@ -368,6 +373,47 @@ class Post extends Postable
|
||||||
|
|
||||||
return $user->getId() == $this->getOwner(false)->getId();
|
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;
|
use Traits\TRichText;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,8 +134,13 @@ class Report extends RowModel
|
||||||
|
|
||||||
function getContentName(): string
|
function getContentName(): string
|
||||||
{
|
{
|
||||||
if (method_exists($this->getContentObject(), "getCanonicalName"))
|
$content_object = $this->getContentObject();
|
||||||
return $this->getContentObject()->getCanonicalName();
|
if(!$content_object) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method_exists($content_object, "getCanonicalName"))
|
||||||
|
return $content_object->getCanonicalName();
|
||||||
|
|
||||||
return $this->getContentType() . " #" . $this->getContentId();
|
return $this->getContentType() . " #" . $this->getContentId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Models\Entities\Traits;
|
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 openvk\Web\Util\Makima\Makima;
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ trait TAttachmentHost
|
||||||
if($h < 0)
|
if($h < 0)
|
||||||
$h = $w;
|
$h = $w;
|
||||||
|
|
||||||
$children = $this->getChildren();
|
$children = iterator_to_array($this->getChildren());
|
||||||
$skipped = $photos = $result = [];
|
$skipped = $photos = $result = [];
|
||||||
foreach($children as $child) {
|
foreach($children as $child) {
|
||||||
if($child instanceof Photo) {
|
if($child instanceof Photo || $child instanceof Video && $child->getDimensions()) {
|
||||||
$photos[] = $child;
|
$photos[] = $child;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,23 @@ class Video extends Media
|
||||||
if(sizeof($durations[1]) === 0)
|
if(sizeof($durations[1]) === 0)
|
||||||
throw new \DomainException("$filename does not contain any meaningful video streams");
|
throw new \DomainException("$filename does not contain any meaningful video streams");
|
||||||
|
|
||||||
foreach($durations[1] as $duration)
|
$length = 0;
|
||||||
if(floatval($duration) < 1.0)
|
foreach($durations[1] as $duration) {
|
||||||
|
$duration = floatval($duration);
|
||||||
|
if($duration < 1.0)
|
||||||
throw new \DomainException("$filename does not contain any meaningful video streams");
|
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 {
|
try {
|
||||||
if(!is_dir($dirId = dirname($this->pathFromHash($hash))))
|
if(!is_dir($dirId = dirname($this->pathFromHash($hash))))
|
||||||
|
@ -118,6 +132,7 @@ class Video extends Media
|
||||||
function getApiStructure(?User $user = NULL): object
|
function getApiStructure(?User $user = NULL): object
|
||||||
{
|
{
|
||||||
$fromYoutube = $this->getType() == Video::TYPE_EMBED;
|
$fromYoutube = $this->getType() == Video::TYPE_EMBED;
|
||||||
|
$dimensions = $this->getDimensions();
|
||||||
$res = (object)[
|
$res = (object)[
|
||||||
"type" => "video",
|
"type" => "video",
|
||||||
"video" => [
|
"video" => [
|
||||||
|
@ -130,7 +145,7 @@ class Video extends Media
|
||||||
"comments" => $this->getCommentsCount(),
|
"comments" => $this->getCommentsCount(),
|
||||||
"date" => $this->getPublicationTime()->timestamp(),
|
"date" => $this->getPublicationTime()->timestamp(),
|
||||||
"description" => $this->getDescription(),
|
"description" => $this->getDescription(),
|
||||||
"duration" => 0, // я хуй знает как получить длину видео
|
"duration" => $this->getLength(),
|
||||||
"image" => [
|
"image" => [
|
||||||
[
|
[
|
||||||
"url" => $this->getThumbnailURL(),
|
"url" => $this->getThumbnailURL(),
|
||||||
|
@ -139,8 +154,8 @@ class Video extends Media
|
||||||
"with_padding" => 1
|
"with_padding" => 1
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"width" => 640,
|
"width" => $dimensions ? $dimensions[0] : 640,
|
||||||
"height" => 480,
|
"height" => $dimensions ? $dimensions[1] : 480,
|
||||||
"id" => $this->getVirtualId(),
|
"id" => $this->getVirtualId(),
|
||||||
"owner_id" => $this->getOwner()->getId(),
|
"owner_id" => $this->getOwner()->getId(),
|
||||||
"user_id" => $this->getOwner()->getId(),
|
"user_id" => $this->getOwner()->getId(),
|
||||||
|
@ -155,6 +170,7 @@ class Video extends Media
|
||||||
"repeat" => 0,
|
"repeat" => 0,
|
||||||
"type" => "video",
|
"type" => "video",
|
||||||
"views" => 0,
|
"views" => 0,
|
||||||
|
"is_processed" => $this->isProcessed(),
|
||||||
"reposts" => [
|
"reposts" => [
|
||||||
"count" => 0,
|
"count" => 0,
|
||||||
"user_reposted" => 0
|
"user_reposted" => 0
|
||||||
|
@ -224,6 +240,74 @@ class Video extends Media
|
||||||
|
|
||||||
return $video;
|
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
|
function canBeViewedBy(?User $user = NULL): bool
|
||||||
{
|
{
|
||||||
|
@ -248,7 +332,7 @@ class Video extends Media
|
||||||
$res->owner_id = $this->getOwner()->getId();
|
$res->owner_id = $this->getOwner()->getId();
|
||||||
$res->title = $this->getName();
|
$res->title = $this->getName();
|
||||||
$res->description = $this->getDescription();
|
$res->description = $this->getDescription();
|
||||||
$res->duration = "22";
|
$res->duration = $this->getLength();
|
||||||
$res->link = "/video".$this->getOwner()->getId()."_".$this->getVirtualId();
|
$res->link = "/video".$this->getOwner()->getId()."_".$this->getVirtualId();
|
||||||
$res->image = $this->getThumbnailURL();
|
$res->image = $this->getThumbnailURL();
|
||||||
$res->date = $this->getPublicationTime()->timestamp();
|
$res->date = $this->getPublicationTime()->timestamp();
|
||||||
|
|
|
@ -3,6 +3,7 @@ namespace openvk\Web\Models\Repositories;
|
||||||
use Chandler\Database\DatabaseConnection as DB;
|
use Chandler\Database\DatabaseConnection as DB;
|
||||||
use Nette\Database\Table\{ActiveRow, Selection};
|
use Nette\Database\Table\{ActiveRow, Selection};
|
||||||
use openvk\Web\Models\Entities\BannedLink;
|
use openvk\Web\Models\Entities\BannedLink;
|
||||||
|
use function Symfony\Component\Translation\t;
|
||||||
|
|
||||||
class BannedLinks
|
class BannedLinks
|
||||||
{
|
{
|
||||||
|
@ -43,7 +44,7 @@ class BannedLinks
|
||||||
|
|
||||||
function isDomainBanned(string $domain): bool
|
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
|
function genLinks($rules): \Traversable
|
||||||
|
@ -57,12 +58,14 @@ class BannedLinks
|
||||||
foreach($links as $link)
|
foreach($links as $link)
|
||||||
if (preg_match($link->getRegexpRule(), $uri))
|
if (preg_match($link->getRegexpRule(), $uri))
|
||||||
yield $link->getId();
|
yield $link->getId();
|
||||||
|
else if ($this->isDomainBanned($link->getDomain()))
|
||||||
|
yield $link->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
function check(string $url): ?array
|
function check(string $url): ?array
|
||||||
{
|
{
|
||||||
$uri = strstr(str_replace(["https://", "http://"], "", $url), "/", true);
|
$uri = str_replace(["https://", "http://"], "", $url);
|
||||||
$domain = str_replace("www.", "", $uri);
|
$domain = explode("/", str_replace("www.", "", $uri))[0];
|
||||||
$rules = $this->getByDomain($domain);
|
$rules = $this->getByDomain($domain);
|
||||||
|
|
||||||
if (is_null($rules))
|
if (is_null($rules))
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Photos
|
||||||
return new Photo($photo);
|
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;
|
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
||||||
$photos = $this->photos->where([
|
$photos = $this->photos->where([
|
||||||
|
@ -41,7 +41,7 @@ class Photos
|
||||||
"deleted" => 0
|
"deleted" => 0
|
||||||
])->order("id DESC");
|
])->order("id DESC");
|
||||||
|
|
||||||
foreach($photos->page($page, $perPage) as $photo) {
|
foreach($photos->limit($limit, $offset) as $photo) {
|
||||||
yield new Photo($photo);
|
yield new Photo($photo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,13 @@ class Videos
|
||||||
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
||||||
foreach($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0])->page($page, $perPage)->order("created DESC") as $video)
|
foreach($this->videos->where("owner", $user->getId())->where(["deleted" => 0, "unlisted" => 0])->page($page, $perPage)->order("created DESC") as $video)
|
||||||
yield new Video($video);
|
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
|
function getUserVideosCount(User $user): int
|
||||||
|
@ -49,7 +56,7 @@ class Videos
|
||||||
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream
|
||||||
{
|
{
|
||||||
$query = "%$query%";
|
$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';
|
$order_str = 'id';
|
||||||
|
|
||||||
switch($order['type']) {
|
switch($order['type']) {
|
||||||
|
|
|
@ -481,7 +481,7 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
if ($link) {
|
if ($link) {
|
||||||
$link->setDomain($new_domain ?? $this->postParam("link"));
|
$link->setDomain($new_domain ?? $this->postParam("link"));
|
||||||
$link->setReason($new_reason);
|
$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();
|
$link->save();
|
||||||
} else {
|
} else {
|
||||||
if (!$new_domain)
|
if (!$new_domain)
|
||||||
|
@ -490,7 +490,7 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
$link = new BannedLink;
|
$link = new BannedLink;
|
||||||
$link->setDomain($new_domain);
|
$link->setDomain($new_domain);
|
||||||
$link->setReason($new_reason);
|
$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->setInitiator($this->user->identity->getId());
|
||||||
$link->save();
|
$link->save();
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderList(?int $owner = NULL, ?string $mode = "list"): void
|
function renderList(?int $owner = NULL, ?string $mode = "list"): void
|
||||||
{
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
$this->template->_template = "Audio/List.xml";
|
$this->template->_template = "Audio/List.xml";
|
||||||
$page = (int)($this->queryParam("p") ?? 1);
|
$page = (int)($this->queryParam("p") ?? 1);
|
||||||
$audios = [];
|
$audios = [];
|
||||||
|
@ -501,6 +502,7 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
|
|
||||||
function renderPlaylist(int $owner_id, int $virtual_id): void
|
function renderPlaylist(int $owner_id, int $virtual_id): void
|
||||||
{
|
{
|
||||||
|
$this->assertUserLoggedIn();
|
||||||
$playlist = $this->audios->getPlaylistByOwnerAndVID($owner_id, $virtual_id);
|
$playlist = $this->audios->getPlaylistByOwnerAndVID($owner_id, $virtual_id);
|
||||||
$page = (int)($this->queryParam("p") ?? 1);
|
$page = (int)($this->queryParam("p") ?? 1);
|
||||||
if (!$playlist || $playlist->isDeleted())
|
if (!$playlist || $playlist->isDeleted())
|
||||||
|
|
|
@ -7,7 +7,7 @@ final class AwayPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
function renderAway(): void
|
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 (OPENVK_ROOT_CONF["openvk"]["preferences"]["susLinks"]["warnings"])
|
||||||
if (sizeof($checkBanEntries) > 0)
|
if (sizeof($checkBanEntries) > 0)
|
||||||
$this->pass("openvk!Away->view", $checkBanEntries[0]);
|
$this->pass("openvk!Away->view", $checkBanEntries[0]);
|
||||||
|
|
|
@ -27,7 +27,12 @@ final class CommentPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("error"), tr("forbidden"));
|
$this->flashFail("err", tr("error"), tr("forbidden"));
|
||||||
|
|
||||||
if(!is_null($this->user)) $comment->toggleLike($this->user->identity);
|
if(!is_null($this->user)) $comment->toggleLike($this->user->identity);
|
||||||
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
$this->returnJson([
|
||||||
|
'success' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$this->redirect($_SERVER["HTTP_REFERER"]);
|
$this->redirect($_SERVER["HTTP_REFERER"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,64 +75,24 @@ final class CommentPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_when_publishing_comment_description"));
|
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_when_publishing_comment_description"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$photos = [];
|
|
||||||
if(!empty($this->postParam("photos"))) {
|
|
||||||
$un = rtrim($this->postParam("photos"), ",");
|
|
||||||
$arr = explode(",", $un);
|
|
||||||
|
|
||||||
if(sizeof($arr) < 11) {
|
$horizontal_attachments = [];
|
||||||
foreach($arr as $dat) {
|
$vertical_attachments = [];
|
||||||
$ids = explode("_", $dat);
|
if(!empty($this->postParam("horizontal_attachments"))) {
|
||||||
$photo = (new Photos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
$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) {
|
||||||
if(!$photo || $photo->isDeleted())
|
$horizontal_attachments = parseAttachments($horizontal_attachments_array, ['photo', 'video']);
|
||||||
continue;
|
|
||||||
|
|
||||||
$photos[] = $photo;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$videos = [];
|
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(!empty($this->postParam("videos"))) {
|
if(sizeof($vertical_attachments_array) > 0) {
|
||||||
$un = rtrim($this->postParam("videos"), ",");
|
$vertical_attachments = parseAttachments($vertical_attachments_array, ['audio', 'note']);
|
||||||
$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)
|
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"));
|
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_empty"));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -143,15 +108,21 @@ final class CommentPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_too_big"));
|
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_too_big"));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($photos as $photo)
|
foreach($horizontal_attachments as $horizontal_attachment) {
|
||||||
$comment->attach($photo);
|
if(!$horizontal_attachment || $horizontal_attachment->isDeleted() || !$horizontal_attachment->canBeViewedBy($this->user->identity)) {
|
||||||
|
continue;
|
||||||
if(sizeof($videos) > 0)
|
}
|
||||||
foreach($videos as $vid)
|
|
||||||
$comment->attach($vid);
|
|
||||||
|
|
||||||
foreach($audios as $audio)
|
$comment->attach($horizontal_attachment);
|
||||||
$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($entity->getOwner()->getId() !== $this->user->identity->getId())
|
||||||
if(($owner = $entity->getOwner()) instanceof User)
|
if(($owner = $entity->getOwner()) instanceof User)
|
||||||
|
|
|
@ -121,9 +121,9 @@ final class InternalAPIPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
|
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
|
||||||
{
|
{
|
||||||
$response[] = [
|
$response[$attachment->getPrettyId()] = [
|
||||||
"url" => $attachment->getURLBySizeId('normal'),
|
"url" => $attachment->getURLBySizeId('larger'),
|
||||||
"id" => $attachment->getPrettyId()
|
"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;
|
$userValidated = 1;
|
||||||
$cacheTime = 0; # Force no cache
|
$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->setOnline(time());
|
||||||
$this->user->identity->setClient_name(NULL);
|
$this->user->identity->setClient_name(NULL);
|
||||||
$this->user->identity->save(false);
|
$this->user->identity->save(false);
|
||||||
|
|
|
@ -176,6 +176,7 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
$this->template->cCount = $photo->getCommentsCount();
|
$this->template->cCount = $photo->getCommentsCount();
|
||||||
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);
|
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);
|
||||||
$this->template->comments = iterator_to_array($photo->getComments($this->template->cPage));
|
$this->template->comments = iterator_to_array($photo->getComments($this->template->cPage));
|
||||||
|
$this->template->owner = $photo->getOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAbsolutePhoto($id): void
|
function renderAbsolutePhoto($id): void
|
||||||
|
@ -287,7 +288,8 @@ final class PhotosPresenter extends OpenVKPresenter
|
||||||
"id" => $photo->getId(),
|
"id" => $photo->getId(),
|
||||||
"vid" => $photo->getVirtualId(),
|
"vid" => $photo->getVirtualId(),
|
||||||
"owner" => $photo->getOwner()->getId(),
|
"owner" => $photo->getOwner()->getId(),
|
||||||
"link" => $photo->getURL()
|
"link" => $photo->getURL(),
|
||||||
|
"pretty_id" => $photo->getPrettyId(),
|
||||||
];
|
];
|
||||||
} catch(ISE $ex) {
|
} catch(ISE $ex) {
|
||||||
$name = $album->getName();
|
$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->flash("succ", tr("photo_is_deleted"), tr("photo_is_deleted_desc"));
|
||||||
$this->redirect($redirect);
|
$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
|
final class VKAPIPresenter extends OpenVKPresenter
|
||||||
{
|
{
|
||||||
|
protected $silent = true;
|
||||||
private function logRequest(string $object, string $method): void
|
private function logRequest(string $object, string $method): void
|
||||||
{
|
{
|
||||||
$date = date(DATE_COOKIE);
|
$date = date(DATE_COOKIE);
|
||||||
|
@ -222,9 +223,13 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
if(!is_callable([$handler, $method]))
|
if(!is_callable([$handler, $method]))
|
||||||
$this->badMethod($object, $method);
|
$this->badMethod($object, $method);
|
||||||
|
|
||||||
|
$has_rss = false;
|
||||||
$route = new \ReflectionMethod($handler, $method);
|
$route = new \ReflectionMethod($handler, $method);
|
||||||
$params = [];
|
$params = [];
|
||||||
foreach($route->getParameters() as $parameter) {
|
foreach($route->getParameters() as $parameter) {
|
||||||
|
if($parameter->getName() == 'rss')
|
||||||
|
$has_rss = true;
|
||||||
|
|
||||||
$val = $this->requestParam($parameter->getName());
|
$val = $this->requestParam($parameter->getName());
|
||||||
if(is_null($val)) {
|
if(is_null($val)) {
|
||||||
if($parameter->allowsNull())
|
if($parameter->allowsNull())
|
||||||
|
@ -260,15 +265,27 @@ final class VKAPIPresenter extends OpenVKPresenter
|
||||||
$this->fail($ex->getCode(), $ex->getMessage(), $object, $method);
|
$this->fail($ex->getCode(), $ex->getMessage(), $object, $method);
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = json_encode([
|
$result = NULL;
|
||||||
"response" => $res,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if($callback) {
|
if($this->queryParam("rss") == '1' && $has_rss) {
|
||||||
$result = $callback . '(' . $result . ')';
|
$feed = new \Bhaktaraz\RSSGenerator\Feed();
|
||||||
header('Content-Type: application/javascript');
|
$res->appendTo($feed);
|
||||||
} else
|
|
||||||
header("Content-Type: application/json");
|
$result = strval($feed);
|
||||||
|
|
||||||
|
header("Content-Type: application/rss+xml;charset=UTF-8");
|
||||||
|
} else {
|
||||||
|
$result = json_encode([
|
||||||
|
"response" => $res,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if($callback) {
|
||||||
|
$result = $callback . '(' . $result . ')';
|
||||||
|
header('Content-Type: application/javascript');
|
||||||
|
} else {
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$size = strlen($result);
|
$size = strlen($result);
|
||||||
header("Content-Length: $size");
|
header("Content-Length: $size");
|
||||||
|
|
|
@ -62,6 +62,7 @@ final class VideosPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("error"), tr("video_uploads_disabled"));
|
$this->flashFail("err", tr("error"), tr("video_uploads_disabled"));
|
||||||
|
|
||||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
$is_ajax = (int)($this->postParam('ajax') ?? '0') == 1;
|
||||||
if(!empty($this->postParam("name"))) {
|
if(!empty($this->postParam("name"))) {
|
||||||
$video = new Video;
|
$video = new Video;
|
||||||
$video->setOwner($this->user->id);
|
$video->setOwner($this->user->id);
|
||||||
|
@ -75,18 +76,29 @@ final class VideosPresenter extends OpenVKPresenter
|
||||||
else if(!empty($this->postParam("link")))
|
else if(!empty($this->postParam("link")))
|
||||||
$video->setLink($this->postParam("link"));
|
$video->setLink($this->postParam("link"));
|
||||||
else
|
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) {
|
} 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) {
|
} 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();
|
$video->save();
|
||||||
|
|
||||||
|
if($is_ajax) {
|
||||||
|
$object = $video->getApiStructure();
|
||||||
|
$this->returnJson([
|
||||||
|
'payload' => $object->video,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$this->redirect("/video" . $video->getPrettyId());
|
$this->redirect("/video" . $video->getPrettyId());
|
||||||
} else {
|
} else {
|
||||||
$this->flashFail("err", tr("error_video"), tr("no_name_error"));
|
$this->flashFail("err", tr("error_video"), tr("no_name_error"), 10, $is_ajax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +163,13 @@ final class VideosPresenter extends OpenVKPresenter
|
||||||
if(!is_null($this->user)) {
|
if(!is_null($this->user)) {
|
||||||
$video->toggleLike($this->user->identity);
|
$video->toggleLike($this->user->identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->returnJson(["success" => true]);
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
$this->returnJson([
|
||||||
|
'success' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redirect("$_SERVER[HTTP_REFERER]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,25 +282,22 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
if($this->postParam("force_sign") === "on")
|
if($this->postParam("force_sign") === "on")
|
||||||
$flags |= 0b01000000;
|
$flags |= 0b01000000;
|
||||||
|
|
||||||
$photos = [];
|
$horizontal_attachments = [];
|
||||||
|
$vertical_attachments = [];
|
||||||
if(!empty($this->postParam("photos"))) {
|
if(!empty($this->postParam("horizontal_attachments"))) {
|
||||||
$un = rtrim($this->postParam("photos"), ",");
|
$horizontal_attachments_array = array_slice(explode(",", $this->postParam("horizontal_attachments")), 0, OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]);
|
||||||
$arr = explode(",", $un);
|
if(sizeof($horizontal_attachments_array) > 0) {
|
||||||
|
$horizontal_attachments = parseAttachments($horizontal_attachments_array, ['photo', 'video']);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
try {
|
||||||
$poll = NULL;
|
$poll = NULL;
|
||||||
$xml = $this->postParam("poll");
|
$xml = $this->postParam("poll");
|
||||||
|
@ -312,61 +309,10 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("failed_to_publish_post"), "Poll format invalid");
|
$this->flashFail("err", tr("failed_to_publish_post"), "Poll format invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
$note = NULL;
|
if(empty($this->postParam("text")) && sizeof($horizontal_attachments) < 1 && sizeof($vertical_attachments) < 1 && !$poll)
|
||||||
|
|
||||||
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)
|
|
||||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big"));
|
$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 {
|
try {
|
||||||
$post = new Post;
|
$post = new Post;
|
||||||
$post->setOwner($this->user->id);
|
$post->setOwner($this->user->id);
|
||||||
|
@ -383,7 +329,7 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
} catch(\Throwable) {}
|
} catch(\Throwable) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2)
|
if($should_be_suggested)
|
||||||
$post->setSuggested(1);
|
$post->setSuggested(1);
|
||||||
|
|
||||||
$post->save();
|
$post->save();
|
||||||
|
@ -391,21 +337,24 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_too_big"));
|
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_too_big"));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($photos as $photo)
|
foreach($horizontal_attachments as $horizontal_attachment) {
|
||||||
$post->attach($photo);
|
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))
|
if(!is_null($poll))
|
||||||
$post->attach($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())
|
if($wall > 0 && $wall !== $this->user->identity->getId())
|
||||||
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
||||||
|
@ -414,9 +363,7 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
if($wall > 0)
|
if($wall > 0)
|
||||||
$excludeMentions[] = $wall;
|
$excludeMentions[] = $wall;
|
||||||
|
|
||||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) {
|
if(!$should_be_suggested) {
|
||||||
# Чтобы не было упоминаний из предложки
|
|
||||||
} else {
|
|
||||||
$mentions = iterator_to_array($post->resolveMentions($excludeMentions));
|
$mentions = iterator_to_array($post->resolveMentions($excludeMentions));
|
||||||
|
|
||||||
foreach($mentions as $mentionee)
|
foreach($mentions as $mentionee)
|
||||||
|
@ -424,18 +371,7 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
(new MentionNotification($mentionee, $post, $post->getOwner(), strip_tags($post->getText())))->emit();
|
(new MentionNotification($mentionee, $post, $post->getOwner(), strip_tags($post->getText())))->emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) {
|
if($should_be_suggested) {
|
||||||
$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();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->redirect("/club".$wallOwner->getId()."/suggested");
|
$this->redirect("/club".$wallOwner->getId()."/suggested");
|
||||||
} else {
|
} else {
|
||||||
$this->redirect($wallOwner->getURL());
|
$this->redirect($wallOwner->getURL());
|
||||||
|
@ -486,6 +422,12 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
if(!is_null($this->user)) {
|
if(!is_null($this->user)) {
|
||||||
$post->toggleLike($this->user->identity);
|
$post->toggleLike($this->user->identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
$this->returnJson([
|
||||||
|
'success' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$this->redirect("$_SERVER[HTTP_REFERER]#postGarter=" . $post->getId());
|
$this->redirect("$_SERVER[HTTP_REFERER]#postGarter=" . $post->getId());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
{script "js/node_modules/umbrellajs/umbrella.min.js"}
|
{script "js/node_modules/umbrellajs/umbrella.min.js"}
|
||||||
{script "js/l10n.js"}
|
{script "js/l10n.js"}
|
||||||
{script "js/openvk.cls.js"}
|
{script "js/openvk.cls.js"}
|
||||||
|
{script "js/utils.js"}
|
||||||
{script "js/node_modules/dashjs/dist/dash.all.min.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 src="/assets/packages/static/openvk/js/node_modules/cropperjs/dist/cropper.js" type="module"></script>
|
||||||
{script "js/al_music.js"}
|
{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/border.css"}
|
||||||
{css "js/node_modules/tippy.js/dist/svg-arrow.css"}
|
{css "js/node_modules/tippy.js/dist/svg-arrow.css"}
|
||||||
{css "js/node_modules/tippy.js/themes/light.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/@popperjs/core/dist/umd/popper.min.js"}
|
||||||
{script "js/node_modules/tippy.js/dist/tippy-bundle.umd.min.js"}
|
{script "js/node_modules/tippy.js/dist/tippy-bundle.umd.min.js"}
|
||||||
{script "js/node_modules/handlebars/dist/handlebars.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 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="notifications_global_wrap"></div>
|
||||||
<div class="dimmer"></div>
|
<div class="dimmer">
|
||||||
|
<div id='absolute_territory'></div>
|
||||||
|
</div>
|
||||||
|
<div class="upLeftErrors"></div>
|
||||||
|
|
||||||
<div class="articleView">
|
<div class="articleView">
|
||||||
<a id="articleCloseButton" class="button" href="javascript:void(u('body').removeClass('article'));">{_close}</a>
|
<a id="articleCloseButton" class="button" href="javascript:void(u('body').removeClass('article'));">{_close}</a>
|
||||||
|
@ -361,7 +366,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="ajloader" class="loader">
|
<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>
|
</div>
|
||||||
|
|
||||||
{include "components/cookies.xml"}
|
{include "components/cookies.xml"}
|
||||||
|
@ -424,6 +429,9 @@
|
||||||
window.openvk = {
|
window.openvk = {
|
||||||
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres},
|
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres},
|
||||||
"at_search": {$atSearch ?? false},
|
"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>
|
</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()}">
|
<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" />
|
<audio class="audio" />
|
||||||
|
|
||||||
<div id="miniplayer" class="audioEntry" style="min-height: 39px;">
|
<div id="miniplayer" class="audioEntry">
|
||||||
<div style="display: flex;">
|
<div class='audioEntryWrapper' style="display: flex;" draggable='true'>
|
||||||
<div class="playerButton">
|
<div class="playerButton">
|
||||||
<div class="playIcon"></div>
|
<div class="playIcon"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="status" style="margin-top: 12px;">
|
<div class="status" draggable='false'>
|
||||||
<div class="mediaInfo noOverflow">
|
<div class="mediaInfo noOverflow">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<strong class="performer">
|
<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>
|
</strong>
|
||||||
—
|
—
|
||||||
<span class="title {if !empty($audio->getLyrics())}withLyrics{/if}">{$audio->getTitle()}</span>
|
<span class="title {if !empty($audio->getLyrics())}withLyrics{/if}">{$audio->getTitle()}</span>
|
||||||
|
@ -27,8 +27,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="volume" style="display: flex; flex-direction: column;width:14%;">
|
<div class="volume">
|
||||||
<span class="nobold {if !$hideButtons}hideOnHover{/if}" data-unformatted="{$audio->getLength()}" style="text-align: center;margin-top: 12px;">{$audio->getFormattedLength()}</span>
|
<span class="nobold {if !$hideButtons}hideOnHover{/if}" data-unformatted="{$audio->getLength()}">{$audio->getFormattedLength()}</span>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
{php $hasAudio = isset($thisUser) && $audio->isInLibraryOf($thisUser)}
|
{php $hasAudio = isset($thisUser) && $audio->isInLibraryOf($thisUser)}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="subTracks">
|
<div class="subTracks" draggable='false'>
|
||||||
<div class="lengthTrackWrapper">
|
<div class="lengthTrackWrapper">
|
||||||
<div class="track lengthTrack">
|
<div class="track lengthTrack">
|
||||||
<div class="selectableTrack" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
<div class="selectableTrack" n:attr="style => $isWithdrawn ? 'display: none;' : ''">
|
||||||
|
|
|
@ -168,10 +168,10 @@
|
||||||
{/if}
|
{/if}
|
||||||
{var $canReport = $thisUser->getId() != $club->getOwner()->getId()}
|
{var $canReport = $thisUser->getId() != $club->getOwner()->getId()}
|
||||||
{if $canReport}
|
{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>
|
<script>
|
||||||
function reportVideo() {
|
function reportClub() {
|
||||||
uReportMsgTxt = tr("going_to_report_club");
|
uReportMsgTxt = tr("going_to_report_club");
|
||||||
uReportMsgTxt += "<br/>"+tr("report_question_text");
|
uReportMsgTxt += "<br/>"+tr("report_question_text");
|
||||||
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
|
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
|
||||||
|
|
|
@ -4,76 +4,72 @@
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
{ifset $album}
|
{ifset $album}
|
||||||
<a href="{$album->getOwner()->getURL()}">
|
{var $album_owner = $album->getOwner()}
|
||||||
{$album->getOwner()->getCanonicalName()}
|
<a href="{$album_owner->getURL()}">
|
||||||
|
{$album_owner->getCanonicalName()}
|
||||||
</a>
|
</a>
|
||||||
{if ($album->getOwner() instanceof openvk\Web\Models\Entities\Club)}
|
{if ($album_owner instanceof openvk\Web\Models\Entities\Club)}
|
||||||
» <a href="/albums{$album->getOwner()->getId() * -1}">{_albums}</a>
|
» <a href="/albums{$album_owner->getId() * -1}">{_albums}</a>
|
||||||
{else}
|
{else}
|
||||||
» <a href="/albums{$album->getOwner()->getId()}">{_albums}</a>
|
» <a href="/albums{$album_owner->getId()}">{_albums}</a>
|
||||||
{/if}
|
{/if}
|
||||||
» <a href="/album{$album->getPrettyId()}">{$album->getName()}</a>
|
» <a href="/album{$album->getPrettyId()}">{$album->getName()}</a>
|
||||||
{else}
|
{else}
|
||||||
<a href="{$photo->getOwner()->getURL()}">{$photo->getOwner()->getCanonicalName()}</a>
|
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||||
{/ifset}
|
{/ifset}
|
||||||
» {_photo}
|
» {_photo}
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<center style="margin-bottom: 8pt;">
|
<div class='media-page-wrapper photo-page-wrapper'>
|
||||||
<img src="{$photo->getURLBySizeId('large')}" style="max-width: 80%; max-height: 60vh;" />
|
<div class='photo-page-wrapper-photo'>
|
||||||
</center>
|
<img src="{$photo->getURLBySizeId('large')}" />
|
||||||
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<div style="width: 100%; min-height: 100px;" class="ovk-photo-details">
|
|
||||||
<div style="float: left; min-height: 100px; width: 68%;margin-left: 3px;">
|
|
||||||
{include "../components/comments.xml", comments => $comments, count => $cCount, page => $cPage, model => "photos", parent => $photo, custom_id => 999}
|
|
||||||
</div>
|
</div>
|
||||||
<div style="float:right;min-height: 100px;width: 30%;margin-left: 1px;">
|
|
||||||
<div>
|
<div class='ovk-photo-details'>
|
||||||
<h4>{_information}</h4>
|
<div class='media-page-wrapper-description'>
|
||||||
<span style="color: grey;">{_info_description}:</span>
|
<p n:if='!empty($photo->getDescription())'>{$photo->getDescription()}</p>
|
||||||
{$photo->getDescription() ?? "(" . tr("none") . ")"}<br/>
|
<div class='upload_time'>
|
||||||
<span style="color: grey;">{_info_uploaded_by}:</span>
|
{_info_upload_date}: {$photo->getPublicationTime()}
|
||||||
<a href="{$photo->getOwner()->getURL()}">{$photo->getOwner()->getFullName()}</a><br/>
|
{if isset($thisUser)}
|
||||||
<span style="color: grey;">{_info_upload_date}:</span>
|
|
|
||||||
{$photo->getPublicationTime()}
|
{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>
|
</div>
|
||||||
<br/>
|
|
||||||
<h4>{_actions}</h4>
|
|
||||||
{if isset($thisUser) && $thisUser->getId() != $photo->getOwner()->getId()}
|
|
||||||
{var canReport = true}
|
|
||||||
{/if}
|
|
||||||
<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")], [
|
<hr/>
|
||||||
(function() {
|
|
||||||
res = document.querySelector("#uReportMsgInput").value;
|
<div class="media-page-wrapper-details">
|
||||||
xhr = new XMLHttpRequest();
|
<div class='media-page-wrapper-comments'>
|
||||||
xhr.open("GET", "/report/" + {$photo->getId()} + "?reason=" + res + "&type=photo", true);
|
{include "../components/comments.xml", comments => $comments, count => $cCount, page => $cPage, model => "photos", parent => $photo, custom_id => 999}
|
||||||
xhr.onload = (function() {
|
</div>
|
||||||
if(xhr.responseText.indexOf("reason") === -1)
|
<div class='media-page-wrapper-actions'>
|
||||||
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]);
|
<a href="{$owner->getURL()}" class='media-page-author-block'>
|
||||||
else
|
<img class='cCompactAvatars' src="{$owner->getAvatarURL('miniscule')}">
|
||||||
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]);
|
|
||||||
});
|
<div class='media-page-author-block-name'>
|
||||||
xhr.send(null);
|
<b>{$owner->getCanonicalName()}</b>
|
||||||
}),
|
</div>
|
||||||
Function.noop
|
</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>
|
||||||
</script>
|
<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="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>
|
||||||
</div>
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -325,13 +325,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div style="padding: 5px;">
|
<div style="padding: 5px;">
|
||||||
<div class="ovk-video" n:foreach="$videos as $video">
|
<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
|
<img
|
||||||
src="{$video->getThumbnailURL()}"
|
src="{$video->getThumbnailURL()}"
|
||||||
style="max-width: 170px; max-height: 127px; margin: auto;" />
|
style="max-width: 170px; max-height: 127px; margin: auto;" />
|
||||||
</a>
|
</a>
|
||||||
<div>
|
<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>
|
<span style="font-size: 10px;">{$video->getPublicationTime()} | {_comments} ({$video->getCommentsCount()})</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,91 +11,88 @@
|
||||||
{/block}
|
{/block}
|
||||||
|
|
||||||
{block content}
|
{block content}
|
||||||
<center style="margin-bottom: 8pt;">
|
<div class='media-page-wrapper video-page-wrapper'>
|
||||||
{if $video->getType() === 0}
|
<div class='video-page-wrapper-video'>
|
||||||
<div class="bsdn" data-name="{$video->getName()}" data-author="{$user->getCanonicalName()}">
|
{if $video->getType() === 0}
|
||||||
<video src="{$video->getURL()}"></video>
|
<div class="bsdn" data-name="{$video->getName()}" data-author="{$user->getCanonicalName()}">
|
||||||
</div>
|
<video src="{$video->getURL()}"></video>
|
||||||
{else}
|
|
||||||
{var $driver = $video->getVideoDriver()}
|
|
||||||
{if !$driver}
|
|
||||||
{_unknown_video}
|
|
||||||
{else}
|
|
||||||
{$driver->getEmbed()|noescape}
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</center>
|
|
||||||
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<div style="width: 100%; min-height: 100px;">
|
|
||||||
<div style="float: left; min-height: 100px; width: 68%; margin-right: 2%;" id="comments">
|
|
||||||
{include "../components/comments.xml",
|
|
||||||
comments => $comments,
|
|
||||||
count => $cCount,
|
|
||||||
page => $cPage,
|
|
||||||
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>
|
|
||||||
<br/>
|
|
||||||
<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%;">
|
|
||||||
{_delete}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<a href="/video{$video->getPrettyId()}" class="profile_link" id="videoOpen" data-id="{$video->getId()}" style="display:block;width:96%;">
|
{else}
|
||||||
{_watch_in_window}
|
{var $driver = $video->getVideoDriver()}
|
||||||
</a>
|
{if !$driver}
|
||||||
</div>
|
{_unknown_video}
|
||||||
|
{else}
|
||||||
{if isset($thisUser)}
|
{$driver->getEmbed()|noescape}
|
||||||
{if $thisUser->getId() != $video->getOwner()->getId()}
|
|
||||||
{var canReport = true}
|
|
||||||
{/if}
|
{/if}
|
||||||
{/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>
|
|
||||||
</div>
|
</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 class="media-page-wrapper-details">
|
||||||
|
<div class='media-page-wrapper-comments' id="comments">
|
||||||
|
{include "../components/comments.xml",
|
||||||
|
comments => $comments,
|
||||||
|
count => $cCount,
|
||||||
|
page => $cPage,
|
||||||
|
model => "videos",
|
||||||
|
parent => $video}
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div n:if="isset($thisUser) && $thisUser->getId() === $user->getId()">
|
||||||
|
<a href="/video{$video->getPrettyId()}/edit" class="profile_link" style="display:block;width:96%;">
|
||||||
|
{_edit}
|
||||||
|
</a>
|
||||||
|
<a id='_videoDelete' href="/video{$video->getPrettyId()}/remove" class="profile_link" style="display:block;width:96%;">
|
||||||
|
{_delete}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<a n:if="isset($thisUser)" onclick="javascript:repost({$video->getPrettyId()}, 'video')" class="profile_link" style="display:block;width:96%;">
|
||||||
|
{_share}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{if isset($thisUser)}
|
||||||
|
{if $thisUser->getId() != $video->getOwner()->getId()}
|
||||||
|
{var canReport = true}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<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>
|
</div>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{if $attachment instanceof \openvk\Web\Models\Entities\Photo}
|
{if $attachment instanceof \openvk\Web\Models\Entities\Photo}
|
||||||
{if !$attachment->isDeleted()}
|
{if !$attachment->isDeleted()}
|
||||||
{var $link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
{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 />
|
<img class="media media_makima" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" loading=lazy />
|
||||||
</a>
|
</a>
|
||||||
{else}
|
{else}
|
||||||
|
@ -10,39 +10,50 @@
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
|
||||||
{if $attachment->getType() === 0}
|
{if $tilesCount <= 1}
|
||||||
<div class="bsdn media" data-name="{$attachment->getName()}" data-author="{$attachment->getOwner()->getCanonicalName()}">
|
{if $attachment->getType() === 0}
|
||||||
<video class="media" src="{$attachment->getURL()}"></video>
|
<div class="bsdn media" data-name="{$attachment->getName()}" data-author="{$attachment->getOwner()->getCanonicalName()}">
|
||||||
|
<video class="media" src="{$attachment->getURL()}"></video>
|
||||||
|
</div>
|
||||||
|
{else}
|
||||||
|
{var $driver = $attachment->getVideoDriver()}
|
||||||
|
{if !$driver}
|
||||||
|
<span style="color:red;">{_version_incompatibility}</span>
|
||||||
|
{else}
|
||||||
|
{$driver->getEmbed("100%")|noescape}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="video-wowzer">
|
||||||
|
<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>
|
</div>
|
||||||
{else}
|
{else}
|
||||||
{var $driver = $attachment->getVideoDriver()}
|
<a class='compact_video' id='videoOpen' data-id='{$attachment->getPrettyId()}' href="/video{$attachment->getPrettyId()}">
|
||||||
{if !$driver}
|
<div class='play-button'>
|
||||||
<span style="color:red;">{_version_incompatibility}</span>
|
<div class='play-button-ico'></div>
|
||||||
{else}
|
</div>
|
||||||
{$driver->getEmbed("100%")|noescape}
|
<div class='video-length' n:if="$attachment->getLength() != NULL">
|
||||||
{/if}
|
{$attachment->getFormattedLength()}
|
||||||
{/if}
|
</div>
|
||||||
|
|
||||||
<div class="video-wowzer">
|
<img class="media media_makima" src="{$attachment->getThumbnailURL()}" loading=lazy />
|
||||||
<img src="/assets/packages/static/openvk/img/videoico.png" />
|
</a>
|
||||||
<a href="/video{$attachment->getPrettyId()}" id="videoOpen" data-id="{$attachment->getId()}">{$attachment->getName()}</a>
|
{/if}
|
||||||
</div>
|
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll}
|
||||||
{presenter "openvk!Poll->view", $attachment->getId()}
|
{presenter "openvk!Poll->view", $attachment->getId()}
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Note}
|
{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">
|
<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>
|
||||||
<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 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>
|
||||||
</div>
|
</div>
|
||||||
{else}
|
</div>
|
||||||
<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}
|
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Post}
|
{elseif $attachment instanceof \openvk\Web\Models\Entities\Post}
|
||||||
{php $GLOBALS["_nesAttGloCou"] = (isset($GLOBALS["_nesAttGloCou"]) ? $GLOBALS["_nesAttGloCou"] : 0) + 1}
|
{php $GLOBALS["_nesAttGloCou"] = (isset($GLOBALS["_nesAttGloCou"]) ? $GLOBALS["_nesAttGloCou"] : 0) + 1}
|
||||||
{if $GLOBALS["_nesAttGloCou"] > 2}
|
{if $GLOBALS["_nesAttGloCou"] > 2}
|
||||||
|
@ -51,7 +62,7 @@
|
||||||
{include "post.xml", post => $attachment, compact => true}
|
{include "post.xml", post => $attachment, compact => true}
|
||||||
{/if}
|
{/if}
|
||||||
{elseif $attachment instanceof \openvk\Web\Models\Entities\Audio}
|
{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}
|
{include "../Audio/player.xml", audio => $attachment}
|
||||||
</div>
|
</div>
|
||||||
{else}
|
{else}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{var $postId = $target instanceof \openvk\Web\Models\Entities\Post ? $target->getId() : NULL}
|
{var $postId = $target instanceof \openvk\Web\Models\Entities\Post ? $target->getId() : NULL}
|
||||||
|
|
||||||
<a name="cid={$comment->getId()}"></a>
|
<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>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="30" valign="top">
|
<td width="30" valign="top">
|
||||||
|
@ -22,12 +22,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content" id="{$comment->getId()}">
|
<div class="post-content" id="{$comment->getId()}">
|
||||||
<div class="text" id="text{$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)}
|
{var $attachmentsLayout = $comment->getChildrenWithLayout(288)}
|
||||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
<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}">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='post-edit'></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
{var $commentTextAreaId = $post === NULL ? rand(1,300) : $post->getId()}
|
{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>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
|
@ -68,13 +68,10 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if $post->canBeEditedBy($thisUser) && !($forceNoEditLink ?? false) && $compact == false}
|
{if $post->canBeEditedBy($thisUser) && !($forceNoEditLink ?? false) && $compact == false}
|
||||||
<a class="edit" id="editPost"
|
<a class="edit" id="editPost"></a>
|
||||||
data-id="{$post->getId()}"
|
|
||||||
data-nsfw="{(int)$post->isExplicit()}"
|
|
||||||
{if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}></a>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</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()}">
|
<div class="text" id="text{$post->getPrettyId()}">
|
||||||
<span data-text="{$post->getText(false)}" class="really_text">{$post->getText()|noescape}</span>
|
<span data-text="{$post->getText(false)}" class="really_text">{$post->getText()|noescape}</span>
|
||||||
|
|
||||||
|
@ -84,8 +81,8 @@
|
||||||
{/if}
|
{/if}
|
||||||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
<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}">
|
<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"}
|
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post", tilesCount => sizeof($attachmentsLayout->tiles)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -112,6 +109,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='post-edit' n:if='!$compact'></div>
|
||||||
<div class="post-menu" n:if="$compact == false">
|
<div class="post-menu" n:if="$compact == false">
|
||||||
<a href="{if !$suggestion}/wall{$post->getPrettyId()}{else}javascript:void(0){/if}" class="date">{$post->getPublicationTime()}
|
<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>
|
<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>
|
<a n:if="!($forceNoCommentsLink ?? false) && $commentsCount == 0" href="javascript:expand_comment_textarea({$commentTextAreaId})">{_comment}</a>
|
||||||
|
|
||||||
<div class="like_wrap">
|
<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>
|
<div class="repost-icon" style="opacity: 0.4;"></div>
|
||||||
<span class="likeCnt" id="repostsCount{$post->getPrettyId()}">{if $repostsCount > 0}{$repostsCount}{/if}</span>
|
<span class="likeCnt" id="repostsCount{$post->getPrettyId()}">{if $repostsCount > 0}{$repostsCount}{/if}</span>
|
||||||
</a>
|
</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>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="54" valign="top">
|
<td width="54" valign="top">
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
</a>
|
</a>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</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()}">
|
<div class="text" id="text{$post->getPrettyId()}">
|
||||||
{var $owner = $author->getId()}
|
{var $owner = $author->getId()}
|
||||||
|
|
||||||
|
@ -79,8 +79,8 @@
|
||||||
{/if}
|
{/if}
|
||||||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
<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}">
|
<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"}
|
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post", tilesCount => sizeof($attachmentsLayout->tiles)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='post-edit' n:if='!$compact'></div>
|
||||||
<div n:if="!($compact ?? false)" class="post-menu">
|
<div n:if="!($compact ?? false)" class="post-menu">
|
||||||
{if is_null($thisUser)}
|
{if is_null($thisUser)}
|
||||||
{var $forceNoDeleteLink = true}
|
{var $forceNoDeleteLink = true}
|
||||||
|
@ -119,9 +120,7 @@
|
||||||
|
|
||||||
{if !($forceNoEditLink ?? false) && $post->canBeEditedBy($thisUser)}
|
{if !($forceNoEditLink ?? false) && $post->canBeEditedBy($thisUser)}
|
||||||
<a id="editPost"
|
<a id="editPost"
|
||||||
data-id="{$post->getId()}"
|
data-id="{$post->getPrettyId()}">{_edit}</a> |
|
||||||
data-nsfw="{(int)$post->isExplicit()}"
|
|
||||||
{if $post->getTargetWall() < 0 && $wallOwner->canBeModifiedBy($thisUser)}data-fromgroup="{(int)$post->isPostedOnBehalfOfGroup()}"{/if}>{_edit}</a> |
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{if !($forceNoDeleteLink ?? false) && $canBeDeleted}
|
{if !($forceNoDeleteLink ?? false) && $canBeDeleted}
|
||||||
|
@ -148,7 +147,7 @@
|
||||||
|
|
|
|
||||||
{/if}
|
{/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}
|
{_share}
|
||||||
{if $repostsCount > 0}
|
{if $repostsCount > 0}
|
||||||
(<b id="repostsCount{$post->getPrettyId()}">{$repostsCount}</b>)
|
(<b id="repostsCount{$post->getPrettyId()}">{$repostsCount}</b>)
|
||||||
|
|
|
@ -2,26 +2,18 @@
|
||||||
{var $textAreaId = ($post ?? NULL) === NULL ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
{var $textAreaId = ($post ?? NULL) === NULL ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
|
||||||
{var $textAreaId = ($custom_id ?? NULL) === NULL ? $textAreaId : $custom_id}
|
{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;">
|
<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>
|
<textarea id="wall-post-input{$textAreaId}" placeholder="{_write}" name="text" style="width: 100%;resize: none;" class="small-textarea"></textarea>
|
||||||
<div>
|
<div>
|
||||||
<!-- padding to fix <br/> bug -->
|
<!-- padding to fix <br/> bug -->
|
||||||
</div>
|
</div>
|
||||||
<div id="post-buttons{$textAreaId}" style="display: none;">
|
<div id="post-buttons{$textAreaId}" class='post-buttons' style="display: none;">
|
||||||
<div class="upload">
|
<div class="post-horizontal"></div>
|
||||||
|
<div class="post-vertical"></div>
|
||||||
</div>
|
|
||||||
<div class="post-upload">
|
|
||||||
<span style="color: inherit;"></span>
|
|
||||||
</div>
|
|
||||||
<div class="post-has-poll">
|
<div class="post-has-poll">
|
||||||
{_poll}
|
{_poll}
|
||||||
</div>
|
</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 class="post-source"></div>
|
||||||
|
|
||||||
<div n:if="$postOpts ?? true" class="post-opts">
|
<div n:if="$postOpts ?? true" class="post-opts">
|
||||||
|
@ -62,42 +54,44 @@
|
||||||
<input type="checkbox" name="as_group" /> {_comment_as_group}
|
<input type="checkbox" name="as_group" /> {_comment_as_group}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="photos" value="" />
|
<input type="hidden" name="horizontal_attachments" value="" />
|
||||||
<input type="hidden" name="videos" value="" />
|
<input type="hidden" name="vertical_attachments" value="" />
|
||||||
<input type="hidden" name="audios" value="" />
|
|
||||||
<input type="hidden" name="poll" value="none" />
|
<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" id="source" name="source" value="none" />
|
||||||
<input type="hidden" name="type" value="1" />
|
<input type="hidden" name="type" value="1" />
|
||||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||||
<br/>
|
<br/>
|
||||||
<input type="submit" value="{_write}" class="button" />
|
<input type="submit" value="{_write}" class="button" />
|
||||||
<div style="float: right; display: flex; flex-direction: column;">
|
<div style="float: right; display: flex; flex-direction: column;">
|
||||||
<a href="javascript:toggleMenu({$textAreaId});">
|
<a class='menu_toggler'>
|
||||||
{_attach}
|
{_attach}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div id="wallAttachmentMenu" class="hidden">
|
<div id="wallAttachmentMenu" class="hidden">
|
||||||
<a class="header" href="javascript:toggleMenu({$textAreaId});">
|
<a class="header menu_toggler">
|
||||||
{_attach}
|
{_attach}
|
||||||
</a>
|
</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" />
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-x-egon.png" />
|
||||||
{_photo}
|
{_photo}
|
||||||
</a>
|
</a>
|
||||||
<a id="videoAttachment">
|
<a id="__videoAttachment">
|
||||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-vnd.rn-realmedia.png" />
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-vnd.rn-realmedia.png" />
|
||||||
{_video}
|
{_video}
|
||||||
</a>
|
</a>
|
||||||
<a id="_audioAttachment">
|
<a id="__audioAttachment">
|
||||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/audio-ac3.png" />
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/audio-ac3.png" />
|
||||||
{_audio}
|
{_audio}
|
||||||
</a>
|
</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" />
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" />
|
||||||
{_graffiti}
|
{_graffiti}
|
||||||
</a>
|
</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" />
|
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/office-chart-bar-stacked.png" />
|
||||||
{_poll}
|
{_poll}
|
||||||
</a>
|
</a>
|
||||||
|
@ -112,13 +106,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(() => {
|
u("#post-buttons{$textAreaId} input[name='horizontal_attachments']")["nodes"].at(0).value = ""
|
||||||
setupWallPostInputHandlers({$textAreaId});
|
u("#post-buttons{$textAreaId} input[name='vertical_attachments']")["nodes"].at(0).value = ""
|
||||||
});
|
|
||||||
|
|
||||||
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 = ""
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{if $graffiti}
|
{if $graffiti}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<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">
|
<div class="video-preview">
|
||||||
<img src="{$video->getThumbnailURL()}"
|
<img src="{$video->getThumbnailURL()}"
|
||||||
style="max-width: 170px; max-height: 127px; margin: auto;" >
|
style="max-width: 170px; max-height: 127px; margin: auto;" >
|
||||||
|
@ -15,10 +15,13 @@
|
||||||
{include infotable, x => $dat}
|
{include infotable, x => $dat}
|
||||||
{else}
|
{else}
|
||||||
<a href="/video{$video->getPrettyId()}">
|
<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()}
|
{$video->getName()}
|
||||||
</b>
|
</b>
|
||||||
</a>
|
</a>
|
||||||
|
{if $video->getLength()}
|
||||||
|
({$video->getFormattedLength()})
|
||||||
|
{/if}
|
||||||
<br/>
|
<br/>
|
||||||
<p>
|
<p>
|
||||||
<span class='video_description'>{$video->getDescription() ?? ""}</span>
|
<span class='video_description'>{$video->getDescription() ?? ""}</span>
|
||||||
|
@ -26,7 +29,7 @@
|
||||||
<span style="color: grey;">{_video_uploaded} {$video->getPublicationTime()}</span><br/>
|
<span style="color: grey;">{_video_uploaded} {$video->getPublicationTime()}</span><br/>
|
||||||
|
|
||||||
<p>
|
<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}
|
{if $video->getCommentsCount() > 0}| <a href="/video{$video->getPrettyId()}#comments">{_comments} ({$video->getCommentsCount()})</a>{/if}
|
||||||
</p>
|
</p>
|
||||||
{/ifset}
|
{/ifset}
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Makima
|
||||||
$this->photos = $photos;
|
$this->photos = $photos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getOrientation(Photo $photo, &$ratio): int
|
private function getOrientation($photo, &$ratio): int
|
||||||
{
|
{
|
||||||
[$width, $height] = $photo->getDimensions();
|
[$width, $height] = $photo->getDimensions();
|
||||||
$ratio = $width / $height;
|
$ratio = $width / $height;
|
||||||
|
|
|
@ -129,8 +129,6 @@ routes:
|
||||||
handler: "Wall->rss"
|
handler: "Wall->rss"
|
||||||
- url: "/wall{num}/makePost"
|
- url: "/wall{num}/makePost"
|
||||||
handler: "Wall->makePost"
|
handler: "Wall->makePost"
|
||||||
- url: "/wall/edit"
|
|
||||||
handler: "Wall->edit"
|
|
||||||
- url: "/wall{num}_{num}"
|
- url: "/wall{num}_{num}"
|
||||||
handler: "Wall->post"
|
handler: "Wall->post"
|
||||||
- url: "/wall{num}_{num}/like"
|
- url: "/wall{num}_{num}/like"
|
||||||
|
@ -171,6 +169,8 @@ routes:
|
||||||
handler: "Photos->uploadPhoto"
|
handler: "Photos->uploadPhoto"
|
||||||
- url: "/photo{num}_{num}"
|
- url: "/photo{num}_{num}"
|
||||||
handler: "Photos->photo"
|
handler: "Photos->photo"
|
||||||
|
- url: "/photo{num}_{num}/like"
|
||||||
|
handler: "Photos->like"
|
||||||
- url: "/photos/thumbnails/{num}_{text}.jpeg"
|
- url: "/photos/thumbnails/{num}_{text}.jpeg"
|
||||||
handler: "Photos->thumbnail"
|
handler: "Photos->thumbnail"
|
||||||
- url: "/photos/{text}"
|
- url: "/photos/{text}"
|
||||||
|
@ -403,6 +403,8 @@ routes:
|
||||||
handler: "About->dev"
|
handler: "About->dev"
|
||||||
- url: "/iapi/getPhotosFromPost/{num}_{num}"
|
- url: "/iapi/getPhotosFromPost/{num}_{num}"
|
||||||
handler: "InternalAPI->getPhotosFromPost"
|
handler: "InternalAPI->getPhotosFromPost"
|
||||||
|
- url: "/iapi/getPostTemplate/{num}_{num}"
|
||||||
|
handler: "InternalAPI->getPostTemplate"
|
||||||
- url: "/tour"
|
- url: "/tour"
|
||||||
handler: "About->tour"
|
handler: "About->tour"
|
||||||
- url: "/{?shortCode}"
|
- url: "/{?shortCode}"
|
||||||
|
|
|
@ -267,6 +267,17 @@
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.audioEntry .volume {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 14%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioEntry .nobold {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.audioEntry.nowPlaying .volume .nobold {
|
.audioEntry.nowPlaying .volume .nobold {
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
@ -303,6 +314,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: 39px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry .playerButton {
|
.audioEntry .playerButton {
|
||||||
|
@ -341,6 +353,7 @@
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
width: 85%;
|
width: 85%;
|
||||||
height: 23px;
|
height: 23px;
|
||||||
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audioEntry .status .mediaInfo {
|
.audioEntry .status .mediaInfo {
|
||||||
|
@ -588,7 +601,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachAudio {
|
.attachAudio {
|
||||||
float: left;
|
|
||||||
width: 28%;
|
width: 28%;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
padding-top: 11px;
|
padding-top: 11px;
|
||||||
|
@ -771,6 +783,7 @@
|
||||||
|
|
||||||
.addToPlaylist {
|
.addToPlaylist {
|
||||||
width: 22%;
|
width: 22%;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
#_addAudioAdditional {
|
#_addAudioAdditional {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
height: 43px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bsdn-player.bsdn-dirty > .bsdn_controls {
|
.bsdn-player.bsdn-dirty > .bsdn_controls {
|
||||||
|
|
|
@ -7,6 +7,11 @@ body.dimmed > .dimmer {
|
||||||
opacity: .5;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.dimmed > .dimmer #absolute_territory {
|
||||||
|
margin: 100px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.ovk-diag-cont {
|
.ovk-diag-cont {
|
||||||
z-index: 1024;
|
z-index: 1024;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -59,243 +64,147 @@ body.dimmed > .dimmer {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Modal player */
|
||||||
|
|
||||||
/* fullscreen player */
|
.ovk-modal-player-window {
|
||||||
|
box-shadow: 0px 0px 9px 2px rgba(0, 0, 0, 0.2);
|
||||||
.ovk-fullscreen-player {
|
|
||||||
top: 9%;
|
|
||||||
left: 50%;
|
|
||||||
margin-right: -50%;
|
|
||||||
transform: translate(-50%, 0%);
|
|
||||||
z-index: 6667;
|
|
||||||
position: absolute;
|
|
||||||
width: 823px;
|
width: 823px;
|
||||||
min-height: 400px;
|
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;
|
color: #515151;
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
transition: color 200ms ease-in-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-part .clickable:hover {
|
.ovk-modal-player-window #ovk-player-part .top-part .top-part-buttons, .ovk-modal-player-window #ovk-player-part .bottom-part {
|
||||||
color: #ffffff;
|
color: #515151;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ovk-fullscreen-player .bsdn_teaserTitleBox span {
|
.ovk-modal-player-window #ovk-player-part .top-part .top-part-buttons a, .ovk-modal-player-window #ovk-player-part .bottom-part a {
|
||||||
color: unset;
|
color: #515151;
|
||||||
font-size: unset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ovk-fullscreen-player .bsdn-player {
|
.ovk-modal-player-window #ovk-player-info {
|
||||||
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 {
|
|
||||||
display: none;
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ovk-modal-player-window #ovk-player-info.shown {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ovk-modal-player-window #ovk-player-info {
|
||||||
background: white;
|
background: white;
|
||||||
padding-bottom: 20px;
|
min-height: 200px;
|
||||||
padding-top: 30px;
|
padding: 5px 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left_block {
|
.ovk-modal-player-window .media-page-wrapper-comments {
|
||||||
padding-left: 20px;
|
width: 100%;
|
||||||
/*padding-top: 20px;*/
|
|
||||||
width: 75%;
|
|
||||||
float: left;
|
|
||||||
background: white;
|
|
||||||
padding-right: 6px;
|
|
||||||
max-height: 400px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.right_block {
|
.ovk-modal-player-window .center-part {
|
||||||
padding-left: 10px;
|
text-align: center;
|
||||||
/*padding-top: 20px;*/
|
height: 90%;
|
||||||
width: 20%;
|
display: flex;
|
||||||
border-left: 1px solid gray;
|
align-items: center;
|
||||||
float: right;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-part span {
|
.ovk-modal-player-window .center-part .gray {
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom-part .gray {
|
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ovk-fullscreen-dimmer {
|
.ovk-modal-player-window .center-part .bsdn, .ovk-modal-player-window .center-part .bsdn-player {
|
||||||
/* спижжено у пулла с несколькими картинками там где просмотрщик фоток */
|
height: 100%;
|
||||||
position: fixed;
|
width: 100%;
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
right: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
overflow: auto;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
z-index: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v_author {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.miniplayer {
|
.miniplayer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top:0;
|
background: rgba(54, 54, 54, 0.95);
|
||||||
background: rgba(54, 54, 54, 0.9);
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
min-width: 299px;
|
min-width: 299px;
|
||||||
min-height: 192px;
|
min-height: 192px;
|
||||||
padding-top: 3px;
|
z-index: 7777;
|
||||||
z-index: 9999;
|
padding: 2px 7px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.miniplayer .bsdn-player {
|
.miniplayer .miniplayer-head {
|
||||||
max-height: 150px;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.miniplayer .fplayer {
|
.miniplayer .miniplayer-head b {
|
||||||
max-width: 286px;
|
color: white;
|
||||||
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;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-draggable {
|
.miniplayer .miniplayer-head .miniplayer-head-buttons {
|
||||||
position:fixed !important;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.miniplayer-actions img {
|
.miniplayer .miniplayer-head .miniplayer-head-buttons div {
|
||||||
max-width: 11px;
|
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;
|
cursor: pointer;
|
||||||
transition: opacity 200ms ease-in-out;
|
|
||||||
opacity: 70%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.miniplayer .fplayer iframe {
|
.miniplayer .miniplayer-head .miniplayer-head-buttons div:hover {
|
||||||
max-width: 260px;
|
opacity: 1;
|
||||||
max-height: 160px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.miniplayer-actions img:hover {
|
.miniplayer .miniplayer-head .miniplayer-head-buttons #__miniplayer_return {
|
||||||
opacity: 100%;
|
background-position: -28px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#vidComments {
|
.miniplayer .miniplayer-head .miniplayer-head-buttons #__miniplayer_close {
|
||||||
margin-top: 10px;
|
background-position: -12px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.showMoreComments {
|
.miniplayer .miniplayer-head-buttons {
|
||||||
background: #eaeaea;
|
height: 20px;
|
||||||
cursor: pointer;
|
|
||||||
text-align: center;
|
|
||||||
padding: 10px;
|
|
||||||
user-select: none;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader {
|
.miniplayer .miniplayer-body {
|
||||||
display: none;
|
height: 100%;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-arrow, .left-arrow {
|
.miniplayer .miniplayer-body .bsdn {
|
||||||
position: absolute;
|
height: 100%;
|
||||||
cursor: pointer;
|
|
||||||
transition: all 200ms ease-in-out;
|
|
||||||
margin-left: -50px;
|
|
||||||
background: none;
|
|
||||||
height: 449px;
|
|
||||||
width: 57px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-arrow img, .left-arrow img {
|
.miniplayer .miniplayer-body .bsdn .bsdn-player {
|
||||||
user-select: none;
|
height: 100%;
|
||||||
opacity: 5%;
|
|
||||||
transition: all 200ms ease-in-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-arrow:hover, .left-arrow:hover {
|
.miniplayer .miniplayer-body iframe {
|
||||||
background: rgba(0, 0, 0, 0.5);
|
width: 100%;
|
||||||
}
|
height: 100%;
|
||||||
|
|
||||||
.right-arrow img:hover, .left-arrow img:hover {
|
|
||||||
opacity: 50%;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@ body {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body, .ovk-fullscreen-dimmer, .ovk-photo-view-dimmer {
|
||||||
|
scrollbar-gutter: stable both-edges;
|
||||||
|
}
|
||||||
|
|
||||||
.nobold,
|
.nobold,
|
||||||
nobold {
|
nobold {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
@ -41,6 +45,16 @@ h1 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.display_flex_column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display_flex_row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
width: 791px;
|
width: 791px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
@ -254,6 +268,28 @@ h1 {
|
||||||
width: calc(550px - 16px - 38px - 171px);
|
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 {
|
.page_body {
|
||||||
width: 632px;
|
width: 632px;
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -772,6 +808,14 @@ h4 {
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editing .post-content, .post-edit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editing .post-edit {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.post-content .text {
|
.post-content .text {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
@ -1464,7 +1508,7 @@ body.scrolled .toTop:hover {
|
||||||
color: #3c3c3c;
|
color: #3c3c3c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-source #remove_source_button {
|
.post-source #remove_source_button, #small_remove_button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background: url('/assets/packages/static/openvk/img/arrows.png?v=2');
|
background: url('/assets/packages/static/openvk/img/arrows.png?v=2');
|
||||||
|
@ -1478,7 +1522,7 @@ body.scrolled .toTop:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-source #remove_source_button:hover {
|
.post-source #remove_source_button:hover, #small_remove_button:hover {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1548,6 +1592,15 @@ body.scrolled .toTop:hover {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.like_wrap.tidy {
|
||||||
|
float: none;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.like_wrap.tidy .post-like-button {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.heart {
|
.heart {
|
||||||
background: url('/assets/packages/static/openvk/img/like.gif') no-repeat 1px 0;
|
background: url('/assets/packages/static/openvk/img/like.gif') no-repeat 1px 0;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
|
@ -1557,12 +1610,22 @@ body.scrolled .toTop:hover {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.like_wrap.tidy .heart {
|
||||||
|
float: none;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.likeCnt {
|
.likeCnt {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.like_wrap.tidy .likeCnt {
|
||||||
|
float: none;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.heart:hover {
|
.heart:hover {
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
|
@ -1726,12 +1789,14 @@ body.scrolled .toTop:hover {
|
||||||
|
|
||||||
#wallAttachmentMenu {
|
#wallAttachmentMenu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
min-width: 94px;
|
||||||
border: 1px solid darkgrey;
|
border: 1px solid darkgrey;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
z-index: 32;
|
z-index: 32;
|
||||||
margin-top: -7px;
|
margin-top: -7px;
|
||||||
margin-left: -16px;
|
margin-left: -16px;
|
||||||
box-shadow: 0 1px 3px -1px;
|
box-shadow: 0 1px 3px -1px;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#wallAttachmentMenu>a {
|
#wallAttachmentMenu>a {
|
||||||
|
@ -2389,26 +2454,66 @@ a.poll-retract-vote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload {
|
.post-horizontal, .post-vertical {
|
||||||
margin-top: 8px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload .upload-item {
|
.post-horizontal {
|
||||||
width: 75px;
|
display: flex;
|
||||||
height: 60px;
|
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;
|
overflow: hidden;
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
margin-right: 3px;
|
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;
|
position: absolute;
|
||||||
background: rgba(0,0,0,0.5);
|
background: rgba(0,0,0,0.5);
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
margin-left: 57px; /* мне лень переделывать :DDDD */
|
right: 0px;
|
||||||
|
top: 0px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: 0.25s;
|
transition: 0.25s;
|
||||||
}
|
}
|
||||||
|
@ -2417,13 +2522,68 @@ a.poll-retract-vote {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-item img {
|
.post-horizontal .upload-item img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 60px;
|
max-height: 60px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border-radius: 3px;
|
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 */
|
/* https://imgur.com/a/ihB3JZ4 */
|
||||||
|
|
||||||
.ovk-photo-view-dimmer {
|
.ovk-photo-view-dimmer {
|
||||||
|
@ -2441,21 +2601,33 @@ a.poll-retract-vote {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
width: 610px;
|
min-width: 600px;
|
||||||
padding: 20px;
|
width: fit-content;
|
||||||
|
padding: 25px;
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
box-shadow: 0px 0px 3px 1px #222;
|
box-shadow: 0px 0px 3px 1px #222;
|
||||||
margin: 15px auto 0 auto;
|
margin: 10px auto 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ovk-photo-details {
|
.ovk-photo-view .photo_viewer_wrapper {
|
||||||
overflow: auto;
|
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 {
|
.photo_com_title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo_com_title div {
|
.photo_com_title div {
|
||||||
|
@ -2467,7 +2639,6 @@ a.poll-retract-vote {
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 35%;
|
width: 35%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: 60vh;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -2476,11 +2647,27 @@ a.poll-retract-vote {
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 35%;
|
width: 35%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-height: 60vh;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
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 {
|
.client_app > img {
|
||||||
top: 3px;
|
top: 3px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -2538,12 +2725,13 @@ a.poll-retract-vote {
|
||||||
padding: 3px 0;
|
padding: 3px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-wowzer a::before {
|
.video-wowzer .small-video-ico {
|
||||||
content: "b";
|
vertical-align: bottom;
|
||||||
color: transparent;
|
display: inline-block;
|
||||||
width: 12px;
|
width: 11px;
|
||||||
background-image: url(/assets/packages/static/openvk/img/videoico.png);
|
height: 14px;
|
||||||
display: none;
|
background: url(/assets/packages/static/openvk/img/wall.png?v=2);
|
||||||
|
background-position: -87px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Da search */
|
/* Da search */
|
||||||
|
@ -2889,17 +3077,33 @@ a.poll-retract-vote {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment_note_icon {
|
.attachment_note .attachment_note_icon {
|
||||||
max-width: 9px;
|
max-width: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment_note_text {
|
.attachment_note .attachment_note_text {
|
||||||
color: #605F63;
|
color: #605F63;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment_note {
|
.attachment_note {
|
||||||
user-select: none;
|
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
|
#notesList
|
||||||
|
@ -3124,10 +3328,81 @@ body.article .floating_sidebar, body.article .page_content {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topGrayBlock {
|
.attachment_selector .topGrayBlock {
|
||||||
background: #F0F0F0;
|
background: #F0F0F0;
|
||||||
height: 37px;
|
height: 37px;
|
||||||
border-bottom: 1px solid #C7C7C7;
|
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 {
|
.edited {
|
||||||
|
@ -3145,16 +3420,20 @@ body.article .floating_sidebar, body.article .page_content {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editMenu.loading {
|
.edit_menu.loading {
|
||||||
filter: opacity(0.5);
|
filter: opacity(0.5);
|
||||||
cursor: progress;
|
cursor: progress;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editMenu.loading * {
|
.edit_menu.loading * {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit_menu .edit_menu_buttons {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.lagged *, .lagged {
|
.lagged *, .lagged {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
@ -3316,6 +3595,129 @@ hr {
|
||||||
height: 7px;
|
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 {
|
#__feed_settings_link {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
.post-nsfw .post-content .media {
|
.post-nsfw .post-content {
|
||||||
filter: saturate(0.8) blur(15px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment {
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment:active .media {
|
.post-nsfw .post-content .text {
|
||||||
filter: none;
|
filter: saturate(0.8) blur(28px);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment::after {
|
.post-nsfw .post-content::after {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(50% - 16px);
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px 0;
|
height: 100%;
|
||||||
background-color: hsla(0, 0%, 0%, .5);
|
z-index: 1;
|
||||||
|
background-color: hsla(0, 0%, 0%, .7);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
content: attr(data-localized-nsfw-text);
|
content: attr(data-localized-nsfw-text);
|
||||||
}
|
|
||||||
|
|
||||||
.post-nsfw .post-content .attachment:active::after {
|
display: flex;
|
||||||
display: none;
|
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 |
|
@ -34,4 +34,22 @@ window.API = new Proxy(Object.create(null), {
|
||||||
window.API.Types = {};
|
window.API.Types = {};
|
||||||
window.API.Types.Message = (class Message {
|
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 но ладно уже
|
// elapsed это вроде прошедшие, а оставшееся это remaining но ладно уже
|
||||||
function getElapsedTime(fullTime, time) {
|
function getElapsedTime(fullTime, time) {
|
||||||
let timer = fullTime - time
|
let timer = fullTime - time
|
||||||
|
@ -1325,8 +1315,8 @@ $(document).on("click", "#_deletePlaylist", (e) => {
|
||||||
}, Function.noop])
|
}, Function.noop])
|
||||||
})
|
})
|
||||||
|
|
||||||
$(document).on("click", "#_audioAttachment", (e) => {
|
$(document).on("click", "#__audioAttachment", (e) => {
|
||||||
let form = e.currentTarget.closest("form")
|
const form = e.target.closest("form")
|
||||||
let body = `
|
let body = `
|
||||||
<div class="searchBox">
|
<div class="searchBox">
|
||||||
<input name="query" type="text" maxlength="50" placeholder="${tr("header_search")}">
|
<input name="query" type="text" maxlength="50" placeholder="${tr("header_search")}">
|
||||||
|
@ -1338,7 +1328,7 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
||||||
|
|
||||||
<div class="audiosInsert"></div>
|
<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-body").style.padding = "0"
|
||||||
document.querySelector(".ovk-diag-cont").style.width = "580px"
|
document.querySelector(".ovk-diag-cont").style.width = "580px"
|
||||||
|
@ -1359,23 +1349,24 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
||||||
|
|
||||||
result.querySelectorAll(".audioEmbed").forEach(el => {
|
result.querySelectorAll(".audioEmbed").forEach(el => {
|
||||||
let id = el.dataset.prettyid
|
let id = el.dataset.prettyid
|
||||||
let name = el.dataset.name
|
const is_attached = (u(form).find(`.post-vertical .vertical-attachment[data-id='${id}']`)).length > 0
|
||||||
let isAttached = (form.querySelector("input[name='audios']").value.includes(`${id},`))
|
|
||||||
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
|
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
|
||||||
<div style="display: table;width: 100%;clear: both;">
|
<div class='audio_attachment_header' style="display: flex;width: 100%;">
|
||||||
<div style="width: 72%;float: left;">${el.outerHTML}</div>
|
<div class='player_part' style="width: 72%;">${el.outerHTML}</div>
|
||||||
<div class="attachAudio" data-attachmentdata="${id}" data-name="${name}">
|
<div class="attachAudio" data-attachmentdata="${id}">
|
||||||
<span>${isAttached ? tr("detach_audio") : tr("attach_audio")}</span>
|
<span>${is_attached ? tr("detach_audio") : tr("attach_audio")}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
u("#loader").remove()
|
u("#loader").remove()
|
||||||
|
u('#show_more').remove()
|
||||||
|
|
||||||
if(thisc.page < pagesCount) {
|
if(thisc.page < pagesCount) {
|
||||||
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
|
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>
|
<span>${tr("show_more_audios")}</span>
|
||||||
</div>`)
|
</div>`)
|
||||||
}
|
}
|
||||||
|
@ -1395,14 +1386,12 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
||||||
|
|
||||||
searcher.movePage(1)
|
searcher.movePage(1)
|
||||||
|
|
||||||
$(".audiosInsert").on("click", "#showMoreAudios", (e) => {
|
u(".audiosInsert").on("click", "#show_more", async (e) => {
|
||||||
u(e.currentTarget).remove()
|
u(e.target).closest('#show_more').addClass('lagged')
|
||||||
searcher.movePage(Number(e.currentTarget.dataset.page))
|
searcher.movePage(Number(e.currentTarget.dataset.page))
|
||||||
})
|
})
|
||||||
|
|
||||||
$(".searchBox input").on("change", async (e) => {
|
$(".searchBox input").on("change", async (e) => {
|
||||||
await new Promise(r => setTimeout(r, 500));
|
|
||||||
|
|
||||||
if(e.currentTarget.value === document.querySelector(".searchBox input").value) {
|
if(e.currentTarget.value === document.querySelector(".searchBox input").value) {
|
||||||
searcher.clearContainer()
|
searcher.clearContainer()
|
||||||
|
|
||||||
|
@ -1433,44 +1422,34 @@ $(document).on("click", "#_audioAttachment", (e) => {
|
||||||
return;
|
return;
|
||||||
})
|
})
|
||||||
|
|
||||||
function insertAttachment(id) {
|
u(".audiosInsert").on("click", ".attachAudio", (ev) => {
|
||||||
let audios = form.querySelector("input[name='audios']")
|
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 + ",")) {
|
// 04.11.2024 19:03
|
||||||
if(audios.value.split(",").length > 10) {
|
if(is_attached) {
|
||||||
NewNotification(tr("error"), tr("max_attached_audios"))
|
u(form).find(`.post-vertical .vertical-attachment[data-id='${id}']`).remove()
|
||||||
return false
|
u(ev.currentTarget).find("span").html(tr("attach_audio"))
|
||||||
|
} else {
|
||||||
|
if(u(form).find(`.upload-item`).length > window.openvk.max_attachments) {
|
||||||
|
makeError(tr('too_many_attachments'), 'Red', 10000, 1)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
form.querySelector("input[name='audios']").value += (id + ",")
|
u(ev.currentTarget).find("span").html(tr("detach_audio"))
|
||||||
|
|
||||||
return true
|
const header = u(ev.currentTarget).closest('.audio_attachment_header')
|
||||||
} else {
|
const player = header.find('.player_part')
|
||||||
form.querySelector("input[name='audios']").value = form.querySelector("input[name='audios']").value.replace(id + ",", "")
|
u(form).find(".post-vertical").append(`
|
||||||
|
<div class="vertical-attachment upload-item" data-type='audio' data-id="${ev.currentTarget.dataset.attachmentdata}">
|
||||||
return false
|
<div class='vertical-attachment-content'>
|
||||||
}
|
${player.html()}
|
||||||
}
|
</div>
|
||||||
|
<div class='vertical-attachment-remove'>
|
||||||
$(".audiosInsert").on("click", ".attachAudio", (ev) => {
|
<div id='small_remove_button'></div>
|
||||||
if(!insertAttachment(ev.currentTarget.dataset.attachmentdata)) {
|
</div>
|
||||||
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")
|
|
||||||
|
|
||||||
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>
|
|
||||||
</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) => {
|
$(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) => {
|
$(document).on("click", ".musicIcon.report-icon", (e) => {
|
||||||
|
|
|
@ -64,8 +64,9 @@ function pollRadioPressed(radio) {
|
||||||
form.submit();
|
form.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function initPoll(id) {
|
function initPoll(event) {
|
||||||
let form = $(`#wall-post-input${id}`).parent();
|
let form = $(event.target.closest('.post-buttons')).parent();
|
||||||
|
const id = random_int(0, 100)
|
||||||
|
|
||||||
let mBody = `
|
let mBody = `
|
||||||
<div id="poll_editor${id}">
|
<div id="poll_editor${id}">
|
||||||
|
@ -87,9 +88,9 @@ function initPoll(id) {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
MessageBox(tr("create_poll"), mBody, [tr("attach"), tr("cancel")], [
|
const msg = MessageBox(tr("create_poll"), mBody, [tr("attach"), tr("cancel")], [
|
||||||
function() {
|
function() {
|
||||||
let dialog = $(this.$dialog().nodes[0]);
|
let dialog = $(msg.getNode().nodes[0]);
|
||||||
$("input", dialog).unbind();
|
$("input", dialog).unbind();
|
||||||
|
|
||||||
let title = $("input[name=title]", dialog).val();
|
let title = $("input[name=title]", dialog).val();
|
||||||
|
@ -117,9 +118,9 @@ function initPoll(id) {
|
||||||
$(".post-has-poll", form).show();
|
$(".post-has-poll", form).show();
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
$("input", $(this.$dialog().nodes[0])).unbind();
|
$("input", $(msg.getNode())).unbind();
|
||||||
}
|
}
|
||||||
]);
|
], true);
|
||||||
|
|
||||||
let editor = $(`#poll_editor${id}`);
|
let editor = $(`#poll_editor${id}`);
|
||||||
$("input[name=newOption]", editor).bind("focus", function() {
|
$("input[name=newOption]", editor).bind("focus", function() {
|
||||||
|
|
|
@ -1,42 +1,177 @@
|
||||||
Function.noop = () => {};
|
Function.noop = () => {};
|
||||||
|
|
||||||
function MessageBox(title, body, buttons, callbacks) {
|
class CMessageBox {
|
||||||
if(u(".ovk-diag-cont").length > 0) return false;
|
constructor(options = {}) {
|
||||||
|
const title = options.title ?? 'Untitled'
|
||||||
document.querySelector("html").style.overflowY = "hidden"
|
const body = options.body ?? '<hr>'
|
||||||
let dialog = u(
|
const buttons = options.buttons ?? []
|
||||||
`<div class="ovk-diag-cont">
|
const callbacks = options.callbacks ?? []
|
||||||
<div class="ovk-diag">
|
const close_on_buttons = options.close_on_buttons ?? true
|
||||||
<div class="ovk-diag-head">${title}</div>
|
const unique_name = options.unique_name ?? null
|
||||||
<div class="ovk-diag-body">${body}</div>
|
const warn_on_exit = options.warn_on_exit ?? false
|
||||||
<div class="ovk-diag-action"></div>
|
const custom_template = options.custom_template ?? null
|
||||||
</div>
|
if(unique_name && window.messagebox_stack.find(item => item.unique_name == unique_name) != null) {
|
||||||
</div>`);
|
return
|
||||||
u("body").addClass("dimmed").append(dialog);
|
}
|
||||||
|
|
||||||
buttons.forEach((text, callback) => {
|
this.title = title
|
||||||
u(".ovk-diag-action").append(u(`<button class="button">${text}</button>`));
|
this.body = body
|
||||||
let button = u(u(".ovk-diag-action > button.button").last());
|
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
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
button.on("click", function(e) {
|
u('html').attr('style', 'overflow-y:hidden')
|
||||||
let __closeDialog = () => {
|
|
||||||
|
buttons.forEach((text, callback) => {
|
||||||
if(document.querySelector(".ovk-photo-view-dimmer") == null && document.querySelector(".ovk-fullscreen-player") == null) {
|
this.getNode().find('.ovk-diag-action').append(u(`<button class="button">${text}</button>`))
|
||||||
u("body").removeClass("dimmed");
|
let button = u(this.getNode().find('.ovk-diag-action > button.button').last())
|
||||||
document.querySelector("html").style.overflowY = "scroll"
|
button.on("click", (e) => {
|
||||||
|
callbacks[callback]()
|
||||||
|
|
||||||
|
if(close_on_buttons) {
|
||||||
|
this.close()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
u(".ovk-diag-cont").remove();
|
})
|
||||||
};
|
|
||||||
|
window.messagebox_stack.push(this)
|
||||||
Reflect.apply(callbacks[callback], {
|
}
|
||||||
closeDialog: () => __closeDialog(),
|
|
||||||
$dialog: () => u(".ovk-diag-cont")
|
__getTemplate() {
|
||||||
}, [e]);
|
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)
|
||||||
|
|
||||||
__closeDialog();
|
delete this
|
||||||
});
|
}
|
||||||
});
|
|
||||||
|
close() {
|
||||||
return u(".ovk-diag-cont");
|
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 @@
|
||||||
|
if(typeof u == 'undefined') {
|
||||||
function expand_wall_textarea(id) {
|
console.error('!!! You forgot to install NPM packages !!!')
|
||||||
var el = document.getElementById('post-buttons'+id);
|
|
||||||
var wi = document.getElementById('wall-post-input'+id);
|
|
||||||
el.style.display = "block";
|
|
||||||
wi.className = "expanded-textarea";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function expand_comment_textarea(id) {
|
function expand_comment_textarea(id) {
|
||||||
|
@ -13,19 +9,6 @@ function expand_comment_textarea(id) {
|
||||||
wi.focus();
|
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)
|
function hidePanel(panel, count = 0)
|
||||||
{
|
{
|
||||||
$(panel).toggleClass("content_title_expanded content_title_unexpanded");
|
$(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.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") + "' >";
|
var formHtml = "<form id='tmpPhDelF' action='" + u(this).attr("href") + "' >";
|
||||||
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
|
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
|
||||||
formHtml += "</form>";
|
formHtml += "</form>";
|
||||||
|
@ -186,74 +159,6 @@ document.addEventListener("DOMContentLoaded", function() { //BEGIN
|
||||||
})
|
})
|
||||||
}); //END ONREADY DECLS
|
}); //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) {
|
function setClubAdminComment(clubId, adminId, hash) {
|
||||||
MessageBox("Изменить комментарий к администратору", `
|
MessageBox("Изменить комментарий к администратору", `
|
||||||
<form action="/club${clubId}/setAdmin" method="post" id="uClubAdminCommentForm_${clubId}_${adminId}">
|
<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) {
|
function autoTab(original, next, previous) {
|
||||||
if(original.getAttribute && original.value.length == original.getAttribute("maxlength") && next !== undefined)
|
if(original.getAttribute && original.value.length == original.getAttribute("maxlength") && next !== undefined)
|
||||||
next.focus();
|
next.focus();
|
||||||
|
@ -361,11 +255,6 @@ function supportFastAnswerDialogOnClick(answer) {
|
||||||
answerInput.focus();
|
answerInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function ovk_proc_strtr(string, length = 0) {
|
|
||||||
const newString = string.substring(0, length);
|
|
||||||
return newString + (string !== newString ? "…" : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
function showProfileDeactivateDialog(hash) {
|
function showProfileDeactivateDialog(hash) {
|
||||||
MessageBox(tr("profile_deactivate"), `
|
MessageBox(tr("profile_deactivate"), `
|
||||||
<div class="messagebox-content-header">
|
<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", () => {
|
$(document).on("scroll", () => {
|
||||||
if($(document).scrollTop() > $(".sidebar").height() + 50) {
|
if($(document).scrollTop() > $(".sidebar").height() + 50) {
|
||||||
$(".floating_sidebar")[0].classList.add("show");
|
$(".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"];
|
return $GLOBALS["requestIsSSL"];
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseAttachments(string $attachments): array
|
function parseAttachments($attachments, array $allow_types = ['photo', 'video', 'note', 'audio']): array
|
||||||
{
|
{
|
||||||
$attachmentsArr = explode(",", $attachments);
|
$exploded_attachments = is_array($attachments) ? $attachments : explode(",", $attachments);
|
||||||
$returnArr = [];
|
$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) {
|
foreach($exploded_attachments as $attachment_string) {
|
||||||
$attachmentType = NULL;
|
if(preg_match("/$imploded_types/", $attachment_string, $matches) == 1) {
|
||||||
|
try {
|
||||||
if(str_contains($attachment, "photo"))
|
$attachment_type = $matches[0];
|
||||||
$attachmentType = "photo";
|
if(!$repositories[$attachment_type])
|
||||||
elseif(str_contains($attachment, "video"))
|
continue;
|
||||||
$attachmentType = "video";
|
|
||||||
elseif(str_contains($attachment, "note"))
|
$attachment_ids = str_replace($attachment_type, '', $attachment_string);
|
||||||
$attachmentType = "note";
|
if($repositories[$attachment_type]['onlyId']) {
|
||||||
elseif(str_contains($attachment, "audio"))
|
[$attachment_id] = array_map('intval', explode('_', $attachment_ids));
|
||||||
$attachmentType = "audio";
|
|
||||||
|
$repository_class = $repositories[$attachment_type]['repo'];
|
||||||
$attachmentIds = str_replace($attachmentType, "", $attachment);
|
if(!$repository_class) continue;
|
||||||
$attachmentOwner = (int) explode("_", $attachmentIds)[0];
|
$attachment_model = (new $repository_class)->{$repositories[$attachment_type]['method']}($attachment_id);
|
||||||
$gatoExplotano = explode("_", $attachmentIds);
|
$output_attachments[] = $attachment_model;
|
||||||
$attachmentId = (int) end($gatoExplotano);
|
} else {
|
||||||
|
[$attachment_owner, $attachment_id] = array_map('intval', explode('_', $attachment_ids));
|
||||||
switch($attachmentType) {
|
|
||||||
case "photo":
|
$repository_class = $repositories[$attachment_type]['repo'];
|
||||||
$attachmentObj = (new openvk\Web\Models\Repositories\Photos)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
if(!$repository_class) continue;
|
||||||
$returnArr[] = $attachmentObj;
|
$attachment_model = (new $repository_class)->{$repositories[$attachment_type]['method']}($attachment_owner, $attachment_id);
|
||||||
break;
|
$output_attachments[] = $attachment_model;
|
||||||
case "video":
|
}
|
||||||
$attachmentObj = (new openvk\Web\Models\Repositories\Videos)->getByOwnerAndVID($attachmentOwner, $attachmentId);
|
} catch(\Throwable) {continue;}
|
||||||
$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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $returnArr;
|
return $output_attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_entity_by_id(int $id)
|
function get_entity_by_id(int $id)
|
||||||
|
|
|
@ -58,6 +58,7 @@ openvk:
|
||||||
enable: false
|
enable: false
|
||||||
account: 100
|
account: 100
|
||||||
postSizes:
|
postSizes:
|
||||||
|
maxAttachments: 10
|
||||||
maxSize: 60000
|
maxSize: 60000
|
||||||
processingLimit: 3000
|
processingLimit: 3000
|
||||||
emojiProcessingLimit: 1000
|
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";
|
"others_posts" = "Others posts";
|
||||||
|
|
||||||
"show_more" = "Show more";
|
"show_more" = "Show more";
|
||||||
|
"has_repost" = "Has repost";
|
||||||
|
|
||||||
/* Friends */
|
/* Friends */
|
||||||
|
|
||||||
|
@ -517,6 +518,7 @@
|
||||||
"click_to_go_to_album" = "Click here to go to album.";
|
"click_to_go_to_album" = "Click here to go to album.";
|
||||||
"error_uploading_photo" = "Error when uploading photo";
|
"error_uploading_photo" = "Error when uploading photo";
|
||||||
"too_many_pictures" = "No more than 10 pictures";
|
"too_many_pictures" = "No more than 10 pictures";
|
||||||
|
"too_many_attachments" = "Too many attachments.";
|
||||||
|
|
||||||
"drag_files_here" = "Drag files here";
|
"drag_files_here" = "Drag files here";
|
||||||
"only_images_accepted" = "File \"$1\" is not an image";
|
"only_images_accepted" = "File \"$1\" is not an image";
|
||||||
|
@ -848,6 +850,9 @@
|
||||||
"no_videos" = "You don't have uploaded videos.";
|
"no_videos" = "You don't have uploaded videos.";
|
||||||
"no_videos_results" = "No results.";
|
"no_videos_results" = "No results.";
|
||||||
|
|
||||||
|
"video_file_upload" = "Upload file";
|
||||||
|
"video_youtube_upload" = "Add from YouTube";
|
||||||
|
|
||||||
"change_video" = "Change video";
|
"change_video" = "Change video";
|
||||||
"unknown_video" = "This video is not supported in your version of OpenVK.";
|
"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?";
|
"question_confirm" = "This action can't be undone. Do you really wanna do it?";
|
||||||
"confirm_m" = "Confirm";
|
"confirm_m" = "Confirm";
|
||||||
"action_successfully" = "Success";
|
"action_successfully" = "Success";
|
||||||
|
"exit_noun" = "Exit";
|
||||||
|
"exit_confirmation" = "Are you sure want to exit?";
|
||||||
"apply" = "Apply";
|
"apply" = "Apply";
|
||||||
|
|
||||||
/* User Alerts */
|
/* User Alerts */
|
||||||
|
|
|
@ -248,6 +248,7 @@
|
||||||
"clubs_posts" = "Записи сообщества";
|
"clubs_posts" = "Записи сообщества";
|
||||||
"others_posts" = "Чужие записи";
|
"others_posts" = "Чужие записи";
|
||||||
"show_more" = "Показать больше";
|
"show_more" = "Показать больше";
|
||||||
|
"has_repost" = "Содержит репост";
|
||||||
|
|
||||||
/* Friends */
|
/* Friends */
|
||||||
|
|
||||||
|
@ -500,9 +501,10 @@
|
||||||
"click_to_go_to_album" = "Нажмите, чтобы перейти к альбому.";
|
"click_to_go_to_album" = "Нажмите, чтобы перейти к альбому.";
|
||||||
"error_uploading_photo" = "Не удалось загрузить фотографию";
|
"error_uploading_photo" = "Не удалось загрузить фотографию";
|
||||||
"too_many_pictures" = "Не больше 10 фотографий";
|
"too_many_pictures" = "Не больше 10 фотографий";
|
||||||
|
"too_many_attachments" = "Слишком много вложений.";
|
||||||
|
|
||||||
"drag_files_here" = "Перетащите файлы сюда";
|
"drag_files_here" = "Перетащите файлы сюда";
|
||||||
"only_images_accepted" = "Файл \"$1\" не является изображением";
|
"only_images_accepted" = "Файл \"$1\" не является изображением или видео.";
|
||||||
"max_filesize" = "Максимальный размер файла — $1 мегабайт";
|
"max_filesize" = "Максимальный размер файла — $1 мегабайт";
|
||||||
|
|
||||||
"uploading_photos_from_computer" = "Загрузка фотографий с Вашего компьютера";
|
"uploading_photos_from_computer" = "Загрузка фотографий с Вашего компьютера";
|
||||||
|
@ -807,6 +809,9 @@
|
||||||
"no_videos" = "У вас нет видео.";
|
"no_videos" = "У вас нет видео.";
|
||||||
"no_videos_results" = "Нет результатов.";
|
"no_videos_results" = "Нет результатов.";
|
||||||
|
|
||||||
|
"video_file_upload" = "Загрузить файл";
|
||||||
|
"video_youtube_upload" = "Добавить с YouTube";
|
||||||
|
|
||||||
/* Audios */
|
/* Audios */
|
||||||
|
|
||||||
"my" = "Моё";
|
"my" = "Моё";
|
||||||
|
@ -1481,7 +1486,7 @@
|
||||||
|
|
||||||
"error_adding_source_regex" = "Ошибка добавления источника: некорректная ссылка.";
|
"error_adding_source_regex" = "Ошибка добавления источника: некорректная ссылка.";
|
||||||
"error_adding_source_long" = "Ошибка добавления источника: слишком длинная ссылка.";
|
"error_adding_source_long" = "Ошибка добавления источника: слишком длинная ссылка.";
|
||||||
"error_adding_source_sus" = "Ошибка добавления источника: подозрительная ссылка.";
|
"error_adding_source_sus" = "Ошибка добавления источника: гиперссылка заблокирована.";
|
||||||
|
|
||||||
/* Admin actions */
|
/* Admin actions */
|
||||||
|
|
||||||
|
@ -1669,6 +1674,8 @@
|
||||||
"question_confirm" = "Это действие нельзя отменить. Вы действительно уверены в том что хотите сделать?";
|
"question_confirm" = "Это действие нельзя отменить. Вы действительно уверены в том что хотите сделать?";
|
||||||
"confirm_m" = "Подтвердить";
|
"confirm_m" = "Подтвердить";
|
||||||
"action_successfully" = "Операция успешна";
|
"action_successfully" = "Операция успешна";
|
||||||
|
"exit_noun" = "Выход";
|
||||||
|
"exit_confirmation" = "Уверены, что хотите выйти?";
|
||||||
"apply" = "Применить";
|
"apply" = "Применить";
|
||||||
|
|
||||||
/* User alerts */
|
/* User alerts */
|
||||||
|
@ -2028,7 +2035,7 @@
|
||||||
|
|
||||||
/* Fullscreen player */
|
/* Fullscreen player */
|
||||||
|
|
||||||
"hide_player" = "Скрыть";
|
"hide_player" = "Свернуть";
|
||||||
"close_player" = "Закрыть";
|
"close_player" = "Закрыть";
|
||||||
"show_comments" = "Показать информацию";
|
"show_comments" = "Показать информацию";
|
||||||
"close_comments" = "Скрыть информацию";
|
"close_comments" = "Скрыть информацию";
|
||||||
|
|
|
@ -60,6 +60,7 @@ openvk:
|
||||||
enable: false
|
enable: false
|
||||||
account: 100
|
account: 100
|
||||||
postSizes:
|
postSizes:
|
||||||
|
maxAttachments: 10
|
||||||
maxSize: 60000
|
maxSize: 60000
|
||||||
processingLimit: 3000
|
processingLimit: 3000
|
||||||
emojiProcessingLimit: 1000
|
emojiProcessingLimit: 1000
|
||||||
|
|