changes to photo viewer + photo/video pages layout

This commit is contained in:
mrilyew 2024-11-07 18:20:25 +03:00
parent 6c2d6f9dd6
commit 890961e63d
16 changed files with 505 additions and 288 deletions

View file

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

View file

@ -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('large'),
"id" => $attachment->getPrettyId() "id" => $attachment->getPrettyId(),
]; ];
} }
} }

View file

@ -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
@ -355,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]");
}
} }

View file

@ -11,11 +11,11 @@
<div class="playIcon"></div> <div class="playIcon"></div>
</div> </div>
<div class="status"> <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 draggable='false' href="/search?section=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>

View file

@ -4,76 +4,69 @@
{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>
<h4>{_information}</h4>
<span style="color: grey;">{_info_description}:</span>
{$photo->getDescription() ?? "(" . tr("none") . ")"}<br/>
<span style="color: grey;">{_info_uploaded_by}:</span>
<a href="{$photo->getOwner()->getURL()}">{$photo->getOwner()->getFullName()}</a><br/>
<span style="color: grey;">{_info_upload_date}:</span>
{$photo->getPublicationTime()}
</div>
<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")], [ <div class='ovk-photo-details'>
(function() { <div class='media-page-wrapper-description'>
res = document.querySelector("#uReportMsgInput").value; <p n:if='!empty($photo->getDescription())'>{$photo->getDescription()}</p>
xhr = new XMLHttpRequest(); <div class='upload_time'>
xhr.open("GET", "/report/" + {$photo->getId()} + "?reason=" + res + "&type=photo", true); {_info_upload_date}: {$photo->getPublicationTime()}
xhr.onload = (function() { {if isset($thisUser)}
if(xhr.responseText.indexOf("reason") === -1) |
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]); {var $liked = $photo->hasLikeFrom($thisUser)}
else {var $likesCount = $photo->getLikesCount()}
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]); <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}">
xhr.send(null); <div class="heart" id="{if $liked}liked{/if}"></div>
}), <span class="likeCnt">{if $likesCount > 0}{$likesCount}{/if}</span>
Function.noop </a>
]); </div>
} {/if}
</script> </div>
</div>
<hr/>
<div class="media-page-wrapper-details">
<div class='media-page-wrapper-comments'>
{include "../components/comments.xml", comments => $comments, count => $cCount, page => $cPage, model => "photos", parent => $photo, custom_id => 999}
</div>
<div class='media-page-wrapper-actions'>
<a href="{$owner->getURL()}" class='media-page-author-block'>
<img class='cCompactAvatars' src="{$owner->getAvatarURL('miniscule')}">
<div class='media-page-author-block-name'>
<b>{$owner->getCanonicalName()}</b>
</div>
</a>
<div n:if="isset($thisUser) && $thisUser->getId() === $photo->getOwner()->getId()">
<a href="/photo{$photo->getPrettyId()}/edit" class="profile_link" style="display:block;width:96%;">{_edit}</a>
<a id="_photoDelete" href="/photo{$photo->getPrettyId()}/delete" class="profile_link" style="display:block;width:96%;">{_delete}</a>
</div>
<a href="{$photo->getURL()}" class="profile_link" target="_blank" style="display:block;width:96%;">{_"open_original"}</a>
<a n:if="isset($thisUser) && $thisUser->getId() != $photo->getOwner()->getId()" class="profile_link" style="display:block;width:96%;" href="javascript:reportPhoto({$photo->getId()})">{_report}</a>
</div>
</div>
</div> </div>
</div> </div>
{/block} {/block}

View file

@ -11,91 +11,108 @@
{/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>
</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()">{_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>
</div> </div>
{/block} {/block}

View file

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

View file

@ -171,6 +171,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}"

View file

@ -783,6 +783,7 @@
.addToPlaylist { .addToPlaylist {
width: 22%; width: 22%;
float: left;
} }
#_addAudioAdditional { #_addAudioAdditional {

