mirror of
https://github.com/openvk/openvk
synced 2025-04-23 08:33:02 +03:00
(смешное название коммита)
- Теперь на странице пользователя/группы показываются три случайные песни, а не первые три как раньше - Теперь пробел на странице аудио не перемещает вас в низ страницы - Оптимизирован мини-плеер, теперь он инициализируется при любом нажатии на него, а не при наведении - Теперь при завершении проигрывания трека в мини-плеере он ищет другой трек рядом, и если находит то воспроизводит. Будет удобно для постов с подборками треков - Поиск теперь показывает 14 результатов - Теперь при возникновении ошибки загрузки аудио она нормально отображается - Вместе с плеером на странице с аудиозаписями теперь двигаются и вкладки - Добавление аудио в группу по идее должно нормально работать
This commit is contained in:
parent
4defb88846
commit
edde634782
15 changed files with 200 additions and 33 deletions
|
@ -120,14 +120,14 @@ class Audio extends Media
|
||||||
Shell::powershell("-executionpolicy bypass", "-File", __DIR__ . "/../shell/processAudio.ps1", ...$args)
|
Shell::powershell("-executionpolicy bypass", "-File", __DIR__ . "/../shell/processAudio.ps1", ...$args)
|
||||||
->start();
|
->start();
|
||||||
} else {
|
} else {
|
||||||
exit("Linux uploads are not implemented");
|
throw new \BadMethodCallException("Linux uploads are not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Wait until processAudio will consume the file
|
# Wait until processAudio will consume the file
|
||||||
$start = time();
|
$start = time();
|
||||||
while(file_exists($filename))
|
while(file_exists($filename))
|
||||||
if(time() - $start > 5)
|
if(time() - $start > 5)
|
||||||
exit("Timed out waiting for ffmpeg"); // TODO replace with exception
|
throw new \RuntimeException("Timed out waiting FFMPEG");
|
||||||
|
|
||||||
} catch(UnknownCommandException $ucex) {
|
} catch(UnknownCommandException $ucex) {
|
||||||
exit(OPENVK_ROOT_CONF["openvk"]["debug"] ? "bash/pwsh is not installed" : VIDEOS_FRIENDLY_ERROR);
|
exit(OPENVK_ROOT_CONF["openvk"]["debug"] ? "bash/pwsh is not installed" : VIDEOS_FRIENDLY_ERROR);
|
||||||
|
|
|
@ -222,4 +222,9 @@ class Playlist extends MediaCollection
|
||||||
|
|
||||||
return $cover;
|
return $cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getURL(): string
|
||||||
|
{
|
||||||
|
return "/playlist" . $this->getOwner()->getRealId() . "_" . $this->getId();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -109,6 +109,33 @@ class Audios
|
||||||
return $this->getByEntityID($user->getId(), ($perPage * ($page - 1)), $perPage, $deleted);
|
return $this->getByEntityID($user->getId(), ($perPage * ($page - 1)), $perPage, $deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRandomThreeAudiosByEntityId(int $id): Array
|
||||||
|
{
|
||||||
|
$iter = $this->rels->where("entity", $id);
|
||||||
|
$ids = [];
|
||||||
|
|
||||||
|
foreach($iter as $it)
|
||||||
|
$ids[] = $it->audio;
|
||||||
|
|
||||||
|
$shuffleSeed = openssl_random_pseudo_bytes(6);
|
||||||
|
$shuffleSeed = hexdec(bin2hex($shuffleSeed));
|
||||||
|
|
||||||
|
$ids = knuth_shuffle($ids, $shuffleSeed);
|
||||||
|
$ids = array_slice($ids, 0, 3);
|
||||||
|
$audios = [];
|
||||||
|
|
||||||
|
foreach($ids as $id) {
|
||||||
|
$audio = $this->get((int)$id);
|
||||||
|
|
||||||
|
if(!$audio || $audio->isDeleted())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$audios[] = $audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $audios;
|
||||||
|
}
|
||||||
|
|
||||||
function getByClub(Club $club, int $page = 1, ?int $perPage = NULL, ?int& $deleted = nullptr): \Traversable
|
function getByClub(Club $club, int $page = 1, ?int $perPage = NULL, ?int& $deleted = nullptr): \Traversable
|
||||||
{
|
{
|
||||||
return $this->getByEntityID($club->getId() * -1, ($perPage * ($page - 1)), $perPage, $deleted);
|
return $this->getByEntityID($club->getId() * -1, ($perPage * ($page - 1)), $perPage, $deleted);
|
||||||
|
|
|
@ -162,7 +162,30 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
} else {
|
} else {
|
||||||
$err = !isset($upload) ? 65536 : $upload["error"];
|
$err = !isset($upload) ? 65536 : $upload["error"];
|
||||||
$err = str_pad(dechex($err), 9, "0", STR_PAD_LEFT);
|
$err = str_pad(dechex($err), 9, "0", STR_PAD_LEFT);
|
||||||
$this->flashFail("err", tr("error"), tr("error_generic") . "Upload error: 0x$err", null, $isAjax);
|
$readableError = tr("error_generic");
|
||||||
|
|
||||||
|
switch($upload["error"]) {
|
||||||
|
default:
|
||||||
|
case UPLOAD_ERR_INI_SIZE:
|
||||||
|
case UPLOAD_ERR_FORM_SIZE:
|
||||||
|
$readableError = tr("file_too_big");
|
||||||
|
break;
|
||||||
|
case UPLOAD_ERR_PARTIAL:
|
||||||
|
$readableError = tr("file_loaded_partially");
|
||||||
|
break;
|
||||||
|
case UPLOAD_ERR_NO_FILE:
|
||||||
|
$readableError = tr("file_not_uploaded");
|
||||||
|
break;
|
||||||
|
case UPLOAD_ERR_NO_TMP_DIR:
|
||||||
|
$readableError = "Missing a temporary folder.";
|
||||||
|
break;
|
||||||
|
case UPLOAD_ERR_CANT_WRITE:
|
||||||
|
case UPLOAD_ERR_EXTENSION:
|
||||||
|
$readableError = "Failed to write file to disk. ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->flashFail("err", tr("error"), $readableError . " " . tr("error_code", $err), null, $isAjax);
|
||||||
}
|
}
|
||||||
|
|
||||||
$performer = $this->postParam("performer");
|
$performer = $this->postParam("performer");
|
||||||
|
@ -186,6 +209,12 @@ final class AudioPresenter extends OpenVKPresenter
|
||||||
} catch(\DomainException $ex) {
|
} catch(\DomainException $ex) {
|
||||||
$e = $ex->getMessage();
|
$e = $ex->getMessage();
|
||||||
$this->flashFail("err", tr("error"), tr("media_file_corrupted_or_too_large") . " $e.", null, $isAjax);
|
$this->flashFail("err", tr("error"), tr("media_file_corrupted_or_too_large") . " $e.", null, $isAjax);
|
||||||
|
} catch(\RuntimeException $ex) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("ffmpeg_timeout"), null, $isAjax);
|
||||||
|
} catch(\BadMethodCallException $ex) {
|
||||||
|
$this->flashFail("err", tr("error"), "Загрузка аудио под Linux на данный момент не реализована. Следите за обновлениями: <a href='https://github.com/openvk/openvk/pull/512/commits'>https://github.com/openvk/openvk/pull/512/commits</a>", null, $isAjax);
|
||||||
|
} catch(\Exception $ex) {
|
||||||
|
$this->flashFail("err", tr("error"), tr("ffmpeg_not_installed"), null, $isAjax);
|
||||||
}
|
}
|
||||||
|
|
||||||
$audio->save();
|
$audio->save();
|
||||||
|
|
|
@ -31,7 +31,7 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
$this->template->albumsCount = (new Albums)->getClubAlbumsCount($club);
|
$this->template->albumsCount = (new Albums)->getClubAlbumsCount($club);
|
||||||
$this->template->topics = (new Topics)->getLastTopics($club, 3);
|
$this->template->topics = (new Topics)->getLastTopics($club, 3);
|
||||||
$this->template->topicsCount = (new Topics)->getClubTopicsCount($club);
|
$this->template->topicsCount = (new Topics)->getClubTopicsCount($club);
|
||||||
$this->template->audios = (new Audios)->getByClub($club, 1, 3);
|
$this->template->audios = (new Audios)->getRandomThreeAudiosByEntityId($club->getRealId());
|
||||||
$this->template->audiosCount = (new Audios)->getClubCollectionSize($club);
|
$this->template->audiosCount = (new Audios)->getClubCollectionSize($club);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,12 +104,13 @@ final class SearchPresenter extends OpenVKPresenter
|
||||||
$repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type.");
|
$repo = $repos[$type] or $this->throwError(400, "Bad Request", "Invalid search entity $type.");
|
||||||
|
|
||||||
$results = $this->{$repo}->find($query, $parameters, $sort);
|
$results = $this->{$repo}->find($query, $parameters, $sort);
|
||||||
$iterator = $results->page($page);
|
$iterator = $results->page($page, 14);
|
||||||
$count = $results->size();
|
$count = $results->size();
|
||||||
|
|
||||||
$this->template->iterator = iterator_to_array($iterator);
|
$this->template->iterator = iterator_to_array($iterator);
|
||||||
$this->template->count = $count;
|
$this->template->count = $count;
|
||||||
$this->template->type = $type;
|
$this->template->type = $type;
|
||||||
$this->template->page = $page;
|
$this->template->page = $page;
|
||||||
|
$this->template->perPage = 14;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ final class UserPresenter extends OpenVKPresenter
|
||||||
$this->template->videosCount = (new Videos)->getUserVideosCount($user);
|
$this->template->videosCount = (new Videos)->getUserVideosCount($user);
|
||||||
$this->template->notes = (new Notes)->getUserNotes($user, 1, 4);
|
$this->template->notes = (new Notes)->getUserNotes($user, 1, 4);
|
||||||
$this->template->notesCount = (new Notes)->getUserNotesCount($user);
|
$this->template->notesCount = (new Notes)->getUserNotesCount($user);
|
||||||
$this->template->audios = (new Audios)->getByUser($user, 1, 3);
|
$this->template->audios = (new Audios)->getRandomThreeAudiosByEntityId($user->getId());
|
||||||
$this->template->audiosCount = (new Audios)->getUserCollectionSize($user);
|
$this->template->audiosCount = (new Audios)->getUserCollectionSize($user);
|
||||||
|
|
||||||
$this->template->user = $user;
|
$this->template->user = $user;
|
||||||
|
|
|
@ -2,6 +2,23 @@
|
||||||
|
|
||||||
{block title}{_playlist}{/block}
|
{block title}{_playlist}{/block}
|
||||||
|
|
||||||
|
{block headIncludes}
|
||||||
|
<meta property="og:type" content="music.album">
|
||||||
|
<meta property="og:title" content="{$playlist->getName()}">
|
||||||
|
<meta property="og:url" content="{$playlist->getURL()}">
|
||||||
|
<meta property="og:description" content="{$playlist->getDescription()}">
|
||||||
|
<meta property="og:image" content="{$playlist->getCoverURL()}">
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "http://schema.org/",
|
||||||
|
"type": "MusicAlbum",
|
||||||
|
"name": {$playlist->getName()},
|
||||||
|
"url": {$playlist->getURL()}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{/block}
|
||||||
|
|
||||||
{block header}
|
{block header}
|
||||||
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
<a href="{$owner->getURL()}">{$owner->getCanonicalName()}</a>
|
||||||
»
|
»
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{php $id = $audio->getId() . rand(0, 1000)}
|
{php $id = $audio->getId() . rand(0, 1000)}
|
||||||
{php $isWithdrawn = $audio->isWithdrawn()}
|
{php $isWithdrawn = $audio->isWithdrawn()}
|
||||||
{php $editable = isset($thisUser) && $audio->canBeModifiedBy($thisUser)}
|
{php $editable = isset($thisUser) && $audio->canBeModifiedBy($thisUser)}
|
||||||
<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" {if $hideButtons}data-prettyid="{$audio->getPrettyId()}" data-name="{$audio->getName()}"{/if} data-genre="{$audio->getGenre()}" class="audioEmbed {if !$audio->isAvailable()}processed{/if} {if $isWithdrawn}withdrawn{/if}" onmouseenter="!this.classList.contains('inited') ? initPlayer({$id}, {$audio->getKeys()}, {$audio->getURL()}, {$audio->getLength()}) : void(0)">
|
<div id="audioEmbed-{$id}" data-realid="{$audio->getId()}" {if $hideButtons}data-prettyid="{$audio->getPrettyId()}" data-name="{$audio->getName()}"{/if} data-genre="{$audio->getGenre()}" class="audioEmbed {if !$audio->isAvailable()}processed{/if} {if $isWithdrawn}withdrawn{/if}" data-length="{$audio->getLength()}" data-keys="{json_encode($audio->getKeys())}" data-url="{$audio->getURL()}">
|
||||||
<audio class="audio" />
|
<audio class="audio" />
|
||||||
|
|
||||||
<div id="miniplayer" class="audioEntry" style="min-height: 39px;">
|
<div id="miniplayer" class="audioEntry" style="min-height: 39px;">
|
||||||
|
|
|
@ -530,7 +530,7 @@
|
||||||
{var $musics = explode(", ", $user->getFavoriteMusic())}
|
{var $musics = explode(", ", $user->getFavoriteMusic())}
|
||||||
|
|
||||||
{foreach $musics as $music}
|
{foreach $musics as $music}
|
||||||
<a href="/search?type=users&query=&fav_mus={urlencode($music)}">{$music}</a>{if $music != end($musics)},{/if}
|
<a href="/search?type=audios&query={urlencode($music)}">{$music}</a>{if $music != end($musics)},{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -559,3 +559,10 @@
|
||||||
.playlistInfo .playlistName {
|
.playlistInfo .playlistName {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.searchList.floating {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 199;
|
||||||
|
width: 156px;
|
||||||
|
margin-top: -65px !important;
|
||||||
|
}
|
|
@ -270,7 +270,7 @@ class bigPlayer {
|
||||||
})
|
})
|
||||||
|
|
||||||
u(document).on("keydown", (e) => {
|
u(document).on("keydown", (e) => {
|
||||||
if(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
|
if(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", " "].includes(e.key)) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
if(document.querySelector(".ovk-diag-cont") != null)
|
if(document.querySelector(".ovk-diag-cont") != null)
|
||||||
|
@ -290,11 +290,19 @@ class bigPlayer {
|
||||||
case "ArrowRight":
|
case "ArrowRight":
|
||||||
this.player().currentTime = this.player().currentTime + 3
|
this.player().currentTime = this.player().currentTime + 3
|
||||||
break
|
break
|
||||||
|
// буквально
|
||||||
|
case " ":
|
||||||
|
if(this.player().paused)
|
||||||
|
this.play()
|
||||||
|
else
|
||||||
|
this.pause()
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
u(document).on("keyup", (e) => {
|
u(document).on("keyup", (e) => {
|
||||||
if([32, 87, 65, 83, 68].includes(e.keyCode)) {
|
if([87, 65, 83, 68].includes(e.keyCode)) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
if(document.querySelector(".ovk-diag-cont") != null)
|
if(document.querySelector(".ovk-diag-cont") != null)
|
||||||
|
@ -302,13 +310,6 @@ class bigPlayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(e.keyCode) {
|
switch(e.keyCode) {
|
||||||
case 32:
|
|
||||||
if(this.player().paused)
|
|
||||||
this.play()
|
|
||||||
else
|
|
||||||
this.pause()
|
|
||||||
|
|
||||||
break
|
|
||||||
case 87:
|
case 87:
|
||||||
case 65:
|
case 65:
|
||||||
this.showPreviousTrack()
|
this.showPreviousTrack()
|
||||||
|
@ -565,8 +566,10 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||||
entries.forEach(x => {
|
entries.forEach(x => {
|
||||||
if(x.isIntersecting) {
|
if(x.isIntersecting) {
|
||||||
document.querySelector('.bigPlayer').classList.remove("floating")
|
document.querySelector('.bigPlayer').classList.remove("floating")
|
||||||
|
document.querySelector('.searchOptions .searchList').classList.remove("floating")
|
||||||
document.querySelector('.bigPlayerDetector').style.marginTop = "0px"
|
document.querySelector('.bigPlayerDetector').style.marginTop = "0px"
|
||||||
} else {
|
} else {
|
||||||
|
document.querySelector('.searchOptions .searchList').classList.add("floating")
|
||||||
document.querySelector('.bigPlayer').classList.add("floating")
|
document.querySelector('.bigPlayer').classList.add("floating")
|
||||||
document.querySelector('.bigPlayerDetector').style.marginTop = "46px"
|
document.querySelector('.bigPlayerDetector').style.marginTop = "46px"
|
||||||
}
|
}
|
||||||
|
@ -581,6 +584,20 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||||
bigPlayerObserver.observe(bigplayer);
|
bigPlayerObserver.observe(bigplayer);
|
||||||
}})
|
}})
|
||||||
|
|
||||||
|
$(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) {
|
function initPlayer(id, keys, url, length) {
|
||||||
document.querySelector(`#audioEmbed-${ id}`).classList.add("inited")
|
document.querySelector(`#audioEmbed-${ id}`).classList.add("inited")
|
||||||
const audio = document.querySelector(`#audioEmbed-${ id} .audio`);
|
const audio = document.querySelector(`#audioEmbed-${ id} .audio`);
|
||||||
|
@ -661,8 +678,40 @@ function initPlayer(id, keys, url, length) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hideTracks = () => {
|
||||||
|
$(`#audioEmbed-${ id} .track`).toggle()
|
||||||
|
$(`#audioEmbed-${ id}`).removeClass("havePlayed")
|
||||||
|
}
|
||||||
|
|
||||||
u(audio).on("play", playButtonImageUpdate);
|
u(audio).on("play", playButtonImageUpdate);
|
||||||
u(audio).on(["pause", "ended", "suspended"], playButtonImageUpdate);
|
u(audio).on(["pause", "suspended"], playButtonImageUpdate);
|
||||||
|
u(audio).on("ended", (e) => {
|
||||||
|
let thisPlayer = e.target.closest(".audioEmbed")
|
||||||
|
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 {
|
||||||
|
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", (e) => {
|
u(`#audioEmbed-${ id} .lengthTrack > div`).on("click", (e) => {
|
||||||
let rect = document.querySelector("#audioEmbed-" + id + " .selectableTrack").getBoundingClientRect();
|
let rect = document.querySelector("#audioEmbed-" + id + " .selectableTrack").getBoundingClientRect();
|
||||||
|
@ -835,7 +884,7 @@ $(document).on("click", ".musicIcon.remove-icon", (e) => {
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeRequest: [
|
beforeRequest: [
|
||||||
(_request) => {
|
(_request) => {
|
||||||
e.currentTarget.classList.add("lagged")
|
e.target.classList.add("lagged")
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
afterResponse: [
|
afterResponse: [
|
||||||
|
@ -843,11 +892,11 @@ $(document).on("click", ".musicIcon.remove-icon", (e) => {
|
||||||
let json = await response.json()
|
let json = await response.json()
|
||||||
|
|
||||||
if(json.success) {
|
if(json.success) {
|
||||||
e.currentTarget.classList.remove("remove-icon")
|
e.target.classList.remove("remove-icon")
|
||||||
e.currentTarget.classList.add("add-icon")
|
e.target.classList.add("add-icon")
|
||||||
e.currentTarget.classList.remove("lagged")
|
e.target.classList.remove("lagged")
|
||||||
|
|
||||||
let withd = e.currentTarget.closest(".audioEmbed.withdrawn")
|
let withd = e.target.closest(".audioEmbed.withdrawn")
|
||||||
|
|
||||||
if(withd != null)
|
if(withd != null)
|
||||||
u(withd).remove()
|
u(withd).remove()
|
||||||
|
@ -920,13 +969,13 @@ $(document).on("click", ".musicIcon.add-icon-group", async (ev) => {
|
||||||
$(".ovk-diag-body").on("click", "input[name='addButton']", (e) => {
|
$(".ovk-diag-body").on("click", "input[name='addButton']", (e) => {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: `/audio${ev.currentTarget.dataset.id}/action?act=add_to_club`,
|
url: `/audio${ev.target.dataset.id}/action?act=add_to_club`,
|
||||||
data: {
|
data: {
|
||||||
hash: u("meta[name=csrf]").attr("value"),
|
hash: u("meta[name=csrf]").attr("value"),
|
||||||
club: document.querySelector("#addIconsWindow").value
|
club: document.querySelector("#addIconsWindow").value
|
||||||
},
|
},
|
||||||
beforeSend: () => {
|
beforeSend: () => {
|
||||||
e.currentTarget.classList.add("lagged")
|
e.target.classList.add("lagged")
|
||||||
document.querySelector(".errorPlace").innerHTML = ""
|
document.querySelector(".errorPlace").innerHTML = ""
|
||||||
},
|
},
|
||||||
success: (response) => {
|
success: (response) => {
|
||||||
|
@ -949,7 +998,7 @@ $(document).on("click", ".musicIcon.add-icon", (e) => {
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeRequest: [
|
beforeRequest: [
|
||||||
(_request) => {
|
(_request) => {
|
||||||
e.currentTarget.classList.add("lagged")
|
e.target.classList.add("lagged")
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
afterResponse: [
|
afterResponse: [
|
||||||
|
@ -957,9 +1006,9 @@ $(document).on("click", ".musicIcon.add-icon", (e) => {
|
||||||
let json = await response.json()
|
let json = await response.json()
|
||||||
|
|
||||||
if(json.success) {
|
if(json.success) {
|
||||||
e.currentTarget.classList.remove("add-icon")
|
e.target.classList.remove("add-icon")
|
||||||
e.currentTarget.classList.add("remove-icon")
|
e.target.classList.add("remove-icon")
|
||||||
e.currentTarget.classList.remove("lagged")
|
e.target.classList.remove("lagged")
|
||||||
} else
|
} else
|
||||||
fastError(json.flash.message)
|
fastError(json.flash.message)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ CREATE TABLE IF NOT EXISTS `audio_listens` (
|
||||||
`audio` bigint unsigned NOT NULL,
|
`audio` bigint unsigned NOT NULL,
|
||||||
`time` bigint unsigned NOT NULL,
|
`time` bigint unsigned NOT NULL,
|
||||||
`index` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'Workaround for Nette DBE bug',
|
`index` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'Workaround for Nette DBE bug',
|
||||||
|
`playlist` bigint(20) UNSIGNED DEFAULT NULL,
|
||||||
PRIMARY KEY (`index`),
|
PRIMARY KEY (`index`),
|
||||||
KEY `audio` (`audio`),
|
KEY `audio` (`audio`),
|
||||||
KEY `user` (`entity`) USING BTREE,
|
KEY `user` (`entity`) USING BTREE,
|
||||||
|
@ -63,6 +64,7 @@ CREATE TABLE IF NOT EXISTS `playlists` (
|
||||||
`length` int unsigned NOT NULL DEFAULT '0',
|
`length` int unsigned NOT NULL DEFAULT '0',
|
||||||
`special_type` tinyint unsigned NOT NULL DEFAULT '0',
|
`special_type` tinyint unsigned NOT NULL DEFAULT '0',
|
||||||
`created` bigint unsigned DEFAULT NULL,
|
`created` bigint unsigned DEFAULT NULL,
|
||||||
|
`listens` bigint(20) unsigned NOT NULL DEFAULT 0,
|
||||||
`edited` bigint unsigned DEFAULT NULL,
|
`edited` bigint unsigned DEFAULT NULL,
|
||||||
`deleted` tinyint unsigned DEFAULT '0',
|
`deleted` tinyint unsigned DEFAULT '0',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
|
|
|
@ -1402,6 +1402,12 @@
|
||||||
"playlist_not_bookmarked" = "This playlist is not in your collection.";
|
"playlist_not_bookmarked" = "This playlist is not in your collection.";
|
||||||
"invalid_cover_photo" = "Error when loading cover photo.";
|
"invalid_cover_photo" = "Error when loading cover photo.";
|
||||||
"not_a_photo" = "Uploaded file doesn't look like a photo.";
|
"not_a_photo" = "Uploaded file doesn't look like a photo.";
|
||||||
|
"file_too_big" = "File is too big.";
|
||||||
|
"file_loaded_partially" = "The file has been uploaded partially.";
|
||||||
|
"file_not_uploaded" = "Failed to upload the file.";
|
||||||
|
"error_code" = "Error code: $1.";
|
||||||
|
"ffmpeg_timeout" = "Timed out waiting ffmpeg. Try to upload file again.";
|
||||||
|
"ffmpeg_not_installed" = "Failed to proccess the file. It looks like ffmpeg is not installed on this server.";
|
||||||
|
|
||||||
/* Admin actions */
|
/* Admin actions */
|
||||||
|
|
||||||
|
@ -1736,8 +1742,17 @@
|
||||||
"tour_section_5_text_3" = "In addition to uploading videos directly, the site also supports embedding videos from YouTube";
|
"tour_section_5_text_3" = "In addition to uploading videos directly, the site also supports embedding videos from YouTube";
|
||||||
|
|
||||||
|
|
||||||
"tour_section_6_title_1" = "Audios section, which doesn't exist yet xdddd";
|
"tour_section_6_title_1" = "Listen to audios";
|
||||||
"tour_section_6_text_1" = "I would love to do a tutorial on this section, but sunshine Vriska didn't make the music :c";
|
"tour_section_6_text_1" = "Вы можете слушать аудиозаписи в разделе \"Мои Аудиозаписи\".";
|
||||||
|
"tour_section_6_text_2" = "Этот раздел также регулируется настройками приватности.";
|
||||||
|
"tour_section_6_text_3" = "Самые прослушиваемые песни находятся во вкладке \"Популярное\", а недавно загруженные — во вкладке \"Новое\"";
|
||||||
|
"tour_section_6_text_4" = "Найти нужную песню можно в поиске.";
|
||||||
|
"tour_section_6_text_5" = "Чтобы добавить песню в свою коллекцию, наведите на неё и нажмите на плюс.";
|
||||||
|
"tour_section_6_text_6" = "Если вы не можете найти нужную песню, вы можете загрузить её самостоятельно.";
|
||||||
|
"tour_section_6_bottom_text_1" = "<b>Важно:</b> песня не должна нарушать авторские права";
|
||||||
|
"tour_section_6_title_1" = "Создавайте плейлисты";
|
||||||
|
"tour_section_6_text_7" = "Вы можете создавать сборники треков во вкладке \"Мои плейлисты\".";
|
||||||
|
"tour_section_6_text_8" = "Можно также добавлять чужие плейлисты в свою коллекцию.";
|
||||||
|
|
||||||
|
|
||||||
"tour_section_7_title_1" = "Follow what your friends write";
|
"tour_section_7_title_1" = "Follow what your friends write";
|
||||||
|
|
|
@ -1298,6 +1298,12 @@
|
||||||
"playlist_not_bookmarked" = "Плейлиста нет в вашей коллекции.";
|
"playlist_not_bookmarked" = "Плейлиста нет в вашей коллекции.";
|
||||||
"invalid_cover_photo" = "Не удалось сохранить обложку плейлиста.";
|
"invalid_cover_photo" = "Не удалось сохранить обложку плейлиста.";
|
||||||
"not_a_photo" = "Загруженный файл не похож на фотографию.";
|
"not_a_photo" = "Загруженный файл не похож на фотографию.";
|
||||||
|
"file_too_big" = "Файл слишком большой.";
|
||||||
|
"file_loaded_partially" = "Файл загрузился частично.";
|
||||||
|
"file_not_uploaded" = "Не удалось загрузить файл.";
|
||||||
|
"error_code" = "Код ошибки: $1.";
|
||||||
|
"ffmpeg_timeout" = "Превышено время ожидания обработки ffmpeg. Попробуйте загрузить файл снова.";
|
||||||
|
"ffmpeg_not_installed" = "Не удалось обработать файл. Похоже, на сервере не установлен ffmpeg.";
|
||||||
|
|
||||||
/* Admin actions */
|
/* Admin actions */
|
||||||
|
|
||||||
|
@ -1625,8 +1631,17 @@
|
||||||
"tour_section_5_text_3" = "Кроме загрузки видео напрямую, сайт поддерживает и встраивание видео из YouTube";
|
"tour_section_5_text_3" = "Кроме загрузки видео напрямую, сайт поддерживает и встраивание видео из YouTube";
|
||||||
|
|
||||||
|
|
||||||
"tour_section_6_title_1" = "Аудиозаписи, которых пока что нет XD";
|
"tour_section_6_title_1" = "Слушайте аудиозаписи";
|
||||||
"tour_section_6_text_1" = "Я был бы очень рад сделать туториал по этому разделу, но солнышко Вриска не сделала музыку";
|
"tour_section_6_text_1" = "Вы можете слушать аудиозаписи в разделе \"Мои Аудиозаписи\".";
|
||||||
|
"tour_section_6_text_2" = "Этот раздел также регулируется настройками приватности.";
|
||||||
|
"tour_section_6_text_3" = "Самые прослушиваемые песни находятся во вкладке \"Популярное\", а недавно загруженные — во вкладке \"Новое\"";
|
||||||
|
"tour_section_6_text_4" = "Найти нужную песню можно в поиске.";
|
||||||
|
"tour_section_6_text_5" = "Чтобы добавить песню в свою коллекцию, наведите на неё и нажмите на плюс.";
|
||||||
|
"tour_section_6_text_6" = "Если вы не можете найти нужную песню, вы можете загрузить её самостоятельно.";
|
||||||
|
"tour_section_6_bottom_text_1" = "<b>Важно:</b> песня не должна нарушать авторские права";
|
||||||
|
"tour_section_6_title_1" = "Создавайте плейлисты";
|
||||||
|
"tour_section_6_text_7" = "Вы можете создавать сборники треков во вкладке \"Мои плейлисты\".";
|
||||||
|
"tour_section_6_text_8" = "Можно также добавлять чужие плейлисты в свою коллекцию.";
|
||||||
|
|
||||||
|
|
||||||
"tour_section_7_title_1" = "Следите за тем, что пишут ваши друзья";
|
"tour_section_7_title_1" = "Следите за тем, что пишут ваши друзья";
|
||||||
|
|
Loading…
Reference in a new issue