From 535809f5764e2768611a046a534be7c87e7affed Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 14 Mar 2026 16:15:07 +0100 Subject: [PATCH] Added an optional role filter for 'appears on' section the artist views, fixes #824 --- approot/artist.xml | 28 ++++++ approot/messages.xml | 77 ++++++++------- approot/messages_es.xml | 77 ++++++++------- approot/messages_fr.xml | 77 ++++++++------- approot/messages_it.xml | 77 ++++++++------- approot/messages_pl.xml | 95 +++++++++---------- approot/messages_zh.xml | 23 +++-- src/lms/CMakeLists.txt | 1 + src/lms/ui/SettingsView.cpp | 14 +-- src/lms/ui/Utils.cpp | 28 +++--- src/lms/ui/explore/ArtistTypeSelector.hpp | 20 ++-- src/lms/ui/explore/ArtistView.cpp | 81 +++++++++++++--- src/lms/ui/explore/ArtistView.hpp | 5 +- .../ui/explore/TrackArtistTypeSelector.cpp | 60 ++++++++++++ .../ui/explore/TrackArtistTypeSelector.hpp | 35 +++++++ 15 files changed, 436 insertions(+), 262 deletions(-) create mode 100644 src/lms/ui/explore/TrackArtistTypeSelector.cpp create mode 100644 src/lms/ui/explore/TrackArtistTypeSelector.hpp diff --git a/approot/artist.xml b/approot/artist.xml index 00c4f3a0..5dc68238 100644 --- a/approot/artist.xml +++ b/approot/artist.xml @@ -50,4 +50,32 @@ + +
+

${tr:Lms.Explore.Artist.appears-on}${artist-type class="ms-2 d-inline-block"}