View file

@ -13,7 +13,7 @@ body {
word-wrap: break-word; word-wrap: break-word;
} }
body, .ovk-fullscreen-dimmer { body, .ovk-fullscreen-dimmer, .ovk-photo-view-dimmer {
scrollbar-gutter: stable both-edges; scrollbar-gutter: stable both-edges;
} }
@ -1574,6 +1574,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;
@ -1583,12 +1592,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;
} }
@ -2439,6 +2458,7 @@ a.poll-retract-vote {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: relative; position: relative;
min-height: 63px;
} }
.post-horizontal .upload-item .play-button, .compact_video .play-button { .post-horizontal .upload-item .play-button, .compact_video .play-button {
@ -2551,21 +2571,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 {
@ -2577,7 +2609,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;
} }
@ -2586,11 +2617,25 @@ 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;
}
.ovk-photo-view .ovk-photo-details {
margin-top: 10px;
}
.client_app > img { .client_app > img {
top: 3px; top: 3px;
position: relative; position: relative;
@ -3535,3 +3580,72 @@ hr {
color: white; color: white;
} }
.media-page-wrapper .photo-page-wrapper-photo {
margin-bottom: 8pt;
text-align: center;
}
.media-page-wrapper .video-page-wrapper-video {
text-align: center;
}
.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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -49,7 +49,7 @@ window.OVKAPI = new class {
if(json_response.response) { if(json_response.response) {
return json_response.response return json_response.response
} else { } else {
throw new Exception(json_response.error_msg) throw new Error(json_response.error_msg)
} }
} }
} }

View file

