mirror of
https://github.com/openvk/openvk
synced 2025-01-09 01:09:46 +03:00
refactor messagebox and repost logic
This commit is contained in:
parent
48c7751d6a
commit
4cb88f94dc
14 changed files with 506 additions and 261 deletions
|
@ -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()
|
||||
];
|
||||
|
|
|
@ -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 src="/assets/packages/static/openvk/js/node_modules/cropperjs/dist/cropper.js" type="module"></script>
|
||||
{script "js/al_music.js"}
|
||||
|
@ -51,7 +52,10 @@
|
|||
<div n:if="OPENVK_ROOT_CONF['openvk']['preferences']['bellsAndWhistles']['testLabel']" id="test-label">FOR TESTING PURPOSES ONLY</div>
|
||||
|
||||
<div class="notifications_global_wrap"></div>
|
||||
<div class="dimmer"></div>
|
||||
<div class="dimmer">
|
||||
<div id='absolute_territory'></div>
|
||||
</div>
|
||||
<div class="upLeftErrors"></div>
|
||||
|
||||
<div class="articleView">
|
||||
<a id="articleCloseButton" class="button" href="javascript:void(u('body').removeClass('article'));">{_close}</a>
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
<a n:if="!($forceNoCommentsLink ?? false) && $commentsCount == 0" href="javascript:expand_comment_textarea({$commentTextAreaId})">{_comment}</a>
|
||||
|
||||
<div class="like_wrap">
|
||||
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
|
||||
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" href="javascript:repost('{$post->getPrettyId()}', 'post')">
|
||||
<div class="repost-icon" style="opacity: 0.4;"></div>
|
||||
<span class="likeCnt" id="repostsCount{$post->getPrettyId()}">{if $repostsCount > 0}{$repostsCount}{/if}</span>
|
||||
</a>
|
||||
|
|
|
@ -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 = ""
|
||||
</script>
|
||||
|
||||
{if $graffiti}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -34,4 +34,22 @@ window.API = new Proxy(Object.create(null), {
|
|||
window.API.Types = {};
|
||||
window.API.Types.Message = (class Message {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"), "<div id='ovkDraw'></div>", [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: "<div id='ovkDraw'></div>",
|
||||
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'), `
|
||||
<div class='display_flex_column' style='gap: 1px;'>
|
||||
<b>${tr('auditory')}</b>
|
||||
|
||||
<div class='display_flex_column'>
|
||||
<label>
|
||||
<input type="radio" name="repost_type" value="wall" checked>
|
||||
${tr("in_wall")}
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input type="radio" name="repost_type" value="group">
|
||||
${tr("in_group")}
|
||||
</label>
|
||||
|
||||
<select name="selected_repost_club" style='display:none;'></select>
|
||||
</div>
|
||||
|
||||
<b>${tr('your_comment')}</b>
|
||||
|
||||
<input type='hidden' id='repost_attachments'>
|
||||
<textarea id='repostMsgInput' placeholder='...'></textarea>
|
||||
|
||||
<div id="repost_signs" class='display_flex_column' style='display:none;'>
|
||||
<label><input type='checkbox' name="asGroup">${tr('post_as_group')}</label>
|
||||
<label><input type='checkbox' name="signed">${tr('add_signature')}</label>
|
||||
</div>
|
||||
</div>
|
||||
`, [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(`(<b id='repostsCount${id}'>1</b>)`)
|
||||
}
|
||||
|
||||
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", "(<b id='repostsCount"+id+"'>1</b>)") //для старого вида постов
|
||||
}
|
||||
});
|
||||
},
|
||||
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(`<option value='${club.id}'>${ovk_proc_strtr(escapeHtml(club.name), 100)}</option>`)
|
||||
})
|
||||
}
|
||||
|
||||
$(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
|
||||
|
|
|
@ -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(
|
||||
`<div class="ovk-diag-cont">
|
||||
<div class="ovk-diag">
|
||||
<div class="ovk-diag-head">${title}</div>
|
||||
<div class="ovk-diag-body">${body}</div>
|
||||
<div class="ovk-diag-action"></div>
|
||||
</div>
|
||||
</div>`);
|
||||
u("body").addClass("dimmed").append(dialog);
|
||||
|
||||
buttons.forEach((text, callback) => {
|
||||
u(".ovk-diag-action").append(u(`<button class="button">${text}</button>`));
|
||||
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 ?? '<hr>'
|
||||
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(`<button class="button">${text}</button>`))
|
||||
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(
|
||||
`<div class="ovk-diag-cont" data-id="${this.id}">
|
||||
<div class="ovk-diag">
|
||||
<div class="ovk-diag-head">${this.title}</div>
|
||||
<div class="ovk-diag-body">${this.body}</div>
|
||||
<div class="ovk-diag-action"></div>
|
||||
</div>
|
||||
</div>`)
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
})
|
|
@ -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 = `
|
||||
<b>${tr('auditory')}:</b> <br/>
|
||||
<input type="radio" name="type" onchange="signs.setAttribute('hidden', 'hidden');document.getElementById('groupId').setAttribute('hidden', 'hidden')" value="wall" checked>${tr("in_wall")}<br/>
|
||||
<input type="radio" name="type" onchange="signs.removeAttribute('hidden');document.getElementById('groupId').removeAttribute('hidden')" value="group" id="group">${tr("in_group")}<br/>
|
||||
<select style="width:50%;" id="groupId" name="groupId" hidden>
|
||||
</select><br/>
|
||||
<b>${tr('your_comment')}:</b>
|
||||
<textarea id='uRepostMsgInput_${id}'></textarea>
|
||||
<div id="signs" hidden>
|
||||
<label><input onchange="signed.checked ? signed.checked = false : null" type="checkbox" id="asgroup" name="asGroup">${tr('post_as_group')}</label><br>
|
||||
<label><input onchange="asgroup.checked = true" type="checkbox" id="signed" name="signed">${tr('add_signature')}</label>
|
||||
</div>
|
||||
<br/><br/>`;
|
||||
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", "(<b id='repostsCount"+id+"'>1</b>)") //для старого вида постов
|
||||
}
|
||||
});
|
||||
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", `<option value="${el.id}">${escapeHtml(el.name)}</option>`)
|
||||
}
|
||||
|
||||
} catch(rejection) {
|
||||
console.error(rejection)
|
||||
document.getElementById("group").setAttribute("disabled", "disabled")
|
||||
}
|
||||
}
|
||||
|
||||
function setClubAdminComment(clubId, adminId, hash) {
|
||||
MessageBox("Изменить комментарий к администратору", `
|
||||
<form action="/club${clubId}/setAdmin" method="post" id="uClubAdminCommentForm_${clubId}_${adminId}">
|
||||
|
@ -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"), `
|
||||
<div class="messagebox-content-header">
|
||||
|
@ -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 `<span class='highlight'>${escapeHtml(match)}</span>`
|
||||
})
|
||||
|
||||
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");
|
||||
|
|
133
Web/static/js/utils.js
Normal file
133
Web/static/js/utils.js
Normal file
|
@ -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 `<span class='highlight'>${escapeHtml(match)}</span>`
|
||||
})
|
||||
|
||||
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(`
|
||||
<div class='upLeftError upLeftError${color}' data-id='${rand_id}'>${escapeHtml(text)}</div>
|
||||
`)
|
||||
|
||||
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;
|
||||
}
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -1652,6 +1652,8 @@
|
|||
"question_confirm" = "Это действие нельзя отменить. Вы действительно уверены в том что хотите сделать?";
|
||||
"confirm_m" = "Подтвердить";
|
||||
"action_successfully" = "Операция успешна";
|
||||
"exit_noun" = "Выход";
|
||||
"exit_confirmation" = "Уверены, что хотите выйти?";
|
||||
|
||||
/* User alerts */
|
||||
|
||||
|
|
Loading…
Reference in a new issue