diff --git a/Web/Models/Repositories/Videos.php b/Web/Models/Repositories/Videos.php index e78a1b0f..8dbda7ab 100644 --- a/Web/Models/Repositories/Videos.php +++ b/Web/Models/Repositories/Videos.php @@ -56,7 +56,7 @@ class Videos function find(string $query = "", array $params = [], array $order = ['type' => 'id', 'invert' => false]): Util\EntityStream { $query = "%$query%"; - $result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0); + $result = $this->videos->where("CONCAT_WS(' ', name, description) LIKE ?", $query)->where("deleted", 0)->where("unlisted", 0); $order_str = 'id'; switch($order['type']) { diff --git a/Web/Presenters/VideosPresenter.php b/Web/Presenters/VideosPresenter.php index 625f4877..49ed1b43 100644 --- a/Web/Presenters/VideosPresenter.php +++ b/Web/Presenters/VideosPresenter.php @@ -62,6 +62,7 @@ final class VideosPresenter extends OpenVKPresenter $this->flashFail("err", tr("error"), tr("video_uploads_disabled")); if($_SERVER["REQUEST_METHOD"] === "POST") { + $is_ajax = (int)($this->postParam('ajax') ?? '0') == 1; if(!empty($this->postParam("name"))) { $video = new Video; $video->setOwner($this->user->id); @@ -75,18 +76,29 @@ final class VideosPresenter extends OpenVKPresenter else if(!empty($this->postParam("link"))) $video->setLink($this->postParam("link")); else - $this->flashFail("err", tr("no_video_error"), tr("no_video_description")); + $this->flashFail("err", tr("no_video_error"), tr("no_video_description"), 10, $is_ajax); } catch(\DomainException $ex) { - $this->flashFail("err", tr("error_video"), tr("file_corrupted")); + $this->flashFail("err", tr("error_video"), tr("file_corrupted"), 10, $is_ajax); } catch(ISE $ex) { - $this->flashFail("err", tr("error_video"), tr("link_incorrect")); + $this->flashFail("err", tr("error_video"), tr("link_incorrect"), 10, $is_ajax); } + if((int)($this->postParam("unlisted") ?? '0') == 1) { + $video->setUnlisted(true); + } + $video->save(); + if($is_ajax) { + $object = $video->getApiStructure(); + $this->returnJson([ + 'payload' => $object->video, + ]); + } + $this->redirect("/video" . $video->getPrettyId()); } else { - $this->flashFail("err", tr("error_video"), tr("no_name_error")); + $this->flashFail("err", tr("error_video"), tr("no_name_error"), 10, $is_ajax); } } } diff --git a/Web/Presenters/templates/components/comment.xml b/Web/Presenters/templates/components/comment.xml index f99f7ddb..31e47071 100644 --- a/Web/Presenters/templates/components/comment.xml +++ b/Web/Presenters/templates/components/comment.xml @@ -27,7 +27,7 @@ {var $attachmentsLayout = $comment->getChildrenWithLayout(288)}
- {include "attachment.xml", attachment => $attachment[2], parent => $comment, parentType => "comment"} + {include "attachment.xml", attachment => $attachment[2], parent => $comment, parentType => "comment", tilesCount => sizeof($attachmentsLayout->tiles)}
diff --git a/Web/Presenters/templates/components/video.xml b/Web/Presenters/templates/components/video.xml index f9ab070e..d2ab40ff 100644 --- a/Web/Presenters/templates/components/video.xml +++ b/Web/Presenters/templates/components/video.xml @@ -19,6 +19,9 @@ {$video->getName()} + {if $video->getLength()} + ({$video->getFormattedLength()}) + {/if}

