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", ` +
+ + + + + + + + +
+ +
+ ${escapeHtml(vid.video.title)} +
+
+
+ + + ${ovk_proc_strtr(escapeHtml(vid.video.title), 30)} + + +
+

+ ${ovk_proc_strtr(escapeHtml(vid.video.description ?? ""), 140)} +

+ ${escapeHtml(vid.video.author_name ?? "")} +
+
+ `) + } + + 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" = "Ответы";