Compare commits

...

2 commits

Author SHA1 Message Date
mrilyew
2cff603e11 Add ajax player
Осталось пофиксить скрипты и создание плейлистов! Ну и ещё некоторые хуйни по аудиозаписям которые я задумал.
2024-11-29 23:26:20 +03:00
mrilyew
34143055b4 Fix most common script problems pt1 2024-11-28 23:15:50 +03:00
21 changed files with 743 additions and 442 deletions

View file

@ -228,6 +228,7 @@ final class AuthPresenter extends OpenVKPresenter
return;
}
$this->template->disable_ajax = 1;
$this->template->is2faEnabled = $request->getUser()->is2faEnabled();
if($_SERVER["REQUEST_METHOD"] === "POST") {

View file

@ -38,6 +38,7 @@ final class NoSpamPresenter extends OpenVKPresenter
if ($mode === "form") {
$this->template->_template = "NoSpam/Index";
$this->template->disable_ajax = 1;
$foundClasses = [];
foreach (Finder::findFiles('*.php')->from($targetDir) as $file) {
$content = file_get_contents($file->getPathname());
@ -67,6 +68,7 @@ final class NoSpamPresenter extends OpenVKPresenter
$this->template->models = $models;
} else if ($mode === "templates") {
$this->template->_template = "NoSpam/Templates.xml";
$this->template->disable_ajax = 1;
$filter = [];
if ($this->queryParam("id")) {
$filter["id"] = (int)$this->queryParam("id");

View file

@ -282,10 +282,9 @@ abstract class OpenVKPresenter extends SimplePresenter
$this->redirect("/maintenances/");
}
}
if($this->queryParam('al') == '1') {
if($_SERVER['HTTP_X_OPENVK_AJAX_QUERY'] == '1' && $this->user->identity) {
error_reporting(0);
$this->assertNoCSRF();
header('Content-Type: text/plain; charset=UTF-8');
}

View file

@ -43,6 +43,7 @@ final class ReportPresenter extends OpenVKPresenter
"perPage" => 15,
];
$this->template->mode = $act ?? "all";
$this->template->disable_ajax = 1;
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$reports = [];
@ -78,6 +79,7 @@ final class ReportPresenter extends OpenVKPresenter
$this->notFound();
$this->template->report = $report;
$this->template->disable_ajax = 1;
}
function renderCreate(int $id): void

View file

@ -198,18 +198,18 @@
{var $canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
{var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="{_admin} [Alt+Shift+A]" accesskey="a">{_admin}</a>
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">{_helpdesk}
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="{_admin} [Alt+Shift+A]" accesskey="a" rel="nofollow">{_admin}</a>
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk" rel="nofollow">{_helpdesk}
{if $helpdeskTicketNotAnsweredCount > 0}
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
{/if}
</a>
<a n:if="$canAccessHelpdesk" href="/scumfeed" class="link">{tr("reports")}
<a n:if="$canAccessHelpdesk" href="/scumfeed" class="link" rel="nofollow">{tr("reports")}
{if $reportNotAnsweredCount > 0}
(<b>{$reportNotAnsweredCount}</b>)
{/if}
</a>
<a n:if="$canAccessHelpdesk" href="/noSpam" class="link">
<a n:if="$canAccessHelpdesk" href="/noSpam" class="link" rel="nofollow">
noSpam
</a>
<a
@ -392,6 +392,7 @@
{script "js/al_navigation.js"}
{script "js/al_comments.js"}
{script "js/al_music.js"}
{script "js/al_despacito_wall.js"}
{ifset $thisUser}
{script "js/al_notifs.js"}
@ -433,13 +434,14 @@
//]]>
</script>
<script>
<script id='_js_ep_script'>
window.openvk = {
"audio_genres": {\openvk\Web\Models\Entities\Audio::genres},
"at_search": {$atSearch ?? false},
"max_attachments": {\OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["postSizes"]["maxAttachments"] ?? 10},
"max_filesize_mb": 5,
"current_id": {$thisUser ? $thisUser->getId() : 0},
"disable_ajax": {$disable_ajax ? $disable_ajax : 0},
}
</script>

View file

@ -70,33 +70,4 @@
<button class="button" type="submit">{_save}</button>
</div>
</form>
<script>
document.querySelector("input[name='audios']").value = {$audiosIds}
u("#editPlaylistForm").on("submit", (e) => {
document.querySelector("#editPlaylistForm input[name='title']").value = document.querySelector(".playlistInfo input[name='title']").value
document.querySelector("#editPlaylistForm textarea[name='description']").value = document.querySelector(".playlistBlock textarea[name='description']").value
document.querySelector("#editPlaylistForm input[name='is_unlisted']").value = document.querySelector("input[name='is_unlisted']").checked ? 1 : 0
})
u("#editPlaylistForm input[name='new_cover']").on("change", (e) => {
if(!e.currentTarget.files[0].type.startsWith("image/")) {
fastError(tr("not_a_photo"))
return
}
let image = URL.createObjectURL(e.currentTarget.files[0])
document.querySelector(".playlistCover img").src = image
})
u(".playlistCover img").on("click", (e) => {
document.querySelector("input[name='new_cover']").click()
})
document.querySelector("#editPlaylistForm input[name='new_cover']").value = ""
</script>
{script "js/al_playlists.js"}
{/block}

View file

@ -51,24 +51,6 @@
</div>
</div>
<div style="margin-top: 19px;">
<input id="playlist_query" type="text" style="height: 26px;" placeholder="{_header_search}">
<div class="playlistAudiosContainer editContainer">
<div id="newPlaylistAudios" n:foreach="$audios as $audio">
<div style="width: 78%;float: left;">
{include "player.xml", audio => $audio, hideButtons => true}
</div>
<div class="attachAudio addToPlaylist" data-id="{$audio->getId()}">
<span>{_add_to_playlist}</span>
</div>
</div>
</div>
<div class="showMoreAudiosPlaylist" data-page="2" {if !is_null($_GET["gid"])}data-club="{abs($_GET['gid'])}"{/if} n:if="$pagesCount > 1">
{_show_more_audios}
</div>
</div>
<form method="post" id="newPlaylistForm" enctype="multipart/form-data">
<input type="hidden" name="title" maxlength="125" />
<input type="hidden" name="hash" value="{$csrfToken}" />
@ -81,35 +63,4 @@
<button class="button" type="submit">{_create}</button>
</div>
</form>
<script>
document.querySelector("input[name='audios']").value = ""
u("#newPlaylistForm").on("submit", (e) => {
document.querySelector("#newPlaylistForm input[name='title']").value = document.querySelector(".plinfo input[name='title']").value
document.querySelector("#newPlaylistForm textarea[name='description']").value = document.querySelector(".plinfo textarea[name='description']").value
document.querySelector("#newPlaylistForm input[name='is_unlisted']").value = document.querySelector(".plinfo input[name='is_unlisted']").checked ? 1 : 0
})
u("#newPlaylistForm input[name='cover']").on("change", (e) => {
if(!e.currentTarget.files[0].type.startsWith("image/")) {
fastError(tr("not_a_photo"))
return
}
let image = URL.createObjectURL(e.currentTarget.files[0])
document.querySelector(".playlistCover img").src = image
document.querySelector(".playlistCover img").style.display = "block"
})
u(".playlistCover img").on("click", (e) => {
document.querySelector("#newPlaylistForm input[name='cover']").value = ""
e.currentTarget.href = ""
})
document.querySelector("#newPlaylistForm input[name='cover']").value = ""
</script>
{script "js/al_playlists.js"}
{/block}

View file

@ -13,7 +13,7 @@
{block content}
<div class="gift_grid scroll_container">
<div n:foreach="$gifts as $gift" n:class="scroll_node, gift_sel, !$gift->canUse($thisUser) ? disabled" data-gift="{$gift->getId()}">
<a href='/gifts?act=confirm&user={$user->getId()}&pack={$cat->getId()}&elid={$gift->getId()}' n:foreach="$gifts as $gift" n:class="scroll_node, gift_sel, !$gift->canUse($thisUser) ? disabled" data-gift="{$gift->getId()}">
<img class="gift_pic" src="{$gift->getImage(2)}" alt="{_gift}" loading=lazy />
<strong class="gift_price">
@ -29,7 +29,7 @@
{tr("gifts_left", $gift->getUsagesLeft($thisUser))}
{/if}&nbsp;
</strong>
</div>
</a>
</div>
<div style="padding: 8px;">
@ -41,18 +41,3 @@
]}
</div>
{/block}
{block bodyScripts}
<script>
$(".gift_sel").click(function() {
let el = $(this);
if(el.hasClass("disabled"))
return false;
let link = "/gifts?act=confirm&user={$user->getId()}&pack={$cat->getId()}&elid=";
let gift = el.data("gift");
window.router.route(link + gift);
});
</script>
{/block}

View file

@ -82,23 +82,25 @@
</table>
<script n:if="$club->getOwner()->getId() != $user->getId() && $manager && $thisUser->getId() == $club->getOwner()->getId()">
function changeOwner(club, newOwner) {
const action = "/groups/" + club + "/setNewOwner/" + newOwner;
if(typeof changeOwner == 'undefined') {
function changeOwner(club, newOwner) {
const action = "/groups/" + club + "/setNewOwner/" + newOwner;
MessageBox({_group_changeowner_modal_title}, `
{tr("group_changeowner_modal_text", htmlentities($user->getFullName()))|noescape}
<br/><br/>
<form id="transfer-owner-permissions-form" method="post">
<label for="password">{_password|noescape}</label>
<input type="password" id="password" name="password" required />
<input type="hidden" name="hash" value={$csrfToken} />
</form>
`, [{_transfer}, {_cancel}], [
() => {
$("#transfer-owner-permissions-form").attr("action", action);
document.querySelector("#transfer-owner-permissions-form").submit();
}, Function.noop
]);
MessageBox({_group_changeowner_modal_title}, `
{tr("group_changeowner_modal_text", htmlentities($user->getFullName()))|noescape}
<br/><br/>
<form id="transfer-owner-permissions-form" method="post">
<label for="password">{_password|noescape}</label>
<input type="password" id="password" name="password" required />
<input type="hidden" name="hash" value={$csrfToken} />
</form>
`, [{_transfer}, {_cancel}], [
() => {
$("#transfer-owner-permissions-form").attr("action", action);
document.querySelector("#transfer-owner-permissions-form").submit();
}, Function.noop
]);
}
}
</script>
{/block}

View file

@ -318,7 +318,3 @@
</div>
{/block}
{block bodyScripts}
{script "js/al_despacito_wall.js"}
{/block}

View file

@ -165,33 +165,10 @@
</form>
{/if}
<a class="profile_link" style="display:block;width:96%;" href="javascript:reportUser()">{_report}</a>
<a class="profile_link" style="display:block;width:96%;" href="javascript:reportUser({$user->getId()})">{_report}</a>
<a n:if="!$user->isHideFromGlobalFeedEnabled()" class="profile_link" style="display:block;width:96%;" id="__ignoreSomeone" data-val='{!$ignore_status ? 1 : 0}' data-id="{$user->getId()}">
{if !$ignore_status}{_ignore_user}{else}{_unignore_user}{/if}
</a>
<script>
function reportUser() {
uReportMsgTxt = tr("going_to_report_user");
uReportMsgTxt += "<br/>"+tr("report_question_text");
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
MessageBox(tr("report_question"), uReportMsgTxt, [tr("confirm_m"), tr("cancel")], [
(function() {
res = document.querySelector("#uReportMsgInput").value;
xhr = new XMLHttpRequest();
xhr.open("GET", "/report/" + {$user->getId()} + "?reason=" + res + "&type=user", true);
xhr.onload = (function() {
if(xhr.responseText.indexOf("reason") === -1)
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]);
else
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]);
});
xhr.send(null);
}),
Function.noop
]);
}
</script>
{/if}
<a style="width: 194px;" n:if="$user->getFollowersCount() > 0" href="/friends{$user->getId()}?act=incoming" class="profile_link">{tr("followers", $user->getFollowersCount())}</a>
</div>
@ -760,51 +737,6 @@
}
{/if}
</script>
<script n:if="isset($thisUser) && $user->getId() == $thisUser->getId()" n:syntax="off">
function setStatusEditorShown(shown) {
document.getElementById("status_editor").style.display = shown ? "block" : "none";
}
document.addEventListener("click", event => {
if(!event.target.closest("#status_editor") && !event.target.closest("#page_status_text"))
setStatusEditorShown(false);
});
document.getElementById("page_status_text").onclick = setStatusEditorShown.bind(this, true);
async function changeStatus() {
const status = document.status_popup_form.status.value;
const broadcast = document.status_popup_form.broadcast.checked;
document.status_popup_form.submit.innerHTML = "<div class=\"button-loading\"></div>";
document.status_popup_form.submit.disabled = true;
const formData = new FormData();
formData.append("status", status);
formData.append("broadcast", Number(broadcast));
formData.append("hash", document.status_popup_form.hash.value);
const response = await ky.post("/edit?act=status", {body: formData});
if(!parseAjaxResponse(await response.text())) {
document.status_popup_form.submit.innerHTML = tr("send");
document.status_popup_form.submit.disabled = false;
return;
}
if(document.status_popup_form.status.value === "") {
document.querySelector("#page_status_text").innerHTML = `[ ${tr("change_status")} ]`;
document.querySelector("#page_status_text").className = "edit_link page_status_edit_button";
} else {
document.querySelector("#page_status_text").innerHTML = status;
document.querySelector("#page_status_text").className = "page_status page_status_edit_button";
}
setStatusEditorShown(false);
document.status_popup_form.submit.innerHTML = tr("send");
document.status_popup_form.submit.disabled = false;
}
</script>
</div>
{/if}
@ -813,7 +745,3 @@
{include "banned.xml"}
{/if}
{/block}
{block bodyScripts}
{script "js/al_despacito_wall.js"}
{/block}

