feat(plugins): filter plugins by abilities in plugins page and show abilities as badge

This commit is contained in:
Kingkor Roy Tirtho 2025-10-23 08:57:45 +06:00
parent 439de5d7f7
commit f6d9d64b7d
41 changed files with 270 additions and 118 deletions

View File

@ -135,7 +135,7 @@ abstract class SpotubeIcons {
static const list = FeatherIcons.list; static const list = FeatherIcons.list;
static const device = FeatherIcons.smartphone; static const device = FeatherIcons.smartphone;
static const engine = FeatherIcons.server; static const engine = FeatherIcons.server;
static const extensions = FeatherIcons.package; static const extensions = Icons.extension_rounded;
static const message = FeatherIcons.send; static const message = FeatherIcons.send;
static const upload = FeatherIcons.uploadCloud; static const upload = FeatherIcons.uploadCloud;
static const plugin = Icons.extension_outlined; static const plugin = Icons.extension_outlined;

View File

@ -452,14 +452,14 @@
"disclaimer": "Disclaimer", "disclaimer": "Disclaimer",
"third_party_plugin_dmca_notice": "The Spotube team does not hold any responsibility (including legal) for any \"Third-party\" plugins.\nPlease use them at your own risk. For any bugs/issues, please report them to the plugin repository.\n\nIf any \"Third-party\" plugin is breaking ToS/DMCA of any service/legal entity, please ask the \"Third-party\" plugin author or the hosting platform .e.g GitHub/Codeberg to take action. Above listed (\"Third-party\" labelled) are all public/community maintained plugins. We're not curating them, so we cannot take any action on them.\n\n", "third_party_plugin_dmca_notice": "The Spotube team does not hold any responsibility (including legal) for any \"Third-party\" plugins.\nPlease use them at your own risk. For any bugs/issues, please report them to the plugin repository.\n\nIf any \"Third-party\" plugin is breaking ToS/DMCA of any service/legal entity, please ask the \"Third-party\" plugin author or the hosting platform .e.g GitHub/Codeberg to take action. Above listed (\"Third-party\" labelled) are all public/community maintained plugins. We're not curating them, so we cannot take any action on them.\n\n",
"input_does_not_match_format": "Input doesn't match the required format", "input_does_not_match_format": "Input doesn't match the required format",
"metadata_provider_plugins": "Metadata Provider Plugins", "plugins": "Plugins",
"paste_plugin_download_url": "Paste download url or GitHub/Codeberg repo url or direct link to .smplug file", "paste_plugin_download_url": "Paste download url or GitHub/Codeberg repo url or direct link to .smplug file",
"download_and_install_plugin_from_url": "Download and install plugin from url", "download_and_install_plugin_from_url": "Download and install plugin from url",
"failed_to_add_plugin_error": "Failed to add plugin: {error}", "failed_to_add_plugin_error": "Failed to add plugin: {error}",
"upload_plugin_from_file": "Upload plugin from file", "upload_plugin_from_file": "Upload plugin from file",
"installed": "Installed", "installed": "Installed",
"available_plugins": "Available plugins", "available_plugins": "Available plugins",
"configure_your_own_metadata_plugin": "Configure your own playlist/album/artist/feed metadata provider", "configure_plugins": "Configure your own metadata provider and audio source plugins",
"audio_scrobblers": "Audio Scrobblers", "audio_scrobblers": "Audio Scrobblers",
"scrobbling": "Scrobbling", "scrobbling": "Scrobbling",
"source": "Source: ", "source": "Source: ",

View File

@ -2871,11 +2871,11 @@ abstract class AppLocalizations {
/// **'Input doesn\'t match the required format'** /// **'Input doesn\'t match the required format'**
String get input_does_not_match_format; String get input_does_not_match_format;
/// No description provided for @metadata_provider_plugins. /// No description provided for @plugins.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Metadata Provider Plugins'** /// **'Plugins'**
String get metadata_provider_plugins; String get plugins;
/// No description provided for @paste_plugin_download_url. /// No description provided for @paste_plugin_download_url.
/// ///
@ -2913,11 +2913,11 @@ abstract class AppLocalizations {
/// **'Available plugins'** /// **'Available plugins'**
String get available_plugins; String get available_plugins;
/// No description provided for @configure_your_own_metadata_plugin. /// No description provided for @configure_plugins.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Configure your own playlist/album/artist/feed metadata provider'** /// **'Configure your own metadata provider and audio source plugins'**
String get configure_your_own_metadata_plugin; String get configure_plugins;
/// No description provided for @audio_scrobblers. /// No description provided for @audio_scrobblers.
/// ///

View File

@ -1504,7 +1504,7 @@ class AppLocalizationsAr extends AppLocalizations {
'المدخل لا يتوافق مع التنسيق المطلوب'; 'المدخل لا يتوافق مع التنسيق المطلوب';
@override @override
String get metadata_provider_plugins => 'إضافات مزود البيانات'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1529,8 +1529,8 @@ class AppLocalizationsAr extends AppLocalizations {
String get available_plugins => 'الإضافات المتوفّرة'; String get available_plugins => 'الإضافات المتوفّرة';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'تهيئة مزوّد بيانات للقائمة/الألبوم/الفنان/المصدر خاص بك'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'أجهزة تتبع الصوت'; String get audio_scrobblers => 'أجهزة تتبع الصوت';

View File

@ -1505,7 +1505,7 @@ class AppLocalizationsBn extends AppLocalizations {
'ইনপুট প্রয়োজনীয় ফরম্যাটের সাথে মেলে না'; 'ইনপুট প্রয়োজনীয় ফরম্যাটের সাথে মেলে না';
@override @override
String get metadata_provider_plugins => 'মেটাডেটা প্রদানকারী প্লাগইনসমূহ'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1530,8 +1530,8 @@ class AppLocalizationsBn extends AppLocalizations {
String get available_plugins => 'উপলব্ধ প্লাগইনগুলো'; String get available_plugins => 'উপলব্ধ প্লাগইনগুলো';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'নিজস্ব প্লেলিস্ট/অ্যালবাম/শিল্পী/ফিড মেটাডেটা প্রদানকারী কনফিগার করুন'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'অডিও স্ক্রোব্বলার্স'; String get audio_scrobblers => 'অডিও স্ক্রোব্বলার্স';

View File

@ -1514,8 +1514,7 @@ class AppLocalizationsCa extends AppLocalizations {
'Lentrada no coincideix amb el format requerit'; 'Lentrada no coincideix amb el format requerit';
@override @override
String get metadata_provider_plugins => String get plugins => 'Plugins';
'Complements de proveïdor de metadades';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1540,8 +1539,8 @@ class AppLocalizationsCa extends AppLocalizations {
String get available_plugins => 'Complements disponibles'; String get available_plugins => 'Complements disponibles';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Configura el teu propi proveïdor de metadades per llistes/reproduccions àlbum/artista/flux'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Scrobblers dàudio'; String get audio_scrobblers => 'Scrobblers dàudio';

View File

@ -1505,7 +1505,7 @@ class AppLocalizationsCs extends AppLocalizations {
'Vstup neodpovídá požadovanému formátu'; 'Vstup neodpovídá požadovanému formátu';
@override @override
String get metadata_provider_plugins => 'Pluginy poskytovatelů metadat'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1530,8 +1530,8 @@ class AppLocalizationsCs extends AppLocalizations {
String get available_plugins => 'Dostupné pluginy'; String get available_plugins => 'Dostupné pluginy';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Nakonfigurujte si vlastního poskytovatele metadat pro playlist/album/umělec/fid'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Audio scrobblers'; String get audio_scrobblers => 'Audio scrobblers';

View File

@ -1517,7 +1517,7 @@ class AppLocalizationsDe extends AppLocalizations {
'Eingabe entspricht nicht dem geforderten Format'; 'Eingabe entspricht nicht dem geforderten Format';
@override @override
String get metadata_provider_plugins => 'Plugins für Metadatenanbieter'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1542,8 +1542,8 @@ class AppLocalizationsDe extends AppLocalizations {
String get available_plugins => 'Verfügbare Plugins'; String get available_plugins => 'Verfügbare Plugins';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Eigenen Anbieter für Playlist-/Album-/Künstler-/Feed-Metadaten konfigurieren'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Audio-Scrobbler'; String get audio_scrobblers => 'Audio-Scrobbler';

View File

@ -1503,7 +1503,7 @@ class AppLocalizationsEn extends AppLocalizations {
'Input doesn\'t match the required format'; 'Input doesn\'t match the required format';
@override @override
String get metadata_provider_plugins => 'Metadata Provider Plugins'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1528,8 +1528,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get available_plugins => 'Available plugins'; String get available_plugins => 'Available plugins';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Configure your own playlist/album/artist/feed metadata provider'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Audio Scrobblers'; String get audio_scrobblers => 'Audio Scrobblers';

View File

@ -1517,8 +1517,7 @@ class AppLocalizationsEs extends AppLocalizations {
'La entrada no coincide con el formato requerido'; 'La entrada no coincide con el formato requerido';
@override @override
String get metadata_provider_plugins => String get plugins => 'Plugins';
'Complementos de proveedor de metadatos';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1543,8 +1542,8 @@ class AppLocalizationsEs extends AppLocalizations {
String get available_plugins => 'Complementos disponibles'; String get available_plugins => 'Complementos disponibles';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Configura tu propio proveedor de metadatos para listas/álbum/artista/feeds'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Scrobblers de audio'; String get audio_scrobblers => 'Scrobblers de audio';

View File

@ -1515,7 +1515,7 @@ class AppLocalizationsEu extends AppLocalizations {
'Sarrera ezin da beharrezko formatutik desberdina izan'; 'Sarrera ezin da beharrezko formatutik desberdina izan';
@override @override
String get metadata_provider_plugins => 'Metadaten hornitzailearen pluginak'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1540,8 +1540,8 @@ class AppLocalizationsEu extends AppLocalizations {
String get available_plugins => 'Eskaintzen diren pluginak'; String get available_plugins => 'Eskaintzen diren pluginak';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Konfiguratu zureko playlists-/album-/artista-/feed-metadaten hornitzailea'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Audio scrobbler-ak'; String get audio_scrobblers => 'Audio scrobbler-ak';

View File

@ -1503,7 +1503,7 @@ class AppLocalizationsFa extends AppLocalizations {
'ورودی با قالب مورد نیاز تطابق ندارد'; 'ورودی با قالب مورد نیاز تطابق ندارد';
@override @override
String get metadata_provider_plugins => 'افزونه‌های ارائه‌دهندهٔ متادیتا'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1528,8 +1528,8 @@ class AppLocalizationsFa extends AppLocalizations {
String get available_plugins => 'افزونه‌های موجود'; String get available_plugins => 'افزونه‌های موجود';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'پیکربندی ارائه‌دهندهٔ متادیتا برای پلی‌لیست/آلبوم/هنرمند/فید به‌صورت سفارشی'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'اسکراب‌بلرهای صوتی'; String get audio_scrobblers => 'اسکراب‌بلرهای صوتی';

View File

@ -1503,7 +1503,7 @@ class AppLocalizationsFi extends AppLocalizations {
String get input_does_not_match_format => 'Syöte ei vastaa vaadittua muotoa'; String get input_does_not_match_format => 'Syöte ei vastaa vaadittua muotoa';
@override @override
String get metadata_provider_plugins => 'Metatietojen tarjoajan lisäosat'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1528,8 +1528,8 @@ class AppLocalizationsFi extends AppLocalizations {
String get available_plugins => 'Saatavilla olevat lisäosat'; String get available_plugins => 'Saatavilla olevat lisäosat';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Määritä oma soittolistan/albumin/artistin/syötteen metatietojen tarjoaja'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Äänen scrobblerit'; String get audio_scrobblers => 'Äänen scrobblerit';

View File

@ -1521,8 +1521,7 @@ class AppLocalizationsFr extends AppLocalizations {
'L\'entrée ne correspond pas au format requis'; 'L\'entrée ne correspond pas au format requis';
@override @override
String get metadata_provider_plugins => String get plugins => 'Plugins';
'Plugins de fournisseur de métadonnées';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1548,8 +1547,8 @@ class AppLocalizationsFr extends AppLocalizations {
String get available_plugins => 'Plugins disponibles'; String get available_plugins => 'Plugins disponibles';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Configurer votre propre fournisseur de métadonnées de playlist/album/artiste/flux'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Scrobblers audio'; String get audio_scrobblers => 'Scrobblers audio';

View File

@ -1509,7 +1509,7 @@ class AppLocalizationsHi extends AppLocalizations {
'इनपुट आवश्यक प्रारूप से मेल नहीं खाता है'; 'इनपुट आवश्यक प्रारूप से मेल नहीं खाता है';
@override @override
String get metadata_provider_plugins => 'मेटाडेटा प्रदाता प्लगइन'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1534,8 +1534,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get available_plugins => 'उपलब्ध प्लगइन'; String get available_plugins => 'उपलब्ध प्लगइन';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'अपनी खुद की प्लेलिस्ट/एल्बम/कलाकार/फ़ीड मेटाडेटा प्रदाता कॉन्फ़िगर करें'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'ऑडियो स्क्रॉबलर्स'; String get audio_scrobblers => 'ऑडियो स्क्रॉबलर्स';

View File

@ -1511,7 +1511,7 @@ class AppLocalizationsId extends AppLocalizations {
'Masukan tidak cocok dengan format yang diperlukan'; 'Masukan tidak cocok dengan format yang diperlukan';
@override @override
String get metadata_provider_plugins => 'Plugin Penyedia Metadata'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1536,8 +1536,8 @@ class AppLocalizationsId extends AppLocalizations {
String get available_plugins => 'Plugin yang tersedia'; String get available_plugins => 'Plugin yang tersedia';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Konfigurasi penyedia metadata playlist/album/artis/feed Anda sendiri'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Scrobblers Audio'; String get audio_scrobblers => 'Scrobblers Audio';

View File

@ -1510,7 +1510,7 @@ class AppLocalizationsIt extends AppLocalizations {
'L\'input non corrisponde al formato richiesto'; 'L\'input non corrisponde al formato richiesto';
@override @override
String get metadata_provider_plugins => 'Plugin del provider di metadati'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1535,8 +1535,8 @@ class AppLocalizationsIt extends AppLocalizations {
String get available_plugins => 'Plugin disponibili'; String get available_plugins => 'Plugin disponibili';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Configura il tuo provider di metadati per playlist/album/artista/feed'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Scrobbler audio'; String get audio_scrobblers => 'Scrobbler audio';

View File

@ -1474,7 +1474,7 @@ class AppLocalizationsJa extends AppLocalizations {
String get input_does_not_match_format => '入力が必須フォーマットと一致しません'; String get input_does_not_match_format => '入力が必須フォーマットと一致しません';
@override @override
String get metadata_provider_plugins => 'メタデータプロバイダープラグイン'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1499,8 +1499,8 @@ class AppLocalizationsJa extends AppLocalizations {
String get available_plugins => '利用可能なプラグイン'; String get available_plugins => '利用可能なプラグイン';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'独自のプレイリスト/アルバム/アーティスト/フィードのメタデータプロバイダーを構成'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'オーディオスクロッブラー'; String get audio_scrobblers => 'オーディオスクロッブラー';

View File

@ -1511,8 +1511,7 @@ class AppLocalizationsKa extends AppLocalizations {
'შეყვანა არ ემთხვევა საჭირო ფორმატს'; 'შეყვანა არ ემთხვევა საჭირო ფორმატს';
@override @override
String get metadata_provider_plugins => String get plugins => 'Plugins';
'მეტამონაცემების პროვაიდერების პლაგინები';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1537,8 +1536,8 @@ class AppLocalizationsKa extends AppLocalizations {
String get available_plugins => 'ხელმისაწვდომი პლაგინები'; String get available_plugins => 'ხელმისაწვდომი პლაგინები';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'დააყენეთ თქვენი საკუთარი პლეილისტის/ალბომის/არტისტის/ფიდის მეტამონაცემების პროვაიდერი'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'აუდიო სქრობლერები'; String get audio_scrobblers => 'აუდიო სქრობლერები';

View File

@ -1479,7 +1479,7 @@ class AppLocalizationsKo extends AppLocalizations {
String get input_does_not_match_format => '입력이 필요한 형식과 일치하지 않습니다'; String get input_does_not_match_format => '입력이 필요한 형식과 일치하지 않습니다';
@override @override
String get metadata_provider_plugins => '메타데이터 제공자 플러그인'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1503,8 +1503,8 @@ class AppLocalizationsKo extends AppLocalizations {
String get available_plugins => '사용 가능한 플러그인'; String get available_plugins => '사용 가능한 플러그인';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'자신만의 플레이리스트/앨범/아티스트/피드 메타데이터 제공자 구성'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => '오디오 스크로블러'; String get audio_scrobblers => '오디오 스크로블러';

View File

@ -1515,7 +1515,7 @@ class AppLocalizationsNe extends AppLocalizations {
String get input_does_not_match_format => 'इनपुट आवश्यक ढाँचासँग मेल खाँदैन'; String get input_does_not_match_format => 'इनपुट आवश्यक ढाँचासँग मेल खाँदैन';
@override @override
String get metadata_provider_plugins => 'मेटाडेटा प्रदायक प्लगइनहरू'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1540,8 +1540,8 @@ class AppLocalizationsNe extends AppLocalizations {
String get available_plugins => 'उपलब्ध प्लगइनहरू'; String get available_plugins => 'उपलब्ध प्लगइनहरू';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'तपाईंको आफ्नै प्लेलिस्ट/एल्बम/कलाकार/फिड मेटाडेटा प्रदायक कन्फिगर गर्नुहोस्'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'अडियो स्क्रब्बलरहरू'; String get audio_scrobblers => 'अडियो स्क्रब्बलरहरू';

View File

@ -1509,7 +1509,7 @@ class AppLocalizationsNl extends AppLocalizations {
'Invoer komt niet overeen met het vereiste formaat'; 'Invoer komt niet overeen met het vereiste formaat';
@override @override
String get metadata_provider_plugins => 'Metadata-aanbieder Plugins'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1534,8 +1534,8 @@ class AppLocalizationsNl extends AppLocalizations {
String get available_plugins => 'Beschikbare plugins'; String get available_plugins => 'Beschikbare plugins';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Configureer uw eigen metadata-aanbieder voor afspeellijst/album/artiest/feed'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Audioscrobblers'; String get audio_scrobblers => 'Audioscrobblers';

View File

@ -1511,7 +1511,7 @@ class AppLocalizationsPl extends AppLocalizations {
'Wprowadzony tekst nie pasuje do wymaganego formatu'; 'Wprowadzony tekst nie pasuje do wymaganego formatu';
@override @override
String get metadata_provider_plugins => 'Wtyczki dostawców metadanych'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1536,8 +1536,8 @@ class AppLocalizationsPl extends AppLocalizations {
String get available_plugins => 'Dostępne wtyczki'; String get available_plugins => 'Dostępne wtyczki';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Skonfiguruj własnego dostawcę metadanych dla playlisty/albumu/artysty/kanału'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Scrobblery audio'; String get audio_scrobblers => 'Scrobblery audio';

View File

@ -1508,7 +1508,7 @@ class AppLocalizationsPt extends AppLocalizations {
'A entrada não corresponde ao formato exigido'; 'A entrada não corresponde ao formato exigido';
@override @override
String get metadata_provider_plugins => 'Plugins do provedor de metadados'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1533,8 +1533,8 @@ class AppLocalizationsPt extends AppLocalizations {
String get available_plugins => 'Plugins disponíveis'; String get available_plugins => 'Plugins disponíveis';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Configure seu próprio provedor de metadados de playlist/álbum/artista/feed'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Scrobblers de áudio'; String get audio_scrobblers => 'Scrobblers de áudio';

View File

@ -1511,7 +1511,7 @@ class AppLocalizationsRu extends AppLocalizations {
'Введенные данные не соответствуют требуемому формату'; 'Введенные данные не соответствуют требуемому формату';
@override @override
String get metadata_provider_plugins => 'Плагины поставщика метаданных'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1536,8 +1536,8 @@ class AppLocalizationsRu extends AppLocalizations {
String get available_plugins => 'Доступные плагины'; String get available_plugins => 'Доступные плагины';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Настройте свой собственный поставщик метаданных для плейлиста/альбома/артиста/ленты'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Аудио скробблеры'; String get audio_scrobblers => 'Аудио скробблеры';

View File

@ -1517,7 +1517,7 @@ class AppLocalizationsTa extends AppLocalizations {
'உள்ளீடு தேவையான வடிவத்துடன் பொருந்தவில்லை'; 'உள்ளீடு தேவையான வடிவத்துடன் பொருந்தவில்லை';
@override @override
String get metadata_provider_plugins => 'மெட்டாடேட்டா வழங்குநர் பிளகின்கள்'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1542,8 +1542,8 @@ class AppLocalizationsTa extends AppLocalizations {
String get available_plugins => 'கிடைக்கக்கூடிய பிளகின்கள்'; String get available_plugins => 'கிடைக்கக்கூடிய பிளகின்கள்';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'உங்கள் சொந்த பிளேலிஸ்ட்/ஆல்பம்/கலைஞர்/ஊட்ட மெட்டாடேட்டா வழங்குநரை உள்ளமைக்கவும்'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'ஆடியோ ஸ்க்ரோப்ளர்கள்'; String get audio_scrobblers => 'ஆடியோ ஸ்க்ரோப்ளர்கள்';

View File

@ -1500,7 +1500,7 @@ class AppLocalizationsTh extends AppLocalizations {
String get input_does_not_match_format => 'อินพุตไม่ตรงกับรูปแบบที่ต้องการ'; String get input_does_not_match_format => 'อินพุตไม่ตรงกับรูปแบบที่ต้องการ';
@override @override
String get metadata_provider_plugins => 'ปลั๊กอินผู้ให้บริการเมตาดาต้า'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1525,8 +1525,8 @@ class AppLocalizationsTh extends AppLocalizations {
String get available_plugins => 'ปลั๊กอินที่มีอยู่'; String get available_plugins => 'ปลั๊กอินที่มีอยู่';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'กำหนดค่าผู้ให้บริการเมตาดาต้าเพลย์ลิสต์/อัลบั้ม/ศิลปิน/ฟีดของคุณเอง'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'เครื่อง scrobbler เสียง'; String get audio_scrobblers => 'เครื่อง scrobbler เสียง';

View File

@ -1518,7 +1518,7 @@ class AppLocalizationsTl extends AppLocalizations {
'Ang input ay hindi tumutugma sa kinakailangang format'; 'Ang input ay hindi tumutugma sa kinakailangang format';
@override @override
String get metadata_provider_plugins => 'Mga Plugin ng Metadata Provider'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1543,8 +1543,8 @@ class AppLocalizationsTl extends AppLocalizations {
String get available_plugins => 'Mga available na plugin'; String get available_plugins => 'Mga available na plugin';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'I-configure ang iyong sariling playlist/album/artist/feed metadata provider'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Mga Audio Scrobbler'; String get audio_scrobblers => 'Mga Audio Scrobbler';

View File

@ -1511,7 +1511,7 @@ class AppLocalizationsTr extends AppLocalizations {
String get input_does_not_match_format => 'Girdi, gerekli biçimle eşleşmiyor'; String get input_does_not_match_format => 'Girdi, gerekli biçimle eşleşmiyor';
@override @override
String get metadata_provider_plugins => 'Meta Veri Sağlayıcısı Eklentileri'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1536,8 +1536,8 @@ class AppLocalizationsTr extends AppLocalizations {
String get available_plugins => 'Mevcut eklentiler'; String get available_plugins => 'Mevcut eklentiler';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Kendi çalma listenizi/albümünüzü/sanatçınızı/akış meta veri sağlayıcınızı yapılandırın'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Ses Scrobbler\'lar'; String get audio_scrobblers => 'Ses Scrobbler\'lar';

View File

@ -1507,7 +1507,7 @@ class AppLocalizationsUk extends AppLocalizations {
'Введені дані не відповідають необхідному формату'; 'Введені дані не відповідають необхідному формату';
@override @override
String get metadata_provider_plugins => 'Плагіни провайдера метаданих'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1532,8 +1532,8 @@ class AppLocalizationsUk extends AppLocalizations {
String get available_plugins => 'Доступні плагіни'; String get available_plugins => 'Доступні плагіни';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Налаштуйте свій власний провайдер метаданих для плейлиста/альбому/виконавця/стрічки'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Аудіо скробблери'; String get audio_scrobblers => 'Аудіо скробблери';

View File

@ -1513,7 +1513,7 @@ class AppLocalizationsVi extends AppLocalizations {
'Đầu vào không khớp với định dạng yêu cầu'; 'Đầu vào không khớp với định dạng yêu cầu';
@override @override
String get metadata_provider_plugins => 'Plugin Nhà cung cấp siêu dữ liệu'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1538,8 +1538,8 @@ class AppLocalizationsVi extends AppLocalizations {
String get available_plugins => 'Các plugin có sẵn'; String get available_plugins => 'Các plugin có sẵn';
@override @override
String get configure_your_own_metadata_plugin => String get configure_plugins =>
'Cấu hình nhà cung cấp siêu dữ liệu danh sách phát/album/nghệ sĩ/nguồn cấp dữ liệu của riêng bạn'; 'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => 'Bộ scrobbler âm thanh'; String get audio_scrobblers => 'Bộ scrobbler âm thanh';

View File

@ -1469,7 +1469,7 @@ class AppLocalizationsZh extends AppLocalizations {
String get input_does_not_match_format => '输入与所需格式不匹配'; String get input_does_not_match_format => '输入与所需格式不匹配';
@override @override
String get metadata_provider_plugins => '元数据提供者插件'; String get plugins => 'Plugins';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
@ -1493,7 +1493,8 @@ class AppLocalizationsZh extends AppLocalizations {
String get available_plugins => '可用插件'; String get available_plugins => '可用插件';
@override @override
String get configure_your_own_metadata_plugin => '配置您自己的播放列表/专辑/艺人/订阅元数据提供者'; String get configure_plugins =>
'Configure your own metadata provider and audio source plugins';
@override @override
String get audio_scrobblers => '音频 Scrobblers'; String get audio_scrobblers => '音频 Scrobblers';
@ -2976,9 +2977,6 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override @override
String get input_does_not_match_format => '輸入不符合所需格式'; String get input_does_not_match_format => '輸入不符合所需格式';
@override
String get metadata_provider_plugins => '中繼資料供應商外掛程式';
@override @override
String get paste_plugin_download_url => String get paste_plugin_download_url =>
'貼上下載網址、GitHub/Codeberg 儲存庫網址或 .smplug 檔案的直接連結'; '貼上下載網址、GitHub/Codeberg 儲存庫網址或 .smplug 檔案的直接連結';
@ -3000,9 +2998,6 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
@override @override
String get available_plugins => '可用的外掛程式'; String get available_plugins => '可用的外掛程式';
@override
String get configure_your_own_metadata_plugin => '設定您自己的播放清單/專輯/藝人/動態中繼資料供應商';
@override @override
String get audio_scrobblers => '音訊 Scrobblers'; String get audio_scrobblers => '音訊 Scrobblers';

View File

@ -6539,6 +6539,7 @@ mixin _$MetadataPluginRepository {
String get owner => throw _privateConstructorUsedError; String get owner => throw _privateConstructorUsedError;
String get description => throw _privateConstructorUsedError; String get description => throw _privateConstructorUsedError;
String get repoUrl => throw _privateConstructorUsedError; String get repoUrl => throw _privateConstructorUsedError;
List<String> get topics => throw _privateConstructorUsedError;
/// Serializes this MetadataPluginRepository to a JSON map. /// Serializes this MetadataPluginRepository to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -6556,7 +6557,12 @@ abstract class $MetadataPluginRepositoryCopyWith<$Res> {
$Res Function(MetadataPluginRepository) then) = $Res Function(MetadataPluginRepository) then) =
_$MetadataPluginRepositoryCopyWithImpl<$Res, MetadataPluginRepository>; _$MetadataPluginRepositoryCopyWithImpl<$Res, MetadataPluginRepository>;
@useResult @useResult
$Res call({String name, String owner, String description, String repoUrl}); $Res call(
{String name,
String owner,
String description,
String repoUrl,
List<String> topics});
} }
/// @nodoc /// @nodoc
@ -6579,6 +6585,7 @@ class _$MetadataPluginRepositoryCopyWithImpl<$Res,
Object? owner = null, Object? owner = null,
Object? description = null, Object? description = null,
Object? repoUrl = null, Object? repoUrl = null,
Object? topics = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
name: null == name name: null == name
@ -6597,6 +6604,10 @@ class _$MetadataPluginRepositoryCopyWithImpl<$Res,
? _value.repoUrl ? _value.repoUrl
: repoUrl // ignore: cast_nullable_to_non_nullable : repoUrl // ignore: cast_nullable_to_non_nullable
as String, as String,
topics: null == topics
? _value.topics
: topics // ignore: cast_nullable_to_non_nullable
as List<String>,
) as $Val); ) as $Val);
} }
} }
@ -6610,7 +6621,12 @@ abstract class _$$MetadataPluginRepositoryImplCopyWith<$Res>
__$$MetadataPluginRepositoryImplCopyWithImpl<$Res>; __$$MetadataPluginRepositoryImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({String name, String owner, String description, String repoUrl}); $Res call(
{String name,
String owner,
String description,
String repoUrl,
List<String> topics});
} }
/// @nodoc /// @nodoc
@ -6632,6 +6648,7 @@ class __$$MetadataPluginRepositoryImplCopyWithImpl<$Res>
Object? owner = null, Object? owner = null,
Object? description = null, Object? description = null,
Object? repoUrl = null, Object? repoUrl = null,
Object? topics = null,
}) { }) {
return _then(_$MetadataPluginRepositoryImpl( return _then(_$MetadataPluginRepositoryImpl(
name: null == name name: null == name
@ -6650,6 +6667,10 @@ class __$$MetadataPluginRepositoryImplCopyWithImpl<$Res>
? _value.repoUrl ? _value.repoUrl
: repoUrl // ignore: cast_nullable_to_non_nullable : repoUrl // ignore: cast_nullable_to_non_nullable
as String, as String,
topics: null == topics
? _value._topics
: topics // ignore: cast_nullable_to_non_nullable
as List<String>,
)); ));
} }
} }
@ -6661,7 +6682,9 @@ class _$MetadataPluginRepositoryImpl implements _MetadataPluginRepository {
{required this.name, {required this.name,
required this.owner, required this.owner,
required this.description, required this.description,
required this.repoUrl}); required this.repoUrl,
required final List<String> topics})
: _topics = topics;
factory _$MetadataPluginRepositoryImpl.fromJson(Map<String, dynamic> json) => factory _$MetadataPluginRepositoryImpl.fromJson(Map<String, dynamic> json) =>
_$$MetadataPluginRepositoryImplFromJson(json); _$$MetadataPluginRepositoryImplFromJson(json);
@ -6674,10 +6697,17 @@ class _$MetadataPluginRepositoryImpl implements _MetadataPluginRepository {
final String description; final String description;
@override @override
final String repoUrl; final String repoUrl;
final List<String> _topics;
@override
List<String> get topics {
if (_topics is EqualUnmodifiableListView) return _topics;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_topics);
}
@override @override
String toString() { String toString() {
return 'MetadataPluginRepository(name: $name, owner: $owner, description: $description, repoUrl: $repoUrl)'; return 'MetadataPluginRepository(name: $name, owner: $owner, description: $description, repoUrl: $repoUrl, topics: $topics)';
} }
@override @override
@ -6689,13 +6719,14 @@ class _$MetadataPluginRepositoryImpl implements _MetadataPluginRepository {
(identical(other.owner, owner) || other.owner == owner) && (identical(other.owner, owner) || other.owner == owner) &&
(identical(other.description, description) || (identical(other.description, description) ||
other.description == description) && other.description == description) &&
(identical(other.repoUrl, repoUrl) || other.repoUrl == repoUrl)); (identical(other.repoUrl, repoUrl) || other.repoUrl == repoUrl) &&
const DeepCollectionEquality().equals(other._topics, _topics));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => int get hashCode => Object.hash(runtimeType, name, owner, description,
Object.hash(runtimeType, name, owner, description, repoUrl); repoUrl, const DeepCollectionEquality().hash(_topics));
/// Create a copy of MetadataPluginRepository /// Create a copy of MetadataPluginRepository
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@ -6719,7 +6750,8 @@ abstract class _MetadataPluginRepository implements MetadataPluginRepository {
{required final String name, {required final String name,
required final String owner, required final String owner,
required final String description, required final String description,
required final String repoUrl}) = _$MetadataPluginRepositoryImpl; required final String repoUrl,
required final List<String> topics}) = _$MetadataPluginRepositoryImpl;
factory _MetadataPluginRepository.fromJson(Map<String, dynamic> json) = factory _MetadataPluginRepository.fromJson(Map<String, dynamic> json) =
_$MetadataPluginRepositoryImpl.fromJson; _$MetadataPluginRepositoryImpl.fromJson;
@ -6732,6 +6764,8 @@ abstract class _MetadataPluginRepository implements MetadataPluginRepository {
String get description; String get description;
@override @override
String get repoUrl; String get repoUrl;
@override
List<String> get topics;
/// Create a copy of MetadataPluginRepository /// Create a copy of MetadataPluginRepository
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.

View File

@ -603,6 +603,8 @@ _$MetadataPluginRepositoryImpl _$$MetadataPluginRepositoryImplFromJson(
owner: json['owner'] as String, owner: json['owner'] as String,
description: json['description'] as String, description: json['description'] as String,
repoUrl: json['repoUrl'] as String, repoUrl: json['repoUrl'] as String,
topics:
(json['topics'] as List<dynamic>).map((e) => e as String).toList(),
); );
Map<String, dynamic> _$$MetadataPluginRepositoryImplToJson( Map<String, dynamic> _$$MetadataPluginRepositoryImplToJson(
@ -612,4 +614,5 @@ Map<String, dynamic> _$$MetadataPluginRepositoryImplToJson(
'owner': instance.owner, 'owner': instance.owner,
'description': instance.description, 'description': instance.description,
'repoUrl': instance.repoUrl, 'repoUrl': instance.repoUrl,
'topics': instance.topics,
}; };

View File

@ -7,6 +7,7 @@ class MetadataPluginRepository with _$MetadataPluginRepository {
required String owner, required String owner,
required String description, required String description,
required String repoUrl, required String repoUrl,
required List<String> topics,
}) = _MetadataPluginRepository; }) = _MetadataPluginRepository;
factory MetadataPluginRepository.fromJson(Map<String, dynamic> json) => factory MetadataPluginRepository.fromJson(Map<String, dynamic> json) =>

View File

@ -5,6 +5,7 @@ import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/markdown/markdown.dart'; import 'package:spotube/components/markdown/markdown.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/models/metadata/metadata.dart'; import 'package:spotube/models/metadata/metadata.dart';
import 'package:spotube/modules/metadata_plugins/plugin_repository.dart';
import 'package:spotube/modules/metadata_plugins/plugin_update_available_dialog.dart'; import 'package:spotube/modules/metadata_plugins/plugin_update_available_dialog.dart';
import 'package:spotube/provider/metadata_plugin/core/auth.dart'; import 'package:spotube/provider/metadata_plugin/core/auth.dart';
import 'package:spotube/provider/metadata_plugin/core/support.dart'; import 'package:spotube/provider/metadata_plugin/core/support.dart';
@ -12,6 +13,11 @@ import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
import 'package:spotube/provider/metadata_plugin/updater/update_checker.dart'; import 'package:spotube/provider/metadata_plugin/updater/update_checker.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
final validAbilities = {
PluginAbilities.metadata: ("Metadata", SpotubeIcons.album),
PluginAbilities.audioSource: ("Audio Source", SpotubeIcons.music),
};
class MetadataInstalledPluginItem extends HookConsumerWidget { class MetadataInstalledPluginItem extends HookConsumerWidget {
final PluginConfiguration plugin; final PluginConfiguration plugin;
final bool isDefault; final bool isDefault;
@ -79,6 +85,18 @@ class MetadataInstalledPluginItem extends HookConsumerWidget {
spacing: 8, spacing: 8,
children: [ children: [
Text(plugin.description), Text(plugin.description),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
for (final ability in plugin.abilities)
if (validAbilities.keys.contains(ability))
SecondaryBadge(
leading: Icon(validAbilities[ability]!.$2),
child: Text(validAbilities[ability]!.$1),
),
],
),
if (repoUrl != null) if (repoUrl != null)
Wrap( Wrap(
spacing: 8, spacing: 8,

View File

@ -11,6 +11,11 @@ import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import 'package:change_case/change_case.dart'; import 'package:change_case/change_case.dart';
final validTopics = {
"spotube-metadata-plugin": ("Metadata", SpotubeIcons.album),
"spotube-audio-source-plugin": ("Audio Source", SpotubeIcons.music),
};
class MetadataPluginRepositoryItem extends HookConsumerWidget { class MetadataPluginRepositoryItem extends HookConsumerWidget {
final MetadataPluginRepository pluginRepo; final MetadataPluginRepository pluginRepo;
const MetadataPluginRepositoryItem({ const MetadataPluginRepositoryItem({
@ -208,6 +213,12 @@ class MetadataPluginRepositoryItem extends HookConsumerWidget {
), ),
), ),
], ],
for (final topic in pluginRepo.topics)
if (validTopics.keys.contains(topic))
SecondaryBadge(
leading: Icon(validTopics[topic]!.$2),
child: Text(validTopics[topic]!.$1),
),
SecondaryBadge( SecondaryBadge(
leading: host == "github.com" leading: host == "github.com"
? const Icon(SpotubeIcons.github) ? const Icon(SpotubeIcons.github)

View File

@ -30,6 +30,7 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final tabState = useState<int>(0);
final formKey = useMemoized(() => GlobalKey<FormBuilderState>(), []); final formKey = useMemoized(() => GlobalKey<FormBuilderState>(), []);
final plugins = ref.watch(metadataPluginsProvider); final plugins = ref.watch(metadataPluginsProvider);
@ -49,11 +50,30 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
final pluginRepos = pluginReposSnapshot.asData?.value.items ?? []; final pluginRepos = pluginReposSnapshot.asData?.value.items ?? [];
if (installedPluginIds.isEmpty) return pluginRepos; if (installedPluginIds.isEmpty) return pluginRepos;
return pluginRepos final availablePlugins = pluginRepos
.whereNot((repo) => installedPluginIds.contains(repo.repoUrl)) .whereNot((repo) => installedPluginIds.contains(repo.repoUrl))
.toList(); .toList();
if (tabState.value != 0) {
// metadata only plugins
return availablePlugins
.where(
(d) => d.topics.contains(
tabState.value == 1
? "spotube-metadata-plugin"
: "spotube-audio-source-plugin",
),
)
.toList();
}
return availablePlugins; // all plugins
}, },
[plugins.asData?.value.plugins, pluginReposSnapshot.asData?.value], [
plugins.asData?.value.plugins,
pluginReposSnapshot.asData?.value,
tabState.value,
],
); );
return SafeArea( return SafeArea(
@ -61,7 +81,7 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
child: Scaffold( child: Scaffold(
headers: [ headers: [
TitleBar( TitleBar(
title: Text(context.l10n.metadata_provider_plugins), title: Text(context.l10n.plugins),
) )
], ],
child: Padding( child: Padding(
@ -193,6 +213,20 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
), ),
), ),
const SliverGap(12), const SliverGap(12),
SliverToBoxAdapter(
child: TabList(
index: tabState.value,
onChanged: (value) {
tabState.value = value;
},
children: const [
TabItem(child: Text("All")),
TabItem(child: Text("Metadata")),
TabItem(child: Text("Audio Source")),
],
),
),
const SliverGap(12),
if (plugins.asData?.value.plugins.isNotEmpty ?? false) if (plugins.asData?.value.plugins.isNotEmpty ?? false)
SliverToBoxAdapter( SliverToBoxAdapter(
child: Row( child: Row(
@ -249,6 +283,7 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
description: "Loading...", description: "Loading...",
repoUrl: "", repoUrl: "",
owner: "", owner: "",
topics: [],
), ),
), ),
); );

View File

@ -21,8 +21,8 @@ class SettingsAccountSection extends HookConsumerWidget {
children: [ children: [
ListTile( ListTile(
leading: const Icon(SpotubeIcons.extensions), leading: const Icon(SpotubeIcons.extensions),
title: Text(context.l10n.metadata_provider_plugins), title: Text(context.l10n.plugins),
subtitle: Text(context.l10n.configure_your_own_metadata_plugin), subtitle: Text(context.l10n.configure_plugins),
onTap: () { onTap: () {
context.pushRoute(const SettingsMetadataProviderRoute()); context.pushRoute(const SettingsMetadataProviderRoute());
}, },

View File

@ -49,6 +49,7 @@ class MetadataPluginRepositoriesNotifier
owner: repo["owner"]["login"] ?? "", owner: repo["owner"]["login"] ?? "",
description: repo["description"] ?? "", description: repo["description"] ?? "",
repoUrl: repo["html_url"] ?? "", repoUrl: repo["html_url"] ?? "",
topics: repo["topics"].cast<String>() ?? [],
); );
}).toList(); }).toList();

View File

@ -1,101 +1,135 @@
{ {
"ar": [ "ar": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"bn": [ "bn": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"ca": [ "ca": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"cs": [ "cs": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"de": [ "de": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"es": [ "es": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"eu": [ "eu": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"fa": [ "fa": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"fi": [ "fi": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"fr": [ "fr": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"hi": [ "hi": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"id": [ "id": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"it": [ "it": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"ja": [ "ja": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"ka": [ "ka": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"ko": [ "ko": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"ne": [ "ne": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
@ -103,72 +137,96 @@
"nl": [ "nl": [
"audio_source", "audio_source",
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"pl": [ "pl": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"pt": [ "pt": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"ru": [ "ru": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"ta": [ "ta": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"th": [ "th": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"tl": [ "tl": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"tr": [ "tr": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"uk": [ "uk": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"vi": [ "vi": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"zh": [ "zh": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"
], ],
"zh_TW": [ "zh_TW": [
"plugins",
"configure_plugins",
"source", "source",
"uncompressed", "uncompressed",
"dab_music_source_description" "dab_music_source_description"