From 82271833a53c19aeb557711f3f37a75986abd8ca Mon Sep 17 00:00:00 2001
From: lalka2016 <99399973+lalka2016@users.noreply.github.com>
Date: Wed, 13 Sep 2023 20:53:01 +0300
Subject: [PATCH] add videosz picjkre
---
ServiceAPI/Wall.php | 44 ++++-
Web/Presenters/CommentPresenter.php | 29 +++-
Web/Presenters/WallPresenter.php | 33 +++-
.../templates/components/textArea.xml | 8 +-
Web/static/css/main.css | 36 +++-
Web/static/img/video.png | Bin 0 -> 510 bytes
Web/static/js/al_wall.js | 156 +++++++++++++++++-
Web/static/js/messagebox.js | 2 +
locales/en.strings | 6 +
locales/ru.strings | 7 +
10 files changed, 299 insertions(+), 22 deletions(-)
create mode 100644 Web/static/img/video.png
diff --git a/ServiceAPI/Wall.php b/ServiceAPI/Wall.php
index 5677f7ba..787a998e 100644
--- a/ServiceAPI/Wall.php
+++ b/ServiceAPI/Wall.php
@@ -2,7 +2,7 @@
namespace openvk\ServiceAPI;
use openvk\Web\Models\Entities\Post;
use openvk\Web\Models\Entities\User;
-use openvk\Web\Models\Repositories\{Posts, Notes};
+use openvk\Web\Models\Repositories\{Posts, Notes, Videos};
class Wall implements Handler
{
@@ -15,6 +15,7 @@ class Wall implements Handler
$this->user = $user;
$this->posts = new Posts;
$this->notes = new Notes;
+ $this->videos = new Videos;
}
function getPost(int $id, callable $resolve, callable $reject): void
@@ -95,4 +96,45 @@ class Wall implements Handler
$resolve($arr);
}
+
+ function getVideos(int $page = 1, callable $resolve, callable $reject)
+ {
+ $videos = $this->videos->getByUser($this->user, $page, 8);
+ $count = $this->videos->getUserVideosCount($this->user);
+
+ $arr = [
+ "count" => $count,
+ "items" => [],
+ ];
+
+ foreach($videos as $video) {
+ $res = json_decode(json_encode($video->toVkApiStruct()), true);
+ $res["video"]["author_name"] = $video->getOwner()->getCanonicalName();
+
+ $arr["items"][] = $res;
+ }
+
+ $resolve($arr);
+ }
+
+ function searchVideos(int $page = 1, string $query, callable $resolve, callable $reject)
+ {
+ $dbc = $this->videos->find($query);
+ $videos = $dbc->page($page, 8);
+ $count = $dbc->size();
+
+ $arr = [
+ "count" => $count,
+ "items" => [],
+ ];
+
+ foreach($videos as $video) {
+ $res = json_decode(json_encode($video->toVkApiStruct()), true);
+ $res["video"]["author_name"] = $video->getOwner()->getCanonicalName();
+
+ $arr["items"][] = $res;
+ }
+
+ $resolve($arr);
+ }
}
diff --git a/Web/Presenters/CommentPresenter.php b/Web/Presenters/CommentPresenter.php
index cb0efd0d..6b3bfb31 100644
--- a/Web/Presenters/CommentPresenter.php
+++ b/Web/Presenters/CommentPresenter.php
@@ -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};
+use openvk\Web\Models\Repositories\{Comments, Clubs, Videos};
final class CommentPresenter extends OpenVKPresenter
{
@@ -73,7 +73,6 @@ final class CommentPresenter extends OpenVKPresenter
# TODO move to trait
try {
$photo = NULL;
- $video = NULL;
if($_FILES["_pic_attachment"]["error"] === UPLOAD_ERR_OK) {
$album = NULL;
if($wall > 0 && $wall === $this->user->id)
@@ -81,13 +80,26 @@ final class CommentPresenter extends OpenVKPresenter
$photo = Photo::fastMake($this->user->id, $this->postParam("text"), $_FILES["_pic_attachment"], $album);
}
-
- if($_FILES["_vid_attachment"]["error"] === UPLOAD_ERR_OK) {
- $video = Video::fastMake($this->user->id, $_FILES["_vid_attachment"]["name"], $this->postParam("text"), $_FILES["_vid_attachment"]);
- }
} catch(ISE $ex) {
$this->flashFail("err", "Не удалось опубликовать комментарий", "Файл медиаконтента повреждён или слишком велик.");
}
+
+ $videos = [];
+
+ if(!empty($this->postParam("videos"))) {
+ $un = rtrim($this->postParam("videos"), ",");
+ $arr = explode(",", $un);
+
+ foreach($arr as $dat) {
+ $ids = explode("_", $dat);
+ $video = (new Videos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
+
+ if(!$video || $video->isDeleted())
+ continue;
+
+ $videos[] = $video;
+ }
+ }
if(empty($this->postParam("text")) && !$photo && !$video)
$this->flashFail("err", "Не удалось опубликовать комментарий", "Комментарий пустой или слишком большой.");
@@ -108,8 +120,9 @@ final class CommentPresenter extends OpenVKPresenter
if(!is_null($photo))
$comment->attach($photo);
- if(!is_null($video))
- $comment->attach($video);
+ if(sizeof($videos) > 0)
+ foreach($videos as $vid)
+ $comment->attach($vid);
if($entity->getOwner()->getId() !== $this->user->identity->getId())
if(($owner = $entity->getOwner()) instanceof User)
diff --git a/Web/Presenters/WallPresenter.php b/Web/Presenters/WallPresenter.php
index 3e115ec7..30e95848 100644
--- a/Web/Presenters/WallPresenter.php
+++ b/Web/Presenters/WallPresenter.php
@@ -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};
+use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums, Notes, Videos};
use Chandler\Database\DatabaseConnection;
use Nette\InvalidStateException as ISE;
use Bhaktaraz\RSSGenerator\Item;
@@ -232,9 +232,6 @@ final class WallPresenter extends OpenVKPresenter
if(!$canPost)
$this->flashFail("err", tr("not_enough_permissions"), tr("not_enough_permissions_comment"));
- if($_FILES["_vid_attachment"] && OPENVK_ROOT_CONF['openvk']['preferences']['videos']['disableUploading'])
- $this->flashFail("err", tr("error"), "Video uploads are disabled by the system administrator.");
-
$anon = OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["anonymousPosting"]["enable"];
if($wallOwner instanceof Club && $this->postParam("as_group") === "on" && $this->postParam("force_sign") !== "on" && $anon) {
$manager = $wallOwner->getManager($this->user->identity);
@@ -263,8 +260,8 @@ final class WallPresenter extends OpenVKPresenter
$photo = Photo::fastMake($this->user->id, $this->postParam("text"), $_FILES["_pic_attachment"], $album, $anon);
}
- 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);
+ /*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) {
@@ -295,8 +292,25 @@ final class WallPresenter extends OpenVKPresenter
$this->flashFail("err", " ");
}
}
+
+ $videos = [];
+
+ if(!empty($this->postParam("videos"))) {
+ $un = rtrim($this->postParam("videos"), ",");
+ $arr = explode(",", $un);
+
+ foreach($arr as $dat) {
+ $ids = explode("_", $dat);
+ $video = (new Videos)->getByOwnerAndVID((int)$ids[0], (int)$ids[1]);
+
+ if(!$video || $video->isDeleted())
+ continue;
+
+ $videos[] = $video;
+ }
+ }
- if(empty($this->postParam("text")) && !$photo && !$video && !$poll && !$note)
+ if(empty($this->postParam("text")) && !$photo && sizeof($videos) < 1 && !$poll && !$note)
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_empty_or_too_big"));
try {
@@ -316,8 +330,9 @@ final class WallPresenter extends OpenVKPresenter
if(!is_null($photo))
$post->attach($photo);
- if(!is_null($video))
- $post->attach($video);
+ if(sizeof($videos) > 0)
+ foreach($videos as $vid)
+ $post->attach($vid);
if(!is_null($poll))
$post->attach($poll);
diff --git a/Web/Presenters/templates/components/textArea.xml b/Web/Presenters/templates/components/textArea.xml
index f76649d6..939e5ad5 100644
--- a/Web/Presenters/templates/components/textArea.xml
+++ b/Web/Presenters/templates/components/textArea.xml
@@ -17,6 +17,8 @@
+
+
{var $anonEnabled = OPENVK_ROOT_CONF['openvk']['preferences']['wall']['anonymousPosting']['enable']}
{if !is_null($thisUser) && !is_null($club ?? NULL) && $owner < 0}
@@ -55,7 +57,7 @@
-
+
@@ -75,7 +77,7 @@
{_photo}
-
+
{_video}
@@ -105,6 +107,8 @@
setupWallPostInputHandlers({$textAreaId});
});
+
+ u("#post-buttons{$textAreaId} input[name='videos']")["nodes"].at(0).value = ""
{if $graffiti}
diff --git a/Web/static/css/main.css b/Web/static/css/main.css
index 55484f13..fdfd6304 100644
--- a/Web/static/css/main.css
+++ b/Web/static/css/main.css
@@ -1466,6 +1466,12 @@ body.scrolled .toTop:hover {
display: none;
}
+.post-has-videos {
+ margin-top: 11px;
+ margin-left: 3px;
+ color: #3c3c3c;
+}
+
.post-upload::before, .post-has-poll::before, .post-has-note::before {
content: " ";
width: 8px;
@@ -1477,6 +1483,28 @@ body.scrolled .toTop:hover {
margin-left: 2px;
}
+.post-has-video {
+ padding-bottom: 4px;
+ cursor: pointer;
+}
+
+.post-has-video:hover span {
+ text-decoration: underline;
+}
+
+.post-has-video::before {
+ content: " ";
+ width: 14px;
+ height: 15px;
+ display: inline-block;
+ vertical-align: bottom;
+ background-image: url("/assets/packages/static/openvk/img/video.png");
+ background-repeat: no-repeat;
+ margin: 3px;
+ margin-left: 2px;
+ margin-bottom: -1px;
+}
+
.post-opts {
margin-top: 10px;
}
@@ -2700,4 +2728,10 @@ body.article .floating_sidebar, body.article .page_content {
position: absolute;
right: 22px;
font-size: 12px;
-}
\ No newline at end of file
+}
+
+.topGrayBlock {
+ background: #F0F0F0;
+ height: 37px;
+ border-bottom: 1px solid #C7C7C7;
+}
diff --git a/Web/static/img/video.png b/Web/static/img/video.png
new file mode 100644
index 0000000000000000000000000000000000000000..5c115f1c231030eafacd5f18a415232bbd0a6d12
GIT binary patch
literal 510
zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA0h38YK~y+Tjgw7J
z!axv)-`PTo2n79q#OQ%&VxkZYiJ$nHATdGIC?tM`qX#|kmyF>cD72*o>e#70TJ^b1
zHt+7dGqbyNb9>K;=>#T|2{cUu!-KBHf;B!FLk!hNt9F6jm=ks||Nqlp_j
z>h(Iit_!MEDqJd+s8T&)v3JK~q*5u^whfOzgOZpDu~-ZmDXbS(saC5oom5X*?nfVqY;A0kL^T);P~JQEUyuF^D(~;HuIo^S
zVW7ObO=G{ezv#bzpuDq7G8`qg;@ItWLpd6m#m3g=x8ra)3>?$xbSOt713W%FB598b
z#Wj}NrDQ2reuX5lT_@Nq*CD?_q6UH@hT}N+0?diKEB)@BE&u=k07*qoM6N<$f@P%F
A4FCWD
literal 0
HcmV?d00001
diff --git a/Web/static/js/al_wall.js b/Web/static/js/al_wall.js
index bb349c14..a1b58628 100644
--- a/Web/static/js/al_wall.js
+++ b/Web/static/js/al_wall.js
@@ -262,4 +262,158 @@ async function showArticle(note_id) {
u("#articleText").html(`${note.title} ` + note.html);
u("body").removeClass("dimmed");
u("body").addClass("article");
-}
\ No newline at end of file
+}
+
+$(document).on("click", "#videoAttachment", async (e) => {
+ e.preventDefault()
+
+ let body = `
+
+
+
+ `
+
+ let form = e.currentTarget.closest("form")
+
+ MessageBox(tr("selecting_video"), body, [tr("close")], [Function.noop]);
+
+ // styles for messageboxx
+ document.querySelector(".ovk-diag-body").style.padding = "0"
+ document.querySelector(".ovk-diag-cont").style.width = "580px"
+ document.querySelector(".ovk-diag-body").style.height = "241px"
+
+ async function insertVideos(page, query = "") {
+ document.querySelector(".videosInsert").insertAdjacentHTML("beforeend", ` `)
+
+ let vidoses
+ let noVideosText = tr("no_videos")
+ if(query == "") {
+ vidoses = await API.Wall.getVideos(page)
+ } else {
+ vidoses = await API.Wall.searchVideos(page, query)
+ noVideosText = tr("no_videos_results")
+ }
+
+ if(vidoses.count < 1) {
+ document.querySelector(".videosInsert").innerHTML = `${noVideosText} `
+ }
+
+ let pagesCount = Math.ceil(Number(vidoses.count) / 8)
+ u("#loader").remove()
+ let insert = document.querySelector(".videosInsert")
+
+ for(const vid of vidoses.items) {
+ let isAttached = (form.querySelector("input[name='videos']").value.includes(`${vid.video.owner_id}_${vid.video.id},`))
+
+ insert.insertAdjacentHTML("beforeend", `
+
+ `)
+ }
+
+ if(page < pagesCount) {
+ document.querySelector(".videosInsert").insertAdjacentHTML("beforeend", `
+
+ more...
+
`)
+ }
+ }
+
+ $(".videosInsert").on("click", "#showMoreVideos", (e) => {
+ u(e.currentTarget).remove()
+ insertVideos(Number(e.currentTarget.dataset.page))
+ })
+
+ $(".topGrayBlock #vquery").on("change", async (e) => {
+ await new Promise(r => setTimeout(r, 1000));
+
+ if(e.currentTarget.value === document.querySelector(".topGrayBlock #vquery").value) {
+ document.querySelector(".videosInsert").innerHTML = ""
+ insertVideos(1, e.currentTarget.value)
+ return;
+ } else {
+ console.info("skipping")
+ }
+ })
+
+ insertVideos(1)
+
+ function insertAttachment(id) {
+ let videos = form.querySelector("input[name='videos']")
+
+ if(!videos.value.includes(id + ",")) {
+ if(videos.value.split(",").length > 10) {
+ NewNotification(tr("error"), tr("max_attached_videos"))
+ return false
+ }
+
+ form.querySelector("input[name='videos']").value += (id + ",")
+
+ console.info(id + " attached")
+ return true
+ } else {
+ form.querySelector("input[name='videos']").value = form.querySelector("input[name='videos']").value.replace(id + ",", "")
+
+ console.info(id + " detached")
+ return false
+ }
+ }
+
+ $(".videosInsert").on("click", "#attachvid", (ev) => {
+ // откреплено от псто
+ if(!insertAttachment(ev.currentTarget.dataset.attachmentdata)) {
+ u(`.post-has-videos .post-has-video[data-id='${ev.currentTarget.dataset.attachmentdata}']`).remove()
+ ev.currentTarget.innerHTML = tr("attach")
+ } else {
+ ev.currentTarget.innerHTML = tr("detach")
+
+ form.querySelector(".post-has-videos").insertAdjacentHTML("beforeend", `
+
+ ${tr("video")} "${ovk_proc_strtr(escapeHtml(ev.currentTarget.dataset.name), 20)}"
+
+ `)
+
+ u(`#unattachVideo[data-id='${ev.currentTarget.dataset.attachmentdata}']`).on("click", (e) => {
+ let id = ev.currentTarget.dataset.attachmentdata
+ form.querySelector("input[name='videos']").value = form.querySelector("input[name='videos']").value.replace(id + ",", "")
+
+ console.info(id + " detached")
+
+ u(e.currentTarget).remove()
+ })
+ }
+ })
+})
diff --git a/Web/static/js/messagebox.js b/Web/static/js/messagebox.js
index 45791fd3..368311dd 100644
--- a/Web/static/js/messagebox.js
+++ b/Web/static/js/messagebox.js
@@ -3,6 +3,7 @@ Function.noop = () => {};
function MessageBox(title, body, buttons, callbacks) {
if(u(".ovk-diag-cont").length > 0) return false;
+ document.querySelector("html").style.overflowY = "hidden"
let dialog = u(
`
@@ -21,6 +22,7 @@ function MessageBox(title, body, buttons, callbacks) {
let __closeDialog = () => {
u("body").removeClass("dimmed");
u(".ovk-diag-cont").remove();
+ document.querySelector("html").style.overflowY = "scroll"
};
Reflect.apply(callbacks[callback], {
diff --git a/locales/en.strings b/locales/en.strings
index 487d2156..00ceeeec 100644
--- a/locales/en.strings
+++ b/locales/en.strings
@@ -202,6 +202,7 @@
"nsfw_warning" = "This post may have NSFW-content";
"report" = "Report";
"attach" = "Attach";
+"detach" = "Detach";
"attach_photo" = "Attach photo";
"attach_video" = "Attach video";
"draw_graffiti" = "Draw graffiti";
@@ -656,6 +657,11 @@
"videos_other" = "$1 videos";
"view_video" = "View";
+"selecting_video" = "Selecting videos";
+"upload_new_video" = "Upload new video";
+"max_attached_videos" = "Max is 10 videos";
+"no_videos" = "You don't have uploaded videos.";
+"no_videos_results" = "No results.";
/* Notifications */
diff --git a/locales/ru.strings b/locales/ru.strings
index dc101e2b..7e4b4a7c 100644
--- a/locales/ru.strings
+++ b/locales/ru.strings
@@ -182,6 +182,7 @@
"nsfw_warning" = "Данный пост может содержать 18+ контент";
"report" = "Пожаловаться";
"attach" = "Прикрепить";
+"detach" = "Открепить";
"attach_photo" = "Прикрепить фото";
"attach_video" = "Прикрепить видео";
"draw_graffiti" = "Нарисовать граффити";
@@ -615,6 +616,12 @@
"videos_other" = "$1 видеозаписей";
"view_video" = "Просмотр";
+"selecting_video" = "Выбор видеозаписей";
+"upload_new_video" = "Загрузить новое видео";
+"max_attached_videos" = "Максимум 10 видеозаписей";
+"no_videos" = "У вас нет видео.";
+"no_videos_results" = "Нет результатов.";
+
/* Notifications */
"feedback" = "Ответы";