Compare commits
9 Commits
main
...
feat/emby-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
914ca6a44f | ||
|
|
a3b281ca72 | ||
|
|
7079a7c653 | ||
|
|
5bf68b6c42 | ||
|
|
0592d64253 | ||
|
|
e149aa796c | ||
|
|
0bf8b7a6e0 | ||
|
|
98c64e30eb | ||
|
|
b7436afabe |
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"play-album": "Пусни албум",
|
||||
"track": "Песен",
|
||||
"jellyfin-user-id": "Jellyfin потребител",
|
||||
"user-id": "Jellyfin потребител",
|
||||
"play-playlist": "Пусни списък",
|
||||
"color-scheme-system": "Система",
|
||||
"streaming": "Предава се поточно",
|
||||
"download-album": "Изтегли албум",
|
||||
"jellyfin-access-token": "Jellyfin Жетон за достъп (access token)",
|
||||
"access-token": "Jellyfin Жетон за достъп (access token)",
|
||||
"delete-playlist": "Изтрий списък",
|
||||
"add-to-queue": "Добави към опашката",
|
||||
"playback-reporting": "Докладване на изпълненията",
|
||||
@@ -16,7 +16,7 @@
|
||||
"no-results": "Няма резултати…",
|
||||
"total-duration": "Обща продължителност",
|
||||
"error-reporting": "Доклаване на грешки",
|
||||
"jellyfin-server-url": "Адрес на Jellyfin сървър",
|
||||
"server-url": "Адрес на Jellyfin сървър",
|
||||
"downloads": "Изтеглени",
|
||||
"onboarding-cta": "За да започнете Ви трябва Jellyfin сървър. Натиснете бутона отдолу, за да въведете адресът на вашия Jellyfin сървър и се впишете в него.",
|
||||
"shuffle-album": "Разбъркай албум",
|
||||
@@ -26,7 +26,7 @@
|
||||
"artists": "Изпълнители",
|
||||
"queue": "Опашка",
|
||||
"error-reporting-description": "Докато използвате приложението, може да срещнете грешки. Докладването на тези грешки помага на програмата да стане по-сигурна и стабилна.",
|
||||
"set-jellyfin-server": "Настройте Jellyfin сървър",
|
||||
"set-server": "Настройте Jellyfin сървър",
|
||||
"similar-albums": "Подобни албуми",
|
||||
"albums": "Албуми",
|
||||
"why-use-tracking-description": "Проследяването помага да се ускори процесът по разработка на приложението, като се докладват странни гранични случаи и недоглеждания. Това помага на приложението да стане по стабилно и приятно за използване от всички.",
|
||||
@@ -52,7 +52,7 @@
|
||||
"disable": "Изключи",
|
||||
"search": "Търси",
|
||||
"download-playlist": "Изтегли списък",
|
||||
"jellyfin-library": "Jellyfin Библиотека",
|
||||
"library": "Jellyfin Библиотека",
|
||||
"enable-error-reporting": "Желаете ли да пуснете докладването на грешки?",
|
||||
"color-scheme-description": "По подразбиране Fintunes ще следва цветовата схмена на вашата операционна система. Вие обаче можете да изберете Fintunes да се показва винаги в тъмен или светъл режим.",
|
||||
"color-scheme": "Цветова схема",
|
||||
@@ -66,7 +66,7 @@
|
||||
"setting-cache": "Кеш",
|
||||
"local-playback": "Локално изпълняване",
|
||||
"clear-queue": "Изчисти опашката",
|
||||
"set-jellyfin-server-instruction": "Моля въведете адресът на вашия Jellyfin сървър. Трябва да включва протоколът и порта",
|
||||
"set-server-instruction": "Моля въведете адресът на вашия Jellyfin сървър. Трябва да включва протоколът и порта",
|
||||
"delete-all-tracks": "Изтрий всички песни",
|
||||
"where-is-data-stored": "Къде се пазят данните?",
|
||||
"color-scheme-light": "Светъл режим",
|
||||
|
||||
@@ -52,13 +52,13 @@
|
||||
"onboarding-welcome": "Benvinguts!",
|
||||
"onboarding-intro": "Fintunes us permetrà reproduir la vostra biblioteca de música des de qualsevol lloc, amb total suport per a l'àudio en segon pla i l'enviament del so a altres dispositius.",
|
||||
"onboarding-cta": "Per començar, necessiteu un servidor de Jellyfin. Si us plau, introdueix dins de la caixa de text els caràcters que veu a la imatge de sota. Això és requerit per evitar enviaments automàtics.",
|
||||
"set-jellyfin-server": "Configura el servidor Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Introduïu l'URL del vostre servidor Jellyfin. Assegureu-vos d'incloure el protocol i el port",
|
||||
"set-server": "Configura el servidor Jellyfin",
|
||||
"set-server-instruction": "Introduïu l'URL del vostre servidor Jellyfin. Assegureu-vos d'incloure el protocol i el port",
|
||||
"settings": "Configuració",
|
||||
"jellyfin-library": "Biblioteca Jellyfin",
|
||||
"jellyfin-server-url": "Preguntes Freqüents - FAQ",
|
||||
"jellyfin-access-token": "Jellyfin Access Token",
|
||||
"jellyfin-user-id": "Jellyfin User ID",
|
||||
"library": "Biblioteca Jellyfin",
|
||||
"server-url": "Preguntes Freqüents - FAQ",
|
||||
"access-token": "Jellyfin Access Token",
|
||||
"user-id": "Jellyfin User ID",
|
||||
"setting-cache": "Caché",
|
||||
"setting-cache-description": "Si heu actualitzat la vostra biblioteca de Jellyfin, però l’aplicació està subjectant a actius amagats, podeu esborrar la memòria cau amb aquest botó. Això obligarà l’aplicació a fer una cerca de la biblioteca des de zero.",
|
||||
"recent-albums": "Afegit Recentment",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"play-album": "Přehrát Album",
|
||||
"track": "Skladba",
|
||||
"jellyfin-user-id": "ID uživatele Jellyfin",
|
||||
"user-id": "ID uživatele Jellyfin",
|
||||
"play-playlist": "Přehrát seznam skladeb",
|
||||
"color-scheme-system": "Systém",
|
||||
"streaming": "Streamování",
|
||||
"download-album": "Stáhnout Album",
|
||||
"jellyfin-access-token": "Přístupový token Jellyfin",
|
||||
"access-token": "Přístupový token Jellyfin",
|
||||
"delete-playlist": "Smazat seznam skladeb",
|
||||
"add-to-queue": "Přidat do Fronty",
|
||||
"playback-reporting": "Hlášení o přehrávání",
|
||||
@@ -16,7 +16,7 @@
|
||||
"no-results": "Žádné výsledky…",
|
||||
"total-duration": "Celková doba trvání",
|
||||
"error-reporting": "Hlášení chyb",
|
||||
"jellyfin-server-url": "Adresa URL serveru Jellyfin",
|
||||
"server-url": "Adresa URL serveru Jellyfin",
|
||||
"downloads": "Ke stažení",
|
||||
"onboarding-cta": "Abyste mohli začít, potřebujete server Jellyfin. Kliknutím na tlačítko níže zadejte adresu svého serveru Jellyfin a přihlaste se k němu.",
|
||||
"shuffle-album": "Zamíchat album",
|
||||
@@ -26,7 +26,7 @@
|
||||
"artists": "Umělci",
|
||||
"queue": "Fronta",
|
||||
"error-reporting-description": "Během používání této aplikace můžete narazit na chyby. Nahlášení těchto chyb pomáhá vytvářet bezpečnější a stabilnější prostředí aplikace.",
|
||||
"set-jellyfin-server": "Nastavit Jellyfin Server",
|
||||
"set-server": "Nastavit Jellyfin Server",
|
||||
"similar-albums": "Podobná alba",
|
||||
"albums": "Alba",
|
||||
"why-use-tracking-description": "Sledování pomáhá urychlit vývoj pro tuto aplikaci tím, že nahlásí divné případy hran a dohledy. To pomáhá, aby aplikace stabilnější a robustní, čímž zlepšuje zážitek z aplikace pro každého.",
|
||||
@@ -52,7 +52,7 @@
|
||||
"disable": "Zakázat",
|
||||
"search": "Vyhledat",
|
||||
"download-playlist": "Stáhnnout seznam skladeb",
|
||||
"jellyfin-library": "Knihovna Jellyfin",
|
||||
"library": "Knihovna Jellyfin",
|
||||
"enable-error-reporting": "Chcete povolit hlášení chyb?",
|
||||
"color-scheme-description": "Ve výchozím nastavení bude Fintunes sledovat barevné schéma vašeho operačního systému. Můžete se však rozhodnout toto nastavení změnit, abyste zajistili, že Fintunes bude vždy v tmavém nebo světlém režimu.",
|
||||
"color-scheme": "Barevné Schéma",
|
||||
@@ -66,7 +66,7 @@
|
||||
"setting-cache": "Mezipaměť",
|
||||
"local-playback": "Místní přehrávání",
|
||||
"clear-queue": "Vymazat Frontu",
|
||||
"set-jellyfin-server-instruction": "Zadejte adresu URL serveru Jellyfin. Nezapomeňte uvést protokol a port",
|
||||
"set-server-instruction": "Zadejte adresu URL serveru Jellyfin. Nezapomeňte uvést protokol a port",
|
||||
"delete-all-tracks": "Smazat Všechny Skladby",
|
||||
"where-is-data-stored": "Kde jsou data uložena?",
|
||||
"color-scheme-light": "Světlý Režim",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"error-reporting": "Fejlrapportering",
|
||||
"music": "Musik",
|
||||
"album": "Album",
|
||||
"jellyfin-server-url": "Jellyfin server URL",
|
||||
"server-url": "Jellyfin server URL",
|
||||
"setting-cache": "Cache",
|
||||
"reset-cache": "Nulstil cache",
|
||||
"enable": "Aktivér",
|
||||
@@ -31,12 +31,12 @@
|
||||
"play-album": "Afspil album",
|
||||
"queue": "Kø",
|
||||
"add-to-queue": "Tilføj til kø",
|
||||
"jellyfin-library": "Jellyfin bibliotek",
|
||||
"jellyfin-user-id": "Jellyfin bruger ID",
|
||||
"library": "Jellyfin bibliotek",
|
||||
"user-id": "Jellyfin bruger ID",
|
||||
"recent-albums": "Seneste albummer",
|
||||
"clear-queue": "Ryd kø",
|
||||
"no-results": "Ingen resultater…",
|
||||
"set-jellyfin-server": "Sæt Jellyfin Server",
|
||||
"set-server": "Sæt Jellyfin Server",
|
||||
"why-use-tracking": "Hvorfor bruge sporing?",
|
||||
"what-data-is-gathered": "Hvilke data indsamles?",
|
||||
"where-is-data-stored": "Hvor gemmes data?",
|
||||
@@ -53,8 +53,8 @@
|
||||
"sleep-timer": "Søvn timer",
|
||||
"onboarding-intro": "Fintunes giver dig mulighed for at streame dit musikbibliotek overalt, med fuld støtte til baggrundslyd og støbning.",
|
||||
"onboarding-cta": "For at komme i gang skal du bruge en Jellyfin server. Klik på knappen nedenfor for at indtaste din Jellyfin-serveradresse og log ind på den.",
|
||||
"set-jellyfin-server-instruction": "Indtast venligst din Jellyfin server URL. Sørg for at inkludere protokollen og havnen",
|
||||
"jellyfin-access-token": "Jellyfin Access Token",
|
||||
"set-server-instruction": "Indtast venligst din Jellyfin server URL. Sørg for at inkludere protokollen og havnen",
|
||||
"access-token": "Jellyfin Access Token",
|
||||
"setting-cache-description": "Hvis du har opdateret dit Jellyfin-bibliotek, men appen holder på cachelagrede aktiver, kan du tvinges til at rydde cachen ved hjælp af denne knap. Dette vil tvinge app til at hente biblioteket fra bunden.",
|
||||
"error-reporting-description": "Under brug af denne app, kan du støde fejl. Rapportering af disse fejl hjælper med at skabe en mere sikker og stabil appoplevelse.",
|
||||
"error-reporting-rationale": "Når du aktiverer fejlrapportering, hver gang en fejl opstår, oprettes en rapport automatisk og sendes til en server, sammen med nyttige fejlfindingsoplysninger såsom enheder, versioner og den specifikke fejl.",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"onboarding-welcome": "Willkommen!",
|
||||
"settings": "Einstellungen",
|
||||
"jellyfin-library": "Jellyfin-Bibliothek",
|
||||
"library": "Jellyfin-Bibliothek",
|
||||
"more-info": "Mehr Informationen",
|
||||
"track": "Titel",
|
||||
"playlists": "Wiedergabelisten",
|
||||
@@ -28,11 +28,11 @@
|
||||
"now-playing": "Läuft gerade",
|
||||
"onboarding-intro": "Mit Fintunes können Sie Ihre Musikbibliothek von überall aus streamen, mit voller Unterstützung für Hintergrundwiedergabe und Casting.",
|
||||
"onboarding-cta": "Um loslegen zu können benötigen Sie einen Jellyfin Server. Klicken Sie auf den Button und geben Sie ihre Jellyfin Serveradresse und Logindaten ein.",
|
||||
"set-jellyfin-server": "Legen Sie den Jellyfin-Server fest",
|
||||
"set-jellyfin-server-instruction": "Bitte geben Sie die URL Ihres Jellyfin-Servers ein. Stellen Sie sicher, dass Sie das Protokoll und den Port angeben",
|
||||
"jellyfin-server-url": "Jellyfin-Server-URL",
|
||||
"jellyfin-access-token": "Jellyfin-Zugriffstoken",
|
||||
"jellyfin-user-id": "Jellyfin-Benutzer-ID",
|
||||
"set-server": "Legen Sie den Jellyfin-Server fest",
|
||||
"set-server-instruction": "Bitte geben Sie die URL Ihres Jellyfin-Servers ein. Stellen Sie sicher, dass Sie das Protokoll und den Port angeben",
|
||||
"server-url": "Jellyfin-Server-URL",
|
||||
"access-token": "Jellyfin-Zugriffstoken",
|
||||
"user-id": "Jellyfin-Benutzer-ID",
|
||||
"setting-cache": "Zwischenspeicher",
|
||||
"setting-cache-description": "Wenn Sie Ihre Jellyfin-Bibliothek aktualisiert haben, aber weiterhin zwischengespeicherte Elemente angezeigt werden kann man mit diesen Button erzwingen, den Zwischenspeicher vollständig zu leeren. Dies zwingt die App Ihre Bibliothek vollständig neu abzurufen.",
|
||||
"reset-cache": "Zwischenspeicher zurücksetzen",
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
"now-playing": "Now Playing",
|
||||
"onboarding-welcome": "Welcome!",
|
||||
"onboarding-intro": "Fintunes will allow you to stream your music library from anywhere, with full support for background audio and casting.",
|
||||
"onboarding-cta": "In order to get started, you need a Jellyfin server. Click the button below to enter your Jellyfin server address and login to it.",
|
||||
"set-jellyfin-server": "Set Jellyfin Server",
|
||||
"set-jellyfin-server-instruction": "Please enter your Jellyfin server URL. Make sure to include the protocol and port",
|
||||
"onboarding-cta": "In order to get started, you need a Jellyfin (or Emby) server. Click the button below to enter your server address and login to it.",
|
||||
"set-server": "Set Server",
|
||||
"set-server-instruction": "Please enter your server URL. Make sure to include the protocol and port",
|
||||
"settings": "Settings",
|
||||
"jellyfin-library": "Jellyfin Library",
|
||||
"jellyfin-server-url": "Jellyfin Server URL",
|
||||
"jellyfin-access-token": "Jellyfin Access Token",
|
||||
"jellyfin-user-id": "Jellyfin User ID",
|
||||
"library": "Library",
|
||||
"server-url": "Server URL",
|
||||
"access-token": "Access Token",
|
||||
"user-id": "User ID",
|
||||
"setting-cache": "Cache",
|
||||
"setting-cache-description": "If you have updated your Jellyfin library, but the app is holding on to cached assets, you can forcefully clear the cache using this button. This will force the app to fetch the library from scratch.",
|
||||
"setting-cache-description": "If you have updated your library, but the app is holding on to cached assets, you can forcefully clear the cache using this button. This will force the app to fetch the library from scratch.",
|
||||
"reset-cache": "Reset Cache",
|
||||
"recent-albums": "Recent Albums",
|
||||
"error-reporting": "Error Reporting",
|
||||
@@ -64,7 +64,7 @@
|
||||
"total-duration": "Total duration",
|
||||
"similar-albums": "Similar albums",
|
||||
"playback-reporting": "Playback Reporting",
|
||||
"playback-reporting-description": "With Playback Reporting, all your playback events are relayed back to Jellyfin. This allows you to track your most listened songs, particularly with Jellyfin plugins such as ListenBrainz.",
|
||||
"playback-reporting-description": "With Playback Reporting, all your playback events are relayed back to your server. This allows you to track your most listened songs, particularly with plugins such as ListenBrainz or LastFM.",
|
||||
"color-scheme": "Color Scheme",
|
||||
"color-scheme-description": "By default, Fintunes will follow your operating system's color scheme. You can however choose to override this to make sure Fintunes is always in dark mode or light mode.",
|
||||
"color-scheme-system": "System",
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
"onboarding-welcome": "Bienvenido!",
|
||||
"onboarding-intro": "Fintunes te permitirá reproducir tu biblioteca musical desde cualquier sitio, con suporte completo para audio en segundo plano y casteo en otros dispositivos.",
|
||||
"onboarding-cta": "Para empezar necesitas un servidor de Jellyfin. Pulsa el botón de abajo para introducir la dirección del servidor y autentifícate con tus credenciales.",
|
||||
"set-jellyfin-server": "Introduce servidor de Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Por favor introduce la URL de tu servidor de Jellyfin. Acuérdate de incluir protocolo y puerto",
|
||||
"set-server": "Introduce servidor de Jellyfin",
|
||||
"set-server-instruction": "Por favor introduce la URL de tu servidor de Jellyfin. Acuérdate de incluir protocolo y puerto",
|
||||
"settings": "Configuración",
|
||||
"jellyfin-library": "Biblioteca Jellyfin",
|
||||
"jellyfin-server-url": "Url del servidor Jellyfin",
|
||||
"jellyfin-access-token": "Token de acceso Jellyfin",
|
||||
"jellyfin-user-id": "ID de usuario Jellyfin",
|
||||
"library": "Biblioteca Jellyfin",
|
||||
"server-url": "Url del servidor Jellyfin",
|
||||
"access-token": "Token de acceso Jellyfin",
|
||||
"user-id": "ID de usuario Jellyfin",
|
||||
"setting-cache": "Caché",
|
||||
"setting-cache-description": "Si actualizó la biblioteca Jellyfin, pero el software aún muestra el contenido anterior, puede hacer clic en el botón a continuación para forzar una actualización. Esto obligará al software a recuperar la información del servidor.",
|
||||
"reset-cache": "Resetear Caché",
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
"onboarding-welcome": "Bienvenue !",
|
||||
"onboarding-intro": "Fintunes vous permettra de diffuser votre bibliothèque musicale de n'importe où, avec un support de la lecture en arrière plan et la diffusion à distance.",
|
||||
"onboarding-cta": "Pour utiliser Fintunes, vous avez besoin d'un serveur Jellyfin. Cliquez sur le bouton ci-dessous pour entrer l'adresse de votre serveur Jellyfin et vous y connecter.",
|
||||
"set-jellyfin-server": "Configurer le serveur Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Veuillez entrer l'URL de votre serveur Jellyfin. Assurez-vous d'inclure le protocole et le port",
|
||||
"set-server": "Configurer le serveur Jellyfin",
|
||||
"set-server-instruction": "Veuillez entrer l'URL de votre serveur Jellyfin. Assurez-vous d'inclure le protocole et le port",
|
||||
"settings": "Réglages",
|
||||
"jellyfin-library": "Bibliothèque Jellyfin",
|
||||
"jellyfin-server-url": "URL du serveur Jellyfin",
|
||||
"jellyfin-access-token": "Jeton d'accès à la Jellyfin",
|
||||
"jellyfin-user-id": "ID utilisateur Jellyfin",
|
||||
"library": "Bibliothèque Jellyfin",
|
||||
"server-url": "URL du serveur Jellyfin",
|
||||
"access-token": "Jeton d'accès à la Jellyfin",
|
||||
"user-id": "ID utilisateur Jellyfin",
|
||||
"setting-cache": "Cache",
|
||||
"setting-cache-description": "Si vous avez mis à jour votre bibliothèque Jellyfin mais que l'application conserve toujours des ressources en cache, vous pouvez vider le cache en utilisant ce bouton. Cela forcera l'application à récupérer l’intégralité de bibliothèque.",
|
||||
"reset-cache": "Réinitialiser le cache",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"jellyfin-server-url": "URL del Server Jellyfin",
|
||||
"server-url": "URL del Server Jellyfin",
|
||||
"settings": "Impostazioni",
|
||||
"why-use-tracking": "Perché utilizzare il Monitoraggio?",
|
||||
"streaming": "Streaming",
|
||||
@@ -23,11 +23,11 @@
|
||||
"onboarding-welcome": "Benvenuto!",
|
||||
"onboarding-intro": "Fintunes ti consentirà di riprodurre in streaming la tua libreria musicale da dove vuoi, con pieno supporto per l'audio di sottofondo e la trasmissione.",
|
||||
"onboarding-cta": "Per iniziare, hai bisogno di un server Jellyfin. Fai clic sul pulsante in basso per inserire l'indirizzo del tuo server Jellyfin e accedere.",
|
||||
"set-jellyfin-server": "Imposta il Server Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Inserisci l'URL del tuo server Jellyfin. Assicurati di includere il protocollo e la porta",
|
||||
"jellyfin-library": "Libreria Jellyfin",
|
||||
"jellyfin-access-token": "Token di Accesso Jellyfin",
|
||||
"jellyfin-user-id": "ID Utente Jellyfin",
|
||||
"set-server": "Imposta il Server Jellyfin",
|
||||
"set-server-instruction": "Inserisci l'URL del tuo server Jellyfin. Assicurati di includere il protocollo e la porta",
|
||||
"library": "Libreria Jellyfin",
|
||||
"access-token": "Token di Accesso Jellyfin",
|
||||
"user-id": "ID Utente Jellyfin",
|
||||
"setting-cache": "Cache",
|
||||
"setting-cache-description": "Se hai aggiornato la tua libreria Jellyfin, ma l'app trattiene le risorse memorizzate nella cache, puoi forzare la cancellazione della cache utilizzando questo pulsante. Ciò costringerà l'app a recuperare la libreria da zero.",
|
||||
"reset-cache": "Reimposta Cache",
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
"onboarding-welcome": "ようこそ。",
|
||||
"onboarding-intro": "Fintunes は、どこからでも音楽ライブラリをストリーミングすることができます。バックグラウンド・オーディオやキャスティングを完全にサポートします。",
|
||||
"onboarding-cta": "始めるためには、Jellyfin サーバーが必要です。下のボタンをクリックして、Jellyfin サーバーのアドレスを入力し、ログインしてください。",
|
||||
"set-jellyfin-server": "Jellyfin サーバ を設定",
|
||||
"set-jellyfin-server-instruction": "Jellyfin サーバの URL を入力してください。プロトコルとポートを必ず含めてください。",
|
||||
"set-server": "Jellyfin サーバ を設定",
|
||||
"set-server-instruction": "Jellyfin サーバの URL を入力してください。プロトコルとポートを必ず含めてください。",
|
||||
"settings": "設定",
|
||||
"jellyfin-library": "Jellyfin ライブライ",
|
||||
"jellyfin-server-url": "Jellyfin サーバの URL",
|
||||
"jellyfin-access-token": "Jellyfin アクセストークン",
|
||||
"jellyfin-user-id": "Jellyfin ユーザ ID",
|
||||
"library": "Jellyfin ライブライ",
|
||||
"server-url": "Jellyfin サーバの URL",
|
||||
"access-token": "Jellyfin アクセストークン",
|
||||
"user-id": "Jellyfin ユーザ ID",
|
||||
"setting-cache": "キャッシュ",
|
||||
"setting-cache-description": "Jellyfinライブラリをアップデートしたにもかかわらず、アプリがキャッシュされたアセットを保持している場合、このボタンを使って強制的にキャッシュをクリアすることができます。これにより、アプリはライブラリを最初から取得するようになります。",
|
||||
"reset-cache": "キャッシュをリセット",
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
"onboarding-welcome": "Velkommen.",
|
||||
"onboarding-intro": "Fintunes lar deg strømme musikkbiblioteket ditt fra hvor som helst, med full støtte for bakgrunnslyd og casting.",
|
||||
"onboarding-cta": "For å begynne trenger du en Jellyfin-tjener. Klikk på knappen nedenfor for å angi Jellyfin-tjeneradressen din og logge på den.",
|
||||
"set-jellyfin-server": "Sett Jellyfin-tjener",
|
||||
"set-jellyfin-server-instruction": "Skriv inn Jellyfin-tjenerens nettadresse. Sørg for å inkludere protokollen og porten.",
|
||||
"set-server": "Sett Jellyfin-tjener",
|
||||
"set-server-instruction": "Skriv inn Jellyfin-tjenerens nettadresse. Sørg for å inkludere protokollen og porten.",
|
||||
"settings": "Innstillinger",
|
||||
"jellyfin-library": "Jellyfin-bibliotek",
|
||||
"jellyfin-server-url": "Jellyfin-tjenernettadresse",
|
||||
"jellyfin-access-token": "Jellyfin-tilgangssymbol",
|
||||
"jellyfin-user-id": "Jellyfin-bruker-ID",
|
||||
"library": "Jellyfin-bibliotek",
|
||||
"server-url": "Jellyfin-tjenernettadresse",
|
||||
"access-token": "Jellyfin-tilgangssymbol",
|
||||
"user-id": "Jellyfin-bruker-ID",
|
||||
"setting-cache": "Mellomlager",
|
||||
"setting-cache-description": "Du tømme hurtiglageret med denne knappen hvis du har oppdatert Jellyfin-biblioteket ditt, men programmet holder på hurtiglagrede eiendeler. Dette vil tvinge programmet til å hente biblioteket fra bunnen av.",
|
||||
"reset-cache": "Tilbakestill hurtiglager",
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
"onboarding-welcome": "Welkom!",
|
||||
"onboarding-intro": "Fintunes maakt het mogelijk om van waar dan ook je muziek te streamen, met volledige support voor achtergroundaudio en casting.",
|
||||
"onboarding-cta": "Om te starten moet je een Jellyfin server hebben. Klik de onderstaande knop om het adres van je Jellyfin server in te vullen en er in te loggen.",
|
||||
"set-jellyfin-server": "Stel Jellyfin Server in",
|
||||
"set-jellyfin-server-instruction": "Vul alsjeblieft je Jellyfin server URL in. Voeg ook het protocol en de poort toe",
|
||||
"set-server": "Stel Jellyfin Server in",
|
||||
"set-server-instruction": "Vul alsjeblieft je Jellyfin server URL in. Voeg ook het protocol en de poort toe",
|
||||
"settings": "Instellingen",
|
||||
"jellyfin-library": "Jellyfin Bibliotheek",
|
||||
"jellyfin-server-url": "Jellyfin Server URL",
|
||||
"jellyfin-access-token": "Jellyfin Toegangstoken",
|
||||
"jellyfin-user-id": "Jellyfin Gebruiker ID",
|
||||
"library": "Jellyfin Bibliotheek",
|
||||
"server-url": "Jellyfin Server URL",
|
||||
"access-token": "Jellyfin Toegangstoken",
|
||||
"user-id": "Jellyfin Gebruiker ID",
|
||||
"setting-cache": "Cache",
|
||||
"setting-cache-description": "Als je Jellyfin bibliotheek geüpdatet hebt, maar de app nog aan elementen uit de cache vasthoudt, kun je de cache geforceerd leegmaken met deze knop. Dit forceert de app om de bibliotheek weer vanaf het begin op te bouwen.",
|
||||
"reset-cache": "Leeg Cache",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"onboarding-welcome": "Witaj!",
|
||||
"onboarding-intro": "Fintunes umożliwia strumieniowe przesyłanie biblioteki muzycznej z dowolnego miejsca, z pełną obsługą dźwięku w tle i przesyłania.",
|
||||
"set-jellyfin-server": "Ustaw Serwer Jellyfin",
|
||||
"set-server": "Ustaw Serwer Jellyfin",
|
||||
"settings": "Ustawienia",
|
||||
"reset-cache": "Zresetuj pamięć podręczną",
|
||||
"color-scheme-light": "Jasny motyw",
|
||||
@@ -19,11 +19,11 @@
|
||||
"music": "Muzyka",
|
||||
"now-playing": "Teraz gra",
|
||||
"onboarding-cta": "Aby rozpocząć pracę, potrzebujesz serwera Jellyfin. Kliknij poniższy przycisk, aby wprowadzić adres serwera Jellyfin i zalogować się do niego.",
|
||||
"set-jellyfin-server-instruction": "Wprowadź adres URL serwera Jellyfin. Upewnij się, że podałeś protokół i port",
|
||||
"jellyfin-library": "Biblioteka Jellyfin",
|
||||
"jellyfin-server-url": "URL do serwera Jellyfin",
|
||||
"jellyfin-access-token": "Token dostępowy do Jellyfin",
|
||||
"jellyfin-user-id": "ID użytkownika Jellyfin",
|
||||
"set-server-instruction": "Wprowadź adres URL serwera Jellyfin. Upewnij się, że podałeś protokół i port",
|
||||
"library": "Biblioteka Jellyfin",
|
||||
"server-url": "URL do serwera Jellyfin",
|
||||
"access-token": "Token dostępowy do Jellyfin",
|
||||
"user-id": "ID użytkownika Jellyfin",
|
||||
"setting-cache": "Pamięć podręczna",
|
||||
"setting-cache-description": "Jeśli zaktualizowałeś bibliotekę Jellyfin, ale aplikacja przechowuje zasoby w pamięci podręcznej, możesz wymusić wyczyszczenie pamięci podręcznej za pomocą tego przycisku. Zmusi to aplikację do pobrania biblioteki od zera.",
|
||||
"recent-albums": "Ostatnie Albumy",
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
"onboarding-welcome": "Boas-vindas!",
|
||||
"onboarding-intro": "O Fintunes permite a você fazer streaming de sua biblioteca de músicas de qualquer lugar, com suporte total para reprodução de áudio em segundo plano e transmissão de áudio.",
|
||||
"onboarding-cta": "Para usar o Fintunes, você precisa de um servidor Jellyfin. Clique no botão abaixo para inserir o endereço do servidor Jellyfin e fazer login.",
|
||||
"set-jellyfin-server": "Configurar o servidor Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Insira a URL do servidor Jellyfin. Certifique-se de incluir o protocolo e a porta",
|
||||
"set-server": "Configurar o servidor Jellyfin",
|
||||
"set-server-instruction": "Insira a URL do servidor Jellyfin. Certifique-se de incluir o protocolo e a porta",
|
||||
"settings": "Configurações",
|
||||
"error-reporting-description": "Durante o uso deste aplicativo, você pode encontrar erros. Relatar esses erros ajuda a criar uma experiência de aplicativo mais segura e estável.",
|
||||
"error-reporting-rationale": "Quando você ativa o relatório de erros, toda vez que ocorre um erro, um relatório é criado automaticamente e enviado a um servidor, juntamente com informações úteis de depuração, como dispositivos, versões e o erro específico.",
|
||||
"jellyfin-library": "Biblioteca do Jellyfin",
|
||||
"jellyfin-server-url": "URL do servidor Jellyfin",
|
||||
"jellyfin-access-token": "Token de acesso do Jellyfin",
|
||||
"jellyfin-user-id": "ID de usuário do Jellyfin",
|
||||
"library": "Biblioteca do Jellyfin",
|
||||
"server-url": "URL do servidor Jellyfin",
|
||||
"access-token": "Token de acesso do Jellyfin",
|
||||
"user-id": "ID de usuário do Jellyfin",
|
||||
"setting-cache": "Cache",
|
||||
"setting-cache-description": "Se você atualizou sua biblioteca do Jellyfin, mas o aplicativo continua usando os recursos em cache, você pode forçar a limpeza do cache usando este botão. Isso forçará o aplicativo a recuperar a biblioteca do zero.",
|
||||
"reset-cache": "Redefinir cache",
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
"onboarding-welcome": "Добро пожаловать!",
|
||||
"onboarding-intro": "Fintunes позволит вам транслировать вашу музыкальную библиотеку из любого места с полной поддержкой фонового воспроизведения и трансляций.",
|
||||
"onboarding-cta": "Для начала вам нужен сервер Jellyfin. Нажмите кнопку ниже, чтобы ввести адрес своего сервера Jellyfin и авторизоваться на нем.",
|
||||
"set-jellyfin-server": "Установить сервер Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Пожалуйста, введите URL вашего сервера Jellyfin. Обязательно укажите протокол и порт",
|
||||
"set-server": "Установить сервер Jellyfin",
|
||||
"set-server-instruction": "Пожалуйста, введите URL вашего сервера Jellyfin. Обязательно укажите протокол и порт",
|
||||
"settings": "Настройки",
|
||||
"jellyfin-library": "Библиотека Jellyfin",
|
||||
"jellyfin-server-url": "URL сервера Jellyfin",
|
||||
"jellyfin-access-token": "Токен доступа Jellyfin",
|
||||
"jellyfin-user-id": "Идентификатор пользователя Jellyfin",
|
||||
"library": "Библиотека Jellyfin",
|
||||
"server-url": "URL сервера Jellyfin",
|
||||
"access-token": "Токен доступа Jellyfin",
|
||||
"user-id": "Идентификатор пользователя Jellyfin",
|
||||
"setting-cache": "Кэш",
|
||||
"setting-cache-description": "Если вы обновили свою библиотеку Jellyfin, но приложение сохраняет кэшированные ресурсы, вы можете принудительно очистить кэш с помощью этой кнопки. Это заставит приложение обновить библиотеку.",
|
||||
"reset-cache": "Сбросить кеш",
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
"search": "Iskanje",
|
||||
"music": "Glasba",
|
||||
"now-playing": "Zdaj igra",
|
||||
"set-jellyfin-server": "Nastavite strežnik Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Vnesite URL svojega strežnika Jellyfin. Ne pozabite vključiti protokola in vrat",
|
||||
"set-server": "Nastavite strežnik Jellyfin",
|
||||
"set-server-instruction": "Vnesite URL svojega strežnika Jellyfin. Ne pozabite vključiti protokola in vrat",
|
||||
"settings": "Nastavitve",
|
||||
"jellyfin-library": "Knjižnica Jellyfin",
|
||||
"jellyfin-server-url": "URL strežnika Jellyfin",
|
||||
"jellyfin-access-token": "Žeton za dostop Jellyfin",
|
||||
"jellyfin-user-id": "ID uporabnika Jellyfin",
|
||||
"library": "Knjižnica Jellyfin",
|
||||
"server-url": "URL strežnika Jellyfin",
|
||||
"access-token": "Žeton za dostop Jellyfin",
|
||||
"user-id": "ID uporabnika Jellyfin",
|
||||
"setting-cache": "Predpomnilnik",
|
||||
"setting-cache-description": "Če ste posodobili knjižnico Jellyfin, vendar aplikacija zadržuje predpomnjena sredstva, lahko s tem gumbom prisilno počistite predpomnilnik. To bo prisililo aplikacijo, da znova pridobi knjižnico.",
|
||||
"reset-cache": "Ponastavi predpomnilnik",
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
"onboarding-welcome": "Välkommen!",
|
||||
"onboarding-intro": "Fintunes låter dig strömma ditt musikbibliotek var som helst, med fullt stöd för bakgrundsljud och casting.",
|
||||
"onboarding-cta": "För att komma igång behöver du en Jellyfin-server. Klicka på knappen nedan för att ange din Jellyfin-serveradress och logga in på den.",
|
||||
"set-jellyfin-server": "Ställ in Jellyfin-server",
|
||||
"set-jellyfin-server-instruction": "Ange din Jellyfin-server-URL. Se till att inkludera protokoll och port",
|
||||
"set-server": "Ställ in Jellyfin-server",
|
||||
"set-server-instruction": "Ange din Jellyfin-server-URL. Se till att inkludera protokoll och port",
|
||||
"settings": "inställningar",
|
||||
"jellyfin-library": "Jellyfin-bibliotek",
|
||||
"jellyfin-server-url": "Jellyfin Server URL",
|
||||
"jellyfin-access-token": "Jellyfin Access Token",
|
||||
"jellyfin-user-id": "Jellyfin användar-ID",
|
||||
"library": "Jellyfin-bibliotek",
|
||||
"server-url": "Jellyfin Server URL",
|
||||
"access-token": "Jellyfin Access Token",
|
||||
"user-id": "Jellyfin användar-ID",
|
||||
"setting-cache": "Cache",
|
||||
"setting-cache-description": "Om du har uppdaterat ditt Jellyfin-bibliotek men appen håller kvar cachelagrade tillgångar kan du tvångsrensa cachen med den här knappen. Detta kommer att tvinga appen att hämta biblioteket från början.",
|
||||
"reset-cache": "Töm cache",
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
"onboarding-welcome": "Ласкаво просимо!",
|
||||
"onboarding-intro": "Fintunes дозволить вам транслювати свою музичну бібліотеку з будь-якого місця з повною підтримкою фонового звуку та трансляції.",
|
||||
"onboarding-cta": "Щоб почати, вам потрібен сервер Jellyfin. Натисніть кнопку нижче, щоб ввести адресу свого сервера Jellyfin і увійти на нього.",
|
||||
"set-jellyfin-server": "Встановити сервер Jellyfin",
|
||||
"set-jellyfin-server-instruction": "Будь ласка, введіть URL-адресу вашого сервера Jellyfin. Не забудьте вказати протокол і порт",
|
||||
"set-server": "Встановити сервер Jellyfin",
|
||||
"set-server-instruction": "Будь ласка, введіть URL-адресу вашого сервера Jellyfin. Не забудьте вказати протокол і порт",
|
||||
"settings": "Налаштування",
|
||||
"jellyfin-library": "Бібліотека Jellyfin",
|
||||
"jellyfin-server-url": "URL-адреса сервера Jellyfin",
|
||||
"jellyfin-access-token": "Токен доступу Jellyfin",
|
||||
"jellyfin-user-id": "ID користувача Jellyfin",
|
||||
"library": "Бібліотека Jellyfin",
|
||||
"server-url": "URL-адреса сервера Jellyfin",
|
||||
"access-token": "Токен доступу Jellyfin",
|
||||
"user-id": "ID користувача Jellyfin",
|
||||
"setting-cache": "Кеш",
|
||||
"setting-cache-description": "Якщо ви оновили свою бібліотеку Jellyfin, але застосунок зберігає кешовані ресурси, ви можете примусово очистити кеш за допомогою цієї кнопки. Це змусить застосунок отримати бібліотеку з нуля.",
|
||||
"reset-cache": "Скинути кеш",
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
"onboarding-welcome": "欢迎",
|
||||
"onboarding-intro": "Fintunes可以在任何地方播放Jellyfin库中的音乐。",
|
||||
"onboarding-cta": "在开始前,你需要一个Jellyfin服务器。点击下方的按钮连接到服务器并登录。",
|
||||
"set-jellyfin-server": "设置Jellyfin服务器",
|
||||
"set-jellyfin-server-instruction": "设置Jellyfin服务器的完整网址,包括HTTP/HTTS和端口。",
|
||||
"set-server": "设置Jellyfin服务器",
|
||||
"set-server-instruction": "设置Jellyfin服务器的完整网址,包括HTTP/HTTS和端口。",
|
||||
"settings": "设置",
|
||||
"jellyfin-library": "Jellyfin库",
|
||||
"jellyfin-server-url": "Jellyfin服务器网址",
|
||||
"jellyfin-access-token": "Jellyfin Access Token",
|
||||
"jellyfin-user-id": "Jellyfin用户ID",
|
||||
"library": "Jellyfin库",
|
||||
"server-url": "Jellyfin服务器网址",
|
||||
"access-token": "Jellyfin Access Token",
|
||||
"user-id": "Jellyfin用户ID",
|
||||
"setting-cache": "缓存",
|
||||
"setting-cache-description": "如果你更新了Jellyfin库,但软件仍显示之前的内容,你可以点击下面的按钮强制刷新。这将强制软件重新从服务器获取信息。",
|
||||
"reset-cache": "清除缓存",
|
||||
|
||||
@@ -13,13 +13,13 @@ export type LocaleKeys = 'play-next'
|
||||
| 'onboarding-welcome'
|
||||
| 'onboarding-intro'
|
||||
| 'onboarding-cta'
|
||||
| 'set-jellyfin-server'
|
||||
| 'set-jellyfin-server-instruction'
|
||||
| 'set-server'
|
||||
| 'set-server-instruction'
|
||||
| 'settings'
|
||||
| 'jellyfin-library'
|
||||
| 'jellyfin-server-url'
|
||||
| 'jellyfin-access-token'
|
||||
| 'jellyfin-user-id'
|
||||
| 'library'
|
||||
| 'server-url'
|
||||
| 'access-token'
|
||||
| 'user-id'
|
||||
| 'setting-cache'
|
||||
| 'setting-cache-description'
|
||||
| 'reset-cache'
|
||||
|
||||
@@ -32,6 +32,7 @@ const HeaderContainer = styled.View`
|
||||
`;
|
||||
|
||||
const NavigationHeader: React.FC = () => {
|
||||
const type = useTypedSelector((state) => state.settings.credentials?.type);
|
||||
const navigation = useNavigation<NavigationProp>();
|
||||
const handleAllAlbumsClick = useCallback(() => { navigation.navigate('Albums'); }, [navigation]);
|
||||
const handlePlaylistsClick = useCallback(() => { navigation.navigate('Playlists'); }, [navigation]);
|
||||
@@ -39,9 +40,17 @@ const NavigationHeader: React.FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListButton onPress={handleAllAlbumsClick} testID="all-albums">{t('all-albums')}</ListButton>
|
||||
<ListButton onPress={handleArtistsClick} testID="artists">{t('artists')}</ListButton>
|
||||
<ListButton onPress={handlePlaylistsClick} testID="playlists">{t('playlists')}</ListButton>
|
||||
<ListButton onPress={handleAllAlbumsClick} testID="all-albums">
|
||||
{t('all-albums')}
|
||||
</ListButton>
|
||||
<ListButton onPress={handleArtistsClick} testID="artists">
|
||||
{t('artists')}
|
||||
</ListButton>
|
||||
{type === 'jellyfin' && (
|
||||
<ListButton onPress={handlePlaylistsClick} testID="playlists">
|
||||
{t('playlists')}
|
||||
</ListButton>
|
||||
)}
|
||||
<ListContainer>
|
||||
<HeaderContainer>
|
||||
<Header>{t('recent-albums')}</Header>
|
||||
|
||||
@@ -114,7 +114,7 @@ const TrackListView: React.FC<TrackListViewProps> = ({
|
||||
return [['0', trackIds]];
|
||||
}
|
||||
|
||||
const groups = groupBy(trackIds, (id) => tracks[id].ParentIndexNumber);
|
||||
const groups = groupBy(trackIds, (id) => tracks[id]?.ParentIndexNumber);
|
||||
return Object.entries(groups);
|
||||
}, [trackIds, tracks, listNumberingStyle]);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ const Logo = styled.Image`
|
||||
|
||||
function Onboarding() {
|
||||
// Get account from Redux and dispatcher
|
||||
const account = useTypedSelector(state => state.settings.jellyfin);
|
||||
const account = useTypedSelector(state => state.settings.credentials);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
// Also retrieve the navigation handler so that we can open the modal in
|
||||
@@ -71,7 +71,7 @@ function Onboarding() {
|
||||
</Text>
|
||||
<ButtonContainer>
|
||||
<Button
|
||||
title={t('set-jellyfin-server')}
|
||||
title={t('set-server')}
|
||||
onPress={handleClick}/>
|
||||
</ButtonContainer>
|
||||
</TextContainer>
|
||||
|
||||
@@ -27,7 +27,7 @@ export function SettingsList() {
|
||||
|
||||
return (
|
||||
<SafeScrollView>
|
||||
<ListButton onPress={handleLibraryClick}>{t('jellyfin-library')}</ListButton>
|
||||
<ListButton onPress={handleLibraryClick}>{t('library')}</ListButton>
|
||||
<ListButton onPress={handleCacheClick}>{t('setting-cache')}</ListButton>
|
||||
<ListButton onPress={handleSentryClick}>{t('error-reporting')}</ListButton>
|
||||
<ListButton onPress={handlePlaybackReportingClick}>{t('playback-reporting')}</ListButton>
|
||||
@@ -50,7 +50,7 @@ export default function Settings() {
|
||||
headerBackground: () => <ColoredBlurView style={StyleSheet.absoluteFill} />,
|
||||
}}>
|
||||
<Stack.Screen name="SettingList" component={SettingsList} options={{ headerTitle: t('settings') }} />
|
||||
<Stack.Screen name="Library" component={Library} options={{ headerTitle: t('jellyfin-library') }} />
|
||||
<Stack.Screen name="Library" component={Library} options={{ headerTitle: t('library') }} />
|
||||
<Stack.Screen name="Cache" component={Cache} options={{ headerTitle: t('setting-cache') }} />
|
||||
<Stack.Screen name="Sentry" component={Sentry} options={{ headerTitle: t('error-reporting') }} />
|
||||
<Stack.Screen name="Playback Reporting" component={PlaybackReporting} options={{ headerTitle: t('playback-reporting')}} />
|
||||
|
||||
@@ -11,25 +11,25 @@ import { InputContainer, Input } from '../components/Input';
|
||||
|
||||
export default function LibrarySettings() {
|
||||
const defaultStyles = useDefaultStyles();
|
||||
const { jellyfin } = useTypedSelector(state => state.settings);
|
||||
const { credentials } = useTypedSelector(state => state.settings);
|
||||
const navigation = useNavigation<NavigationProp>();
|
||||
const handleSetLibrary = useCallback(() => navigation.navigate('SetJellyfinServer'), [navigation]);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<InputContainer>
|
||||
<Paragraph style={defaultStyles.text}>{t('jellyfin-server-url')}</Paragraph>
|
||||
<Input placeholder="https://jellyfin.yourserver.com/" value={jellyfin?.uri} editable={false} style={defaultStyles.input} />
|
||||
<Paragraph style={defaultStyles.text}>{t('server-url')}</Paragraph>
|
||||
<Input placeholder="https://jellyfin.yourserver.com/" value={credentials?.uri} editable={false} style={defaultStyles.input} />
|
||||
</InputContainer>
|
||||
<InputContainer>
|
||||
<Paragraph style={defaultStyles.text}>{t('jellyfin-access-token')}</Paragraph>
|
||||
<Input placeholder="deadbeefdeadbeefdeadbeef" value={jellyfin?.access_token} editable={false} style={defaultStyles.input} />
|
||||
<Paragraph style={defaultStyles.text}>{t('access-token')}</Paragraph>
|
||||
<Input placeholder="deadbeefdeadbeefdeadbeef" value={credentials?.access_token} editable={false} style={defaultStyles.input} />
|
||||
</InputContainer>
|
||||
<InputContainer>
|
||||
<Paragraph style={defaultStyles.text}>{t('jellyfin-user-id')}</Paragraph>
|
||||
<Input placeholder="deadbeefdeadbeefdeadbeef" value={jellyfin?.user_id} editable={false} style={defaultStyles.input} />
|
||||
<Paragraph style={defaultStyles.text}>{t('user-id')}</Paragraph>
|
||||
<Input placeholder="deadbeefdeadbeefdeadbeef" value={credentials?.user_id} editable={false} style={defaultStyles.input} />
|
||||
</InputContainer>
|
||||
<Button title={t('set-jellyfin-server')} onPress={handleSetLibrary} />
|
||||
<Button title={t('set-server')} onPress={handleSetLibrary} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@@ -5,9 +5,50 @@ import { AppState } from '@/store';
|
||||
|
||||
interface Props {
|
||||
serverUrl: string;
|
||||
onCredentialsRetrieved: (credentials: AppState['settings']['jellyfin']) => void;
|
||||
onCredentialsRetrieved: (credentials: AppState['settings']['credentials']) => void;
|
||||
}
|
||||
|
||||
type CredentialEventData = {
|
||||
credentials: {
|
||||
Servers: {
|
||||
ManualAddress: string,
|
||||
ManualAddressOnly: boolean,
|
||||
IsLocalServer: boolean,
|
||||
DateLastAccessed: number,
|
||||
LastConnectionMode: number,
|
||||
Type: string,
|
||||
Name: string,
|
||||
Id: string,
|
||||
UserId: string | null,
|
||||
AccessToken: string | null,
|
||||
Users: {
|
||||
UserId: string,
|
||||
AccessToken: string,
|
||||
}[]
|
||||
LocalAddress: string,
|
||||
RemoteAddress: string,
|
||||
}[]
|
||||
},
|
||||
deviceId: string,
|
||||
type: 'emby',
|
||||
} | {
|
||||
credentials: {
|
||||
Servers: {
|
||||
ManualAddress: string,
|
||||
manualAddressOnly: boolean,
|
||||
DateLastAccessed: number,
|
||||
LastConnectionMode: number,
|
||||
Name: string,
|
||||
Id: string,
|
||||
UserId: string | null,
|
||||
AccessToken: string | null,
|
||||
LocalAddress: string,
|
||||
}[]
|
||||
},
|
||||
deviceId: string,
|
||||
type: 'jellyfin',
|
||||
} | undefined;
|
||||
|
||||
class CredentialGenerator extends Component<Props> {
|
||||
ref = createRef<WebView>();
|
||||
|
||||
@@ -18,12 +59,18 @@ class CredentialGenerator extends Component<Props> {
|
||||
|
||||
checkIfCredentialsAreThere = debounce(() => {
|
||||
// Inject some javascript to check if the credentials can be extracted
|
||||
// from localstore
|
||||
// from localstore. We simultaneously attempt to extract credentials for
|
||||
// any back-end.
|
||||
this.ref.current?.injectJavaScript(`
|
||||
try {
|
||||
let credentials = JSON.parse(window.localStorage.getItem('jellyfin_credentials'));
|
||||
let deviceId = window.localStorage.getItem('_deviceId2');
|
||||
window.ReactNativeWebView.postMessage(JSON.stringify({ credentials, deviceId }))
|
||||
window.ReactNativeWebView.postMessage(JSON.stringify({ credentials, deviceId, type: 'jellyfin' }))
|
||||
} catch(e) { }; true;
|
||||
try {
|
||||
let credentials = JSON.parse(window.localStorage.getItem('servercredentials3'));
|
||||
let deviceId = window.localStorage.getItem('_deviceId2');
|
||||
window.ReactNativeWebView.postMessage(JSON.stringify({ credentials, deviceId, type: 'emby' }))
|
||||
} catch(e) { }; true;
|
||||
`);
|
||||
}, 500);
|
||||
@@ -35,36 +82,73 @@ class CredentialGenerator extends Component<Props> {
|
||||
}
|
||||
|
||||
// Parse the content
|
||||
const data = JSON.parse(event.nativeEvent.data);
|
||||
const data = JSON.parse(event.nativeEvent.data) as CredentialEventData;
|
||||
if (__DEV__) {
|
||||
console.log('Received credential event data: ', JSON.stringify(data));
|
||||
}
|
||||
|
||||
if (!data.deviceId
|
||||
|| !data.credentials?.Servers?.length
|
||||
|| !data.credentials?.Servers[0]?.UserId
|
||||
|| !data.credentials?.Servers[0]?.AccessToken) {
|
||||
// Since Jellyfin and Emby are similar, we'll attempt to extract the
|
||||
// credentials in a generic way.
|
||||
let userId: string | undefined, accessToken: string | undefined;
|
||||
|
||||
// GUARD: Attempt to extract emby format credentials
|
||||
if (data?.type === 'emby'
|
||||
&& data.credentials?.Servers?.length
|
||||
&& data.credentials?.Servers[0]?.Users?.length
|
||||
) {
|
||||
userId = data.credentials.Servers[0].Users[0].UserId;
|
||||
accessToken = data.credentials.Servers[0].Users[0].AccessToken;
|
||||
// GUARD: Attempt to extract jellyfin format credentials
|
||||
} else if (data?.type === 'jellyfin'
|
||||
&& data.credentials?.Servers?.length
|
||||
) {
|
||||
userId = data.credentials.Servers[0].UserId || undefined;
|
||||
accessToken = data.credentials.Servers[0].AccessToken || undefined;
|
||||
}
|
||||
|
||||
// We can extract the deviceId and server address in the same way for
|
||||
// both Jellyfin and Emby.
|
||||
const deviceId = data?.deviceId;
|
||||
const address = data?.credentials?.Servers?.length
|
||||
&& data?.credentials.Servers[0].ManualAddress;
|
||||
|
||||
// GUARD: log extract credentials in dev
|
||||
if (__DEV__) {
|
||||
console.log('Extracted the following credentials:', { userId, accessToken, deviceId, address });
|
||||
}
|
||||
|
||||
// GUARD: Check that all the required credentials are available
|
||||
if (!userId || !accessToken || !deviceId || !address) {
|
||||
if (__DEV__) {
|
||||
console.error('Failed to extract credentials from event');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const { credentials: { Servers: [ credentials ] }, deviceId } = data;
|
||||
|
||||
// Attempt to perform a request using the credentials to see if they're
|
||||
// good
|
||||
const response = await fetch(`${credentials.ManualAddress}/Users/Me`, {
|
||||
const response = await fetch(`${address}/Users/${userId}`, {
|
||||
headers: {
|
||||
'X-Emby-Authorization': `MediaBrowser Client="", Device="", DeviceId="", Version="", Token="${credentials.AccessToken}"`
|
||||
'X-Emby-Authorization': `MediaBrowser Client="", Device="", DeviceId="", Version="", Token="${accessToken}"`
|
||||
}
|
||||
});
|
||||
|
||||
// GUARD: The request must succeed
|
||||
if (response.status !== 200) {
|
||||
if (__DEV__) {
|
||||
const body = await response.text();
|
||||
console.error('Failed to retrieve user object using credentials:', response.status, body);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If a message is received, the credentials should be there
|
||||
this.props.onCredentialsRetrieved({
|
||||
uri: credentials.ManualAddress,
|
||||
user_id: credentials.UserId,
|
||||
access_token: credentials.AccessToken,
|
||||
uri: address,
|
||||
user_id: userId,
|
||||
access_token: accessToken,
|
||||
device_id: deviceId,
|
||||
type: data.type,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export default function SetJellyfinServer() {
|
||||
const navigation = useNavigation();
|
||||
|
||||
// Save creedentials to store and close the modal
|
||||
const saveCredentials = useCallback((credentials: AppState['settings']['jellyfin']) => {
|
||||
const saveCredentials = useCallback((credentials: AppState['settings']['credentials']) => {
|
||||
if (credentials) {
|
||||
dispatch(setJellyfinCredentials(credentials));
|
||||
navigation.dispatch(StackActions.popToTop());
|
||||
@@ -39,7 +39,7 @@ export default function SetJellyfinServer() {
|
||||
) : (
|
||||
<View style={{ padding: 20, flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||
<Text>
|
||||
{t('set-jellyfin-server-instruction')}
|
||||
{t('set-server-instruction')}
|
||||
</Text>
|
||||
<Input
|
||||
placeholder="https://jellyfin.yourserver.io/"
|
||||
@@ -51,7 +51,7 @@ export default function SetJellyfinServer() {
|
||||
style={[ defaultStyles.input, { width: '100%' } ]}
|
||||
/>
|
||||
<Button
|
||||
title={t('set-jellyfin-server')}
|
||||
title={t('set-server')}
|
||||
onPress={() => setIsLogginIn(true)}
|
||||
disabled={!serverUrl?.length}
|
||||
color={defaultStyles.themeColor.color}
|
||||
|
||||
@@ -64,6 +64,23 @@ const persistConfig: PersistConfig<Omit<AppState, '_persist'>> = {
|
||||
}
|
||||
};
|
||||
},
|
||||
// @ts-expect-error migrations are poorly typed
|
||||
5: (state: AppState) => {
|
||||
// @ts-expect-error
|
||||
const credentials = state.settings.jellyfin && {
|
||||
// @ts-expect-error
|
||||
...(state.settings.jellyfin as AppState['settings']['credentials']),
|
||||
type: 'jellyfin',
|
||||
};
|
||||
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...state.settings,
|
||||
credentials,
|
||||
},
|
||||
};
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import { ColorScheme } from './types';
|
||||
|
||||
export const setJellyfinCredentials = createAction<{ access_token: string, user_id: string, uri: string, device_id: string; }>('SET_JELLYFIN_CREDENTIALS');
|
||||
export const setJellyfinCredentials = createAction<{ access_token: string, user_id: string, uri: string, device_id: string; type: 'jellyfin' | 'emby' }>('SET_JELLYFIN_CREDENTIALS');
|
||||
export const setBitrate = createAction<number>('SET_BITRATE');
|
||||
export const setOnboardingStatus = createAction<boolean>('SET_ONBOARDING_STATUS');
|
||||
export const setReceivedErrorReportingAlert = createAction<void>('SET_RECEIVED_ERROR_REPORTING_ALERT');
|
||||
|
||||
@@ -3,11 +3,12 @@ import { setReceivedErrorReportingAlert, setBitrate, setJellyfinCredentials, set
|
||||
import { ColorScheme } from './types';
|
||||
|
||||
interface State {
|
||||
jellyfin?: {
|
||||
credentials?: {
|
||||
uri: string;
|
||||
user_id: string;
|
||||
access_token: string;
|
||||
device_id: string;
|
||||
type: 'jellyfin' | 'emby';
|
||||
}
|
||||
bitrate: number;
|
||||
isOnboardingComplete: boolean;
|
||||
@@ -27,7 +28,7 @@ const initialState: State = {
|
||||
const settings = createReducer(initialState, builder => {
|
||||
builder.addCase(setJellyfinCredentials, (state, action) => ({
|
||||
...state,
|
||||
jellyfin: action.payload,
|
||||
credentials: action.payload,
|
||||
}));
|
||||
builder.addCase(setBitrate, (state, action) => ({
|
||||
...state,
|
||||
|
||||
@@ -36,7 +36,9 @@ export async function retrieveAlbum(id: string): Promise<Album> {
|
||||
const latestAlbumsOptions = {
|
||||
IncludeItemTypes: 'MusicAlbum',
|
||||
Fields: 'DateCreated',
|
||||
SortOrder: 'Ascending',
|
||||
SortOrder: 'Descending',
|
||||
SortBy: 'DateCreated',
|
||||
Recursive: 'true',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -51,7 +53,8 @@ export async function retrieveRecentAlbums(numberOfAlbums = 24) {
|
||||
const params = new URLSearchParams(options).toString();
|
||||
|
||||
// Retrieve albums
|
||||
return fetchApi<Album[]>(({ user_id }) => `/Users/${user_id}/Items/Latest?${params}`);
|
||||
return fetchApi<{ Items: Album[] }>(({ user_id }) => `/Users/${user_id}/Items?${params}`)
|
||||
.then((d) => d.Items);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
import type { AppState, Store } from '@/store';
|
||||
import { Platform } from 'react-native';
|
||||
import { version } from '../../../package.json';
|
||||
|
||||
type Credentials = AppState['settings']['jellyfin'];
|
||||
type Credentials = AppState['settings']['credentials'];
|
||||
|
||||
/** Map the output of `Platform.OS`, so that Jellyfin can understand it. */
|
||||
const deviceMap: Record<typeof Platform['OS'], string> = {
|
||||
ios: 'iOS',
|
||||
android: 'Android',
|
||||
macos: 'macOS',
|
||||
web: 'Web',
|
||||
windows: 'Windows',
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a convenience function that converts a set of Jellyfin credentials
|
||||
@@ -10,7 +21,7 @@ type Credentials = AppState['settings']['jellyfin'];
|
||||
function generateConfig(credentials: Credentials): RequestInit {
|
||||
return {
|
||||
headers: {
|
||||
'X-Emby-Authorization': `MediaBrowser Client="", Device="", DeviceId="", Version="", Token="${credentials?.access_token}"`
|
||||
'X-Emby-Authorization': `MediaBrowser Client="Fintunes", Device="${deviceMap[Platform.OS]}", DeviceId="${credentials?.device_id}", Version="${version}", Token="${credentials?.access_token}"`
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -36,7 +47,7 @@ export async function fetchApi<T>(
|
||||
parseResponse = true
|
||||
) {
|
||||
// Retrieve the latest credentials from the Redux store
|
||||
const credentials = asyncFetchStore().getState().settings.jellyfin;
|
||||
const credentials = asyncFetchStore().getState().settings.credentials;
|
||||
|
||||
// GUARD: Check that the credentials are present
|
||||
if (!credentials) {
|
||||
@@ -95,7 +106,7 @@ export async function fetchApi<T>(
|
||||
* Retrieve an image URL for a given ItemId
|
||||
*/
|
||||
export function getImage(ItemId: string): string {
|
||||
const credentials = asyncFetchStore().getState().settings.jellyfin;
|
||||
const credentials = asyncFetchStore().getState().settings.credentials;
|
||||
const uri = encodeURI(`${credentials?.uri}/Items/${ItemId}/Images/Primary?format=jpeg`);
|
||||
return uri;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ export async function sendPlaybackEvent(
|
||||
ItemId: activeTrack.backendId,
|
||||
CanSeek: true,
|
||||
PlaybackStartTimeTicks: null,
|
||||
PlaySessionId: activeTrack?.backendId || 'fintunes',
|
||||
};
|
||||
|
||||
// Generate a config from the credentials and dispatch the request
|
||||
|
||||
@@ -27,7 +27,7 @@ export async function retrieveAllPlaylists() {
|
||||
* Retrieve all albums that are available on the Jellyfin server
|
||||
*/
|
||||
export async function retrievePlaylistTracks(ItemId: string) {
|
||||
const credentials = asyncFetchStore().getState().settings.jellyfin;
|
||||
const credentials = asyncFetchStore().getState().settings.credentials;
|
||||
const singlePlaylistOptions = {
|
||||
SortBy: 'IndexNumber,SortName',
|
||||
UserId: credentials?.user_id || '',
|
||||
|
||||
@@ -30,7 +30,7 @@ const baseTrackOptions: Record<string, string> = {
|
||||
* Generate the track streaming url from the trackId
|
||||
*/
|
||||
export function generateTrackUrl(trackId: string) {
|
||||
const credentials = store.getState().settings.jellyfin;
|
||||
const credentials = store.getState().settings.credentials;
|
||||
const trackOptions = {
|
||||
...baseTrackOptions,
|
||||
UserId: credentials?.user_id || '',
|
||||
|
||||
Reference in New Issue
Block a user