diff --git a/VKAPI/Handlers/Wall.php b/VKAPI/Handlers/Wall.php index 13c42f07..f4a83d8c 100644 --- a/VKAPI/Handlers/Wall.php +++ b/VKAPI/Handlers/Wall.php @@ -661,25 +661,13 @@ final class Wall extends VKAPIRequestHandler (new WallPostNotification($wallOwner, $post, $this->user->identity))->emit(); if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2) { - $suggsCount = (new PostsRepo)->getSuggestedPostsCount($wallOwner->getId()); - - if($suggsCount % 10 == 0) { - $managers = $wallOwner->getManagers(); - $owner = $wallOwner->getOwner(); - (new NewSuggestedPostsNotification($owner, $wallOwner))->emit(); - - foreach($managers as $manager) { - (new NewSuggestedPostsNotification($manager->getUser(), $wallOwner))->emit(); - } - } - return (object)["post_id" => "on_view"]; } return (object)["post_id" => $post->getVirtualId()]; } - function repost(string $object, string $message = "", int $group_id = 0) { + function repost(string $object, string $message = "", string $attachments = "", int $group_id = 0, int $as_group = 0, int $signed = 0) { $this->requireUser(); $this->willExecuteWriteAction(); @@ -697,14 +685,22 @@ final class Wall extends VKAPIRequestHandler $nPost->setOwner($this->user->getId()); if($group_id > 0) { - $club = (new ClubsRepo)->get($group_id); + $club = (new ClubsRepo)->get($group_id); if(!$club) $this->fail(42, "Invalid group"); if(!$club->canBeModifiedBy($this->user)) $this->fail(16, "Access to group denied"); - $nPost->setWall($group_id * -1); + $nPost->setWall($club->getRealId()); + $flags = 0; + if($as_group === 1 || $signed === 1) + $flags |= 0b10000000; + + if($signed === 1) + $flags |= 0b01000000; + + $nPost->setFlags($flags); } else { $nPost->setWall($this->user->getId()); } @@ -712,14 +708,24 @@ final class Wall extends VKAPIRequestHandler $nPost->setContent($message); $nPost->setApi_Source_Name($this->getPlatform()); $nPost->save(); + $nPost->attach($post); - + $attachments_arr = parseAttachments($attachments, ['photo', 'video', 'audio']); + foreach($attachments_arr as $attachment) { + if(!$attachment || $attachment->isDeleted() || !$attachment->canBeViewedBy($this->getUser())) { + continue; + } + + $nPost->attach($attachment); + } + if($post->getOwner(false)->getId() !== $this->user->getId() && !($post->getOwner() instanceof Club)) (new RepostNotification($post->getOwner(false), $post, $this->user))->emit(); return (object) [ "success" => 1, // 👍 "post_id" => $nPost->getVirtualId(), + "pretty_id" => $nPost->getPrettyId(), "reposts_count" => $post->getRepostCount(), "likes_count" => $post->getLikesCount() ]; diff --git a/Web/Presenters/templates/@layout.xml b/Web/Presenters/templates/@layout.xml index b54ef44c..632bb96f 100644 --- a/Web/Presenters/templates/@layout.xml +++ b/Web/Presenters/templates/@layout.xml @@ -17,6 +17,7 @@ {script "js/node_modules/umbrellajs/umbrella.min.js"} {script "js/l10n.js"} {script "js/openvk.cls.js"} + {script "js/utils.js"} {script "js/node_modules/dashjs/dist/dash.all.min.js"} {script "js/al_music.js"} @@ -51,7 +52,10 @@
FOR TESTING PURPOSES ONLY
-
+
+
+
+
{_close} diff --git a/Web/Presenters/templates/components/post/microblogpost.xml b/Web/Presenters/templates/components/post/microblogpost.xml index ce720b55..a37076b1 100644 --- a/Web/Presenters/templates/components/post/microblogpost.xml +++ b/Web/Presenters/templates/components/post/microblogpost.xml @@ -126,7 +126,7 @@ {_comment}
- +
{if $repostsCount > 0}{$repostsCount}{/if}
diff --git a/Web/Presenters/templates/components/textArea.xml b/Web/Presenters/templates/components/textArea.xml index 859865ca..e53c1d88 100644 --- a/Web/Presenters/templates/components/textArea.xml +++ b/Web/Presenters/templates/components/textArea.xml @@ -114,9 +114,8 @@ setupWallPostInputHandlers({$textAreaId}); }); - u("#post-buttons{$textAreaId} input[name='videos']")["nodes"].at(0).value = "" - u("#post-buttons{$textAreaId} input[name='photos']")["nodes"].at(0).value = "" - u("#post-buttons{$textAreaId} input[name='audios']")["nodes"].at(0).value = "" + u("#post-buttons{$textAreaId} input[name='horizontal_attachments']")["nodes"].at(0).value = "" + u("#post-buttons{$textAreaId} input[name='vertical_attachments']")["nodes"].at(0).value = "" {if $graffiti} diff --git a/Web/static/css/dialog.css b/Web/static/css/dialog.css index c264dbb6..6f940d40 100644 --- a/Web/static/css/dialog.css +++ b/Web/static/css/dialog.css @@ -7,6 +7,11 @@ body.dimmed > .dimmer { opacity: .5; } +body.dimmed > .dimmer #absolute_territory { + margin: 100px; + height: 100%; +} + .ovk-diag-cont { z-index: 1024; position: fixed; diff --git a/Web/static/css/main.css b/Web/static/css/main.css index a0e37144..680a4a14 100644 --- a/Web/static/css/main.css +++ b/Web/static/css/main.css @@ -13,6 +13,10 @@ body { word-wrap: break-word; } +body, .ovk-fullscreen-dimmer { + scrollbar-gutter: stable both-edges; +} + .nobold, nobold { font-weight: normal; @@ -41,6 +45,11 @@ h1 { margin-top: 0; } +.display_flex_column { + display: flex; + flex-direction: column; +} + .layout { width: 791px; margin: 0 auto; @@ -254,6 +263,28 @@ h1 { width: calc(550px - 16px - 38px - 171px); } +.upLeftErrors { + position: absolute; + display: flex; + flex-direction: column; + z-index: 1025; +} + +.upLeftErrors .upLeftError { + padding: 2px 2px 2px 2px; + display: inline-block; + border-radius: 0px 0px 5px 0px; + font-size: 15px; +} + +.upLeftErrors .upLeftError.upLeftErrorRed { + background: #ff7474; +} + +.upLeftErrors .upLeftError.upLeftErrorGreen { + background: #74ff92; +} + .page_body { width: 632px; float: right; diff --git a/Web/static/js/al_api.js b/Web/static/js/al_api.js index 04344415..eb613dc1 100644 --- a/Web/static/js/al_api.js +++ b/Web/static/js/al_api.js @@ -34,4 +34,22 @@ window.API = new Proxy(Object.create(null), { window.API.Types = {}; window.API.Types.Message = (class Message { -}); \ No newline at end of file +}); + +window.OVKAPI = new class { + async call(method, params) { + if(!method) { + return + } + + const url = `/method/${method}?auth_mechanism=roaming&${new URLSearchParams(params).toString()}` + const res = await fetch(url) + const json_response = await res.json() + + if(json_response.response) { + return json_response.response + } else { + throw new Exception(json_response.error_msg) + } + } +} diff --git a/Web/static/js/al_music.js b/Web/static/js/al_music.js index 7ee1f035..f25518b4 100644 --- a/Web/static/js/al_music.js +++ b/Web/static/js/al_music.js @@ -1,13 +1,3 @@ -function fmtTime(time) { - const mins = String(Math.floor(time / 60)).padStart(2, '0'); - const secs = String(Math.floor(time % 60)).padStart(2, '0'); - return `${ mins}:${ secs}`; -} - -function fastError(message) { - MessageBox(tr("error"), message, [tr("ok")], [Function.noop]) -} - // elapsed это вроде прошедшие, а оставшееся это remaining но ладно уже function getElapsedTime(fullTime, time) { let timer = fullTime - time diff --git a/Web/static/js/al_wall.js b/Web/static/js/al_wall.js index a8273b21..76ce1750 100644 --- a/Web/static/js/al_wall.js +++ b/Web/static/js/al_wall.js @@ -1,35 +1,3 @@ -function humanFileSize(bytes, si) { - var thresh = si ? 1000 : 1024; - if(Math.abs(bytes) < thresh) { - return bytes + ' B'; - } - var units = si - ? ['kB','MB','GB','TB','PB','EB','ZB','YB'] - : ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB']; - var u = -1; - do { - bytes /= thresh; - ++u; - } while(Math.abs(bytes) >= thresh && u < units.length - 1); - return bytes.toFixed(1)+' '+units[u]; -} - -function trim(string) { - var newStr = string.substring(0, 10); - if(newStr.length !== string.length) - newStr += "…"; - - return newStr; -} - -function trimNum(string, num) { - var newStr = string.substring(0, num); - if(newStr.length !== string.length) - newStr += "…"; - - return newStr; -} - function handleUpload(id) { console.warn("блять..."); @@ -49,23 +17,34 @@ function handleUpload(id) { function initGraffiti(id) { let canvas = null; - let msgbox = MessageBox(tr("draw_graffiti"), "
", [tr("save"), tr("cancel")], [function() { - canvas.getImage({includeWatermark: false}).toBlob(blob => { - let fName = "Graffiti-" + Math.ceil(performance.now()).toString() + ".jpeg"; - let image = new File([blob], fName, {type: "image/jpeg", lastModified: new Date().getTime()}); + const msgbox = new CMessageBox({ + title: tr("draw_graffiti"), + body: "
", + close_on_buttons: false, + buttons: [tr("save"), tr("cancel")], + callbacks: [function() { + canvas.getImage({includeWatermark: false}).toBlob(blob => { + let fName = "Graffiti-" + Math.ceil(performance.now()).toString() + ".jpeg"; + let image = new File([blob], fName, {type: "image/jpeg", lastModified: new Date().getTime()}); + + fastUploadImage(id, image) + }, "image/jpeg", 0.92); - fastUploadImage(id, image) - }, "image/jpeg", 0.92); - - canvas.teardown(); - }, function() { - canvas.teardown(); - }]); + canvas.teardown(); + msgbox.close() + }, async function() { + const res = await msgbox.__showCloseConfirmationDialog() + if(res === true) { + canvas.teardown() + msgbox.close() + } + }] + }) let watermarkImage = new Image(); watermarkImage.src = "/assets/packages/static/openvk/img/logo_watermark.gif"; - msgbox.attr("style", "width: 750px;"); + msgbox.getNode().attr("style", "width: 750px;"); canvas = LC.init(document.querySelector("#ovkDraw"), { backgroundColor: "#fff", imageURLPrefix: "/assets/packages/static/openvk/js/node_modules/literallycanvas/lib/img", @@ -1382,6 +1361,124 @@ $(document).on("click", "#photosAttachments", async (e) => { }) }) +async function repost(id, repost_type = 'post') { + const repostsCount = u(`#repostsCount${id}`) + const previousVal = repostsCount.length > 0 ? Number(repostsCount.html()) : 0; + + MessageBox(tr('share'), ` +
+ ${tr('auditory')} + +
+ + + + + +
+ + ${tr('your_comment')} + + + + + +
+ `, [tr('send'), tr('cancel')], [ + async () => { + const message = u('#repostMsgInput').nodes[0].value + const type = u(`input[name='repost_type']:checked`).nodes[0].value + const club_id = parseInt(u(`select[name='selected_repost_club']`).nodes[0].selectedOptions[0].value) + const as_group = u(`input[name='asGroup']`).nodes[0].checked + const signed = u(`input[name='signed']`).nodes[0].checked + const attachments = u(`#repost_attachments`).nodes[0].value + + const params = {} + switch(repost_type) { + case 'post': + params.object = `wall${id}` + break + case 'video': + params.object = `video${id}` + break + } + + params.message = message + if(type == 'group' && club_id != 0) { + params.group_id = club_id + } + + if(as_group) { + params.as_group = Number(as_group) + } + + if(signed) { + params.signed = Number(signed) + } + + if(attachments != '') { + params.attachments = attachments + } + + try { + res = await window.OVKAPI.call('wall.repost', params) + if(repostsCount.length > 0) { + repostsCount.html(previousVal + 1) + } else { + u('#reposts' + id).append(`(1)`) + } + + NewNotification(tr('information_-1'), tr('shared_succ'), null, () => {window.location.assign(`/wall${res.pretty_id}`)}); + } catch(e) { + console.error(e) + fastError(e.message) + } + + xhr = new XMLHttpRequest(); + xhr.onload = (function() { + if(xhr.responseText.indexOf("wall_owner") === -1) { + let jsonR = JSON.parse(xhr.responseText); + + repostsCount != null ? + repostsCount.innerHTML = prevVal+1 : + document.getElementById("reposts"+id).insertAdjacentHTML("beforeend", "(1)") //для старого вида постов + } + }); + }, + Function.noop + ]); + + u('.ovk-diag-body').attr('style', 'padding: 14px;') + u('.ovk-diag-body').on('change', `input[name='repost_type']`, (e) => { + const value = e.target.value + + switch(value) { + case 'wall': + u('#repost_signs').attr('style', 'display:none') + u(`select[name='selected_repost_club']`).attr('style', 'display:none') + break + case 'group': + u('#repost_signs').attr('style', 'display:flex') + u(`select[name='selected_repost_club']`).attr('style', 'display:block') + break + } + }) + + const clubs = await window.OVKAPI.call('groups.get', {'filter': 'admin', 'count': 100}) + clubs.items.forEach(club => { + u(`select[name='selected_repost_club']`).append(``) + }) +} + $(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 diff --git a/Web/static/js/messagebox.js b/Web/static/js/messagebox.js index c9fa9c31..33b3b3cf 100644 --- a/Web/static/js/messagebox.js +++ b/Web/static/js/messagebox.js @@ -1,42 +1,148 @@ 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( - `
-
-
${title}
-
${body}
-
-
-
`); - u("body").addClass("dimmed").append(dialog); - - buttons.forEach((text, callback) => { - u(".ovk-diag-action").append(u(``)); - let button = u(u(".ovk-diag-action > button.button").last()); - - button.on("click", function(e) { - let __closeDialog = () => { - - if(document.querySelector(".ovk-photo-view-dimmer") == null && document.querySelector(".ovk-fullscreen-player") == null) { - u("body").removeClass("dimmed"); - document.querySelector("html").style.overflowY = "scroll" +class CMessageBox { + constructor(options = {}) { + const title = options.title ?? 'Untitled' + const body = options.body ?? '
' + const buttons = options.buttons ?? [] + const callbacks = options.callbacks ?? [] + const close_on_buttons = options.close_on_buttons ?? true + const unique_name = options.unique_name ?? null + + this.title = title + this.body = body + this.id = random_int(0, 10000) + this.close_on_buttons = close_on_buttons + this.unique_name = unique_name + + u('body').addClass('dimmed').append(this.__getTemplate()) + u('html').attr('style', 'overflow-y:hidden') + + buttons.forEach((text, callback) => { + this.getNode().find('.ovk-diag-action').append(u(``)) + let button = u(this.getNode().find('.ovk-diag-action > button.button').last()) + button.on("click", (e) => { + callbacks[callback]() + + if(close_on_buttons) { + this.close() } - - u(".ovk-diag-cont").remove(); - }; - - Reflect.apply(callbacks[callback], { - closeDialog: () => __closeDialog(), - $dialog: () => u(".ovk-diag-cont") - }, [e]); + }) + }) + + window.messagebox_stack.push(this) + } + + __getTemplate() { + return u( + `
+
+
${this.title}
+
${this.body}
+
+
+
`) + } + + getNode() { + return u(`.ovk-diag-cont[data-id='${this.id}']`) + } + + 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'), + body: tr('exit_confirmation'), + warn_on_exit: false, + unique_name: 'close_confirmation', + buttons: [tr('no'), tr('yes')], + callbacks: [() => { + msg.close() + resolve(false) + }, () => { + this.__exitDialog() + resolve(true) + }] + }) + }) + } + + __exitDialog() { + u(`.ovk-diag-cont[data-id='${this.id}']`).remove() + if(u('.ovk-diag-cont').length < 1) { + u('body').removeClass('dimmed') + u('html').attr('style', 'overflow-y:scroll') + } + + const current_item = window.messagebox_stack.find(item => item.id == this.id) + const index_of_item = window.messagebox_stack.indexOf(current_item) + window.messagebox_stack = array_splice(window.messagebox_stack, index_of_item) - __closeDialog(); - }); - }); - - return u(".ovk-diag-cont"); + delete this + } + + close() { + this.__exitDialog() + } } + +window.messagebox_stack = [] + +function MessageBox(title, body, buttons, callbacks, return_msg = false) { + const msg = new CMessageBox({ + title: title, + body: body, + buttons: buttons, + callbacks: callbacks, + }) + + if(return_msg) { + return msg + } + + return msg.getNode() +} + +// Close on 'Escape' key +u(document).on('keyup', async (e) => { + if(e.keyCode == 27 && window.messagebox_stack.length > 0) { + const msg = window.messagebox_stack[window.messagebox_stack.length - 1] + if(!msg) { + return + } + + if(msg.close_on_buttons) { + msg.close() + return + } + + const res = await msg.__showCloseConfirmationDialog() + if(res === true) { + msg.close() + } + } +}) + +// Close when clicking on shadow +u(document).on('click', 'body.dimmed .dimmer', async (e) => { + if(u(e.target).hasClass('dimmer')) { + const msg = window.messagebox_stack[window.messagebox_stack.length - 1] + if(!msg) { + return + } + + if(msg.close_on_buttons) { + msg.close() + return + } + + const res = await msg.__showCloseConfirmationDialog() + if(res === true) { + msg.close() + } + } +}) \ No newline at end of file diff --git a/Web/static/js/openvk.cls.js b/Web/static/js/openvk.cls.js index a1b1e584..f849cdd7 100644 --- a/Web/static/js/openvk.cls.js +++ b/Web/static/js/openvk.cls.js @@ -16,19 +16,6 @@ function expand_comment_textarea(id) { wi.focus(); } -function edit_post(id, wid) { - var el = document.getElementById('text'+wid+'_'+id); - var ed = document.getElementById('text_edit'+wid+'_'+id); - if (el.style.display == "none") { - el.style.display = "block"; - ed.style.display = "none"; - } else { - el.style.display = "none"; - ed.style.display = "block"; - } -} - - function hidePanel(panel, count = 0) { $(panel).toggleClass("content_title_expanded content_title_unexpanded"); @@ -189,74 +176,6 @@ document.addEventListener("DOMContentLoaded", function() { //BEGIN }) }); //END ONREADY DECLS -async function repostPost(id, hash) { - uRepostMsgTxt = ` - ${tr('auditory')}:
- ${tr("in_wall")}
- ${tr("in_group")}
-
- ${tr('your_comment')}: - - -

`; - let clubs = []; - repostsCount = document.getElementById("repostsCount"+id) - prevVal = repostsCount != null ? Number(repostsCount.innerHTML) : 0; - - MessageBox(tr('share'), uRepostMsgTxt, [tr('send'), tr('cancel')], [ - (function() { - text = document.querySelector("#uRepostMsgInput_"+id).value; - type = "user"; - radios = document.querySelectorAll('input[name="type"]') - for(const r of radios) - { - if(r.checked) - { - type = r.value; - break; - } - } - groupId = document.querySelector("#groupId").value; - asGroup = asgroup.checked == true ? 1 : 0; - signed = signed.checked == true ? 1 : 0; - hash = encodeURIComponent(hash); - - xhr = new XMLHttpRequest(); - xhr.open("POST", "/wall"+id+"/repost?hash="+hash, true); - xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - xhr.onload = (function() { - if(xhr.responseText.indexOf("wall_owner") === -1) - MessageBox(tr('error'), tr('error_repost_fail'), [tr('ok')], [Function.noop]); - else { - let jsonR = JSON.parse(xhr.responseText); - NewNotification(tr('information_-1'), tr('shared_succ'), null, () => {window.location.href = "/wall" + jsonR.wall_owner}); - repostsCount != null ? - repostsCount.innerHTML = prevVal+1 : - document.getElementById("reposts"+id).insertAdjacentHTML("beforeend", "(1)") //для старого вида постов - } - }); - xhr.send('text='+encodeURI(text) + '&type='+type + '&groupId='+groupId + "&asGroup="+asGroup + "&signed="+signed); - }), - Function.noop - ]); - - try - { - clubs = await API.Groups.getWriteableClubs(); - for(const el of clubs) { - document.getElementById("groupId").insertAdjacentHTML("beforeend", ``) - } - - } catch(rejection) { - console.error(rejection) - document.getElementById("group").setAttribute("disabled", "disabled") - } -} - function setClubAdminComment(clubId, adminId, hash) { MessageBox("Изменить комментарий к администратору", `
@@ -322,17 +241,6 @@ function showCoinsTransferDialog(coinsCount, hash) { ]); } -function chunkSubstr(string, size) { - const numChunks = Math.ceil(string.length / size); - const chunks = new Array(numChunks); - - for (let i = 0, o = 0; i < numChunks; ++i, o += size) { - chunks[i] = string.substr(o, size); - } - - return chunks; -} - function autoTab(original, next, previous) { if(original.getAttribute && original.value.length == original.getAttribute("maxlength") && next !== undefined) next.focus(); @@ -364,11 +272,6 @@ function supportFastAnswerDialogOnClick(answer) { answerInput.focus(); } -function ovk_proc_strtr(string, length = 0) { - const newString = string.substring(0, length); - return newString + (string !== newString ? "…" : ""); -} - function showProfileDeactivateDialog(hash) { MessageBox(tr("profile_deactivate"), `
@@ -491,57 +394,6 @@ function showIncreaseRatingDialog(coinsCount, userUrl, hash) { }; } -function escapeHtml(text) { - var map = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - - return text.replace(/[&<>"']/g, function(m) { return map[m]; }); -} - -function highlightText(searchText, container_selector, selectors = []) { - const container = u(container_selector) - const regexp = new RegExp(`(${searchText})`, 'gi') - - function highlightNode(node) { - if(node.nodeType == 3) { - let newNode = escapeHtml(node.nodeValue) - newNode = newNode.replace(regexp, (match, ...args) => { - return `${escapeHtml(match)}` - }) - - const tempDiv = document.createElement('div') - tempDiv.innerHTML = newNode - - while(tempDiv.firstChild) { - node.parentNode.insertBefore(tempDiv.firstChild, node) - } - node.parentNode.removeChild(node) - } else if(node.nodeType === 1 && node.tagName !== 'SCRIPT' && node.tagName !== 'BR' && node.tagName !== 'STYLE') { - Array.from(node.childNodes).forEach(highlightNode); - } - } - - selectors.forEach(selector => { - elements = container.find(selector) - if(!elements || elements.length < 1) return; - - elements.nodes.forEach(highlightNode) - }) -} - -String.prototype.escapeHtml = function() { - try { - return escapeHtml(this) - } catch(e) { - return '' - } -} - $(document).on("scroll", () => { if($(document).scrollTop() > $(".sidebar").height() + 50) { $(".floating_sidebar")[0].classList.add("show"); diff --git a/Web/static/js/utils.js b/Web/static/js/utils.js new file mode 100644 index 00000000..5a18edc2 --- /dev/null +++ b/Web/static/js/utils.js @@ -0,0 +1,133 @@ +function escapeHtml(text) { + var map = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + return text.replace(/[&<>"']/g, function(m) { return map[m]; }); +} + +function highlightText(searchText, container_selector, selectors = []) { + const container = u(container_selector) + const regexp = new RegExp(`(${searchText})`, 'gi') + + function highlightNode(node) { + if(node.nodeType == 3) { + let newNode = escapeHtml(node.nodeValue) + newNode = newNode.replace(regexp, (match, ...args) => { + return `${escapeHtml(match)}` + }) + + const tempDiv = document.createElement('div') + tempDiv.innerHTML = newNode + + while(tempDiv.firstChild) { + node.parentNode.insertBefore(tempDiv.firstChild, node) + } + node.parentNode.removeChild(node) + } else if(node.nodeType === 1 && node.tagName !== 'SCRIPT' && node.tagName !== 'BR' && node.tagName !== 'STYLE') { + Array.from(node.childNodes).forEach(highlightNode); + } + } + + selectors.forEach(selector => { + elements = container.find(selector) + if(!elements || elements.length < 1) return; + + elements.nodes.forEach(highlightNode) + }) +} + +String.prototype.escapeHtml = function() { + try { + return escapeHtml(this) + } catch(e) { + return '' + } +} + +function fmtTime(time) { + const mins = String(Math.floor(time / 60)).padStart(2, '0'); + const secs = String(Math.floor(time % 60)).padStart(2, '0'); + return `${ mins}:${ secs}`; +} + +function fastError(message) { + MessageBox(tr("error"), message, [tr("ok")], [Function.noop]) +} + +function humanFileSize(bytes, si) { + var thresh = si ? 1000 : 1024; + if(Math.abs(bytes) < thresh) { + return bytes + ' B'; + } + var units = si + ? ['kB','MB','GB','TB','PB','EB','ZB','YB'] + : ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB']; + var u = -1; + do { + bytes /= thresh; + ++u; + } while(Math.abs(bytes) >= thresh && u < units.length - 1); + return bytes.toFixed(1)+' '+units[u]; +} + +function trim(string) { + var newStr = string.substring(0, 10); + if(newStr.length !== string.length) + newStr += "…"; + + return newStr; +} + +function trimNum(string, num) { + return ovk_proc_strtr(string, num); +} + +function ovk_proc_strtr(string, length = 0) { + const newString = string.substring(0, length); + return newString + (string !== newString ? "…" : ""); +} + +function chunkSubstr(string, size) { + const numChunks = Math.ceil(string.length / size); + const chunks = new Array(numChunks); + + for (let i = 0, o = 0; i < numChunks; ++i, o += size) { + chunks[i] = string.substr(o, size); + } + + return chunks; +} + +function random_int(min, max) { + return Math.round(Math.random() * (max - min) + min) +} + +function makeError(text, color = 'Red', timeout = 10000) { + const rand_id = random_int(0, 10000) + + u('.upLeftErrors').append(` +
${escapeHtml(text)}
+ `) + + setTimeout(() => { + u(`.upLeftError[data-id='${rand_id}']`).remove() + }, timeout) +} + +function array_splice(array, key) +{ + let resultArray = []; + + for(let i = 0; i < array.length; i++){ + if(i != key){ + resultArray.push(array[i]); + } + } + + return resultArray; +} diff --git a/locales/en.strings b/locales/en.strings index 50c045b2..ece69a9f 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -1762,6 +1762,8 @@ "question_confirm" = "This action can't be undone. Do you really wanna do it?"; "confirm_m" = "Confirm"; "action_successfully" = "Success"; +"exit_noun" = "Exit"; +"exit_confirmation" = "Are you sure want to exit?"; /* User Alerts */ diff --git a/locales/ru.strings b/locales/ru.strings index 93f553e4..e8b27be1 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -1652,6 +1652,8 @@ "question_confirm" = "Это действие нельзя отменить. Вы действительно уверены в том что хотите сделать?"; "confirm_m" = "Подтвердить"; "action_successfully" = "Операция успешна"; +"exit_noun" = "Выход"; +"exit_confirmation" = "Уверены, что хотите выйти?"; /* User alerts */