- {php $length = $playlist->getLengthInMinutes()}
-
{$playlist->getPublicationTime()}
- {if $length > 0} •
-
- {/if}
+ {$playlist->getMetaDescription()|noescape}
{nl2br($playlist->getDescriptionHTML())|noescape}
diff --git a/Web/static/css/audios.css b/Web/static/css/audios.css
index 098a80b3..7db5a3fa 100644
--- a/Web/static/css/audios.css
+++ b/Web/static/css/audios.css
@@ -42,10 +42,11 @@
width: 22px;
height: 22px;
float: left;
+ background-position-x: -72px;
}
.bigPlayer .paddingLayer .playButtons .playButton.pause {
- background-position-x: -144px;
+ background-position-x: -168px;
}
.bigPlayer .paddingLayer .playButtons .nextButton {
@@ -146,7 +147,7 @@
.bigPlayer .paddingLayer .slider, .audioEmbed .track .slider {
width: 18px;
height: 7px;
- background: #707070;
+ background: #606060;
position: absolute;
bottom: 0;
top: 0px;
@@ -229,7 +230,7 @@
.audioEmbed .track > .selectableTrack, .bigPlayer .selectableTrack {
margin-top: 3px;
width: calc(100% - 8px);
- border-top: #707070 1px solid;
+ border-top: #606060 1px solid;
height: 6px;
position: relative;
user-select: none;
diff --git a/Web/static/img/audio.png b/Web/static/img/audio.png
index c7553692..62d9dff2 100644
Binary files a/Web/static/img/audio.png and b/Web/static/img/audio.png differ
diff --git a/Web/static/js/al_music.js b/Web/static/js/al_music.js
index d7750988..d0bd604d 100644
--- a/Web/static/js/al_music.js
+++ b/Web/static/js/al_music.js
@@ -16,6 +16,50 @@ function getElapsedTime(fullTime, time) {
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,
@@ -60,6 +104,7 @@ class bigPlayer {
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)
@@ -251,10 +296,7 @@ class bigPlayer {
e.currentTarget.classList.toggle("pressed")
- if(e.currentTarget.classList.contains("pressed"))
- this.player().muted = true
- else
- this.player().muted = false
+ this.player().muted = e.currentTarget.classList.contains("pressed")
})
u(".bigPlayer .arrowsButtons .nextButton").on("click", (e) => {
@@ -324,6 +366,31 @@ class bigPlayer {
u(this.player()).on("ended", (e) => {
e.preventDefault()
+ let playlist = this.context.context_type == "playlist_context" ? this.context.context_id : null
+
+ $.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.")
+ }
+ })
+
+ if(!this.tracks.nextTrack) {
+ this.setTrack(this.tracks.tracks[0].id)
+ return
+ }
+
this.showNextTrack()
})
@@ -513,27 +580,6 @@ class bigPlayer {
if(this.timeType == 1)
this.nodes["thisPlayer"].querySelector(".elapsedTime").innerHTML = fmtTime(this.tracks["currentTrack"].length)
- let tempThisTrack = this.tracks["currentTrack"]
- // если трек слушали больше 10 сек.
- setTimeout(() => {
- if(tempThisTrack.id != this.tracks["currentTrack"].id)
- return;
-
- $.ajax({
- type: "POST",
- url: `/audio${id}/listen`,
- data: {
- hash: u("meta[name=csrf]").attr("value"),
- },
- success: (response) => {
- if(response.success)
- console.info("Listen is counted.")
- else
- console.info("Listen is not counted.")
- }
- })
- }, "10000")
-
let album = document.querySelector(".playlistBlock")
navigator.mediaSession.metadata = new MediaMetadata({
@@ -1058,79 +1104,92 @@ $(document).on("click", "#_audioAttachment", (e) => {
document.querySelector(".ovk-diag-cont").style.width = "580px"
document.querySelector(".ovk-diag-body").style.height = "335px"
- async function insertAudios(page, query = "", type = "by_name") {
- document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `

`)
+ let searcher = new playersSearcher("entity_audios", 0)
+ searcher.successCallback = (response, page) => {
+ let domparser = new DOMParser()
+ let result = domparser.parseFromString(response, "text/html")
- $.ajax({
- type: "POST",
- url: "/audios/context",
- data: {
- context: query == "" ? "entity_audios" : "search_context",
- hash: u("meta[name=csrf]").attr("value"),
- page: page,
- query: query == "" ? null : query,
- context_entity: 0,
- type: type,
- returnPlayers: 1,
- },
- success: (response) => {
- 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)
- let pagesCount = result.querySelector("input[name='pagesCount']").value
- let count = Number(result.querySelector("input[name='count']").value)
+ if(count < 1) {
+ document.querySelector(".audiosInsert").innerHTML = tr("no_results")
+ return
+ }
- if(count < 1) {
- document.querySelector(".audiosInsert").innerHTML = 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(page < pagesCount) {
- document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
-
- more...
-
`)
- }
- }
+ 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(this.page < pagesCount) {
+ document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", `
+
+ more...
+
`)
+ }
}
- insertAudios(1)
+ 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()
- insertAudios(Number(e.currentTarget.dataset.page))
+ searcher.movePage(Number(e.currentTarget.dataset.page))
})
$(".searchBox input").on("change", async (e) => {
- await new Promise(r => setTimeout(r, 1000));
+ await new Promise(r => setTimeout(r, 500));
if(e.currentTarget.value === document.querySelector(".searchBox input").value) {
- document.querySelector(".audiosInsert").innerHTML = ""
- insertAudios(1, e.currentTarget.value, document.querySelector(".searchBox select").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) => {
- document.querySelector(".audiosInsert").innerHTML = ""
- insertAudios(1, document.querySelector(".searchBox input").value, e.currentTarget.value)
+ searcher.clearContainer()
+ searcher.searchType = e.currentTarget.value
+
+ $(".searchBox input").trigger("change")
return;
})
@@ -1296,99 +1355,3 @@ $(document).on("click", "#bookmarkPlaylist, #unbookmarkPlaylist", (e) => {
}
})
})
-
-function getPlayers(page = 1, query = "", playlist = 0, club = 0) {
- $.ajax({
- type: "POST",
- url: "/audios/context",
- data: {
- context: query == "" ? (playlist == 0 ? "entity_audios" : "playlist_context") : "search_context",
- hash: u("meta[name=csrf]").attr("value"),
- page: page,
- context_entity: playlist == 0 ? club * -1 : playlist,
- query: query,
- returnPlayers: 1,
- },
- beforeSend: () => {
- document.querySelector(".playlistAudiosContainer").parentNode.insertAdjacentHTML("beforeend", `

`)
-
- if(document.querySelector(".showMoreAudiosPlaylist") != null)
- document.querySelector(".showMoreAudiosPlaylist").style.display = "none"
- },
- error: () => {
- fastError("Error when loading players")
- },
- success: (response) => {
- let domparser = new DOMParser()
- let result = domparser.parseFromString(response, "text/html")
- let pagesCount = Number(result.querySelector("input[name='pagesCount']").value)
- let count = Number(result.querySelector("input[name='count']").value)
-
- result.querySelectorAll(".audioEmbed").forEach(el => {
- let id = Number(el.dataset.realid)
- let isAttached = (document.querySelector("input[name='audios']").value.includes(`${id},`))
-
- document.querySelector(".playlistAudiosContainer").insertAdjacentHTML("beforeend", `
-
-
- ${el.outerHTML}
-
-
- ${isAttached ? tr("remove_from_playlist") : tr("add_to_playlist")}
-
-
- `)
- })
-
- if(count < 1)
- document.querySelector(".playlistAudiosContainer").insertAdjacentHTML("beforeend", `
- ${tr("no_results")}
- `)
-
- if(Number(page) >= pagesCount)
- u(".showMoreAudiosPlaylist").remove()
- else {
- if(document.querySelector(".showMoreAudiosPlaylist") != null) {
- document.querySelector(".showMoreAudiosPlaylist").setAttribute("data-page", page + 1)
-
- if(query != "") {
- document.querySelector(".showMoreAudiosPlaylist").setAttribute("data-query", query)
- }
-
- document.querySelector(".showMoreAudiosPlaylist").style.display = "block"
- } else {
- document.querySelector(".playlistAudiosContainer").parentNode.insertAdjacentHTML("beforeend", `
-
- ${tr("show_more_audios")}
-
- `)
- }
- }
-
- u("#loader").remove()
- }
- })
-}
-
-$(document).on("click", ".showMoreAudiosPlaylist", (e) => {
- getPlayers(Number(e.currentTarget.dataset.page),
- e.currentTarget.dataset.query != null ? e.currentTarget.dataset.query : "",
- e.currentTarget.dataset.playlist != null ? Number(e.currentTarget.dataset.playlist) : 0,
- e.currentTarget.dataset.club != null ? Number(e.currentTarget.dataset.club) : 0,
- )
-})
-
-$(document).on("change", "input#playlist_query", async (e) => {
- e.preventDefault()
- await new Promise(r => setTimeout(r, 500));
-
- if(e.currentTarget.value === document.querySelector("input#playlist_query").value) {
- document.querySelector(".playlistAudiosContainer").innerHTML = ""
- getPlayers(1, e.currentTarget.value)
- return
- } else
- return
-})
diff --git a/Web/static/js/al_playlists.js b/Web/static/js/al_playlists.js
new file mode 100644
index 00000000..1316e96b
--- /dev/null
+++ b/Web/static/js/al_playlists.js
@@ -0,0 +1,113 @@
+let context_type = "entity_audios"
+let context_id = 0
+
+if(document.querySelector("#editPlaylistForm")) {
+ context_type = "playlist_context"
+ context_id = document.querySelector("#editPlaylistForm").dataset.id
+}
+
+if(document.querySelector(".showMoreAudiosPlaylist").dataset.club != null) {
+ context_type = "entity_audios"
+ context_id = Number(document.querySelector(".showMoreAudiosPlaylist").dataset.club) * -1
+}
+
+let searcher = new playersSearcher(context_type, context_id)
+
+searcher.successCallback = (response, thisc) => {
+ let domparser = new DOMParser()
+ let result = domparser.parseFromString(response, "text/html")
+ let pagesCount = Number(result.querySelector("input[name='pagesCount']").value)
+ let count = Number(result.querySelector("input[name='count']").value)
+
+ result.querySelectorAll(".audioEmbed").forEach(el => {
+ let id = Number(el.dataset.realid)
+ let isAttached = (document.querySelector("input[name='audios']").value.includes(`${id},`))
+
+ document.querySelector(".playlistAudiosContainer").insertAdjacentHTML("beforeend", `
+
+
+ ${el.outerHTML}
+
+
+ ${isAttached ? tr("remove_from_playlist") : tr("add_to_playlist")}
+
+
+ `)
+ })
+
+ if(count < 1)
+ document.querySelector(".playlistAudiosContainer").insertAdjacentHTML("beforeend", `
+ ${tr("no_results")}
+ `)
+
+ if(Number(thisc.page) >= pagesCount)
+ u(".showMoreAudiosPlaylist").remove()
+ else {
+ if(document.querySelector(".showMoreAudiosPlaylist") != null) {
+ document.querySelector(".showMoreAudiosPlaylist").setAttribute("data-page", thisc.page + 1)
+
+ if(thisc.query != "") {
+ document.querySelector(".showMoreAudiosPlaylist").setAttribute("data-query", thisc.query)
+ }
+
+ document.querySelector(".showMoreAudiosPlaylist").style.display = "block"
+ } else {
+ document.querySelector(".playlistAudiosContainer").parentNode.insertAdjacentHTML("beforeend", `
+
+ ${tr("show_more_audios")}
+
+ `)
+ }
+ }
+
+ u("#loader").remove()
+}
+
+searcher.beforesendCallback = () => {
+ document.querySelector(".playlistAudiosContainer").parentNode.insertAdjacentHTML("beforeend", `

`)
+
+ if(document.querySelector(".showMoreAudiosPlaylist") != null)
+ document.querySelector(".showMoreAudiosPlaylist").style.display = "none"
+}
+
+searcher.errorCallback = () => {
+ fastError("Error when loading players")
+}
+
+searcher.clearContainer = () => {
+ document.querySelector(".playlistAudiosContainer").innerHTML = ""
+}
+
+$(document).on("click", ".showMoreAudiosPlaylist", (e) => {
+ searcher.movePage(Number(e.currentTarget.dataset.page))
+})
+
+$(document).on("change", "input#playlist_query", async (e) => {
+ e.preventDefault()
+
+ await new Promise(r => setTimeout(r, 500));
+
+ if(e.currentTarget.value === document.querySelector("input#playlist_query").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;
+ }
+})
\ No newline at end of file
diff --git a/locales/en.strings b/locales/en.strings
index 2feabd4c..2e35498f 100644
--- a/locales/en.strings
+++ b/locales/en.strings
@@ -786,6 +786,7 @@
"new_playlist" = "New playlist";
"created_playlist" = "created";
+"updated_playlist" = "updated";
"bookmark" = "Add to collection";
"unbookmark" = "Remove from collection";
"empty_playlist" = "There are no audios in this playlist.";
@@ -813,6 +814,12 @@
"minutes_count_many" = "lasts $1 minutes";
"minutes_count_other" = "lasts $1 minutes";
+"listens_count_zero" = "no listens";
+"listens_count_one" = "one listen";
+"listens_count_few" = "$1 listens";
+"listens_count_many" = "$1 listens";
+"listens_count_other" = "$1 listens";
+
"add_audio_to_club" = "Add audio to group";
"what_club_add" = "Which group do you want to add the song to?";
"group_has_audio" = "This group already has this song.";
diff --git a/locales/ru.strings b/locales/ru.strings
index 58b16417..ab9d9a02 100644
--- a/locales/ru.strings
+++ b/locales/ru.strings
@@ -742,6 +742,7 @@
"new_playlist" = "Новый плейлист";
"created_playlist" = "создан";
+"updated_playlist" = "обновлён";
"bookmark" = "Добавить в коллекцию";
"unbookmark" = "Убрать из коллекции";
"empty_playlist" = "В этом плейлисте нет аудиозаписей.";
@@ -768,6 +769,12 @@
"minutes_count_many" = "длится $1 минут";
"minutes_count_other" = "длится $1 минут";
+"listens_count_zero" = "нет прослушиваний";
+"listens_count_one" = "одно прослушивание";
+"listens_count_few" = "$1 прослушивания";
+"listens_count_many" = "$1 прослушиваний";
+"listens_count_other" = "$1 прослушиваний";
+
"add_audio_to_club" = "Добавить аудио в группу";
"what_club_add" = "В какую группу вы хотите добавить песню?";
"group_has_audio" = "У группы уже есть эта песня.";