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
if(timer < 0) return "-00:00"
return "-" + fmtTime(timer)
}
window.savedAudiosPages = {}
class playersSearcher {
constructor(context_type, context_id) {
this.context_type = context_type
this.context_id = context_id
this.searchType = "by_name"
this.query = ""
this.page = 1
this.successCallback = () => {}
this.errorCallback = () => {}
this.beforesendCallback = () => {}
this.clearContainer = () => {}
}
execute() {
$.ajax({
type: "POST",
url: "/audios/context",
data: {
context: this.context_type,
hash: u("meta[name=csrf]").attr("value"),
page: this.page,
query: this.query,
context_entity: this.context_id,
type: this.searchType,
returnPlayers: 1,
},
beforeSend: () => {
this.beforesendCallback()
},
error: () => {
this.errorCallback()
},
success: (response) => {
this.successCallback(response, this)
}
})
}
movePage(page) {
this.page = page
this.execute()
}
}
class bigPlayer {
tracks = {
currentTrack: null,
nextTrack: null,
previousTrack: null,
tracks: []
}
context = {
context_type: null,
context_id: 0,
pagesCount: 0,
playedPages: [],
object: [],
}
nodes = {
dashPlayer: null,
audioPlayer: null,
thisPlayer: null,
playButtons: null,
}
timeType = 0
findTrack(id) {
return this.tracks["tracks"].find(item => item.id == id)
}
constructor(context, context_id, page = 1) {
this.context["context_type"] = context
this.context["context_id"] = context_id
this.context["playedPages"].push(String(page))
this.nodes["thisPlayer"] = document.querySelector(".bigPlayer")
this.nodes["thisPlayer"].classList.add("lagged")
this.nodes["audioPlayer"] = document.createElement("audio")
this.player = () => { return this.nodes["audioPlayer"] }
this.nodes["playButtons"] = this.nodes["thisPlayer"].querySelector(".playButtons")
this.nodes["dashPlayer"] = dashjs.MediaPlayer().create()
let formdata = new FormData()
formdata.append("context", context)
formdata.append("context_entity", context_id)
formdata.append("query", context_id)
formdata.append("hash", u("meta[name=csrf]").attr("value"))
formdata.append("page", page)
ky.post("/audios/context", {
hooks: {
afterResponse: [
async (_request, _options, response) => {
if(response.status !== 200) {
fastError(tr("unable_to_load_queue"))
return
}
let contextObject = await response.json()
if(!contextObject.success) {
fastError(tr("unable_to_load_queue"))
return
}
this.nodes["thisPlayer"].classList.remove("lagged")
this.tracks["tracks"] = contextObject["items"]
this.context["pagesCount"] = contextObject["pagesCount"]
if(localStorage.lastPlayedTrack != null && this.tracks["tracks"].find(item => item.id == localStorage.lastPlayedTrack) != null) {
this.setTrack(localStorage.lastPlayedTrack)
this.pause()
}
console.info("Context is successfully loaded")
}
]
},
body: formdata,
timeout: 20000,
})
u(this.nodes["playButtons"].querySelector(".playButton")).on("click", (e) => {
if(this.player().paused)
this.play()
else
this.pause()
})
u(this.player()).on("timeupdate", (e) => {
const time = this.player().currentTime;
const ps = ((time * 100) / this.tracks["currentTrack"].length).toFixed(3)
this.nodes["thisPlayer"].querySelector(".time").innerHTML = fmtTime(time)
this.timeType == 0 ? this.nodes["thisPlayer"].querySelector(".elapsedTime").innerHTML = getElapsedTime(this.tracks["currentTrack"].length, time)
: null
if (ps <= 100)
this.nodes["thisPlayer"].querySelector(".selectableTrack .slider").style.left = `${ ps}%`;
})
u(this.player()).on("volumechange", (e) => {
const volume = this.player().volume;
const ps = Math.ceil((volume * 100) / 1);
if (ps <= 100)
this.nodes["thisPlayer"].querySelector(".volumePanel .selectableTrack .slider").style.left = `${ ps}%`;
localStorage.volume = volume
})
u(".bigPlayer .track > div").on("click mouseup", (e) => {
if(this.tracks["currentTrack"] == null)
return
let rect = this.nodes["thisPlayer"].querySelector(".selectableTrack").getBoundingClientRect();
const width = e.clientX - rect.left;
const time = Math.ceil((width * this.tracks["currentTrack"].length) / (rect.right - rect.left));
this.player().currentTime = time;
})
u(".bigPlayer .trackPanel .selectableTrack").on("mousemove", (e) => {
if(this.tracks["currentTrack"] == null)
return
let rect = this.nodes["thisPlayer"].querySelector(".selectableTrack").getBoundingClientRect();
const width = e.clientX - rect.left;
const time = Math.ceil((width * this.tracks["currentTrack"].length) / (rect.right - rect.left));
document.querySelector(".bigPlayer .track .bigPlayerTip").style.display = "block"
document.querySelector(".bigPlayer .track .bigPlayerTip").innerHTML = fmtTime(time)
document.querySelector(".bigPlayer .track .bigPlayerTip").style.left = `min(${width - 15}px, 315.5px)`
})
u(".bigPlayer .nextButton").on("mouseover mouseleave", (e) => {
if(this.tracks["currentTrack"] == null)
return
if(e.type == "mouseleave") {
$(".nextTrackTip").remove()
return
}
e.currentTarget.parentNode.insertAdjacentHTML("afterbegin", `
${ovk_proc_strtr(escapeHtml(this.findTrack(this.tracks["previousTrack"]).name), 20) ?? ""}
`)
document.querySelector(".nextTrackTip").style.display = "block"
})
u(".bigPlayer .backButton").on("mouseover mouseleave", (e) => {
if(this.tracks["currentTrack"] == null)
return
if(e.type == "mouseleave") {
$(".previousTrackTip").remove()
return
}
e.currentTarget.parentNode.insertAdjacentHTML("afterbegin", `
${ovk_proc_strtr(escapeHtml(this.findTrack(this.tracks["nextTrack"]).name), 20) ?? ""}
`)
document.querySelector(".previousTrackTip").style.display = "block"
})
u(".bigPlayer .trackPanel .selectableTrack").on("mouseleave", (e) => {
if(this.tracks["currentTrack"] == null)
return
document.querySelector(".bigPlayer .track .bigPlayerTip").style.display = "none"
})
u(".bigPlayer .volumePanel > div").on("click mouseup mousemove", (e) => {
if(this.tracks["currentTrack"] == null)
return
if(e.type == "mousemove") {
let buttonsPresseed = _bsdnUnwrapBitMask(e.buttons)
if(!buttonsPresseed[0])
return;
}
let rect = this.nodes["thisPlayer"].querySelector(".volumePanel .selectableTrack").getBoundingClientRect();
const width = e.clientX - rect.left;
const volume = Math.max(0, (width * 1) / (rect.right - rect.left));
this.player().volume = volume;
})
u(".bigPlayer .elapsedTime").on("click", (e) => {
if(this.tracks["currentTrack"] == null)
return
this.timeType == 0 ? (this.timeType = 1) : (this.timeType = 0)
localStorage.playerTimeType = this.timeType
this.nodes["thisPlayer"].querySelector(".elapsedTime").innerHTML = this.timeType == 1 ?
fmtTime(this.tracks["currentTrack"].length)
: getElapsedTime(this.tracks["currentTrack"].length, this.player().currentTime)
})
u(".bigPlayer .additionalButtons .repeatButton").on("click", (e) => {
if(this.tracks["currentTrack"] == null)
return
e.currentTarget.classList.toggle("pressed")
if(e.currentTarget.classList.contains("pressed"))
this.player().loop = true
else
this.player().loop = false
})
u(".bigPlayer .additionalButtons .shuffleButton").on("click", (e) => {
if(this.tracks["currentTrack"] == null)
return
this.tracks["tracks"].sort(() => Math.random() - 0.59)
this.setTrack(this.tracks["tracks"].at(0).id)
})
// хз что она делала в самом вк, но тут сделаем вид что это просто мут музыки
u(".bigPlayer .additionalButtons .deviceButton").on("click", (e) => {
if(this.tracks["currentTrack"] == null)
return
e.currentTarget.classList.toggle("pressed")
this.player().muted = e.currentTarget.classList.contains("pressed")
})
u(".bigPlayer .arrowsButtons .nextButton").on("click", (e) => {
this.showPreviousTrack()
})
u(".bigPlayer .arrowsButtons .backButton").on("click", (e) => {
this.showNextTrack()
})
u(".bigPlayer .trackInfo b").on("click", (e) => {
window.location.assign(`/search?q=${e.currentTarget.innerHTML}§ion=audios&only_performers=on`)
})
u(document).on("keydown", (e) => {
if(document.activeElement.closest('.page_header')) {
return
}
if(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", " "].includes(e.key)) {
if(document.querySelector(".ovk-diag-cont") != null)
return
e.preventDefault()
}
switch(e.key) {
case "ArrowUp":
this.player().volume = Math.min(0.99, this.player().volume + 0.1)
break
case "ArrowDown":
this.player().volume = Math.max(0, this.player().volume - 0.1)
break
case "ArrowLeft":
this.player().currentTime = this.player().currentTime - 3
break
case "ArrowRight":
this.player().currentTime = this.player().currentTime + 3
break
// буквально
case " ":
if(this.player().paused)
this.play()
else
this.pause()
break;
}
})
u(document).on("keyup", (e) => {
if(document.activeElement.closest('.page_header')) {
return
}
if([87, 65, 83, 68, 82, 77].includes(e.keyCode)) {
if(document.querySelector(".ovk-diag-cont") != null)
return
e.preventDefault()
}
switch(e.keyCode) {
case 87:
case 65:
this.showPreviousTrack()
break
case 83:
case 68:
this.showNextTrack()
break
case 82:
document.querySelector(".bigPlayer .additionalButtons .repeatButton").click()
break
case 77:
document.querySelector(".bigPlayer .additionalButtons .deviceButton").click()
break
}
})
u(this.player()).on("ended", (e) => {
e.preventDefault()
// в начало очереди
if(!this.tracks.nextTrack) {
if(!this.context["playedPages"].includes("1")) {
$.ajax({
type: "POST",
url: "/audios/context",
data: {
context: this["context"].context_type,
context_entity: this["context"].context_id,
hash: u("meta[name=csrf]").attr("value"),
page: 1
},
success: (response_2) => {
this.tracks["tracks"] = response_2["items"].concat(this.tracks["tracks"])
this.context["playedPages"].push(String(1))
this.setTrack(this.tracks["tracks"][0].id)
}
})
} else {
this.setTrack(this.tracks.tracks[0].id)
}
return
}
this.showNextTrack()
})
u(this.player()).on("loadstart", (e) => {
let playlist = this.context.context_type == "playlist_context" ? this.context.context_id : null
let tempThisId = this.tracks.currentTrack.id
setTimeout(() => {
if(tempThisId != this.tracks.currentTrack.id) return
$.ajax({
type: "POST",
url: `/audio${this.tracks["currentTrack"].id}/listen`,
data: {
hash: u("meta[name=csrf]").attr("value"),
playlist: playlist
},
success: (response) => {
if(response.success) {
console.info("Listen is counted.")
if(response.new_playlists_listens)
document.querySelector("#listensCount").innerHTML = tr("listens_count", response.new_playlists_listens)
} else
console.info("Listen is not counted.")
}
})
}, 2000)
})
if(localStorage.volume != null && localStorage.volume < 1 && localStorage.volume > 0)
this.player().volume = localStorage.volume
else
this.player().volume = 0.75
if(localStorage.playerTimeType == 'null' || localStorage.playerTimeType == null)
this.timeType = 0
else
this.timeType = localStorage.playerTimeType
navigator.mediaSession.setActionHandler('play', () => { this.play() });
navigator.mediaSession.setActionHandler('pause', () => { this.pause() });
navigator.mediaSession.setActionHandler('previoustrack', () => { this.showPreviousTrack() });
navigator.mediaSession.setActionHandler('nexttrack', () => { this.showNextTrack() });
navigator.mediaSession.setActionHandler("seekto", (details) => {
this.player().currentTime = details.seekTime;
});
}
play() {
if(this.tracks["currentTrack"] == null)
return
document.querySelectorAll('audio').forEach(el => el.pause());
document.querySelector(`.audioEmbed[data-realid='${this.tracks["currentTrack"].id}'] .audioEntry .playerButton .playIcon`) != null ? document.querySelector(`.audioEmbed[data-realid='${this.tracks["currentTrack"].id}'] .audioEntry .playerButton .playIcon`).classList.add("paused") : void(0)
this.player().play()
this.nodes["playButtons"].querySelector(".playButton").classList.add("pause")
document.querySelector('link[rel="icon"], link[rel="shortcut icon"]').setAttribute("href", "/assets/packages/static/openvk/img/favicons/favicon24_paused.png")
navigator.mediaSession.playbackState = "playing"
}
pause() {
if(this.tracks["currentTrack"] == null)
return
document.querySelector(`.audioEmbed[data-realid='${this.tracks["currentTrack"].id}'] .audioEntry .playerButton .playIcon`) != null ? document.querySelector(`.audioEmbed[data-realid='${this.tracks["currentTrack"].id}'] .audioEntry .playerButton .playIcon`).classList.remove("paused") : void(0)
this.player().pause()
this.nodes["playButtons"].querySelector(".playButton").classList.remove("pause")
document.querySelector('link[rel="icon"], link[rel="shortcut icon"]').setAttribute("href", "/assets/packages/static/openvk/img/favicons/favicon24_playing.png")
navigator.mediaSession.playbackState = "paused"
}
showPreviousTrack() {
if(this.tracks["currentTrack"] == null || this.tracks["previousTrack"] == null)
return
this.setTrack(this.tracks["previousTrack"])
}
showNextTrack() {
if(this.tracks["currentTrack"] == null || this.tracks["nextTrack"] == null)
return
this.setTrack(this.tracks["nextTrack"])
}
updateButtons() {
// перепутал некст и бек.
let prevButton = this.nodes["thisPlayer"].querySelector(".nextButton")
let nextButton = this.nodes["thisPlayer"].querySelector(".backButton")
if(this.tracks["previousTrack"] == null)
prevButton.classList.add("lagged")
else
prevButton.classList.remove("lagged")
if(this.tracks["nextTrack"] == null)
nextButton.classList.add("lagged")
else
nextButton.classList.remove("lagged")
if(document.querySelector(".nextTrackTip") != null) {
let track = this.findTrack(this.tracks["previousTrack"])
document.querySelector(".nextTrackTip").innerHTML = `
${track != null ? ovk_proc_strtr(escapeHtml(track.name), 20) : ""}
`
}
if(document.querySelector(".previousTrackTip") != null) {
let track = this.findTrack(this.tracks["nextTrack"])
document.querySelector(".previousTrackTip").innerHTML = `
${track != null ? ovk_proc_strtr(escapeHtml(track.name ?? ""), 20) : ""}
`
}
}
setTrack(id) {
if(this.tracks["tracks"] == null) {
console.info("Context is not loaded yet. Wait please")
return 0;
}
document.querySelectorAll(".audioEntry.nowPlaying").forEach(el => el.classList.remove("nowPlaying"))
let obj = this.tracks["tracks"].find(item => item.id == id)
if(obj == null) {
fastError("No audio in context")
return
}
this.nodes["thisPlayer"].querySelector(".trackInfo span").innerHTML = escapeHtml(obj.name)
this.nodes["thisPlayer"].querySelector(".trackInfo b").innerHTML = escapeHtml(obj.performer)
this.nodes["thisPlayer"].querySelector(".trackInfo .time").innerHTML = fmtTime(obj.length)
this.tracks["currentTrack"] = obj
let indexOfCurrentTrack = this.tracks["tracks"].indexOf(obj) ?? 0
this.tracks["nextTrack"] = this.tracks["tracks"].at(indexOfCurrentTrack + 1) != null ? this.tracks["tracks"].at(indexOfCurrentTrack + 1).id : null
if(indexOfCurrentTrack - 1 >= 0)
this.tracks["previousTrack"] = this.tracks["tracks"].at(indexOfCurrentTrack - 1).id
else
this.tracks["previousTrack"] = null
if(this.tracks["nextTrack"] == null && Math.max(...this.context["playedPages"]) < this.context["pagesCount"]
|| this.tracks["previousTrack"] == null && (Math.min(...this.context["playedPages"]) > 1)) {
// idk how it works
let lesser = this.tracks["previousTrack"] == null ? (Math.min(...this.context["playedPages"]) > 1)
: Math.max(...this.context["playedPages"]) > this.context["pagesCount"]
let formdata = new FormData()
formdata.append("context", this.context["context_type"])
formdata.append("context_entity", this.context["context_id"])
formdata.append("hash", u("meta[name=csrf]").attr("value"))
if(lesser)
formdata.append("page", Math.min(...this.context["playedPages"]) - 1)
else
formdata.append("page", Number(Math.max(...this.context["playedPages"])) + 1)
ky.post("/audios/context", {
hooks: {
afterResponse: [
async (_request, _options, response) => {
let newArr = await response.json()
if(lesser)
this.tracks["tracks"] = newArr["items"].concat(this.tracks["tracks"])
else
this.tracks["tracks"] = this.tracks["tracks"].concat(newArr["items"])
this.context["playedPages"].push(String(newArr["page"]))
if(lesser)
this.tracks["previousTrack"] = this.tracks["tracks"].at(this.tracks["tracks"].indexOf(obj) - 1).id
else
this.tracks["nextTrack"] = this.tracks["tracks"].at(indexOfCurrentTrack + 1) != null ? this.tracks["tracks"].at(indexOfCurrentTrack + 1).id : null
this.updateButtons()
console.info("Context is successfully loaded")
}
]
},
body: formdata
})
}
if(this.tracks["currentTrack"].available == false || this.tracks["currentTrack"].withdrawn)
this.showNextTrack()
this.updateButtons()
const protData = {
"org.w3.clearkey": {
"clearkeys": obj.keys
}
};
this.nodes["dashPlayer"].initialize(this.player(), obj.url, false);
this.nodes["dashPlayer"].setProtectionData(protData);
this.play()
let playerAtPage = document.querySelector(`.audioEmbed[data-realid='${this.tracks["currentTrack"].id}'] .audioEntry`)
if(playerAtPage != null)
playerAtPage.classList.add("nowPlaying")
document.querySelectorAll(`.audioEntry .playerButton .playIcon.paused`).forEach(el => el.classList.remove("paused"))
localStorage.lastPlayedTrack = this.tracks["currentTrack"].id
if(this.timeType == 1)
this.nodes["thisPlayer"].querySelector(".elapsedTime").innerHTML = fmtTime(this.tracks["currentTrack"].length)
let album = document.querySelector(".playlistBlock")
navigator.mediaSession.metadata = new MediaMetadata({
title: obj.name,
artist: obj.performer,
album: album == null ? "OpenVK Audios" : album.querySelector(".playlistInfo h4").innerHTML,
artwork: [{ src: album == null ? "/assets/packages/static/openvk/img/song.jpg" : album.querySelector(".playlistCover img").src }],
});
navigator.mediaSession.setPositionState({
duration: this.tracks["currentTrack"].length
})
}
}
document.addEventListener("DOMContentLoaded", function() {
if(document.querySelector(".bigPlayer") != null) {
let context = document.querySelector("input[name='bigplayer_context']")
if(!context)
return
let type = context.dataset.type
let entity = context.dataset.entity
window.player = new bigPlayer(type, entity, context.dataset.page)
}
$(document).on("mouseover mouseleave", `.audioEntry .mediaInfo`, (e) => {
const info = e.currentTarget.closest(".mediaInfo")
if(e.originalEvent.type == "mouseleave" || e.originalEvent.type == "mouseout") {
info.classList.add("noOverflow")
info.classList.remove("overflowedName")
} else {
info.classList.remove("noOverflow")
info.classList.add("overflowedName")
}
})
})
$(document).on("click", ".audioEmbed > *", (e) => {
const player = e.currentTarget.closest(".audioEmbed")
if(player.classList.contains("inited")) return
initPlayer(player.id.replace("audioEmbed-", ""),
JSON.parse(player.dataset.keys),
player.dataset.url,
player.dataset.length)
if(e.target.classList.contains("playIcon"))
e.target.click()
})
function initPlayer(id, keys, url, length) {
document.querySelector(`#audioEmbed-${ id}`).classList.add("inited")
const audio = document.querySelector(`#audioEmbed-${ id} .audio`);
const playButton = u(`#audioEmbed-${ id} .playerButton > .playIcon`);
const trackDiv = u(`#audioEmbed-${ id} .track > div > div`);
const volumeSpan = u(`#audioEmbed-${ id} .volume span`);
const rect = document.querySelector(`#audioEmbed-${ id} .selectableTrack`).getBoundingClientRect();
const playerObject = document.querySelector(`#audioEmbed-${ id}`)
if(document.querySelector(".bigPlayer") != null) {
playButton.on("click", () => {
if(window.player.tracks["tracks"] == null)
return
if(window.player.tracks["currentTrack"] == null || window.player.tracks["currentTrack"].id != playerObject.dataset.realid)
window.player.setTrack(playerObject.dataset.realid)
else
document.querySelector(".bigPlayer .playButton").click()
})
return
}
const protData = {
"org.w3.clearkey": {
"clearkeys": keys
}
};
const player = dashjs.MediaPlayer().create();
player.initialize(audio, url, false);
player.setProtectionData(protData);
playButton.on("click", () => {
if (audio.paused) {
document.querySelectorAll('audio').forEach(el => el.pause());
audio.play();
} else {
audio.pause();
}
});
u(audio).on("timeupdate", () => {
const time = audio.currentTime;
const ps = ((time * 100) / length).toFixed(3);
volumeSpan.html(fmtTime(Math.floor(time)));
if (ps <= 100)
playerObject.querySelector(".lengthTrack .slider").style.left = `${ ps}%`;
});
u(audio).on("volumechange", (e) => {
const volume = audio.volume;
const ps = Math.ceil((volume * 100) / 1);
if (ps <= 100)
playerObject.querySelector(".volumeTrack .slider").style.left = `${ ps}%`;
})
const playButtonImageUpdate = () => {
if (!audio.paused) {
playButton.addClass("paused")
document.querySelector('link[rel="icon"], link[rel="shortcut icon"]').setAttribute("href", "/assets/packages/static/openvk/img/favicons/favicon24_paused.png")
} else {
playButton.removeClass("paused")
document.querySelector('link[rel="icon"], link[rel="shortcut icon"]').setAttribute("href", "/assets/packages/static/openvk/img/favicons/favicon24_playing.png")
}
u('.subTracks').nodes.forEach(el => {
el.classList.remove('shown')
})
u(`#audioEmbed-${ id} .subTracks`).addClass('shown')
if(!$(`#audioEmbed-${ id}`).hasClass("havePlayed")) {
$(`#audioEmbed-${ id}`).addClass("havePlayed")
$.post(`/audio${playerObject.dataset.realid}/listen`, {
hash: u("meta[name=csrf]").attr("value")
});
}
};
const hideTracks = () => {
$(`#audioEmbed-${ id} .track`).removeClass('shown')
$(`#audioEmbed-${ id}`).removeClass("havePlayed")
}
u(audio).on("play", playButtonImageUpdate);
u(audio).on(["pause", "suspended"], playButtonImageUpdate);
u(audio).on("ended", (e) => {
let thisPlayer = playerObject
let nextPlayer = null
if(thisPlayer.closest(".attachment") != null) {
try {
nextPlayer = thisPlayer.closest(".attachment").nextElementSibling.querySelector(".audioEmbed")
} catch(e) {return}
} else if(thisPlayer.closest(".audio") != null) {
try {
nextPlayer = thisPlayer.closest(".audio").nextElementSibling.querySelector(".audioEmbed")
} catch(e) {return}
} else if(thisPlayer.closest(".search_content") != null) {
try {
nextPlayer = thisPlayer.closest(".search_content").nextElementSibling.querySelector(".audioEmbed")
} catch(e) {return}
} else {
nextPlayer = thisPlayer.nextElementSibling
}
playButtonImageUpdate()
if(!nextPlayer) return
initPlayer(nextPlayer.id.replace("audioEmbed-", ""),
JSON.parse(nextPlayer.dataset.keys),
nextPlayer.dataset.url,
nextPlayer.dataset.length)
nextPlayer.querySelector(".playIcon").click()
hideTracks()
})
u(`#audioEmbed-${ id} .lengthTrack > div`).on("click mouseup mousemove", (e) => {
if(e.type == "mousemove") {
let buttonsPresseed = _bsdnUnwrapBitMask(e.buttons)
if(!buttonsPresseed[0])
return;
}
let rect = document.querySelector("#audioEmbed-" + id + " .selectableTrack").getBoundingClientRect();
const width = e.clientX - rect.left;
const time = Math.ceil((width * length) / (rect.right - rect.left));
audio.currentTime = time;
});
u(`#audioEmbed-${ id} .volumeTrack > div`).on("click mouseup mousemove", (e) => {
if(e.type == "mousemove") {
let buttonsPresseed = _bsdnUnwrapBitMask(e.buttons)
if(!buttonsPresseed[0])
return;
}
let rect = document.querySelector("#audioEmbed-" + id + " .volumeTrack").getBoundingClientRect();
const width = e.clientX - rect.left;
const volume = (width * 1) / (rect.right - rect.left);
audio.volume = Math.max(0, volume);
});
audio.volume = localStorage.volume ?? 0.75
u(audio).trigger("volumechange")
}
$(document).on("click", ".musicIcon.edit-icon", (e) => {
let player = e.currentTarget.closest(".audioEmbed")
let id = Number(player.dataset.realid)
let performer = e.currentTarget.dataset.performer
let name = e.currentTarget.dataset.title
let genre = player.dataset.genre
let lyrics = e.currentTarget.dataset.lyrics
MessageBox(tr("edit_audio"), `
${tr("performer")}
${tr("audio_name")}
${tr("genre")}
${tr("lyrics")}
`, [tr("save"), tr("cancel")], [
function() {
let t_name = $(".ovk-diag-body input[name=name]").val();
let t_perf = $(".ovk-diag-body input[name=performer]").val();
let t_genre = $(".ovk-diag-body select[name=genre]").val();
let t_lyrics = $(".ovk-diag-body textarea[name=lyrics]").val();
let t_explicit = document.querySelector(".ovk-diag-body input[name=explicit]").checked;
let t_unlisted = document.querySelector(".ovk-diag-body input[name=searchable]").checked;
$.ajax({
type: "POST",
url: `/audio${id}/action?act=edit`,
data: {
name: t_name,
performer: t_perf,
genre: t_genre,
lyrics: t_lyrics,
unlisted: Number(t_unlisted),
explicit: Number(t_explicit),
hash: u("meta[name=csrf]").attr("value")
},
success: (response) => {
if(response.success) {
let perf = player.querySelector(".performer a")
perf.innerHTML = escapeHtml(response.new_info.performer)
perf.setAttribute("href", "/search?q=§ion=audios&order=listens&only_performers=on&q="+response.new_info.performer)
e.target.setAttribute("data-performer", escapeHtml(response.new_info.performer))
let name = player.querySelector(".title")
name.innerHTML = escapeHtml(response.new_info.name)
e.target.setAttribute("data-title", escapeHtml(response.new_info.name))
if(response.new_info.lyrics_unformatted != "") {
if(player.querySelector(".lyrics") != null) {
player.querySelector(".lyrics").innerHTML = response.new_info.lyrics
player.querySelector(".title").classList.add("withLyrics")
} else {
player.insertAdjacentHTML("beforeend", `
${response.new_info.lyrics}
`)
player.querySelector(".title").classList.add("withLyrics")
}
} else {
$(player.querySelector(".lyrics")).remove()
player.querySelector(".title").classList.remove("withLyrics")
}
e.target.setAttribute("data-lyrics", response.new_info.lyrics_unformatted)
e.target.setAttribute("data-explicit", Number(response.new_info.explicit))
if(Number(response.new_info.explicit) == 1) {
if(!player.querySelector(".mediaInfo .explicitMark"))
player.querySelector(".mediaInfo").insertAdjacentHTML("beforeend", `
`)
} else {
$(player.querySelector(".mediaInfo .explicitMark")).remove()
}
e.target.setAttribute("data-searchable", Number(!response.new_info.unlisted))
player.setAttribute("data-genre", response.new_info.genre)
let url = new URL(location.href)
let page = "1"
if(url.searchParams.p != null)
page = String(url.searchParams.p)
window.savedAudiosPages[page] = null
} else
fastError(response.flash.message)
}
});
},
Function.noop
]);
window.openvk.audio_genres.forEach(elGenre => {
document.querySelector(".ovk-diag-body select[name=genre]").insertAdjacentHTML("beforeend", `
`)
})
u(".ovk-diag-body #_fullyDeleteAudio").on("click", (e) => {
u("body").removeClass("dimmed");
u(".ovk-diag-cont").remove();
document.querySelector("html").style.overflowY = "scroll"
MessageBox(tr('confirm'), tr('confirm_deleting_audio'), [tr('yes'), tr('no')], [() => {
$.ajax({
type: "POST",
url: `/audio${id}/action?act=delete`,
data: {
hash: u("meta[name=csrf]").attr("value")
},
success: (response) => {
if(response.success)
u(player).remove()
else
fastError(response.flash.message)
}
});
}, () => {Function.noop}])
})
})
$(document).on("click", ".title.withLyrics", (e) => {
const parent = e.currentTarget.closest(".audioEmbed")
parent.querySelector(".lyrics").classList.toggle("showed")
})
$(document).on("click", ".musicIcon.remove-icon", (e) => {
e.stopImmediatePropagation()
const id = e.currentTarget.dataset.id
if(e.detail > 1 || e.altKey) {
const player = e.target.closest('.audioEmbed')
player.querySelector('.add-icon-group').click()
return
}
let formdata = new FormData()
formdata.append("hash", u("meta[name=csrf]").attr("value"))
ky.post(`/audio${id}/action?act=remove`, {
hooks: {
beforeRequest: [
(_request) => {
e.target.classList.add("lagged")
}
],
afterResponse: [
async (_request, _options, response) => {
let json = await response.json()
if(json.success) {
e.target.classList.remove("remove-icon")
e.target.classList.add("add-icon")
e.target.classList.remove("lagged")
let withd = e.target.closest(".audioEmbed.withdrawn")
if(withd != null)
u(withd).remove()
} else
fastError(json.flash.message)
}
]
}, body: formdata
})
})
$(document).on("click", ".musicIcon.remove-icon-group", (e) => {
e.stopImmediatePropagation()
let id = e.currentTarget.dataset.id
let formdata = new FormData()
formdata.append("hash", u("meta[name=csrf]").attr("value"))
formdata.append("club", e.currentTarget.dataset.club)
ky.post(`/audio${id}/action?act=remove_club`, {
hooks: {
beforeRequest: [
(_request) => {
e.currentTarget.classList.add("lagged")
}
],
afterResponse: [
async (_request, _options, response) => {
let json = await response.json()
if(json.success)
$(e.currentTarget.closest(".audioEmbed")).remove()
else
fastError(json.flash.message)
}
]
}, body: formdata
})
})
$(document).on("click", ".musicIcon.add-icon-group", async (ev) => {
let current_tab = 'club';
const id = Number(ev.target.dataset.id)
const body = `
${tr('add_audio_limitations')}
`
MessageBox(tr("add_audio"), body, [tr("cancel"), tr("add")], [Function.noop, () => {
const ids = []
u('#_content .entity_vertical_list_item').nodes.forEach(item => {
const _checkbox = item.querySelector(`input[type='checkbox'][name='add_to']`)
if(_checkbox.checked) {
ids.push(item.dataset.id)
}
})
if(ids.length < 1 || ids.length > 10) {
return
}
console.log(ids)
switch(current_tab) {
case 'club':
$.ajax({
type: "POST",
url: `/audio${id}/action?act=add_to_club`,
data: {
hash: u("meta[name=csrf]").attr("value"),
clubs: ids.join(',')
},
success: (response) => {
if(!response.success)
fastError(response.flash.message)
else
NewNotification(tr("audio_was_successfully_added"), '')
}
})
break
case 'playlist':
$.ajax({
type: "POST",
url: `/audio${id}/action?act=add_to_playlist`,
data: {
hash: u("meta[name=csrf]").attr("value"),
playlists: ids.join(',')
},
success: (response) => {
if(!response.success)
fastError(response.flash.message)
else
NewNotification(tr("audio_was_successfully_added"), '')
}
})
break
}
}])
u(".ovk-diag-body").attr('style', 'padding:0px;height: 260px;')
async function switchTab(tab = 'club') {
current_tab = tab
u(`#_addAudioAdditional .mb_tab`).attr('id', 'ki')
u(`#_addAudioAdditional .mb_tab[data-name='${tab}']`).attr('id', 'active')
switch(tab) {
case 'club':
u("#_content").html(``)
if(window.openvk.writeableClubs == null) {
u('.entity_vertical_list').append(``)
try {
window.openvk.writeableClubs = await API.Groups.getWriteableClubs()
} catch (e) {
u("#_content").html(tr("no_access_clubs"))
return
}
u('.entity_vertical_list #gif_loader').remove()
}
window.openvk.writeableClubs.forEach(el => {
u("#_content .entity_vertical_list").append(`
`)
})
break
case 'playlist':
const per_page = 10
let page = 0
u("#_content").html(``)
async function recievePlaylists(s_page) {
res = await fetch(`/method/audio.searchAlbums?auth_mechanism=roaming&query=&limit=10&offset=${s_page * per_page}&from_me=1`)
res = await res.json()
return res
}
function appendPlaylists(response) {
response.items.forEach(el => {
u("#_content .entity_vertical_list").append(`
`)
})
if(response.count > per_page * page) {
u("#_content .entity_vertical_list").append(`${tr('show_more')}`)
}
}
if(window.openvk.writeablePlaylists == null) {
u('.entity_vertical_list').append(``)
try {
res = await recievePlaylists(page)
page += 1
window.openvk.writeablePlaylists = res.response
if(!window.openvk.writeablePlaylists || window.openvk.writeablePlaylists.count < 1) {
throw new Error
}
} catch (e) {
u("#_content").html(tr("no_access_playlists"))
return
}
u('.entity_vertical_list #gif_loader').remove()
}
appendPlaylists(window.openvk.writeablePlaylists)
u('#_addAudioAdditional').on('click', '#_pladdwinshowmore', async (e) => {
e.target.outerHTML = ''
res = await recievePlaylists(page)
page += 1
appendPlaylists(res.response)
})
break
}
}
switchTab(current_tab)
u("#_addAudioAdditional").on("click", ".mb_tab a", async (e) => {
await switchTab(u(e.target).closest('.mb_tab').attr('data-name'))
})
u("#_addAudioAdditional").on("click", "input[name='add_to']", async (e) => {
if(u(`input[name='add_to']:checked`).length > 10) {
e.preventDefault()
}
})
})
$(document).on("click", ".musicIcon.add-icon", (e) => {
const id = e.currentTarget.dataset.id
if(e.detail > 1 || e.altKey) {
const player = e.target.closest('.audioEmbed')
player.querySelector('.add-icon-group').click()
return
}
let formdata = new FormData()
formdata.append("hash", u("meta[name=csrf]").attr("value"))
ky.post(`/audio${id}/action?act=add`, {
hooks: {
beforeRequest: [
(_request) => {
e.target.classList.add("lagged")
}
],
afterResponse: [
async (_request, _options, response) => {
let json = await response.json()
if(json.success) {
e.target.classList.remove("add-icon")
e.target.classList.add("remove-icon")
e.target.classList.remove("lagged")
} else
fastError(json.flash.message)
}
]
}, body: formdata
})
})
$(document).on("click", "#_deletePlaylist", (e) => {
let id = e.currentTarget.dataset.id
MessageBox(tr("warning"), tr("sure_delete_playlist"), [tr("yes"), tr("no")], [() => {
$.ajax({
type: "POST",
url: `/playlist${id}/action?act=delete`,
data: {
hash: u("meta[name=csrf]").attr("value"),
},
beforeSend: () => {
e.currentTarget.classList.add("lagged")
},
success: (response) => {
if(response.success) {
window.location.assign("/playlists" + response.id)
} else {
fastError(response.flash.message)
}
}
})
}, Function.noop])
})
$(document).on("click", "#_audioAttachment", (e) => {
let form = e.currentTarget.closest("form")
let body = `
`
MessageBox(tr("select_audio"), body, [tr("ok")], [Function.noop])
document.querySelector(".ovk-diag-body").style.padding = "0"
document.querySelector(".ovk-diag-cont").style.width = "580px"
document.querySelector(".ovk-diag-body").style.height = "335px"
let searcher = new playersSearcher("entity_audios", 0)
searcher.successCallback = (response, thisc) => {
let domparser = new DOMParser()
let result = domparser.parseFromString(response, "text/html")
let pagesCount = result.querySelector("input[name='pagesCount']").value
let count = Number(result.querySelector("input[name='count']").value)
if(count < 1) {
document.querySelector(".audiosInsert").innerHTML = thisc.context_type == "entity_audios" ? tr("no_audios_thisuser") : tr("no_results")
return
}
result.querySelectorAll(".audioEmbed").forEach(el => {
let id = el.dataset.prettyid
let name = el.dataset.name
let isAttached = (form.querySelector("input[name='audios']").value.includes(`${id},`))
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
${el.outerHTML}
${isAttached ? tr("detach_audio") : tr("attach_audio")}
`)
})
u("#loader").remove()
if(thisc.page < pagesCount) {
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
${tr("show_more_audios")}
`)
}
}
searcher.errorCallback = () => {
fastError("Error when loading players.")
}
searcher.beforesendCallback = () => {
document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", ``)
}
searcher.clearContainer = () => {
document.querySelector(".audiosInsert").innerHTML = ""
}
searcher.movePage(1)
$(".audiosInsert").on("click", "#showMoreAudios", (e) => {
u(e.currentTarget).remove()
searcher.movePage(Number(e.currentTarget.dataset.page))
})
$(".searchBox input").on("change", async (e) => {
await new Promise(r => setTimeout(r, 500));
if(e.currentTarget.value === document.querySelector(".searchBox input").value) {
searcher.clearContainer()
if(e.currentTarget.value == "") {
searcher.context_type = "entity_audios"
searcher.context_id = 0
searcher.query = ""
searcher.movePage(1)
return
}
searcher.context_type = "search_context"
searcher.context_id = 0
searcher.query = e.currentTarget.value
searcher.movePage(1)
return;
}
})
$(".searchBox select").on("change", async (e) => {
searcher.clearContainer()
searcher.searchType = e.currentTarget.value
$(".searchBox input").trigger("change")
return;
})
function insertAttachment(id) {
let audios = form.querySelector("input[name='audios']")
if(!audios.value.includes(id + ",")) {
if(audios.value.split(",").length > 10) {
NewNotification(tr("error"), tr("max_attached_audios"))
return false
}
form.querySelector("input[name='audios']").value += (id + ",")
return true
} else {
form.querySelector("input[name='audios']").value = form.querySelector("input[name='audios']").value.replace(id + ",", "")
return false
}
}
$(".audiosInsert").on("click", ".attachAudio", (ev) => {
if(!insertAttachment(ev.currentTarget.dataset.attachmentdata)) {
u(`.post-has-audios .post-has-audio[data-id='${ev.currentTarget.dataset.attachmentdata}']`).remove()
ev.currentTarget.querySelector("span").innerHTML = tr("attach_audio")
} else {
ev.currentTarget.querySelector("span").innerHTML = tr("detach_audio")
form.querySelector(".post-has-audios").insertAdjacentHTML("beforeend", `
${ovk_proc_strtr(escapeHtml(ev.currentTarget.dataset.name), 40)}
`)
u(`#unattachAudio[data-id='${ev.currentTarget.dataset.attachmentdata}']`).on("click", (e) => {
let id = ev.currentTarget.dataset.attachmentdata
form.querySelector("input[name='audios']").value = form.querySelector("input[name='audios']").value.replace(id + ",", "")
u(e.currentTarget).remove()
})
}
})
})
$(document).on("click", ".audioEmbed.processed .playerButton", (e) => {
MessageBox(tr("error"), tr("audio_embed_processing"), [tr("ok")], [Function.noop])
})
$(document).on("click", ".audioEmbed.withdrawn", (e) => {
MessageBox(tr("error"), tr("audio_embed_withdrawn"), [tr("ok")], [Function.noop])
})
$(document).on("click", ".musicIcon.report-icon", (e) => {
MessageBox(tr("report_question"), `
${tr("going_to_report_audio")}
${tr("report_question_text")}
${tr("report_reason")}: `, [tr("confirm_m"), tr("cancel")], [(function() {
res = document.querySelector("#uReportMsgInput").value;
xhr = new XMLHttpRequest();
xhr.open("GET", "/report/" + e.target.dataset.id + "?reason=" + res + "&type=audio", 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", ".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["tracks"].currentTrack != null ? window.player["tracks"].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["tracks"].currentTrack != null ? window.player["tracks"].currentTrack.id : 0)
if(!window.player.context["playedPages"].includes(page)) {
$.ajax({
type: "POST",
url: "/audios/context",
data: {
context: window.player["context"].context_type,
context_entity: window.player["context"].context_id,
hash: u("meta[name=csrf]").attr("value"),
page: page
},
success: (response_2) => {
window.player.tracks["tracks"] = window.player.tracks["tracks"].concat(response_2["items"])
window.player.context["playedPages"].push(String(page))
console.info("Page is switched")
}
})
}
}
})
})
$(document).on("click", ".addToPlaylist", (e) => {
let audios = document.querySelector("input[name='audios']")
let id = e.currentTarget.dataset.id
if(!audios.value.includes(id + ",")) {
document.querySelector("input[name='audios']").value += (id + ",")
e.currentTarget.querySelector("span").innerHTML = tr("remove_from_playlist")
} else {
document.querySelector("input[name='audios']").value = document.querySelector("input[name='audios']").value.replace(id + ",", "")
e.currentTarget.querySelector("span").innerHTML = tr("add_to_playlist")
}
})
$(document).on("click", "#bookmarkPlaylist, #unbookmarkPlaylist", (e) => {
let target = e.currentTarget
let id = target.id
$.ajax({
type: "POST",
url: `/playlist${e.currentTarget.dataset.id}/action?act=${id == "unbookmarkPlaylist" ? "unbookmark" : "bookmark"}`,
data: {
hash: u("meta[name=csrf]").attr("value"),
},
beforeSend: () => {
e.currentTarget.classList.add("lagged")
},
success: (response) => {
if(response.success) {
e.currentTarget.setAttribute("id", id == "unbookmarkPlaylist" ? "bookmarkPlaylist" : "unbookmarkPlaylist")
e.currentTarget.innerHTML = id == "unbookmarkPlaylist" ? tr("bookmark") : tr("unbookmark")
e.currentTarget.classList.remove("lagged")
} else
fastError(response.flash.message)
}
})
})