@ -85,175 +85,207 @@ u(document).on("input", "textarea", function(e) {
// textArea.style.height = (newHeight > originalHeight ? (newHeight + boost) : originalHeight) + "px"; // textArea.style.height = (newHeight > originalHeight ? (newHeight + boost) : originalHeight) + "px";
}); });
function OpenMiniature(e, photo, post, photo_id, type = "post") { async function OpenMiniature(e, photo, post, photo_id, type = "post") {
/* /*
костыли но смешные однако костыли но смешные однако
*/ */
e.preventDefault(); e.preventDefault();
if(u(".ovk-photo-view").length > 0) u(".ovk-photo-view-dimmer").remove();
// Значения для переключения фоток // Значения для переключения фоток
const albums_per_page = 20
let json; let json;
let offset = type == 'album' ? (Number((new URL(location.href)).searchParams.get('p') ?? 1) - 1) * albums_per_page : 0
let shown_offset = 0
let imagesCount = 0; let imagesCount = 0;
let imagesIndex = 0; let currentImageid = '0_0';
let tempDetailsSection = []; const photo_viewer = new CMessageBox({
title: '',
let dialog = u( custom_template: u(`
`<div class="ovk-photo-view-dimmer"> <div class="ovk-photo-view-dimmer">
<div class="ovk-photo-view"> <div class="ovk-photo-view">
<div class="photo_com_title"> <div class="photo_com_title">
<text id="photo_com_title_photos"> <text id="photo_com_title_photos">
<img src="/assets/packages/static/openvk/img/loading_mini.gif">
</text>
<div>
<a id="ovk-photo-close">${tr("close")}</a>
</div>
</div>
<div class='photo_viewer_wrapper'>
<div class="ovk-photo-slide-left"></div>
<div class="ovk-photo-slide-right"></div>
<img src="${photo}" id="ovk-photo-img">
</div>
<div class="ovk-photo-details">
<img src="/assets/packages/static/openvk/img/loading_mini.gif"> <img src="/assets/packages/static/openvk/img/loading_mini.gif">
</text>
<div>
<a id="ovk-photo-close">${tr("close")}</a>
</div> </div>
</div> </div>
<center style="margin-bottom: 8pt; position: relative;"> </div>`)
<div class="ovk-photo-slide-left"></div> })
<div class="ovk-photo-slide-right"></div>
<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">
</div>
</div>
</div>`);
u("body").addClass("dimmed").append(dialog);
document.querySelector("html").style.overflowY = "hidden"
let button = u("#ovk-photo-close"); photo_viewer.getNode().find("#ovk-photo-close").on("click", function(e) {
photo_viewer.close()
button.on("click", function(e) {
let __closeDialog = () => {
u("body").removeClass("dimmed");
u(".ovk-photo-view-dimmer").remove();
document.querySelector("html").style.overflowY = "scroll"
};
__closeDialog();
}); });
function __reloadTitleBar() { function __getIndex(photo_id = null) {
u("#photo_com_title_photos").last().innerHTML = imagesCount > 1 ? tr("photo_x_from_y", imagesIndex, imagesCount) : tr("photo"); return Object.keys(json.body).findIndex(item => item == (photo_id ?? currentImageid)) + 1
} }
function __loadDetails(photo_id, index) { function __getByIndex(id) {
if(tempDetailsSection[index] == null) { const ids = Object.keys(json.body)
u(".ovk-photo-details").last().innerHTML = '<img src="/assets/packages/static/openvk/img/loading_mini.gif">'; const _id = ids[id - 1]
ky("/photo" + photo_id, {
hooks: {
afterResponse: [
async (_request, _options, response) => {
let parser = new DOMParser();
let body = parser.parseFromString(await response.text(), "text/html");
let element = u(body.getElementsByClassName("ovk-photo-details")).last(); return json.body[_id]
}
tempDetailsSection[index] = element.innerHTML; function __reloadTitleBar() {
photo_viewer.getNode().find("#photo_com_title_photos").last().innerHTML = imagesCount > 1 ? tr("photo_x_from_y", shown_offset, imagesCount) : tr("photo");
}
if(index == imagesIndex) { async function __loadDetails(photo_id) {
u(".ovk-photo-details").last().innerHTML = element.innerHTML ?? ''; if(json.body[photo_id].cached == null) {
} photo_viewer.getNode().find(".ovk-photo-details").last().innerHTML = '<img src="/assets/packages/static/openvk/img/loading_mini.gif">';
const photo_url = `/photo${photo_id}`
const photo_page = await fetch(photo_url)
const photo_text = await photo_page.text()
const parser = new DOMParser
const body = parser.parseFromString(photo_text, "text/html")
const details = body.querySelector('.ovk-photo-details')
json.body[photo_id].cached = details.innerHTML ?? ''
if(photo_id == currentImageid) {
photo_viewer.getNode().find(".ovk-photo-details").last().innerHTML = details.innerHTML ?? '';
}
document.querySelectorAll(".ovk-photo-details .bsdn").forEach(bsdnInitElement) photo_viewer.getNode().find(".ovk-photo-details .bsdn").nodes.forEach(bsdnInitElement)
document.querySelectorAll(".ovk-photo-details script").forEach(scr => {
// stolen from #953
let newScr = document.createElement('script')
if(scr.src) {
newScr.src = scr.src
} else {
newScr.textContent = scr.textContent
}
document.querySelector(".ovk-photo-details").appendChild(newScr);
})
}
]
}
});
} else { } else {
u(".ovk-photo-details").last().innerHTML = tempDetailsSection[index]; photo_viewer.getNode().find(".ovk-photo-details").last().innerHTML = json.body[photo_id].cached
} }
} }
function __slidePhoto(direction) { async function __slidePhoto(direction) {
/* direction = 1 - right /* direction = 1 - right
direction = 0 - left */ direction = 0 - left */
if(json == undefined) { if(json == undefined) {
console.log("Да подожди ты. Куда торопишься?"); console.log("Да подожди ты. Куда торопишься?");
} else { } else {
if(imagesIndex >= imagesCount && direction == 1) { let current_index = __getIndex()
imagesIndex = 1; if(current_index >= imagesCount && direction == 1) {
} else if(imagesIndex <= 1 && direction == 0) { shown_offset = 1
imagesIndex = imagesCount; current_index = 1
} else if(current_index <= 1 && direction == 0) {
shown_offset += imagesCount - 1
current_index = imagesCount
} else if(direction == 1) { } else if(direction == 1) {
imagesIndex++; shown_offset += 1
current_index += 1
} else if(direction == 0) { } else if(direction == 0) {
imagesIndex--; shown_offset -= 1
current_index -= 1
} }
let photoURL = json.body[imagesIndex - 1].url; currentImageid = __getByIndex(current_index)
if(!currentImageid) {
if(type == 'album') {
if(direction == 1) {
offset += albums_per_page
} else {
offset -= albums_per_page
}
u("#ovk-photo-img").last().src = photoURL; await __loadContext(type, post, true, direction == 0)
} else {
return
}
}
currentImageid = currentImageid.id
let photoURL = json.body[currentImageid].url;
photo_viewer.getNode().find("#ovk-photo-img").last().src = ''
photo_viewer.getNode().find("#ovk-photo-img").last().src = photoURL;
__reloadTitleBar(); __reloadTitleBar();
__loadDetails(json.body[imagesIndex - 1].id, imagesIndex); __loadDetails(json.body[currentImageid].id);
} }
} }
let slideLeft = u(".ovk-photo-slide-left"); async function __loadContext(type, id, ref = false, inverse = false) {
if(type == 'post' || type == 'comment') {
const form_data = new FormData()
form_data.append('parentType', type);
slideLeft.on("click", (e) => { const endpoint_url = `/iapi/getPhotosFromPost/${type == "post" ? id : "1_"+id}`
__slidePhoto(0); const fetcher = await fetch(endpoint_url, {
}); method: 'POST',
body: form_data,
})
json = await fetcher.json()
imagesCount = Object.entries(json.body).length
} else {
const params = {
'offset': offset,
'count': albums_per_page,
'owner_id': id.split('_')[0],
'album_id': id.split('_')[1],
'photo_sizes': 1
}
let slideRight = u(".ovk-photo-slide-right"); const result = await window.OVKAPI.call('photos.get', params)
const converted_items = {}
slideRight.on("click", (e) => { result.items.forEach(item => {
__slidePhoto(1); const id = item.owner_id + '_' + item.id
}); converted_items[id] = {
'url': item.src_xbig,
'id': id,
}
})
imagesCount = result.count
let data = new FormData() if(!json)
data.append('parentType', type); json = {'body': []}
if(type) { if(!inverse) {
ky.post("/iapi/getPhotosFromPost/" + (type == "post" ? post : "1_"+post), { json.body = Object.assign(converted_items, json.body)
hooks: { } else {
afterResponse: [ json.body = Object.assign(json.body, converted_items)
async (_request, _options, response) => { }
json = await response.json(); }
imagesCount = json.body.length; currentImageid = photo_id
imagesIndex = 0;
// Это всё придётся правда на 1 прибавлять
json.body.every(element => {
imagesIndex++;
if(element.id == photo_id) {
return false;
} else {
return true;
}
});
__reloadTitleBar();
__loadDetails(json.body[imagesIndex - 1].id, imagesIndex); }
]
},
body: data
});
} else {
imagesCount = 1
__reloadTitleBar()
__loadDetails(photo_id, imagesIndex)
} }
return u(".ovk-photo-view-dimmer"); photo_viewer.getNode().find(".ovk-photo-slide-left").on("click", (e) => {
__slidePhoto(0);
})
photo_viewer.getNode().find(".ovk-photo-slide-right").on("click", (e) => {
__slidePhoto(1);
})
if(!type) {
imagesCount = 1
json = {
'body': {}
}
json.body[photo_id] = {
'id': photo_id,
'url': photo
}
currentImageid = photo_id
__reloadTitleBar()
__loadDetails(photo_id)
} else {
await __loadContext(type, post)
shown_offset = offset + __getIndex()
__reloadTitleBar();
__loadDetails(json.body[currentImageid].id);
}
return photo_viewer.getNode()
} }
u("#write > form").on("keydown", function(event) { u("#write > form").on("keydown", function(event) {
@ -261,6 +293,28 @@ u("#write > form").on("keydown", function(event) {
this.submit(); this.submit();
}); });
function reportPhoto(photo_id) {
uReportMsgTxt = tr("going_to_report_photo");
uReportMsgTxt += "<br/>"+tr("report_question_text");
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
MessageBox(tr("report_question"), uReportMsgTxt, [tr("confirm_m"), tr("cancel")], [
(function() {
res = document.querySelector("#uReportMsgInput").value;
xhr = new XMLHttpRequest();
xhr.open("GET", "/report/" + photo_id + "?reason=" + res + "&type=photo", true);
xhr.onload = (function() {
if(xhr.responseText.indexOf("reason") === -1)
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]);
else
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]);
});
xhr.send(null);
}),
Function.noop
]);
}
var tooltipClientTemplate = Handlebars.compile(` var tooltipClientTemplate = Handlebars.compile(`
<table> <table>
<tr> <tr>

View file

@ -9,6 +9,7 @@ class CMessageBox {
const close_on_buttons = options.close_on_buttons ?? true const close_on_buttons = options.close_on_buttons ?? true
const unique_name = options.unique_name ?? null const unique_name = options.unique_name ?? null
const warn_on_exit = options.warn_on_exit ?? false const warn_on_exit = options.warn_on_exit ?? false
const custom_template = options.custom_template ?? null
if(unique_name && window.messagebox_stack.find(item => item.unique_name == unique_name) != null) { if(unique_name && window.messagebox_stack.find(item => item.unique_name == unique_name) != null) {
return return
} }
@ -20,7 +21,14 @@ class CMessageBox {
this.unique_name = unique_name this.unique_name = unique_name
this.warn_on_exit = warn_on_exit this.warn_on_exit = warn_on_exit
u('body').addClass('dimmed').append(this.__getTemplate()) 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)
}
u('html').attr('style', 'overflow-y:hidden') u('html').attr('style', 'overflow-y:hidden')
buttons.forEach((text, callback) => { buttons.forEach((text, callback) => {
@ -40,7 +48,7 @@ class CMessageBox {
__getTemplate() { __getTemplate() {
return u( return u(
`<div class="ovk-diag-cont" data-id="${this.id}"> `<div class="ovk-diag-cont ovk-msg-all" data-id="${this.id}">
<div class="ovk-diag"> <div class="ovk-diag">
<div class="ovk-diag-head">${this.title}</div> <div class="ovk-diag-head">${this.title}</div>
<div class="ovk-diag-body">${this.body}</div> <div class="ovk-diag-body">${this.body}</div>
@ -50,7 +58,7 @@ class CMessageBox {
} }
getNode() { getNode() {
return u(`.ovk-diag-cont[data-id='${this.id}']`) return u(`.ovk-msg-all[data-id='${this.id}']`)
} }
async __showCloseConfirmationDialog() { async __showCloseConfirmationDialog() {
@ -73,8 +81,8 @@ class CMessageBox {
} }
__exitDialog() { __exitDialog() {
u(`.ovk-diag-cont[data-id='${this.id}']`).remove() this.getNode().remove()
if(u('.ovk-diag-cont').length < 1) { if(u('.ovk-msg-all').length < 1) {
u('body').removeClass('dimmed') u('body').removeClass('dimmed')
u('html').attr('style', 'overflow-y:scroll') u('html').attr('style', 'overflow-y:scroll')
} }

View file

@ -48,7 +48,7 @@ function parseAjaxResponse(responseString) {
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>";