optimize likes and foto piker & add photo drag

This commit is contained in:
mrilyew 2024-11-04 15:41:02 +03:00
parent 4cb88f94dc
commit 88d3057cf3
19 changed files with 418 additions and 1058 deletions

View file

@ -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);
}
}

View file

@ -11,6 +11,12 @@ final class Groups extends VKAPIRequestHandler
{
$this->requireUser();
# InfoApp fix
if($filter == "admin" && ($user_id != 0 && $user_id != $this->getUser()->getId())) {
$this->fail(15, 'Access denied: filter admin is available only for current user');
}
$clbs = [];
if($user_id == 0) {
foreach($this->getUser()->getClubs($offset, $filter == "admin", $count, true) as $club)
$clbs[] = $club;

View file

@ -427,7 +427,7 @@ final class Photos extends VKAPIRequestHandler
$this->fail(15, "Access denied");
$photos = array_slice(iterator_to_array($album->getPhotos(1, $count + $offset)), $offset);
$res["count"] = sizeof($photos);
$res["count"] = $album->size();
foreach($photos as $photo) {
if(!$photo || $photo->isDeleted()) continue;
@ -638,15 +638,15 @@ final class Photos extends VKAPIRequestHandler
$this->fail(4, "This method doesn't works with clubs");
$user = (new UsersRepo)->get($owner_id);
if(!$user)
$this->fail(4, "Invalid user");
if(!$user->getPrivacyPermission('photos.read', $this->getUser()))
$this->fail(21, "This user chose to hide his albums.");
$photos = array_slice(iterator_to_array((new PhotosRepo)->getEveryUserPhoto($user, 1, $count + $offset)), $offset);
$photos = (new PhotosRepo)->getEveryUserPhoto($user, $offset, $count);
$res = [
"count" => (new PhotosRepo)->getUserPhotosCount($user),
"items" => [],
];

View file

@ -87,6 +87,7 @@ class Album extends MediaCollection
$res = (object) [];
$res->id = $this->getPrettyId();
$res->vid = $this->getId();
$res->thumb_id = !is_null($this->getCoverPhoto()) ? $this->getCoverPhoto()->getPrettyId() : 0;
$res->owner_id = $this->getOwner()->getId();
$res->title = $this->getName();

View file

@ -308,7 +308,7 @@ class Photo extends Media
$res->date = $res->created = $this->getPublicationTime()->timestamp();
if($photo_sizes) {
$res->sizes = $this->getVkApiSizes();
$res->sizes = array_values($this->getVkApiSizes());
$res->src_small = $res->photo_75 = $this->getURLBySizeId("miniscule");
$res->src = $res->photo_130 = $this->getURLBySizeId("tiny");
$res->src_big = $res->photo_604 = $this->getURLBySizeId("normal");

View file

@ -33,7 +33,7 @@ class Photos
return new Photo($photo);
}
function getEveryUserPhoto(User $user, int $page = 1, ?int $perPage = NULL): \Traversable
function getEveryUserPhoto(User $user, int $offset = 0, int $limit = 10): \Traversable
{
$perPage = $perPage ?? OPENVK_DEFAULT_PER_PAGE;
$photos = $this->photos->where([
@ -41,7 +41,7 @@ class Photos
"deleted" => 0
])->order("id DESC");
foreach($photos->page($page, $perPage) as $photo) {
foreach($photos->limit($limit, $offset) as $photo) {
yield new Photo($photo);
}
}

View file

@ -33,6 +33,7 @@ final class AudioPresenter extends OpenVKPresenter
function renderList(?int $owner = NULL, ?string $mode = "list"): void
{
$this->assertUserLoggedIn();
$this->template->_template = "Audio/List.xml";
$page = (int)($this->queryParam("p") ?? 1);
$audios = [];
@ -501,6 +502,7 @@ final class AudioPresenter extends OpenVKPresenter
function renderPlaylist(int $owner_id, int $virtual_id): void
{
$this->assertUserLoggedIn();
$playlist = $this->audios->getPlaylistByOwnerAndVID($owner_id, $virtual_id);
$page = (int)($this->queryParam("p") ?? 1);
if (!$playlist || $playlist->isDeleted())

View file

@ -27,7 +27,12 @@ final class CommentPresenter extends OpenVKPresenter
$this->flashFail("err", tr("error"), tr("forbidden"));
if(!is_null($this->user)) $comment->toggleLike($this->user->identity);
if($_SERVER["REQUEST_METHOD"] === "POST") {
$this->returnJson([
'success' => true,
]);
}
$this->redirect($_SERVER["HTTP_REFERER"]);
}
@ -108,7 +113,7 @@ final class CommentPresenter extends OpenVKPresenter
continue;
}
$post->attach($horizontal_attachment);
$comment->attach($horizontal_attachment);
}
foreach($vertical_attachments as $vertical_attachment) {
@ -116,7 +121,7 @@ final class CommentPresenter extends OpenVKPresenter
continue;
}
$post->attach($vertical_attachment);
$comment->attach($vertical_attachment);
}
if($entity->getOwner()->getId() !== $this->user->identity->getId())

View file

@ -287,7 +287,8 @@ final class PhotosPresenter extends OpenVKPresenter
"id" => $photo->getId(),
"vid" => $photo->getVirtualId(),
"owner" => $photo->getOwner()->getId(),
"link" => $photo->getURL()
"link" => $photo->getURL(),
"pretty_id" => $photo->getPrettyId(),
];
} catch(ISE $ex) {
$name = $album->getName();

View file

@ -412,6 +412,12 @@ final class WallPresenter extends OpenVKPresenter
if(!is_null($this->user)) {
$post->toggleLike($this->user->identity);
}
if($_SERVER["REQUEST_METHOD"] === "POST") {
$this->returnJson([
'success' => true,
]);
}
$this->redirect("$_SERVER[HTTP_REFERER]#postGarter=" . $post->getId());
}