View file

@ -54,11 +54,11 @@
<input type="checkbox" name="as_group" /> {_comment_as_group}
</label>
</div>
<input type="hidden" name="horizontal_attachments" value="" />
<input type="hidden" name="vertical_attachments" value="" />
<input type="hidden" name="poll" value="none" />
<input type="hidden" id="source" name="source" value="none" />
<input type="hidden" name="type" value="1" />
<input type="hidden" name="horizontal_attachments" value="" autocomplete="off" />
<input type="hidden" name="vertical_attachments" value="" autocomplete="off" />
<input type="hidden" name="poll" value="none" autocomplete="off" />
<input type="hidden" id="source" name="source" value="none" autocomplete="off" />
<input type="hidden" name="type" value="1" autocomplete="off" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<br/>
<input type="submit" value="{_write}" class="button" />
@ -105,11 +105,6 @@
</form>
</div>
<script>
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}
{script "js/node_modules/react/dist/react-with-addons.min.js"}
{script "js/node_modules/react-dom/dist/react-dom.min.js"}

View file

@ -13,7 +13,7 @@
}
.musicIcon {
background-image: url('/assets/packages/static/openvk/img/audios_controls.png?v=2');
background-image: url('/assets/packages/static/openvk/img/audios_controls.png?v=6');
background-repeat: no-repeat;
cursor: pointer;
}
@ -150,7 +150,7 @@
}
.bigPlayer .slider, .audioEmbed .track .slider {
width: 18px;
width: 15px;
height: 7px;
background: #606060;
position: absolute;
@ -231,13 +231,13 @@
}
.bigPlayer .trackPanel .track .selectableTrack > div {
width: 95%;
width: 96%;
position: relative;
}
.bigPlayer .volumePanel .selectableTrack > div {
position: relative;
width: 72%
width: 77%;
}
.audioEmbed .track > .selectableTrack, .bigPlayer .selectableTrack {
@ -881,3 +881,137 @@
margin-top: 6px;
padding: 1px;
}
/* AJAX player */
#ajax_audio_player {
transition: background .1s ease-out;
background: rgba(44, 44, 44, 0.7);
padding: 1px;
width: 500px;
height: 37px;
position: fixed;
z-index: 99;
border-radius: 3px;
}
#ajax_audio_player.hidden {
display: none;
}
#ajax_audio_player #aj_player {
position: relative;
height: 100%;
}
#ajax_audio_player #aj_player #aj_player_internal_controls {
padding: 7px 8px;
display: flex;
gap: 7px;
}
#ajax_audio_player.ui-draggable-dragging {
background: rgba(20, 20, 20, 0.9);
}
#ajax_audio_player #aj_player_close_btn, #ajax_audio_player #aj_player_play {
padding: 3px 0px;
}
#ajax_audio_player #aj_player_close_btn,
#ajax_audio_player #aj_player_play #aj_player_play_btn,
#ajax_audio_player #aj_player_buttons > div {
background: url('/assets/packages/static/openvk/img/audios_controls.png?v=6');
background-repeat: no-repeat;
cursor: pointer;
}
#ajax_audio_player #aj_player_close_btn {
position: absolute;
top: 0;
right: 0;
width: 10px;
height: 9px;
background-position: 0px -77px;
opacity: 0.6;
}
#ajax_audio_player #aj_player_close_btn:hover {
opacity: 1;
}
#ajax_audio_player #aj_player_play #aj_player_play_btn {
width: 16px;
height: 16px;
background-position: -147px -28px;
}
#ajax_audio_player #aj_player_play #aj_player_play_btn.paused {
background-position: -165px -28px;
}
#ajax_audio_player #aj_player_track {
width: 100%;
position: relative;
}
#ajax_audio_player #aj_player_track #aj_player_track_name {
display: flex;
justify-content: space-between;
}
#ajax_audio_player #aj_player_track #aj_player_track_name #aj_player_track_title,
#ajax_audio_player #aj_player_track #aj_player_track_name #aj_player_track_title b,
#ajax_audio_player #aj_player_track #aj_player_track_name #aj_player_track_title span,
#ajax_audio_player #aj_player_track #aj_player_track_name span {
color: white;
}
#ajax_audio_player .selectableTrack {
width: 100%;
position: relative;
height: 6px;
border-top: #ffffff 1px solid;
user-select: none;
}
#ajax_audio_player .selectableTrack .slider {
width: 11px;
height: 6px;
background: #ffffff;
position: absolute;
}
#ajax_audio_player #aj_player_volume {
width: 60px;
padding-top: 15px;
position: relative;
}
#ajax_audio_player #aj_player_buttons {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
}
#ajax_audio_player #aj_player_buttons #aj_player_previous {
width: 14px;
height: 12px;
background-position: -194px -5px;
}
#ajax_audio_player #aj_player_buttons #aj_player_repeat {
width: 14px;
height: 13px;
background-position: -233px -5px;
}
#ajax_audio_player #aj_player_buttons #aj_player_repeat.pressed {
opacity: 0.6;
}
#ajax_audio_player #aj_player_buttons #aj_player_next {
width: 15px;
height: 12px;
background-position: -214px -5px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -1,4 +1,3 @@
const contentPage = document.querySelector(".page_content");
const rootElement = document.documentElement;
// охуенное название файла, КТО ЭТО ПРИДУМАЛ КРАСАВА Я ИЗ КОМНАТЫ С ЭТОГО УЛЕТЕЛ НАХУЙ
@ -8,11 +7,11 @@ let scrolledAndHidden = false;
let smallBlockObserver = new IntersectionObserver(entries => {
entries.forEach(x => {
window.requestAnimationFrame(() => {
let pastHeight = contentPage.getBoundingClientRect().height;
let pastHeight = u('.page_content').nodes[0].getBoundingClientRect().height;
if(x.isIntersecting)
contentPage.classList.remove("overscrolled");
u('.page_content').nodes[0].classList.remove("overscrolled");
else
contentPage.classList.add("overscrolled");
u('.page_content').nodes[0].classList.add("overscrolled");
// let currentHeight = contentPage.getBoundingClientRect().height;
// let ratio = currentHeight / pastHeight;
@ -22,7 +21,7 @@ let smallBlockObserver = new IntersectionObserver(entries => {
// То что я задокументировал - работает мегакриво.
// Пусть юзер и проскролливает какую-то часть контента, зато не получит
// эпилепсии при использовании :)
}, contentPage);
}, u('.page_content').nodes[0]);
});
}, {
root: null, // screen

View file

@ -1,5 +1,3 @@
window.savedAudiosPages = {}
class playersSearcher {
constructor(context_type, context_id) {
this.context_type = context_type
@ -68,6 +66,18 @@ window.player = new class {
return this.__realAudioPlayer
}
get linkedInlinePlayer() {
if(!this.__linked_player_id) {
return null;
}
return u('#' + this.__linked_player_id)
}
get ajaxPlayer() {
return u('#ajax_audio_player')
}
get uiPlayer() {
return u('.bigPlayer')
}
@ -86,17 +96,9 @@ window.player = new class {
return this.__findByIndex(current + 1)
}
get linkedInlinePlayer() {
if(!this.__linked_player_id) {
return null;
}
return u('#' + this.__linked_player_id)
}
async init(input_context) {
let context = Object.assign({
url: location.pathname
url: location.pathname + location.search
}, input_context)
this.context.object = !input_context ? null : context
this.__realAudioPlayer = document.createElement("audio")
@ -109,8 +111,13 @@ window.player = new class {
initEvents() {
this.audioPlayer.ontimeupdate = () => {
const time = this.audioPlayer.currentTime;
const ps = ((time * 100) / this.currentTrack.length).toFixed(3)
const current_track = this.currentTrack
if(!current_track) {
return
}
const time = this.audioPlayer.currentTime
const ps = ((time * 100) / current_track.length).toFixed(3)
this.uiPlayer.find(".time").html(fmtTime(time))
this.__updateTime(time)
@ -121,6 +128,11 @@ window.player = new class {
this.linkedInlinePlayer.find(".subTracks .lengthTrackWrapper .slider").attr('style', `left:${ ps}%`)
this.linkedInlinePlayer.find('.mini_timer .nobold').html(fmtTime(time))
}
if(this.ajaxPlayer) {
this.ajaxPlayer.find('#aj_player_track_length .slider').attr('style', `left:${ ps}%`)
this.ajaxPlayer.find('#aj_player_track_name #aj_time').html(fmtTime(time))
}
}
}
@ -134,6 +146,10 @@ window.player = new class {
if(this.linkedInlinePlayer) {
this.linkedInlinePlayer.find(".subTracks .volumeTrackWrapper .slider").attr('style', `left:${ ps}%`)
}
if(this.ajaxPlayer) {
this.ajaxPlayer.find('#aj_player_volume .slider').attr('style', `left:${ ps}%`)
}
}
localStorage.setItem('audio.volume', volume)
@ -162,12 +178,12 @@ window.player = new class {
}
}
this.audioPlayer.onended = (e) => {
this.audioPlayer.onended = async (e) => {
e.preventDefault()
if(!this.nextTrack && window.player.context.playedPages.indexOf(1) == -1) {
this.loadContext(1, false)
this.setTrack(this.__findByIndex(0).id)
await this.setTrack(this.__findByIndex(0).id)
} else {
this.playNextTrack()
}
@ -243,10 +259,28 @@ window.player = new class {
return
}
if(window.__current_page_audio_context && (!this.context.object || this.context.object.url != location.pathname + location.search)) {
console.log('Audio | Resetting context because of ajax :3')
this.__renewContext()
await this.loadContext(window.__current_page_audio_context.page ?? 1)
if(!isNaN(parseInt(location.hash.replace('#', '')))) {
const adp = parseInt(location.hash.replace('#', ''))
await this.loadContext(adp)
} else if((new URL(location.href)).searchParams.p) {
const adp = (new URL(location.href)).searchParams.p
await this.loadContext(adp)
}
this.__updateFace()
}
this.listen_coef = 0.0
const old_id = this.current_track_id
this.current_track_id = id
const c_track = this.currentTrack
if(!c_track) {
this.current_track_id = old_id
makeError('Error playing audio: track not found')
return
}
@ -258,9 +292,7 @@ window.player = new class {
};
u('.nowPlaying').removeClass('nowPlaying')
if(this.isAtAudiosPage()) {
u(`.audioEmbed[data-realid='${id}'] .audioEntry`).addClass('nowPlaying')
}
this.__highlightActiveTrack()
navigator.mediaSession.setPositionState({
duration: this.currentTrack.length
@ -277,6 +309,7 @@ window.player = new class {
await this.loadContext(Math.min(...this.context["playedPages"]) - 1, false)
}
this.is_closed = false
this.__updateFace()
u(this.audioPlayer).trigger('volumechange')
}
@ -324,12 +357,12 @@ window.player = new class {
navigator.mediaSession.playbackState = "paused"
}
playPreviousTrack() {
async playPreviousTrack() {
if(!this.currentTrack || !this.previousTrack) {
return
}
this.setTrack(this.previousTrack.id)
await this.setTrack(this.previousTrack.id)
if(!this.currentTrack.available || this.currentTrack.withdrawn) {
if(!this.previousTrack) {
return
@ -341,12 +374,12 @@ window.player = new class {
this.play()
}
playNextTrack() {
async playNextTrack() {
if(!this.currentTrack || !this.nextTrack) {
return
}
this.setTrack(this.nextTrack.id)
await this.setTrack(this.nextTrack.id)
if(!this.currentTrack.available || this.currentTrack.withdrawn) {
if(!this.nextTrack) {
return
@ -359,15 +392,78 @@ window.player = new class {
}
// fake shuffle
shuffle() {
async shuffle() {
this.tracks.sort(() => Math.random() - 0.59)
this.setTrack(this.tracks.at(0).id)
await this.setTrack(this.tracks.at(0).id)
}
isAtAudiosPage() {
return u('.bigPlayer').length > 0
}
// Добавляем ощущение продуманности.
__highlightActiveTrack() {
u(`.audiosContainer .audioEmbed[data-realid='${this.current_track_id}'] .audioEntry, .audios_padding .audioEmbed[data-realid='${this.current_track_id}'] .audioEntry`).addClass('nowPlaying')
}
__renewContext() {
let context = Object.assign({
url: location.pathname + location.search
}, window.__current_page_audio_context)
this.pause()
this.__resetContext()
this.context.object = context
}
__resetContext() {
this.context = {
object: {},
pagesCount: 0,
count: 0,
playedPages: [],
}
this.tracks = []
//this.__realAudioPlayer = document.createElement("audio")
this.listen_coef = 0
}
async _handlePageTransition() {
console.log('Audio | Switched page :3')
const state = this.isAtAudiosPage()
if(!state) {
// AJAX audio player
if(this.is_closed) {
return
}
this.ajaxPlayer.removeClass('hidden')
if(this.ajaxPlayer.length > 0) {
return
} else {
if(this.audioPlayer.paused) {
return
}
this.ajCreate()
this.__updateFace()
}
} else {
this.ajClose()
this.is_closed = false
if(this.tracks.length < 1) {
if(window.__current_page_audio_context) {
await this.init(window.__current_page_audio_context)
}
}
}
this.__linked_player_id = null
if(this.currentTrack) {
this.__updateFace()
}
this.__highlightActiveTrack()
u(this.audioPlayer).trigger('volumechange')
}
__setFavicon(state = 'playing') {
if(state == 'playing') {
document.querySelector('link[rel="icon"], link[rel="shortcut icon"]').setAttribute("href", "/assets/packages/static/openvk/img/favicons/favicon24_paused.png")
@ -418,16 +514,28 @@ window.player = new class {
if(!this.previousTrack) {
prev_button.addClass('lagged')
if(this.ajaxPlayer.length > 0) {
this.ajaxPlayer.find('#aj_player_previous').addClass('lagged')
}
} else {
prev_button.removeClass('lagged')
prev_button.attr('data-title', ovk_proc_strtr(escapeHtml(this.previousTrack.name), 50))
if(this.ajaxPlayer.length > 0) {
this.ajaxPlayer.find('#aj_player_previous').removeClass('lagged')
}
}
if(!this.nextTrack) {
next_button.addClass('lagged')
if(this.ajaxPlayer.length > 0) {
this.ajaxPlayer.find('#aj_player_next').addClass('lagged')
}
} else {
next_button.removeClass('lagged')
next_button.attr('data-title', ovk_proc_strtr(escapeHtml(this.nextTrack.name), 50))
if(this.ajaxPlayer.length > 0) {
this.ajaxPlayer.find('#aj_player_next').removeClass('lagged')
}
}
if(!this.audioPlayer.paused) {
@ -435,11 +543,17 @@ window.player = new class {
if(this.linkedInlinePlayer) {
this.linkedInlinePlayer.find('.playerButton .playIcon').addClass('paused')
}
if(this.ajaxPlayer.length > 0) {
this.ajaxPlayer.find('#aj_player_play_btn').addClass('paused')
}
} else {
this.uiPlayer.find('.playButton').removeClass('pause')
if(this.linkedInlinePlayer) {
this.linkedInlinePlayer.find('.playerButton .playIcon').removeClass('paused')
}
if(this.ajaxPlayer.length > 0) {
this.ajaxPlayer.find('#aj_player_play_btn').removeClass('paused')
}
}
this.uiPlayer.find('.trackInfo .trackName span').html(escapeHtml(_c.name))
@ -450,6 +564,12 @@ window.player = new class {
this.uiPlayer.find('.trackInfo .trackPerformers').append(
`<a href='/search?section=audios&order=listens&only_performers=on&q=${encodeURIComponent(performer.escapeHtml())}'>${performer.escapeHtml()}${(performer != lastPerformer ? ', ' : '')}</a>`)
})
if(this.ajaxPlayer.length > 0) {
this.ajaxPlayer.find('#aj_player_track_title b').html(escapeHtml(_c.performer))
this.ajaxPlayer.find('#aj_player_track_title span').html(escapeHtml(_c.name))
}
u(`.tip_result`).remove()
}
@ -501,13 +621,95 @@ window.player = new class {
console.log('Listen is not counted ! ! !')
}
}
ajClose() {
this.is_closed = true
this.pause()
u('#ajax_audio_player').addClass('hidden')
}
ajReveal() {
this.is_closed = false
u('#ajax_audio_player').removeClass('hidden')
}
ajCreate() {
const previous_time_x = localStorage.getItem('audio.lastX') ?? 100
const previous_time_y = localStorage.getItem('audio.lastY') ?? scrollY
const miniplayer_template = u(`
<div id='ajax_audio_player'>
<div id='aj_player'>
<div id='aj_player_internal_controls'>
<div id='aj_player_play'>
<div id='aj_player_play_btn'></div>
</div>
<div id='aj_player_track'>
<div id='aj_player_track_name'>
<a id='aj_player_track_title' class='noOverflow' style='width: 300px;'>
<b>Unknown</b>
<span>Untitled</span>
</a>
<span id='aj_time'>00:00</span>
</div>
<div id='aj_player_track_length'>
<div class="selectableTrack">
<div style='width: 97%;position: relative;'>
<div class="slider"></div>
</div>
</div>
</div>
</div>
<div id='aj_player_volume'>
<div class="selectableTrack">
<div style='width: 75%;position: relative;'>
<div class="slider"></div>
</div>
</div>
</div>
<div id='aj_player_buttons'>
<div id='aj_player_previous'></div>
<div id='aj_player_repeat'></div>
<div id='aj_player_next'></div>
</div>
</div>
<div id='aj_player_close_btn'></div>
</div>
</div>
`)
u('body').append(miniplayer_template)
miniplayer_template.attr('style', `left:${previous_time_x}px;top:${previous_time_y}px`)
miniplayer_template.find('#aj_player_close_btn').on('click', (e) => {
this.ajClose()
})
miniplayer_template.find('#aj_player_track_title').on('click', (e) => {
if(window.player && window.player.context && window.player.context.object) {
window.router.route(window.player.context.object.url)
}
})
$('#ajax_audio_player').draggable({
cursor: 'grabbing',
containment: 'window',
cancel: '#aj_player_track .selectableTrack, #aj_player_volume .selectableTrack',
stop: function(e) {
if(window.player.ajaxPlayer.length > 0) {
const left = parseInt(window.player.ajaxPlayer.nodes[0].style.left)
const top = parseInt(window.player.ajaxPlayer.nodes[0].style.top)
localStorage.setItem('audio.lastX', left)
localStorage.setItem('audio.lastY', top)
}
}
})
}
}
document.addEventListener("DOMContentLoaded", async () => {
await window.player.init(window.__current_page_audio_context)
})
u(document).on('click', '.audioEntry .playerButton > .playIcon', (e) => {
u(document).on('click', '.audioEntry .playerButton > .playIcon', async (e) => {
const audioPlayer = u(e.target).closest('.audioEmbed')
const id = Number(audioPlayer.attr('data-realid'))
if(!window.player) {
@ -540,7 +742,7 @@ u(document).on('click', '.audioEntry .playerButton > .playIcon', (e) => {
}
if(window.player.current_track_id != id) {
window.player.setTrack(id)
await window.player.setTrack(id)
}
if(window.player.audioPlayer.paused) {
@ -563,7 +765,7 @@ u(document).on('click', '.audioEntry .playerButton > .playIcon', (e) => {
}
})
u(document).on('click', '.bigPlayer .playButton', (e) => {
u(document).on('click', '.bigPlayer .playButton, #ajax_audio_player #aj_player_play_btn', (e) => {
if(window.player.audioPlayer.paused) {
window.player.play()
} else {
@ -571,12 +773,12 @@ u(document).on('click', '.bigPlayer .playButton', (e) => {
}
})
u(document).on('click', '.bigPlayer .backButton', (e) => {
window.player.playNextTrack()
u(document).on('click', '.bigPlayer .backButton, #ajax_audio_player #aj_player_next', async (e) => {
await window.player.playNextTrack()
})
u(document).on('click', '.bigPlayer .nextButton', (e) => {
window.player.playPreviousTrack()
u(document).on('click', '.bigPlayer .nextButton, #ajax_audio_player #aj_player_previous', async (e) => {
await window.player.playPreviousTrack()
})
u(document).on("click", ".bigPlayer .elapsedTime", (e) => {
@ -588,7 +790,7 @@ u(document).on("click", ".bigPlayer .elapsedTime", (e) => {
window.player.__updateTime(window.player.audioPlayer.currentTime)
})
u(document).on("click", ".bigPlayer .additionalButtons .repeatButton", (e) => {
u(document).on("click", ".bigPlayer .additionalButtons .repeatButton, #ajax_audio_player #aj_player_repeat", (e) => {
if(window.player.current_track_id == 0)
return
@ -601,11 +803,11 @@ u(document).on("click", ".bigPlayer .additionalButtons .repeatButton", (e) => {
window.player.audioPlayer.loop = false
})
u(document).on("click", ".bigPlayer .additionalButtons .shuffleButton", (e) => {
u(document).on("click", ".bigPlayer .additionalButtons .shuffleButton", async (e) => {
if(window.player.current_track_id == 0)
return
window.player.shuffle()
await window.player.shuffle()
})
u(document).on("click", ".bigPlayer .additionalButtons .deviceButton", (e) => {
@ -621,7 +823,7 @@ u(document).on('keydown', (e) => {
return
}
if(!window.player) {
if(!window.player || !window.player.isAtAudiosPage()) {
return
}
@ -693,7 +895,7 @@ u(document).on('keyup', (e) => {
}
})
u(document).on("mousemove click mouseup", ".bigPlayer .trackPanel .selectableTrack, .audioEntry .subTracks .lengthTrackWrapper .selectableTrack", (e) => {
u(document).on("mousemove click mouseup", ".bigPlayer .trackPanel .selectableTrack, .audioEntry .subTracks .lengthTrackWrapper .selectableTrack, #aj_player_track_length .selectableTrack", (e) => {
if(window.player.isAtAudiosPage() && window.player.current_track_id == 0)
return
@ -724,17 +926,17 @@ u(document).on("mousemove click mouseup", ".bigPlayer .trackPanel .selectableTra
parent.find('.tip_result').html(fmtTime(time)).attr('style', `left:min(${width - 15}px, 315.5px)`)
})
u(document).on("mouseout", ".bigPlayer .trackPanel .selectableTrack, .audioEntry .subTracks .lengthTrackWrapper .selectableTrack", (e) => {
u(document).on("mouseout", ".bigPlayer .trackPanel .selectableTrack, .audioEntry .subTracks .lengthTrackWrapper .selectableTrack, #aj_player_track_length .selectableTrack", (e) => {
if(window.player.isAtAudiosPage() && window.player.current_track_id == 0)
return
u(e.target).closest('.selectableTrack').parent().find('.tip_result').remove()
})
u(document).on("mousemove click mouseup", ".bigPlayer .volumePanelTrack .selectableTrack, .audioEntry .subTracks .volumeTrack .selectableTrack", (e) => {
u(document).on("mousemove click mouseup", ".bigPlayer .volumePanelTrack .selectableTrack, .audioEntry .subTracks .volumeTrack .selectableTrack, #aj_player_volume .selectableTrack", (e) => {
if(window.player.isAtAudiosPage() && window.player.current_track_id == 0)
return
function __defaultAction(i_volume) {
window.player.audioPlayer.volume = i_volume
}
@ -761,7 +963,7 @@ u(document).on("mousemove click mouseup", ".bigPlayer .volumePanelTrack .selecta
parent.find('.tip_result').html((volume * 100).toFixed(0) + '%').attr('style', `left:${width - 15}px`)
})
u(document).on("mouseout", ".bigPlayer .volumePanelTrack .selectableTrack, .audioEntry .subTracks .volumeTrack .selectableTrack", (e) => {
u(document).on("mouseout", ".bigPlayer .volumePanelTrack .selectableTrack, .audioEntry .subTracks .volumeTrack .selectableTrack, #aj_player_volume .selectableTrack", (e) => {
if(window.player.isAtAudiosPage() && window.player.current_track_id == 0)
return
@ -924,8 +1126,6 @@ u(document).on("click", ".musicIcon.edit-icon", (e) => {
if(url.searchParams.p != null)
page = String(url.searchParams.p)
window.savedAudiosPages[page] = null
} else
fastError(response.flash.message)
}
@ -1483,47 +1683,6 @@ $(document).on("click", ".musicIcon.report-icon", (e) => {
Function.noop])
})
u(document).on("click", ".audiosContainer .paginator a", (e) => {
e.preventDefault()
let url = new URL(e.currentTarget.href)
let page = url.searchParams.get("p")
function searchNode(id) {
let node = document.querySelector(`.audioEmbed[data-realid='${id}'] .audioEntry`)
if(node != null) {
node.classList.add("nowPlaying")
}
}
if(window.savedAudiosPages[page] != null) {
history.pushState({}, "", e.currentTarget.href)
document.querySelector(".audiosContainer").innerHTML = window.savedAudiosPages[page].innerHTML
searchNode(window.player.currentTrack != null ? window.player.currentTrack.id : 0)
return
}
e.currentTarget.parentNode.classList.add("lagged")
$.ajax({
type: "GET",
url: e.currentTarget.href,
success: (response) => {
let domparser = new DOMParser()
let result = domparser.parseFromString(response, "text/html")
document.querySelector(".audiosContainer").innerHTML = result.querySelector(".audiosContainer").innerHTML
history.pushState({}, "", e.currentTarget.href)
window.savedAudiosPages[page] = result.querySelector(".audiosContainer")
searchNode(window.player.currentTrack != null ? window.player.currentTrack.id : 0)
if(!window.player.context["playedPages"].includes(page)) {
window.player.loadContext(page)
}
}
})
})
$(document).on("click", ".addToPlaylist", (e) => {
let audios = document.querySelector("input[name='audios']")
let id = e.currentTarget.dataset.id

View file

@ -161,6 +161,7 @@ function loadMoreSuggestedPosts() {
// нажатие на "x предложенных записей"
$(document).on("click", ".sugglist a", (e) => {
e.preventDefault()
e.stopPropagation()
if(e.currentTarget.getAttribute("data-toogled") == null || e.currentTarget.getAttribute("data-toogled") == "false") {
e.currentTarget.setAttribute("data-toogled", "true")

View file

@ -91,6 +91,7 @@ async function OpenMiniature(e, photo, post, photo_id, type = "post") {
костыли но смешные однако
*/
e.preventDefault();
e.stopPropagation()
// Значения для переключения фоток
@ -449,6 +450,7 @@ async function OpenVideo(video_arr = [], init_player = true)
u(document).on('click', '#videoOpen', (e) => {
e.preventDefault()
e.stopPropagation()
try {
const target = e.target.closest('#videoOpen')
@ -471,6 +473,7 @@ u(document).on('keydown', '.edit_menu #write', (e) => {
e.target.closest('.edit_menu').querySelector('#__edit_save').click()
})
// Migrated from inline start
function reportPhoto(photo_id) {
uReportMsgTxt = tr("going_to_report_photo");
uReportMsgTxt += "<br/>"+tr("report_question_text");
@ -515,6 +518,154 @@ function reportVideo(video_id) {
]);
}
function reportUser(user_id) {
uReportMsgTxt = tr("going_to_report_user");
uReportMsgTxt += "<br/>"+tr("report_question_text");
uReportMsgTxt += "<br/><br/><b>"+tr("report_reason")+"</b>: <input type='text' id='uReportMsgInput' placeholder='" + tr("reason") + "' />"
MessageBox(tr("report_question"), uReportMsgTxt, [tr("confirm_m"), tr("cancel")], [
(function() {
res = document.querySelector("#uReportMsgInput").value;
xhr = new XMLHttpRequest();
xhr.open("GET", "/report/" + user_id + "?reason=" + res + "&type=user", true);
xhr.onload = (function() {
if(xhr.responseText.indexOf("reason") === -1)
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]);
else
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]);
});
xhr.send(null);
}),
Function.noop
]);
}
$(document).on("click", "#_photoDelete, #_videoDelete", function(e) {
var formHtml = "<form id='tmpPhDelF' action='" + u(this).attr("href") + "' >";
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
formHtml += "</form>";
u("body").append(formHtml);
MessageBox(tr('warning'), tr('question_confirm'), [
tr('yes'),
tr('no')
], [
(function() {
u("#tmpPhDelF").nodes[0].submit();
}),
(function() {
u("#tmpPhDelF").remove();
}),
]);
e.stopPropagation()
return e.preventDefault();
});
/* @rem-pai why this func wasn't named as "#_deleteDialog"? It looks universal IMO */
u(document).on("click", "#_noteDelete", function(e) {
var formHtml = "<form id='tmpPhDelF' action='" + u(this).attr("href") + "' >";
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
formHtml += "</form>";
u("body").append(formHtml);
MessageBox(tr('warning'), tr('question_confirm'), [
tr('yes'),
tr('no')
], [
(function() {
u("#tmpPhDelF").nodes[0].submit();
}),
(function() {
u("#tmpPhDelF").remove();
}),
]);
e.stopPropagation()
return e.preventDefault();
});
// TODO REWRITE cuz its a little broken
u(document).on("click", "#_pinGroup", async function(e) {
e.preventDefault();
e.stopPropagation()
let link = u(this).attr("href");
let thisButton = u(this);
let groupName = u(this).attr("data-group-name");
let groupUrl = u(this).attr("data-group-url");
let list = u('#_groupListPinnedGroups');
thisButton.nodes[0].classList.add('loading');
thisButton.nodes[0].classList.add('disable');
let req = await ky(link);
if(req.ok == false) {
NewNotification(tr('error'), tr('error_1'), null);
thisButton.nodes[0].classList.remove('loading');
thisButton.nodes[0].classList.remove('disable');
return;
}
if(!parseAjaxResponse(await req.text())) {
thisButton.nodes[0].classList.remove('loading');
thisButton.nodes[0].classList.remove('disable');
return;
}
// Adding a divider if not already there
if(list.nodes[0].children.length == 0) {
list.nodes[0].append(u('<div class="menu_divider"></div>').first());
}
// Changing the button name
if(thisButton.html().trim() == tr('remove_from_left_menu')) {
thisButton.html(tr('add_to_left_menu'));
for(let i = 0; i < list.nodes[0].children.length; i++) {
let element = list.nodes[0].children[i];
if(element.pathname == groupUrl) {
element.remove();
}
}
}else{
thisButton.html(tr('remove_from_left_menu'));
list.nodes[0].append(u('<a href="' + groupUrl + '" class="link group_link">' + groupName + '</a>').first());
}
// Adding the group to the left group list
if(list.nodes[0].children[0].className != "menu_divider" || list.nodes[0].children.length == 1) {
list.nodes[0].children[0].remove();
}
thisButton.nodes[0].classList.remove('loading');
thisButton.nodes[0].classList.remove('disable');
return false;
});
u(document).handle("submit", "#_submitUserSubscriptionAction", async function(e) {
e.preventDefault()
e.stopPropagation()
u(this).nodes[0].parentElement.classList.add('loading');
u(this).nodes[0].parentElement.classList.add('disable');
console.log(e.target);
const data = await fetch(u(this).attr('action'), { method: 'POST', body: new FormData(e.target) });
if (data.ok) {
u(this).nodes[0].parentElement.classList.remove('loading');
u(this).nodes[0].parentElement.classList.remove('disable');
if (e.target[0].value == "add") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_add_msg");
} else if (e.target[0].value == "rej") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_rej_msg");
} else if (e.target[0].value == "rem") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_rem_msg");
}
}
})
// Migrated from inline end
var tooltipClientTemplate = Handlebars.compile(`
<table>
<tr>
@ -2083,7 +2234,9 @@ async function __processPaginatorNextPage(page)
window.player.loadContext(page)
}
location.hash = 'pages/'+page
const new_url = new URL(location.href)
new_url.hash = page
history.replaceState(null, null, new_url)
if(typeof __scrollHook != 'undefined') {
__scrollHook(page)
@ -2247,3 +2400,52 @@ u(document).on('mouseover mousemove mouseout', `div[data-tip='simple']`, (e) =>
</div>
`)
})
function setStatusEditorShown(shown) {
document.getElementById("status_editor").style.display = shown ? "block" : "none";
}
document.addEventListener("click", event => {
if(u('#status_editor').length < 1) {
return
}
if(!event.target.closest("#status_editor") && !event.target.closest("#page_status_text"))
setStatusEditorShown(false);
});
u(document).on('click', '#page_status_text', (e) => {
setStatusEditorShown(true)
})
async function changeStatus() {
const status = document.status_popup_form.status.value;
const broadcast = document.status_popup_form.broadcast.checked;
document.status_popup_form.submit.innerHTML = "<div class=\"button-loading\"></div>";
document.status_popup_form.submit.disabled = true;
const formData = new FormData();
formData.append("status", status);
formData.append("broadcast", Number(broadcast));
formData.append("hash", document.status_popup_form.hash.value);
const response = await ky.post("/edit?act=status", {body: formData});
if(!parseAjaxResponse(await response.text())) {
document.status_popup_form.submit.innerHTML = tr("send");
document.status_popup_form.submit.disabled = false;
return;
}
if(document.status_popup_form.status.value === "") {
document.querySelector("#page_status_text").innerHTML = `[ ${tr("change_status")} ]`;
document.querySelector("#page_status_text").className = "edit_link page_status_edit_button";
} else {
document.querySelector("#page_status_text").innerHTML = status;
document.querySelector("#page_status_text").className = "page_status page_status_edit_button";
}
setStatusEditorShown(false);
document.status_popup_form.submit.innerHTML = tr("send");
document.status_popup_form.submit.disabled = false;
}

View file

@ -39,126 +39,6 @@ function parseAjaxResponse(responseString) {
}
}
document.addEventListener("DOMContentLoaded", function() { //BEGIN
$(document).on("click", "#_photoDelete, #_videoDelete", function(e) {
var formHtml = "<form id='tmpPhDelF' action='" + u(this).attr("href") + "' >";
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
formHtml += "</form>";
u("body").append(formHtml);
MessageBox(tr('warning'), tr('question_confirm'), [
tr('yes'),
tr('no')
], [
(function() {
u("#tmpPhDelF").nodes[0].submit();
}),
(function() {
u("#tmpPhDelF").remove();
}),
]);
return e.preventDefault();
});
/* @rem-pai why this func wasn't named as "#_deleteDialog"? It looks universal IMO */
u(document).on("click", "#_noteDelete", function(e) {
var formHtml = "<form id='tmpPhDelF' action='" + u(this).attr("href") + "' >";
formHtml += "<input type='hidden' name='hash' value='" + u("meta[name=csrf]").attr("value") + "' />";
formHtml += "</form>";
u("body").append(formHtml);
MessageBox(tr('warning'), tr('question_confirm'), [
tr('yes'),
tr('no')
], [
(function() {
u("#tmpPhDelF").nodes[0].submit();
}),
(function() {
u("#tmpPhDelF").remove();
}),
]);
return e.preventDefault();
});
u("#_pinGroup").on("click", async function(e) {
e.preventDefault();
let link = u(this).attr("href");
let thisButton = u(this);
let groupName = u(this).attr("data-group-name");
let groupUrl = u(this).attr("data-group-url");
let list = u('#_groupListPinnedGroups');
thisButton.nodes[0].classList.add('loading');
thisButton.nodes[0].classList.add('disable');
let req = await ky(link);
if(req.ok == false) {
NewNotification(tr('error'), tr('error_1'), null);
thisButton.nodes[0].classList.remove('loading');
thisButton.nodes[0].classList.remove('disable');
return;
}
if(!parseAjaxResponse(await req.text())) {
thisButton.nodes[0].classList.remove('loading');
thisButton.nodes[0].classList.remove('disable');
return;
}
// Adding a divider if not already there
if(list.nodes[0].children.length == 0) {
list.nodes[0].append(u('<div class="menu_divider"></div>').first());
}
// Changing the button name
if(thisButton.html().trim() == tr('remove_from_left_menu')) {
thisButton.html(tr('add_to_left_menu'));
for(let i = 0; i < list.nodes[0].children.length; i++) {
let element = list.nodes[0].children[i];
if(element.pathname == groupUrl) {
element.remove();
}
}
}else{
thisButton.html(tr('remove_from_left_menu'));
list.nodes[0].append(u('<a href="' + groupUrl + '" class="link group_link">' + groupName + '</a>').first());
}
// Adding the group to the left group list
if(list.nodes[0].children[0].className != "menu_divider" || list.nodes[0].children.length == 1) {
list.nodes[0].children[0].remove();
}
thisButton.nodes[0].classList.remove('loading');
thisButton.nodes[0].classList.remove('disable');
return false;
});
u(document).handle("submit", "#_submitUserSubscriptionAction", async function(e) {
u(this).nodes[0].parentElement.classList.add('loading');
u(this).nodes[0].parentElement.classList.add('disable');
console.log(e.target);
const data = await fetch(u(this).attr('action'), { method: 'POST', body: new FormData(e.target) });
if (data.ok) {
u(this).nodes[0].parentElement.classList.remove('loading');
u(this).nodes[0].parentElement.classList.remove('disable');
if (e.target[0].value == "add") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_add_msg");
} else if (e.target[0].value == "rej") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_rej_msg");
} else if (e.target[0].value == "rem") {
u(this).nodes[0].parentElement.innerHTML = tr("friends_rem_msg");
}
}
})
}); //END ONREADY DECLS
function setClubAdminComment(clubId, adminId, hash) {
MessageBox("Изменить комментарий к администратору", `
<form action="/club${clubId}/setAdmin" method="post" id="uClubAdminCommentForm_${clubId}_${adminId}">

View file

@ -1,8 +1,4 @@
window.router = new class {
skeletons = {
}
get csrf() {
return u("meta[name=csrf]").attr("value")
}
@ -20,12 +16,30 @@ window.router = new class {
__appendScript(script) {
const _t_scr = document.createElement('script')
_t_scr.crossorigin = 'anonymous'
if(script.getAttribute('integrity')) {
_t_scr.setAttribute('integrity', script.getAttribute('integrity'))
}
if(script.getAttribute('id')) {
_t_scr.id = script.id
}
if(script.getAttribute('type')) {
_t_scr.type = script.type
}
//const parent = script.parentNode
//const idx = Array.from(parent.children).indexOf(script)
if(script.src) {
_t_scr.src = script.src
} else {
_t_scr.async = false
_t_scr.textContent = script.textContent
}
//parent.children[idx].before(script)
document.body.appendChild(_t_scr)
}
@ -33,25 +47,26 @@ window.router = new class {
u(`script:not([src])`).remove()
}
__closeMsgs() {
window.messagebox_stack.forEach(msg => msg.close())
}
__appendPage(parsed_content) {
if(u('.paginator:not(.paginator-at-top)').length > 0) {
showMoreObserver.unobserve(u('.paginator:not(.paginator-at-top)').nodes[0])
}
const scripts_to_append = []
const page_body = u(parsed_content.querySelector('.page_body'))
const sidebar = u(parsed_content.querySelector('.sidebar'))
const page_header = u(parsed_content.querySelector('.page_header'))
if(page_body.length < 1) {
makeError('Err')
throw new Error('Invalid page has been loaded')
return
}
window.__current_page_audio_context = null
this.__clearScripts()
parsed_content.querySelectorAll('script').forEach(script => {
console.log(script)
parsed_content.querySelectorAll('.page_body script, #_js_ep_script').forEach(script => {
if(!this.__isScriptAlreadyLoaded(script)) {
this.__appendScript(script)
scripts_to_append.push(script)
script.parentNode.removeChild(script)
}
})
u('.page_body').html(page_body.html())
@ -71,15 +86,43 @@ window.router = new class {
u("meta[name=csrf]").attr("value", u(parsed_content.querySelector('meta[name=csrf]')).attr('value'))
document.title = parsed_content.title
scripts_to_append.forEach(append_me => {
this.__appendScript(append_me)
})
}
async __integratePage() {
window.scrollTo(0, 0)
bsdnHydrate()
if(u('.paginator:not(.paginator-at-top)').length > 0) {
showMoreObserver.observe(u('.paginator:not(.paginator-at-top)').nodes[0])
}
if(u(`div[class$="_small_block"]`).length > 0 && typeof smallBlockObserver != 'undefined') {
smallBlockObserver.observe(u(`div[class$="_small_block"]`).nodes[0])
}
if(window.player) {
await window.player._handlePageTransition()
}
}
__unlinkObservers() {
if(u('.paginator:not(.paginator-at-top)').length > 0) {
showMoreObserver.unobserve(u('.paginator:not(.paginator-at-top)').nodes[0])
}
if(u(`div[class$="_small_block"]`).length > 0 && typeof smallBlockObserver != 'undefined') {
smallBlockObserver.unobserve(u(`div[class$="_small_block"]`).nodes[0])
}
}
checkUrl(url) {
if(window.openvk.disable_ajax == 1) {
return false
}
if((localStorage.getItem('ux.disable_ajax_routing') ?? 0) == 1 || window.openvk.current_id == 0) {
return false
}
@ -92,6 +135,10 @@ window.router = new class {
return false
}
if(url.indexOf('hash=') != -1) {
return false
}
return true
}
@ -115,8 +162,6 @@ window.router = new class {
const push_url = params.push_state ?? true
const next_page_url = new URL(url)
next_page_url.searchParams.append('al', 1)
next_page_url.searchParams.append('hash', this.csrf)
if(push_url) {
history.pushState({'from_router': 1}, '', url)
} else {
@ -125,7 +170,10 @@ window.router = new class {
const parser = new DOMParser
const next_page_request = await fetch(next_page_url, {
method: 'GET'
method: 'GET',
headers: {
'X-OpenVK-Ajax-Query': '1',
}
})
const next_page_text = await next_page_request.text()
const parsed_content = parser.parseFromString(next_page_text, 'text/html')
@ -133,7 +181,17 @@ window.router = new class {
history.replaceState({'from_router': 1}, '', next_page_request.url)
}
this.__appendPage(parsed_content)
this.__closeMsgs()
this.__unlinkObservers()
try {
this.__appendPage(parsed_content)
await this.__integratePage()
} catch(e) {
console.error(e)
next_page_url.searchParams.delete('al', 1)
location.assign(next_page_url)
}
}
}
@ -144,19 +202,29 @@ u(document).on('click', 'a', async (e) => {
let url = target.nodes[0].href
if(id) {
if(['act_tab_a', 'ki'].indexOf(id) == -1) {
if(['act_tab_a', 'ki', 'used', '_pinGroup', 'profile_link'].indexOf(id) == -1) {
console.log('AJAX | Skipping cuz maybe its function call link.')
return
}
}
/*if(url.indexOf('hash=') != -1) {
e.preventDefault()
return false
}*/
if(target.rel == 'nofollow') {
console.log('AJAX | Skipped because its nofollow')
return
}
if(!dom_url || dom_url == '#' || dom_url.indexOf('javascript:') != -1) {
console.log('AJAX | Skipped cuz its anchor or function call')
console.log('AJAX | Skipped because its anchor or function call')
return
}
if(target.attr('target') == '_blank') {
console.log('AJAX | Skipping cuz its _blank.')
console.log('AJAX | Skipping because its _blank.')
return
}
@ -188,9 +256,12 @@ u(document).on('submit', 'form', async (e) => {
const form = e.target
const method = form.method ?? 'get'
const url = form.action
if(form.onsubmit) {
u('#ajloader').removeClass('shown')
return false
}
const url_object = new URL(url)
url_object.searchParams.append('al', 1)
if(method == 'get' || method == 'GET') {
url_object.searchParams.append('hash', window.router.csrf)
$(form).serializeArray().forEach(param => {
@ -199,12 +270,16 @@ u(document).on('submit', 'form', async (e) => {
}
if(!url) {
u('#ajloader').removeClass('shown')
return
}
const form_data = serializeForm(form)
const request_object = {
method: method
method: method,
headers: {
'X-OpenVK-Ajax-Query': '1',
}
}
if(method != 'GET' && method != 'get') {
@ -215,6 +290,7 @@ u(document).on('submit', 'form', async (e) => {
const form_result = await form_res.text()
switch(form_res.status) {
case 500:
case 502:
makeError(form_res.statusText)
break
}
@ -234,6 +310,15 @@ u(document).on('submit', 'form', async (e) => {
console.log(form_res)
window.router.__appendPage(parsed_content)
await window.router.__integratePage()
u('#ajloader').removeClass('shown')
})
window.addEventListener('popstate', (e) => {
e.preventDefault();
window.router.route({
url: location.href,
push_state: false,
})
})

View file

@ -186,7 +186,7 @@ function serializeForm(form)
{
const u_ = u(form)
const inputs = u_.find('input, textarea')
console.log(inputs)
let fd = new FormData()
inputs.nodes.forEach(inp => {
if(!inp || !inp.name) {
@ -203,7 +203,14 @@ function serializeForm(form)
case 'hidden':
case 'text':
case 'textarea':
case 'select':
fd.append(inp.name, inp.value)
break
case 'checkbox':
if(inp.checked) {
fd.append(inp.name, inp.value)
}
break
case 'file':
for(const __file of inp.files) {