{$video->getDescription() ?? ""} diff --git a/Web/static/js/al_music.js b/Web/static/js/al_music.js index 51590511..ac609358 100644 --- a/Web/static/js/al_music.js +++ b/Web/static/js/al_music.js @@ -1459,7 +1459,13 @@ $(document).on("click", ".audioEmbed.processed .playerButton", (e) => { }) $(document).on("click", ".audioEmbed.withdrawn", (e) => { - MessageBox(tr("error"), tr("audio_embed_withdrawn"), [tr("ok")], [Function.noop]) + const msg = new CMessageBox({ + title: tr('error'), + body: tr('audio_embed_withdrawn'), + unique_name: 'withdrawn_notify', + buttons: [tr('ok')], + callbacks: [Function.noop] + }) }) $(document).on("click", ".musicIcon.report-icon", (e) => { diff --git a/Web/static/js/al_wall.js b/Web/static/js/al_wall.js index be2e51ef..ee5bda47 100644 --- a/Web/static/js/al_wall.js +++ b/Web/static/js/al_wall.js @@ -4,6 +4,7 @@ function initGraffiti(event) { title: tr("draw_graffiti"), body: "

", close_on_buttons: false, + warn_on_exit: true, buttons: [tr("save"), tr("cancel")], callbacks: [function() { canvas.getImage({includeWatermark: false}).toBlob(blob => { @@ -746,7 +747,7 @@ u(document).on('click', '#__videoAttachment', async (e) => { body: `
- ${tr("upload_new_video")} +
@@ -890,6 +891,11 @@ u(document).on('click', '#__videoAttachment', async (e) => { } }) + u(".ovk-diag-body .attachment_selector").on('click', '#__fast_video_upload', (ev) => { + ev.preventDefault() + showFastVideoUpload(form) + }) + __recieveVideos(0) }) @@ -1012,6 +1018,184 @@ u(document).on('click', '#__notesAttachment', async (e) => { __recieveNotes(0) }) +function showFastVideoUpload(node) { + let current_tab = 'file' + const msg = new CMessageBox({ + title: tr('upload_video'), + close_on_buttons: false, + unique_name: 'video_uploader', + body: ` +
+ +
+
+ `, + buttons: [tr('close'), tr('upload_button')], + callbacks: [() => {msg.close()}, async () => { + const video_name = u(`#_fast_video_upload input[name='name']`).nodes[0].value + const video_desc = u(`#_fast_video_upload textarea[name='desc']`).nodes[0].value + let append_result = null + + if(video_name.length < 1) { + u(`#_fast_video_upload input[name='name']`).nodes[0].focus() + return + } + + const form_data = new FormData + switch(current_tab) { + default: + case 'file': + const video_file = u(`#_fast_video_upload input[name='blob']`).nodes[0] + if(video_file.files.length < 1) { + return + } + + const video_blob = video_file.files[0] + form_data.append('ajax', '1') + form_data.append('name', video_name) + form_data.append('desc', video_desc) + form_data.append('blob', video_blob) + form_data.append('unlisted', 1) + form_data.append("hash", u("meta[name=csrf]").attr("value")) + + window.messagebox_stack[1].getNode().find('.ovk-diag-action button').nodes[1].classList.add('lagged') + const fetcher = await fetch(`/videos/upload`, { + method: 'POST', + body: form_data + }) + const fetcher_results = await fetcher.json() + append_result = fetcher_results + + break + case 'youtube': + const video_url = u(`#_fast_video_upload input[name='link']`).nodes[0] + const video_link = video_url.value + if(video_link.length < 1) { + u(`#_fast_video_upload input[name='link']`).nodes[0].focus() + return + } + + form_data.append('ajax', '1') + form_data.append('name', video_name) + form_data.append('desc', video_desc) + form_data.append('link', video_link) + form_data.append('unlisted', 1) + form_data.append("hash", u("meta[name=csrf]").attr("value")) + + window.messagebox_stack[1].getNode().find('.ovk-diag-action button').nodes[1].classList.add('lagged') + const fetcher_yt = await fetch(`/videos/upload`, { + method: 'POST', + body: form_data + }) + const fetcher_yt_results = await fetcher_yt.json() + append_result = fetcher_yt_results + + break + } + + if(append_result.payload) { + append_result = append_result.payload + const preview = append_result.image[0] + __appendToTextarea({ + 'type': 'video', + 'preview': preview.url, + 'id': append_result.owner_id + '_' + append_result.id, + 'fullsize_preview': preview.url, + }, node) + + window.messagebox_stack.forEach(msg_ => { + msg_.close() + }) + } else { + fastError(append_result.flash.message) + msg.close() + } + }] + }) + + msg.getNode().find('.ovk-diag-body').attr('style', 'padding:0px;height: 161px;') + async function __switchTab(tab_name) { + current_tab = tab_name + u(`#_fast_video_upload .mb_tab`).attr('id', 'ki') + u(`#_fast_video_upload .mb_tab[data-name='${current_tab}']`).attr('id', 'active') + + switch(current_tab) { + case 'file': + msg.getNode().find('#__content').html(` + + + + + + + + + + + + + + + +
${tr('info_name')}:
${tr('description')}:
${tr('video')}: + + +
+ `) + break + case 'youtube': + msg.getNode().find('#__content').html(` + + + + + + + + + + + + + + + +
${tr('info_name')}:
${tr('description')}:
${tr('video_link_to_yt')}: + +
+ `) + break + } + } + + u('#_fast_video_upload').on('click', '.mb_tab', (e) => { + __switchTab(u(e.target).closest('.mb_tab').nodes[0].dataset.name) + }) + + u('#_fast_video_upload').on('change', '#blob', (e) => { + u('#_fast_video_upload #filename').html(escapeHtml(e.target.files[0].name)) + u(`#_fast_video_upload input[name='name']`).nodes[0].value = escapeHtml(e.target.files[0].name) + }) + + __switchTab('file') +} + u(document).on('click', `.post-horizontal .upload-item .upload-delete`, (e) => { e.preventDefault() u(e.target).closest('.upload-item').remove() diff --git a/Web/static/js/messagebox.js b/Web/static/js/messagebox.js index 33b3b3cf..0bc51d86 100644 --- a/Web/static/js/messagebox.js +++ b/Web/static/js/messagebox.js @@ -8,12 +8,17 @@ class CMessageBox { const callbacks = options.callbacks ?? [] const close_on_buttons = options.close_on_buttons ?? true const unique_name = options.unique_name ?? null + const warn_on_exit = options.warn_on_exit ?? false + if(unique_name && window.messagebox_stack.find(item => item.unique_name == unique_name) != null) { + return + } this.title = title this.body = body this.id = random_int(0, 10000) this.close_on_buttons = close_on_buttons this.unique_name = unique_name + this.warn_on_exit = warn_on_exit u('body').addClass('dimmed').append(this.__getTemplate()) u('html').attr('style', 'overflow-y:hidden') @@ -49,10 +54,6 @@ class CMessageBox { } async __showCloseConfirmationDialog() { - if(window.messagebox_stack.find(item => item.unique_name == 'close_confirmation') != null) { - return - } - return new Promise((resolve, reject) => { const msg = new CMessageBox({ title: tr('exit_noun'), @@ -120,9 +121,11 @@ u(document).on('keyup', async (e) => { return } - const res = await msg.__showCloseConfirmationDialog() - if(res === true) { - msg.close() + if(msg.warn_on_exit) { + const res = await msg.__showCloseConfirmationDialog() + if(res === true) { + msg.close() + } } } }) @@ -140,9 +143,11 @@ u(document).on('click', 'body.dimmed .dimmer', async (e) => { return } - const res = await msg.__showCloseConfirmationDialog() - if(res === true) { - msg.close() + if(msg.warn_on_exit) { + const res = await msg.__showCloseConfirmationDialog() + if(res === true) { + msg.close() + } } } }) \ No newline at end of file diff --git a/locales/en.strings b/locales/en.strings index ece69a9f..eae93644 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -836,6 +836,9 @@ "no_videos" = "You don't have uploaded videos."; "no_videos_results" = "No results."; +"video_file_upload" = "Upload file"; +"video_youtube_upload" = "Add from YouTube"; + "change_video" = "Change video"; "unknown_video" = "This video is not supported in your version of OpenVK."; diff --git a/locales/ru.strings b/locales/ru.strings index e2020569..be398411 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -796,6 +796,9 @@ "no_videos" = "У вас нет видео."; "no_videos_results" = "Нет результатов."; +"video_file_upload" = "Загрузить файл"; +"video_youtube_upload" = "Добавить с YouTube"; + /* Audios */ "my" = "Моё";