View file

@ -427,6 +427,9 @@
window.openvk = {
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres},
"at_search": {$atSearch ?? false},
"max_attachments": {\OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"]},
"max_filesize_mb": 5,
"current_id": {$thisUser ? $thisUser->getId() : 0},
}
</script>

View file

@ -148,7 +148,7 @@
&nbsp;|&nbsp;
{/if}
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}>
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repost('{$post->getPrettyId()}', 'post')"{/ifset}>
{_share}
{if $repostsCount > 0}
(<b id="repostsCount{$post->getPrettyId()}">{$repostsCount}</b>)

View file

@ -2,26 +2,18 @@
{var $textAreaId = ($post ?? NULL) === NULL ? (++$GLOBALS["textAreaCtr"]) : $post->getId()}
{var $textAreaId = ($custom_id ?? NULL) === NULL ? $textAreaId : $custom_id}
<div id="write" style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
<div id="write" class='model_content_textarea' style="padding: 5px 0;" onfocusin="expand_wall_textarea({$textAreaId});">
<form action="{$route}" method="post" enctype="multipart/form-data" style="margin:0;">
<textarea id="wall-post-input{$textAreaId}" placeholder="{_write}" name="text" style="width: 100%;resize: none;" class="small-textarea"></textarea>
<div>
<!-- padding to fix <br/> bug -->
</div>
<div id="post-buttons{$textAreaId}" style="display: none;">
<div class="upload">
</div>
<div class="post-upload">
<span style="color: inherit;"></span>
</div>
<div id="post-buttons{$textAreaId}" class='post-buttons' style="display: none;">
<div class="post-horizontal"></div>
<div class="post-vertical"></div>
<div class="post-has-poll">
{_poll}
</div>
<div class="post-has-note"></div>
<div class="post-has-videos"></div>
<div class="post-has-audios"></div>
<div class="post-source"></div>
<div n:if="$postOpts ?? true" class="post-opts">
@ -71,15 +63,15 @@
<br/>
<input type="submit" value="{_write}" class="button" />
<div style="float: right; display: flex; flex-direction: column;">
<a href="javascript:toggleMenu({$textAreaId});">
<a class='menu_toggler'>
{_attach}
</a>
<div id="wallAttachmentMenu" class="hidden">
<a class="header" href="javascript:toggleMenu({$textAreaId});">
<a class="header menu_toggler">
{_attach}
</a>
<a id="photosAttachments" {if !is_null($club ?? NULL) && $club->canBeModifiedBy($thisUser)}data-club="{$club->getId()}"{/if}>
<a id="__photoAttachment" {if !is_null($club ?? NULL) && $club->canBeModifiedBy($thisUser)}data-club="{$club->getId()}"{/if}>
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/application-x-egon.png" />
{_photo}
</a>
@ -91,11 +83,11 @@
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/mimetypes/audio-ac3.png" />
{_audio}
</a>
<a n:if="$graffiti ?? false" href="javascript:initGraffiti({$textAreaId});">
<a n:if="$graffiti ?? false" onclick="initGraffiti(event);">
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/draw-brush.png" />
{_graffiti}
</a>
<a n:if="$polls ?? false" href="javascript:initPoll({$textAreaId})">
<a n:if="$polls ?? false" onclick="initPoll(event);">
<img src="/assets/packages/static/openvk/img/oxygen-icons/16x16/actions/office-chart-bar-stacked.png" />
{_poll}
</a>
@ -110,10 +102,6 @@
</div>
<script>
$(document).ready(() => {
setupWallPostInputHandlers({$textAreaId});
});
u("#post-buttons{$textAreaId} input[name='horizontal_attachments']")["nodes"].at(0).value = ""
u("#post-buttons{$textAreaId} input[name='vertical_attachments']")["nodes"].at(0).value = ""
</script>

View file

