diff --git a/Web/Presenters/AudioPresenter.php b/Web/Presenters/AudioPresenter.php index 313e3c8e..5cc82106 100644 --- a/Web/Presenters/AudioPresenter.php +++ b/Web/Presenters/AudioPresenter.php @@ -63,6 +63,7 @@ final class AudioPresenter extends OpenVKPresenter $this->template->owner = $entity; $this->template->ownerId = $owner; + $this->template->club = $owner < 0 ? $entity : NULL; $this->template->isMy = ($owner > 0 && ($entity->getId() === $this->user->id)); $this->template->isMyClub = ($owner < 0 && $entity->canBeModifiedBy($this->user->identity)); } else if ($mode === "new") { @@ -252,7 +253,7 @@ final class AudioPresenter extends OpenVKPresenter try { $playlist->fastMakeCover($this->user->id, $_FILES["cover"]); - } catch(\ImagickException $e) { + } catch(\Throwable $e) { $this->flashFail("err", tr("error"), tr("invalid_cover_photo")); } } @@ -342,7 +343,7 @@ final class AudioPresenter extends OpenVKPresenter $this->template->playlist = $playlist; $this->template->page = $page; - $audios = iterator_to_array($playlist->getAudios()); + $audios = iterator_to_array($playlist->fetch(1, $playlist->size())); $this->template->audios = array_slice($audios, 0, 10); $audiosIds = []; @@ -448,6 +449,30 @@ final class AudioPresenter extends OpenVKPresenter else $this->flashFail("err", "error", tr("do_not_have_audio"), null, true); + break; + case "remove_club": + $club = (new Clubs)->get((int)$this->postParam("club")); + + if(!$club || !$club->canBeModifiedBy($this->user->identity)) + $this->flashFail("err", "error", tr("access_denied"), null, true); + + if($audio->isInLibraryOf($club)) + $audio->remove($club); + else + $this->flashFail("err", "error", tr("group_hasnt_audio"), null, true); + + break; + case "add_to_club": + $club = (new Clubs)->get((int)$this->postParam("club")); + + if(!$club || !$club->canBeModifiedBy($this->user->identity)) + $this->flashFail("err", "error", tr("access_denied"), null, true); + + if(!$audio->isInLibraryOf($club)) + $audio->add($club); + else + $this->flashFail("err", "error", tr("group_has_audio"), null, true); + break; case "delete": if($audio->canBeModifiedBy($this->user->identity)) @@ -555,7 +580,7 @@ final class AudioPresenter extends OpenVKPresenter $audiosCount = $playlist->size(); break; case "search_context": - $stream = $this->audios->search($this->postParam("query"), 2); + $stream = $this->audios->search($this->postParam("query"), 2, $this->postParam("type") === "by_performer"); $audios = $stream->page($page, 10); $audiosCount = $stream->size(); break; diff --git a/Web/Presenters/templates/Audio/EditPlaylist.xml b/Web/Presenters/templates/Audio/EditPlaylist.xml index bd46efa7..de55d8f6 100644 --- a/Web/Presenters/templates/Audio/EditPlaylist.xml +++ b/Web/Presenters/templates/Audio/EditPlaylist.xml @@ -74,6 +74,11 @@ }) 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 diff --git a/Web/Presenters/templates/Audio/List.xml b/Web/Presenters/templates/Audio/List.xml index 2f904045..2d20932c 100644 --- a/Web/Presenters/templates/Audio/List.xml +++ b/Web/Presenters/templates/Audio/List.xml @@ -55,11 +55,11 @@
- {include "../components/nothing.xml"} + {include "../components/error.xml", description => $ownerId > 0 ? ($ownerId == $thisUser->getId() ? tr("no_audios_thisuser") : tr("no_audios_user")) : tr("no_audios_club")}
- {include "player.xml", audio => $audio} + {include "player.xml", audio => $audio, club => $club}
@@ -89,9 +89,13 @@
- + {ovk_proc_strtr($playlist->getName(), 12)} + + + {ovk_proc_strtr($playlist->getOwner()->getCanonicalName(), 15)} +
diff --git a/Web/Presenters/templates/Audio/NewPlaylist.xml b/Web/Presenters/templates/Audio/NewPlaylist.xml index 93812c05..abbec8ff 100644 --- a/Web/Presenters/templates/Audio/NewPlaylist.xml +++ b/Web/Presenters/templates/Audio/NewPlaylist.xml @@ -22,42 +22,45 @@ -
- -

