mirror of
https://github.com/openvk/openvk
synced 2025-04-23 00:23:01 +03:00
Add photos picker (#986)
* early implementation of photos pickir Добавлен пикер фоточек и быстрая загрузка фото. Так же пофикшен просмотрщик фото в группах. Но, правда, я сломал копипейст, но это ладн. * Fiks fotos viver four coments. * Add picking photos from clubs albums Копипейст и граффити так и не пофикшены * Fix graffiti and copypaste Какого-то хуя копипаста у постов срабатывает два раза. * some fixesx * dragon drop
This commit is contained in:
parent
2e8c48a3dd
commit
123bc63441
16 changed files with 509 additions and 129 deletions
92
ServiceAPI/Photos.php
Normal file
92
ServiceAPI/Photos.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ class Comment extends Post
|
|||
|
||||
function getPrettyId(): string
|
||||
{
|
||||
return $this->getRecord()->id;
|
||||
return (string)$this->getRecord()->id;
|
||||
}
|
||||
|
||||
function getVirtualId(): int
|
||||
|
|
|
@ -33,14 +33,26 @@ class Photos
|
|||
return new Photo($photo);
|
||||
}
|
||||
|
||||
function getEveryUserPhoto(User $user): \Traversable
|
||||
function getEveryUserPhoto(User $user, int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
{
|
||||
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
|
||||
$photos = $this->photos->where([
|
||||
"owner" => $user->getId()
|
||||
]);
|
||||
"owner" => $user->getId(),
|
||||
"deleted" => 0
|
||||
])->order("id DESC");
|
||||
|
||||
foreach($photos as $photo) {
|
||||
foreach($photos->page($page, $perPage) as $photo) {
|
||||
yield new Photo($photo);
|
||||
}
|
||||
}
|
||||
|
||||
function getUserPhotosCount(User $user)
|
||||
{
|
||||
$photos = $this->photos->where([
|
||||
"owner" => $user->getId(),
|
||||
"deleted" => 0
|
||||
]);
|
||||
|
||||
return sizeof($photos);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Models\Entities\{Comment, Notifications\MentionNotification, Photo, Video, User, Topic, Post};
|
||||
use openvk\Web\Models\Entities\Notifications\CommentNotification;
|
||||
use openvk\Web\Models\Repositories\{Comments, Clubs, Videos};
|
||||
use openvk\Web\Models\Repositories\{Comments, Clubs, Videos, Photos};
|
||||
|
||||
final class CommentPresenter extends OpenVKPresenter
|
||||
{
|
||||
|
@ -54,9 +54,6 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
if ($entity instanceof Post && $entity->getWallOwner()->isBanned())
|
||||
$this->flashFail("err", tr("error"), tr("forbidden"));
|
||||
|
||||
if($_FILES["_vid_attachment"] && OPENVK_ROOT_CONF['openvk']['preferences']['videos']['disableUploading'])
|
||||
$this->flashFail("err", tr("error"), tr("video_uploads_disabled"));
|
||||
|
||||
$flags = 0;
|
||||
if($this->postParam("as_group") === "on" && !is_null($club) && $club->canBeModifiedBy($this->user->identity))
|
||||
$flags |= 0b10000000;
|
||||
|
@ -70,18 +67,22 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
}
|
||||
}
|
||||
|
||||
# TODO move to trait
|
||||
try {
|
||||
$photo = NULL;
|
||||
if($_FILES["_pic_attachment"]["error"] === UPLOAD_ERR_OK) {
|
||||
$album = NULL;
|
||||
if($wall > 0 && $wall === $this->user->id)
|
||||
$album = (new Albums)->getUserWallAlbum($wallOwner);
|
||||
|
||||
$photo = Photo::fastMake($this->user->id, $this->postParam("text"), $_FILES["_pic_attachment"], $album);
|
||||
$photos = [];
|
||||
if(!empty($this->postParam("photos"))) {
|
||||
$un = rtrim($this->postParam("photos"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
if(sizeof($arr) < 11) {
|
||||
foreach($arr as $dat) {
|
||||
$ids = explode("_", $dat);
|
||||
$photo = (new Photos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
|
||||
|
||||
if(!$photo || $photo->isDeleted())
|
||||
continue;
|
||||
|
||||
$photos[] = $photo;
|
||||
}
|
||||
}
|
||||
} catch(ISE $ex) {
|
||||
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_file_too_big"));
|
||||
}
|
||||
|
||||
$videos = [];
|
||||
|
@ -103,7 +104,7 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
}
|
||||
}
|
||||
|
||||
if(empty($this->postParam("text")) && !$photo && !$video)
|
||||
if(empty($this->postParam("text")) && sizeof($photos) < 1 && sizeof($videos) < 1)
|
||||
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_empty"));
|
||||
|
||||
try {
|
||||
|
@ -119,8 +120,8 @@ final class CommentPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("error_when_publishing_comment"), tr("error_comment_too_big"));
|
||||
}
|
||||
|
||||
if(!is_null($photo))
|
||||
$comment->attach($photo);
|
||||
foreach($photos as $photo)
|
||||
$comment->attach($photo);
|
||||
|
||||
if(sizeof($videos) > 0)
|
||||
foreach($videos as $vid)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Models\Repositories\Posts;
|
||||
use openvk\Web\Models\Repositories\{Posts, Comments};
|
||||
use MessagePack\MessagePack;
|
||||
use Chandler\Session\Session;
|
||||
|
||||
|
@ -97,14 +97,18 @@ final class InternalAPIPresenter extends OpenVKPresenter
|
|||
}
|
||||
}
|
||||
|
||||
function renderGetPhotosFromPost(string $post_id) {
|
||||
function renderGetPhotosFromPost(int $owner_id, int $post_id) {
|
||||
if($_SERVER["REQUEST_METHOD"] !== "POST") {
|
||||
header("HTTP/1.1 405 Method Not Allowed");
|
||||
exit("иди нахуй заебал");
|
||||
}
|
||||
|
||||
$id = explode("_", $post_id);
|
||||
$post = (new Posts)->getPostById(intval($id[0]), intval($id[1]));
|
||||
|
||||
if($this->postParam("parentType", false) == "post") {
|
||||
$post = (new Posts)->getPostById($owner_id, $post_id);
|
||||
} else {
|
||||
$post = (new Comments)->get($post_id);
|
||||
}
|
||||
|
||||
|
||||
if(is_null($post)) {
|
||||
$this->returnJson([
|
||||
|
|
|
@ -222,15 +222,20 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
{
|
||||
$this->assertUserLoggedIn();
|
||||
$this->willExecuteWriteAction(true);
|
||||
|
||||
if(is_null($this->queryParam("album")))
|
||||
$this->flashFail("err", tr("error"), tr("error_adding_to_deleted"), 500, true);
|
||||
|
||||
[$owner, $id] = explode("_", $this->queryParam("album"));
|
||||
$album = $this->albums->get((int) $id);
|
||||
|
||||
if(is_null($this->queryParam("album"))) {
|
||||
$album = $this->albums->getUserWallAlbum($this->user->identity);
|
||||
} else {
|
||||
[$owner, $id] = explode("_", $this->queryParam("album"));
|
||||
$album = $this->albums->get((int) $id);
|
||||
}
|
||||
|
||||
if(!$album)
|
||||
$this->flashFail("err", tr("error"), tr("error_adding_to_deleted"), 500, true);
|
||||
if(is_null($this->user) || !$album->canBeModifiedBy($this->user->identity))
|
||||
|
||||
# Для быстрой загрузки фоток из пикера фотографий нужен альбом, но юзер не может загружать фото
|
||||
# в системные альбомы, так что так.
|
||||
if(is_null($this->user) || !is_null($this->queryParam("album")) && !$album->canBeModifiedBy($this->user->identity))
|
||||
$this->flashFail("err", tr("error_access_denied_short"), tr("error_access_denied"), 500, true);
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
|
@ -261,6 +266,9 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("no_photo"), tr("select_file"), 500, true);
|
||||
|
||||
$photos = [];
|
||||
if((int)$this->postParam("count") > 10)
|
||||
$this->flashFail("err", tr("no_photo"), "ты еблан", 500, true);
|
||||
|
||||
for($i = 0; $i < $this->postParam("count"); $i++) {
|
||||
try {
|
||||
$photo = new Photo;
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace openvk\Web\Presenters;
|
|||
use openvk\Web\Models\Exceptions\TooMuchOptionsException;
|
||||
use openvk\Web\Models\Entities\{Poll, Post, Photo, Video, Club, User};
|
||||
use openvk\Web\Models\Entities\Notifications\{MentionNotification, RepostNotification, WallPostNotification};
|
||||
use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums, Notes, Videos, Comments};
|
||||
use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums, Notes, Videos, Comments, Photos};
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use Nette\InvalidStateException as ISE;
|
||||
use Bhaktaraz\RSSGenerator\Item;
|
||||
|
@ -249,35 +249,23 @@ final class WallPresenter extends OpenVKPresenter
|
|||
if($this->postParam("force_sign") === "on")
|
||||
$flags |= 0b01000000;
|
||||
|
||||
try {
|
||||
$photos = [];
|
||||
$video = NULL;
|
||||
/* if($_FILES["_pic_attachment"]["error"] === UPLOAD_ERR_OK) {
|
||||
$album = NULL;
|
||||
if(!$anon && $wall > 0 && $wall === $this->user->id)
|
||||
$album = (new Albums)->getUserWallAlbum($wallOwner);
|
||||
|
||||
$photo = Photo::fastMake($this->user->id, $this->postParam("text"), $_FILES["_pic_attachment"], $album, $anon);
|
||||
} */
|
||||
$photos = [];
|
||||
|
||||
$album = NULL;
|
||||
if(!$anon && $wall > 0 && $wall === $this->user->id)
|
||||
$album = (new Albums)->getUserWallAlbum($wallOwner);
|
||||
if(!empty($this->postParam("photos"))) {
|
||||
$un = rtrim($this->postParam("photos"), ",");
|
||||
$arr = explode(",", $un);
|
||||
|
||||
foreach($_FILES as $fileId => $file) {
|
||||
bdump([$fileId, $file, $file["error"] !== UPLOAD_ERR_OK, strncmp($fileId, "attachPic", 9) !== 0]);
|
||||
if($file["error"] !== UPLOAD_ERR_OK || strncmp($fileId, "attachPic", 9) !== 0)
|
||||
continue;
|
||||
|
||||
$photos[] = Photo::fastMake($this->user->id, $this->postParam("text"), $file, $album, $anon);
|
||||
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($_FILES["_vid_attachment"]["error"] === UPLOAD_ERR_OK)
|
||||
$video = Video::fastMake($this->user->id, $_FILES["_vid_attachment"]["name"], $this->postParam("text"), $_FILES["_vid_attachment"], $anon);*/
|
||||
} catch(\DomainException $ex) {
|
||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("media_file_corrupted"));
|
||||
} catch(ISE $ex) {
|
||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("media_file_corrupted_or_too_large"));
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -324,7 +312,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
}
|
||||
}
|
||||
|
||||
if(empty($this->postParam("text")) && !$photos && sizeof($videos) < 1 && !$poll && !$note)
|
||||
if(empty($this->postParam("text")) && sizeof($photos) < 1 && sizeof($videos) < 1 && !$poll && !$note)
|
||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big"));
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{if $attachment instanceof \openvk\Web\Models\Entities\Photo}
|
||||
{if !$attachment->isDeleted()}
|
||||
{var $link = "/photo" . ($attachment->isAnonymous() ? ("s/" . base_convert((string) $attachment->getId(), 10, 32)) : $attachment->getPrettyId())}
|
||||
<a href="{$link}" onclick="OpenMiniature(event, {$attachment->getURLBySizeId('normal')}, {$post->getPrettyId()}, {$attachment->getPrettyId()})">
|
||||
<a href="{$link}" onclick="OpenMiniature(event, {$attachment->getURLBySizeId('normal')}, {$parent->getPrettyId()}, {$attachment->getPrettyId()}, {$parentType})">
|
||||
<img class="media media_makima" src="{$attachment->getURLBySizeId('normal')}" alt="{$attachment->getDescription()}" />
|
||||
</a>
|
||||
{else}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
<div n:ifcontent class="attachments_b">
|
||||
<div class="attachment" n:foreach="$comment->getChildren() as $attachment" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
{include "attachment.xml", attachment => $attachment}
|
||||
{include "attachment.xml", attachment => $attachment, parent => $comment, parentType => "comment"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
{include "../attachment.xml", attachment => $attachment[2], post => $post}
|
||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
{var $attachmentsLayout = $post->getChildrenWithLayout($width)}
|
||||
<div n:ifcontent class="attachments attachments_b" style="height: {$attachmentsLayout->height|noescape}; width: {$attachmentsLayout->width|noescape};">
|
||||
<div class="attachment" n:foreach="$attachmentsLayout->tiles as $attachment" style="float: {$attachment[3]|noescape}; width: {$attachment[0]|noescape}; height: {$attachment[1]|noescape};" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
{include "../attachment.xml", attachment => $attachment[2], post => $post}
|
||||
{include "../attachment.xml", attachment => $attachment[2], parent => $post, parentType => "post"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<input type="checkbox" name="as_group" /> {_comment_as_group}
|
||||
</label>
|
||||
</div>
|
||||
<input type="file" class="postFileSel" id="postFilePic" name="_pic_attachment" accept="image/*" style="display:none;" />
|
||||
<input type="hidden" name="photos" value="" />
|
||||
<input type="hidden" name="videos" value="" />
|
||||
<input type="hidden" name="poll" value="none" />
|
||||
<input type="hidden" id="note" name="note" value="none" />
|
||||
|
@ -77,7 +77,7 @@
|
|||
<a class="header" href="javascript:toggleMenu({$textAreaId});">
|
||||
{_attach}
|
||||
</a>
|
||||
<a href="javascript:void(document.querySelector('#post-buttons{$textAreaId} input[name=_pic_attachment]').click());">
|
||||
<a id="photosAttachments" {if !is_null($club ?? NULL) && $club->canBeModifiedBy($thisUser)}data-club="{$club->getId()}"{/if}>
|
||||
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-x-egon.png" />
|
||||
{_photo}
|
||||
</a>
|
||||
|
@ -109,6 +109,7 @@
|
|||
});
|
||||
|
||||
u("#post-buttons{$textAreaId} input[name='videos']")["nodes"].at(0).value = ""
|
||||
u("#post-buttons{$textAreaId} input[name='photos']")["nodes"].at(0).value = ""
|
||||
</script>
|
||||
|
||||
{if $graffiti}
|
||||
|
|
|
@ -371,7 +371,7 @@ routes:
|
|||
handler: "About->humansTxt"
|
||||
- url: "/dev"
|
||||
handler: "About->dev"
|
||||
- url: "/iapi/getPhotosFromPost/{text}"
|
||||
- url: "/iapi/getPhotosFromPost/{num}_{num}"
|
||||
handler: "InternalAPI->getPhotosFromPost"
|
||||
- url: "/tour"
|
||||
handler: "About->tour"
|
||||
|
|
|
@ -22,7 +22,7 @@ function trim(string) {
|
|||
return newStr;
|
||||
}
|
||||
|
||||
function handleVideoTAreaUpdate(event, id) {
|
||||
/*function handleVideoTAreaUpdate(event, id) {
|
||||
console.log(event, id);
|
||||
let indicator = u("#post-buttons" + id + " .post-upload");
|
||||
let file = event.target.files[0];
|
||||
|
@ -34,7 +34,7 @@ function handleVideoTAreaUpdate(event, id) {
|
|||
}
|
||||
|
||||
document.querySelector("#post-buttons" + id + " #wallAttachmentMenu").classList.add("hidden");
|
||||
}
|
||||
}*/
|
||||
|
||||
function initGraffiti(id) {
|
||||
let canvas = null;
|
||||
|
@ -42,14 +42,8 @@ function initGraffiti(id) {
|
|||
canvas.getImage({includeWatermark: false}).toBlob(blob => {
|
||||
let fName = "Graffiti-" + Math.ceil(performance.now()).toString() + ".jpeg";
|
||||
let image = new File([blob], fName, {type: "image/jpeg", lastModified: new Date().getTime()});
|
||||
let trans = new DataTransfer();
|
||||
trans.items.add(image);
|
||||
|
||||
let fileSelect = document.querySelector("#post-buttons" + id + " input[name='_pic_attachment']");
|
||||
fileSelect.files = trans.files;
|
||||
|
||||
u(fileSelect).trigger("change");
|
||||
u("#post-buttons" + id + " #write textarea").trigger("focusin");
|
||||
fastUploadImage(id, image)
|
||||
}, "image/jpeg", 0.92);
|
||||
|
||||
canvas.teardown();
|
||||
|
@ -72,6 +66,79 @@ function initGraffiti(id) {
|
|||
});
|
||||
}
|
||||
|
||||
function fastUploadImage(textareaId, file) {
|
||||
// uploading images
|
||||
|
||||
if(!file.type.startsWith('image/')) {
|
||||
MessageBox(tr("error"), tr("only_images_accepted", escapeHtml(file.name)), [tr("ok")], [() => {Function.noop}])
|
||||
return;
|
||||
}
|
||||
|
||||
// 🤓🤓🤓
|
||||
if(file.size > 5 * 1024 * 1024) {
|
||||
MessageBox(tr("error"), tr("max_filesize", 5), [tr("ok")], [() => {Function.noop}])
|
||||
return;
|
||||
}
|
||||
|
||||
let imagesCount = document.querySelector("#post-buttons" + textareaId + " input[name='photos']").value.split(",").length
|
||||
|
||||
if(imagesCount > 10) {
|
||||
MessageBox(tr("error"), tr("too_many_photos"), [tr("ok")], [() => {Function.noop}])
|
||||
return
|
||||
}
|
||||
|
||||
let xhr = new XMLHttpRequest
|
||||
let data = new FormData
|
||||
|
||||
data.append("photo_0", file)
|
||||
data.append("count", 1)
|
||||
data.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
|
||||
xhr.open("POST", "/photos/upload")
|
||||
|
||||
xhr.onloadstart = () => {
|
||||
document.querySelector("#post-buttons"+textareaId+" .upload").insertAdjacentHTML("beforeend", `<img id="loader" src="/assets/packages/static/openvk/img/loading_mini.gif">`)
|
||||
}
|
||||
|
||||
xhr.onload = () => {
|
||||
let response = JSON.parse(xhr.responseText)
|
||||
|
||||
appendImage(response, textareaId)
|
||||
}
|
||||
|
||||
xhr.send(data)
|
||||
}
|
||||
|
||||
// append image after uploading via /photos/upload
|
||||
function appendImage(response, textareaId) {
|
||||
if(!response.success) {
|
||||
MessageBox(tr("error"), (tr("error_uploading_photo") + response.flash.message), [tr("ok")], [() => {Function.noop}])
|
||||
} else {
|
||||
let form = document.querySelector("#post-buttons"+textareaId)
|
||||
let photosInput = form.querySelector("input[name='photos']")
|
||||
let photosIndicator = form.querySelector(".upload")
|
||||
|
||||
for(const phot of response.photos) {
|
||||
let id = phot.owner + "_" + phot.vid
|
||||
|
||||
photosInput.value += (id + ",")
|
||||
|
||||
u(photosIndicator).append(u(`
|
||||
<div class="upload-item" id="aP" data-id="${id}">
|
||||
<a class="upload-delete">×</a>
|
||||
<img src="${phot.url}">
|
||||
</div>
|
||||
`))
|
||||
|
||||
u(photosIndicator.querySelector(`.upload #aP[data-id='${id}'] .upload-delete`)).on("click", () => {
|
||||
photosInput.value = photosInput.value.replace(id + ",", "")
|
||||
u(form.querySelector(`.upload #aP[data-id='${id}']`)).remove()
|
||||
})
|
||||
}
|
||||
}
|
||||
u(`#post-buttons${textareaId} .upload #loader`).remove()
|
||||
}
|
||||
|
||||
u(".post-like-button").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -92,17 +159,16 @@ u(".post-like-button").on("click", function(e) {
|
|||
return false;
|
||||
});
|
||||
|
||||
let picCount = 0;
|
||||
|
||||
function setupWallPostInputHandlers(id) {
|
||||
/* u("#wall-post-input" + id).on("paste", function(e) {
|
||||
u("#wall-post-input" + id).on("paste", function(e) {
|
||||
// Если вы находитесь на странице с постом с id 11, то копирование произойдёт джва раза.
|
||||
// Оч ржачный баг, но вот как его исправить, я, если честно, не знаю.
|
||||
|
||||
if(e.clipboardData.files.length === 1) {
|
||||
var input = u("#post-buttons" + id + " input[name=_pic_attachment]").nodes[0];
|
||||
input.files = e.clipboardData.files;
|
||||
|
||||
u(input).trigger("change");
|
||||
fastUploadImage(id, e.clipboardData.files[0])
|
||||
return;
|
||||
}
|
||||
}); */
|
||||
});
|
||||
|
||||
u("#wall-post-input" + id).on("input", function(e) {
|
||||
var boost = 5;
|
||||
|
@ -116,50 +182,21 @@ function setupWallPostInputHandlers(id) {
|
|||
// textArea.style.height = (newHeight > originalHeight ? (newHeight + boost) : originalHeight) + "px";
|
||||
});
|
||||
|
||||
u(`#wall-post-input${id}`).on("paste", function(e) {
|
||||
for (let i = 0; i < e.clipboardData.files.length; i++) {
|
||||
console.log(e.clipboardData.files[i]);
|
||||
if(e.clipboardData.files[i].type.match('^image/')) {
|
||||
let blobURL = URL.createObjectURL(e.clipboardData.files[i]);
|
||||
addPhotoMedia(e.clipboardData.files, blobURL, id);
|
||||
}
|
||||
}
|
||||
u("#wall-post-input" + id).on("dragover", function(e) {
|
||||
e.preventDefault()
|
||||
|
||||
// todo add animation
|
||||
return;
|
||||
});
|
||||
|
||||
u(`#post-buttons${id} input[name=_pic_attachment]`).on("change", function(e) {
|
||||
let blobURL = URL.createObjectURL(e.target.files[0]);
|
||||
addPhotoMedia(e.target.files, blobURL, id);
|
||||
$("#wall-post-input" + id).on("drop", function(e) {
|
||||
e.originalEvent.dataTransfer.dropEffect = 'move';
|
||||
fastUploadImage(id, e.originalEvent.dataTransfer.files[0])
|
||||
return;
|
||||
});
|
||||
|
||||
function addPhotoMedia(files, preview, id) {
|
||||
if(getMediaCount() >= 10) {
|
||||
alert('Не больше 10 пикч');
|
||||
} else {
|
||||
picCount++;
|
||||
u(`#post-buttons${id} .upload`).append(u(`
|
||||
<div class="upload-item" id="aP${picCount}">
|
||||
<a href="javascript:removePicture(${picCount})" class="upload-delete">×</a>
|
||||
<img src="${preview}">
|
||||
</div>
|
||||
`));
|
||||
u(`div#aP${picCount}`).nodes[0].append(u(`<input type="file" accept="image/*" name="attachPic${picCount}" id="attachPic${picCount}" style="display: none;">`).first());
|
||||
let input = u(`#attachPic${picCount}`).nodes[0];
|
||||
input.files = files; // нужен рефактор, но щас не
|
||||
console.log(input);
|
||||
u(input).trigger("change");
|
||||
}
|
||||
}
|
||||
|
||||
function getMediaCount() {
|
||||
return u(`#post-buttons${id} .upload`).nodes[0].children.length;
|
||||
}
|
||||
}
|
||||
|
||||
function removePicture(idA) {
|
||||
u(`div#aP${idA}`).nodes[0].remove();
|
||||
}
|
||||
|
||||
function OpenMiniature(e, photo, post, photo_id) {
|
||||
function OpenMiniature(e, photo, post, photo_id, type = "post") {
|
||||
/*
|
||||
костыли но смешные однако
|
||||
*/
|
||||
|
@ -190,7 +227,7 @@ function OpenMiniature(e, photo, post, photo_id) {
|
|||
<center style="margin-bottom: 8pt;">
|
||||
<div class="ovk-photo-slide-left"></div>
|
||||
<div class="ovk-photo-slide-right"></div>
|
||||
<img src="${photo}" style="max-width: 100%; max-height: 60vh;" id="ovk-photo-img">
|
||||
<img src="${photo}" style="max-width: 100%; max-height: 60vh; user-select:none;" id="ovk-photo-img">
|
||||
</center>
|
||||
<div class="ovk-photo-details">
|
||||
<img src="/assets/packages/static/openvk/img/loading_mini.gif">
|
||||
|
@ -276,7 +313,9 @@ function OpenMiniature(e, photo, post, photo_id) {
|
|||
__slidePhoto(1);
|
||||
});
|
||||
|
||||
ky.post("/iapi/getPhotosFromPost/" + post, {
|
||||
let data = new FormData()
|
||||
data.append('parentType', type);
|
||||
ky.post("/iapi/getPhotosFromPost/" + (type == "post" ? post : "1_"+post), {
|
||||
hooks: {
|
||||
afterResponse: [
|
||||
async (_request, _options, response) => {
|
||||
|
@ -298,7 +337,8 @@ function OpenMiniature(e, photo, post, photo_id) {
|
|||
__reloadTitleBar();
|
||||
__loadDetails(json.body[imagesIndex - 1].id, imagesIndex); }
|
||||
]
|
||||
}
|
||||
},
|
||||
body: data
|
||||
});
|
||||
|
||||
return u(".ovk-photo-view-dimmer");
|
||||
|
@ -396,6 +436,7 @@ function addNote(textareaId, nid)
|
|||
|
||||
u("body").removeClass("dimmed");
|
||||
u(".ovk-diag-cont").remove();
|
||||
document.querySelector("html").style.overflowY = "scroll"
|
||||
}
|
||||
|
||||
async function attachNote(id)
|
||||
|
@ -711,3 +752,210 @@ $(document).on("click", "#editPost", (e) => {
|
|||
text.style.display = "block"
|
||||
}
|
||||
})
|
||||
|
||||
// copypaste from videos picker
|
||||
$(document).on("click", "#photosAttachments", async (e) => {
|
||||
let body = `
|
||||
<div class="topGrayBlock">
|
||||
<div style="padding-top: 7px;padding-left: 12px;">
|
||||
${tr("upload_new_photo")}:
|
||||
<input type="file" multiple accept="image/*" id="fastFotosUplod" style="display:none">
|
||||
<input type="button" class="button" value="${tr("upload_button")}" onclick="fastFotosUplod.click()">
|
||||
<select id="albumSelect" style="width: 154px;float: right;margin-right: 17px;">
|
||||
<option value="0">${tr("all_photos")}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="photosInsert" style="padding: 5px;height: 287px;overflow-y: scroll;">
|
||||
<div style="position: fixed;z-index: 1007;width: 92%;background: white;margin-top: -5px;padding-top: 6px;"><h4>${tr("is_x_photos", 0)}</h4></div>
|
||||
<div class="photosList album-flex" style="margin-top: 20px;"></div>
|
||||
</div>
|
||||
`
|
||||
|
||||
let form = e.currentTarget.closest("form")
|
||||
|
||||
MessageBox(tr("select_photo"), body, [tr("close")], [Function.noop]);
|
||||
|
||||
document.querySelector(".ovk-diag-body").style.padding = "0"
|
||||
document.querySelector(".ovk-diag-cont").style.width = "630px"
|
||||
document.querySelector(".ovk-diag-body").style.height = "335px"
|
||||
|
||||
async function insertPhotos(page, album = 0) {
|
||||
u("#loader").remove()
|
||||
|
||||
let insertPlace = document.querySelector(".photosInsert .photosList")
|
||||
document.querySelector(".photosInsert").insertAdjacentHTML("beforeend", `<img id="loader" style="max-height: 8px;max-width: 36px;" src="/assets/packages/static/openvk/img/loading_mini.gif">`)
|
||||
|
||||
let photos;
|
||||
|
||||
try {
|
||||
photos = await API.Photos.getPhotos(page, Number(album))
|
||||
} catch(e) {
|
||||
document.querySelector(".photosInsert h4").innerHTML = tr("is_x_photos", -1)
|
||||
insertPlace.innerHTML = "Invalid album"
|
||||
console.error(e)
|
||||
u("#loader").remove()
|
||||
return;
|
||||
}
|
||||
|
||||
document.querySelector(".photosInsert h4").innerHTML = tr("is_x_photos", photos.count)
|
||||
|
||||
let pagesCount = Math.ceil(Number(photos.count) / 24)
|
||||
u("#loader").remove()
|
||||
|
||||
for(const photo of photos.items) {
|
||||
let isAttached = (form.querySelector("input[name='photos']").value.includes(`${photo.owner_id}_${photo.id},`))
|
||||
|
||||
insertPlace.insertAdjacentHTML("beforeend", `
|
||||
<div style="width: 14%;margin-bottom: 7px;margin-left: 13px;" class="album-photo" data-attachmentdata="${photo.owner_id}_${photo.id}" data-preview="${photo.photo_130}">
|
||||
<a href="/photo${photo.owner_id}_${photo.id}">
|
||||
<img class="album-photo--image" src="${photo.photo_130}" alt="..." style="${isAttached ? "background-color: #646464" : ""}">
|
||||
</a>
|
||||
</div>
|
||||
`)
|
||||
}
|
||||
|
||||
if(page < pagesCount) {
|
||||
insertPlace.insertAdjacentHTML("beforeend", `
|
||||
<div id="showMorePhotos" data-pagesCount="${pagesCount}" data-page="${page + 1}" style="width: 100%;text-align: center;background: #f0f0f0;height: 22px;padding-top: 9px;cursor:pointer;">
|
||||
<span>more...</span>
|
||||
</div>`)
|
||||
}
|
||||
}
|
||||
|
||||
insertPhotos(1)
|
||||
|
||||
let albums = await API.Photos.getAlbums(Number(e.currentTarget.dataset.club ?? 0))
|
||||
|
||||
for(const alb of albums.items) {
|
||||
let sel = document.querySelector(".ovk-diag-body #albumSelect")
|
||||
|
||||
sel.insertAdjacentHTML("beforeend", `<option value="${alb.id}">${ovk_proc_strtr(escapeHtml(alb.name), 20)}</option>`)
|
||||
}
|
||||
|
||||
$(".photosInsert").on("click", "#showMorePhotos", (e) => {
|
||||
u(e.currentTarget).remove()
|
||||
insertPhotos(Number(e.currentTarget.dataset.page), document.querySelector(".topGrayBlock #albumSelect").value)
|
||||
})
|
||||
|
||||
$(".topGrayBlock #albumSelect").on("change", (evv) => {
|
||||
document.querySelector(".photosInsert .photosList").innerHTML = ""
|
||||
|
||||
insertPhotos(1, evv.currentTarget.value)
|
||||
})
|
||||
|
||||
function insertAttachment(id) {
|
||||
let photos = form.querySelector("input[name='photos']")
|
||||
|
||||
if(!photos.value.includes(id + ",")) {
|
||||
if(photos.value.split(",").length > 10) {
|
||||
NewNotification(tr("error"), tr("max_attached_photos"))
|
||||
return false
|
||||
}
|
||||
|
||||
form.querySelector("input[name='photos']").value += (id + ",")
|
||||
|
||||
console.info(id + " attached")
|
||||
return true
|
||||
} else {
|
||||
form.querySelector("input[name='photos']").value = form.querySelector("input[name='photos']").value.replace(id + ",", "")
|
||||
|
||||
console.info(id + " detached")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
$(".photosList").on("click", ".album-photo", (ev) => {
|
||||
ev.preventDefault()
|
||||
|
||||
if(!insertAttachment(ev.currentTarget.dataset.attachmentdata)) {
|
||||
u(form.querySelector(`.upload #aP[data-id='${ev.currentTarget.dataset.attachmentdata}']`)).remove()
|
||||
ev.currentTarget.querySelector("img").style.backgroundColor = "white"
|
||||
} else {
|
||||
ev.currentTarget.querySelector("img").style.backgroundColor = "#646464"
|
||||
let id = ev.currentTarget.dataset.attachmentdata
|
||||
|
||||
u(form.querySelector(`.upload`)).append(u(`
|
||||
<div class="upload-item" id="aP" data-id="${ev.currentTarget.dataset.attachmentdata}">
|
||||
<a class="upload-delete">×</a>
|
||||
<img src="${ev.currentTarget.dataset.preview}">
|
||||
</div>
|
||||
`));
|
||||
|
||||
u(`.upload #aP[data-id='${ev.currentTarget.dataset.attachmentdata}'] .upload-delete`).on("click", () => {
|
||||
form.querySelector("input[name='photos']").value = form.querySelector("input[name='photos']").value.replace(id + ",", "")
|
||||
u(form.querySelector(`.upload #aP[data-id='${ev.currentTarget.dataset.attachmentdata}']`)).remove()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
u("#fastFotosUplod").on("change", (evn) => {
|
||||
let xhr = new XMLHttpRequest()
|
||||
xhr.open("POST", "/photos/upload")
|
||||
|
||||
let formdata = new FormData()
|
||||
let iterator = 0
|
||||
|
||||
for(const fille of evn.currentTarget.files) {
|
||||
if(!fille.type.startsWith('image/')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(fille.size > 5 * 1024 * 1024) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(evn.currentTarget.files.length >= 10) {
|
||||
NewNotification(tr("error"), tr("max_attached_photos"))
|
||||
return;
|
||||
}
|
||||
|
||||
formdata.append("photo_"+iterator, fille)
|
||||
iterator += 1
|
||||
}
|
||||
|
||||
xhr.onloadstart = () => {
|
||||
evn.currentTarget.parentNode.insertAdjacentHTML("beforeend", `<img id="loader" style="max-height: 8px;max-width: 36px;" src="/assets/packages/static/openvk/img/loading_mini.gif">`)
|
||||
}
|
||||
|
||||
xhr.onload = () => {
|
||||
let result = JSON.parse(xhr.responseText)
|
||||
|
||||
u("#loader").remove()
|
||||
if(result.success) {
|
||||
for(const pht of result.photos) {
|
||||
let id = pht.owner + "_" + pht.vid
|
||||
|
||||
if(!insertAttachment(id)) {
|
||||
return
|
||||
}
|
||||
|
||||
u(form.querySelector(`.upload`)).append(u(`
|
||||
<div class="upload-item" id="aP" data-id="${pht.owner + "_" + pht.vid}">
|
||||
<a class="upload-delete">×</a>
|
||||
<img src="${pht.url}">
|
||||
</div>
|
||||
`));
|
||||
|
||||
u(`.upload #aP[data-id='${pht.owner + "_" + pht.vid}'] .upload-delete`).on("click", () => {
|
||||
form.querySelector("input[name='photos']").value = form.querySelector("input[name='photos']").value.replace(id + ",", "")
|
||||
u(form.querySelector(`.upload #aP[data-id='${id}']`)).remove()
|
||||
})
|
||||
}
|
||||
|
||||
u("body").removeClass("dimmed");
|
||||
u(".ovk-diag-cont").remove();
|
||||
document.querySelector("html").style.overflowY = "scroll"
|
||||
} else {
|
||||
// todo: https://vk.com/wall-32295218_78593
|
||||
alert(result.flash.message)
|
||||
}
|
||||
}
|
||||
|
||||
formdata.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
formdata.append("count", iterator)
|
||||
|
||||
xhr.send(formdata)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -412,6 +412,18 @@
|
|||
"tip" = "Tip";
|
||||
"tip_ctrl" = "to select multiple photos at once, hold down the Ctrl key when selecting files in Windows or the CMD key in Mac OS.";
|
||||
"album_poster" = "Album poster";
|
||||
"select_photo" = "Select photos";
|
||||
"upload_new_photo" = "Upload new photo";
|
||||
|
||||
"is_x_photos_zero" = "Just zero photos.";
|
||||
"is_x_photos_one" = "Just one photo.";
|
||||
"is_x_photos_few" = "Just $1 photos.";
|
||||
"is_x_photos_many" = "Just $1 photos.";
|
||||
"is_x_photos_other" = "Just $1 photos.";
|
||||
|
||||
"all_photos" = "All photos";
|
||||
"error_uploading_photo" = "Error when uploading photo. Error text: ";
|
||||
"too_many_photos" = "Too many photos.";
|
||||
|
||||
/* Notes */
|
||||
|
||||
|
@ -697,6 +709,7 @@
|
|||
"selecting_video" = "Selecting videos";
|
||||
"upload_new_video" = "Upload new video";
|
||||
"max_attached_videos" = "Max is 10 videos";
|
||||
"max_attached_photos" = "Max is 10 photos";
|
||||
"no_videos" = "You don't have uploaded videos.";
|
||||
"no_videos_results" = "No results.";
|
||||
|
||||
|
|
|
@ -394,6 +394,18 @@
|
|||
"tip" = "Подсказка";
|
||||
"tip_ctrl" = "для того, чтобы выбрать сразу несколько фотографий, удерживайте клавишу Ctrl при выборе файлов в ОС Windows или клавишу CMD в Mac OS.";
|
||||
"album_poster" = "Обложка альбома";
|
||||
"select_photo" = "Выберите фотографию";
|
||||
"upload_new_photo" = "Загрузить новую фотографию";
|
||||
|
||||
"is_x_photos_zero" = "Всего ноль фотографий.";
|
||||
"is_x_photos_one" = "Всего одна фотография.";
|
||||
"is_x_photos_few" = "Всего $1 фотографии.";
|
||||
"is_x_photos_many" = "Всего $1 фотографий.";
|
||||
"is_x_photos_other" = "Всего $1 фотографий.";
|
||||
|
||||
"all_photos" = "Все фотографии";
|
||||
"error_uploading_photo" = "Не удалось загрузить фотографию. Текст ошибки: ";
|
||||
"too_many_photos" = "Слишком много фотографий.";
|
||||
|
||||
/* Notes */
|
||||
|
||||
|
@ -656,6 +668,7 @@
|
|||
"selecting_video" = "Выбор видеозаписей";
|
||||
"upload_new_video" = "Загрузить новое видео";
|
||||
"max_attached_videos" = "Максимум 10 видеозаписей";
|
||||
"max_attached_photos" = "Максимум 10 фотографий";
|
||||
"no_videos" = "У вас нет видео.";
|
||||
"no_videos_results" = "Нет результатов.";
|
||||
|
||||
|
|
Loading…
Reference in a new issue