@ -50,6 +50,11 @@ h1 {
flex-direction: column;
}
.display_flex_row {
display: flex;
flex-direction: row;
}
.layout {
width: 791px;
margin: 0 auto;
@ -264,7 +269,7 @@ h1 {
}
.upLeftErrors {
position: absolute;
position: fixed;
display: flex;
flex-direction: column;
z-index: 1025;
@ -1747,12 +1752,14 @@ body.scrolled .toTop:hover {
#wallAttachmentMenu {
position: absolute;
min-width: 94px;
border: 1px solid darkgrey;
background-color: white;
z-index: 32;
margin-top: -7px;
margin-left: -16px;
box-shadow: 0 1px 3px -1px;
user-select: none;
}
#wallAttachmentMenu>a {
@ -2406,16 +2413,27 @@ a.poll-retract-vote {
}
}
.upload {
.post-horizontal {
margin-top: 8px;
}
.upload .upload-item {
width: 75px;
height: 60px;
.post-horizontal {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 3px;
}
.post-horizontal .upload-item {
/*width: 75px;
height: 60px;*/
overflow: hidden;
display: inline-block;
margin-right: 3px;
position: relative;
}
.post-horizontal .upload-item.dragged {
filter: contrast(0.5);
}
.upload-item .upload-delete {
@ -2425,7 +2443,7 @@ a.poll-retract-vote {
text-decoration: none;
color: #fff;
font-size: 11px;
margin-left: 57px; /* мне лень переделывать :DDDD */
right: 0px;
opacity: 0;
transition: 0.25s;
}
@ -3141,10 +3159,61 @@ body.article .floating_sidebar, body.article .page_content {
font-size: 11px;
}
.topGrayBlock {
.attachment_selector .topGrayBlock {
background: #F0F0F0;
height: 37px;
border-bottom: 1px solid #C7C7C7;
padding: 3px 10px;
align-items: center;
justify-content: center;
justify-content: space-between;
}
.attachment_selector .topGrayBlock #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;
}
.edited {

View file

@ -64,8 +64,9 @@ function pollRadioPressed(radio) {
form.submit();
}
function initPoll(id) {
let form = $(`#wall-post-input${id}`).parent();
function initPoll(event) {
let form = $(event.target.closest('.post-buttons')).parent();
const id = random_int(0, 100)
let mBody = `
<div id="poll_editor${id}">
@ -87,9 +88,9 @@ function initPoll(id) {
</div>
`;
MessageBox(tr("create_poll"), mBody, [tr("attach"), tr("cancel")], [
const msg = MessageBox(tr("create_poll"), mBody, [tr("attach"), tr("cancel")], [
function() {
let dialog = $(this.$dialog().nodes[0]);
let dialog = $(msg.getNode().nodes[0]);
$("input", dialog).unbind();
let title = $("input[name=title]", dialog).val();
@ -117,9 +118,9 @@ function initPoll(id) {
$(".post-has-poll", form).show();
},
function() {
$("input", $(this.$dialog().nodes[0])).unbind();
$("input", $(msg.getNode())).unbind();
}
]);
], true);
let editor = $(`#poll_editor${id}`);
$("input[name=newOption]", editor).bind("focus", function() {

File diff suppressed because it is too large Load diff

View file

@ -46,16 +46,6 @@ function parseAjaxResponse(responseString) {
}
}
function toggleMenu(id) {
if($(`#post-buttons${id} #wallAttachmentMenu`).is('.hidden')) {
$(`#post-buttons${id} #wallAttachmentMenu`).css({ opacity: 0 });
$(`#post-buttons${id} #wallAttachmentMenu`).toggleClass('hidden').fadeTo(250, 1);
} else {
$(`#post-buttons${id} #wallAttachmentMenu`).fadeTo(250, 0, function () {
$(this).toggleClass('hidden');
});
}
}
document.addEventListener("DOMContentLoaded", function() { //BEGIN
$(document).on("click", "#_photoDelete", function(e) {

View file

@ -107,8 +107,12 @@ function random_int(min, max) {
return Math.round(Math.random() * (max - min) + min)
}
function makeError(text, color = 'Red', timeout = 10000) {
const rand_id = random_int(0, 10000)
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>

View file

@ -488,9 +488,10 @@
"click_to_go_to_album" = "Нажмите, чтобы перейти к альбому.";
"error_uploading_photo" = "Не удалось загрузить фотографию";
"too_many_pictures" = "Не больше 10 фотографий";
"too_many_attachments" = "Слишком много вложений.";
"drag_files_here" = "Перетащите файлы сюда";
"only_images_accepted" = "Файл \"$1\" не является изображением";
"only_images_accepted" = "Файл \"$1\" не является изображением или видео.";
"max_filesize" = "Максимальный размер файла — $1 мегабайт";
"uploading_photos_from_computer" = "Загрузка фотографий с Вашего компьютера";