+ ${releases} +
+
+ + + + + + diff --git a/approot/messages.xml b/approot/messages.xml index 1bcfd5f8..f9484c1b 100644 --- a/approot/messages.xml +++ b/approot/messages.xml @@ -196,9 +196,19 @@ Add filter All +All artists +All roles Artists Bitrate Codec + + Composer + Composers + + + Conductor + Conductors + Copyright Cover art Download @@ -206,26 +216,54 @@ Filter added Filters Label + + Lyricist + Lyricists + Music Library + + Mixer + Mixers + Most played MusicBrainz Artist MusicBrainz Release + + Performer + Performers + Play Play last Play next Play shuffled Play count + + Producer + Producers + Random Recently added Recently modified Recently played + + Album artist + Album artists + Release information Release type Albums + + Remixer + Remixers + Search Star Star {1} Starred + + Track artist + Track artists + Track information Lyrics Playlists @@ -241,45 +279,6 @@ Biography Similar artists - -All artists - - Composer - Composers - - - Conductor - Conductors - - - Lyricist - Lyricists - - - Mixer - Mixers - - - Performer - Performers - - - Producer - Producers - - - Album artist - Album artists - - - Remixer - Remixers - - - Track artist - Track artists - - Copyright Disc {1} diff --git a/approot/messages_es.xml b/approot/messages_es.xml index 75a7c8e1..81b586f8 100644 --- a/approot/messages_es.xml +++ b/approot/messages_es.xml @@ -196,9 +196,19 @@ Añadir filtro Todos +Todos los artistas +Todos los roles Artistas Bitrate Codec + + Compositor + Compositores + + + Director de orquesta + Directores de orquesta + Derechos de autor Carátula Descargar @@ -206,26 +216,54 @@ Filtro añadido Filtros Sello discográfico + + Letrista + Letristas + Biblioteca musical + + Mezclador + Mezcladores + Reproducidos frecuentemente Artista de MusicBrainz Álbum de MusicBrainz + + Intérprete + Intérpretes + Reproducir Reproducir al final Reproducir a continuación Reproducción aleatoria Número de reproducciones + + Productor + Productores + Aleatorio Añadidos recientemente Modificados recientemente Reproducidos recientemente + + Artista del álbum + Artistas del álbum + Información sobre el álbum Tipo de publicación Álbumes + + Remezclador + Remezcladores + Buscar Añadir a favoritos Agregar {1} a favoritos Favoritos + + Artista de la pista + Artistas de la pista + Información sobre la pista Letras Listas de reproducción @@ -241,45 +279,6 @@ Biografía Artistas similares - -Todos los artistas - - Compositor - Compositores - - - Director de orquesta - Directores de orquesta - - - Letrista - Letristas - - - Mezclador - Mezcladores - - - Intérprete - Intérpretes - - - Productor - Productores - - - Artista del álbum - Artistas del álbum - - - Remezclador - Remezcladores - - - Artista de la pista - Artistas de la pista - - Copyright Disco {1} diff --git a/approot/messages_fr.xml b/approot/messages_fr.xml index e77abe2b..af320285 100644 --- a/approot/messages_fr.xml +++ b/approot/messages_fr.xml @@ -196,9 +196,19 @@ Ajouter filtre Tous +Tous les artistes +Tous les rôles Artistes Bitrate Codec + + Compositeur + Compositeurs + + + Chef d'orchestre + Chefs d'orchestre + Droits d'auteur Pochette Télécharger @@ -206,26 +216,54 @@ Filtre ajouté Filtres Label + + Parolier + Paroliers + Bibliothèque musicale + + Mixeur + Mixeurs + Plus joués MusicBrainz Artist MusicBrainz Release + + Interprète + Interprètes + Jouer Jouer en dernier Jouer ensuite Jouer aléatoirement Nombre d'écoutes + + Producteur + Producteurs + Aléatoire Ajoutés récemment Modifiés récemment Joués récemment + + Artiste d'album + Artistes d'album + Informations sur l'album Type de publication Albums + + Remixeur + Remixeurs + Rechercher Ajouter aux favoris Ajouter {1} aux favoris Favoris + + Artiste de piste + Artistes de piste + Informations sur la piste Paroles Playlists @@ -241,45 +279,6 @@ Biographie Artistes similaires - -Tous les artistes - - Compositeur - Compositeurs - - - Chef d'orchestre - Chefs d'orchestre - - - Parolier - Paroliers - - - Mixeur - Mixeurs - - - Interprète - Interprètes - - - Producteur - Producteurs - - - Artiste d'album - Artistes d'album - - - Remixeur - Remixeurs - - - Artiste de piste - Artistes de piste - - Copyright Disque {1} diff --git a/approot/messages_it.xml b/approot/messages_it.xml index 5eba39d8..0254d1cc 100644 --- a/approot/messages_it.xml +++ b/approot/messages_it.xml @@ -196,9 +196,19 @@ Aggiungi filtro Tutti +Tutti gli artisti +Tutti i ruoli Artisti Bitrate Codec + + Compositore + Compositori + + + Direttore d'orchestra + Direttori d'orchestra + Diritti d'autore Copertina Download @@ -206,26 +216,54 @@ Filtro aggiunto Filtri Etichetta + + Paroliere + Parolieri + Libreria musicale + + Tecnico del mixaggio + Tecnici del mixaggio + Più ascoltati Artista MusicBrainz Album MusicBrainz + + Interprete + Interpreti + Riproduci Aggiungi alla coda di riproduzione Riproduci successiva Riproduci mischiando Conteggio riproduzioni + + Produttore + Produttori + Casuali Aggiunti di recente Modificati di recente Riprodotti di recente + + Artista dell'album + Artisti dell'album + Informazioni sull'album Tipo di pubblicazione Album + + Remixer + Remixers + Ricerca Aggiungi ai preferiti Aggiungi {1} ai preferiti Preferiti + + Artista della traccia + Artisti della traccia + Informazioni sulla traccia Testo Playlist @@ -241,45 +279,6 @@ Biografia Artisti simili - -Tutti gli artisti - - Compositore - Compositori - - - Direttore d'orchestra - Direttori d'orchestra - - - Paroliere - Parolieri - - - Tecnico del mixaggio - Tecnici del mixaggio - - - Interprete - Interpreti - - - Produttore - Produttori - - - Artista dell'album - Artisti dell'album - - - Remixer - Remixers - - - Artista della traccia - Artisti della traccia - - Copyright Disco {1} diff --git a/approot/messages_pl.xml b/approot/messages_pl.xml index 08181d06..48dd4b72 100644 --- a/approot/messages_pl.xml +++ b/approot/messages_pl.xml @@ -213,9 +213,21 @@ Dodaj filtr Wszystko +Wszyscy artyści +Wszystkie role Artyści Przepływność Kodek + + Kompozytor + Kompozytorzy + Kompozytorów + + + Dyrygent + Dyrygenci + Dyrygentów + Prawa autorskie Okładka Pobierz @@ -223,26 +235,61 @@ Filtr dodany Filtry Wytwórnia + + Tekściarz + Tekściarze + Tekściarzy + Biblioteka muzyczna + + Mikser + Mikserzy + Mikserów + Najczęściej odtwarzane Artysta w MusicBrainz Wydanie w MusicBrainz + + Wykonawca + Wykonawcy + Wykonawców + Odtwarzaj Odtwórz na końcu Odtwórz po obecnym Odtwarzaj losowo Liczba odtworzeń + + Producent + Producenci + Producentów + Losowo Ostatnio dodane Ostatnio zmienione Ostatnio odtwarzane + + Artysta albumu + Artyści albumu + Artystów albumu + Informacje o wydaniu Typ wydania Albumy + + Remikser + Remikserzy + Remikserów + Szukaj Wyróżnij Dodaj {1} do ulubionych Wyróżnione + + Artysta utworu + Artyści utworu + Artystów utworu + Informacje o ścieżce Tekst Listy odtwarzania @@ -258,54 +305,6 @@ Biografia Podobni artyści - -Wszyscy artyści - - Kompozytor - Kompozytorzy - Kompozytorzy - - - Dyrygent - Dyrygenci - Dyrygenci - - - Tekściarz - Tekściarze - Tekściarze - - - Realizator - Realizatorzy - Realizatorzy - - - Wykonawca - Wykonawcy - Wykonawcy - - - Producent - Producenci - Producenci - - - Artysta z albumu - Artyści z albumu - Artyści z albumu - - - Remixer - Remikserzy - Remikserzy - - - Artysta ze ścieżki - Artyści ze ścieżki - Artyści ze ścieżki - - Prawa autorskie Dysk {1} diff --git a/approot/messages_zh.xml b/approot/messages_zh.xml index ee81802d..810d2c4a 100644 --- a/approot/messages_zh.xml +++ b/approot/messages_zh.xml @@ -194,9 +194,13 @@ 添加过滤器 全部 +所有艺术家 +所有角色 歌手 比特率 编码器 +作曲者 +指挥 版权所有 封面 下载 @@ -204,26 +208,33 @@ 过滤器已添加 过滤器 厂牌 +作词者 音乐库 +混音师 播放最多 MusicBrainz 歌手 MusicBrainz 专辑 +表演者 播放 最后播放 下一首播放 随机播放 播放次数 +制作人 随机 最近添加 最近更改 最近播放 +专辑艺术家 专辑信息 专辑类型 专辑 +混音师 搜索 收藏 将 {1} 加入收藏 已收藏 +曲目艺术家 曲目信息 歌词 播放列表 @@ -239,18 +250,6 @@ 简介 相似歌手 - -所有艺术家 -作曲者 -指挥 -作词者 -混音师 -表演者 -制作人 -专辑艺术家 -混音师 -曲目艺术家 - 版权所有 唱片 {1} diff --git a/src/lms/CMakeLists.txt b/src/lms/CMakeLists.txt index 699d0662..a2dec023 100644 --- a/src/lms/CMakeLists.txt +++ b/src/lms/CMakeLists.txt @@ -49,6 +49,7 @@ add_executable(lms ui/explore/ReleasesView.cpp ui/explore/ReleaseView.cpp ui/explore/ReleaseTypes.cpp + ui/explore/TrackArtistTypeSelector.cpp ui/explore/TrackCollector.cpp ui/explore/TrackListHelpers.cpp ui/explore/TrackListView.cpp diff --git a/src/lms/ui/SettingsView.cpp b/src/lms/ui/SettingsView.cpp index 158064a3..4be8126c 100644 --- a/src/lms/ui/SettingsView.cpp +++ b/src/lms/ui/SettingsView.cpp @@ -459,13 +459,13 @@ namespace lms::ui _artistReleaseSortMethodModel->add(Wt::WString::tr("Lms.Settings.name"), db::ReleaseSortMethod::Name); _artistRelationshipsModel = std::make_shared(); - _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.Artists.composer", 2), db::TrackArtistLinkType::Composer); - _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.Artists.conductor", 2), db::TrackArtistLinkType::Conductor); - _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.Artists.lyricist", 2), db::TrackArtistLinkType::Lyricist); - _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.Artists.mixer", 2), db::TrackArtistLinkType::Mixer); - _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.Artists.performer", 2), db::TrackArtistLinkType::Performer); - _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.Artists.producer", 2), db::TrackArtistLinkType::Producer); - _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.Artists.remixer", 2), db::TrackArtistLinkType::Remixer); + _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.composer", 2), db::TrackArtistLinkType::Composer); + _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.conductor", 2), db::TrackArtistLinkType::Conductor); + _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.lyricist", 2), db::TrackArtistLinkType::Lyricist); + _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.mixer", 2), db::TrackArtistLinkType::Mixer); + _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.performer", 2), db::TrackArtistLinkType::Performer); + _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.producer", 2), db::TrackArtistLinkType::Producer); + _artistRelationshipsModel->add(Wt::WString::trn("Lms.Explore.remixer", 2), db::TrackArtistLinkType::Remixer); _transcodingModeModeModel = std::make_shared(); _transcodingModeModeModel->add(Wt::WString::tr("Lms.Settings.transcoding-mode.always"), MediaPlayer::Settings::Transcoding::Mode::Always); diff --git a/src/lms/ui/Utils.cpp b/src/lms/ui/Utils.cpp index f2241c3c..f61dd1f7 100644 --- a/src/lms/ui/Utils.cpp +++ b/src/lms/ui/Utils.cpp @@ -407,17 +407,17 @@ namespace lms::ui::utils }); }; - addArtists(db::TrackArtistLinkType::Composer, "Lms.Explore.Artists.composer"); - addArtists(db::TrackArtistLinkType::Conductor, "Lms.Explore.Artists.conductor"); - addArtists(db::TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.lyricist"); - addArtists(db::TrackArtistLinkType::Mixer, "Lms.Explore.Artists.mixer"); - addArtists(db::TrackArtistLinkType::Remixer, "Lms.Explore.Artists.remixer"); - addArtists(db::TrackArtistLinkType::Producer, "Lms.Explore.Artists.producer"); + addArtists(db::TrackArtistLinkType::Composer, "Lms.Explore.composer"); + addArtists(db::TrackArtistLinkType::Conductor, "Lms.Explore.conductor"); + addArtists(db::TrackArtistLinkType::Lyricist, "Lms.Explore.lyricist"); + addArtists(db::TrackArtistLinkType::Mixer, "Lms.Explore.mixer"); + addArtists(db::TrackArtistLinkType::Remixer, "Lms.Explore.remixer"); + addArtists(db::TrackArtistLinkType::Producer, "Lms.Explore.producer"); addPerformerArtists(); if (!rolelessPerformers.empty()) { - Wt::WString performersStr{ Wt::WString::trn("Lms.Explore.Artists.performer", rolelessPerformers.size()) }; + Wt::WString performersStr{ Wt::WString::trn("Lms.Explore.performer", rolelessPerformers.size()) }; artistMap[performersStr] = std::move(rolelessPerformers); } @@ -458,17 +458,17 @@ namespace lms::ui::utils }); }; - addArtists(db::TrackArtistLinkType::Composer, "Lms.Explore.Artists.composer"); - addArtists(db::TrackArtistLinkType::Conductor, "Lms.Explore.Artists.conductor"); - addArtists(db::TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.lyricist"); - addArtists(db::TrackArtistLinkType::Mixer, "Lms.Explore.Artists.mixer"); - addArtists(db::TrackArtistLinkType::Remixer, "Lms.Explore.Artists.remixer"); - addArtists(db::TrackArtistLinkType::Producer, "Lms.Explore.Artists.producer"); + addArtists(db::TrackArtistLinkType::Composer, "Lms.Explore.composer"); + addArtists(db::TrackArtistLinkType::Conductor, "Lms.Explore.conductor"); + addArtists(db::TrackArtistLinkType::Lyricist, "Lms.Explore.lyricist"); + addArtists(db::TrackArtistLinkType::Mixer, "Lms.Explore.mixer"); + addArtists(db::TrackArtistLinkType::Remixer, "Lms.Explore.remixer"); + addArtists(db::TrackArtistLinkType::Producer, "Lms.Explore.producer"); addPerformerArtists(); if (!rolelessPerformers.empty()) { - Wt::WString performersStr{ Wt::WString::trn("Lms.Explore.Artists.performer", rolelessPerformers.size()) }; + Wt::WString performersStr{ Wt::WString::trn("Lms.Explore.performer", rolelessPerformers.size()) }; artistMap[performersStr] = std::move(rolelessPerformers); } diff --git a/src/lms/ui/explore/ArtistTypeSelector.hpp b/src/lms/ui/explore/ArtistTypeSelector.hpp index aaa56726..aceca46d 100644 --- a/src/lms/ui/explore/ArtistTypeSelector.hpp +++ b/src/lms/ui/explore/ArtistTypeSelector.hpp @@ -30,16 +30,16 @@ namespace lms::ui ArtistTypeSelector(ArtistType defaultArtistType) : DropDownMenuSelector{ Wt::WString::tr("Lms.Explore.Artists.template.artist-type-selector"), defaultArtistType } { - bindItem("artist-type-all", Wt::WString::tr("Lms.Explore.Artists.all"), AllArtistsTag{}); - bindItem("artist-type-release-artist", Wt::WString::trn("Lms.Explore.Artists.release-artist", 2), ReleaseArtistsTag{}); - bindItem("artist-type-track-artist", Wt::WString::trn("Lms.Explore.Artists.track-artist", 2), db::TrackArtistLinkType::Artist); - bindItem("artist-type-composer", Wt::WString::trn("Lms.Explore.Artists.composer", 2), db::TrackArtistLinkType::Composer); - bindItem("artist-type-conductor", Wt::WString::trn("Lms.Explore.Artists.conductor", 2), db::TrackArtistLinkType::Conductor); - bindItem("artist-type-lyricist", Wt::WString::trn("Lms.Explore.Artists.lyricist", 2), db::TrackArtistLinkType::Lyricist); - bindItem("artist-type-mixer", Wt::WString::trn("Lms.Explore.Artists.mixer", 2), db::TrackArtistLinkType::Mixer); - bindItem("artist-type-performer", Wt::WString::trn("Lms.Explore.Artists.performer", 2), db::TrackArtistLinkType::Performer); - bindItem("artist-type-producer", Wt::WString::trn("Lms.Explore.Artists.producer", 2), db::TrackArtistLinkType::Producer); - bindItem("artist-type-remixer", Wt::WString::trn("Lms.Explore.Artists.remixer", 2), db::TrackArtistLinkType::Remixer); + bindItem("artist-type-all", Wt::WString::tr("Lms.Explore.all-artists"), AllArtistsTag{}); + bindItem("artist-type-release-artist", Wt::WString::trn("Lms.Explore.release-artist", 2), ReleaseArtistsTag{}); + bindItem("artist-type-track-artist", Wt::WString::trn("Lms.Explore.track-artist", 2), db::TrackArtistLinkType::Artist); + bindItem("artist-type-composer", Wt::WString::trn("Lms.Explore.composer", 2), db::TrackArtistLinkType::Composer); + bindItem("artist-type-conductor", Wt::WString::trn("Lms.Explore.conductor", 2), db::TrackArtistLinkType::Conductor); + bindItem("artist-type-lyricist", Wt::WString::trn("Lms.Explore.lyricist", 2), db::TrackArtistLinkType::Lyricist); + bindItem("artist-type-mixer", Wt::WString::trn("Lms.Explore.mixer", 2), db::TrackArtistLinkType::Mixer); + bindItem("artist-type-performer", Wt::WString::trn("Lms.Explore.performer", 2), db::TrackArtistLinkType::Performer); + bindItem("artist-type-producer", Wt::WString::trn("Lms.Explore.producer", 2), db::TrackArtistLinkType::Producer); + bindItem("artist-type-remixer", Wt::WString::trn("Lms.Explore.remixer", 2), db::TrackArtistLinkType::Remixer); } }; } // namespace lms::ui diff --git a/src/lms/ui/explore/ArtistView.cpp b/src/lms/ui/explore/ArtistView.cpp index 98096848..c3073f1f 100644 --- a/src/lms/ui/explore/ArtistView.cpp +++ b/src/lms/ui/explore/ArtistView.cpp @@ -19,7 +19,10 @@ #include "ArtistView.hpp" +#include + #include +#include #include "core/String.hpp" #include "database/Session.hpp" @@ -30,6 +33,8 @@ #include "database/objects/Release.hpp" #include "database/objects/ScanSettings.hpp" #include "database/objects/Track.hpp" +#include "database/objects/TrackArtistLink.hpp" +#include "database/objects/Types.hpp" #include "database/objects/User.hpp" #include "services/feedback/IFeedbackService.hpp" #include "services/recommendation/IRecommendationService.hpp" @@ -40,6 +45,7 @@ #include "LmsApplicationException.hpp" #include "PlayQueueController.hpp" #include "ReleaseHelpers.hpp" +#include "TrackArtistTypeSelector.hpp" #include "TrackListHelpers.hpp" #include "Utils.hpp" #include "common/InfiniteScrollingContainer.hpp" @@ -272,30 +278,77 @@ namespace lms::ui void Artist::refreshAppearsOnReleases() { + _appearsOnReleases.clear(); _appearsOnReleaseContainer = {}; - db::Release::FindParameters params; - params.setTrackArtist(_artistId); - params.setSortMethod(db::ReleaseSortMethod::OriginalDateDesc); + auto addToReleaseContainer = [&](std::optional linkType) -> bool { + db::Release::FindParameters params; - db::Release::find(LmsApp->getDbSession(), params, [this](const db::Release::pointer& release) { - if (!release->hasArtist(_artistId)) - _appearsOnReleaseContainer.releases.push_back(release->getId()); - }); + core::EnumSet linkTypes; + if (linkType) + linkTypes.insert(*linkType); - if (!_appearsOnReleaseContainer.releases.empty()) + params.setTrackArtist(_artistId, linkTypes); + params.setSortMethod(db::ReleaseSortMethod::OriginalDateDesc); + + bool found{}; + db::Release::find(LmsApp->getDbSession(), params, [&](const db::Release::pointer& release) { + if (release->hasArtist(_artistId)) + return; + + _appearsOnReleases[linkType].push_back(release->getId()); + found = true; + }); + + return found; + }; + + constexpr std::array, 9> types{ + std::nullopt, + db::TrackArtistLinkType::Artist, + db::TrackArtistLinkType::Composer, + db::TrackArtistLinkType::Conductor, + db::TrackArtistLinkType::Lyricist, + db::TrackArtistLinkType::Mixer, + db::TrackArtistLinkType::Performer, + db::TrackArtistLinkType::Producer, + db::TrackArtistLinkType::Remixer, + }; + + core::EnumSet foundTypes; + for (const auto type : types) { - Wt::WTemplate* releaseContainer{ bindNew("appears-on-releases", Wt::WString::tr("Lms.Explore.Artist.template.release-container")) }; - releaseContainer->bindString("release-type", Wt::WString::tr("Lms.Explore.Artist.appears-on")); - _appearsOnReleaseContainer.container = releaseContainer->bindNew("releases", Wt::WString::tr("Lms.Explore.Releases.template.container")); - _appearsOnReleaseContainer.container->onRequestElements.connect(this, [this] { + if (addToReleaseContainer(type) && type) + foundTypes.insert(*type); + } + + if (!_appearsOnReleases.empty()) + { + std::optional defaultType{ std::nullopt }; + if (_appearsOnReleases.size() == 2) + { + auto it{ std::find_if(std::cbegin(_appearsOnReleases), std::cend(_appearsOnReleases), [=](const auto& entry) { return entry.first != defaultType; }) }; + if (it != std::cend(_appearsOnReleases)) + defaultType = it->first; + } + + Wt::WTemplate* appearsOnContainer{ bindNew("appears-on-releases", Wt::WString::tr("Lms.Explore.Artist.template.appears-on-container")) }; + appearsOnContainer->addFunction("tr", &Wt::WTemplate::Functions::tr); + + _appearsOnReleaseContainer.container = appearsOnContainer->bindNew("releases", Wt::WString::tr("Lms.Explore.Releases.template.container")); + _appearsOnReleaseContainer.releases = _appearsOnReleases[defaultType]; + _appearsOnReleaseContainer.container->onRequestElements.connect(this, [&] { addSomeReleases(_appearsOnReleaseContainer, { releaseListHelpers::DisplayOptions::ShowYearAndOriginalYear, releaseListHelpers::DisplayOptions::ShowArtist }); }); + + TrackArtistTypeSelector* trackArtistTypeSelector{ appearsOnContainer->bindNew("artist-type", defaultType, foundTypes) }; + trackArtistTypeSelector->itemSelected.connect([this](std::optional newArtistLinkType) { + _appearsOnReleaseContainer.releases = _appearsOnReleases[newArtistLinkType]; + _appearsOnReleaseContainer.container->reset(); + }); } else - { bindEmpty("appears-on-releases"); - } } void Artist::refreshNonReleaseTracks() diff --git a/src/lms/ui/explore/ArtistView.hpp b/src/lms/ui/explore/ArtistView.hpp index ebd8877c..47d37c63 100644 --- a/src/lms/ui/explore/ArtistView.hpp +++ b/src/lms/ui/explore/ArtistView.hpp @@ -20,6 +20,7 @@ #pragma once #include +#include #include "core/EnumSet.hpp" @@ -31,6 +32,7 @@ #include "ReleaseHelpers.hpp" #include "ReleaseTypes.hpp" #include "common/Template.hpp" +#include "database/objects/Types.hpp" namespace lms::db { @@ -76,7 +78,8 @@ namespace lms::ui std::vector releases; }; std::map _releaseContainers; - ReleaseContainer _appearsOnReleaseContainer{}; + std::map, std::vector> _appearsOnReleases; + ReleaseContainer _appearsOnReleaseContainer; InfiniteScrollingContainer* _trackContainer{}; db::ArtistId _artistId{}; std::string _artistName; diff --git a/src/lms/ui/explore/TrackArtistTypeSelector.cpp b/src/lms/ui/explore/TrackArtistTypeSelector.cpp new file mode 100644 index 00000000..6b41f104 --- /dev/null +++ b/src/lms/ui/explore/TrackArtistTypeSelector.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2026 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#include "TrackArtistTypeSelector.hpp" + +#include + +namespace lms::ui +{ + TrackArtistTypeSelector::TrackArtistTypeSelector(std::optional defaultRole, core::EnumSet types) + : DropDownMenuSelector{ Wt::WString::tr("Lms.Explore.Artist.template.track-artist-type-selector"), defaultRole } + { + struct Entry + { + std::string var; + Wt::WString title; + std::optional linkType; + core::LiteralString condition; + }; + + auto bindItemWithCondition = [&](const std::string& var, const Wt::WString& title, std::optional item, core::LiteralString condition) { + if (!condition.empty()) + setCondition(condition.c_str(), true); + bindItem(var, title, item); + }; + const std::array entries{ + Entry{ "artist-type-all", Wt::WString::tr("Lms.Explore.all-roles"), std::nullopt, core::LiteralString{} }, + Entry{ "artist-type-track-artist", Wt::WString::trn("Lms.Explore.track-artist", 1), db::TrackArtistLinkType::Artist, "if-has-track-artist" }, + Entry{ "artist-type-composer", Wt::WString::trn("Lms.Explore.composer", 1), db::TrackArtistLinkType::Composer, "if-has-composer" }, + Entry{ "artist-type-conductor", Wt::WString::trn("Lms.Explore.conductor", 1), db::TrackArtistLinkType::Conductor, "if-has-conductor" }, + Entry{ "artist-type-lyricist", Wt::WString::trn("Lms.Explore.lyricist", 1), db::TrackArtistLinkType::Lyricist, "if-has-lyricist" }, + Entry{ "artist-type-mixer", Wt::WString::trn("Lms.Explore.mixer", 1), db::TrackArtistLinkType::Mixer, "if-has-mixer" }, + Entry{ "artist-type-performer", Wt::WString::trn("Lms.Explore.performer", 1), db::TrackArtistLinkType::Performer, "if-has-performer" }, + Entry{ "artist-type-producer", Wt::WString::trn("Lms.Explore.producer", 1), db::TrackArtistLinkType::Producer, "if-has-producer" }, + Entry{ "artist-type-remixer", Wt::WString::trn("Lms.Explore.remixer", 1), db::TrackArtistLinkType::Remixer, "if-has-remixer" }, + }; + + for (const Entry& entry : entries) + { + if (!entry.linkType || types.contains(*entry.linkType)) + bindItemWithCondition(entry.var, entry.title, entry.linkType, entry.condition); + } + } +} // namespace lms::ui diff --git a/src/lms/ui/explore/TrackArtistTypeSelector.hpp b/src/lms/ui/explore/TrackArtistTypeSelector.hpp new file mode 100644 index 00000000..380767cb --- /dev/null +++ b/src/lms/ui/explore/TrackArtistTypeSelector.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2026 Emeric Poupon + * + * This file is part of LMS. + * + * LMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LMS. If not, see . + */ + +#pragma once + +#include "core/EnumSet.hpp" + +#include "database/objects/Types.hpp" + +#include "DropDownMenuSelector.hpp" + +namespace lms::ui +{ + class TrackArtistTypeSelector : public DropDownMenuSelector> + { + public: + TrackArtistTypeSelector(std::optional defaultRole, core::EnumSet types); + }; +} // namespace lms::ui