From 77bd3932157618c29a9e345247af65300d8b98f5 Mon Sep 17 00:00:00 2001
From: lalka2018 <99399973+lalka2016@users.noreply.github.com>
Date: Sun, 4 Feb 2024 18:59:34 +0300
Subject: [PATCH] feat(profiles): add ability to crop avatar
Closes #1068 and maybe slash 106
---
Web/Presenters/GroupPresenter.php | 95 +++++++++---
Web/Presenters/UserPresenter.php | 63 ++++++--
Web/Presenters/templates/@layout.xml | 2 +
Web/Presenters/templates/Group/View.xml | 22 +--
Web/Presenters/templates/User/View.xml | 21 +--
Web/Presenters/templates/_includeCSS.xml | 4 +-
Web/routes.yml | 4 +
Web/static/css/avatar-edit.css | 182 ++++++++++++++++++++++
Web/static/css/avataredit.css | 88 -----------
Web/static/img/delete.png | Bin 263 -> 0 bytes
Web/static/img/upload.png | Bin 165 -> 923 bytes
Web/static/js/al_wall.js | 187 +++++++++++++++++++++++
Web/static/js/openvk.cls.js | 85 -----------
Web/static/js/package.json | 1 +
Web/static/js/yarn.lock | 24 +--
locales/en.strings | 8 +-
locales/ru.strings | 8 +-
themepacks/midnight/stylesheet.css | 4 +
18 files changed, 542 insertions(+), 256 deletions(-)
create mode 100644 Web/static/css/avatar-edit.css
delete mode 100644 Web/static/css/avataredit.css
delete mode 100644 Web/static/img/delete.png
diff --git a/Web/Presenters/GroupPresenter.php b/Web/Presenters/GroupPresenter.php
index beeede13..a0d1ce47 100644
--- a/Web/Presenters/GroupPresenter.php
+++ b/Web/Presenters/GroupPresenter.php
@@ -279,48 +279,99 @@ final class GroupPresenter extends OpenVKPresenter
function renderSetAvatar(int $id)
{
- $photo = new Photo;
+ $this->assertUserLoggedIn();
+ $this->willExecuteWriteAction();
+
$club = $this->clubs->get($id);
- if ($club->isBanned()) $this->flashFail("err", tr("error"), tr("forbidden"));
- if($_SERVER["REQUEST_METHOD"] === "POST" && $_FILES["ava"]["error"] === UPLOAD_ERR_OK) {
+
+ if(!$club || $club->isBanned() || !$club->canBeModifiedBy($this->user->identity))
+ $this->flashFail("err", tr("error"), tr("forbidden"), NULL, true);
+
+ if($_SERVER["REQUEST_METHOD"] === "POST" && $_FILES["blob"]["error"] === UPLOAD_ERR_OK) {
try {
+ $photo = new Photo;
+
$anon = OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["anonymousPosting"]["enable"];
if($anon && $this->user->id === $club->getOwner()->getId())
$anon = $club->isOwnerHidden();
else if($anon)
$anon = $club->getManager($this->user->identity)->isHidden();
+
$photo->setOwner($this->user->id);
$photo->setDescription("Club image");
- $photo->setFile($_FILES["ava"]);
+ $photo->setFile($_FILES["blob"]);
$photo->setCreated(time());
$photo->setAnonymous($anon);
$photo->save();
(new Albums)->getClubAvatarAlbum($club)->addPhoto($photo);
- $flags = 0;
- $flags |= 0b00010000;
- $flags |= 0b10000000;
+ if($this->postParam("on_wall") == 1) {
+ $post = new Post;
+
+ $post->setOwner($this->user->id);
+ $post->setWall($club->getId() * -1);
+ $post->setCreated(time());
+ $post->setContent("");
- $post = new Post;
- $post->setOwner($this->user->id);
- $post->setWall($club->getId()*-1);
- $post->setCreated(time());
- $post->setContent("");
- $post->setFlags($flags);
- $post->save();
- $post->attach($photo);
+ $flags = 0;
+ $flags |= 0b00010000;
+ $flags |= 0b10000000;
- } catch(ISE $ex) {
- $name = $album->getName();
- $this->flashFail("err", tr("error"), tr("error_when_uploading_photo"));
+ $post->setFlags($flags);
+ $post->save();
+
+ $post->attach($photo);
+ }
+
+ } catch(\Throwable $ex) {
+ $this->flashFail("err", tr("error"), tr("error_when_uploading_photo"), NULL, true);
}
+
+ $this->returnJson([
+ "success" => true,
+ "new_photo" => $photo->getPrettyId(),
+ "url" => $photo->getURL(),
+ ]);
+ } else {
+ return " ";
}
- $this->returnJson([
- "url" => $photo->getURL(),
- "id" => $photo->getPrettyId()
- ]);
}
+
+ function renderDeleteAvatar(int $id) {
+ $this->assertUserLoggedIn();
+ $this->willExecuteWriteAction();
+
+ $club = $this->clubs->get($id);
+
+ if(!$club || $club->isBanned() || !$club->canBeModifiedBy($this->user->identity))
+ $this->flashFail("err", tr("error"), tr("forbidden"), NULL, true);
+
+ $avatar = $club->getAvatarPhoto();
+
+ if(!$avatar)
+ $this->flashFail("succ", tr("error"), "no avatar bro", NULL, true);
+
+ $avatar->isolate();
+
+ $newAvatar = $club->getAvatarPhoto();
+
+ if(!$newAvatar)
+ $this->returnJson([
+ "success" => true,
+ "has_new_photo" => false,
+ "new_photo" => NULL,
+ "url" => "/assets/packages/static/openvk/img/camera_200.png",
+ ]);
+ else
+ $this->returnJson([
+ "success" => true,
+ "has_new_photo" => true,
+ "new_photo" => $newAvatar->getPrettyId(),
+ "url" => $newAvatar->getURL(),
+ ]);
+ }
+
function renderEditBackdrop(int $id): void
{
$this->assertUserLoggedIn();
diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php
index 3785e47b..2b8c3087 100644
--- a/Web/Presenters/UserPresenter.php
+++ b/Web/Presenters/UserPresenter.php
@@ -334,8 +334,7 @@ final class UserPresenter extends OpenVKPresenter
$this->redirect($user->getURL());
}
- function renderSetAvatar()
- {
+ function renderSetAvatar() {
$this->assertUserLoggedIn();
$this->willExecuteWriteAction();
@@ -346,8 +345,8 @@ final class UserPresenter extends OpenVKPresenter
$photo->setFile($_FILES["blob"]);
$photo->setCreated(time());
$photo->save();
- } catch(ISE $ex) {
- $this->flashFail("err", tr("error"), tr("error_upload_failed"));
+ } catch(\Throwable $ex) {
+ $this->flashFail("err", tr("error"), tr("error_upload_failed"), NULL, (int)$this->postParam("ajax", true) == 1);
}
$album = (new Albums)->getUserAvatarAlbum($this->user->identity);
@@ -358,23 +357,57 @@ final class UserPresenter extends OpenVKPresenter
$flags = 0;
$flags |= 0b00010000;
- $post = new Post;
- $post->setOwner($this->user->id);
- $post->setWall($this->user->id);
- $post->setCreated(time());
- $post->setContent("");
- $post->setFlags($flags);
- $post->save();
- $post->attach($photo);
- if($this->postParam("ava", true) == (int)1) {
+ if($this->postParam("on_wall") == 1) {
+ $post = new Post;
+ $post->setOwner($this->user->id);
+ $post->setWall($this->user->id);
+ $post->setCreated(time());
+ $post->setContent("");
+ $post->setFlags($flags);
+ $post->save();
+
+ $post->attach($photo);
+ }
+
+ if((int)$this->postParam("ajax", true) == 1) {
$this->returnJson([
- "url" => $photo->getURL(),
- "id" => $photo->getPrettyId()
+ "success" => true,
+ "new_photo" => $photo->getPrettyId(),
+ "url" => $photo->getURL(),
]);
} else {
$this->flashFail("succ", tr("photo_saved"), tr("photo_saved_comment"));
}
}
+
+ function renderDeleteAvatar() {
+ $this->assertUserLoggedIn();
+ $this->willExecuteWriteAction();
+
+ $avatar = $this->user->identity->getAvatarPhoto();
+
+ if(!$avatar)
+ $this->flashFail("succ", tr("error"), "no avatar bro", NULL, true);
+
+ $avatar->isolate();
+
+ $newAvatar = $this->user->identity->getAvatarPhoto();
+
+ if(!$newAvatar)
+ $this->returnJson([
+ "success" => true,
+ "has_new_photo" => false,
+ "new_photo" => NULL,
+ "url" => "/assets/packages/static/openvk/img/camera_200.png",
+ ]);
+ else
+ $this->returnJson([
+ "success" => true,
+ "has_new_photo" => true,
+ "new_photo" => $newAvatar->getPrettyId(),
+ "url" => $newAvatar->getURL(),
+ ]);
+ }
function renderSettings(): void
{
diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml
index d636ad42..a90fdc36 100644
--- a/Web/Presenters/templates/@layout.xml
+++ b/Web/Presenters/templates/@layout.xml
@@ -18,9 +18,11 @@
{script "js/l10n.js"}
{script "js/openvk.cls.js"}
{script "js/node_modules/dashjs/dist/dash.all.min.js"}
+
{script "js/al_music.js"}
{css "js/node_modules/tippy.js/dist/backdrop.css"}
+ {css "js/node_modules/cropperjs/dist/cropper.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/themes/light.css"}
diff --git a/Web/Presenters/templates/Group/View.xml b/Web/Presenters/templates/Group/View.xml
index 91a96119..79ef3704 100644
--- a/Web/Presenters/templates/Group/View.xml
+++ b/Web/Presenters/templates/Group/View.xml
@@ -127,25 +127,19 @@
{var $avatarPhoto = $club->getAvatarPhoto()}
{var $avatarLink = ((is_null($avatarPhoto) ? FALSE : $avatarPhoto->isAnonymous()) ? "/photo" . ("s/" . base_convert((string) $avatarPhoto->getId(), 10, 32)) : $club->getAvatarLink())}
-
- {var $hasAvatar = !str_contains($club->getAvatarUrl('miniscule'), "/assets/packages/static/openvk/img/camera_200.png")}
- {if !is_null($thisUser) && $hasAvatar == false && $club->canBeModifiedBy($thisUser)}
-
{_add_image_group}
- {elseif !is_null($thisUser) && $hasAvatar == true && $club->canBeModifiedBy($thisUser)}
-
-
-
-
+
+ {if $thisUser && $club->canBeModifiedBy($thisUser)}
+
{_add_image}
+
{/if}
+
-
+
diff --git a/Web/Presenters/templates/User/View.xml b/Web/Presenters/templates/User/View.xml
index a4a74508..a574bd83 100644
--- a/Web/Presenters/templates/User/View.xml
+++ b/Web/Presenters/templates/User/View.xml
@@ -69,27 +69,22 @@
{else}
-
+
{var $hasAvatar = !str_contains($user->getAvatarUrl('miniscule'), "/assets/packages/static/openvk/img/camera_200.png")}
- {if !is_null($thisUser) && $hasAvatar == false && $user->getId() == $thisUser->getId()}
-
{_add_image}
- {elseif !is_null($thisUser) && $user && $hasAvatar == true && $user->getId() == $thisUser->getId()}
-
-
-
-
+
+ {if $thisUser && $user->getId() == $thisUser->getId()}
+
{_add_image}
+
{/if}
diff --git a/Web/Presenters/templates/_includeCSS.xml b/Web/Presenters/templates/_includeCSS.xml
index 8e1aef6a..5edd88ae 100644
--- a/Web/Presenters/templates/_includeCSS.xml
+++ b/Web/Presenters/templates/_includeCSS.xml
@@ -9,7 +9,7 @@
{css "css/bsdn.css"}
{css "css/dialog.css"}
{css "css/notifications.css"}
- {css "css/avataredit.css"}
+ {css "css/avatar-edit.css"}
{css "css/audios.css"}
{if $isXmas}
@@ -27,7 +27,7 @@
{css "css/bsdn.css"}
{css "css/dialog.css"}
{css "css/notifications.css"}
- {css "css/avataredit.css"}
+ {css "css/avatar-edit.css"}
{css "css/audios.css"}
{if $isXmas}
diff --git a/Web/routes.yml b/Web/routes.yml
index d4496f03..51e76675 100644
--- a/Web/routes.yml
+++ b/Web/routes.yml
@@ -181,6 +181,8 @@ routes:
handler: "Photos->deletePhoto"
- url: "/al_avatars"
handler: "User->setAvatar"
+ - url: "/delete_avatar"
+ handler: "User->deleteAvatar"
- url: "/videos{num}"
handler: "Videos->list"
- url: "/videos/upload"
@@ -229,6 +231,8 @@ routes:
handler: "Group->edit"
- url: "/club{num}/al_avatar"
handler: "Group->setAvatar"
+ - url: "/club{num}/delete_avatar"
+ handler: "Group->deleteAvatar"
- url: "/club{num}/backdrop"
handler: "Group->editBackdrop"
- url: "/club{num}/stats"
diff --git a/Web/static/css/avatar-edit.css b/Web/static/css/avatar-edit.css
new file mode 100644
index 00000000..4f472e4d
--- /dev/null
+++ b/Web/static/css/avatar-edit.css
@@ -0,0 +1,182 @@
+.avatar_block {
+ position: relative;
+ clip-path: inset(0 0 0.7% 0);
+}
+
+.avatar_block .add_image_text {
+ position: absolute;
+ font-size: 12px;
+ color: #2B587A;
+ text-align: center;
+ width: 100%;
+ left: 0px;
+ bottom: 30px;
+}
+
+.avatar_block .add_image_text:hover {
+ text-decoration: underline;
+}
+
+#temp_uploadPic {
+ width: 40%;
+ margin-left: auto;
+ margin-right: auto;
+ display: block;
+}
+
+.hoverable {
+ transition: all 200ms ease-in-out;
+ opacity: 0.6;
+ cursor: pointer;
+}
+
+.hoverable:hover {
+ opacity: 1;
+}
+
+.avatar_block *, .avatar_block .avatarDelete::before {
+ -webkit-transition: all 200ms ease-in-out;
+ -moz-transition: all 200ms ease-in-out;
+ -o-transition: all 200ms ease-in-out;
+ transition: all 200ms ease-in-out;
+}
+
+._add_image::before {
+ margin-top: 2px;
+ content: ' ';
+ background: url('/assets/packages/static/openvk/img/upload.png');
+ width: 10px;
+ height: 10px;
+ display: inline-block;
+ margin-left: 15px;
+}
+
+.avatarDelete {
+ position: absolute;
+ right: 0%;
+ background-color: rgba(0, 0, 0, 0.75);
+ padding: 1px 0px 4px 3px;
+ border-radius: 0px 0px 0px 5px;
+ opacity: 0;
+ cursor: pointer;
+ width: 15px;
+ height: 13px;
+}
+
+.avatarDelete::before {
+ content: ' ';
+ background: url('/assets/packages/static/openvk/img/upload.png');
+ background-position: -10px 2px;
+ background-repeat: no-repeat;
+ width: 12px;
+ height: 14px;
+ display: inline-block;
+ opacity: 0.6;
+}
+
+div.avatar_block:hover .avatarDelete {
+ opacity: 1 !important;
+}
+
+div.avatar_block:hover .avatar_variants {
+ opacity: 1 !important;
+ margin-bottom: 1px;
+}
+
+.avatar_controls .avatar_variants {
+ opacity:0;
+ position:absolute;
+ background-color: rgba(0, 0, 0, 0.75);
+ width:100%;
+ bottom:0;
+ margin-bottom:-8px;
+ color:white;
+ padding-top: 2px;
+ padding-bottom: 2px;
+}
+
+.avatar_controls .avatar_variants a {
+ opacity: 60%;
+ display: flex;
+ user-select: none;
+ padding: 5px 0px;
+}
+
+.avatar_controls .avatar_variants span {
+ color: white;
+ margin-left: 6px;
+}
+
+.avatar_controls .avatar_variants a:hover, .avatarDelete:hover::before {
+ opacity: 100%;
+}
+
+.cropper-container.moving .cropper-point {
+ opacity: 1;
+}
+
+.cropper-modal {
+ opacity: 0.7;
+ background-color: #000;
+}
+
+.cropper-point {
+ transition: opacity 200ms ease-in-out;
+ background-color: #fff !important;
+ height: 7px !important;
+ width: 9px !important;
+ opacity: 0.6;
+ box-shadow: black 0px 0px 2px;
+}
+
+.cropper-line {
+ opacity: 0;
+}
+
+.cropper-container {
+ width: 421px;
+ height: 279px;
+}
+
+.cropper-view-box {
+ outline: none;
+ outline-color: unset;
+}
+
+.cropper-image-cont {
+ height: 100vh;
+}
+
+.cropper-image-cont img {
+ max-width: 100%;
+}
+
+.cropper-image-cont .rotateButtons {
+ height: 20px;
+ margin-top: -31px;
+ margin-right: 5px;
+ width: 45px;
+ float: right;
+ position: relative;
+ display: flex;
+ padding: 3px 5px 3px 2px;
+ background: rgba(0,0,0,0.5);
+}
+
+.cropper-image-cont .rotateButtons div {
+ background-repeat: no-repeat;
+}
+
+.cropper-image-cont .rotateButtons ._rotateLeft {
+ background: url(/assets/packages/static/openvk/img/upload.png);
+ height: 20px;
+ width: 23px;
+ background-position: -23px 0px;
+}
+
+.cropper-image-cont .rotateButtons ._rotateRight {
+ background: url(/assets/packages/static/openvk/img/upload.png);
+ height: 18px;
+ width: 22px;
+ background-position: -46px 0px;
+}
diff --git a/Web/static/css/avataredit.css b/Web/static/css/avataredit.css
deleted file mode 100644
index dd6bc43a..00000000
--- a/Web/static/css/avataredit.css
+++ /dev/null
@@ -1,88 +0,0 @@
-.text_add_image
-{
- position:absolute;
- font-size:12px;
- color: #2B587A;
- text-align:center;
- width: 100%;
- left: 0px;
- bottom:30px;
-}
-.text_add_image:hover
-{
- color:rgb(48, 41, 141);
-}
-.text_add_image, .avatarDelete img, .avatarDelete, .avatar_variants, .variant {
- -webkit-transition: all 200ms ease-in-out;
- -moz-transition: all 200ms ease-in-out;
- -o-transition: all 200ms ease-in-out;
- transition: all 200ms ease-in-out;
-}
-.avatarDelete
-{
- position:absolute;
- right:0%;
- background-color: rgba(0, 0, 0, 0.75);
- padding: 1px 0px 4px 3px;
- border-radius: 0px 0px 0px 5px;
- opacity:0;
- cursor:pointer;
-}
-.avatarDelete img
-{
- width:77%;
- opacity:60%;
- vertical-align:middle;
-}
-.avatarDelete img:hover
-{
- opacity:100%
-}
-
-div.avatar_block:hover .avatarDelete
-{
- opacity:1 !important;
-}
-
-div.avatar_block:hover .avatar_variants
-{
- opacity:1 !important;
- margin-bottom:1px;
-}
-
-.avatar_variants
-{
- opacity:0;
- position:absolute;
- background-color: rgba(0, 0, 0, 0.75);
- width:100%;
- bottom:0;
- margin-bottom:-8px;
- color:white;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-
-.variant
-{
- opacity:60%;
- display:flex;
- user-select:none;
-}
-
-.variant p
-{
- color:white;
- margin-left: 6px;
-}
-
-.variant img
-{
- color:white;
- margin-top: 7px;
-}
-
-.variant:hover
-{
- opacity:100%;
-}
diff --git a/Web/static/img/delete.png b/Web/static/img/delete.png
deleted file mode 100644
index 92eecbe856b30b0ceb9485c4dbbb474464838842..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 263
zcmeAS@N?(olHy`uVBq!ia0vp^{2
g`;yn{IC&nJYf#N(<`YpJ(_!-KEn}Ai3tCpqZyZ!~H|%Z$c+LVq-Pd;d7Y&$lWQS
zb#F)Tt$&4*2mZx`@JuV@Nm%=9>jCCluB=X(2PTCd-MZp{25-O(SJp=LKc2r@^xqUM
z;bGdRp8VsUf43ENZ@DzLv4g29;
zxE4M@VotJg(3Hz%U0Yc)x+Gmo2e@qy;ZL{$-huldIRJUgq%diZ;K-2GWg+WQ$cFY0
zL|da$6U}N})ti-e>BFoTUs7!Bl`{poGS)|5gN}9upLD9y(f3g@;a#BGM
zu-+>9hk7Q!waR9N$m!rFtT#mQ;)t8z~KHDzyIgyzdQ+2Tl0h}4-
zoY6LO?RuJd5~=#&_e>w`e-CZ!pW~?U?D1Q4^v|y`P2Q`a@qPXbmRi-2n~+KCjhbB2
zwODei$8{~9v~fu=G5v55cHS#OOhevg>8Z(DFrLYC4g1hhEy4?%fD@;?^1|_TSQq^y
zh9`dunmy(M{0_Mx--df(Dv*@e%c~~;4FL{A#P(
ziJcg;$-3HHhEL!*XusT%7m)3I3B1CF1nT+$rLdFXeQ9%N5=GiLpvU*V$OPW2GXTuV
zn#VP$EPVVjwPnZTe>;5~CdYl}(N%$Wqps5~mE4D8$C?S_ecR3ahtInx?aNKC5OG-KH@{XVW&gs24gR)&j-i8^5$6Z8JfTXk%R8lQ|bF@%$I
zVSC&OdlDBJYx-foJNN8X{Toz31S3yO7yNCc@g>K%nsk`2SiRk5^_zyFC&qWO9n@N{
z72Nx%ort(w%#)n(Un=r9enskjqj2Xn^v$;y(#)-&e$z0t6*H_0uu=?d#SDtUtQaBw
Y0@XA+X)inufB*mh07*qoM6N<$f;kAK;s5{u
delta 134
zcmbQuzLZh1Gr-TCmrII^fq{Y7)59eQNQ2m19Be?c*XaD-iHaIAhZz|74l^FlUy%Y7
zwDNRu4ABTqc3}U%kl|D-vzrDl+Y2s`%4B=rCQ
diff --git a/Web/static/js/al_wall.js b/Web/static/js/al_wall.js
index 3f9745c3..59d37df8 100644
--- a/Web/static/js/al_wall.js
+++ b/Web/static/js/al_wall.js
@@ -1374,3 +1374,190 @@ $(document).on("click", "#photosAttachments", async (e) => {
xhr.send(formdata)
})
})
+
+$(document).on("click", "#add_image", (e) => {
+ let isGroup = e.currentTarget.closest(".avatar_block").dataset.club != null
+ let group = isGroup ? e.currentTarget.closest(".avatar_block").dataset.club : 0
+
+ let body = `
+
+
${isGroup == true ? tr('groups_avatar') : tr('friends_avatar')}
+
${tr('formats_avatar')}
+
+
+
+
+
+
${tr('troubles_avatar')}
+
+ `
+
+ let msg = MessageBox(tr('uploading_new_image'), body, [
+ tr('cancel')
+ ], [
+ (function() {
+ u("#tmpPhDelF").remove();
+ }),
+ ]);
+
+ msg.attr("style", "width: 600px;");
+ document.querySelector(".ovk-diag-body").style.padding = "13px"
+
+ $("#avatarUpload input").on("change", (ev) => {
+ let image = URL.createObjectURL(ev.currentTarget.files[0])
+ $(".ovk-diag-body")[0].innerHTML = `
+ ${!isGroup ? tr("selected_area_user") : tr("selected_area_club")}
+
+ ${tr("selected_area_rotate")}
+
+
+
+
+
+
+
+
+ `
+
+ document.querySelector(".ovk-diag-action").insertAdjacentHTML("beforeend", `
+
+ `)
+
+ const image_div = document.getElementById('temp_uploadPic');
+ const cropper = new Cropper(image_div, {
+ aspectRatio: NaN,
+ zoomable: true,
+ minCropBoxWidth: 150,
+ minCropBoxHeight: 150,
+ dragMode: 'move',
+ background: false,
+ center: false,
+ guides: false,
+ modal: true,
+ viewMode: 2,
+ cropstart(event) {
+ document.querySelector(".cropper-container").classList.add("moving")
+ },
+ cropend(event) {
+ document.querySelector(".cropper-container").classList.remove("moving")
+ },
+ });
+
+ msg.attr("style", "width: 487px;");
+
+ document.querySelector("#_uploadImg").onclick = (evv) => {
+ cropper.getCroppedCanvas({
+ fillColor: '#fff',
+ imageSmoothingEnabled: false,
+ imageSmoothingQuality: 'high',
+ }).toBlob((blob) => {
+ document.querySelector("#_uploadImg").classList.add("lagged")
+ let formdata = new FormData()
+ formdata.append("blob", blob)
+ formdata.append("ajax", 1)
+ formdata.append("on_wall", Number(document.querySelector("#publish_on_wall").checked))
+ formdata.append("hash", u("meta[name=csrf]").attr("value"))
+
+ $.ajax({
+ type: "POST",
+ url: isGroup ? "/club" + group + "/al_avatar" : "/al_avatars",
+ data: formdata,
+ processData: false,
+ contentType: false,
+ error: (response) => {
+ fastError(response.flash.message)
+ },
+ success: (response) => {
+ document.querySelector("#_uploadImg").classList.remove("lagged")
+ u("body").removeClass("dimmed");
+ document.querySelector("html").style.overflowY = "scroll"
+ u(".ovk-diag-cont").remove();
+
+ if(!response.success) {
+ fastError(response.flash.message)
+ return
+ }
+
+ document.querySelector("#bigAvatar").src = response.url
+ document.querySelector("#bigAvatar").parentNode.href = "/photo" + response.new_photo
+
+ document.querySelector(".add_image_text").style.display = "none"
+ document.querySelector(".avatar_controls").style.display = "block"
+ }
+ })
+ })
+ }
+
+ $(".ovk-diag-body ._rotateLeft").on("click", (e) => {
+ cropper.rotate(90)
+ })
+
+ $(".ovk-diag-body ._rotateRight").on("click", (e) => {
+ cropper.rotate(-90)
+ })
+ })
+})
+
+$(document).on("click", ".avatarDelete", (e) => {
+ let isGroup = e.currentTarget.closest(".avatar_block").dataset.club != null
+ let group = isGroup ? e.currentTarget.closest(".avatar_block").dataset.club : 0
+
+ let body = `
+ ${tr("deleting_avatar_sure")}
+ `
+
+ let msg = MessageBox(tr('deleting_avatar'), body, [
+ tr('yes'),
+ tr('no')
+ ], [
+ (function() {
+ let formdata = new FormData()
+ formdata.append("hash", u("meta[name=csrf]").attr("value"))
+
+ $.ajax({
+ type: "POST",
+ url: isGroup ? "/club" + group + "/delete_avatar" : "/delete_avatar",
+ data: formdata,
+ processData: false,
+ contentType: false,
+ beforeSend: () => {
+ document.querySelector(".avatarDelete").classList.add("lagged")
+ },
+ error: (response) => {
+ fastError(response.flash.message)
+ },
+ success: (response) => {
+ if(!response.success) {
+ fastError(response.flash.message)
+ return
+ }
+
+ document.querySelector(".avatarDelete").classList.remove("lagged")
+
+ u("body").removeClass("dimmed");
+ document.querySelector("html").style.overflowY = "scroll"
+ u(".ovk-diag-cont").remove();
+
+ document.querySelector("#bigAvatar").src = response.url
+ document.querySelector("#bigAvatar").parentNode.href = response.new_photo ? ("/photo" + response.new_photo) : "javascript:void(0)"
+
+ if(!response.has_new_photo) {
+ document.querySelector(".avatar_controls").style.display = "none"
+ document.querySelector(".add_image_text").style.display = "block"
+ }
+ }
+ })
+ }),
+ (function() {
+ u("#tmpPhDelF").remove();
+ }),
+ ]);
+})
diff --git a/Web/static/js/openvk.cls.js b/Web/static/js/openvk.cls.js
index b131bfa0..a4f5cd06 100644
--- a/Web/static/js/openvk.cls.js
+++ b/Web/static/js/openvk.cls.js
@@ -483,91 +483,6 @@ function escapeHtml(text) {
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
-function addAvatarImage(groupStrings = false, groupId = 0)
-{
- let inputname = groupStrings == true ? 'ava' : 'blob';
- let body = `
-
-
${groupStrings == true ? tr('groups_avatar') : tr('friends_avatar')}
-
${tr('formats_avatar')}
-
-
-
${tr('troubles_avatar')}
-
- `
- let msg = MessageBox(tr('uploading_new_image'), body, [
- tr('cancel')
- ], [
- (function() {
- u("#tmpPhDelF").remove();
- }),
- ]);
- msg.attr("style", "width: 600px;");
-}
-
-function uploadAvatar(group = false, group_id = 0)
-{
- loader.style.display = "block";
- uploadbtn.setAttribute("hidden", "hidden")
- let xhr = new XMLHttpRequest();
- let formData = new FormData();
- let bloborava = group == false ? "blob" : "ava"
- formData.append(bloborava, document.getElementById(bloborava).files[0]);
- formData.append("ava", 1)
- formData.append("hash", u("meta[name=csrf]").attr("value"))
- xhr.open("POST", group == true ? "/club"+group_id+"/al_avatar" : "/al_avatars")
- xhr.onload = () => {
- let json = JSON.parse(xhr.responseText);
- document.getElementById(group == false ? "thisUserAvatar" : "thisGroupAvatar").src = json["url"];
- u("body").removeClass("dimmed");
- u(".ovk-diag-cont").remove();
- if(document.getElementsByClassName("text_add_image")[0] == undefined)
- {
- document.getElementById("upl").href = "javascript:deleteAvatar('"+json["id"]+"', '"+u("meta[name=csrf]").attr("value")+"')"
- }
- //console.log(json["id"])
- NewNotification(tr("update_avatar_notification"), tr("update_avatar_description"), json["url"], () => {window.location.href = "/photo" + json["id"]});
- if(document.getElementsByClassName("text_add_image")[0] != undefined)
- {
- //ожидание чтобы в уведомлении была аватарка
- let promise = new Promise((resolve, reject) => {
- setTimeout(() => {
- location.reload()
- }, 500);
- });
- }
- }
- xhr.send(formData)
-}
-
-function deleteAvatar(avatar)
-{
- let body = `
- ${tr("deleting_avatar_sure")}
- `
- let msg = MessageBox(tr('deleting_avatar'), body, [
- tr('yes'),
- tr('cancel')
- ], [
- (function() {
- let xhr = new XMLHttpRequest();
- xhr.open("POST", "/photo"+avatar+"/delete")
- xhr.onload = () => {
- //не люблю формы
- NewNotification(tr("deleted_avatar_notification"), "");
- location.reload()
- }
- xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
- xhr.send("hash="+u("meta[name=csrf]").attr("value"))
- }),
- (function() {
- u("#tmpPhDelF").remove();
- }),
- ]);
-}
-
function expandSearch()
{
// console.log("search expanded")
diff --git a/Web/static/js/package.json b/Web/static/js/package.json
index f5c37008..bb622c72 100644
--- a/Web/static/js/package.json
+++ b/Web/static/js/package.json
@@ -2,6 +2,7 @@
"dependencies": {
"@atlassian/aui": "^9.6.0",
"create-react-class": "^15.7.0",
+ "cropperjs": "^1.6.1",
"dashjs": "^4.3.0",
"id3js": "^2.1.1",
"handlebars": "^4.7.7",
diff --git a/Web/static/js/yarn.lock b/Web/static/js/yarn.lock
index 289fc81e..e87c407e 100644
--- a/Web/static/js/yarn.lock
+++ b/Web/static/js/yarn.lock
@@ -59,16 +59,16 @@ create-react-class@^15.7.0:
loose-envify "^1.3.1"
object-assign "^4.1.1"
+cropperjs@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/cropperjs/-/cropperjs-1.6.1.tgz#fd132021d93b824b1b0f2c2c3b763419fb792d89"
+ integrity sha512-F4wsi+XkDHCOMrHMYjrTEE4QBOrsHHN5/2VsVAaRq8P7E5z7xQpT75S+f/9WikmBEailas3+yo+6zPIomW+NOA==
+
css.escape@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
-dompurify@2.4.5:
- version "2.4.5"
- resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.5.tgz#0e89a27601f0bad978f9a924e7a05d5d2cccdd87"
- integrity sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA==
-
dashjs@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/dashjs/-/dashjs-4.3.0.tgz#cccda5a490cabf6c3b48aa887ec8c8ac0df1a233"
@@ -81,6 +81,11 @@ dashjs@^4.3.0:
imsc "^1.0.2"
localforage "^1.7.1"
+dompurify@2.4.5:
+ version "2.4.5"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.5.tgz#0e89a27601f0bad978f9a924e7a05d5d2cccdd87"
+ integrity sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA==
+
encoding@^0.1.11:
version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
@@ -121,10 +126,6 @@ fbjs@^0.8.0:
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
-html-entities@^1.2.1:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc"
- integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==
handlebars@^4.7.7:
version "4.7.7"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
@@ -137,6 +138,11 @@ handlebars@^4.7.7:
optionalDependencies:
uglify-js "^3.1.4"
+html-entities@^1.2.1:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc"
+ integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==
+
iconv-lite@^0.6.2:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
diff --git a/locales/en.strings b/locales/en.strings
index fea19671..9aadcf2d 100644
--- a/locales/en.strings
+++ b/locales/en.strings
@@ -466,15 +466,15 @@
"formats_avatar" = "You can upload an image in JPG, GIF or PNG format.";
"troubles_avatar" = "If you're having trouble uploading, try selecting a smaller photo.";
"webcam_avatar" = "If your computer is equipped with a webcam, you can take a snapshot.";
+"publish_on_wall" = "Make post on wall";
-"update_avatar_notification" = "Profile photo was updated";
-"update_avatar_description" = "Click to watch";
+"selected_area_user" = "The selected area will be shown on your page.";
+"selected_area_club" = "The selected area will be shown on the group page.";
+"selected_area_rotate" = "If the image is not oriented correctly, the photo can be rotated.";
"deleting_avatar" = "Deleting photo";
"deleting_avatar_sure" = "Do you sure you want to delete avatar?";
-"deleted_avatar_notification" = "Picture successfully deleted";
-
"save_changes" = "Save changes";
"upd_m" = "updated his profile picture";
diff --git a/locales/ru.strings b/locales/ru.strings
index b88d8d05..7070f6bc 100644
--- a/locales/ru.strings
+++ b/locales/ru.strings
@@ -452,15 +452,15 @@
"formats_avatar" = "Вы можете загрузить изображение в формате JPG, GIF или PNG.";
"troubles_avatar" = "Если возникают проблемы с загрузкой, попробуйте выбрать фотографию меньшего размера.";
"webcam_avatar" = "Если ваш компьютер оснащён веб-камерой, Вы можете сделать моментальную фотографию »";
+"publish_on_wall" = "Опубликовать запись на стене";
-"update_avatar_notification" = "Фотография профиля обновлена";
-"update_avatar_description" = "Нажмите сюда, чтобы перейти к просмотру";
+"selected_area_user" = "Выбранная область будет показываться на вашей странице.";
+"selected_area_club" = "Выбранная область будет показываться на странице сообщества.";
+"selected_area_rotate" = "Если изображение ориентировано неправильно, фотографию можно повернуть.";
"deleting_avatar" = "Удаление фотографии";
"deleting_avatar_sure" = "Вы действительно хотите удалить аватар?";
-"deleted_avatar_notification" = "Фотография успешно удалена";
-
"save_changes" = "Сохранить изменения";
"upd_m" = "обновил фотографию на своей странице";
diff --git a/themepacks/midnight/stylesheet.css b/themepacks/midnight/stylesheet.css
index d733f5d1..c8dd1b84 100644
--- a/themepacks/midnight/stylesheet.css
+++ b/themepacks/midnight/stylesheet.css
@@ -385,4 +385,8 @@ ul {
}
.tabcontent{
background: #2c2640 !important;
+}
+
+.add_image_text {
+ z-index: 999;
}
\ No newline at end of file