- +
@@ -694,7 +769,7 @@ $(document).on("click", ".musicIcon.edit-icon", (e) => { e.currentTarget.setAttribute("data-lyrics", response.new_info.lyrics_unformatted) e.currentTarget.setAttribute("data-explicit", Number(response.new_info.explicit)) - e.currentTarget.setAttribute("data-searchable", Number(response.new_info.unlisted)) + e.currentTarget.setAttribute("data-searchable", Number(!response.new_info.unlisted)) player.setAttribute("data-genre", response.new_info.genre) let url = new URL(location.href) @@ -781,6 +856,86 @@ $(document).on("click", ".musicIcon.remove-icon", (e) => { }) }) +$(document).on("click", ".musicIcon.remove-icon-group", (e) => { + 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 body = ` + ${tr("what_club_add")} +
+ + +
+ + ` + MessageBox(tr("add_audio_to_club"), body, [tr("close")], [Function.noop]) + + document.querySelector(".ovk-diag-body").style.padding = "11px" + + if(window.openvk.writeableClubs == null) { + try { + window.openvk.writeableClubs = await API.Groups.getWriteableClubs() + } catch (e) { + document.querySelector(".errorPlace").innerHTML = tr("no_access_clubs") + document.querySelector(".ovk-diag-body input[name='addButton']").classList.add("lagged") + + return + } + } + + window.openvk.writeableClubs.forEach(el => { + document.querySelector("#addIconsWindow").insertAdjacentHTML("beforeend", ` + + `) + }) + + $(".ovk-diag-body").on("click", "input[name='addButton']", (e) => { + $.ajax({ + type: "POST", + url: `/audio${ev.currentTarget.dataset.id}/action?act=add_to_club`, + data: { + hash: u("meta[name=csrf]").attr("value"), + club: document.querySelector("#addIconsWindow").value + }, + beforeSend: () => { + e.currentTarget.classList.add("lagged") + document.querySelector(".errorPlace").innerHTML = "" + }, + success: (response) => { + if(!response.success) + document.querySelector(".errorPlace").innerHTML = response.flash.message + + e.currentTarget.classList.remove("lagged") + } + }) + }) +}) + $(document).on("click", ".musicIcon.add-icon", (e) => { let id = e.currentTarget.dataset.id @@ -836,7 +991,11 @@ $(document).on("click", "#_audioAttachment", (e) => { let form = e.currentTarget.closest("form") let body = `
@@ -847,7 +1006,7 @@ $(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 = "") { + async function insertAudios(page, query = "", type = "by_name") { document.querySelector(".audiosInsert").insertAdjacentHTML("beforeend", ``) $.ajax({ @@ -859,6 +1018,7 @@ $(document).on("click", "#_audioAttachment", (e) => { page: page, query: query == "" ? null : query, context_entity: 0, + type: type, returnPlayers: 1, }, success: (response) => { @@ -911,11 +1071,17 @@ $(document).on("click", "#_audioAttachment", (e) => { if(e.currentTarget.value === document.querySelector(".searchBox input").value) { document.querySelector(".audiosInsert").innerHTML = "" - insertAudios(1, e.currentTarget.value) + insertAudios(1, e.currentTarget.value, document.querySelector(".searchBox select").value) return; } }) + $(".searchBox select").on("change", async (e) => { + document.querySelector(".audiosInsert").innerHTML = "" + insertAudios(1, document.querySelector(".searchBox input").value, e.currentTarget.value) + return; + }) + function insertAttachment(id) { let audios = form.querySelector("input[name='audios']") @@ -1074,7 +1240,7 @@ $(document).on("click", "#bookmarkPlaylist, #unbookmarkPlaylist", (e) => { }) }) -function getPlayers(page = 1, query = "", playlist = 0) { +function getPlayers(page = 1, query = "", playlist = 0, club = 0) { $.ajax({ type: "POST", url: "/audios/context", @@ -1082,12 +1248,12 @@ function getPlayers(page = 1, query = "", playlist = 0) { context: query == "" ? (playlist == 0 ? "entity_audios" : "playlist_context") : "search_context", hash: u("meta[name=csrf]").attr("value"), page: page, - context_entity: playlist, + context_entity: playlist == 0 ? club * -1 : playlist, query: query, returnPlayers: 1, }, beforeSend: () => { - document.querySelector(".playlistAudiosContainer").insertAdjacentHTML("beforeend", ``) + document.querySelector(".playlistAudiosContainer").parentNode.insertAdjacentHTML("beforeend", ``) if(document.querySelector(".showMoreAudiosPlaylist") != null) document.querySelector(".showMoreAudiosPlaylist").style.display = "none" @@ -1143,7 +1309,10 @@ function getPlayers(page = 1, query = "", playlist = 0) { } $(document).on("click", ".showMoreAudiosPlaylist", (e) => { - getPlayers(Number(e.currentTarget.dataset.page), "", e.currentTarget.dataset.playlist != null ? Number(e.currentTarget.dataset.playlist) : 0) + getPlayers(Number(e.currentTarget.dataset.page), "", + 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) => { diff --git a/locales/en.strings b/locales/en.strings index 89cdf891..fc4e2f65 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -728,6 +728,7 @@ "audio" = "Audio"; "playlist" = "Playlist"; "upload_audio" = "Upload audio"; +"upload_audio_to_group" = "Upload audio to group"; "performer" = "Performer"; "audio_name" = "Name"; @@ -778,6 +779,10 @@ "no_playlists_user" = "This user has not added any playlists yet."; "no_playlists_club" = "This group hasn't added playlists yet."; +"no_audios_thisuser" = "You haven't added any audios yet."; +"no_audios_user" = "This user has not added any audios yet."; +"no_audios_club" = "This group has not added any audios yet."; + "new_playlist" = "New playlist"; "created_playlist" = "created"; "bookmark" = "Add to collection"; @@ -807,6 +812,15 @@ "minutes_count_many" = "lasts $1 minutes"; "minutes_count_other" = "lasts $1 minutes"; +"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."; +"group_hasnt_audio" = "This group doesn't have this song."; + +"by_name" = "by name"; +"by_performer" = "by performer"; +"no_access_clubs" = "There are no groups where you are an administrator."; + /* Notifications */ "feedback" = "Feedback"; diff --git a/locales/ru.strings b/locales/ru.strings index b53de206..a035e8f2 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -684,6 +684,7 @@ "audio" = "Аудиозапись"; "playlist" = "Плейлист"; "upload_audio" = "Загрузить аудио"; +"upload_audio_to_group" = "Загрузить аудио в группу"; "performer" = "Исполнитель"; "audio_name" = "Название"; @@ -734,6 +735,10 @@ "no_playlists_user" = "Этот пользователь ещё не добавлял плейлистов."; "no_playlists_club" = "Эта группа ещё не добавляла плейлистов."; +"no_audios_thisuser" = "Вы ещё не добавляли аудиозаписей."; +"no_audios_user" = "Этот пользователь ещё не добавлял аудиозаписей."; +"no_audios_club" = "Эта группа ещё не добавляла аудиозаписей."; + "new_playlist" = "Новый плейлист"; "created_playlist" = "создан"; "bookmark" = "Добавить в коллекцию"; @@ -762,6 +767,15 @@ "minutes_count_many" = "длится $1 минут"; "minutes_count_other" = "длится $1 минут"; +"add_audio_to_club" = "Добавить аудио в группу"; +"what_club_add" = "В какую группу вы хотите добавить песню?"; +"group_has_audio" = "У группы уже есть эта песня."; +"group_hasnt_audio" = "У группы нет этой песни."; + +"by_name" = "по композициям"; +"by_performer" = "по исполнителю"; +"no_access_clubs" = "Нет групп, где вы являетесь администратором."; + /* Notifications */ "feedback" = "Ответы";