Compare commits

...

1706 Commits

Author SHA1 Message Date
renovate[bot]
85fec29a3a Update gradle/actions action to v6 2026-04-08 15:33:49 +00:00
Alejandro Delgado Folgado
d301a675a4 Translated using Weblate (Spanish)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2026-04-08 13:26:16 +00:00
Andi Chandler
d87947266a Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2026-04-08 00:26:15 +00:00
Fjuro
d0f5974f86 Translated using Weblate (Czech)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2026-04-07 21:26:16 +00:00
Dzmitry Zubialevich
ccf3c85788 Translated using Weblate (Belarusian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/be/
2026-04-07 08:26:17 +00:00
Dzmitry Zubialevich
e34647548b Translated using Weblate (Belarusian)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-04-07 08:26:16 +00:00
Niels van Velzen
eaf2411a99 Fix missing focus in new player UI (#5513)
* Fix missing focus in new player UI

* Update app/src/main/java/org/jellyfin/androidtv/ui/base/BaseScreen.kt

Co-authored-by: Bill Thornton <thornbill@users.noreply.github.com>

---------

Co-authored-by: Bill Thornton <thornbill@users.noreply.github.com>
2026-04-06 08:44:37 -04:00
renovate[bot]
25dd7515cb Update dependency org.jellyfin.sdk:jellyfin-core to v1.8.8 2026-04-06 12:29:24 +02:00
Gallyam Biktashev
afb55fc06c Translated using Weblate (Russian)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2026-04-06 10:27:22 +00:00
Gargotaire
bacbea0b59 Translated using Weblate (Catalan)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2026-04-06 09:33:58 +00:00
kscop-n1
cdcd528bcc Translated using Weblate (Ukrainian)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2026-04-06 09:33:57 +00:00
Lofuuzi
a8cd75aec3 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-06 07:50:10 +00:00
Pavel Miniutka
cac4958a0b Translated using Weblate (Belarusian)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-04-06 07:50:09 +00:00
Niels van Velzen
19cbfcda3e Fix interaction tracking in popover composable 2026-04-06 07:36:38 +02:00
Kityn
dd7f64d1e0 Translated using Weblate (Polish)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2026-04-06 00:54:39 +00:00
Daniel Aleksander Martinsen
d4c0af73c3 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2026-04-05 23:26:15 +00:00
Lofuuzi
5ab2e91ae8 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-05 18:26:16 +00:00
Bas
62c7a65365 Translated using Weblate (Dutch)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2026-04-05 18:26:16 +00:00
Addi90
c2391f85e4 Translated using Weblate (German)
Currently translated at 100.0% (589 of 589 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2026-04-05 18:26:15 +00:00
renovate[bot]
d1691499a9 Update kotest to v6.1.11 2026-04-05 18:10:53 +02:00
Weblate
fa2fd94a6e Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2026-04-05 15:56:24 +00:00
Lofuuzi
59e918a144 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-05 15:56:23 +00:00
Akhil
de74f641ce Add ability to unblur backdrops (#5216)
* Add preference for enabling background blur on backdrops

* value for strings.xml for enabling backdrop blur feature

* Respect preference option for enabling backdrop blur feature

* update new customization screen

* Added Enum for backdrop state

* Added a new screen for CustomizationBackdrops

* Combined backdrop enabled and blur into a single behavior

modified type to enum , removed checkbox, instead added a subroute, updated BackgroundService to reflect new type values

* rename pref variable and run migration

* Misc fixes

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2026-04-05 17:56:17 +02:00
Lofuuzi
48b5d262bc Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 97.7% (575 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-05 15:40:53 +00:00
Lofuuzi
6fe5a96045 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 97.2% (572 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-05 15:40:37 +00:00
Lofuuzi
9307bb8d81 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 93.5% (550 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-05 15:38:03 +00:00
Lofuuzi
0e0aa4bd26 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 48.9% (288 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-05 08:26:20 +00:00
Lofuuzi
7e2300e5fa Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 16.3% (96 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-05 05:37:27 +00:00
Lofuuzi
a50663a33c Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 16.1% (95 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-04 13:26:16 +00:00
Lofuuzi
1a3d8d8cb0 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 14.1% (83 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-04 10:50:16 +00:00
Lofuuzi
d6453b7224 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/yue_Hant/
2026-04-03 11:26:19 +00:00
Lofuuzi
1d2a0842a6 Translated using Weblate (Cantonese (Traditional Han script))
Currently translated at 5.6% (33 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/yue_Hant/
2026-04-03 11:26:18 +00:00
Dzmitry Zubialevich
cea16ea8d0 Translated using Weblate (Belarusian)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-04-03 11:26:17 +00:00
Niels van Velzen
8415802188 Move in-app screensaver cancellation into compose 2026-04-03 10:07:26 +02:00
Niels van Velzen
c7d8790e17 Use new interaction tracking API in MainActivity 2026-04-03 10:07:26 +02:00
Niels van Velzen
cafd225074 Support interaction tracking within dialogs 2026-04-03 10:07:26 +02:00
Niels van Velzen
74e24efcbf Add new InteractionTracker API to compose to allow for user interaction detection 2026-04-03 10:07:26 +02:00
Niels van Velzen
7600b4a27a Avoid nested composition local providers in JellyfinTheme 2026-04-03 10:07:26 +02:00
Lofuuzi
613ba0ef8b Added translation using Weblate (Cantonese (Traditional Han script)) 2026-04-02 12:37:49 +00:00
renovate[bot]
2242d15a7a Update dependency org.jellyfin.sdk:jellyfin-core to v1.8.7 2026-04-02 00:09:32 +02:00
renovate[bot]
193fa73799 Update kotest to v6.1.10 2026-04-01 11:46:18 +02:00
newton181
af80f41aac Translated using Weblate (Spanish (Latin America))
Currently translated at 93.0% (547 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2026-03-31 22:26:15 +00:00
Jens van Almsick
3e8e059ab2 Change heading from 'Refresh Switching' to 'Resume Preroll' 2026-03-31 16:46:27 +02:00
Niels van Velzen
0fca5d77fe Remove redundant JellyfinTheme usages 2026-03-29 22:08:50 +02:00
Niels van Velzen
b9f8757123 Refactor MainActivity to use compose as basis 2026-03-29 22:08:50 +02:00
Niels van Velzen
72ff0cfae8 Cleanup navigation destinations 2026-03-28 21:55:37 +01:00
Niels van Velzen
1f8cfa0f30 Fix dismissing in-app screensaver with remote 2026-03-28 15:32:38 +01:00
renovate[bot]
64f3bdac41 Update github/codeql-action action to v4.35.1 2026-03-27 19:53:10 +01:00
renovate[bot]
8eaaa39c24 Update androidx.media3 to v1.10.0 2026-03-27 19:48:03 +01:00
renovate[bot]
cbb230a588 Update github/codeql-action action to v4.35.0 2026-03-27 19:47:47 +01:00
renovate[bot]
489780f4ae Update kotest to v6.1.9 2026-03-27 19:47:36 +01:00
Gatis Rīders
b861f7372c Translated using Weblate (Latvian)
Currently translated at 99.1% (583 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lv/
2026-03-27 16:26:15 +00:00
gitlepus
f8aa323580 Translated using Weblate (Croatian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/hr/
2026-03-27 13:26:15 +00:00
renovate[bot]
ab6c32825c Update androidx.compose to v1.10.6 2026-03-25 20:21:07 +01:00
renovate[bot]
b9aabaacec Update dependency androidx.work:work-runtime to v2.11.2 2026-03-25 20:20:49 +01:00
UncleNet41
b8c9b079ee Translated using Weblate (Italian)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2026-03-24 19:47:20 +00:00
renovate[bot]
9436e6966a Update kotest to v6.1.8 2026-03-24 19:43:38 +01:00
deepak r
eb6e931a22 Translated using Weblate (Tamil)
Currently translated at 94.7% (557 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ta/
2026-03-24 18:41:11 +00:00
Denislav Denev
a3f4b112b8 Translated using Weblate (Bulgarian)
Currently translated at 79.0% (465 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2026-03-20 23:17:19 +00:00
renovate[bot]
5bae1198dc Update Gradle to v9.4.1 2026-03-19 20:43:37 +01:00
renovate[bot]
38d0ee6bce Update koin to v4.2.0 2026-03-19 20:43:26 +01:00
Winoox
5d395978a7 Translated using Weblate (Bulgarian)
Currently translated at 78.7% (463 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2026-03-16 23:26:15 +00:00
renovate[bot]
02ec11135c Update androidx.media3 to v1.9.3 2026-03-16 21:02:50 +01:00
renovate[bot]
df0ff6eaa1 Update github/codeql-action action to v4.33.0 2026-03-16 15:26:52 +01:00
renovate[bot]
58a1449766 Update Kotlin to v2.3.20 2026-03-16 15:26:34 +01:00
Dimitar \"Topper\" Maznekov
d07a5d0fc4 Translated using Weblate (Bulgarian)
Currently translated at 76.1% (448 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2026-03-16 08:40:21 +00:00
renovate[bot]
924463bff9 Update kotest to v6.1.7 2026-03-15 14:11:42 +01:00
Andreas Olsson
67c7d7c0d0 Translated using Weblate (Swedish)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2026-03-15 10:26:14 +00:00
Andreas Olsson
db9695d702 Translated using Weblate (Swedish)
Currently translated at 98.8% (581 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2026-03-15 00:26:14 +00:00
lednurb
10d599d5df Translated using Weblate (Dutch)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2026-03-12 19:26:14 +00:00
jasoncoder666
aff07fcbd7 Translated using Weblate (Greek)
Currently translated at 96.0% (565 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2026-03-12 16:26:14 +00:00
renovate[bot]
d8b072383d Update dependency androidx.core:core-ktx to v1.18.0 2026-03-12 08:10:40 +01:00
aniara001
c5de74cf33 Translated using Weblate (Swedish)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/sv/
2026-03-11 22:26:14 +00:00
Bas
e7f51dba01 Translated using Weblate (Dutch)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2026-03-11 20:08:38 +00:00
lednurb
456bb619bc Translated using Weblate (Dutch)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2026-03-11 20:08:38 +00:00
renovate[bot]
2de7bd876a Update kotest to v6.1.6 2026-03-11 20:43:51 +01:00
renovate[bot]
7f0fbba0d2 Update androidx.compose to v1.10.5 2026-03-11 20:43:34 +01:00
renovate[bot]
829a88761f Update androidx.activity to v1.13.0 2026-03-11 20:43:24 +01:00
Antoni Encarnacion Marte
a054d9430e Translated using Weblate (Spanish (Dominican Republic))
Currently translated at 10.8% (64 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_DO/
2026-03-11 03:38:25 +00:00
nextlooper42
cab17b8bee Translated using Weblate (Slovak)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2026-03-10 11:26:14 +00:00
nextlooper42
b87d26d2ed Translated using Weblate (Slovak)
Currently translated at 96.4% (567 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2026-03-10 08:49:06 +00:00
Denislav Denev
e4952e6eba Translated using Weblate (Bulgarian)
Currently translated at 76.0% (447 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2026-03-10 02:26:21 +00:00
Weblate
26c78157d9 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2026-03-09 20:03:59 +00:00
Denislav Denev
8edf76c5dd Translated using Weblate (Bulgarian)
Currently translated at 53.2% (313 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2026-03-09 20:03:57 +00:00
Pavel Miniutka
83183892fd Translated using Weblate (Belarusian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/be/
2026-03-09 08:26:13 +00:00
Bryan
5b8c76c531 Translated using Weblate (Afrikaans)
Currently translated at 10.3% (61 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/af/
2026-03-07 17:26:14 +00:00
queeup
56b16b37c5 Translated using Weblate (Turkish)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2026-03-07 00:26:13 +00:00
makoto
ba4b57ef93 Translated using Weblate (Japanese)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2026-03-06 11:26:14 +00:00
renovate[bot]
4ba1bbc946 Update github/codeql-action action to v4.32.6 2026-03-06 11:56:32 +01:00
Niels van Velzen
aa964647b5 Support Advanced SubStation Alpha direct play 2026-03-05 21:27:48 +01:00
renovate[bot]
e3062edc91 Update android.gradle to v9.1.0 2026-03-04 19:13:44 +01:00
renovate[bot]
2a54faee98 Update Gradle to v9.4.0 2026-03-04 13:39:42 +01:00
Niels van Velzen
3f0d4bdbfc Add next media preloading 2026-03-03 14:07:45 +01:00
Niels van Velzen
4308f46f4d Add timed event blocks and support for negative positions 2026-03-02 19:56:15 +01:00
renovate[bot]
861e00ad1a Update github/codeql-action action to v4.32.5 2026-03-02 19:55:54 +01:00
Niels van Velzen
947ab42e33 Refactor PlayerBackendEventListener to abstract class 2026-03-01 18:04:16 +01:00
renovate[bot]
22f3bafcab Update actions/upload-artifact action to v7 2026-02-27 20:55:01 +01:00
Niels van Velzen
62153f648a Add initial media segment support 2026-02-27 20:53:57 +01:00
Niels van Velzen
6a03b75eb2 Add timed event API 2026-02-27 20:53:57 +01:00
Niels van Velzen
333c8b9630 Move lyrics plugin into own package 2026-02-27 20:53:57 +01:00
Pavel Miniutka
3c9fe12ddc Translated using Weblate (Belarusian)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-02-27 13:03:05 +00:00
Pavel Miniutka
26a83a6bc4 Translated using Weblate (Belarusian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/be/
2026-02-26 09:26:13 +00:00
Pavel Miniutka
978177c48b Translated using Weblate (Belarusian)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-02-26 09:26:13 +00:00
renovate[bot]
afa7d42fa4 Update kotest to v6.1.4 2026-02-25 21:59:06 +01:00
renovate[bot]
5c804a65d3 Update androidx.compose to v1.10.4 2026-02-25 21:58:45 +01:00
renovate[bot]
b15581c8a4 Update coil to v3.4.0 2026-02-24 22:22:38 +01:00
renovate[bot]
fcd3b2dcd6 Update android.gradle to v9.0.1 2026-02-24 13:18:02 +01:00
Dzmitry Zubialevich
c1d1b52fc0 Translated using Weblate (Belarusian)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-02-24 11:09:39 +00:00
renovate[bot]
d6e32b1075 Update gradle/actions action to v5.0.2 2026-02-24 10:32:50 +01:00
renovate[bot]
df610b2ec4 Update github/codeql-action action to v4.32.4 2026-02-20 16:51:07 +01:00
John Doe
c0c2a08572 Translated using Weblate (Finnish)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2026-02-18 14:31:09 +00:00
John Doe
fcff716b28 Translated using Weblate (Finnish)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2026-02-18 14:02:23 +00:00
John Doe
fce6998218 Translated using Weblate (Finnish)
Currently translated at 99.6% (586 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2026-02-18 13:28:23 +00:00
renovate[bot]
fc62714955 Update CI dependencies 2026-02-17 15:41:48 +01:00
Dzmitry Zubialevich
f0a8604acc Translated using Weblate (Belarusian)
Currently translated at 98.9% (582 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-02-16 10:25:23 +00:00
Gargotaire
bd5b10e040 Translated using Weblate (Catalan)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2026-02-14 21:53:54 +00:00
WizardOfYendor1
f6af0b8075 Fix recording from playback overlay by passing programId to timer defaults 2026-02-12 21:43:39 +01:00
Galaterro
ca715d4c10 Show additional parts for episodes 2026-02-12 21:41:15 +01:00
renovate[bot]
967d690139 Update dependency androidx.navigation3:navigation3-ui to v1.0.1 2026-02-11 21:43:26 +01:00
renovate[bot]
53e8a80592 Update androidx.compose to v1.10.3 2026-02-11 21:25:02 +01:00
renovate[bot]
8bb34428f8 Update androidx.activity to v1.12.4 2026-02-11 21:24:42 +01:00
skalthoff
3ab0ae4cf9 Fix non-enum preferences not persisting to server
The generic rememberPreference() overload for non-enum types (Int,
String, etc.) updates the local in-memory cache but never calls
commit() on the AsyncPreferenceStore. This means preferences like
skipForwardLength and skipBackLength are never sent to the server
via the DisplayPreferences API, silently reverting on app restart.

Add the same commit() call that the enum overload already has.
2026-02-11 09:10:50 +01:00
Pavel Miniutka
421ba3704c Translated using Weblate (Belarusian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/be/
2026-02-10 11:05:56 +00:00
Pavel Miniutka
9f2ea8434f Translated using Weblate (Belarusian)
Currently translated at 95.0% (559 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2026-02-10 11:05:56 +00:00
無情天
ad46a348ad Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2026-02-06 21:58:34 +00:00
Niels van Velzen
02f9405c40 Remove unused NumberSpinnerView 2026-02-06 22:43:40 +01:00
Niels van Velzen
a368382262 Check for playAccess in BaseItemDto.canPlay extension 2026-02-06 22:43:35 +01:00
Niels van Velzen
6c7af50a34 Fix item names not showing when showCardInfoOverlay is set 2026-02-06 19:22:58 +01:00
renovate[bot]
8976dc302a Update github/codeql-action action to v4.32.2 2026-02-06 11:53:42 +01:00
renovate[bot]
c24ab17b10 Update androidx.media3 to v1.9.2 2026-02-06 11:53:18 +01:00
Jonas Engen Larsen
4ae28b1f2c Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2026-02-05 23:03:32 +00:00
renovate[bot]
c14e504d8b Update kotest to v6.1.3 2026-02-05 17:52:08 +01:00
renovate[bot]
cf507e8385 Update Kotlin to v2.3.10 2026-02-05 17:46:51 +01:00
Augusto
faaec6a999 Translated using Weblate (Spanish (Argentina))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/es_AR/
2026-02-04 04:05:55 +00:00
JagerSprinkles
3d7f252664 Correct video start delay setting not showing decimal values in settings (#5376) 2026-02-03 13:02:21 +00:00
Niels van Velzen
d41f992b62 Add media type API to set proper content type in audio attributes 2026-02-03 09:00:05 +01:00
Niels van Velzen
7acfc41498 Specify audio attributes in VideoManager 2026-02-02 20:32:57 +01:00
renovate[bot]
067f227983 Update github/codeql-action action to v4.32.1 2026-02-02 20:23:11 +01:00
Flavian Kathurima
b844bf3165 Translated using Weblate (Swahili)
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-02-02 09:06:00 +00:00
Niels van Velzen
0935cc473b Specify JDK version for CI in .tools-versions file 2026-02-01 22:26:11 +01:00
Augusto
ebfa4bba7f Translated using Weblate (Spanish (Argentina))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/es_AR/
2026-02-01 17:05:56 +00:00
Augusto
2b9280f3ef Translated using Weblate (Spanish (Argentina))
Currently translated at 100.0% (588 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_AR/
2026-02-01 17:05:56 +00:00
Flavian Kathurima
258e20f605 Translated using Weblate (Swahili)
Currently translated at 85.8% (505 of 588 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-02-01 09:05:57 +00:00
Weblate
5fa51d489d Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2026-01-31 16:08:00 +00:00
Niels van Velzen
ed0e470a40 Remove unused defaultRatingType setting 2026-01-31 17:07:56 +01:00
Flavian Kathurima
62d68a8485 Translated using Weblate (Swahili)
Currently translated at 68.6% (406 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-31 10:05:56 +00:00
KWeasley
d1d45906cf Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2026-01-30 01:05:55 +00:00
KWeasley
c83d7c62f1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2026-01-29 22:48:43 +00:00
KWeasley
8822076391 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2026-01-29 21:09:32 +00:00
KWeasley
fd9ab5d431 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2026-01-29 20:43:39 +00:00
millallo
d4ff5983a3 Translated using Weblate (Italian)
Currently translated at 98.6% (583 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2026-01-29 20:43:38 +00:00
renovate[bot]
f60a72909d Update Gradle to v9.3.1 2026-01-29 16:30:34 +01:00
Saman Miran
1ef40b614a Remove drop shadows from BrowseGridFragment (#5370) 2026-01-29 15:18:17 +00:00
renovate[bot]
e25acfadd6 Update kotest to v6.1.2 2026-01-29 16:17:30 +01:00
renovate[bot]
92148e9da8 Update dependency io.mockk:mockk to v1.14.9 2026-01-29 16:17:22 +01:00
renovate[bot]
4f700ba9d3 Update CI dependencies 2026-01-29 16:17:06 +01:00
renovate[bot]
69b3fa48be Update androidx.compose to v1.10.2 2026-01-29 16:16:56 +01:00
renovate[bot]
59c1ef00d5 Update dependency androidx.activity:activity to v1.12.3 2026-01-29 16:16:47 +01:00
renovate[bot]
860bfa529e Update dependency androidx.work:work-runtime to v2.11.1 2026-01-29 16:16:37 +01:00
Flavian Kathurima
51cec68bc9 Translated using Weblate (Swahili)
Currently translated at 60.9% (360 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-29 09:40:48 +00:00
Flavian Kathurima
a8d18f70ad Translated using Weblate (Swahili)
Currently translated at 53.4% (316 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-29 08:05:55 +00:00
Jonas Engen Larsen
da0ebbc5ce Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2026-01-29 08:05:54 +00:00
Niels van Velzen
a91e9f9ad3 Update badge styling in ItemCardBaseItemOverlay 2026-01-28 08:29:17 +01:00
Niels van Velzen
153ca1662f Update progress styling in NowPlayingView 2026-01-27 17:06:34 +01:00
renovate[bot]
eb1ef2f295 Update androidx.media3 to v1.9.1 2026-01-26 12:47:58 +01:00
renovate[bot]
aa54863603 Update CI dependencies 2026-01-25 21:46:32 +01:00
renovate[bot]
51ce9dece4 Update kotest to v6.1.1 2026-01-25 21:46:20 +01:00
Gabriel S
0bdcccf29b Translated using Weblate (Romanian)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2026-01-25 18:38:49 +00:00
queeup
7100b26c83 Translated using Weblate (Turkish)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2026-01-25 10:57:19 +00:00
Jógvan Olsen
da38f75a0f Added translation using Weblate (Faroese) 2026-01-25 09:38:32 +00:00
queeup
44682144c8 Translated using Weblate (Turkish)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2026-01-24 23:43:17 +00:00
Niels van Velzen
035a115dc9 Add media toasts to new video player 2026-01-24 18:55:47 +01:00
Andi Chandler
2480b05007 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2026-01-24 04:05:54 +00:00
Deniz ŞAHİN
9184f106a7 Translated using Weblate (Turkish)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2026-01-22 13:40:48 +00:00
rimasx
fc1f469661 Translated using Weblate (Estonian)
Currently translated at 99.8% (590 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2026-01-22 12:33:49 +00:00
renovate[bot]
e7ee94ab82 Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.10.0 2026-01-21 21:36:08 +01:00
markrieder
24aac6a392 Translated using Weblate (Slovak)
Currently translated at 96.4% (570 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2026-01-21 18:05:54 +00:00
Flavian Kathurima
430f0ff689 Translated using Weblate (Swahili)
Currently translated at 51.4% (304 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-20 09:05:55 +00:00
renovate[bot]
3e7e9618c7 Update kotest to v6.1.0 2026-01-20 09:32:22 +01:00
renovate[bot]
5e9bfd4744 Update dependency org.jellyfin.sdk:jellyfin-core to v1.8.6 2026-01-20 09:31:55 +01:00
Flavian Kathurima
9a1a55160a Translated using Weblate (Swahili)
Currently translated at 44.5% (263 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-20 06:56:23 +00:00
Flavian Kathurima
6f0bc196ba Translated using Weblate (Swahili)
Currently translated at 34.5% (204 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-19 13:05:54 +00:00
Flavian Kathurima
96cd70d5a8 Translated using Weblate (Swahili)
Currently translated at 32.1% (190 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-19 10:05:54 +00:00
Niels van Velzen
6ad07f274f Recreate LegacyImageCardView with compose (#5343)
* Recreate LegacyImageCardView with compose

* Fix wrong aspect ratio used for Live TV cards

* Update app/src/main/java/org/jellyfin/androidtv/ui/presentation/CardPresenter.kt
2026-01-19 08:17:35 +00:00
Niels van Velzen
913beda916 Increase amount of cached MediaItems to 10 2026-01-17 17:57:57 +01:00
hoanghuy309
e39877b6f5 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2026-01-17 16:21:03 +00:00
Niels van Velzen
346c21c0b4 Migrate to AGP9 2026-01-17 13:27:28 +01:00
renovate[bot]
60e58e9fdb Update dependency com.android.tools.build:gradle to v9 2026-01-17 13:27:28 +01:00
renovate[bot]
99fb7d38aa Update Gradle to v9.3.0 2026-01-16 19:20:34 +01:00
Tal Sarid
8ac778d39f Translated using Weblate (Hebrew)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2026-01-16 16:05:55 +00:00
Flavian Kathurima
e77593265b Translated using Weblate (Swahili)
Currently translated at 24.3% (144 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-16 11:03:10 +00:00
Flavian Kathurima
eab61bd3a3 Translated using Weblate (Swahili)
Currently translated at 24.1% (143 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-16 08:05:54 +00:00
Flavian Kathurima
2c885a2ba7 Translated using Weblate (Swahili)
Currently translated at 17.2% (102 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-15 11:05:53 +00:00
Flavian Kathurima
9234073344 Translated using Weblate (Swahili)
Currently translated at 16.4% (97 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-15 08:43:44 +00:00
Flavian Kathurima
5d5ffc79ce Translated using Weblate (Swahili)
Currently translated at 8.4% (50 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-15 07:55:29 +00:00
Flavian Kathurima
63a6dca0e2 Translated using Weblate (Swahili)
Currently translated at 1.6% (10 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-15 06:52:32 +00:00
Flavian Kathurima
5189e2931a Translated using Weblate (Swahili)
Currently translated at 1.1% (7 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-15 06:43:03 +00:00
Flavian Kathurima
0eb848c2f2 Translated using Weblate (Swahili)
Currently translated at 0.5% (3 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2026-01-15 06:34:27 +00:00
renovate[bot]
e6a20cb47e Update github/codeql-action action to v4.31.10 2026-01-14 20:57:26 +01:00
renovate[bot]
84476439e7 Update androidx.compose to v1.10.1 2026-01-14 20:52:08 +01:00
Urbán Zoltán
a654d2af68 Translated using Weblate (Hungarian)
Currently translated at 94.4% (558 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2026-01-13 19:32:47 +00:00
Thadah D. Denyse
875ca123bb Translated using Weblate (Basque)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/eu/
2026-01-12 13:05:53 +00:00
Translation expert
341f031660 Translated using Weblate (Arabic)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ar/
2026-01-12 13:05:53 +00:00
nenadsuperzmaj
14920a506e Translated using Weblate (Serbian)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2026-01-12 10:05:54 +00:00
Gallyam Biktashev
690977498c Translated using Weblate (Russian)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2026-01-12 10:05:53 +00:00
Translation expert
6998e6cdbb Translated using Weblate (Arabic)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ar/
2026-01-12 01:14:00 +00:00
Marcos Soares
74535c7c03 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2026-01-10 23:05:53 +00:00
Harvey
25babf42c8 Fix issue playing multiple items remotely (#5017)
* Fix issue starting multiple items remotely

* Use separate code path for starting playback from SocketHandler.onPlayMessage

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2026-01-10 11:13:02 +00:00
Tal Sarid
ce2023a4b1 Show placeholder thumbnail while Trickplay thumbnail loads (#4946) 2026-01-10 11:56:52 +01:00
Kityn
4466b2fd69 Translated using Weblate (Polish)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2026-01-09 21:50:47 +00:00
Dan Tsivinsky
1d6c9a81fc Translated using Weblate (Russian)
Currently translated at 99.6% (589 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2026-01-09 16:05:53 +00:00
vlatka-sinisa
a11ef51851 Translated using Weblate (Croatian)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2026-01-08 23:05:54 +00:00
Weblate
a056ac1e25 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2026-01-08 10:05:55 +00:00
John Doe
05de9bf84b Translated using Weblate (Finnish)
Currently translated at 99.4% (588 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2026-01-08 10:05:53 +00:00
Translation expert
dcd536cd19 Translated using Weblate (Arabic)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ar/
2026-01-08 01:20:46 +00:00
Gallyam Biktashev
bb239f548c Translated using Weblate (Russian)
Currently translated at 98.8% (584 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2026-01-05 18:54:05 +00:00
mihlau
143be2f4f2 Translated using Weblate (Romanian)
Currently translated at 99.3% (587 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2026-01-05 18:54:04 +00:00
mihlau
5312958e3b Translated using Weblate (English (United Kingdom))
Currently translated at 99.3% (587 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2026-01-05 18:54:04 +00:00
Gargotaire
f1590c69be Translated using Weblate (Catalan)
Currently translated at 99.8% (590 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2026-01-05 14:26:06 +00:00
Thunderstrike116
3cb86e356b Translated using Weblate (Greek)
Currently translated at 93.0% (550 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2026-01-05 13:05:53 +00:00
kscop-n1
bb150ba8bf Translated using Weblate (Ukrainian)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2026-01-05 10:46:02 +00:00
takyaO
21d0072d7d Translated using Weblate (Japanese)
Currently translated at 94.9% (561 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2026-01-05 10:46:02 +00:00
Translation expert
df494a9392 Translated using Weblate (Arabic)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ar/
2026-01-05 08:05:52 +00:00
Gabriel S
8d64f1ba63 Translated using Weblate (Romanian)
Currently translated at 96.2% (569 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2026-01-05 08:05:52 +00:00
Antonio Toledo
72ca9cdc66 Translated using Weblate (Spanish)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2026-01-04 22:05:53 +00:00
Fjuro
96d247c2b5 Translated using Weblate (Czech)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2026-01-04 22:05:52 +00:00
Enzo GIOIELLI
a45f5ce626 Translated using Weblate (French)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2026-01-04 00:49:19 +00:00
Niels van Velzen
c69c0ab23d Use space tokens in settings UI 2026-01-03 23:04:42 +01:00
Niels van Velzen
75b5f62e6b Use color tokens for settings UI 2026-01-03 18:52:43 +01:00
Niels van Velzen
5ae1347ec0 Update color tokens 2026-01-03 18:52:43 +01:00
Niels van Velzen
59a36bacf1 Support layout direction in ToolbarLayout 2026-01-03 18:52:29 +01:00
Niels van Velzen
9b321a1b17 Show progress and duration in video player 2026-01-03 16:51:29 +01:00
Niels van Velzen
638bd222fd Remove old preference UI 2026-01-03 14:33:03 +01:00
無情天
9c312645b3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2026-01-03 05:05:53 +00:00
Niels van Velzen
84cdc00115 Migrate advanced playback settings to compose 2026-01-02 23:58:19 +01:00
Finn Möbius
40f4af82bc Translated using Weblate (German)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2026-01-02 17:05:52 +00:00
Niels van Velzen
a01d539b92 Fix 720 and 420 Kbit/s bitrate options not working 2026-01-02 14:49:28 +01:00
AfmanS
f87302d15f Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2026-01-02 13:05:53 +00:00
Niels van Velzen
7c8020ba30 Add shared transitions to RouterContent 2026-01-02 08:36:16 +01:00
Niels van Velzen
068880e780 Fix initial focus on visibility change in DialogBase 2026-01-01 18:29:43 +01:00
Niels van Velzen
2af5ea8c28 Use DialogBase for InAppScreensaver 2026-01-01 18:29:35 +01:00
Niels van Velzen
4f67eeb0d2 Animate settings dialog 2026-01-01 18:05:20 +01:00
Niels van Velzen
875f094ff2 Use sliding transition for settings navigation 2026-01-01 18:05:20 +01:00
Lionel Morin
0f5f1b23fc Translated using Weblate (French)
Currently translated at 99.6% (589 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2026-01-01 00:05:52 +00:00
Kityn
a3f5928349 Translated using Weblate (Polish)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-12-31 19:05:53 +00:00
Bas
105f86b16b Translated using Weblate (Dutch)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-12-31 16:06:00 +00:00
tan
b26b04bddc Translated using Weblate (Thai)
Currently translated at 36.7% (217 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/th/
2025-12-31 16:05:59 +00:00
Translation expert
6d1c48b696 Translated using Weblate (Arabic)
Currently translated at 100.0% (591 of 591 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-12-31 16:05:57 +00:00
Niels van Velzen
2912b830b5 Add explanation about branches to README 2025-12-31 14:56:15 +01:00
Niels van Velzen
ebec491592 Migrate live tv guide settings to compose 2025-12-31 14:56:05 +01:00
Niels van Velzen
00125664ac Migrate library display settings to compose 2025-12-31 11:50:38 +01:00
Niels van Velzen
d38627cb24 Support defaultRouteParameters in ProvideRouter 2025-12-31 11:50:38 +01:00
Niels van Velzen
540a3855b4 Fix rememberPreference not saving for AsyncPreferenceStore 2025-12-30 21:08:29 +01:00
Niels van Velzen
c1f78e5c66 Remove unused server/user preferences UI 2025-12-30 21:08:00 +01:00
Niels van Velzen
cff7ed0d74 Use ListMessage for errors 2025-12-30 21:08:00 +01:00
Niels van Velzen
07f89b2ac2 Don't overwrite displayPreferencesId in ItemRowAdapterHelper.retrieveUserViews 2025-12-30 20:59:12 +01:00
Niels van Velzen
c3ce0bdc4b Migrate home settings to compose 2025-12-30 15:50:09 +01:00
Niels van Velzen
139c8e6202 Migrate libraries settings to compose 2025-12-30 08:56:49 +01:00
Niels van Velzen
0e0f330bc0 Migrate customization settings to compose 2025-12-30 08:56:49 +01:00
Fjuro
022ca79fc8 Translated using Weblate (Czech)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-12-30 03:05:52 +00:00
l00d3r
52bde656d0 Translated using Weblate (Estonian)
Currently translated at 99.6% (588 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-29 19:05:52 +00:00
kscop-n1
9ce1487056 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-12-29 16:05:52 +00:00
Niels van Velzen
5d086b4ca3 Remove profile picture from ClockUserView 2025-12-29 15:45:09 +01:00
Niels van Velzen
184b966491 Add design tokens 2025-12-29 14:40:05 +01:00
renovate[bot]
695bf20d27 Update dependency org.jellyfin.media3:media3-ffmpeg-decoder to v1.9.0+1 2025-12-29 12:14:27 +01:00
ilker
e41e2874b2 Translated using Weblate (Turkish)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/tr/
2025-12-29 11:05:54 +00:00
Gargotaire
df51fc0fea Translated using Weblate (Catalan)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-12-29 11:05:54 +00:00
ilker
42d7078e5c Translated using Weblate (Turkish)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-12-29 11:05:53 +00:00
Thunderstrike116
2c3066b624 Translated using Weblate (Greek)
Currently translated at 93.0% (549 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2025-12-29 11:05:52 +00:00
alxhu
76647acd33 Translated using Weblate (German)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-12-29 07:18:19 +00:00
Translation expert
88ac61fe0b Translated using Weblate (Arabic)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-12-28 23:05:54 +00:00
無情天
b0cd5db981 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-12-28 23:05:54 +00:00
Yofi-FR
d481842b13 Translated using Weblate (French)
Currently translated at 99.8% (589 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-12-28 23:05:53 +00:00
Spillutvikler
d0678c3982 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-12-28 15:05:53 +00:00
Niels van Velzen
81d84e47aa Run build workflow on release branches 2025-12-28 15:30:27 +01:00
Niels van Velzen
df94aadb19 Remove premieresEnabled and mediaManagementEnabled preferences 2025-12-28 15:16:21 +01:00
Niels van Velzen
d05836f755 Migrate screensaver customization settings to compose 2025-12-28 12:14:40 +01:00
Niels van Velzen
f0d4a97e12 Remove shortcut preferences 2025-12-28 12:13:11 +01:00
Kityn
45d0ee8b7d Translated using Weblate (Polish)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-12-28 09:05:52 +00:00
rimasx
ae22ecc1fd Translated using Weblate (Estonian)
Currently translated at 99.4% (587 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-28 06:05:52 +00:00
Niels van Velzen
7bf042f389 Update README build instructions 2025-12-27 20:19:35 +01:00
Bas
a91ae41bb6 Translated using Weblate (Dutch)
Currently translated at 100.0% (590 of 590 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-12-27 19:05:52 +00:00
Niels van Velzen
64763edf4d Allow selecting external video player app 2025-12-27 16:20:35 +01:00
Fjuro
eeb3e95283 Translated using Weblate (Czech)
Currently translated at 100.0% (586 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-12-27 13:05:53 +00:00
Translation expert
f012168d66 Translated using Weblate (Arabic)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ar/
2025-12-27 00:05:52 +00:00
Translation expert
a29926b0c4 Translated using Weblate (Arabic)
Currently translated at 100.0% (586 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-12-27 00:05:52 +00:00
無情天
cae30bdacc Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (586 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-12-26 18:05:52 +00:00
rimasx
3768ac9728 Translated using Weblate (Estonian)
Currently translated at 99.1% (581 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-26 14:05:53 +00:00
koffevar
f2ec78235d Translated using Weblate (Russian)
Currently translated at 99.4% (583 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-12-26 11:05:52 +00:00
User X
fe04c050f1 Translated using Weblate (German)
Currently translated at 100.0% (586 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-12-25 17:05:52 +00:00
Kityn
3a8ca61cdc Translated using Weblate (Polish)
Currently translated at 100.0% (586 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-12-25 09:05:52 +00:00
Bas
30e43e12e7 Translated using Weblate (Dutch)
Currently translated at 100.0% (586 of 586 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-12-24 18:30:27 +00:00
DeDuplicate
b46dba52f8 Translated using Weblate (Hebrew)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-12-24 17:58:43 +00:00
Niels van Velzen
3fbc3a35ca Migrate subtitle customization settings to compose 2025-12-24 18:58:39 +01:00
Niels van Velzen
1c30542802 Add FMP4 support for transcodes 2025-12-24 15:18:47 +01:00
Niels van Velzen
9f328d0281 Fix AVC high 10 reporting as main 10 in device profile 2025-12-24 15:18:40 +01:00
Translation expert
c5c98b4513 Translated using Weblate (Arabic)
Currently translated at 99.4% (569 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-12-23 23:19:12 +00:00
Fjuro
0e0f6c601c Translated using Weblate (Czech)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-12-23 15:05:52 +00:00
takyaO
4bf92183d2 Translated using Weblate (Japanese)
Currently translated at 98.6% (564 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-12-23 08:05:51 +00:00
Niels van Velzen
15bd5a247c Remove value override from RangeControl 2025-12-23 07:27:29 +01:00
Gallyam Biktashev
29dacd490a Translated using Weblate (Russian)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-12-22 19:47:08 +00:00
Niels van Velzen
4158b701c6 Fix range control calculation when minimum is not 0 2025-12-22 15:50:55 +01:00
Gargotaire
4fc21f94bf Translated using Weblate (Catalan)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-12-22 13:05:52 +00:00
Weblate
8dd9545b47 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2025-12-22 10:05:55 +00:00
nenadsuperzmaj
3eea008374 Translated using Weblate (Swahili)
Currently translated at 0.3% (2 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sw/
2025-12-22 10:05:54 +00:00
nenadsuperzmaj
d600fcac38 Translated using Weblate (Serbian)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2025-12-22 10:05:53 +00:00
Maltavius
16f394afa6 Translated using Weblate (Swedish)
Currently translated at 98.9% (566 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2025-12-22 10:05:53 +00:00
Thunderstrike116
e6d8d8671c Translated using Weblate (Greek)
Currently translated at 92.6% (530 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2025-12-22 10:05:52 +00:00
alxhu
2d5f5966e6 Translated using Weblate (German)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-12-22 10:05:51 +00:00
Andi Chandler
69209bb842 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-12-21 21:05:52 +00:00
Niels van Velzen
af62319d11 Use dedicated screen for about section in settings 2025-12-21 15:31:32 +01:00
Bas
beb08e071b Translated using Weblate (Dutch)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-12-20 16:55:09 +00:00
renovate[bot]
629719d75a Update aboutlibraries to v13.2.1 2025-12-20 15:15:26 +01:00
Modac
a32f58d4e0 Translated using Weblate (German)
Currently translated at 99.3% (568 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-12-19 12:55:09 +00:00
jomi
096516b819 Translated using Weblate (Spanish)
Currently translated at 99.6% (570 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-12-19 06:55:09 +00:00
Gabriel S
8a20f864de Translated using Weblate (Romanian)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-12-18 14:55:09 +00:00
Kityn
d9fd231034 Translated using Weblate (Polish)
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-12-18 08:55:08 +00:00
無情天
022cc909f9 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-12-18 01:55:08 +00:00
無情天
fa97921c31 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (572 of 572 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-12-17 23:22:26 +00:00
renovate[bot]
133f189d5c Update Kotlin to v2.3.0 2025-12-17 22:18:53 +01:00
Niels van Velzen
ca57f2e103 Migrate playback settings to compose 2025-12-17 22:17:52 +01:00
renovate[bot]
036ca2bafa Update androidx.media3 to v1.9.0 2025-12-17 22:17:40 +01:00
renovate[bot]
7e0a1529f7 Update androidx.activity to v1.12.2 2025-12-17 22:16:48 +01:00
Niels van Velzen
d38d742cf5 Remove brief descriptions from settings screens 2025-12-17 13:10:47 +01:00
Niels van Velzen
ae52b479e0 Add RangeControl composable and use color tokens for Seekbar 2025-12-17 13:10:34 +01:00
Niels van Velzen
43b41ad4d5 Add footer to ListItemContent 2025-12-17 13:10:20 +01:00
Niels van Velzen
eee0942272 Add ListControl as base for ListButton 2025-12-17 13:10:20 +01:00
DeDuplicate
8bf581dae3 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/he_IL/
2025-12-17 09:55:08 +00:00
DeDuplicate
f7698e205c Translated using Weblate (Hebrew)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-12-17 09:55:08 +00:00
renovate[bot]
964e8eb065 Update github/codeql-action action to v4.31.9 2025-12-16 21:34:42 +01:00
Chris
700220bc07 Translated using Weblate (Swedish)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2025-12-16 10:55:08 +00:00
renovate[bot]
888bfaa05b Update dependency org.jellyfin.sdk:jellyfin-core to v1.8.5 2025-12-16 11:21:27 +01:00
rimasx
46dcc32a38 Translated using Weblate (Estonian)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-15 10:10:59 +00:00
alxhu
701d4b2826 Translated using Weblate (German)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-12-15 10:10:59 +00:00
Translation expert
9c64544a0e Translated using Weblate (Arabic)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ar/
2025-12-14 23:55:09 +00:00
Translation expert
1247475cbf Translated using Weblate (Arabic)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-12-14 23:55:08 +00:00
Merlin Anne Garcia
cb8b690a69 Translated using Weblate (French)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-12-14 23:55:08 +00:00
Jesus Oziel Duran Gonzalez
1a69f77a14 Translated using Weblate (Spanish (Mexico))
Currently translated at 95.0% (535 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_MX/
2025-12-14 23:55:08 +00:00
tobster093
ac89159455 Fix Live TV direct play stability (#5229) 2025-12-14 22:27:33 +01:00
Niels van Velzen
24218f9717 Add ProfilePicture composable 2025-12-14 13:30:44 +01:00
Niels van Velzen
d714d58fef Add SettingsColumn composable and clean up formatting 2025-12-14 13:30:44 +01:00
Niels van Velzen
c6e0badbae Add and use checkbox 2025-12-14 13:30:44 +01:00
renovate[bot]
507127c842 Update actions/upload-artifact action to v6 2025-12-13 16:51:37 +01:00
renovate[bot]
72d5b209f3 Update github/codeql-action action to v4.31.8 2025-12-13 16:51:18 +01:00
queeup
dc781ea86f Translated using Weblate (Turkish)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-12-13 00:55:07 +00:00
Niels van Velzen
66cafdd3c8 Disallow seeking when duration is unknown 2025-12-12 09:21:44 +01:00
Niels van Velzen
25161f11db Use AAC over HLS for music transcoding 2025-12-12 09:21:36 +01:00
rimasx
3c97433a34 Translated using Weblate (Estonian)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-11 14:55:07 +00:00
renovate[bot]
d5783740f7 Update dependency com.android.tools.build:gradle to v8.13.2 2025-12-11 09:23:22 +01:00
Niels van Velzen
a145a437a8 Remove account manager migration 2025-12-11 08:30:28 +01:00
Niels van Velzen
385c6483f3 Use new settings from login screen 2025-12-11 08:30:06 +01:00
Andi Chandler
e339290b53 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-12-09 13:55:07 +00:00
Gargotaire
4dbad2ddc3 Translated using Weblate (Catalan)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-12-09 07:49:19 +00:00
Niels van Velzen
1b4d09a37d Migrate server/user settings to compose 2025-12-09 07:46:12 +01:00
takyaO
73a8945830 Translated using Weblate (Japanese)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-12-09 03:50:16 +00:00
無情天
58714986ae Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-12-08 23:55:07 +00:00
Gianluigi
e4a9b0dc78 Translated using Weblate (Italian)
Currently translated at 99.6% (561 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2025-12-08 16:55:07 +00:00
Resistive
7584e54ed6 Translated using Weblate (Russian)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-12-08 12:20:43 +00:00
Fabrizio Mansilla
b44ac842c9 Translated using Weblate (Spanish (Latin America))
Currently translated at 97.5% (549 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2025-12-08 09:55:11 +00:00
Fabrizio Mansilla
b96f934b49 Translated using Weblate (Spanish (Argentina))
Currently translated at 99.6% (561 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_AR/
2025-12-08 09:55:11 +00:00
kscop-n1
49f386f59d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-12-08 09:55:08 +00:00
Fabrizio Mansilla
74fde37643 Translated using Weblate (Spanish)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-12-08 09:55:07 +00:00
Thunderstrike116
dcc28101e1 Translated using Weblate (Greek)
Currently translated at 92.7% (522 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2025-12-08 09:55:07 +00:00
Kityn
b22b611c22 Translated using Weblate (Polish)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-12-08 06:32:08 +00:00
Bas
2b41879dfa Translated using Weblate (Dutch)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-12-07 23:55:08 +00:00
Fjuro
54ea9bf805 Translated using Weblate (Czech)
Currently translated at 100.0% (563 of 563 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-12-07 23:55:07 +00:00
Niels van Velzen
1868d8eb53 Migrate authentication settings to compose 2025-12-07 22:37:00 +01:00
renovate[bot]
759cc88e61 Update dependency io.mockk:mockk to v1.14.7 2025-12-07 22:16:15 +01:00
Niels van Velzen
a6811b462e Migrate licenses to compose 2025-12-07 16:50:21 +01:00
Niels van Velzen
a2fc550adc Add initial parameter support to router 2025-12-07 16:50:21 +01:00
Niels van Velzen
4461ff1776 Use mutableLongState in SettingsDeveloperScreen 2025-12-07 16:50:21 +01:00
Niels van Velzen
c3a2bb5120 Migrate developer settings to compose 2025-12-07 11:02:20 +01:00
renovate[bot]
5cac1a155e Update github/codeql-action action to v4.31.7 2025-12-06 17:48:56 +01:00
rimasx
ffcfacd893 Translated using Weblate (Estonian)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-06 14:55:08 +00:00
Lionel Morin
98489f603a Translated using Weblate (French)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-12-04 19:56:13 +00:00
Gargotaire
72d67b5e03 Translated using Weblate (Catalan)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-12-04 16:01:16 +00:00
Niels van Velzen
d69d6a29bb Migrate telemetry settings to compose 2025-12-04 09:58:10 +01:00
renovate[bot]
e240769daf Update actions/setup-java action to v5.1.0 2025-12-04 07:34:32 +01:00
renovate[bot]
20ccff5514 Update androidx.compose to v1.10.0 2025-12-03 22:17:29 +01:00
Weblate
ff22b8d666 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2025-12-03 20:55:11 +00:00
Fabrizio Mansilla
08930ce9a9 Translated using Weblate (Spanish (Argentina))
Currently translated at 96.0% (540 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_AR/
2025-12-03 20:55:09 +00:00
Fabrizio Mansilla
740de57703 Translated using Weblate (Spanish)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-12-03 20:55:07 +00:00
renovate[bot]
805bf966e2 Update androidx.activity to v1.12.1 2025-12-03 21:43:57 +01:00
renovate[bot]
fea336522d Update actions/stale action to v10.1.1 2025-12-03 09:13:25 +01:00
Damontecres
6674239bae Add VC-1 to device direct play profile
Adds direct play support for VC-1 video codec on devices with a builtin decoder
2025-12-02 22:48:49 +01:00
renovate[bot]
a0957534a9 Update actions/checkout action to v6.0.1 2025-12-02 21:00:14 +01:00
Niels van Velzen
1c75688935 Use android plugin for AboutLibraries generation 2025-12-02 16:33:17 +01:00
Niels van Velzen
1b0c5bf47b Use compose dialog for DialogBase 2025-12-02 16:26:04 +01:00
Niels van Velzen
ffb74649e6 Add navigation support to settings 2025-12-02 16:25:56 +01:00
Prasanth Baskar
357374d698 Translated using Weblate (Tamil)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ta/
2025-12-02 02:07:07 +00:00
Prasanth Baskar
d6a70bab64 Translated using Weblate (Tamil)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ta/
2025-12-02 02:07:06 +00:00
rimasx
0fbe21882f Translated using Weblate (Estonian)
Currently translated at 99.6% (560 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-01 22:08:57 +00:00
kscop-n1
3f4366c876 Translated using Weblate (Ukrainian)
Currently translated at 99.8% (561 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-12-01 19:46:37 +00:00
刘汉源
d35a1d328d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-12-01 19:46:37 +00:00
AfmanS
f3597cd8ce Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-12-01 19:46:36 +00:00
rimasx
f41f61ebb6 Translated using Weblate (Estonian)
Currently translated at 99.6% (560 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-01 15:55:07 +00:00
rimasx
dd3378b66e Translated using Weblate (Estonian)
Currently translated at 99.6% (560 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-12-01 12:46:22 +00:00
renovate[bot]
98838ed123 Update dependency org.jellyfin.sdk:jellyfin-core to v1.8.4 2025-12-01 12:36:44 +01:00
renovate[bot]
59047e11f8 Update github/codeql-action action to v4.31.6 2025-12-01 12:36:37 +01:00
renovate[bot]
c851c0bb71 Update kotest to v6.0.7 2025-12-01 12:36:27 +01:00
Gallyam Biktashev
47d45b4dc9 Translated using Weblate (Russian)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-12-01 10:55:08 +00:00
Thunderstrike116
d62035bb58 Translated using Weblate (Greek)
Currently translated at 92.7% (521 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2025-12-01 10:55:08 +00:00
lasse_g
a8cf6310b4 Translated using Weblate (German)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-12-01 10:55:07 +00:00
nenadsuperzmaj
5272d851c1 Translated using Weblate (Serbian)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2025-12-01 07:54:58 +00:00
nextlooper42
b8a5525f14 Translated using Weblate (Slovak)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-12-01 07:54:57 +00:00
Gargotaire
de961044ff Translated using Weblate (Catalan)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-12-01 07:21:12 +00:00
takyaO
bd95c13f50 Translated using Weblate (Japanese)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-12-01 07:21:12 +00:00
Fabien
f4ed78a611 Translated using Weblate (French)
Currently translated at 99.8% (561 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-12-01 07:21:12 +00:00
Fjuro
04abc96882 Translated using Weblate (Czech)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-11-30 23:55:07 +00:00
Kityn
3bfff95465 Translated using Weblate (Polish)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-11-30 14:46:51 +00:00
Kityn
d98b8acf22 Translated using Weblate (Polish)
Currently translated at 99.8% (561 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-11-30 14:41:18 +00:00
Bas
81cb9f04ad Translated using Weblate (Dutch)
Currently translated at 100.0% (562 of 562 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-11-30 14:41:17 +00:00
Niels van Velzen
f8ee6de28f Add new settings UI 2025-11-30 15:32:24 +01:00
rimasx
d80032fb7f Translated using Weblate (Estonian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-11-30 14:15:35 +00:00
rimasx
f490064bec Translated using Weblate (Estonian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-11-30 06:19:51 +00:00
rimasx
4b3fe53bda Translated using Weblate (Estonian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-11-30 06:07:52 +00:00
rimasx
98128190d6 Translated using Weblate (Estonian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-11-29 21:46:45 +00:00
rimasx
248fe58381 Translated using Weblate (Estonian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-11-29 16:05:44 +00:00
Jens van Almsick
66573c399f utilize group id for track selection
group ids always start at 0 so we don't need the ```indexStartsAtOne```
parameter anymore
2025-11-29 15:48:28 +01:00
Jens van Almsick
a1e6b17faf clear audio stream index on item start 2025-11-29 15:48:28 +01:00
Niels van Velzen
07e3809227 Fix tinting in account switcher button fallback icon 2025-11-29 15:15:04 +01:00
renovate[bot]
f9e7e735e8 Update appleboy/ssh-action action to v1.2.4 2025-11-29 14:39:54 +01:00
renovate[bot]
f394d17f37 Update github/codeql-action action to v4.31.5 2025-11-27 21:59:13 +01:00
renovate[bot]
72d98710a9 Update kotest to v6.0.5 2025-11-27 21:58:32 +01:00
renovate[bot]
bb0096905f Update actions/checkout action to v6 2025-11-27 21:58:15 +01:00
clams4shoes
da71c6f6a0 Add AV1 detection support for older Android versions (#5186)
* Fix AV1 support on Fire OS

* Use API checks instead of reflection
2025-11-27 21:57:43 +01:00
Douglas Newman
7e95582f89 Fix Vimu Player Integration (#5187)
* fix activity result status code handling for vimu

* Fixup

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2025-11-26 22:08:44 +01:00
Niels van Velzen
50e21994da Update issue templates 2025-11-23 11:08:32 +01:00
José Benigno
009fe70ed3 Translated using Weblate (Galician)
Currently translated at 13.3% (75 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/gl/
2025-11-23 00:55:07 +00:00
José Benigno
6c3d289169 Translated using Weblate (Galician)
Currently translated at 11.0% (62 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/gl/
2025-11-22 16:55:09 +00:00
Oatavandi
a5328eecb0 Translated using Weblate (Tamil)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ta/
2025-11-21 18:55:06 +00:00
Gabriel S
cd1e323616 Translated using Weblate (Romanian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-11-21 13:55:11 +00:00
Gabriel S
3929512331 Translated using Weblate (Romanian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-11-21 10:55:07 +00:00
Gabriel S
73cdfda7af Translated using Weblate (Romanian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-11-21 07:58:57 +00:00
Gabriel S
0337f27942 Translated using Weblate (Romanian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-11-21 00:55:08 +00:00
renovate[bot]
44ff6ebbbf Update androidx.activity to v1.12.0 2025-11-20 09:10:23 +01:00
renovate[bot]
35df230463 Update androidx.lifecycle to v2.10.0 2025-11-20 09:10:10 +01:00
renovate[bot]
d706f937c1 Update dependency androidx.window:window to v1.5.1 2025-11-19 19:49:45 +01:00
renovate[bot]
da950a1e07 Update androidx.compose to v1.9.5 2025-11-19 19:49:30 +01:00
renovate[bot]
07fc2d614a Update Gradle to v9.2.1 2025-11-17 19:11:35 +01:00
renovate[bot]
48357a6f81 Update actions/checkout action to v5.0.1 2025-11-17 19:01:33 +01:00
renovate[bot]
c663982ba0 Update dependency org.jellyfin.sdk:jellyfin-core to v1.8.3 2025-11-17 19:01:26 +01:00
Niels van Velzen
9d9adab416 Fix search input not set to single line 2025-11-17 18:03:41 +01:00
Niels van Velzen
04da7eb69e Do not clear audio stream index when starting item 2025-11-16 21:36:20 +01:00
Niels van Velzen
fd5ff1cdd9 Increase log level for useful debug log messages 2025-11-16 19:51:37 +01:00
Niels van Velzen
7bc34dce91 Use media source instead of item in switchAudioStream 2025-11-16 14:46:41 +01:00
Niels van Velzen
ceaaa51812 Use MediaSource runtime when available 2025-11-16 14:22:46 +01:00
Ivan Noleto
2e2d9ec9b4 Fix play all and shuffle album/artist playback (#5135) 2025-11-16 12:57:59 +01:00
renovate[bot]
9471d4adf4 Update github/codeql-action action to v4.31.3 2025-11-14 20:47:24 +01:00
Ivan Noleto
d3c84df367 Fix music playback sort order to match web client 2025-11-14 20:40:48 +01:00
Niels van Velzen
936e33903c Add badge composable 2025-11-13 20:47:45 +01:00
Niels van Velzen
a377834e35 Remove redundant TargetApi annotations 2025-11-13 19:41:12 +01:00
Niels van Velzen
eb362165b1 Fix getting supportedSampleRates on Fire OS throwing NullPointerException 2025-11-13 19:40:58 +01:00
renovate[bot]
93287746a8 Update dependency com.android.tools.build:gradle to v8.13.1 2025-11-11 17:06:24 +01:00
Niels van Velzen
4d8e432c67 Apply API model changes 2025-11-09 19:21:10 +01:00
Niels van Velzen
5c9b6c625c Update SDK to 1.8.2 2025-11-09 19:21:10 +01:00
Niels van Velzen
0e7f52fd42 Bump upcomingMinimumServerVersion to 10.11 2025-11-09 19:21:10 +01:00
Niels van Velzen
0d9abb9f17 Fix crash in FullDetailsFragmentHelper.resumePlayback 2025-11-09 16:58:41 +01:00
Niels van Velzen
36da60a1e2 Update pull request template 2025-11-08 22:54:09 +01:00
Niels van Velzen
a330cdcc26 Remove display Dolby Vision checks 2025-11-08 22:53:58 +01:00
Niels van Velzen
56ac9ca8ff Disable visibilityThreshold in rememberPlayerProgress 2025-11-08 22:53:49 +01:00
Niels van Velzen
1dba22557d Get audio duration from player instead of item metadata in AudioNowPlayingFragment 2025-11-08 22:53:49 +01:00
Frederik Boster
f748a566dd Fix low quality card images
To avoid low quality card images the scaling is moved to the server-side by requesting images with appropriate dimensions in all cases.

Fixes #4955
2025-11-08 11:44:42 +01:00
renovate[bot]
f5dfa010f8 Update appleboy/ssh-action action to v1.2.3 2025-11-08 11:03:40 +01:00
Niels van Velzen
55f3fd7b05 Infer subtitle format from media stream path for external players 2025-11-07 18:16:54 +01:00
Niels van Velzen
ffc6765cfe Avoid divide by zero in Seekbar 2025-11-06 20:31:01 +01:00
Translation expert
3be558ce91 Translated using Weblate (Arabic)
Currently translated at 99.8% (559 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-11-06 13:45:30 +00:00
Translation expert
d3130e38d1 Translated using Weblate (Arabic)
Currently translated at 99.6% (558 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-11-05 00:01:49 +00:00
Fjuro
25ba439e9c Translated using Weblate (Czech)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/cs/
2025-11-04 19:06:49 +00:00
Fjuro
76d92c3361 Translated using Weblate (Czech)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-11-04 19:06:49 +00:00
renovate[bot]
b07bc3062c Update dependency androidx.window:window to v1.5.0 2025-11-04 15:52:20 +01:00
renovate[bot]
f43dca4b76 Update dependency androidx.work:work-runtime to v2.11.0 2025-11-04 15:46:36 +01:00
Niels van Velzen
278cdb8e0f Require Android 6 at minimum (API 23) 2025-11-04 15:42:07 +01:00
Niels van Velzen
05180de3b4 Enable Proguard 2025-11-04 15:35:09 +01:00
renovate[bot]
d9c27d3849 Update aboutlibraries to v13 2025-11-04 15:34:26 +01:00
renovate[bot]
d5167884f0 Update Gradle to v9.2.0 2025-11-04 15:34:19 +01:00
renovate[bot]
fe8f180354 Update github/codeql-action action to v4.31.2 2025-11-04 15:34:11 +01:00
Jens van Almsick
a1dd6fcfd9 fix: clear only audio stream index on media item start
Before clearPlaybackSessionOptions() was called which also cleared the
subtitle index, but because baking in subs will restart the playback
this lead to an infinite loop.
2025-11-04 15:31:37 +01:00
Thadah D. Denyse
395db1ccf2 Translated using Weblate (Basque)
Currently translated at 50.0% (2 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/eu/
2025-11-03 14:51:53 +00:00
Translation expert
2d89bd4670 Translated using Weblate (Arabic)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ar/
2025-11-02 20:32:12 +00:00
Translation expert
b3711228ab Translated using Weblate (Arabic)
Currently translated at 99.2% (556 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-11-02 20:32:10 +00:00
Niels van Velzen
3fe6ed6f7b Revert "fix: audio track selection on subsequent video media items"
This reverts commit 5c4ebcf7da.
2025-11-01 15:08:02 +01:00
Niels van Velzen
d105175395 Fix speechRecognizer not using BCP47 tag for language extra 2025-10-31 22:13:10 +01:00
Niels van Velzen
30f781741c Fix lyrics not synced on screensaver 2025-10-31 22:12:58 +01:00
Jens van Almsick
5c4ebcf7da fix: audio track selection on subsequent video media items 2025-10-31 19:05:31 +01:00
Themsamsam
b169bbc788 Translated using Weblate (Sinhala)
Currently translated at 50.0% (2 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/si/
2025-10-31 10:51:53 +00:00
Themsamsam
3f7f2292ae Translated using Weblate (Sinhala)
Currently translated at 0.5% (3 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/si/
2025-10-31 10:51:53 +00:00
Themsamsam
14c8cefa09 Added translation using Weblate (Sinhala) 2025-10-31 07:49:40 +00:00
Battseren Badral
411d3cc7af Translated using Weblate (Mongolian)
Currently translated at 31.7% (178 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/mn/
2025-10-29 22:51:54 +00:00
Klara T.
14abfaf6ec Translated using Weblate (Czech)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/cs/
2025-10-29 11:51:53 +00:00
Klara T.
e733fa8d41 Translated using Weblate (Czech)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-10-29 11:51:53 +00:00
Battseren Badral
681deaef99 Translated using Weblate (Mongolian)
Currently translated at 30.8% (173 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/mn/
2025-10-28 21:51:54 +00:00
Battseren Badral
e0dd8882ac Translated using Weblate (Mongolian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/mn/
2025-10-28 18:53:57 +00:00
Battseren Badral
0cb1ea48c6 Translated using Weblate (Mongolian)
Currently translated at 27.6% (155 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/mn/
2025-10-28 18:53:56 +00:00
Gasper Mlinar
ddd5b2cff5 Translated using Weblate (Slovenian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sl/
2025-10-28 15:51:53 +00:00
HanaO00
3cc3cd6ac5 Translated using Weblate (French)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-10-28 15:51:53 +00:00
Niels van Velzen
1e48a53a31 Refactor still watching behavior 2025-10-27 19:46:06 +01:00
kreaxv
2012867344 Translated using Weblate (Mongolian)
Currently translated at 15.3% (86 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/mn/
2025-10-27 11:51:52 +00:00
Niels van Velzen
b5f674530d Reset still watching state on confirmation 2025-10-26 14:13:06 +01:00
renovate[bot]
5ca541e2b0 Update actions/upload-artifact action to v5 2025-10-26 12:53:32 +01:00
renovate[bot]
36afe5a52f Update github/codeql-action action to v4.31.0 2025-10-26 12:53:19 +01:00
renovate[bot]
c698c737c6 Update Kotlin to v2.2.21 2025-10-26 12:53:08 +01:00
renovate[bot]
90e6d00fda Update androidx.compose to v1.9.4 2025-10-22 21:50:27 +02:00
Niels van Velzen
ef53924ccd Remove libass library 2025-10-19 20:42:40 +02:00
Niels van Velzen
3902d6ac93 Fix Live TV timers loaded on main thread 2025-10-19 20:40:50 +02:00
Niels van Velzen
2636e86afb Refactor audio night mode implementation 2025-10-19 20:40:43 +02:00
renovate[bot]
99b27aaac2 Update github/codeql-action action to v4.30.8 2025-10-17 18:44:01 +02:00
zhao-hw
adea5b2163 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-10-17 14:51:26 +00:00
Bas
c87bf43dfc Translated using Weblate (Dutch)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-10-17 14:51:26 +00:00
rimasx
c4f14e8afe Translated using Weblate (Estonian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-10-17 07:51:26 +00:00
Niels van Velzen
f9d5cb546d Add back lifecycle check in response callbacks 2025-10-16 22:12:25 +02:00
renovate[bot]
1708cfe69f Update kotest to v6.0.4 2025-10-16 21:58:48 +02:00
Niels van Velzen
2690754527 Flatten HDR codec profile conditions (#5021)
* Flatten HDR codec profile conditions

* Skip AV1/HEVC specific profile range condition codec profiles when same as display profile

* Address review feedback

* Use applyConditions to work around server behavior
2025-10-16 20:03:59 +02:00
linger
77500f9e0d Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2025-10-15 06:51:25 +00:00
Niels van Velzen
81d09a7036 Fix "shuffle all" not working for music album/artist 2025-10-14 14:05:16 +02:00
Niels van Velzen
3578b53676 Don't show exception message as toast 2025-10-14 14:05:01 +02:00
rimasx
eb17b5f057 Translated using Weblate (Estonian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-10-12 13:51:25 +00:00
Bas
feb32201fa Translated using Weblate (Dutch)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-10-09 19:52:27 +00:00
renovate[bot]
67bbae0c60 Update androidx.compose to v1.9.3 2025-10-08 21:35:20 +02:00
Niels van Velzen
ab473d127d Revert "Add Google TV Streamer to modelsWithDoViHdr10PlusBug"
This reverts commit e340b7267a.
2025-10-08 15:29:45 +02:00
renovate[bot]
27fc47ca52 Update github/codeql-action action to v4 2025-10-07 17:53:12 +02:00
Niels van Velzen
9fb0cc5fa7 Fix direct play of external video sources like Live TV 2025-10-07 17:52:22 +02:00
Niels van Velzen
f61c8a533f Fix direct play and direct stream swapped in PlaybackController retry mechanic 2025-10-07 17:52:15 +02:00
renovate[bot]
7d9b6ebf78 Update actions/stale action to v10.1.0 2025-10-07 17:48:52 +02:00
Niels van Velzen
e340b7267a Add Google TV Streamer to modelsWithDoViHdr10PlusBug 2025-10-07 17:48:29 +02:00
Niels van Velzen
e5f502900a Add KnownDefects as registry for known device bugs 2025-10-07 17:48:29 +02:00
Andrew
4e6bb55ed9 Fix DoVi/HDR10+ playback on Fire TV devices
Adds more device identifiers to the profile report to help find
hardware commonalities behind cross-device issues.
2025-10-07 17:48:29 +02:00
rimasx
2a5af08fc8 Translated using Weblate (Estonian)
Currently translated at 99.4% (557 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-10-07 13:51:25 +00:00
rimasx
ca56a88435 Translated using Weblate (Estonian)
Currently translated at 99.1% (555 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-10-05 11:23:05 +00:00
rimasx
be8cae9acd Translated using Weblate (Estonian)
Currently translated at 94.2% (528 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-10-05 07:51:25 +00:00
Bas
a099462368 Translated using Weblate (Dutch)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-10-04 21:51:25 +00:00
hoanghuy309
e6a5a79c99 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-10-04 09:06:00 +00:00
renovate[bot]
b0403351a1 Update dependency org.jellyfin.sdk:jellyfin-core to v1.7.1 2025-10-03 21:50:49 +02:00
Niels van Velzen
163d7b164c Paying the Bill 2025-10-03 21:46:32 +02:00
Niels van Velzen
8dc4e2c359 Only use 10.11 video range types on 10.11 servers 2025-10-03 21:46:32 +02:00
Niels van Velzen
8418be01a0 Keep track of current server in server repository 2025-10-03 21:46:32 +02:00
renovate[bot]
4ad6daeec0 Update github/codeql-action action to v3.30.6 2025-10-03 21:24:35 +02:00
Niels van Velzen
ac9ade8041 Remove disableDirectPlay option from device profile 2025-10-01 18:07:30 +02:00
Niels van Velzen
4d532f8060 Fix logo constraints in DreamContentLibraryShowcase 2025-10-01 16:11:32 +02:00
renovate[bot]
233ae5df64 Update dependency io.mockk:mockk to v1.14.6 2025-10-01 15:24:30 +02:00
renovate[bot]
910cf301c3 Update gradle/actions action to v5 2025-10-01 15:24:17 +02:00
renovate[bot]
75e269526d Update acra to v5.13.1 2025-10-01 15:12:33 +02:00
Bas
9a0402bb69 Translated using Weblate (Dutch)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-09-30 19:51:24 +00:00
Hallvard Høyland Lavik
97ed08044b Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-09-30 11:51:24 +00:00
renovate[bot]
dac1d35250 Update dependency org.jellyfin.sdk:jellyfin-core to v1.7.0 2025-09-27 11:49:20 +02:00
renovate[bot]
04794b8313 Update github/codeql-action action to v3.30.5 2025-09-27 11:39:48 +02:00
Gianluigi
54a2a06301 Translated using Weblate (Italian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2025-09-25 14:30:48 +00:00
renovate[bot]
f7fb767a48 Update dependency androidx.work:work-runtime to v2.10.5 2025-09-24 20:49:11 +02:00
renovate[bot]
cb589a8e73 Update androidx.compose to v1.9.2 2025-09-24 20:48:51 +02:00
Ricardo Verduguez
59d93c321e Translated using Weblate (Spanish)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-09-24 00:51:24 +00:00
Tal Sarid
c775603df4 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-09-22 10:51:23 +00:00
Niels van Velzen
55c806ff16 Update client name for crash reports 2025-09-21 16:18:47 +02:00
Andrew
4994a26986 Add codec HDR capabilities to device profile 2025-09-21 12:56:45 +02:00
queeup
987022cb6a Translated using Weblate (Turkish)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-09-21 09:40:35 +00:00
Tal Sarid
bc785e58d2 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-09-20 15:51:23 +00:00
renovate[bot]
b9b0d8c127 Update Gradle to v9.1.0 2025-09-19 22:47:39 +02:00
xxzp3
2dbef26bcf Translated using Weblate (Danish)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/da/
2025-09-19 14:51:24 +00:00
nenadsuperzmaj
ce6251e1a7 Translated using Weblate (Serbian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2025-09-19 14:51:23 +00:00
xxzp3
816a0eb778 Translated using Weblate (Danish)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2025-09-19 14:51:23 +00:00
renovate[bot]
e17611170a Update androidx.lifecycle to v2.9.4 2025-09-17 22:19:12 +02:00
nenadsuperzmaj
5502434285 Translated using Weblate (Serbian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2025-09-17 12:51:24 +00:00
Tal Sarid
983e2888cf Made button row height adaptive to its content 2025-09-16 13:46:26 +02:00
gogu
2695e606cc Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-09-14 03:19:55 +00:00
Tal Sarid
7bb1096da6 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-09-12 20:51:23 +00:00
Niels van Velzen
0abeca3020 Avoid stopping speech recognizer when not active 2025-09-11 22:48:33 +02:00
Bas
ba6f54936a Translated using Weblate (Dutch)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-09-11 19:51:23 +00:00
renovate[bot]
f7beea91af Update Kotlin to v2.2.20 2025-09-11 17:19:31 +02:00
renovate[bot]
f0bdf54338 Update github/codeql-action action to v3.30.3 2025-09-11 17:19:09 +02:00
renovate[bot]
f2d4d99ecf Update androidx.activity to v1.11.0 2025-09-11 08:09:57 +02:00
Niels van Velzen
ee806deddb Improve focus switching between Compose and RowsSupportFragment 2025-09-10 23:01:55 +02:00
Tal Sarid
36ff60380f Disabled ImageRequest maxBitmapSize to avoid trickplay tile scaling and cropping issues 2025-09-10 21:13:05 +02:00
renovate[bot]
724867acff Update androidx.compose to v1.9.1 2025-09-10 21:11:23 +02:00
renovate[bot]
01a40dc620 Update dependency androidx.work:work-runtime to v2.10.4 2025-09-10 21:11:07 +02:00
Tal Sarid
e3a2f8fb93 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-09-10 16:44:19 +00:00
Tal Sarid
038ae65123 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-09-10 16:35:04 +00:00
Tal Sarid
8bfb70fad1 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-09-10 10:30:25 +00:00
Tal Sarid
c626cb9f15 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-09-10 10:25:06 +00:00
aricholm
f4a11790e0 Translated using Weblate (Hungarian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2025-09-09 21:51:22 +00:00
Niels van Velzen
bd5f55a374 Fix switching between baked and non-baked subtitles 2025-09-09 22:57:05 +02:00
Niels van Velzen
dde1ecfb29 Fix voice search cancellation showing error toast 2025-09-09 18:30:16 +02:00
Niels van Velzen
0b5525f94b Disable BlurHash on low memory devices 2025-09-09 15:30:44 +02:00
renovate[bot]
d3d8586990 Update CI dependencies 2025-09-09 13:11:39 +02:00
Lucas
3fc8338e33 Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.6% (558 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2025-09-09 04:58:07 +00:00
renovate[bot]
1d206177a3 Update kotest to v6.0.3 2025-09-08 22:41:24 +02:00
Bas
4b6450ba10 Translated using Weblate (Dutch)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-09-08 11:51:22 +00:00
z33k90
b864857c18 Translated using Weblate (Danish)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2025-09-08 07:51:22 +00:00
Niels van Velzen
f0043526d8 Avoid NPE in JellyfinImage helpers 2025-09-05 22:54:21 +02:00
Niels van Velzen
6b0d74efed Remove duplicate hebrew translations 2025-09-05 22:31:30 +02:00
Niels van Velzen
3eb8f14c89 Fix some languages using wrong code 2025-09-05 22:12:57 +02:00
renovate[bot]
fa64bd487a Update github/codeql-action action to v3.30.1 2025-09-05 17:41:46 +02:00
Niels van Velzen
b38f31a947 Fix home navigation from rows to toolbar on older Android versions 2025-09-04 21:30:04 +02:00
Niels van Velzen
bd92af2f46 Fix compilation issues 2025-09-04 18:47:34 +02:00
renovate[bot]
91d25f8ab6 Update dependency org.jellyfin.sdk:jellyfin-core to v1.7.0-beta.6 2025-09-04 18:47:34 +02:00
renovate[bot]
481851041d Update actions/stale action to v10 2025-09-04 18:37:28 +02:00
HanaO00
06beb7f3f9 Translated using Weblate (French)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-09-03 23:51:22 +00:00
renovate[bot]
601bbf7e98 Update kotest to v6.0.2 2025-09-03 21:37:43 +02:00
renovate[bot]
299c2cab90 Update dependency com.android.tools.build:gradle to v8.13.0 2025-09-03 21:33:04 +02:00
renovate[bot]
110e953947 Update github/codeql-action action to v3.30.0 2025-09-03 21:32:39 +02:00
renovate[bot]
be6e7c73de Update koin to v4.1.1 2025-09-03 21:32:34 +02:00
Filip Radić
85b3898a50 Translated using Weblate (Croatian)
Currently translated at 96.7% (542 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2025-09-01 17:51:22 +00:00
Filip Radić
fddfeed271 Translated using Weblate (Croatian)
Currently translated at 95.8% (537 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2025-09-01 12:51:22 +00:00
AfmanS
9c663a90f9 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-09-01 09:51:22 +00:00
Niels van Velzen
0087fb6a02 Use transparent buttons in player controls 2025-08-31 09:21:10 +02:00
Niels van Velzen
0490dc48d5 Use JellyfinTheme in full compose fragments 2025-08-31 09:20:56 +02:00
Gargotaire
679a211c85 Translated using Weblate (Catalan)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-08-30 22:51:22 +00:00
Niels van Velzen
cee87dbc99 Rewrite picture viewer in compose 2025-08-30 14:56:56 +02:00
renovate[bot]
a825b2dac5 Update dependency com.android.tools.build:gradle to v8.12.2 2025-08-29 10:41:22 +02:00
Mark Street
c95041b7ee Trim whitespace from search query (#4885) 2025-08-28 21:21:51 +02:00
renovate[bot]
c69652e120 Update androidx.lifecycle to v2.9.3 2025-08-27 21:00:23 +02:00
Niels van Velzen
0b70ae1fa2 Fix navigation issues in AudioNowPlayingFragment 2025-08-27 09:07:30 +02:00
takyaO
4bce5f4ad7 Translated using Weblate (Japanese)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-08-27 04:51:21 +00:00
takyaO
380a5ed51b Translated using Weblate (Japanese)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ja/
2025-08-26 09:51:22 +00:00
takyaO
b15d200774 Translated using Weblate (Japanese)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-08-26 09:51:22 +00:00
Gargotaire
0601036148 Translated using Weblate (Catalan)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-08-25 22:13:32 +00:00
renovate[bot]
baed90aa2f Update dependency io.kotest:kotest-assertions-core to v6.0.1 2025-08-25 21:17:55 +02:00
Niels van Velzen
619757e1c8 Fix focus always forced to first queue item in AudioNowPlayingFragment 2025-08-25 21:17:24 +02:00
ReDFiRe
43bac2841d Translated using Weblate (Bulgarian)
Currently translated at 50.5% (283 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2025-08-25 15:51:22 +00:00
Maltavius
b1cb69821d Translated using Weblate (Swedish)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2025-08-25 12:51:21 +00:00
Tal Sarid
a305e5eb78 Translated using Weblate (Hebrew)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-08-25 08:51:22 +00:00
Tal Sarid
5724ec718c Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-08-25 08:51:22 +00:00
Filip Radić
1e1a268340 Translated using Weblate (Croatian)
Currently translated at 95.3% (534 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2025-08-25 08:51:22 +00:00
TothCsanad
1f349a9fb6 Translated using Weblate (Hungarian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2025-08-25 08:51:22 +00:00
Gallyam Biktashev
5a47a9beaa Translated using Weblate (Russian)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-08-25 08:51:21 +00:00
Sven
613f241547 Translated using Weblate (German)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-08-25 08:51:21 +00:00
Andi Chandler
0bd4e3db89 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-08-25 00:43:27 +00:00
Tushar Joshi
e72b8ea413 Translated using Weblate (Hindi)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2025-08-24 20:42:55 +00:00
Niels van Velzen
3f0ea9c83b Refactor visibilityTimer into visibility state with support for popover 2025-08-24 21:11:53 +02:00
Niels van Velzen
6a16bb1063 Add previous/next entry buttons within "more options" menu in new video player 2025-08-24 21:11:53 +02:00
Niels van Velzen
61990e09ca Add popover composable 2025-08-24 21:11:53 +02:00
Niels van Velzen
1a80b8e264 Only show music entries in now screensaver now playing 2025-08-24 16:22:42 +02:00
Niels van Velzen
d04d3b9388 Fix seekbar getting stuck in seek mode 2025-08-24 16:22:32 +02:00
Niels van Velzen
ff46f2e7d6 Remove libass preference in non-development builds 2025-08-24 16:22:26 +02:00
renovate[bot]
49cfa77d0b Update kotest to v6 2025-08-24 15:44:50 +02:00
renovate[bot]
28743ddff2 Update github/codeql-action action to v3.29.11 2025-08-24 15:43:41 +02:00
renovate[bot]
324605c39e Update actions/setup-java action to v5 2025-08-24 15:43:31 +02:00
spurdl
81c8af6585 Translated using Weblate (Finnish)
Currently translated at 99.8% (559 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2025-08-22 20:07:47 +00:00
Fjuro
bc607f0f82 Translated using Weblate (Czech)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-08-22 11:51:21 +00:00
無情天
880dd1701b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-08-20 17:51:21 +00:00
nextlooper42
c619c469e0 Translated using Weblate (Slovak)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-08-20 11:45:14 +00:00
myrad2267
65995edc5a Translated using Weblate (French)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-08-20 04:51:21 +00:00
Kityn
44539c59f3 Translated using Weblate (Polish)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-08-19 13:36:12 +00:00
Bas
cb7d7341fa Translated using Weblate (Dutch)
Currently translated at 100.0% (560 of 560 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-08-19 12:37:03 +00:00
renovate[bot]
8c2d22a965 Update github/codeql-action action to v3.29.10 2025-08-19 14:15:39 +02:00
Ruben Teixeira
48dff8ee2b Add preference for subtitle position offset (#4825) 2025-08-19 14:14:51 +02:00
renovate[bot]
66982ca241 Update dependency com.android.tools.build:gradle to v8.12.1 2025-08-18 19:45:37 +02:00
Niels van Velzen
0206159536 Fix scaling of profile pictures in UserCardView 2025-08-18 19:36:08 +02:00
Niels van Velzen
5391bcf1bd Add compose based video player 2025-08-17 08:48:38 +02:00
renovate[bot]
a0879c20a1 Update dependency org.jellyfin.sdk:jellyfin-core to v1.7.0-beta.5 2025-08-16 17:39:14 +02:00
Niels van Velzen
d9be6bcde4 Add display HDR capabilities to device profile 2025-08-16 16:56:50 +02:00
Niels van Velzen
ffdd28ee39 Add display information to playback report 2025-08-16 08:36:46 +02:00
Niels van Velzen
f22bd7cca4 Remove removed parameters from JellyfinImage for user image URLs 2025-08-14 17:58:54 +02:00
Niels van Velzen
f0c874778a Use JellyfinImage in AuthenticationRepository 2025-08-14 17:58:54 +02:00
renovate[bot]
d960fd5ff4 Update dependency org.jellyfin.sdk:jellyfin-core to v1.7.0-beta.4 2025-08-14 17:58:54 +02:00
renovate[bot]
7b7847b43d Update dependency androidx.core:core-ktx to v1.17.0 2025-08-14 11:06:27 +02:00
renovate[bot]
8ae56a42f1 Update Kotlin to v2.2.10 2025-08-14 10:52:41 +02:00
renovate[bot]
110082573f Update dependency io.github.peerless2012:ass-media to v0.3.0-rc03 2025-08-14 09:10:52 +02:00
renovate[bot]
243e40633d Update androidx.compose to v1.9.0 2025-08-14 09:10:35 +02:00
renovate[bot]
19f48287b4 Update dependency androidx.fragment:fragment-ktx to v1.8.9 2025-08-14 09:00:01 +02:00
Vladislav Trofimenko
2eab6be7c8 Translated using Weblate (Russian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-08-13 23:51:21 +00:00
renovate[bot]
f5ca880b93 Update github/codeql-action action to v3.29.9 2025-08-12 20:52:58 +02:00
renovate[bot]
a8b060e498 Update actions/checkout action to v5 2025-08-11 21:53:37 +02:00
TothCsanad
8e25f28287 Translated using Weblate (Hungarian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2025-08-11 18:13:10 +00:00
TothCsanad
8300eb218d Translated using Weblate (Hungarian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2025-08-11 15:47:36 +00:00
Fjuro
3255a8ba8b Translated using Weblate (Czech)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-08-10 19:51:20 +00:00
Niels van Velzen
5a4b7308ec Use new seekbar in DreamContentNowPlaying 2025-08-10 18:02:27 +02:00
Niels van Velzen
0641ba827c Use new seekbar in AudioNowPlayingFragment 2025-08-10 18:02:27 +02:00
Niels van Velzen
0296131026 Add new Seekbar composable 2025-08-10 18:02:27 +02:00
Niels van Velzen
cb3ba76876 Use toolbar clock in screensaver 2025-08-10 18:02:27 +02:00
Niels van Velzen
e7d6b7bd70 Fix division by zero issue in VideoSize.aspectRatio 2025-08-10 13:36:32 +02:00
Niels van Velzen
14a6ba6002 Fix warning logs in PlaySessionService 2025-08-10 13:36:32 +02:00
Niels van Velzen
8df9200bb0 Add scrubbing API 2025-08-10 13:36:32 +02:00
Andi Chandler
9a28bfb7ae Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/en_GB/
2025-08-10 01:51:38 +00:00
Andi Chandler
e797272c5c Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-08-10 00:55:09 +00:00
Adithya Krishna
cf4413ddb0 Translated using Weblate (Malayalam)
Currently translated at 50.4% (282 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ml/
2025-08-09 15:01:24 +00:00
Adithya Krishna
fb7275e0e6 Translated using Weblate (Malayalam)
Currently translated at 38.4% (215 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ml/
2025-08-09 14:27:55 +00:00
Julio García
3bd6187c21 Translated using Weblate (Spanish)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/es/
2025-08-09 10:51:21 +00:00
Julio García
61309e0c51 Translated using Weblate (Spanish)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-08-09 10:51:21 +00:00
Tal Sarid
c3080d7bf2 Fix wrong Trickplay thumbnail displayed while seeking (#4819) 2025-08-08 19:21:36 +00:00
renovate[bot]
671d6974b6 Update github/codeql-action action to v3.29.8 2025-08-08 21:17:19 +02:00
newton181
13e859f01b Translated using Weblate (Spanish (Latin America))
Currently translated at 98.0% (548 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2025-08-06 00:23:43 +00:00
renovate[bot]
96e34b019b Update gradle/actions action to v4.4.2 2025-08-05 14:29:43 +02:00
Niels van Velzen
323b412dca Target Android 16 (API 36) 2025-08-03 13:49:34 +02:00
Niels van Velzen
870f027715 Remove logo from screensaver 2025-08-03 13:48:27 +02:00
Ruben Teixeira
e4aec294e3 Finer subtitle size control (#4821) 2025-08-03 11:40:03 +02:00
renovate[bot]
03179b134c Update dependency gradle to v9 2025-08-03 11:31:05 +02:00
renovate[bot]
2579090d61 Update dependency com.android.tools.build:gradle to v8.12.0 2025-08-03 11:30:51 +02:00
Niels van Velzen
b4982babec Use audio API for audio playback 2025-08-03 09:57:02 +02:00
Adriano Vargas IFFAR
0d8d30055e Translated using Weblate (Portuguese)
Currently translated at 11.6% (65 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-08-01 03:26:13 +00:00
Niels van Velzen
83f95c9c74 Update app build script for Gradle 9 compatibility 2025-07-31 22:53:25 +02:00
renovate[bot]
e30e9928d1 Update androidx.media3 2025-07-31 22:53:10 +02:00
renovate[bot]
f0094f265d Update github/codeql-action action to v3.29.5 2025-07-31 19:32:30 +02:00
renovate[bot]
aa48a90dd3 Update dependency androidx.work:work-runtime to v2.10.3 2025-07-31 10:33:57 +02:00
Troj@
451a2e0558 Translated using Weblate (Belarusian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2025-07-29 11:40:25 +00:00
Troj@
8987c16d7c Translated using Weblate (Belarusian)
Currently translated at 98.3% (550 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2025-07-29 08:56:45 +00:00
Troj@
4b7e21268d Translated using Weblate (Belarusian)
Currently translated at 96.4% (539 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2025-07-29 08:23:20 +00:00
Troj@
e92dbb15b7 Translated using Weblate (Belarusian)
Currently translated at 94.4% (528 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2025-07-29 08:11:18 +00:00
Gargotaire
7212ad40d8 Translated using Weblate (Catalan)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-07-28 00:58:07 +00:00
Niels van Velzen
9029795c74 Render ASS to custom view 2025-07-27 21:48:13 +02:00
Maltavius
d7b60b057e Translated using Weblate (Swedish)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2025-07-26 09:18:45 +00:00
Cabeça De Bode
3a495efeae Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.8% (558 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2025-07-25 15:22:36 +00:00
renovate[bot]
e41886ce60 Update github/codeql-action action to v3.29.4 2025-07-24 21:34:52 +02:00
Niels van Velzen
8d28a22337 Run Detekt from root module only 2025-07-24 21:30:01 +02:00
Shreyas Math
d5d1954aa6 Translated using Weblate (Hindi)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2025-07-24 14:51:19 +00:00
Shreyas Math
8282cba0f1 Translated using Weblate (Hindi)
Currently translated at 86.2% (482 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2025-07-24 11:51:20 +00:00
renovate[bot]
e116e467f6 Update coil to v3.3.0 2025-07-23 08:46:30 +02:00
renovate[bot]
98bf2151cd Update github/codeql-action action to v3.29.3 2025-07-22 21:45:38 +02:00
Niels van Velzen
e859986075 Remove WebSocket subscriptions when process is inactive 2025-07-20 18:54:21 +02:00
Gargotaire
f7d96f7be1 Translated using Weblate (Catalan)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-07-19 14:34:33 +00:00
SaddFox
378acb9571 Translated using Weblate (Slovenian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sl/
2025-07-18 21:23:01 +00:00
SaddFox
b6d114f55c Translated using Weblate (Slovenian)
Currently translated at 98.9% (553 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sl/
2025-07-18 20:41:54 +00:00
Niels van Velzen
9baf348fa7 Differentiate client name for debug version in API authorization 2025-07-18 22:35:20 +02:00
Niels van Velzen
52b15b2572 Prefer imageVector painting for icon drawables 2025-07-18 09:30:10 +02:00
Bernardo Oliveira
180325060a Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-07-18 00:55:45 +00:00
Niels van Velzen
fe528df011 Catch API issues in StartupActivity when opening a library 2025-07-17 22:36:41 +02:00
renovate[bot]
d76fbb8f85 Update androidx.lifecycle to v2.9.2 2025-07-16 22:55:02 +02:00
renovate[bot]
53ad0bc032 Update dependency io.mockk:mockk to v1.14.5 2025-07-16 22:54:43 +02:00
Niels van Velzen
d193945d37 Use round design in NowPlayingView 2025-07-16 22:50:24 +02:00
Niels van Velzen
784df130a1 Redesign main toolbar 2025-07-16 22:50:24 +02:00
madman38
f8d0c1274c Translated using Weblate (Turkish)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-07-16 16:51:19 +00:00
kylep09
df2e2fab01 Start Live TV player when activating channel header (#4777) 2025-07-15 13:33:36 +00:00
sharanchius
0c9f08286c Translated using Weblate (Lithuanian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2025-07-14 15:51:18 +00:00
felix920506
d542095c36 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2025-07-14 11:51:18 +00:00
Niels van Velzen
184564c807 Fix AsyncImageView.load showing incorrect images on rapid changes 2025-07-14 08:43:26 +02:00
Niels van Velzen
2fc45565f1 Refetch server information on authenticate when cached server version is unsupported 2025-07-13 19:49:57 +02:00
Niels van Velzen
cf572a16d8 Query based on seriesId in FullDetailsFragmentHelper.getNextUpEpisode 2025-07-13 19:49:46 +02:00
Niels van Velzen
e774a39075 Fix DreamViewModel retrieving showcase items over main thread 2025-07-13 19:49:36 +02:00
sharanchius
61440368e2 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2025-07-13 11:51:18 +00:00
Niels van Velzen
dee024b88a Support removing items from playback queue 2025-07-13 11:17:12 +02:00
Niels van Velzen
9712f0cc44 Use shared OkHttpFactory for SDK, Coil and ExoPlayer
With this change all networking in the app is extended from the same base OkHttpClient making their connection pool, caches, dns and more shared
2025-07-13 11:10:40 +02:00
Niels van Velzen
f64b704abc Resolve compile errors 2025-07-13 11:10:40 +02:00
Niels van Velzen
d5923f4f23 Update SDK to 1.7.0-beta.3 2025-07-13 11:10:40 +02:00
Niels van Velzen
597b723885 Always run MediaStreamResolver on IO thread 2025-07-12 15:28:45 +02:00
Niels van Velzen
052c96a4b5 Remove testStream parameter from MediaStreamResolver.getStream 2025-07-12 15:28:45 +02:00
renovate[bot]
5404b697c6 Update dependency com.android.tools.build:gradle to v8.11.1 2025-07-12 14:54:51 +02:00
oofybruh9
4d8074d350 Translated using Weblate (Spanish)
Currently translated at 98.0% (548 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-07-10 04:51:18 +00:00
Buiko32
8d54e56d55 Translated using Weblate (Italian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2025-07-08 23:51:18 +00:00
Jens van Almsick
0e3bba9853 Keep same audio language while binge watching a series (#4713) 2025-07-06 09:47:52 +02:00
renovate[bot]
e1f5e47bff Update dependency gradle to v8.14.3 2025-07-05 11:31:00 +02:00
Tal Sarid
21985945a2 Translated using Weblate (Hebrew)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/he/
2025-07-04 11:25:16 +00:00
Tal Sarid
6e9480235a Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/he_IL/
2025-07-04 11:25:16 +00:00
Jay Halani
bd2934f725 Translated using Weblate (Hindi)
Currently translated at 54.9% (307 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2025-07-04 08:51:18 +00:00
queeup
6c47a6879c Translated using Weblate (Turkish)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-07-03 22:51:17 +00:00
kylep09
c1e144da32 Fix LiveTV Guide Issue #2144 (#4761) 2025-07-02 09:27:39 +02:00
Айдаев Найдан Александрович
13710e13fa Translated using Weblate (Russian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-07-02 06:51:18 +00:00
Farid Irwan
7e984d7cce Translated using Weblate (Indonesian)
Currently translated at 92.3% (516 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/id/
2025-07-01 22:51:17 +00:00
renovate[bot]
7de5031bff Update github/codeql-action action to v3.29.2 2025-07-01 21:25:54 +02:00
renovate[bot]
67e6cfe40a Update aboutlibraries to v12.2.4 2025-07-01 21:25:25 +02:00
Niels van Velzen
38d9fe9f21 Fix retrieveAndPlay incorrectly using ticks instead of milliseconds as start position 2025-07-01 21:18:44 +02:00
Petrică Andrei-Cosmin
3afaa13126 Translated using Weblate (Romanian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-07-01 03:51:17 +00:00
Tal Sarid
01c0910560 Translated using Weblate (Hebrew)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/he/
2025-06-30 10:51:17 +00:00
Tal Sarid
d7e98d4d33 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/he_IL/
2025-06-30 10:51:17 +00:00
Gargotaire
3d0aa28032 Translated using Weblate (Catalan)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-29 12:51:17 +00:00
renovate[bot]
72b9d06ed2 Update github/codeql-action action to v3.29.1 2025-06-28 11:11:58 +02:00
myrad2267
34261fbf69 Translated using Weblate (French)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-06-28 07:51:17 +00:00
renovate[bot]
d8199c952a Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.9.0 2025-06-28 07:52:01 +02:00
Ruben Teixeira
e836b62f2b Translated using Weblate (Portuguese)
Currently translated at 4.6% (26 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-06-27 18:51:17 +00:00
Serhii Romanov
c958b98fdd Translated using Weblate (Ukrainian)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-06-27 15:51:17 +00:00
Fjuro
c9f645bb84 Translated using Weblate (Czech)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-06-27 11:51:17 +00:00
Niels van Velzen
56e0138f22 Rewrite ServerButtonView using compose 2025-06-27 08:33:59 +02:00
hoanghuy309
8295531efe Translated using Weblate (Vietnamese)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-06-27 03:51:17 +00:00
Blackspirits
c73382176d Translated using Weblate (Portuguese)
Currently translated at 4.2% (24 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-06-26 20:51:17 +00:00
Blackspirits
8d9058c9e3 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-06-26 20:51:17 +00:00
Oatavandi
c7628e5115 Translated using Weblate (Tamil)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ta/
2025-06-26 15:51:17 +00:00
Tal Sarid
dd09da9877 Translated using Weblate (Hebrew)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-26 15:51:17 +00:00
Tal Sarid
8c7f6b6bff Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-26 15:51:17 +00:00
vikingnope
246317043e Added translation using Weblate (Maltese) 2025-06-25 00:03:30 +00:00
nextlooper42
9458654174 Translated using Weblate (Slovak)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-06-24 22:01:34 +00:00
jh
c92f89d8de Translated using Weblate (Danish)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2025-06-23 20:01:34 +00:00
renovate[bot]
499e21d240 Update Kotlin to v2.2.0 2025-06-23 21:34:26 +02:00
Niels van Velzen
4c86b6f9b2 KGP: replace kotlinOptions with compilerOptions 2025-06-23 21:08:46 +02:00
renovate[bot]
44ab75f62c Update dependency io.mockk:mockk to v1.14.4 2025-06-23 18:22:09 +02:00
Niels van Velzen
1e9c8a6a5c Don't attempt to load logo in screensaver when there is none 2025-06-23 18:21:19 +02:00
Niels van Velzen
2e5aff3191 Replace DefaultCardView with UserCard(View) 2025-06-23 18:21:12 +02:00
Niels van Velzen
66aa9c4247 Create channels if they are missing in LeanbackChannelWorker 2025-06-23 18:21:02 +02:00
Gallyam Biktashev
6c9769bf52 Translated using Weblate (Russian)
Currently translated at 99.8% (558 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-06-23 13:01:34 +00:00
Gargotaire
4193cebf16 Translated using Weblate (Catalan)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-23 09:01:34 +00:00
無情天
3b728dd2f5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-06-23 09:01:34 +00:00
MrPlow
6eb786c00c Translated using Weblate (German)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-06-23 09:01:34 +00:00
Kityn
9a4b55801a Translated using Weblate (Polish)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-06-22 17:01:34 +00:00
Ēvalds Zemturis
28610750a4 Translated using Weblate (Latvian)
Currently translated at 99.8% (558 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lv/
2025-06-22 11:01:34 +00:00
Bas
2135dd68ec Translated using Weblate (Dutch)
Currently translated at 100.0% (559 of 559 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-06-22 11:01:34 +00:00
Connor Smith
1743ab62c0 Add still watching feature (#4509)
* Add still watching feature

# Conflicts:
#	app/src/main/java/org/jellyfin/androidtv/ui/playback/VideoManager.java

* Use Duration for StillWatchingStates

* Fix thumbnail alignment in StillWatchingFragment

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2025-06-22 10:22:24 +02:00
Blackspirits
9aedbd258d Translated using Weblate (Portuguese)
Currently translated at 2.7% (15 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-06-22 03:01:34 +00:00
Blackspirits
e592ad1460 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (552 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-06-22 03:01:34 +00:00
Tal Sarid
a6a0b76a2b Translated using Weblate (Hebrew)
Currently translated at 100.0% (552 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-22 00:01:34 +00:00
Tal Sarid
01ce3d09e1 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (552 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-22 00:01:34 +00:00
無情天
344a26ecf7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (552 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-06-20 18:01:34 +00:00
Fjuro
d344ef48e8 Translated using Weblate (Czech)
Currently translated at 100.0% (552 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-06-20 12:01:34 +00:00
Kityn
cad1014460 Translated using Weblate (Polish)
Currently translated at 100.0% (552 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-06-20 03:01:34 +00:00
Bas
fa3baef039 Translated using Weblate (Dutch)
Currently translated at 100.0% (552 of 552 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-06-19 23:01:34 +00:00
linkandzelda91
9562ef9d79 Add option to disable PGS direct play (#4729)
* Update deviceProfile.kt

set PGS sub support to depend on the option to direct play ASS for testing.

* Update deviceProfile.kt

added option for pgsDirectPlay similar to how assDirectPlay works

* Update deviceProfile.kt

additional references to assDirectPlay discovered, creating pgsDirectPlay replicas

* Update strings.xml

added entry for the pgs subs option in advanced options, based it on the existing libass option wording.

* Update strings.xml

included notice about the current state of PGS subtitle rendering on exoplayer.

* Update UserPreferences.kt

copying more references to assDirectPlay for pgsDirectPlay option

* Update DeveloperPreferencesScreen.kt

* Update deviceProfile.kt

testing external subtitle delivery

* Update deviceProfile.kt

waffling back and forth on the best way to do what I want.

* Update DeveloperPreferencesScreen.kt

moving the checkbox to player settings

* Update strings.xml

create enable_pgs_description string

* Update PlaybackAdvancedPreferencesScreen.kt

attempt to add the PGS textbox to advanced playback settings.

* Update strings.xml

rephrase for brevity?

* Update strings.xml

update for clarity...again

* Update UserPreferences.kt

update for clarity

* Update UserPreferences.kt

better comment?

* Update strings.xml

slightly longer description to clarify the limitation is just exoplayer related.

* Update strings.xml

grammar.

* Update UserPreferences.kt

attempt setting checkbox to default checked.

* Update strings.xml

update message to reflect that this change appears to only effect the internal player.

* Update strings.xml

made title of checkbox shorter, it was longer than the actual description and it was bothering me.

* Update strings.xml

one more rephrase?

* Update strings

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2025-06-19 20:44:41 +00:00
renovate[bot]
3c8de8969a Update dependency androidx.work:work-runtime to v2.10.2 2025-06-19 21:24:58 +02:00
renovate[bot]
ec148f3188 Update dependency androidx.compose.foundation:foundation to v1.8.3 2025-06-19 21:24:52 +02:00
Tal Sarid
f2fd441c9d Translated using Weblate (Hebrew)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-19 16:01:34 +00:00
Tal Sarid
81a6401de5 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-19 16:01:34 +00:00
Edvin Mohlin
586b68fce7 Translated using Weblate (Swedish)
Currently translated at 99.6% (549 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2025-06-19 16:01:34 +00:00
Romulo Alves
d32d9eb827 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2025-06-19 16:01:34 +00:00
renovate[bot]
0675ff208f Update dependency androidx.compose.ui:ui-tooling to v1.8.3 2025-06-18 20:46:47 +02:00
queeup
15e9d9fb93 Translated using Weblate (Turkish)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-06-18 17:01:34 +00:00
Qeynos
a6cfb5df4c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-06-18 04:01:34 +00:00
MrGcGamer
006f171024 Translated using Weblate (German)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-06-18 01:01:34 +00:00
Tal Sarid
d0ae35a8f3 Translated using Weblate (Hebrew)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-17 21:52:08 +00:00
Tal Sarid
847c930dba Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-17 21:52:08 +00:00
Blackspirits
c8f570d89a Translated using Weblate (Portuguese)
Currently translated at 2.5% (14 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-06-17 20:01:34 +00:00
Blackspirits
e766d6f80b Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-06-17 20:01:34 +00:00
nextlooper42
6cb57a6de6 Translated using Weblate (Slovak)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-06-17 11:01:34 +00:00
Kityn
0a517917ff Translated using Weblate (Polish)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-06-17 08:01:34 +00:00
Bas
bc76b289cd Translated using Weblate (Dutch)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-06-16 22:01:34 +00:00
Thomas Schwery
f6a92d50f2 Translated using Weblate (French)
Currently translated at 100.0% (551 of 551 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-06-16 22:01:34 +00:00
renovate[bot]
8f3d351691 Update dependency com.android.tools.build:gradle to v8.10.1 2025-06-16 22:21:34 +02:00
renovate[bot]
586b78f180 Update CI dependencies 2025-06-16 22:21:07 +02:00
Niels van Velzen
5521348057 Use tvShowsApi.getNextUp in FullDetailsFragmentHelper.getNextUpEpisode 2025-06-16 21:59:30 +02:00
Niels van Velzen
d0608b5f58 Remove unused parameters in SdkPlaybackHelper 2025-06-16 21:59:30 +02:00
Niels van Velzen
588e844941 Use getEpisodes API for series/seasons in SdkPlaybackHelper 2025-06-16 21:59:30 +02:00
Niels van Velzen
0e4c60c80d Fix formatting 2025-06-16 21:21:32 +02:00
Edvin Mohlin
798567c843 Add option for bold subtitles (#4559) 2025-06-16 21:21:32 +02:00
renovate[bot]
35793e2544 Update aboutlibraries to v12.2.3 2025-06-16 21:01:17 +02:00
Gargotaire
1da2eaa97a Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-15 18:07:34 +00:00
Gargotaire
2ee64ba613 Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-14 19:01:34 +00:00
dtrexler
46ce0561ae Clear skip overlay before applying media segments 2025-06-14 12:40:30 +02:00
Gargotaire
1a3fd1f4a0 Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-14 08:01:33 +00:00
Gargotaire
6c5a765382 Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-14 02:01:34 +00:00
Gargotaire
3ce2de5481 Translated using Weblate (Catalan)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ca/
2025-06-13 00:01:34 +00:00
Gargotaire
86e3d6cf8f Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-13 00:01:33 +00:00
Ēvalds Zemturis
87b1e365a0 Translated using Weblate (Latvian)
Currently translated at 98.7% (543 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lv/
2025-06-12 17:27:32 +00:00
Gargotaire
d7dea2ce89 Translated using Weblate (Catalan)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ca/
2025-06-11 19:01:34 +00:00
Gargotaire
012de52125 Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-11 19:01:33 +00:00
Gargotaire
17e7aacf31 Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-11 08:01:33 +00:00
Gargotaire
798515f339 Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-11 02:01:33 +00:00
Gargotaire
3a999683f5 Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-10 23:01:33 +00:00
renovate[bot]
5eee5361da Update koin to v4.1.0 2025-06-09 21:16:56 +02:00
Serhii Romanov
d4df35e045 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-06-09 12:01:33 +00:00
ilker
80cfc9e876 Translated using Weblate (Turkish)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-06-09 09:01:35 +00:00
Tal Sarid
fb9368f52b Translated using Weblate (Hebrew)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-09 09:01:34 +00:00
Tal Sarid
602451d887 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-09 09:01:34 +00:00
Persephone42
b4655156fa Translated using Weblate (Serbian)
Currently translated at 58.1% (320 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2025-06-09 09:01:34 +00:00
無情天
9afe6f5b00 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-06-09 09:01:34 +00:00
Gallyam Biktashev
e024341fdf Translated using Weblate (Russian)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-06-09 09:01:34 +00:00
r4dius
c0d7d03b19 Translated using Weblate (French)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-06-09 09:01:33 +00:00
Sven
dcf88b5026 Translated using Weblate (German)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-06-09 09:01:33 +00:00
nextlooper42
acb5fb367a Translated using Weblate (Slovak)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-06-08 14:01:33 +00:00
Tal Sarid
bc3666558c Translated using Weblate (Hebrew)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-08 09:01:34 +00:00
Tal Sarid
36acfecade Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-08 09:01:33 +00:00
hoanghuy309
0952230083 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-06-08 06:01:34 +00:00
Tal Sarid
3d370d618b Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-07 22:01:33 +00:00
Tal Sarid
672593da02 Translated using Weblate (Hebrew)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-07 16:01:34 +00:00
Tal Sarid
0f95c6f090 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-07 16:01:33 +00:00
Pere
0f6993d5ce Translated using Weblate (Catalan)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ca/
2025-06-07 13:01:34 +00:00
Pere
959760a21f Translated using Weblate (Catalan)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-06-07 13:01:33 +00:00
Fabien
08a26aed67 Translated using Weblate (French)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-06-07 13:01:33 +00:00
Kityn
239517ee9d Translated using Weblate (Polish)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-06-07 08:01:33 +00:00
Tal Sarid
eebcb898d4 Translated using Weblate (Hebrew)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-06 23:01:34 +00:00
Tal Sarid
e0e9001144 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-06 23:01:33 +00:00
Bas
193ce07455 Translated using Weblate (Dutch)
Currently translated at 100.0% (550 of 550 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-06-06 20:46:47 +00:00
Niels van Velzen
d53c4bc810 New search design 2025-06-06 22:13:52 +02:00
renovate[bot]
f20c5957c5 Update github/codeql-action action to v3.28.19 2025-06-06 22:10:58 +02:00
osiris86
6f06639137 Change/Fix Resume Button Behaviour on Series (#4679) 2025-06-06 22:08:40 +02:00
renovate[bot]
428d68a356 Update aboutlibraries to v12.2.1 2025-06-06 21:53:47 +02:00
renovate[bot]
d96dd0a687 Update dependency gradle to v8.14.2 2025-06-06 21:53:34 +02:00
Niels van Velzen
fdd079d32b Fix DestinationFragmentView not replacing existing fragment on resume 2025-06-06 21:38:02 +02:00
Bas
f726d978c1 Translated using Weblate (Dutch)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-06-06 19:01:33 +00:00
Tal Sarid
fd9e2e3fb5 Translated using Weblate (Hebrew)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-06 15:42:33 +00:00
Tal Sarid
c94f88ffbd Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-06 15:42:33 +00:00
Tal Sarid
35b68474b0 Translated using Weblate (Hebrew)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-06 12:43:41 +00:00
Tal Sarid
ed206858dd Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-06 12:43:40 +00:00
Tal Sarid
a0e510e0a9 Translated using Weblate (Hebrew)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-06-06 10:25:56 +00:00
Tal Sarid
a1d06388d3 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-06-06 10:25:56 +00:00
Sander Scheijvens
a77bd8a448 Translated using Weblate (Dutch)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-06-05 18:50:56 +00:00
renovate[bot]
3e3e1386ca Update dependency androidx.appcompat:appcompat to v1.7.1 2025-06-05 06:55:34 +02:00
renovate[bot]
a3555869cb Update androidx.lifecycle to v2.9.1 2025-06-04 22:11:51 +02:00
renovate[bot]
1c5fd6e3ee Update androidx.fragment to v1.8.8 2025-06-04 22:11:47 +02:00
Niels van Velzen
1b43a742c3 Fix URL generation for user profile pictures 2025-06-03 14:25:01 +02:00
General-c4
99336e51b2 Translated using Weblate (Arabic)
Currently translated at 92.6% (506 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-06-02 22:10:56 +00:00
Serhii Romanov
7bd87ac87d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-06-02 10:01:33 +00:00
Niels van Velzen
8f4309360b Display cover art of currently playing music via compose 2025-05-30 22:06:00 +02:00
renovate[bot]
3f29622948 Update aboutlibraries to v12.2.0 2025-05-30 19:59:54 +02:00
Ludovico de Nittis
95f8e4db22 Allow Exoplayer to invalidate the track selection on capabilities change
If the capabilities of a device change, Exoplayer can invalidate the
current selection to adhere to the new list of capabilities.

This helps the Nvidia Shield and its content matching refresh rate
option because, during the refresh rate switching period, the reported
capabilities change. Without this flag, the device could reproduce audio
as PCM instead of the expected passthrough.

Addresses https://github.com/jellyfin/jellyfin-androidtv/issues/4067,
additional context https://github.com/androidx/media/issues/2258
2025-05-30 11:17:12 +02:00
Niels van Velzen
9a689cc662 Fix screensaver request loop when there are no items to showcase 2025-05-28 21:16:58 +02:00
DevAgac
f8a0fd9399 Translated using Weblate (Turkish)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-05-27 01:01:33 +00:00
Tal Sarid
2e4ea83c0a Translated using Weblate (Hebrew)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-26 08:35:26 +00:00
Tal Sarid
6e986f7f27 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-26 08:35:26 +00:00
MrPlow
71182d1f81 Translated using Weblate (German)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-05-26 08:35:25 +00:00
Sven
c1df2e6327 Translated using Weblate (German)
Currently translated at 99.6% (544 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-05-25 13:01:33 +00:00
tm2244
f3aa788b37 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-05-25 02:01:33 +00:00
Gallyam Biktashev
afd229b169 Translated using Weblate (Russian)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-05-24 22:01:33 +00:00
Tal Sarid
059587f2b3 Translated using Weblate (Hebrew)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-24 12:01:33 +00:00
Tal Sarid
01fba046a1 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-24 12:01:33 +00:00
Niels van Velzen
63b295b7e1 Remove Koin from playback module 2025-05-23 22:27:12 +02:00
renovate[bot]
ed268d2cbe Update Kotlin 2025-05-23 22:27:12 +02:00
renovate[bot]
0ecec926e8 Update jellyfin-androidx-media to 1.6.1+1 2025-05-23 22:03:13 +02:00
Dimitar \"Topper\" Maznekov
bb9a44f485 Translated using Weblate (Bulgarian)
Currently translated at 42.1% (230 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2025-05-23 15:01:33 +00:00
Jonas Engen Larsen
8345594219 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-05-23 06:01:33 +00:00
BromTeque
28c6e26912 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.8% (545 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-05-22 19:01:32 +00:00
renovate[bot]
80ae0dd206 Update dependency gradle to v8.14.1 2025-05-22 18:43:38 +02:00
Fjuro
abc9155b5b Translated using Weblate (Czech)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-05-22 15:01:32 +00:00
無情天
4d676c80e9 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-05-22 11:01:32 +00:00
myrad2267
a7bdc9ae04 Translated using Weblate (French)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-05-21 20:01:33 +00:00
renovate[bot]
454a129e93 Update dependency androidx.compose.foundation:foundation to v1.8.2 2025-05-21 21:48:39 +02:00
hoanghuy309
18b86bcd11 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-05-21 14:01:33 +00:00
nextlooper42
477dd692c5 Translated using Weblate (Slovak)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-05-21 14:01:33 +00:00
Blackspirits
52ffbd4186 Translated using Weblate (Portuguese)
Currently translated at 2.1% (12 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-05-21 09:01:33 +00:00
Blackspirits
e32eeb0e49 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-05-21 09:01:32 +00:00
renovate[bot]
5253cae13d Update dependency androidx.window:window to v1.4.0 2025-05-20 22:30:31 +02:00
renovate[bot]
528c8e5ce3 Update androidx.fragment to v1.8.7 2025-05-20 22:21:50 +02:00
renovate[bot]
30e9c6e6e1 Update dependency androidx.compose.ui:ui-tooling to v1.8.2 2025-05-20 22:21:46 +02:00
Kityn
0efb45cea4 Translated using Weblate (Polish)
Currently translated at 100.0% (546 of 546 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-05-20 15:55:40 +00:00
Niels van Velzen
c4412cfac2 Fix compose focus deprecations 2025-05-20 17:30:04 +02:00
Niels van Velzen
6a64d351f0 Fix nullability issues in presenter usages 2025-05-20 16:24:19 +02:00
Niels van Velzen
694ed15dde Add experimental ASS direct play using libass 2025-05-20 08:41:50 +02:00
Niels van Velzen
3ff7fc058c Disable channel badge for media notification channel 2025-05-19 22:52:51 +02:00
Niels van Velzen
7bc2af7ff7 Add missing action for AndroidMediaService 2025-05-19 22:52:51 +02:00
Simon Hung
5de8626e9a Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2025-05-19 19:24:27 +00:00
Gallyam Biktashev
60ad989eba Translated using Weblate (Russian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ru/
2025-05-19 08:56:44 +00:00
claireratigan
90a4d40e2c Change screensaver to cycle through random selection and avoid repeats (#4619)
* Have screensaver cycle through random selection to avoid repeats

* DRY

* Break logic out of timing loop and reduce request size

* Use flow for getRandomLibraryShowcaseItems

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2025-05-17 14:50:18 +00:00
cani1see
49f9735830 Improve status bar hiding behavior (#4650) 2025-05-17 14:15:21 +00:00
renovate[bot]
d0c7c8647e Update CI dependencies 2025-05-16 22:26:10 +02:00
Tal Sarid
716125ad56 Translated using Weblate (Hebrew)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-16 10:57:31 +00:00
Tal Sarid
064c70677e Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-16 10:57:29 +00:00
Tal Sarid
bea76b96e5 Translated using Weblate (Hebrew (Israel))
Currently translated at 91.3% (498 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-16 01:01:06 +00:00
Tal Sarid
96eebba125 Translated using Weblate (Hebrew)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-15 22:01:07 +00:00
Tal Sarid
23a58644ff Translated using Weblate (Hebrew (Israel))
Currently translated at 91.1% (497 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-15 22:01:06 +00:00
Tal Sarid
7048868f3f Translated using Weblate (Hebrew)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-15 19:49:10 +00:00
Tal Sarid
8d3c557626 Translated using Weblate (Hebrew (Israel))
Currently translated at 84.5% (461 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-15 19:49:10 +00:00
Tal Sarid
f428d54881 Translated using Weblate (Hebrew (Israel))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/he_IL/
2025-05-14 23:04:14 +00:00
Tal Sarid
89805d3a5d Translated using Weblate (Hebrew)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-14 23:04:14 +00:00
Tal Sarid
680063665e Translated using Weblate (Hebrew (Israel))
Currently translated at 77.6% (423 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-14 23:04:12 +00:00
Tal Sarid
e55e999db0 Translated using Weblate (Hebrew)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/he/
2025-05-14 22:40:37 +00:00
Tal Sarid
a3f6020ab3 Translated using Weblate (Hebrew)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-14 22:40:37 +00:00
Tal Sarid
9035aac014 Translated using Weblate (Hebrew)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-14 21:14:07 +00:00
Morteza Taherkhani
72ee17db16 Translated using Weblate (Persian)
Currently translated at 72.1% (393 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fa/
2025-05-13 22:01:06 +00:00
Blackspirits
41a2bc6890 Translated using Weblate (Portuguese)
Currently translated at 1.8% (10 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-05-13 17:01:06 +00:00
Generator
231455887c Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-05-13 17:01:06 +00:00
renovate[bot]
5242c6dd74 Update coil to v3.2.0 2025-05-13 13:07:55 +02:00
Blackspirits
9c94d3e7c9 Translated using Weblate (Portuguese)
Currently translated at 1.6% (9 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-05-13 10:01:06 +00:00
r4dius
454cd2548f Translated using Weblate (French)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/fr/
2025-05-12 20:01:06 +00:00
Blackspirits
0f82dbfb33 Translated using Weblate (Portuguese (Portugal))
Currently translated at 99.8% (544 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-05-12 20:01:06 +00:00
r4dius
5b470bf6e5 Translated using Weblate (French)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-05-12 20:01:06 +00:00
Generator
7c29539a75 Translated using Weblate (Portuguese (Portugal))
Currently translated at 99.8% (544 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-05-12 17:11:37 +00:00
Gallyam Biktashev
96ea906fa8 Translated using Weblate (Russian)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-05-11 21:26:33 +00:00
hoanghuy309
a5c30b56e8 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-05-11 09:01:06 +00:00
Niels van Velzen
213debfab0 Always create boxset queues with default sorting instead of using sort names of individual items 2025-05-10 17:58:24 +02:00
Florian Dreier
a78db2701a Fix crash on startup (#4640)
* Fix crash on startup

* Changed condition evaluation order
2025-05-10 17:29:12 +02:00
dgirones
aaf26ec4bf Translated using Weblate (Catalan)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-05-10 11:01:06 +00:00
renovate[bot]
598dec5bb0 Update dependency com.android.tools.build:gradle to v8.10.0 2025-05-08 21:00:26 +02:00
renovate[bot]
2b04aa3a51 Update aboutlibraries to v12.1.2 2025-05-08 21:00:07 +02:00
DJSweder
ecb9047162 Translated using Weblate (Czech)
Currently translated at 99.6% (543 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-05-08 09:24:10 +00:00
master translator
4af3efcf93 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2025-05-08 05:01:06 +00:00
renovate[bot]
1e8a546aca Update androidx.lifecycle to v2.9.0 2025-05-07 21:14:23 +02:00
renovate[bot]
a713cf5af3 Update androidx.compose to v1.8.1 2025-05-07 21:08:47 +02:00
renovate[bot]
8b49e8a957 Update dependency androidx.tvprovider:tvprovider to v1.1.0 2025-05-07 21:08:21 +02:00
renovate[bot]
a2f7f0b20b Update github/codeql-action action to v3.28.17 2025-05-07 08:24:47 +02:00
renovate[bot]
f5a77a66ec Update aboutlibraries to v12.1.1 2025-05-07 08:24:31 +02:00
Dor Ban
1ba81d30da Translated using Weblate (Hebrew)
Currently translated at 99.4% (542 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-05-05 21:20:03 +00:00
Dor Ban
d34a8a5dbe Translated using Weblate (Hebrew (Israel))
Currently translated at 76.6% (418 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-05 21:20:03 +00:00
Ofek
e28c58f3f4 Translated using Weblate (Hebrew (Israel))
Currently translated at 76.6% (418 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-05-05 21:20:03 +00:00
Luiz Moraes
26c584b368 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2025-05-03 06:01:05 +00:00
Niels van Velzen
68bdf5a28c Use new intermediate model in most places 2025-05-02 16:15:52 +02:00
Tushar Joshi
fddbb95a90 Translated using Weblate (Hindi)
Currently translated at 54.4% (297 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2025-05-02 10:01:05 +00:00
Niels van Velzen
62c37ce906 Add intermediate model for image information 2025-05-01 19:23:16 +02:00
renovate[bot]
d2dbeb594b Update aboutlibraries to v12.1.0 2025-05-01 13:30:38 +02:00
GeorgeAL78
8e66b9e587 Translated using Weblate (Albanian)
Currently translated at 35.7% (195 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sq/
2025-05-01 08:01:06 +00:00
Acrotos
d93a841e9f Translated using Weblate (Romanian)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-04-29 15:01:05 +00:00
Jonas Engen Larsen
cd71dbb164 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-04-29 15:01:05 +00:00
renovate[bot]
9e11eeb0d4 Update dependency io.mockk:mockk to v1.14.2 2025-04-29 16:23:14 +02:00
nextlooper42
e5a4463867 Translated using Weblate (Slovak)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-04-29 12:01:05 +00:00
Gallyam Biktashev
4a55e9c947 Translated using Weblate (Russian)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-04-27 22:01:05 +00:00
RikyR
ee95f7266f Translated using Weblate (Italian)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2025-04-27 15:01:05 +00:00
Blackspirits
16aa1d11b5 Translated using Weblate (Portuguese)
Currently translated at 1.4% (8 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-04-26 18:13:51 +00:00
Blackspirits
d173ad4b14 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-04-26 18:13:51 +00:00
Blackspirits
b2e877d21f Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/pt_PT/
2025-04-26 14:52:53 +00:00
Blackspirits
9503155a43 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-04-26 14:52:52 +00:00
Blackspirits
5ab4dd3048 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-04-26 09:01:05 +00:00
Andi Chandler
04fa220634 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-04-25 19:33:19 +00:00
renovate[bot]
579cb1274c Update dependency gradle to v8.14 2025-04-25 19:43:17 +02:00
renovate[bot]
99d4dffe3b Update aboutlibraries to v12.0.1 2025-04-25 09:26:02 +02:00
renovate[bot]
f39adeec1a Update androidx.compose to v1.8.0 2025-04-24 18:55:53 +02:00
Blackspirits
f38903f1f3 Translated using Weblate (Portuguese)
Currently translated at 1.2% (7 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-04-24 16:38:44 +00:00
Blackspirits
31106bdb28 Translated using Weblate (Portuguese (Portugal))
Currently translated at 99.8% (544 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-04-24 16:38:44 +00:00
Blackspirits
1403b256ca Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.0% (529 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2025-04-24 16:38:43 +00:00
myrad2267
67a2d1af1e Translated using Weblate (French)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-04-24 06:21:26 +00:00
Kityn
87583243dc Translated using Weblate (Polish)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-04-24 02:01:05 +00:00
無情天
7d58908a44 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-04-23 20:54:25 +00:00
Bas
05dc1a72f5 Translated using Weblate (Dutch)
Currently translated at 99.6% (543 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-04-23 20:54:24 +00:00
MrPlow
1eb17a5098 Translated using Weblate (German)
Currently translated at 100.0% (545 of 545 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-04-23 20:54:24 +00:00
renovate[bot]
d04f052afc Update dependency androidx.work:work-runtime to v2.10.1 2025-04-23 20:38:51 +02:00
renovate[bot]
26e8bc227b Update androidx.leanback to v1.2.0 2025-04-23 20:37:58 +02:00
Niels van Velzen
904d5c1a31 Replace leanback animations with our own definitions in CustomPlaybackOverlayFragment 2025-04-23 19:45:49 +02:00
conihorse
f9bcd4ba54 Add Rewind & FastForward buttons to AudioNowPlayingFragment (#4503)
* Add Rewind & FastForward buttons to AudioNowPlayingFragment

* Add Rewind & FastForward buttons to AudioNowPlayingFragment

* Merge remote-tracking branch 'origin/master'

# Conflicts:
#	app/src/main/java/org/jellyfin/androidtv/ui/playback/rewrite/RewriteMediaManager.kt

* Cleanup

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2025-04-23 19:25:03 +02:00
renovate[bot]
16d8640c01 Update github/codeql-action action to v3.28.16 2025-04-23 19:10:03 +02:00
nextlooper42
287f2297c9 Translated using Weblate (Slovak)
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-04-22 01:01:05 +00:00
Gallyam Biktashev
5191966abd Translated using Weblate (Russian)
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-04-21 13:01:05 +00:00
Niels van Velzen
b22d45816e Fix crash in CustomPlaybackOverlayFragment.prepareChannelAdapter when Live TV channels are not loaded 2025-04-21 09:26:26 +02:00
Niels van Velzen
fa83fc1b30 Drop leanback implementation of search 2025-04-21 08:34:15 +02:00
Tanja L.
2a32babc8e Translated using Weblate (German)
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-04-20 14:19:03 +00:00
Pentaphon
6bcc7db97b Translated using Weblate (Spanish (Latin America))
Currently translated at 99.0% (538 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2025-04-20 07:00:08 +00:00
Kityn
1318b9fe7d Translated using Weblate (Polish)
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-04-19 06:25:01 +00:00
Nero
ceb7888907 Translated using Weblate (Spanish)
Currently translated at 99.6% (541 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-04-19 05:16:51 +00:00
Fjuro
055d003625 Translated using Weblate (Czech)
Currently translated at 99.6% (541 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-04-18 20:01:04 +00:00
renovate[bot]
e075cd17e9 Update aboutlibraries to v12 2025-04-18 21:50:34 +02:00
Blackspirits
b6a903f94c Translated using Weblate (Portuguese)
Currently translated at 0.9% (5 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-04-17 17:01:05 +00:00
Blackspirits
a3666d24d1 Translated using Weblate (Portuguese (Portugal))
Currently translated at 99.8% (542 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-04-17 17:01:04 +00:00
hoanghuy309
10ec88a3df Translated using Weblate (Vietnamese)
Currently translated at 99.8% (542 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-04-17 08:57:26 +00:00
無情天
a12666be45 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-04-16 15:01:04 +00:00
Linards Naglis
a669fee6ab Translated using Weblate (Latvian)
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lv/
2025-04-16 12:01:05 +00:00
hoanghuy309
00f4798a4a Translated using Weblate (Vietnamese)
Currently translated at 99.6% (541 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-04-15 18:01:04 +00:00
myrad2267
86893151ac Translated using Weblate (French)
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-04-15 13:01:04 +00:00
Henning Weiss
5276259c6c Fix watch next row ordering, Change watch next row meta data (#4298)
* Tweaks to watch next row.

- episodes now have meta data in line with other streaming apps
- watch next is now correctly ordered
- movies to resume will now be inserted correctly

* WATCH_NEXT_TYPE_NEW now ordered by item creation date.

* Overview field is retrieved from server.

* Improvements to handling null values in LeanbackChannelWorker.

* Additional null check.

* Style improvements.
2025-04-15 14:57:06 +02:00
Kityn
233174394e Translated using Weblate (Polish)
Currently translated at 100.0% (543 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-04-15 08:01:04 +00:00
Niels van Velzen
62ef55d49a Also use playback launcher for launching audio 2025-04-14 22:19:12 +02:00
Anonymous
35de3cc8fe Translated using Weblate (Hindi)
Currently translated at 54.3% (295 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2025-04-14 19:17:18 +00:00
Anonymous
eff7d2cf61 Translated using Weblate (Belarusian)
Currently translated at 94.4% (513 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/be/
2025-04-14 19:17:18 +00:00
Anonymous
f7abba8378 Translated using Weblate (Estonian)
Currently translated at 95.3% (518 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2025-04-14 19:17:17 +00:00
Anonymous
45a62c9315 Translated using Weblate (Esperanto)
Currently translated at 60.9% (331 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/eo/
2025-04-14 19:17:17 +00:00
Anonymous
cf64134114 Translated using Weblate (Arabic)
Currently translated at 92.6% (503 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ar/
2025-04-14 19:17:17 +00:00
Anonymous
6c7aaab3bc Translated using Weblate (Malayalam)
Currently translated at 36.4% (198 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ml/
2025-04-14 19:17:17 +00:00
Anonymous
8105daa925 Translated using Weblate (Catalan)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-04-14 19:17:16 +00:00
Anonymous
1d414e892c Translated using Weblate (Turkish)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-04-14 19:17:16 +00:00
Anonymous
795bbbaf63 Translated using Weblate (Vietnamese)
Currently translated at 99.2% (539 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-04-14 19:17:16 +00:00
Anonymous
cfa95459db Translated using Weblate (Tamil)
Currently translated at 92.8% (504 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ta/
2025-04-14 19:17:16 +00:00
Anonymous
014c49f269 Translated using Weblate (Hebrew)
Currently translated at 98.3% (534 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-04-14 19:17:16 +00:00
Anonymous
a7006a132d Translated using Weblate (Croatian)
Currently translated at 97.7% (531 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2025-04-14 19:17:16 +00:00
Anonymous
e201d3f3aa Translated using Weblate (Spanish (Latin America))
Currently translated at 98.5% (535 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2025-04-14 19:17:15 +00:00
Anonymous
a0d363f0f2 Translated using Weblate (Spanish (Argentina))
Currently translated at 95.0% (516 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_AR/
2025-04-14 19:17:15 +00:00
Anonymous
ee91a0e92e Translated using Weblate (Ukrainian)
Currently translated at 97.7% (531 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-04-14 19:17:15 +00:00
Anonymous
5194e2e088 Translated using Weblate (Finnish)
Currently translated at 98.8% (537 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2025-04-14 19:17:15 +00:00
Anonymous
35ee90cdd3 Translated using Weblate (Lithuanian)
Currently translated at 98.3% (534 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2025-04-14 19:17:15 +00:00
Anonymous
1359200d15 Translated using Weblate (Macedonian)
Currently translated at 90.4% (491 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/mk/
2025-04-14 19:17:14 +00:00
Anonymous
b9b694d7e2 Translated using Weblate (Polish)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-04-14 19:17:14 +00:00
Anonymous
901b933477 Translated using Weblate (Serbian)
Currently translated at 57.4% (312 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2025-04-14 19:17:14 +00:00
Anonymous
6b96536181 Translated using Weblate (Slovenian)
Currently translated at 98.3% (534 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sl/
2025-04-14 19:17:14 +00:00
Anonymous
fcbd4c8c4e Translated using Weblate (Hungarian)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2025-04-14 19:17:14 +00:00
Anonymous
5638d876b5 Translated using Weblate (Indonesian)
Currently translated at 91.7% (498 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/id/
2025-04-14 19:17:14 +00:00
Anonymous
920ce10880 Translated using Weblate (Slovak)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-04-14 19:17:13 +00:00
Anonymous
cf40474c4d Translated using Weblate (Japanese)
Currently translated at 69.2% (376 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-04-14 19:17:13 +00:00
Anonymous
9e028cc37c Translated using Weblate (Korean)
Currently translated at 98.7% (536 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ko/
2025-04-14 19:17:13 +00:00
Anonymous
5c04ea78a1 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2025-04-14 19:17:13 +00:00
Anonymous
2fe239f2b2 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-04-14 19:17:13 +00:00
Anonymous
913ea219e9 Translated using Weblate (Swedish)
Currently translated at 98.3% (534 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2025-04-14 19:17:13 +00:00
Anonymous
17deb349b5 Translated using Weblate (Russian)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-04-14 19:17:12 +00:00
Anonymous
2f88c8d978 Translated using Weblate (Romanian)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-04-14 19:17:12 +00:00
Anonymous
3a3c1a2fa1 Translated using Weblate (Portuguese (Portugal))
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-04-14 19:17:12 +00:00
Anonymous
af936b90a5 Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.4% (529 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2025-04-14 19:17:12 +00:00
Bas
0310f0bbfe Translated using Weblate (Dutch)
Currently translated at 99.6% (541 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-04-14 19:17:12 +00:00
Anonymous
87d3fcabd8 Translated using Weblate (Dutch)
Currently translated at 99.6% (541 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-04-14 19:17:12 +00:00
Anonymous
a6bb3e99b3 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-04-14 19:17:11 +00:00
Anonymous
31fdacf544 Translated using Weblate (Kazakh)
Currently translated at 60.9% (331 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/kk/
2025-04-14 19:17:11 +00:00
Anonymous
02ac630dc6 Translated using Weblate (Italian)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2025-04-14 19:17:11 +00:00
Anonymous
fe2f4a42ae Translated using Weblate (French)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-04-14 19:17:11 +00:00
Anonymous
662b2e0db5 Translated using Weblate (Spanish)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-04-14 19:17:10 +00:00
Anonymous
1bfe03bac7 Translated using Weblate (Spanish (Mexico))
Currently translated at 97.9% (532 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_MX/
2025-04-14 19:17:10 +00:00
Anonymous
99fd361bcf Translated using Weblate (English (United Kingdom))
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-04-14 19:17:10 +00:00
Anonymous
cae9af69b8 Translated using Weblate (Greek)
Currently translated at 95.2% (517 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2025-04-14 19:17:10 +00:00
Anonymous
a2ab9c3663 Translated using Weblate (German)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-04-14 19:17:10 +00:00
Anonymous
29028fac31 Translated using Weblate (Danish)
Currently translated at 97.9% (532 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2025-04-14 19:17:09 +00:00
Anonymous
3632c9ddbb Translated using Weblate (Czech)
Currently translated at 99.4% (540 of 543 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-04-14 19:17:09 +00:00
Niels van Velzen
f6c0804d82 Add hearing impaired indicator for subtitles (SDH) (#4593)
* Add hearing impaired indicator for subtitles (SDH)

* Show both CC and SDH badges
2025-04-14 20:29:05 +02:00
Niels van Velzen
14f5f5c9b3 Move activity opening out of navigation code (#4591)
* Remove activityDestination

* Rewrite PlaybackLauncher to actually launch playback
2025-04-14 17:35:12 +02:00
renovate[bot]
084061df65 Update androidx.media3 to v1.6.1 2025-04-14 16:30:23 +02:00
Niels van Velzen
3067f07b2e Fix "favorites" playlist not showing when the user has no playlists 2025-04-14 07:14:54 +02:00
DeDuplicate
dcc8c18db6 Translated using Weblate (Hebrew (Israel))
Currently translated at 49.2% (267 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-04-14 02:01:05 +00:00
renovate[bot]
7a8c2c2bc3 Update CI dependencies 2025-04-13 22:20:37 +02:00
renovate[bot]
14db765b06 Update dependency io.mockk:mockk to v1.14.0 2025-04-13 22:19:39 +02:00
Egglestron
d11340fa4e Translated using Weblate (French)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-04-13 12:01:04 +00:00
newton181
77214ff064 Translated using Weblate (Spanish (Latin America))
Currently translated at 99.0% (537 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2025-04-10 21:01:04 +00:00
Niels van Velzen
9d87030c1b Do not set audio session to pipeline on create 2025-04-10 21:50:36 +02:00
Niels van Velzen
1574220fb4 Fix experimental audio night mode feature crashing the app 2025-04-10 19:51:21 +02:00
renovate[bot]
b5957625dd Update dependency androidx.core:core-ktx to v1.16.0 2025-04-09 22:30:46 +02:00
renovate[bot]
24e29be72c Update dependency androidx.tvprovider:tvprovider to v1.1.0-beta01 2025-04-09 22:29:04 +02:00
Blackspirits
f9009b1a7c Translated using Weblate (Portuguese)
Currently translated at 0.5% (3 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt/
2025-04-08 18:01:03 +00:00
oltanis
32017d1cd0 Added translation using Weblate (Galician) 2025-04-07 12:57:00 +00:00
Fjuro
f380de5d87 Translated using Weblate (Czech)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-04-07 12:01:03 +00:00
Valter Vicente
b4a9b978db Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-04-06 11:01:03 +00:00
Niels van Velzen
da8f1e1321 Fix time formatting in toolbar, merge duplicate rememberCurrentTime implementations 2025-04-06 07:58:40 +02:00
Niels van Velzen
cd57de5bf4 Fix non-square profile picture in toolbar 2025-04-06 07:58:40 +02:00
renovate[bot]
7636916166 Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.8 2025-04-05 22:00:36 +02:00
Niels van Velzen
545aeed706 Fix tinting of user switch button in HomeToolbar 2025-04-04 22:45:46 +02:00
Niels van Velzen
8ec1fd0650 Add ButtonColors and colorScheme 2025-04-04 22:45:46 +02:00
Niels van Velzen
719de0f787 Rewrite toolbar in compose 2025-04-03 22:35:54 +02:00
Adnan Sönmez
98a96ca635 Translated using Weblate (Turkish)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2025-04-03 03:01:03 +00:00
Niels van Velzen
170d14a107 Use OkHttp for networking in media3 2025-04-02 21:48:52 +02:00
Linards Naglis
11e9d8ceda Translated using Weblate (Latvian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/lv/
2025-04-02 17:01:04 +00:00
Linards Naglis
7d4eed6989 Translated using Weblate (Latvian)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lv/
2025-04-02 17:01:04 +00:00
Linards Naglis
2809d98c13 Translated using Weblate (Latvian)
Currently translated at 72.3% (392 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lv/
2025-04-02 14:01:04 +00:00
vahtos
1e67e589e0 Add season and episode numbers for Live TV programs (#4558) 2025-04-01 20:49:54 +02:00
renovate[bot]
db06ff4561 Update koin to v4.0.4 2025-03-31 19:39:59 +02:00
renovate[bot]
885b1e99cc Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.7 2025-03-31 11:31:10 +02:00
Sinahe2
e5f27ce6fc Translated using Weblate (Persian)
Currently translated at 72.5% (393 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fa/
2025-03-29 11:01:02 +00:00
renovate[bot]
21fe0048b1 Update CI dependencies 2025-03-28 14:20:06 +01:00
renovate[bot]
8fae049a74 Update dependency com.android.tools.build:gradle to v8.9.1 2025-03-28 14:09:40 +01:00
Niels van Velzen
f4bbacec2f Fix some more API calls being made on main thread 2025-03-28 07:10:20 +01:00
Patrick Sletvold
9aa4159d0b Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-03-26 23:01:02 +00:00
Niels van Velzen
968a7317db Directplay VobSub and DVDSub 2025-03-26 22:45:24 +01:00
renovate[bot]
2aec7b32fd Update androidx.media3 to v1.6.0 2025-03-26 21:20:45 +01:00
Niels van Velzen
e224e84197 Fix some API calls being made on main thread 2025-03-25 22:12:35 +01:00
Niels van Velzen
a8b5209b5a Fix ItemRowAdapter failures never logged 2025-03-25 21:42:58 +01:00
renovate[bot]
9c02a48152 Update koin to v4.0.3 2025-03-25 19:18:15 +01:00
Niels van Velzen
77d03192b2 Fix missing dependency in playback:jellyfin module 2025-03-25 16:41:12 +01:00
boydaihungst
6daeadeb68 Translated using Weblate (Vietnamese)
Currently translated at 99.8% (541 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-03-23 06:01:01 +00:00
Niels van Velzen
6354fc3bcd Fix crash when trying to update detached AudioNowPlayingFragment 2025-03-22 22:13:08 +01:00
Jawad
2960b96e21 Translated using Weblate (Persian)
Currently translated at 71.9% (390 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fa/
2025-03-20 20:01:01 -04:00
Alejandro Delgado Folgado
70b8a126db Translated using Weblate (Catalan)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-03-20 09:01:01 -04:00
Alejandro Delgado Folgado
c1267d0356 Translated using Weblate (Spanish)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-03-20 09:01:01 -04:00
Niels van Velzen
0522e3d03b Fix logo in next up too large 2025-03-20 07:11:22 +01:00
renovate[bot]
8bb163f676 Update CI dependencies 2025-03-19 21:33:07 +01:00
Niels van Velzen
5444cad8bd Disable default indication on ButtonBase
Right now we're not providing an indication instance causing Compose to fallback to the default debug indication. Disable indications on the ButtonBase for now until we can provide our own.
2025-03-19 21:29:29 +01:00
Niels van Velzen
9f7ab6c26e Add button_default_progress_background color 2025-03-19 21:29:29 +01:00
Niels van Velzen
f26c997d7d Rewrite NextUpFragment with Compose 2025-03-19 21:29:29 +01:00
Niels van Velzen
6d2bcabee3 Add Button composable 2025-03-19 19:41:50 +01:00
Jonas Engen Larsen
a0f965e78c Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-03-17 22:01:01 -04:00
Niels van Velzen
1f55126008 Replace androidx.tv with own theme implementation 2025-03-16 19:54:03 +01:00
HanaO00
160965f50a Translated using Weblate (French)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-03-14 15:01:01 -04:00
Neokeek
417114c71e Translated using Weblate (German)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-03-14 15:01:00 -04:00
Le Quellec Christophe
64bde6b788 Translated using Weblate (French)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/fr/
2025-03-12 13:01:00 -04:00
Niels van Velzen
99a8f78623 Add custom connectivity checker for Coil that always claims to be connected 2025-03-11 21:58:52 +01:00
pitiBalrog
aeb2554734 Translated using Weblate (French)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-03-11 10:01:00 -04:00
Niels van Velzen
6678292fc8 Rewrite media stream resolvers to be device profile based 2025-03-10 19:23:34 +01:00
Niels van Velzen
f0886fccc3 Enable logging for Coil 2025-03-10 17:24:56 +01:00
renovate[bot]
59187429cf Update CI dependencies 2025-03-10 14:28:47 +01:00
hoanghuy309
fe5ff01160 Translated using Weblate (Vietnamese)
Currently translated at 99.2% (538 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-03-09 12:38:34 -04:00
laborantine
ae911e6bd5 Translated using Weblate (French)
Currently translated at 98.8% (536 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-03-08 13:01:18 -05:00
Kevin Puertas
eb884c9498 Translated using Weblate (Spanish)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/es/
2025-03-08 10:01:18 -05:00
Bas
e7800bebe2 Translated using Weblate (Dutch)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-03-08 10:01:18 -05:00
Kevin Puertas
981d4fc8df Translated using Weblate (Spanish)
Currently translated at 98.5% (534 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2025-03-08 10:01:18 -05:00
youngzheimer
317bae9eb3 Translated using Weblate (Korean)
Currently translated at 99.2% (538 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ko/
2025-03-08 07:01:18 -05:00
Blopper Blopstein
376ced9d0b Translated using Weblate (French)
Currently translated at 98.8% (536 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-03-08 07:01:18 -05:00
hoanghuy309
abfa3cfe06 Translated using Weblate (Vietnamese)
Currently translated at 97.6% (529 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-03-08 03:01:18 -05:00
Niels van Velzen
e9d69faf74 Use collapsed detail blocks in device profile report 2025-03-07 21:10:43 +01:00
Niels van Velzen
1bded7a41c Add device codec features 2025-03-07 21:10:43 +01:00
Niels van Velzen
088461598b Add color formats and profile levels to device profile report 2025-03-07 21:10:43 +01:00
Kaue Lima
cdafe5e086 Added translation using Weblate (Portuguese) 2025-03-07 11:20:55 -05:00
Bas
8014a8c646 Translated using Weblate (Dutch)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-03-06 16:01:18 -05:00
millallo
479433093a Translated using Weblate (Italian)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2025-03-06 11:01:18 -05:00
hoanghuy309
7719148355 Translated using Weblate (Vietnamese)
Currently translated at 96.1% (521 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2025-03-06 04:01:18 -05:00
renovate[bot]
6ca9aedcc8 Update dependency com.android.tools.build:gradle to v8.9.0 2025-03-04 21:50:34 +01:00
Zilvinas
83a2e22a2c Translated using Weblate (Lithuanian)
Currently translated at 98.8% (536 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2025-03-03 14:01:18 -05:00
Sonik H
822102e351 Translated using Weblate (Greek)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/el/
2025-03-03 07:01:18 -05:00
hyperjoco
828d34dc15 Translated using Weblate (Hungarian)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2025-03-03 07:01:17 -05:00
Sonik H
377c7c200f Translated using Weblate (Greek)
Currently translated at 95.7% (519 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2025-03-03 07:01:17 -05:00
Niels van Velzen
a4d8295ecd Fix filtering not working in collections view (v2) 2025-03-03 08:47:13 +01:00
Niels van Velzen
71a205dc5a Revert "Fix filtering not working in collections view"
This reverts commit 27c430e864.
2025-03-02 20:50:07 +01:00
azumukupoe
a925f4196e Translated using Weblate (Japanese)
Currently translated at 69.3% (376 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-03-02 05:14:04 -05:00
azumukupoe
da967f312d Translated using Weblate (Japanese)
Currently translated at 69.1% (375 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-03-02 05:04:30 -05:00
Weblate
a1e3609af8 Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2025-03-02 04:45:56 -05:00
azumukupoe
24bca378f6 Translated using Weblate (Japanese)
Currently translated at 68.2% (370 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-03-02 04:45:54 -05:00
Blackspirits
390e9f85a2 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-03-02 04:45:54 -05:00
Blackspirits
4702f2f1a4 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-03-02 04:15:35 -05:00
Gallyam Biktashev
8b60168c85 Translated using Weblate (Russian)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-03-01 20:56:30 -05:00
AfmanS
e404f93b20 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-03-01 03:45:58 -05:00
nextlooper42
86595aa792 Translated using Weblate (Slovak)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2025-02-28 18:13:42 -05:00
renovate[bot]
62c4047487 Update dependency io.mockk:mockk to v1.13.17 2025-02-28 22:39:16 +01:00
Niels van Velzen
612f074bb5 Fix crash when switching subtitle track to non existent index 2025-02-28 22:23:03 +01:00
Niels van Velzen
27c430e864 Fix filtering not working in collections view 2025-02-28 22:22:53 +01:00
John Doe
611954fc6d Translated using Weblate (Finnish)
Currently translated at 99.4% (539 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2025-02-28 00:19:21 -05:00
Gabriel S
a2cf0b61ec Translated using Weblate (Romanian)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 17:30:36 -05:00
Gabriel S
989110c78b Translated using Weblate (Romanian)
Currently translated at 98.7% (535 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 16:36:38 -05:00
Gabriel S
05f6582f11 Translated using Weblate (Romanian)
Currently translated at 96.4% (523 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 16:13:18 -05:00
Gabriel S
4ac482db9a Translated using Weblate (Romanian)
Currently translated at 96.3% (522 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 16:10:49 -05:00
Gabriel S
42efa9d780 Translated using Weblate (Romanian)
Currently translated at 95.7% (519 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 16:06:54 -05:00
Gabriel S
04adefc15e Translated using Weblate (Romanian)
Currently translated at 94.4% (512 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 15:53:26 -05:00
Gabriel S
6bc2b9621c Translated using Weblate (Romanian)
Currently translated at 93.9% (509 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 15:44:25 -05:00
felix920506
6355cd8815 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2025-02-27 15:36:43 -05:00
felix920506
029255c735 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-02-27 15:36:42 -05:00
Gabriel S
69567f4d79 Translated using Weblate (Romanian)
Currently translated at 93.1% (505 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 15:36:42 -05:00
Gabriel S
c7b1280516 Translated using Weblate (Romanian)
Currently translated at 91.8% (498 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 15:21:43 -05:00
Gabriel S
39b31478a3 Translated using Weblate (Romanian)
Currently translated at 91.6% (497 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 15:13:50 -05:00
Gabriel S
18e7aae9df Translated using Weblate (Romanian)
Currently translated at 89.8% (487 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2025-02-27 14:57:27 -05:00
Andi Chandler
47e90c8a60 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-02-27 14:02:16 -05:00
Kityn
87bfd65f58 Translated using Weblate (Polish)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-02-27 01:09:36 -05:00
Bas
1d982994ee Translated using Weblate (Dutch)
Currently translated at 100.0% (542 of 542 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-02-26 15:42:07 -05:00
renovate[bot]
3aabf11bb0 Update dependency androidx.constraintlayout:constraintlayout to v2.2.1 2025-02-26 20:52:29 +01:00
Niels van Velzen
5ae05c1270 Add button to report device profile to server for troubleshooting 2025-02-26 20:46:28 +01:00
renovate[bot]
1fdbce3d69 Update dependency com.android.tools.build:gradle to v8.8.2 2025-02-26 19:29:00 +01:00
renovate[bot]
c12d01b1ac Update dependency androidx.activity:activity to v1.10.1 2025-02-26 19:28:43 +01:00
Lukas Fichtner
2a49b8ba50 fix progress time calculation 2025-02-26 19:21:23 +01:00
millallo
f855c1ae8d Translated using Weblate (Italian)
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2025-02-26 05:01:17 -05:00
Niels van Velzen
a70662d89f Use color type in OptionsColorList 2025-02-25 22:06:33 +01:00
Niels van Velzen
1a711efc81 Use media3 MimeTypes in deviceProfile
The AV1 constant in MediaFormat is not available in older API levels, use the media3 constants instead
2025-02-25 22:06:25 +01:00
Marco Ferrari
68d8b1163c fix: set max resolution for common video codecs
Instead of relying on the max resolution for the H264 codec decoder as a
global setting when computing device capabilities, set the max supported
resolution for the most common video codecs by querying the decoder.

Video codecs that support this are: AVC (H264), HEVC (H265), AV1.

This change avoids unnecessary transcodings because, on some devices,
the AVC decoder might support a lower maximum resolution compared to
other decoders that the device supports. For example, if the AVC decoder
supports up to 2K resolution decoding, and the HEVC supports up to 4K
resolution decoding, Jellyfin would have transcoded a 4K HEVC media
stream.
2025-02-25 17:26:57 +01:00
Andi Chandler
c8ebcd2407 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-02-25 10:01:17 -05:00
renovate[bot]
03b577d228 Update dependency com.android.tools:desugar_jdk_libs to v2.1.5 2025-02-25 11:43:27 +01:00
renovate[bot]
6d4a342fac Update dependency gradle to v8.13 2025-02-25 11:37:42 +01:00
Kityn
a994f8ab66 Translated using Weblate (Polish)
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2025-02-25 04:01:17 -05:00
Blackspirits
e2ac09b168 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2025-02-25 04:01:17 -05:00
Bas
9643aa93ae Translated using Weblate (Dutch)
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2025-02-24 19:01:17 -05:00
OwOchlé
3c62490471 Subtitles background opacity (#4423)
* feat: added subtitles background opacity option

* feat: merged opacity and background color settings

* chore: cleared unused imports
2025-02-24 21:58:55 +01:00
renovate[bot]
aa64fc504f Update CI dependencies 2025-02-23 21:39:11 +01:00
renovate[bot]
4aa54f8e1f Update dependency io.gitlab.arturbosch.detekt to v1.23.8 2025-02-23 21:38:59 +01:00
HanaO00
a874991831 Translated using Weblate (French)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-02-21 11:01:17 -05:00
Serhii Romanov
f0e4ad050f Translated using Weblate (Ukrainian)
Currently translated at 99.4% (533 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-02-20 10:01:17 -05:00
Serhii Romanov
4dc36c506d Translated using Weblate (Ukrainian)
Currently translated at 98.8% (530 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2025-02-20 07:01:17 -05:00
naokiiida
b18a642fd6 Translated using Weblate (Japanese)
Currently translated at 69.2% (371 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2025-02-20 07:01:17 -05:00
Ronan Fitzgerald
51604826ff Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2025-02-19 18:01:17 -05:00
renovate[bot]
ea0c55811b Update appleboy/ssh-action action to v1.2.1 2025-02-19 19:14:34 +01:00
renovate[bot]
848adb3e9b Update aboutlibraries to v11.6.3 2025-02-19 19:14:16 +01:00
Niels van Velzen
55565901d1 Use getSubtitleUrl in ExternalPlayerActivity 2025-02-17 11:04:37 +01:00
renovate[bot]
734dc04f35 Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.6 2025-02-17 11:04:37 +01:00
Niels van Velzen
e696f3f944 Remove aboutLibraries config (now default) 2025-02-16 21:32:57 +01:00
renovate[bot]
6eeddba9d6 Update aboutlibraries to v11.6.2 2025-02-16 21:32:57 +01:00
renovate[bot]
fda68f4aab Update CI dependencies 2025-02-16 21:31:17 +01:00
Command
5826984ff9 Translated using Weblate (Hebrew (Israel))
Currently translated at 11.5% (62 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he_IL/
2025-02-16 11:01:17 -05:00
Niels van Velzen
bc6336c376 Remove org.jellyfin.apiclient dependency 2025-02-13 21:57:52 +01:00
Niels van Velzen
1ed6611b7d Replace Response<T> usages with local type 2025-02-13 21:57:52 +01:00
Niels van Velzen
a4d2f0a030 Remove ModelCompat 2025-02-13 21:57:52 +01:00
Niels van Velzen
d189178d46 Remove Java ApiClient instance 2025-02-13 21:57:52 +01:00
renovate[bot]
38372a5f6b Update dependency com.android.tools.build:gradle to v8.8.1 2025-02-13 21:13:47 +01:00
Niels van Velzen
e33d85c4ff Rewrite PlaybackManager with SDK 2025-02-13 21:09:06 +01:00
renovate[bot]
40e0b98964 Update dependency androidx.compose.ui:ui-tooling to v1.7.8 2025-02-12 22:15:21 +01:00
renovate[bot]
47304e3f96 Update dependency androidx.compose.foundation:foundation to v1.7.8 2025-02-12 19:25:06 +01:00
renovate[bot]
6160d5c789 Update androidx.fragment to v1.8.6 2025-02-12 19:24:54 +01:00
Niels van Velzen
9fc1efb35d Decouple external video playback from internal playback code (#4438)
* Decouple ExternalPlayerActivity from playback code

* Add external subtitle support

* Automatically play next video queue item

* Fix resume & position report

* Fix VLC forced to play from start
2025-02-12 19:16:32 +01:00
renovate[bot]
6418140797 Update coil to v3.1.0 2025-02-05 09:27:36 +01:00
Toyo
8346adba34 Translated using Weblate (Spanish (Argentina))
Currently translated at 96.6% (518 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_AR/
2025-01-30 01:01:17 -05:00
renovate[bot]
75d8b3e2c7 Update dependency androidx.compose.foundation:foundation to v1.7.7 2025-01-29 20:04:35 +01:00
renovate[bot]
0d5369dc4c Update CI dependencies 2025-01-29 20:01:21 +01:00
renovate[bot]
28864231c6 Update dependency androidx.compose.ui:ui-tooling to v1.7.7 2025-01-29 20:00:58 +01:00
Niels van Velzen
c0422547d3 Update reported client name 2025-01-29 20:00:45 +01:00
Keaahu
4c51b935cc Translated using Weblate (French)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-01-28 08:01:16 -05:00
Resistive
abe7225079 Translated using Weblate (Russian)
Currently translated at 99.6% (534 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2025-01-26 17:01:16 -05:00
renovate[bot]
9882ffb7b7 Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.5 2025-01-26 19:21:00 +01:00
renovate[bot]
5d551f3cfa Update dependency com.android.tools.build:gradle to v8.8.0 2025-01-24 20:07:17 +01:00
renovate[bot]
e4cbe2ae3a Update CI dependencies 2025-01-24 20:04:45 +01:00
renovate[bot]
7de76927ee Update dependency gradle to v8.12.1 2025-01-24 20:04:24 +01:00
renovate[bot]
1a3b9bfb34 Update koin to v4.0.2 2025-01-24 20:04:15 +01:00
Dominik
80bbe8f6ff Translated using Weblate (Slovenian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/sl/
2025-01-24 10:01:16 -05:00
Dominik
b6fc1210dd Translated using Weblate (Slovenian)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sl/
2025-01-23 11:01:16 -05:00
renovate[bot]
db7d7f9993 Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.4 2025-01-22 22:52:13 +01:00
Aleksandar Petrov
b540f29197 Translated using Weblate (Bulgarian)
Currently translated at 34.7% (186 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/bg/
2025-01-19 12:01:15 -05:00
dtrexler
bbb82ddc12 Fix codec keys in new playback module (#4411)
* Fix codec names in mime type maps

* Update CONTRIBUTORS.md
2025-01-19 15:02:59 +00:00
renovate[bot]
6d2778cd7a Update aboutlibraries to v11.4.0 2025-01-18 18:59:31 +01:00
renovate[bot]
2ff7f1f0ac Update dependency io.mockk:mockk to v1.13.16 2025-01-18 18:59:08 +01:00
renovate[bot]
556b215920 Update CI dependencies 2025-01-18 18:58:54 +01:00
smarthome-abc
f6f324cfa9 Trust user added CA certificates (#4397)
* Update AndroidManifest.xml

* Create network_security_config.xml

* Allow user CA certs: Fix PR lint issues

* Allow user CA certs: Add a new line

---------

Co-authored-by: ABC <ABC@Macbook.local>
2025-01-17 20:18:56 +01:00
newton181
fe8399a36d Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2025-01-16 18:01:15 -05:00
renovate[bot]
35b17af75b Update dependency androidx.activity:activity to v1.10.0 2025-01-15 20:09:11 +01:00
renovate[bot]
1a35df92eb Update dependency androidx.recyclerview:recyclerview to v1.4.0 2025-01-15 20:08:59 +01:00
coldwlan
1457e9c089 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2025-01-15 03:01:16 -05:00
warkurre86
67b80043e5 Translated using Weblate (Czech)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2025-01-14 11:01:15 -05:00
Pere
63d30ebf20 Translated using Weblate (Catalan)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2025-01-07 09:01:15 -05:00
Dockey
ba39c2307b Translated using Weblate (Swedish)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2025-01-07 09:01:15 -05:00
Kachelkaiser
fb5b4d78ba Translated using Weblate (German)
Currently translated at 99.8% (535 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2025-01-07 06:01:15 -05:00
Niels van Velzen
54a70e9e69 Fix crash when favoriting Live TV program while loading additional channels in the guide 2025-01-05 22:12:03 +01:00
Henning Weiss
3c315be080 Run LeanbackHelper onStop() to refresh home screen (#4347)
* Run LeanbackHelper onPause() to refresh home screen.

* Moved Leanback worker call to onStop().

* Moved workManager to class property.
2025-01-05 15:56:38 +01:00
BotBlake
e3c47b8500 update issue forms (#4369)
* update versions

* add before-posting checkboxes

* fix indents 🗿

* add headlines to playback report

* add 'other' to playback issue form

* fix indent (again) 🗿

* update bug-report issue form

* update issue forms

* shorten placeholders

* adress review

* rephrase issue forms
2025-01-05 15:56:08 +01:00
Niels van Velzen
38aa2f1cb3 Prevent seeking from crashing app if video info is not initialized yet 2025-01-03 22:38:32 +01:00
Catherine Gilbert
d91d873c61 Dismiss playback actions popups on fragment detach (#4365)
* Dismiss playback actions popups on fragment detach

* Update CONTRIBUTORS.md
2025-01-03 22:06:33 +01:00
Niels van Velzen
b6b2c0335f Fix unable to focus toolbar in item details screen 2025-01-03 22:04:54 +01:00
Niels van Velzen
eb8d7f8392 Fix unable to focus toolbar in server selection screen 2025-01-03 22:04:54 +01:00
vasapol
9ebbaa5bb4 Translated using Weblate (Thai)
Currently translated at 40.6% (218 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/th/
2025-01-03 15:01:15 -05:00
RedDot
e1e6ffdfcb Translated using Weblate (French)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2025-01-03 15:01:15 -05:00
hyperjoco
1a9bb5d061 Translated using Weblate (Hungarian)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2025-01-03 07:01:15 -05:00
Roi Gabay
67c545152b Translated using Weblate (Hebrew)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2025-01-02 17:01:15 -05:00
John Doe
da78cf4a2f Translated using Weblate (Finnish)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2025-01-02 08:01:15 -05:00
BromTeque
c2cbd1c925 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2025-01-01 20:01:15 -05:00
bene toffix
f2b6bda258 Translated using Weblate (Catalan)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2024-12-31 14:01:15 -05:00
Niels van Velzen
c86573b671 Fix app crashing when playback reporting fails 2024-12-31 17:27:04 +01:00
Niels van Velzen
3385058775 Fix Live TV fail-over not working 2024-12-30 22:18:34 +01:00
Diogo Dinis
abf32626ac Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2024-12-30 10:01:15 -05:00
Ilias Theodoopoulos
40f4682f17 Translated using Weblate (Greek)
Currently translated at 96.2% (516 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2024-12-30 10:01:15 -05:00
Niels van Velzen
a0e9bd73c4 Replace Icons.Default.Done with ic_check in ConnectHelpAlertFragment 2024-12-30 09:04:56 +01:00
millallo
0f00a8fad9 Translated using Weblate (Italian)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2024-12-29 20:01:15 -05:00
Pere
d86b9c177a Translated using Weblate (Catalan)
Currently translated at 98.1% (526 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2024-12-29 17:01:15 -05:00
nextlooper42
0970c88338 Translated using Weblate (Slovak)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2024-12-29 13:01:15 -05:00
Kityn
72c888cf21 Translated using Weblate (Polish)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-12-28 18:01:15 -05:00
Niels van Velzen
0533d54bbd Enable audio focus for music playback 2024-12-28 23:12:33 +01:00
Bas
f26a1e49e4 Translated using Weblate (Dutch)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-12-28 12:01:14 -05:00
Niels van Velzen
832ab68777 Centralize requested item fields 2024-12-28 15:22:05 +01:00
Weblate
7e6f88e33f Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2024-12-28 09:21:54 -05:00
dtrexler
518200028f Use string formatting for media runtime display 2024-12-28 15:21:50 +01:00
dtrexler
2fa7753e91 Update runtime display to be consistent with web client 2024-12-28 15:21:50 +01:00
Niels van Velzen
df2aeeac75 Infer subtitle codec from delivery URL 2024-12-25 10:33:34 +01:00
Niels van Velzen
d349b79665 Fix crash when starting progress report loop without active stream in video player 2024-12-24 14:00:18 +01:00
renovate[bot]
dae017c970 Update koin to v4.0.1 2024-12-23 17:25:11 +01:00
renovate[bot]
3323442cdd Update github/codeql-action action to v3.28.0 2024-12-23 17:24:06 +01:00
renovate[bot]
f098472827 Update dependency io.insert-koin:koin-androidx-compose to v4.0.1 2024-12-23 17:21:45 +01:00
Niels van Velzen
1adb9b08d7 Use private entry index in QueueService 2024-12-21 21:29:40 +01:00
Niels van Velzen
c18a68a54d Fix repeat mode not working 2024-12-21 21:29:40 +01:00
Niels van Velzen
f95f3d4637 Fix music play action not working after queue has ended 2024-12-21 21:29:33 +01:00
Niels van Velzen
8b2d398942 Fix QueueService.getNextIndices returning one item too many when using REPEAT_ENTRY_ONCE 2024-12-21 09:47:22 +01:00
Niels van Velzen
eb7fd833b0 Prevent AudioNowPlayingFragment from showing without active queue 2024-12-21 09:47:16 +01:00
Niels van Velzen
25e79e939e Fix QueueService.next not respecting usePlaybackOrder and useRepeatMode properly 2024-12-21 09:47:04 +01:00
Niels van Velzen
5547bbc468 Fix useNextIndex never removing first element in ShuffleOrderIndexProvider and RandomOrderIndexProvider 2024-12-21 09:47:04 +01:00
Niels van Velzen
e87e96e9e3 Fix UI audio queue order when shuffling 2024-12-21 09:46:57 +01:00
renovate[bot]
4ebb45b565 Update dependency io.mockk:mockk to v1.13.14 2024-12-20 19:31:16 +01:00
renovate[bot]
ed9dd720c1 Update dependency gradle to v8.12 2024-12-20 19:30:59 +01:00
renovate[bot]
6565059de6 Update dependency com.android.tools:desugar_jdk_libs to v2.1.4 2024-12-20 13:23:23 +01:00
renovate[bot]
7fee15f2cd Update CI dependencies 2024-12-19 21:50:49 +01:00
renovate[bot]
9b9c37937b Update androidx.media3 to v1.5.1 2024-12-19 21:50:31 +01:00
stanol
4b7779ade6 Translated using Weblate (Ukrainian)
Currently translated at 98.5% (527 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2024-12-19 08:57:45 -05:00
Niels van Velzen
25db7d5286 Fix external subtitles not added to external player 2024-12-19 08:54:24 +01:00
DJAlone1992
2c5f17a0f4 Translated using Weblate (Russian)
Currently translated at 99.6% (533 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2024-12-18 21:01:14 -05:00
wxwrn
8e34d96832 Translated using Weblate (Slovenian)
Currently translated at 95.1% (509 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sl/
2024-12-17 12:51:14 -05:00
shape93
933e00fadf Translated using Weblate (Italian)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2024-12-17 06:01:14 -05:00
renovate[bot]
3126762c58 Update dependency androidx.work:work-runtime to v2.10.0 2024-12-13 22:25:58 +01:00
renovate[bot]
eaa7a4274b Update dependency androidx.core:core-ktx to v1.15.0 2024-12-13 22:25:37 +01:00
renovate[bot]
81050c208b Update github/codeql-action action to v3.27.9 2024-12-13 22:21:23 +01:00
Niels van Velzen
dd380ee7d7 Update androidx.media3 to 1.5.0 2024-12-13 22:20:52 +01:00
Niels van Velzen
bb7851beb1 Fix new linter issues 2024-12-13 22:16:21 +01:00
Niels van Velzen
458baabe93 Use Android SDK 35 (Android 15) 2024-12-13 22:16:21 +01:00
John Doe
93f71a776d Translated using Weblate (Finnish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2024-12-13 09:01:14 -05:00
stanol
20d8cb5ee1 Translated using Weblate (Ukrainian)
Currently translated at 97.5% (522 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2024-12-12 17:01:14 -05:00
renovate[bot]
141e0b7539 Update dependency androidx.compose.ui:ui-tooling to v1.7.6 2024-12-11 21:30:48 +01:00
renovate[bot]
490d2276d3 Update github/codeql-action action to v3.27.7 2024-12-11 21:27:50 +01:00
renovate[bot]
62c1062d8f Update dependency androidx.compose.foundation:foundation to v1.7.6 2024-12-11 21:27:27 +01:00
luizfern12
f8919ec5df Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.4% (532 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2024-12-09 15:01:14 -05:00
Marek Pavelka
dc6e861ad7 Translated using Weblate (Czech)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2024-12-08 09:01:13 -05:00
Marek Pavelka
c2988afb7e Translated using Weblate (Czech)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2024-12-08 06:01:14 -05:00
queeup
1c08735ffd Translated using Weblate (Turkish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2024-12-07 11:01:13 -05:00
queeup
c9144fc82f Translated using Weblate (Turkish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2024-12-07 07:01:14 -05:00
newton181
ae1362e694 Translated using Weblate (Spanish (Mexico))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_MX/
2024-12-06 19:00:03 -05:00
Niels van Velzen
c62c0511a4 Always call notifyInteraction on navigation 2024-12-06 21:46:38 +01:00
Niels van Velzen
f37036faf2 Make playbackController reference optional in ReportingHelper 2024-12-05 22:25:50 +01:00
Niels van Velzen
b600484b19 Fix ItemRowAdapterHelper.refreshItem using wrong thread when invoking callback 2024-12-05 21:52:49 +01:00
renovate[bot]
f4bd3afd1b Update github/codeql-action action to v3.27.6 2024-12-05 17:08:28 +01:00
Niels van Velzen
006a6d008f Fix crash when trying to report playback progress when there is no current stream 2024-12-05 17:06:10 +01:00
Niels van Velzen
2fea54658e Fix crash when viewing audio now playing while using Emerald theme 2024-12-05 17:05:59 +01:00
Niels van Velzen
33f11515c9 Fix crash when restoring DestinationFragmentView state 2024-12-05 17:05:50 +01:00
lanklaas
f4a291f38c Translated using Weblate (Afrikaans)
Currently translated at 1.6% (9 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/af/
2024-12-05 04:00:03 -05:00
lanklaas
eff17801bd Added translation using Weblate (Afrikaans) 2024-12-05 01:16:16 -05:00
YFDOOR
5eabe9f43d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-12-03 21:00:02 -05:00
John Doe
5c3d296580 Translated using Weblate (Finnish)
Currently translated at 99.6% (533 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2024-12-03 16:00:03 -05:00
renovate[bot]
b3068e52f7 Update dependency com.android.tools.build:gradle to v8.7.3 2024-12-02 22:09:07 +01:00
Benedict Endemann
33d24175aa Translated using Weblate (German)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2024-12-01 18:00:02 -05:00
Niels van Velzen
79a97c3f4a Specify fields in resumePlayback() API request 2024-11-29 21:19:08 +01:00
John Doe
e60c2a49de Translated using Weblate (Finnish)
Currently translated at 95.3% (510 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2024-11-29 01:00:02 -05:00
Aidas
952a53a54b Translated using Weblate (Lithuanian)
Currently translated at 79.4% (425 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2024-11-28 17:00:02 -05:00
Aidas
1ec062fcd4 Translated using Weblate (Lithuanian)
Currently translated at 79.2% (424 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2024-11-27 18:00:01 -05:00
HanaO00
f90ef25386 Translated using Weblate (French)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-11-27 13:00:01 -05:00
Aidas
c734f30bd9 Translated using Weblate (Lithuanian)
Currently translated at 79.0% (423 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2024-11-27 04:00:02 -05:00
Aidas
d16615796d Translated using Weblate (Lithuanian)
Currently translated at 77.7% (416 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2024-11-26 14:00:02 -05:00
Simon Hung
a37995f770 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2024-11-26 14:00:01 -05:00
Thunderstrike116
9e45391850 Translated using Weblate (Greek)
Currently translated at 96.2% (515 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2024-11-26 14:00:01 -05:00
Aidas
3a4a4ada1c Translated using Weblate (Lithuanian)
Currently translated at 76.6% (410 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/lt/
2024-11-26 11:18:31 -05:00
renovate[bot]
1caaf3de67 Update coil to v3.0.4 2024-11-26 08:38:56 +01:00
Andi Chandler
4928d26d8b Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2024-11-25 11:00:01 -05:00
xephos1one
82089d2734 Translated using Weblate (German)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2024-11-22 09:00:01 -05:00
renovate[bot]
b16f4b8667 Update dependency gradle to v8.11.1 2024-11-20 19:35:48 +01:00
renovate[bot]
50088ef5cd Update github/codeql-action action to v3.27.5 2024-11-20 19:35:02 +01:00
Justin
57b918433f Translated using Weblate (German)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2024-11-19 19:00:01 -05:00
Niels van Velzen
8c2caf627f Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.3 2024-11-19 16:04:19 +01:00
Muhammad Zufar
b2711084c7 Translated using Weblate (Indonesian)
Currently translated at 93.6% (501 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/id/
2024-11-19 10:00:01 -05:00
Ace
7807bb32f2 Translated using Weblate (Swedish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2024-11-18 18:00:01 -05:00
renovate[bot]
2218246478 Update gradle/actions action to v4.2.1 2024-11-18 21:59:13 +01:00
Andi Chandler
0ec4d4e4bf Translated using Weblate (English (United Kingdom))
Currently translated at 99.8% (534 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2024-11-17 19:00:01 -05:00
koreapyj
1a95759d59 Translated using Weblate (Korean)
Currently translated at 99.6% (533 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ko/
2024-11-17 05:00:01 -05:00
renovate[bot]
e83cef2b26 Update appleboy/ssh-action action to v1.2.0 2024-11-17 09:26:51 +01:00
renovate[bot]
b876c4b782 Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.2 2024-11-17 09:26:15 +01:00
Niels van Velzen
300346feb8 Reset queue index on end
With this change the queue index will always reset to -1 (INDEX_NONE) once the last item in the queue ends instead of leaving the last queue item active. This solves various issues in the UI (like the screensaver) where it keeps showing the last item when nothing is playing
2024-11-16 20:26:34 +01:00
Niels van Velzen
ee1403aaad Fix audio now playing screen always showing "1 of x" instead of the actual queue position 2024-11-15 19:37:17 +01:00
renovate[bot]
a572710fd7 Update dependency io.coil-kt.coil3:coil-gif to v3.0.3 2024-11-15 19:33:38 +01:00
Niels van Velzen
003b4148cf Fix background of album in now playing screen when lyrics are displaying 2024-11-15 07:30:12 +01:00
newton181
52d844e281 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2024-11-14 15:00:01 -05:00
newton181
f7994d0e38 Translated using Weblate (Spanish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2024-11-14 15:00:00 -05:00
Niels van Velzen
ea33799059 Refactor subtitle profiles to be more readable 2024-11-14 20:06:14 +01:00
MichaelR416
487104fdf8 Really never load PGS externally 2024-11-14 19:21:40 +01:00
renovate[bot]
59b4bac902 Update CI dependencies 2024-11-14 19:20:23 +01:00
newton181
67467ec0ed Translated using Weblate (Spanish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2024-11-13 22:00:00 -05:00
nextlooper42
307bad3ecc Translated using Weblate (Slovak)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2024-11-12 21:00:00 -05:00
Martin
93227bd5b0 Translated using Weblate (Czech)
Currently translated at 99.2% (531 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/cs/
2024-11-12 15:00:00 -05:00
Niels van Velzen
6bb5055136 Fix player UI not hiding automatically 2024-11-12 16:44:30 +01:00
Niels van Velzen
3e059e5857 Never load PGS externally 2024-11-12 16:22:27 +01:00
Niels van Velzen
2ba2b70b85 Use relative index matching for subtitle selection 2024-11-12 15:59:39 +01:00
renovate[bot]
9732b3a232 Update dependency gradle to v8.11 2024-11-12 13:16:12 +01:00
renovate[bot]
af52c4d2d0 Update github/codeql-action action to v3.27.2 2024-11-12 13:15:06 +01:00
Niels van Velzen
169d094471 Fix skipping to end of video reports wrong end time 2024-11-12 09:02:39 +01:00
jh
87e4e7e0ee Translated using Weblate (Danish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2024-11-11 20:00:00 -05:00
Niels van Velzen
ae19a4c862 Fix subtitle menu not always showing "None" as first item 2024-11-11 21:51:17 +01:00
Niels van Velzen
f969f019d3 Fix ImageProvider always throwing 2024-11-11 21:51:07 +01:00
Roi Gabay
e7cbb2077b Translated using Weblate (Hebrew)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2024-11-11 11:00:01 -05:00
Lucas
b64ed6a3b2 Translated using Weblate (French)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-11-11 11:00:00 -05:00
Simon Hung
9e508cca75 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2024-11-11 08:00:00 -05:00
hoanghuy309
590b813b99 Translated using Weblate (Vietnamese)
Currently translated at 96.4% (516 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-11-11 05:00:01 -05:00
Frederik Palmø
ed097cb2b9 Translated using Weblate (Danish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2024-11-11 05:00:01 -05:00
Simon Hung
2544af5c7d Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 97.5% (522 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2024-11-11 05:00:00 -05:00
Blackspirits
5cf636c35d Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2024-11-11 05:00:00 -05:00
hyperjoco
5c6b798d86 Translated using Weblate (Hungarian)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2024-11-11 02:44:55 -05:00
Blackspirits
06d3fd07d0 Translated using Weblate (Portuguese (Portugal))
Currently translated at 99.8% (534 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2024-11-11 02:44:55 -05:00
無情天
20484a21be Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-11-11 00:00:00 -05:00
Paulo Henrique Garcia
69a5e5100f Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.5% (522 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2024-11-10 14:00:01 -05:00
Kityn
d3063d7738 Translated using Weblate (Polish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-11-10 11:00:00 -05:00
Bas
fa2a7bbca8 Translated using Weblate (Dutch)
Currently translated at 100.0% (535 of 535 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-11-10 11:00:00 -05:00
Niels van Velzen
9acf4e3800 Upgrade to Coil 3 2024-11-10 16:51:11 +01:00
Niels van Velzen
91a27ee0ef Fix skipping to end of video reports wrong end time 2024-11-10 16:41:31 +01:00
kabel2
15554bd8f2 Add option to customize seek time (#3794)
* Add skip forward length setting

* Change default skipForwardLength to 30 seconds

* Add variable for skipForwardLength

* Fix merge

* Fix merge

* Try fix tests

* Fix test

* Fix seekbar preference with minimum value above 100

* Use long for forwardTime

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2024-11-10 13:49:02 +00:00
renovate[bot]
17ed07c7f7 Update github/codeql-action action to v3.27.1 2024-11-10 14:28:20 +01:00
koreapyj
8f77b68346 Translated using Weblate (Korean)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/ko/
2024-11-10 07:00:00 -05:00
koreapyj
72163a48aa Translated using Weblate (Korean)
Currently translated at 99.4% (531 of 534 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ko/
2024-11-10 07:00:00 -05:00
Kristian
53d982eff7 Translated using Weblate (Croatian)
Currently translated at 100.0% (534 of 534 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2024-11-09 18:00:00 -05:00
Anthony Magalhaes
5fb69dcb3c Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.3% (520 of 534 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_BR/
2024-11-08 17:00:00 -05:00
Roi Gabay
3109684eab Translated using Weblate (Hebrew)
Currently translated at 100.0% (534 of 534 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2024-11-08 12:00:00 -05:00
Zachary Arnaise
a98e131760 Translated using Weblate (French)
Currently translated at 99.6% (532 of 534 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-11-08 12:00:00 -05:00
renovate[bot]
b74b63bb0a Update dependency com.android.tools:desugar_jdk_libs to v2.1.3 2024-11-07 13:05:26 +01:00
hoanghuy309
baf313c710 Translated using Weblate (Vietnamese)
Currently translated at 96.4% (515 of 534 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-11-07 03:00:00 -05:00
無情天
5914d752b8 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (534 of 534 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-11-06 17:00:00 -05:00
Weblate
28ffa78b8f Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2024-11-05 16:36:51 -05:00
Kityn
c49e7d289c Translated using Weblate (Polish)
Currently translated at 100.0% (539 of 539 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-11-05 16:36:49 -05:00
Niels van Velzen
56d0064319 Use percentage seekbar for subtitle text size 2024-11-05 22:36:45 +01:00
Bas
18ff2a6ce3 Translated using Weblate (Dutch)
Currently translated at 100.0% (539 of 539 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-11-05 14:00:00 -05:00
Niels van Velzen
77ef06de34 Implement TrickPlay images 2024-11-05 17:53:44 +01:00
Niels van Velzen
e1867b23e7 Catch errors when reporting playback state 2024-11-05 15:45:20 +01:00
Niels van Velzen
f21a9022d5 Fix position on playback stop reporting when skipping to playback end 2024-11-05 15:44:14 +01:00
Niels van Velzen
de883fb709 Fix sorting TV shows by last played 2024-11-05 15:44:06 +01:00
Niels van Velzen
f6e65fadac Catch errors when loading MediaSessionService artwork 2024-11-05 15:43:58 +01:00
Niels van Velzen
fc03e95d23 Remove runBlocking usage in HomeRowsFragment 2024-11-05 15:43:50 +01:00
Ayla Ounce
0d00adc8a6 Fix exo track id parsing for format change.
Without this changing to other audio tracks fails, it just keeps playing
the first one in the file. I was tipped off to the source of the problem
by lines like this in logcat:

11-04 19:26:01.244 11669 11669 D VideoManager: failed to parse track ID [0:2]

It appears exoplayer changed from a simple number for trackid to two
numbers separated by a colon. Haven't had any luck tracking down why,
but the latter of the two appears to match the old single number so,
just pull that out and use it.
2024-11-05 13:51:04 +01:00
Niels van Velzen
f474e2a753 Fix audio track selection when baking subtitles 2024-11-03 20:37:24 +01:00
Bas
ef236c8a55 Translated using Weblate (Dutch)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-11-03 14:06:00 -05:00
renovate[bot]
873f66c256 Update acra to v5.12.0 2024-11-03 18:46:29 +01:00
renovate[bot]
1e7c8bbf38 Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.1 2024-11-03 18:45:55 +01:00
Niels van Velzen
0dae580732 Fix player crashing when playback failed 2024-11-03 18:42:59 +01:00
Niels van Velzen
98f84c630c Fix getSubtitleDeliveryMethod in StreamInfo always returning "Encoding" 2024-11-02 22:45:01 +01:00
Niels van Velzen
ef25757b45 Add additional information to PlaybackStartInfo 2024-11-02 22:44:52 +01:00
Niels van Velzen
ef4e2b56d7 Consider artist names before album artist names 2024-11-02 16:50:08 +01:00
Niels van Velzen
b0d5a788dc Consider artist images before album artist images 2024-11-02 16:02:38 +01:00
jh
2f14d77ed1 Translated using Weblate (Danish)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2024-11-02 10:41:37 -04:00
Niels van Velzen
bc4f246b66 Don't close player with invalid state in onCreate 2024-11-02 10:35:42 +01:00
jh
3f96c3e7b9 Translated using Weblate (Danish)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2024-11-01 21:41:37 -04:00
Bas
1939569320 Translated using Weblate (Dutch)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-11-01 16:41:37 -04:00
Niels van Velzen
0f97f5a95b Add missing audioCodec to music transcode 2024-10-31 23:01:29 +01:00
renovate[bot]
3657ad707e Update dependency com.android.tools.build:gradle to v8.7.2 2024-10-31 22:29:49 +01:00
Niels van Velzen
0c378dd7ff Fix synced lyrics not working in AudioNowPlayingFragment 2024-10-31 20:04:53 +01:00
Niels van Velzen
44ddb3b1b8 Decrease scaling size of active lyric line 2024-10-31 20:04:53 +01:00
Niels van Velzen
1bfc00a4d0 Fix moving focus down from home button in AudioNowPlayingFragment 2024-10-31 20:04:53 +01:00
x1Rz47
e41d1405ca Translated using Weblate (Uyghur)
Currently translated at 19.7% (106 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ug/
2024-10-31 06:41:37 -04:00
newton181
69a4d13081 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2024-10-30 17:41:38 -04:00
newton181
26a73b9282 Translated using Weblate (Spanish)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2024-10-30 17:41:37 -04:00
newton181
84f7a26017 Translated using Weblate (Spanish (Mexico))
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_MX/
2024-10-30 17:41:37 -04:00
renovate[bot]
b616a94287 Update dependency androidx.compose.ui:ui-tooling to v1.7.5 2024-10-30 21:19:14 +01:00
renovate[bot]
f6c5e6f467 Update dependency androidx.constraintlayout:constraintlayout to v2.2.0 2024-10-30 21:09:50 +01:00
renovate[bot]
a7f51b5a2c Update dependency androidx.compose.foundation:foundation to v1.7.5 2024-10-30 21:07:23 +01:00
renovate[bot]
322985c054 Update androidx.lifecycle to v2.8.7 2024-10-30 19:50:21 +01:00
renovate[bot]
0568361b6b Update androidx.fragment to v1.8.5 2024-10-30 19:48:35 +01:00
Niels van Velzen
b3beb8a92d Fix video restarting immediately when baking subtitles 2024-10-30 19:33:26 +01:00
Niels van Velzen
1062d7b844 Hide video player controls by default 2024-10-29 22:16:32 +01:00
Niels van Velzen
e7738c7bc1 Sync custom controls with built-in controls in leanback overlay 2024-10-29 21:30:35 +01:00
Niels van Velzen
e44b36e830 Fix adding music to existing queue 2024-10-29 18:41:39 +01:00
Niels van Velzen
2b4a5b6f2e Rewrite reporting helper with SDK 2024-10-29 16:40:35 +01:00
Niels van Velzen
67d470f961 Rewrite usages of QueueEntry in UI 2024-10-28 15:39:56 +01:00
Niels van Velzen
81aa372e40 Automatically disable subtitles when baking fails 2024-10-28 07:31:52 +01:00
Niels van Velzen
059140f7a2 Use "Ask to skip" by default for intros and outros 2024-10-27 22:17:17 +01:00
Frederik Palmø
cae32a2015 Translated using Weblate (Danish)
Currently translated at 99.8% (537 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/da/
2024-10-27 11:41:37 -04:00
NOV
3b3f5e2e42 Translated using Weblate (French)
Currently translated at 99.8% (537 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-10-26 23:41:37 -04:00
queeup
8e1ce880a8 Translated using Weblate (Turkish)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2024-10-26 19:41:37 -04:00
renovate[bot]
f88dd54bcf Update dependency org.jellyfin.sdk:jellyfin-core to v1.6.0 2024-10-26 21:05:14 +02:00
Niels van Velzen
786110b52e Implement lyrics 2024-10-26 19:48:14 +02:00
renovate[bot]
7b51b848ca Update actions/setup-java action to v4.5.0 2024-10-26 16:59:28 +02:00
fract exe
829334a147 Translated using Weblate (Croatian)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2024-10-25 10:41:37 -04:00
Rafael Morine
b128fa32b9 Translated using Weblate (Russian)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2024-10-25 06:41:37 -04:00
Ruben Teixeira
175d04d5ad Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2024-10-24 16:41:36 -04:00
renovate[bot]
4e67e51271 Update CI dependencies 2024-10-23 20:50:58 +02:00
fract exe
dabb514d17 Translated using Weblate (Croatian)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2024-10-23 09:41:37 -04:00
fract exe
4d0a56aa68 Translated using Weblate (Croatian)
Currently translated at 93.1% (501 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hr/
2024-10-23 06:41:37 -04:00
John Doe
b49a09425f Translated using Weblate (Finnish)
Currently translated at 91.4% (492 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fi/
2024-10-23 06:41:37 -04:00
Bas
0ac521096f Translated using Weblate (Dutch)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-22 17:41:36 -04:00
Niels van Velzen
8cdeb65345 Fix PlaybackController not always disabling default track 2024-10-20 22:44:25 +02:00
Niels van Velzen
fbfd681917 Fix not disabling embedded subtitle tracks that require baking 2024-10-20 15:04:18 +02:00
Niels van Velzen
9ea1cc58a7 Always use lowercase codec when mapping to mime type 2024-10-20 15:04:18 +02:00
Niels van Velzen
662b1825c1 Rewrite all subtitle behavior 2024-10-20 15:04:18 +02:00
AfmanS
0cd34ba163 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2024-10-19 14:41:36 -04:00
Bas
24120146ec Translated using Weblate (Dutch)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-19 06:41:36 -04:00
Niels van Velzen
d96e23d001 Change upcomingMinimumServerVersion to 10.10.0 to warn about upcoming 10.10 requirement 2024-10-17 18:55:26 +02:00
renovate[bot]
354acf5bf5 Update dependency androidx.compose.ui:ui-tooling to v1.7.4 2024-10-16 22:10:40 +02:00
renovate[bot]
7f480ea7fc Update dependency androidx.activity:activity to v1.9.3 2024-10-16 21:34:33 +02:00
renovate[bot]
e04824ce5e Update dependency androidx.compose.foundation:foundation to v1.7.4 2024-10-16 21:34:07 +02:00
Roi Gabay
d6d48ca78a Translated using Weblate (Hebrew)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2024-10-16 05:44:46 -04:00
Niels van Velzen
016de2d087 Update package for Koin viewModel import
Old one is deprecated
2024-10-15 22:46:25 +02:00
renovate[bot]
c1e8653da8 Update dependency com.android.tools.build:gradle to v8.7.1 2024-10-15 22:16:09 +02:00
Niels van Velzen
746c662bb9 Use parcelable array list in DestinationFragmentView saved state 2024-10-15 22:15:16 +02:00
renovate[bot]
79f6bc9683 Update github/codeql-action action to v3.26.13 2024-10-15 22:15:06 +02:00
Niels van Velzen
acf8af6441 Use Java 21 in jvm toolchain 2024-10-15 17:54:32 +02:00
myrad2267
b4e4029c86 Translated using Weblate (French)
Currently translated at 99.0% (533 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-10-15 00:41:36 -04:00
Persephone42
957f3643bf Translated using Weblate (Serbian)
Currently translated at 59.4% (320 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sr/
2024-10-14 15:25:55 -04:00
Ilias Theodoopoulos
f97dd87984 Translated using Weblate (Greek)
Currently translated at 92.7% (499 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/el/
2024-10-14 10:41:36 -04:00
Niels van Velzen
cade3fd6bf Fix skipping to next episode 2024-10-13 16:56:56 +02:00
hyperjoco
19dc038087 Translated using Weblate (Hungarian)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2024-10-13 09:41:36 -04:00
無情天
1957185e18 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-10-13 02:41:36 -04:00
nextlooper42
73384b6b9a Translated using Weblate (Slovak)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2024-10-12 21:41:36 -04:00
Justin
4ba02728c2 Translated using Weblate (German)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2024-10-12 21:41:36 -04:00
Hoomaane79
8902e63a31 Translated using Weblate (Persian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/fa/
2024-10-12 16:41:36 -04:00
hoanghuy309
288c01befb Translated using Weblate (Vietnamese)
Currently translated at 96.4% (519 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-10-12 13:41:36 -04:00
Andi Chandler
f7ff9f768a Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2024-10-12 13:41:36 -04:00
Niels van Velzen
bec60ed4eb Remove DeviceUtils 2024-10-12 15:25:36 +02:00
Kityn
c509955f21 Translated using Weblate (Polish)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-10-12 07:41:36 -04:00
Bas
26f43ced62 Translated using Weblate (Dutch)
Currently translated at 100.0% (538 of 538 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-12 07:41:36 -04:00
JagerSprinkles
24acb71eee Add preference for default zoom mode (#4020)
* Add logic for default zoom mode setting

* Update to use enumPreference.

* Use MenuBuilder for the zoom mode menu in the player.
Update string for zoom mode preference to aspect ratio.
Update variable name for playerZoomMode in UserPreferences.kt

* Add NonNull as suggested by bot.
Removed unused line of code.

* Add NonNull as suggested by bot

* update string resource for default video zoom

* Misc fixes and refactoring

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2024-10-12 11:33:29 +02:00
Kityn
e1db0523ee Translated using Weblate (Polish)
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-10-12 04:41:36 -04:00
nextlooper42
84d7639f3e Translated using Weblate (Slovak)
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2024-10-11 23:41:36 -04:00
Bas
8e13a51b68 Translated using Weblate (Dutch)
Currently translated at 100.0% (537 of 537 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-11 19:41:36 -04:00
Niels van Velzen
bf4198a8b8 Restore forced aspect ratio for poster types on video items 2024-10-11 21:45:50 +02:00
renovate[bot]
dd4bafd5a4 Update dependency io.mockk:mockk to v1.13.13 2024-10-11 21:45:40 +02:00
renovate[bot]
2d9cdb7d6f Update actions/upload-artifact action to v4.4.3 2024-10-11 21:45:32 +02:00
renovate[bot]
f458d3fdf3 Update Kotlin to v2.0.21 2024-10-11 21:44:41 +02:00
Niels van Velzen
0537a2031e Add "ask to skip" media segment action 2024-10-11 21:33:33 +02:00
Bas
4f23ad47b6 Translated using Weblate (Dutch)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-10 17:41:36 -04:00
trawzified
dede52b978 Translated using Weblate (Dutch)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-10 15:38:44 -04:00
BromTeque
8fe6d807e3 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2024-10-10 09:41:36 -04:00
newton181
90cc4dc658 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_419/
2024-10-09 17:41:36 -04:00
Matheo
8acd8c1e69 Translated using Weblate (French)
Currently translated at 97.7% (524 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-10-09 17:41:36 -04:00
newton181
8574947aa1 Translated using Weblate (Spanish)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es/
2024-10-09 17:41:36 -04:00
newton181
85bbb5daaa Translated using Weblate (Spanish (Mexico))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_MX/
2024-10-09 17:41:36 -04:00
Niels van Velzen
961c858d55 Don't skip segments shorter than 1 second 2024-10-09 21:36:14 +02:00
無情天
ea397196a7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-10-09 08:41:35 -04:00
Roi Gabay
fbcb96f051 Translated using Weblate (Hebrew)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/he/
2024-10-09 03:41:36 -04:00
hoanghuy309
b9d57641d2 Translated using Weblate (Vietnamese)
Currently translated at 96.4% (517 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-10-08 08:41:36 -04:00
Andi Chandler
10b0d33fc7 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2024-10-08 08:41:35 -04:00
Niels van Velzen
c522f09cc2 Fix video player not closing when fragment is stopped 2024-10-08 11:59:17 +02:00
Kityn
095721e021 Translated using Weblate (Polish)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-10-08 04:41:35 -04:00
nextlooper42
d90827c524 Translated using Weblate (Slovak)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2024-10-07 21:41:35 -04:00
Bas
1ac4d49e2b Translated using Weblate (Dutch)
Currently translated at 100.0% (536 of 536 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-07 21:41:35 -04:00
renovate[bot]
ef5b764ae2 Update CI dependencies 2024-10-07 22:41:39 +02:00
Niels van Velzen
e43492ffa5 Implement skip action 2024-10-07 22:41:08 +02:00
Niels van Velzen
8096632a79 Add preferences for media segments 2024-10-07 22:41:08 +02:00
Niels van Velzen
cd1623c6f3 Fix Detekt max line length not matching Editorconfig 2024-10-07 22:34:13 +02:00
hyperjoco
50ad7b30b9 Translated using Weblate (Hungarian)
Currently translated at 100.0% (527 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2024-10-07 05:41:35 -04:00
hoanghuy309
505cdcd723 Translated using Weblate (Vietnamese)
Currently translated at 96.3% (508 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-10-07 01:41:35 -04:00
stanol
025a55ca08 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (527 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2024-10-06 10:41:35 -04:00
Andi Chandler
2e9182a868 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (527 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2024-10-06 10:41:35 -04:00
Niels van Velzen
64924719ba Remove nullability checks for BaseItemDtoQueryResult.items 2024-10-05 14:51:00 +02:00
Niels van Velzen
dc9f36285c Update "new premieres" to use new indexNumber filter in API request 2024-10-05 14:51:00 +02:00
Niels van Velzen
64b7fb1e79 Add missing properties in ModelCompat 2024-10-05 14:51:00 +02:00
Niels van Velzen
50848441ac Update Jellyfin SDK to 10.6.0-beta.1 2024-10-05 14:51:00 +02:00
nextlooper42
939ec5a1c0 Translated using Weblate (Slovak)
Currently translated at 100.0% (527 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2024-10-05 06:41:35 -04:00
皇甫朝云
187bc9c5d1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (527 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-10-05 06:41:35 -04:00
Kityn
9478600764 Translated using Weblate (Polish)
Currently translated at 100.0% (527 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-10-04 19:41:35 -04:00
Bas
70fbbcd9db Translated using Weblate (Dutch)
Currently translated at 100.0% (527 of 527 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-10-04 19:41:35 -04:00
JagerSprinkles
f4401578de Add preference to delay start of video (#4025)
* Add setting to adjust video player start delay

* Update PlaybackController to skip video start delay if set to zero.
Update default for video start delay.
Update video start delay string.

* Update mVideoManager null check for delayed start logic.

* Final changes

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2024-10-04 20:53:03 +00:00
CPK
ef4082cb38 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-10-03 09:41:35 -04:00
Yogesh
c6ed49c0ac Translated using Weblate (Hindi)
Currently translated at 57.6% (303 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-10-03 01:41:35 -04:00
renovate[bot]
7955cbddb7 Update dependency androidx.compose.ui:ui-tooling to v1.7.3 2024-10-03 07:28:11 +02:00
renovate[bot]
cbda5142e8 Update androidx.fragment to v1.8.4 2024-10-02 21:27:48 +02:00
renovate[bot]
b02b7925da Update dependency androidx.compose.foundation:foundation to v1.7.3 2024-10-02 21:27:36 +02:00
hoanghuy309
eb4389f32f Translated using Weblate (Vietnamese)
Currently translated at 96.3% (507 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-10-02 02:41:35 -04:00
Niels van Velzen
c993be8450 Rewrite NowPlayingView in compose 2024-09-30 16:13:31 +02:00
michael
0cfffdbe3d VLC long position 2024-09-29 10:01:44 +02:00
Niels van Velzen
d5bb7327f7 Add flow support for elements 2024-09-28 23:19:13 +02:00
Niels van Velzen
56eb00197c Fix queue not advancing 2024-09-28 18:33:14 +02:00
renovate[bot]
b219f46994 Update dependency ubuntu to v24 2024-09-27 21:39:52 +02:00
renovate[bot]
241139d5cf Update CI dependencies 2024-09-27 21:39:18 +02:00
Niels van Velzen
2c7bd27525 Fix incorrectly navigating on resume 2024-09-27 21:23:44 +02:00
BromTeque
30fcb192da Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nb_NO/
2024-09-26 17:41:35 -04:00
Niels van Velzen
fdde857be6 Change upcomingMinimumServerVersion to 10.9.11 to encourage updating
Profile related fixes in 10.9.10 improve playback, however users may not be aware of that. Use the upcoming minimum server function to notify users about this version. We'll still support 10.9.0>=.
2024-09-26 20:47:23 +02:00
hyperjoco
a607cb4a83 Translated using Weblate (Hungarian)
Currently translated at 99.8% (525 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hu/
2024-09-26 12:41:35 -04:00
renovate[bot]
70654a2720 Update dependency gradle to v8.10.2 2024-09-24 09:01:43 +02:00
utmrxanpq
0c5eda9572 Translated using Weblate (Kannada)
Currently translated at 4.7% (25 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/kn/
2024-09-23 19:41:35 -04:00
utmrxanpq
3e944fa2bc Translated using Weblate (Kannada)
Currently translated at 3.8% (20 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/kn/
2024-09-23 17:28:33 -04:00
Bond_009
90573f610f Fix aspect ratio specials
Don't overwrite the aspect ratio for videos
Change return value of ImageHelper.getImageAspectRatio to not be nullable

Fixes #1192
Possibly a regression from #830
2024-09-23 12:40:25 +02:00
hoanghuy309
64ffa02250 Translated using Weblate (Vietnamese)
Currently translated at 96.0% (505 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-09-22 16:04:43 -04:00
Yogesh
8d5414ce5c Translated using Weblate (Hindi)
Currently translated at 57.2% (301 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-09-22 05:41:36 -04:00
aspectxDev
ecc5d47146 Translated using Weblate (Indonesian)
Currently translated at 75.2% (396 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/id/
2024-09-22 02:41:35 -04:00
renovate[bot]
c5ce43c95b Update koin to v4 2024-09-21 22:37:50 +02:00
renovate[bot]
a3e8482d3e Update github/codeql-action action to v3.26.8 2024-09-21 22:37:42 +02:00
l00d3r
d3834f5e73 Translated using Weblate (Estonian)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2024-09-21 10:41:35 -04:00
Niels van Velzen
579186d661 Implement My media (small) home section 2024-09-21 16:38:41 +02:00
Niels van Velzen
7b61de171d Increase amount of home sections from 7 to 10 2024-09-21 15:54:52 +02:00
renovate[bot]
fe66a61ce0 Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.7.3 2024-09-19 21:59:09 +02:00
renovate[bot]
208e7c4ee1 Update dependency androidx.compose.foundation:foundation to v1.7.2 2024-09-19 08:54:45 +02:00
renovate[bot]
a3965fcce6 Update dependency com.android.tools.build:gradle to v8.6.1 2024-09-19 08:53:04 +02:00
renovate[bot]
249a3f6bbe Update androidx.lifecycle to v2.8.6 2024-09-19 08:50:55 +02:00
renovate[bot]
50eee051c3 Update dependency androidx.compose.ui:ui-tooling to v1.7.2 2024-09-19 08:50:34 +02:00
renovate[bot]
03a0001770 Update dependency androidx.startup:startup-runtime to v1.2.0 2024-09-19 08:50:21 +02:00
Niels van Velzen
933fdbcca4 Fix back press callback in CustomPlaybackOverlayFragment 2024-09-17 14:16:10 +02:00
sand14
9c6c9c4315 Translated using Weblate (Romanian)
Currently translated at 91.0% (479 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ro/
2024-09-14 22:41:34 -04:00
renovate[bot]
949c7e7198 Update CI dependencies 2024-09-14 10:56:01 +02:00
renovate[bot]
2efe6622b9 Update Kotlin to v1.9.0 2024-09-14 10:55:53 +02:00
renovate[bot]
1281785513 Update acra to v5.11.4 2024-09-14 10:55:40 +02:00
Ruben Teixeira
bcc9462514 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pt_PT/
2024-09-12 17:41:34 -04:00
nextlooper42
6d3b27ebac Translated using Weblate (Slovak)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sk/
2024-09-11 07:41:34 -04:00
queeup
f4df2fd1d7 Translated using Weblate (Turkish)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2024-09-10 17:41:34 -04:00
renovate[bot]
0dae1535b2 Update dependency androidx.compose.ui:ui-tooling to v1.7.1 2024-09-10 22:08:25 +02:00
renovate[bot]
a6a34ffff0 Update dependency androidx.compose.foundation:foundation to v1.7.1 2024-09-10 22:04:43 +02:00
renovate[bot]
14d67e446d Update dependency gradle to v8.10.1 2024-09-10 15:01:02 +02:00
Pascal Weidenhammer
51cedee9b3 Upgrade ConnectHelpAlertFragment to Jetpack Compose (#3596)
* Add AndroidX TV Material implementation

* Upgrade ConnectHelpAlertFragment to Jetpack Compose

* Add Jellyfin blue Material Theme

* Add Material Theme and remove back button from ConnectHelpAlert

There should be no onscreen back buttons, because the tv remote has a dedicated back button: https://developer.android.com/design/ui/tv/guides/foundations/navigation-on-tv#dont-display-a-back-button

* Add "Got it" button back to ConnectHelp

* Remove duplicate tv-material library inclusion

* Revert "Add Jellyfin blue Material Theme"

This reverts commit 1c16039208.

* Remove custom theme in ConnectHelp

* Hardcode colors in ConnectHelpAlert

* Refactor ConnectHelpAlertFragment

---------

Co-authored-by: Niels van Velzen <git@ndat.nl>
2024-09-10 12:59:51 +00:00
renovate[bot]
715a15a5ba Update actions/setup-java action to v4.3.0 2024-09-10 14:59:42 +02:00
renovate[bot]
9ecea3088f Update dependency io.gitlab.arturbosch.detekt to v1.23.7 2024-09-10 14:59:31 +02:00
Niels van Velzen
a87ea6c060 Avoid baking subtitles when transcoding 2024-09-10 14:48:23 +02:00
MichaelRUSF
706b64573a Add resolution codec check (#3953)
* Add 4k resolution codec check

* 4k profile check

* Apply review changes

* Remove hard-coded resolutions
2024-09-08 11:33:16 +02:00
renovate[bot]
cd8e619ddc Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.7.2 2024-09-08 10:52:02 +02:00
renovate[bot]
8d6d3b3a35 Update dependency org.jellyfin.sdk:jellyfin-core to v1.5.5 2024-09-08 10:51:51 +02:00
bene toffix
25354395ed Translated using Weblate (Catalan)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2024-09-07 12:41:34 -04:00
Hoomaane79
3a6b619aa4 Translated using Weblate (Persian)
Currently translated at 100.0% (4 of 4 strings)

Translation: Jellyfin Android/Jellyfin Android TV Fastlane
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv-fastlane/fa/
2024-09-05 19:41:34 -04:00
Andreas Hantschel
309d2dc532 Translated using Weblate (German)
Currently translated at 99.8% (525 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2024-09-05 15:41:34 -04:00
renovate[bot]
1d0e2b0f66 Update dependency androidx.compose.ui:ui-tooling to v1.7.0 2024-09-05 16:19:02 +02:00
renovate[bot]
0557df1faa Update dependency androidx.compose.foundation:foundation to v1.7.0 2024-09-05 16:13:01 +02:00
renovate[bot]
7684efbf0b Update dependency com.android.tools:desugar_jdk_libs to v2.1.2 2024-09-05 09:06:45 +02:00
renovate[bot]
a4e14dbf45 Update dependency androidx.activity:activity to v1.9.2 2024-09-05 09:04:23 +02:00
renovate[bot]
32c3b80008 Update androidx.fragment to v1.8.3 2024-09-05 09:04:03 +02:00
renovate[bot]
05249719b4 Update androidx.lifecycle to v2.8.5 2024-09-05 09:03:48 +02:00
Fabian T
987bda9918 Translated using Weblate (German)
Currently translated at 99.4% (523 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2024-09-03 19:41:33 -04:00
Niels van Velzen
13f6a70fa5 Fix current fragment not removed on back press 2024-09-03 21:37:08 +02:00
Niels van Velzen
e460c6e403 Use custom logic for fragment back stack 2024-09-03 16:38:23 +02:00
MichaelRUSF
86d6195a06 Update DeviceUtils with Xiaomi TV Stick (#3951)
* Add Mi Stick to DeviceUtils

* Fix comment
2024-09-03 13:54:20 +02:00
renovate[bot]
c1df5a69aa Update CI dependencies 2024-09-02 13:22:19 +02:00
renovate[bot]
ea4289b1ef Update dependency com.android.tools.build:gradle to v8.6.0 2024-09-02 13:21:48 +02:00
Cielo Gaona
7357694c8e Translated using Weblate (Spanish (Mexico))
Currently translated at 99.6% (524 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/es_MX/
2024-09-01 02:41:34 -04:00
Rattapoom Suaydee
1d79a8bafe Translated using Weblate (Thai)
Currently translated at 40.3% (212 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/th/
2024-08-31 14:41:33 -04:00
Simon Hung
dd450c607d Translated using Weblate (Chinese (Traditional))
Currently translated at 99.0% (521 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hant/
2024-08-30 10:41:33 -04:00
millallo
d64c35c6f9 Translated using Weblate (Italian)
Currently translated at 99.8% (525 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2024-08-29 08:41:33 -04:00
無情天
f521abf7bd Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-08-28 20:41:33 -04:00
renovate[bot]
144e501bd2 Update dependency com.android.tools:desugar_jdk_libs to v2.1.1 2024-08-28 22:10:19 +02:00
stanol
80f2de16b1 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2024-08-28 09:41:33 -04:00
Kityn
13f95d5f60 Translated using Weblate (Polish)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-08-28 03:41:33 -04:00
Bas
990c8d4ad8 Translated using Weblate (Dutch)
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-08-27 10:41:33 -04:00
Andi Chandler
b7753deb2f Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (526 of 526 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2024-08-27 10:41:33 -04:00
Niels van Velzen
0c88593d30 Tidy up 2024-08-27 13:50:53 +02:00
rickysixx
a304403fc0 Enable ExoPlayer debugging logs if debug mode is active 2024-08-27 13:50:53 +02:00
rickysixx
1235eb1ff5 Add developer preference to prefer extension renderers to core ones 2024-08-27 13:50:53 +02:00
renovate[bot]
2b1143a362 Update gradle/actions action to v4.0.1 2024-08-27 13:33:40 +02:00
renovate[bot]
be43311978 Update androidx.media3 to v1.4.1 2024-08-27 13:33:25 +02:00
renovate[bot]
3916c2a117 Update dependency org.jellyfin.sdk:jellyfin-core to v1.5.4 2024-08-27 13:29:25 +02:00
renovate[bot]
7c9dd0001e Update dependency com.android.tools:desugar_jdk_libs to v2.1.0 2024-08-26 18:50:47 +02:00
Niels van Velzen
b116db0d49 Fix capitalization in video profiles causing invalid transcodes 2024-08-25 22:28:02 +02:00
renovate[bot]
b362ac42ff Update aboutlibraries to v11.2.3 2024-08-25 18:48:38 +02:00
renovate[bot]
de2a27052e Update github/codeql-action action to v3.26.5 2024-08-25 18:48:15 +02:00
MichaelRUSF
fe05b82b95 Fix for devices with no HEVC Main 10 support 2024-08-25 18:47:35 +02:00
MichaelRUSF
50ef4a7718 AVC level check profiles 2024-08-25 11:55:24 +02:00
MichaelRUSF
49bcd6fe2c AVC media codec levels 2024-08-25 11:55:24 +02:00
Eric Leblanc
c03bec878b more granular seek setting 2024-08-24 17:58:29 +02:00
renovate[bot]
8cca27238f Update github/codeql-action action to v3.26.4 2024-08-22 17:35:10 +02:00
renovate[bot]
09027c2bc5 Update Kotlin to v2.0.20 2024-08-22 17:34:53 +02:00
無情天
7297086045 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-08-21 16:25:07 -04:00
renovate[bot]
f2a47d1c9a Update dependency androidx.tv:tv-material to v1.0.0 2024-08-21 20:48:38 +02:00
Niels van Velzen
1f789ac00f Improve behavior when no playable items found 2024-08-20 16:44:06 +02:00
Niels van Velzen
1199fa5253 Disable direct play when encountering playback error twice 2024-08-20 16:43:47 +02:00
renovate[bot]
a9ff992926 Update github/codeql-action action to v3.26.3 2024-08-20 13:04:24 +02:00
Niels van Velzen
a4ec607543 Fix toggling favorites in ItemListFragment 2024-08-18 17:18:32 +02:00
renovate[bot]
299751156d Update dependency com.android.tools.build:gradle to v8.5.2 2024-08-18 10:19:41 +02:00
renovate[bot]
f8eb6468d4 Update CI dependencies 2024-08-18 10:19:32 +02:00
itoudium
77cc5902bb Translated using Weblate (Japanese)
Currently translated at 70.8% (371 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ja/
2024-08-17 02:41:32 -04:00
bene toffix
a143dcbec9 Translated using Weblate (Catalan)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ca/
2024-08-16 18:41:32 -04:00
Andi Chandler
c1c144f813 Translated using Weblate (English (United Kingdom))
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/en_GB/
2024-08-16 14:41:32 -04:00
Niels van Velzen
ae2d74b263 Fix channels interpreted as Live TV channels 2024-08-16 20:29:01 +02:00
renovate[bot]
c025b62f85 Update dependency gradle to v8.10 2024-08-16 08:44:59 +02:00
Mjöllnir
5f181b9ded Translated using Weblate (French)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-08-15 21:41:32 -04:00
Niels van Velzen
ff52e2a9a7 Use device profile builder in jellyfinPlugin 2024-08-13 17:38:24 +02:00
Niels van Velzen
e65492c254 Enable constant bitrate seeking 2024-08-13 16:33:26 +02:00
elokoidu
9ac58e22fb Translated using Weblate (Estonian)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/et/
2024-08-13 09:41:32 -04:00
millallo
cc080fe93c Translated using Weblate (Italian)
Currently translated at 99.8% (523 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/it/
2024-08-12 17:41:32 -04:00
VOLO Digital Agency
2e3e8f258c Translated using Weblate (Swedish)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/sv/
2024-08-12 03:41:32 -04:00
Niels van Velzen
9577e11e41 Fix crash when item doesn't have a default audio/subtitle stream 2024-08-12 08:30:40 +02:00
Niels van Velzen
6111cbec5a Re-use supportsHevc in one additional place 2024-08-10 22:06:33 +02:00
Joseph Price
c7a4c89b74 Really don't request HEVC if unsupported 2024-08-10 22:06:33 +02:00
stanol
35300e605b Translated using Weblate (Ukrainian)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/uk/
2024-08-10 08:41:32 -04:00
Niels van Velzen
b0cd0c5b37 Fix InfoRow not using requested media source 2024-08-10 08:24:06 +02:00
Niels van Velzen
aa5fb63b71 Reset display mode when exiting video player 2024-08-09 22:12:19 +02:00
Niels van Velzen
d661583a86 Improve InfoRow colors/font readability 2024-08-09 22:12:13 +02:00
Niels van Velzen
fe31c19f15 Fix intros showing next up screen 2024-08-09 20:37:40 +02:00
Niels van Velzen
fcd9751d82 Fix crash when starting next episode 2024-08-09 19:57:53 +02:00
Niels van Velzen
f8c5345871 Graduate reactive homepage to stable 2024-08-08 22:28:59 +02:00
Sina Faghihi
213fa1fcf8 Translated using Weblate (Persian)
Currently translated at 70.0% (367 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fa/
2024-08-08 10:41:31 -04:00
無情天
157352cf3a Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/zh_Hans/
2024-08-08 06:41:31 -04:00
renovate[bot]
b5c5478c76 Update gradle/actions action to v4 2024-08-07 22:16:27 +02:00
renovate[bot]
0385f63fbe Update dependency androidx.tv:tv-material to v1.0.0-rc02 2024-08-07 22:09:41 +02:00
renovate[bot]
6cc1031b8a Update dependency androidx.work:work-runtime to v2.9.1 2024-08-07 22:09:33 +02:00
Vladimir Apraksin
3269a5283d Translated using Weblate (Russian)
Currently translated at 95.6% (501 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/ru/
2024-08-07 14:32:34 -04:00
renovate[bot]
587f0fb35a Update dependency org.jellyfin.sdk:jellyfin-core to v1.5.3 2024-08-07 12:55:12 +02:00
moi15moi
1f7c6cc4d3 Translated using Weblate (French)
Currently translated at 99.8% (523 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/fr/
2024-08-06 18:41:31 -04:00
queeup
e307b3baa0 Translated using Weblate (Turkish)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2024-08-06 13:41:31 -04:00
Justin
a8cb3a595c Translated using Weblate (German)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/de/
2024-08-06 13:41:31 -04:00
Niels van Velzen
044ce67110 Fix SelectQualityAction crashing when opening menu 2024-08-06 15:14:39 +02:00
Niels van Velzen
f6c536880d Use "direct play" as default audio behavior 2024-08-06 15:14:31 +02:00
renovate[bot]
409b34238a Update Kotlin to v2.0.10 2024-08-06 14:51:05 +02:00
Kityn
6ca4b4679c Translated using Weblate (Polish)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/pl/
2024-08-06 03:41:31 -04:00
hoanghuy309
5bb74f689a Translated using Weblate (Vietnamese)
Currently translated at 96.1% (504 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/vi/
2024-08-05 23:41:31 -04:00
queeup
daa4188887 Translated using Weblate (Turkish)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/tr/
2024-08-05 20:41:31 -04:00
Marc Vollmer
3b852a031e Fix NullPointerException in LeanbackOverlayFragment.onPause 2024-08-05 21:37:42 +02:00
Bas
7aa4d2e5fa Translated using Weblate (Dutch)
Currently translated at 100.0% (524 of 524 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/nl/
2024-08-05 14:41:31 -04:00
Niels van Velzen
8c3be44664 Fix RewriteMediaManager emitting onQueueStatusChanged with a queue when there is no audio items available 2024-08-05 20:12:40 +02:00
Niels van Velzen
7bc99d2e66 Fix NullPointerException in CustomPlaybackOverlayFragment.onResume 2024-08-05 19:08:41 +02:00
Niels van Velzen
9ecf952351 Remove context requirement from ExoPlayerProfile 2024-08-05 19:00:41 +02:00
Weblate
2e78a483aa Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/
2024-08-05 12:33:51 -04:00
Niels van Velzen
e8a81799e2 Add new subtitle customization preferences 2024-08-05 18:33:47 +02:00
Niels van Velzen
be06693978 Remove custom subtitle renderer 2024-08-05 18:33:47 +02:00
Niels van Velzen
0f38bd1691 Rewrite queuing 2024-08-05 18:33:30 +02:00
majmongoose
a8c9f054ab Add Google Chromecast HD limitation (#3820)
* Add identification for Google Chromecast HD

Possibly an upstream bug is preventing this from working, as the chromecast is being idenitified correctly in debugging.

* Update DeviceUtils.kt

Added a note for the reason of the change.

* Removed unintentional imports

* Update app/src/main/java/org/jellyfin/androidtv/util/DeviceUtils.kt

Make changes suggested by maintainer.

Co-authored-by: Niels van Velzen <nielsvanvelzen@users.noreply.github.com>

* Update DeviceUtils.kt

Removed unneeded isChromecastHD

---------

Co-authored-by: Niels van Velzen <nielsvanvelzen@users.noreply.github.com>
2024-08-05 15:43:30 +00:00
renovate[bot]
4f3c6b331d Update actions/setup-java action to v4.2.2 2024-08-05 17:42:28 +02:00
Niels van Velzen
61b4178dec Fix AudioNowPlayingFragment showing wrong item in extremely rare cases 2024-08-04 22:03:00 +02:00
Niels van Velzen
9aa1759ae7 Fix race condition in PictureViewerViewModel
Using the showNext/showPrevious functions while the album is still loading can cause an IndexOutOfBoundsException. Check if the album is empty (default value) first before trying to read from it to avoid these crashes.
2024-08-04 22:02:53 +02:00
Niels van Velzen
2e55987939 Strip HTML from descriptions in leanback integration 2024-08-04 22:02:42 +02:00
dharmik2319
d3f3b38c31 Translated using Weblate (Hindi)
Currently translated at 27.1% (141 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 08:15:01 -04:00
dharmik2319
f8cf1f48a3 Translated using Weblate (Hindi)
Currently translated at 26.9% (140 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 08:14:28 -04:00
dharmik2319
691a8f8ac5 Translated using Weblate (Hindi)
Currently translated at 26.5% (138 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 08:13:55 -04:00
dharmik2319
af6df123d2 Translated using Weblate (Hindi)
Currently translated at 26.3% (137 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 08:12:48 -04:00
dharmik2319
dad6570d28 Translated using Weblate (Hindi)
Currently translated at 18.4% (96 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:18:33 -04:00
dharmik2319
8abfc9ebd2 Translated using Weblate (Hindi)
Currently translated at 18.3% (95 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:17:59 -04:00
dharmik2319
8aabf8dc9a Translated using Weblate (Hindi)
Currently translated at 18.1% (94 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:16:20 -04:00
dharmik2319
31abdc6060 Translated using Weblate (Hindi)
Currently translated at 17.9% (93 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:15:47 -04:00
dharmik2319
954491718e Translated using Weblate (Hindi)
Currently translated at 17.7% (92 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:15:14 -04:00
dharmik2319
bb550630dd Translated using Weblate (Hindi)
Currently translated at 17.5% (91 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:14:41 -04:00
dharmik2319
1007e22d97 Translated using Weblate (Hindi)
Currently translated at 17.3% (90 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:14:08 -04:00
dharmik2319
ec6161bc97 Translated using Weblate (Hindi)
Currently translated at 17.1% (89 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:13:35 -04:00
dharmik2319
f1204ccbb6 Translated using Weblate (Hindi)
Currently translated at 16.7% (87 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:13:02 -04:00
dharmik2319
77b27e490e Translated using Weblate (Hindi)
Currently translated at 16.5% (86 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:11:56 -04:00
dharmik2319
6d1fac382b Translated using Weblate (Hindi)
Currently translated at 16.3% (85 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:11:23 -04:00
dharmik2319
c24a7dcc3a Translated using Weblate (Hindi)
Currently translated at 15.9% (83 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:09:43 -04:00
dharmik2319
461a6939cd Translated using Weblate (Hindi)
Currently translated at 15.7% (82 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:09:10 -04:00
dharmik2319
ce13ff4c11 Translated using Weblate (Hindi)
Currently translated at 15.6% (81 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:08:04 -04:00
dharmik2319
70fe0ecd2c Translated using Weblate (Hindi)
Currently translated at 15.4% (80 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 07:05:52 -04:00
dharmik2319
0630bbd9ec Translated using Weblate (Hindi)
Currently translated at 15.2% (79 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 06:59:47 -04:00
dharmik2319
40b941ce4b Translated using Weblate (Hindi)
Currently translated at 14.8% (77 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 06:59:14 -04:00
dharmik2319
ab2298feff Translated using Weblate (Hindi)
Currently translated at 14.6% (76 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 06:58:08 -04:00
dharmik2319
ed481e6492 Translated using Weblate (Hindi)
Currently translated at 14.4% (75 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 06:35:49 -04:00
dharmik2319
3f96cab559 Translated using Weblate (Hindi)
Currently translated at 14.2% (74 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 06:35:16 -04:00
dharmik2319
47ffc9f8ee Translated using Weblate (Hindi)
Currently translated at 14.0% (73 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 06:33:37 -04:00
dharmik2319
8b14af8770 Translated using Weblate (Hindi)
Currently translated at 13.8% (72 of 519 strings)

Translation: Jellyfin Android/Jellyfin Android TV
Translate-URL: https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv/hi/
2024-08-04 06:33:04 -04:00
Niels van Velzen
4e8fd15508 Support float preferences 2024-08-04 10:47:30 +02:00
Filip Czaplicki
8230479059 Fix typos 2024-08-03 10:54:38 +02:00
renovate[bot]
96e39c34f3 chore(deps): update ci dependencies 2024-08-03 10:41:15 +02:00
697 changed files with 29256 additions and 15753 deletions

2
.gitattributes vendored
View File

@@ -5,3 +5,5 @@
CONTRIBUTORS.md merge=union
app/src/main/res/values*/strings.xml merge=union
design/src/main/kotlin/token/* linguist-generated

View File

@@ -4,6 +4,24 @@ labels:
- bug
- playback
body:
- type: checkboxes
id: before-posting
attributes:
label: "This issue respects the following points:"
description: All conditions are **required**.
options:
- label: I have discussed this issue in the [Jellyfin forum](https://forum.jellyfin.org/) and/or [troubleshooting chat](https://jellyfin.org/contact) before opening this issue.
required: true
- label: This issue is **not** already reported on [GitHub](https://github.com/jellyfin/jellyfin-androidtv/issues?q=is%3Aopen+is%3Aissue) _(I've searched it)_.
required: true
- label: I agree to follow Jellyfin's [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct).
required: true
- label: This report addresses only a single issue; If you encounter multiple issues, kindly create separate reports for each one.
required: true
- type: markdown
attributes:
value: |
## Bug information
- type: textarea
id: description
attributes:
@@ -20,10 +38,38 @@ body:
Instead, I expect …
validations:
required: true
- type: textarea
id: mediainfo
attributes:
label: Media info of the file
description: |
Please share the media information for the file causing issues. You can use a variety of tools to retrieve this information.
- Use ffprobe (`ffprobe ./file.mp4`)
- Copy the media info from the web interface
placeholder: Paste media info…
render: shell
- type: textarea
id: mediacapabilitiesreport
attributes:
label: Media capabilities report
description: |
Please share the media capability report generated from within the app. To do some follow these steps:
1. Open the Jellyfin for Android TV app
2. Connect to a server **that you have admin access to**
3. Go to Preferences -> Playback -> Advanced playback preferences
4. On the bottom, press the "Report playback capabilities to server" button
5. Go to the logs in your Jellyfin dashboard (in your browser)
6. Open the newest log file, it should be named similar to `upload_Jellyfin Android TV[...].log`
7. Press the "Download" button and paste the file contents
placeholder: Paste capability report contents…
- type: markdown
attributes:
value: |
## Logs
- type: textarea
id: logs
attributes:
label: Logs
label: Client logs
description: |
Please paste your crash logs here if applicable. You can find these in your servers dashboard under "logs".
The file name should start with "upload_org.jellyfin.androidtv".
@@ -37,31 +83,34 @@ body:
Please paste your FFmpeg logs here. You can find these in your servers dashboard under "logs".
placeholder: Paste logs…
render: shell
- type: textarea
id: mediainfo
- type: markdown
attributes:
label: Media info of the file
description: |
Please share the media information for the file causing issues. You can use a variety of tools to retrieve this information.
- Use ffprobe (`ffprobe ./file.mp4`)
- Use the Media Info tool (set to text format, download here: https://mediaarea.net/en/MediaInfo)
- Copy the media info from the web interface
placeholder: Paste media info…
render: shell
value: |
## Environment
- type: input
id: app-version
attributes:
label: Application version
description: The version of the installed Jellyfin Android TV app.
placeholder: 0.14.0
placeholder: 0.18.2
validations:
required: true
- type: dropdown
id: installation-source
attributes:
label: Where did you install the app from?
description: Choose the appropriate app store or installation method.
options:
- Google Play Store
- Amazon Appstore
- F-Droid
- Sideloaded APK
- type: input
id: device-info
attributes:
label: Device information
description: Manufacturer and model
placeholder: Nvidia Shield Pro (2017), Amazon Fire TV Stick v1 (2014)
placeholder: Nvidia Shield TV Pro (2019), Fire TV Stick HD (2020)
validations:
required: true
- type: input
@@ -69,7 +118,7 @@ body:
attributes:
label: Android version
description: Version of the OS and other information (e.g. custom ROM / OEM skin)
placeholder: Android 9, Fire OS 7
placeholder: Android 13, Fire OS 7
validations:
required: true
- type: input
@@ -77,6 +126,18 @@ body:
attributes:
label: Jellyfin server version
description: If on unstable, please specify the commit hash.
placeholder: 10.8.1
placeholder: 10.10.2
validations:
required: true
- type: markdown
attributes:
value: |
## Additional
- type: input
id: other-sources
attributes:
label: Other sources
description: Please link the related forum topics or chat messages that prompted you open this issue.
placeholder: https://forum.jellyfin.org/…
validations:
required: false

View File

@@ -3,6 +3,24 @@ description: Create a bug report
labels:
- bug
body:
- type: checkboxes
id: before-posting
attributes:
label: "This issue respects the following points:"
description: All conditions are **required**.
options:
- label: I have discussed this issue in the [Jellyfin forum](https://forum.jellyfin.org/) and/or [troubleshooting chat](https://jellyfin.org/contact) before opening this issue.
required: true
- label: This issue is **not** already reported on [GitHub](https://github.com/jellyfin/jellyfin-androidtv/issues?q=is%3Aopen+is%3Aissue) _(I've searched it)_.
required: true
- label: I agree to follow Jellyfin's [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct).
required: true
- label: This report addresses only a single issue; If you encounter multiple issues, kindly create separate reports for each one.
required: true
- type: markdown
attributes:
value: |
## Bug information
- type: textarea
id: description
attributes:
@@ -28,12 +46,16 @@ body:
The file name should start with "upload_org.jellyfin.androidtv".
Make sure that they don't contain any sensitive information like server URL, auth tokens or passwords.
placeholder: Paste logs…
- type: markdown
attributes:
value: |
## Environment
- type: input
id: app-version
attributes:
label: Application version
description: The version of the installed Jellyfin Android TV app.
placeholder: 0.14.0
placeholder: 0.18.2
validations:
required: true
- type: dropdown
@@ -42,15 +64,16 @@ body:
label: Where did you install the app from?
description: Choose the appropriate app store or installation method.
options:
- Google Play
- Google Play Store
- Amazon Appstore
- F-Droid
- Sideloaded APK
- type: input
id: device-info
attributes:
label: Device information
description: Manufacturer and model
placeholder: Nvidia Shield Pro (2017), Amazon Fire TV Stick v1 (2014)
placeholder: Nvidia Shield TV Pro (2019), Fire TV Stick HD (2020)
validations:
required: true
- type: input
@@ -58,7 +81,7 @@ body:
attributes:
label: Android version
description: Version of the OS and other information (e.g. custom ROM / OEM skin)
placeholder: Android 9, Fire OS 7
placeholder: Android 13, Fire OS 7
validations:
required: true
- type: input
@@ -66,6 +89,18 @@ body:
attributes:
label: Jellyfin server version
description: If on unstable, please specify the commit hash.
placeholder: 10.8.1
placeholder: 10.10.2
validations:
required: true
- type: markdown
attributes:
value: |
## Additional
- type: input
id: other-sources
attributes:
label: Other sources
description: Please link the related forum topics or chat messages that prompted you open this issue.
placeholder: https://forum.jellyfin.org/…
validations:
required: false

View File

@@ -3,12 +3,54 @@ description: Request a new feature
labels:
- enhancement
body:
- type: textarea
id: description
- type: checkboxes
id: before-posting
attributes:
label: Describe the feature you'd like
description: |
A clear and concise description of what you want to request.
You can also attach screenshots or screen recordings to help explain your request.
label: "This request respects the following points:"
description: All conditions are **required**.
options:
- label: This request is **not** already on [GitHub](https://github.com/jellyfin/jellyfin-androidtv/labels/enhancement) _(I've searched it)_.
required: true
- label: I agree to follow Jellyfin's [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct).
required: true
- type: textarea
attributes:
label: Problem description
description: Describe the issue you are experiencing or the gap you are trying to address.
placeholder: |
The Android TV app does not support displaying lyrics, while the Jellyfin web interface does.
This creates an inconsistent user experience across platforms.
validations:
required: true
- type: textarea
attributes:
label: Proposed solution
description: Provide a detailed description of what you would like to see implemented or changed.
placeholder: |
The app could display lyrics in the screensaver. Additionally, a lyrics section could be integrated into the page that opens when music is played.
validations:
required: true
- type: textarea
attributes:
label: Alternatives considered
description: Outline any other approaches you have thought about or explored to solve the problem.
placeholder: |
An alternative approach could involve adding a dedicated "Lyrics" button in the app, similar to the Jellyfin web interface.
Users could press this button to open a full-screen lyrics view.
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Include any relevant details, resources, or screenshots that might help in understanding or implementing the request.
placeholder: Add any additional context here.
validations:
required: false
- type: input
id: other-sources
attributes:
label: Other sources
description: If this topic has been discussed outside of GitHub, please link it.
placeholder: https://forum.jellyfin.org/…
validations:
required: false

View File

@@ -1,11 +1,15 @@
<!--
Ensure your title is short, descriptive, and in the imperative mood (Fix X, Change Y, instead of Fixed X, Changed Y).
For a good inspiration of what to write in commit messages and PRs please review https://chris.beams.io/posts/git-commit/ and our https://docs.jellyfin.org/general/contributing/issues.html page.
For a good inspiration of what to write in commit messages and PRs please review https://chris.beams.io/posts/git-commit/ and our https://jellyfin.org/docs/general/contributing/issues/ page.
-->
**Changes**
<!-- Describe your changes here in 1-5 sentences. -->
**Code assistance**
<!-- If code assistance was used, describe how it contributed
e.g., code generated by LLM, explanation of code base, debugging guidance. -->
**Issues**
<!-- Tag any issues that this PR solves here.
ex. Fixes # -->

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- master
- release-*
pull_request:
permissions:
@@ -12,23 +13,23 @@ permissions:
jobs:
build:
name: Build
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
java-version: 17
java-version-file: .tools-versions
- name: Setup Gradle
uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Assemble debug APKs
run: ./gradlew assembleDebug
- name: Create publish bundle
run: mkdir -p build/gh-app-publish/; find app/build/ -iname "*.apk" -exec mv "{}" build/gh-app-publish/ \;
- name: Upload artifacts
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: build-artifacts
retention-days: 14

View File

@@ -14,21 +14,21 @@ permissions:
jobs:
lint:
name: Lint
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
java-version: 17
java-version-file: .tools-versions
- name: Setup Gradle
uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Run detekt and lint tasks
run: ./gradlew detekt lint
- name: Upload SARIF files
uses: github/codeql-action/upload-sarif@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14
uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
if: ${{ always() }}
with:
sarif_file: .

View File

@@ -8,18 +8,18 @@ on:
jobs:
publish:
name: Publish
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: ${{ contains(github.repository_owner, 'jellyfin') }}
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
java-version: 17
java-version-file: .tools-versions
- name: Setup Gradle
uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Set JELLYFIN_VERSION
run: echo "JELLYFIN_VERSION=$(echo ${GITHUB_REF#refs/tags/v} | tr / -)" >> $GITHUB_ENV
- name: Assemble release files
@@ -70,7 +70,7 @@ jobs:
remote_user: ${{ secrets.REPO_USER }}
remote_key: ${{ secrets.REPO_KEY }}
- name: Update repo.jellyfin.org symlinks
uses: appleboy/ssh-action@029f5b4aeeeb58fdfe1410a5d17f967dacf36262 # v1.0.3
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
with:
host: ${{ secrets.REPO_HOST }}
username: ${{ secrets.REPO_USER }}

View File

@@ -13,16 +13,16 @@ permissions:
jobs:
test:
name: Test
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: temurin
java-version: 17
java-version-file: .tools-versions
- name: Setup Gradle
uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Run test task
run: ./gradlew test

View File

@@ -14,9 +14,9 @@ permissions:
jobs:
validate:
name: Validate
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0

View File

@@ -9,10 +9,10 @@ on:
jobs:
triage:
name: Triage
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: ${{ contains(github.repository_owner, 'jellyfin') }}
steps:
- uses: eps1lon/actions-label-merge-conflict@1b1b1fcde06a9b3d089f3464c96417961dde1168 # v3.0.2
- uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
with:
dirtyLabel: merge conflict
repoToken: ${{ secrets.JF_BOT_TOKEN }}

View File

@@ -12,10 +12,10 @@ permissions:
jobs:
triage:
name: Triage
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: ${{ contains(github.repository_owner, 'jellyfin') }}
steps:
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
with:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
days-before-stale: 120

1
.tools-versions Normal file
View File

@@ -0,0 +1 @@
java 21

View File

@@ -13,6 +13,9 @@
- [sparky3387](https://github.com/sparky3387)
- [mohd-akram](https://github.com/mohd-akram)
- [3l0w](https://github.com/3l0w)
- [MajMongoose](https://github.com/majmongoose)
- [Olaren15](https://github.com/Olaren15)
- [dtrexler](https://github.com/dtrexler)
# Emby Contributors

View File

@@ -25,9 +25,6 @@
<a href="https://matrix.to/#/+jellyfin:matrix.org">
<img alt="Chat on Matrix" src="https://img.shields.io/matrix/jellyfin:matrix.org.svg?logo=matrix"/>
</a>
<a href="https://www.reddit.com/r/jellyfin">
<img alt="Join our Subreddit" src="https://img.shields.io/badge/reddit-r%2Fjellyfin-%23FF5700.svg"/>
</a>
<br/>
<a href="https://play.google.com/store/apps/details?id=org.jellyfin.androidtv">
<img width="153" alt="Jellyfin on Google Play" src="https://jellyfin.org/images/store-icons/google-play.png"/>
@@ -42,48 +39,39 @@
<a href="https://repo.jellyfin.org/releases/client/androidtv/">Download archive</a>
</p>
Jellyfin Android TV is a Jellyfin client for Android TV, Nvidia Shield, and Amazon Fire TV devices.
We welcome all contributions and pull requests! If you have a larger feature in mind please open an
issue so we can discuss the implementation before you start.
Jellyfin Android TV is a Jellyfin client for Android TV, Nvidia Shield, and Amazon Fire TV devices. We welcome all contributions and pull
requests! If you have a larger feature in mind please open an issue so we can discuss the implementation before you start.
## Building
The app uses Gradle and requires the Android SDK. We recommend using Android Studio, which includes all required dependencies, for
development and building. For manual building without Android Studio make sure a compatible JDK and Android SDK are installed and in your
PATH, then use the Gradle wrapper (`./gradlew`) to build the project with the `assembleDebug` Gradle task to generate an apk file:
```shell
./gradlew assembleDebug
```
The task will create an APK file in the `/app/build/outputs/apk/debug` directory. This APK file uses a different app-id from our stable
builds and can be manually installed to your device.
## Branching
The `master` branch is the primary development branch and the target for all pull requests. It is **unstable** and may contain breaking
changes or unresolved bugs. For production deployments and forks, always use the latest `release-x.y.z` branch. Do not base production work
or long-lived forks on `master`.
Release branches are created at the start of a beta cycle and are kept up to date with each published release. Maintainers will cherry-pick
selected changes into release branches as needed for backports. These branches are reused for subsequent patch releases.
## Translating
Translations can be improved very easily from our
[Weblate](https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv) instance.
Look through the following graphic to see if your native language could use some work!
Translations can be improved very easily from our [Weblate](https://translate.jellyfin.org/projects/jellyfin-android/jellyfin-androidtv)
instance. Look through the following graphic to see if your native language could use some work! We cannot accept changes to translation
files via pull requests.
<p align="center">
<a href="https://translate.jellyfin.org/engage/jellyfin-android/">
<img alt="Detailed Translation Status" src="https://translate.jellyfin.org/widgets/jellyfin-android/-/jellyfin-androidtv/multi-auto.svg"/>
</a>
## Build Process
### Dependencies
- Android Studio
### Build
1. Clone or download this repository
```sh
git clone https://github.com/jellyfin/jellyfin-androidtv.git
cd jellyfin-androidtv
```
2. Open the project in Android Studio and run it from there or build an APK directly through Gradle:
```sh
./gradlew assembleDebug
```
Add the Android SDK to your PATH environment variable or create the ANDROID_SDK_ROOT variable for
this to work.
### Deploy to device/emulator
```sh
./gradlew installDebug
```
*You can also replace the "Debug" with "Release" to get an optimized release binary.*
</p>

View File

@@ -13,12 +13,13 @@
<issue id="MangledCRLF" severity="warning" />
<issue id="NegativeMargin" severity="warning" />
<issue id="NoHardKeywords" severity="warning" />
<issue id="NotificationPermission">
<ignore regexp="com.bumptech.glide.request.target.NotificationTarget" />
</issue>
<issue id="Registered" severity="warning" />
<issue id="RequiredSize" severity="error" />
<issue id="Typos" severity="ignore" />
<issue id="UnknownNullness" severity="informational" />
<issue id="UnusedIds" severity="ignore" />
<issue id="UnusedAttribute">
<ignore regexp="usesCleartextTraffic" />
<ignore regexp="networkSecurityConfig" />
</issue>
</lint>

View File

@@ -1,9 +1,8 @@
plugins {
id("com.android.application")
kotlin("android")
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.aboutlibraries)
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
}
android {
@@ -18,13 +17,13 @@ android {
applicationId = namespace
versionName = project.getVersionName()
versionCode = getVersionCode(versionName!!)
setProperty("archivesBaseName", "jellyfin-androidtv-v$versionName")
}
buildFeatures {
buildConfig = true
viewBinding = true
compose = true
resValues = true
}
compileOptions {
@@ -32,8 +31,8 @@ android {
}
buildTypes {
val release by getting {
isMinifyEnabled = false
release {
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
// Set package names used in various XML files
resValue("string", "app_id", namespace!!)
@@ -46,7 +45,7 @@ android {
buildConfigField("boolean", "DEVELOPMENT", "false")
}
val debug by getting {
debug {
// Use different application id to run release and debug at the same time
applicationIdSuffix = ".debug"
@@ -74,12 +73,9 @@ android {
}
}
aboutLibraries {
// Remove the "generated" timestamp to allow for reproducible builds
excludeFields = arrayOf("generated")
}
base.archivesName.set("jellyfin-androidtv-v${project.getVersionName()}")
val versionTxt by tasks.registering {
tasks.register("versionTxt") {
val path = layout.buildDirectory.asFile.get().resolve("version.txt")
doLast {
@@ -91,12 +87,12 @@ val versionTxt by tasks.registering {
dependencies {
// Jellyfin
implementation(projects.design)
implementation(projects.playback.core)
implementation(projects.playback.jellyfin)
implementation(projects.playback.media3.exoplayer)
implementation(projects.playback.media3.session)
implementation(projects.preference)
implementation(libs.jellyfin.apiclient)
implementation(libs.jellyfin.sdk) {
// Change version if desired
val sdkVersion = findProperty("sdk.version")?.toString()
@@ -114,10 +110,12 @@ dependencies {
// Android(x)
implementation(libs.androidx.core)
implementation(libs.androidx.activity)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.fragment)
implementation(libs.androidx.fragment.compose)
implementation(libs.androidx.leanback.core)
implementation(libs.androidx.leanback.preference)
implementation(libs.androidx.navigation3.ui)
implementation(libs.androidx.preference)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.tvprovider)
@@ -129,15 +127,18 @@ dependencies {
implementation(libs.androidx.cardview)
implementation(libs.androidx.startup)
implementation(libs.bundles.androidx.compose)
implementation(libs.accompanist.permissions)
// Dependency Injection
implementation(libs.bundles.koin)
// Media players
implementation(libs.androidx.media3.exoplayer)
implementation(libs.androidx.media3.datasource.okhttp)
implementation(libs.androidx.media3.exoplayer.hls)
implementation(libs.androidx.media3.ui)
implementation(libs.jellyfin.androidx.media3.ffmpeg.decoder)
implementation(libs.libass.media3)
// Markdown
implementation(libs.bundles.markwon)

1
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1 @@
-dontwarn org.commonmark.ext.gfm.strikethrough.Strikethrough

View File

@@ -35,6 +35,11 @@
android:host="youtube.com"
android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:mimeType="video/*" />
</intent>
</queries>
<application
@@ -47,22 +52,11 @@
android:icon="@mipmap/app_icon"
android:label="@string/app_name"
android:largeHeap="true"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/Theme.Jellyfin"
android:usesCleartextTraffic="true">
<!-- Legacy service required for AccountManagerMigration -->
<service
android:name=".auth.service.AuthenticatorService"
android:exported="false">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<!-- Screensaver -->
<service
android:name=".integration.dream.LibraryDreamService"
@@ -108,9 +102,8 @@
<activity
android:name=".ui.startup.StartupActivity"
android:exported="true"
android:noHistory="true"
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:noHistory="true"
android:windowSoftInputMode="adjustNothing">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -132,14 +125,9 @@
<!-- Main application -->
<activity
android:name=".ui.browsing.MainActivity"
android:screenOrientation="landscape"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustNothing" />
<activity
android:name=".ui.preference.PreferencesActivity"
android:screenOrientation="behind"
android:theme="@style/Theme.Jellyfin.Preferences" />
<activity android:name=".ui.playback.ExternalPlayerActivity" />
</application>
</manifest>

View File

@@ -5,6 +5,7 @@ import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.startup.AppInitializer
import androidx.startup.Initializer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.jellyfin.androidtv.auth.repository.SessionRepository
import org.jellyfin.androidtv.di.KoinInitializer
@@ -17,7 +18,7 @@ class SessionInitializer : Initializer<Unit> {
.koin
// Restore system session
ProcessLifecycleOwner.get().lifecycleScope.launch {
ProcessLifecycleOwner.get().lifecycleScope.launch(Dispatchers.IO) {
koin.get<SessionRepository>().restoreSession(destroyOnly = false)
}
}

View File

@@ -1,48 +0,0 @@
package org.jellyfin.androidtv.auth
import android.accounts.AccountManager
import android.content.Context
import androidx.core.content.getSystemService
import org.jellyfin.androidtv.BuildConfig
import org.jellyfin.androidtv.auth.model.AuthenticationStoreServer
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
import timber.log.Timber
import java.util.UUID
class AccountManagerMigration(
context: Context,
) {
private val accountManager = requireNotNull(context.getSystemService<AccountManager>())
fun migrate(
servers: Map<UUID, AuthenticationStoreServer>,
) = servers.mapValues { (serverId, server) ->
Timber.i("Migrating server $serverId (${server.name})")
server.copy(
users = server.users.mapValues { (userId, user) ->
val accessToken = getAccessToken(serverId, userId)
Timber.i("Migrating user $userId (${user.name}): ${if (accessToken != null) "success" else "no token"}")
user.copy(accessToken = accessToken)
}
)
}
@Suppress("MissingPermission")
private fun getAccessToken(serverId: UUID, userId: UUID): String? = runCatching {
accountManager.getAccountsByType(ACCOUNT_TYPE)
.firstOrNull {
val validServerId = accountManager.getUserData(it, ACCOUNT_DATA_SERVER)?.toUUIDOrNull() == serverId
val validUserId = accountManager.getUserData(it, ACCOUNT_DATA_ID)?.toUUIDOrNull() == userId
validServerId && validUserId
}
?.let { account -> accountManager.peekAuthToken(account, ACCOUNT_ACCESS_TOKEN_TYPE) }
}.getOrNull()
companion object {
const val ACCOUNT_TYPE = BuildConfig.APPLICATION_ID
const val ACCOUNT_DATA_ID = "$ACCOUNT_TYPE.id"
const val ACCOUNT_DATA_SERVER = "$ACCOUNT_TYPE.server"
const val ACCOUNT_ACCESS_TOKEN_TYPE = "$ACCOUNT_TYPE.access_token"
}
}

View File

@@ -1,48 +0,0 @@
package org.jellyfin.androidtv.auth.apiclient
import org.jellyfin.androidtv.auth.repository.Session
import org.jellyfin.androidtv.auth.store.AuthenticationStore
import org.jellyfin.androidtv.util.sdk.legacy
import org.jellyfin.apiclient.interaction.ApiClient
import org.jellyfin.apiclient.model.apiclient.ServerInfo
import org.jellyfin.sdk.model.DeviceInfo
import timber.log.Timber
class ApiBinder(
private val api: ApiClient,
private val authenticationStore: AuthenticationStore,
) {
fun updateSession(session: Session?, deviceInfo: DeviceInfo): Boolean {
@Suppress("TooGenericExceptionCaught")
val success = try {
updateSessionInternal(session, deviceInfo)
} catch (throwable: Throwable) {
Timber.e(throwable, "Unable to update legacy API session.")
false
}
return success
}
private fun updateSessionInternal(session: Session?, deviceInfo: DeviceInfo): Boolean {
if (session == null) return true
val server = authenticationStore.getServer(session.serverId)
if (server == null) {
Timber.e("Could not bind API because server ${session.serverId} was not found in the store.")
return false
}
api.device = deviceInfo.legacy()
api.SetAuthenticationInfo(session.accessToken, session.userId.toString())
api.EnableAutomaticNetworking(ServerInfo().apply {
id = session.serverId.toString()
name = server.name
address = server.address.removeSuffix("/")
userId = session.userId.toString()
accessToken = session.accessToken
})
return true
}
}

View File

@@ -3,7 +3,7 @@ package org.jellyfin.androidtv.auth.model
sealed class QuickConnectState
/**
* State unknown untill first poll completed.
* State unknown until first poll completed.
*/
data object UnknownQuickConnectState : QuickConnectState()

View File

@@ -18,7 +18,7 @@ data class Server(
val setupCompleted: Boolean = true,
var dateLastAccessed: Instant = Instant.MIN,
) {
private val serverVersion = version?.let(ServerVersion::fromString)
val serverVersion = version?.let(ServerVersion::fromString)
val versionSupported = serverVersion != null && serverVersion >= ServerRepository.minimumServerVersion
operator fun compareTo(other: ServerVersion): Int = serverVersion?.compareTo(other) ?: -1

View File

@@ -1,9 +1,11 @@
package org.jellyfin.androidtv.auth.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import org.jellyfin.androidtv.auth.model.ApiClientErrorLoginState
import org.jellyfin.androidtv.auth.model.AuthenticateMethod
import org.jellyfin.androidtv.auth.model.AuthenticatedState
@@ -21,7 +23,10 @@ import org.jellyfin.androidtv.auth.model.ServerVersionNotSupported
import org.jellyfin.androidtv.auth.model.User
import org.jellyfin.androidtv.auth.store.AuthenticationPreferences
import org.jellyfin.androidtv.auth.store.AuthenticationStore
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.apiclient.JellyfinImage
import org.jellyfin.androidtv.util.apiclient.JellyfinImageSource
import org.jellyfin.androidtv.util.apiclient.getUrl
import org.jellyfin.androidtv.util.apiclient.primaryImage
import org.jellyfin.androidtv.util.sdk.forUser
import org.jellyfin.sdk.Jellyfin
import org.jellyfin.sdk.api.client.ApiClient
@@ -29,10 +34,10 @@ import org.jellyfin.sdk.api.client.exception.ApiClientException
import org.jellyfin.sdk.api.client.exception.TimeoutException
import org.jellyfin.sdk.api.client.extensions.authenticateUserByName
import org.jellyfin.sdk.api.client.extensions.authenticateWithQuickConnect
import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.api.client.extensions.userApi
import org.jellyfin.sdk.model.DeviceInfo
import org.jellyfin.sdk.model.api.AuthenticationResult
import org.jellyfin.sdk.model.api.ImageType
import org.jellyfin.sdk.model.api.UserDto
import timber.log.Timber
import java.time.Instant
@@ -55,9 +60,6 @@ class AuthenticationRepositoryImpl(
private val defaultDeviceInfo: DeviceInfo,
) : AuthenticationRepository {
override fun authenticate(server: Server, method: AuthenticateMethod): Flow<LoginState> {
// Check server version first
if (!server.versionSupported) return flowOf(ServerVersionNotSupported(server))
return when (method) {
is AutomaticAuthenticateMethod -> authenticateAutomatic(server, method.user)
is CredentialAuthenticateMethod -> authenticateCredential(server, method.username, method.password)
@@ -94,7 +96,7 @@ class AuthenticationRepositoryImpl(
}
emitAll(authenticateAuthenticationResult(server, result))
}
}.flowOn(Dispatchers.IO)
private fun authenticateQuickConnect(server: Server, secret: String) = flow {
val api = jellyfin.createApi(server.address, deviceInfo = defaultDeviceInfo)
@@ -112,7 +114,7 @@ class AuthenticationRepositoryImpl(
}
emitAll(authenticateAuthenticationResult(server, result))
}
}.flowOn(Dispatchers.IO)
private fun authenticateAuthenticationResult(server: Server, result: AuthenticationResult) = flow {
val accessToken = result.accessToken ?: return@flow emit(RequireSignInState)
@@ -122,7 +124,7 @@ class AuthenticationRepositoryImpl(
serverId = server.id,
name = userInfo.name!!,
accessToken = result.accessToken,
imageTag = userInfo.primaryImageTag,
imageTag = userInfo.primaryImage?.tag,
lastUsed = Instant.now().toEpochMilli(),
)
@@ -132,16 +134,18 @@ class AuthenticationRepositoryImpl(
emit(AuthenticatedState)
} else {
Timber.w("Failed to set active session after authenticating")
emit(RequireSignInState)
if (!server.versionSupported) emit(ServerVersionNotSupported(server))
else emit(RequireSignInState)
}
}
}.flowOn(Dispatchers.IO)
private fun authenticateToken(server: Server, user: User) = flow {
emit(AuthenticatingState)
val success = setActiveSession(user, server)
if (!success) {
emit(RequireSignInState)
if (!server.versionSupported) emit(ServerVersionNotSupported(server))
else emit(RequireSignInState)
} else try {
// Update user info
val userInfo by userApiClient.userApi.getCurrentUser()
@@ -155,7 +159,7 @@ class AuthenticationRepositoryImpl(
Timber.e(err, "Unable to get current user data")
emit(ApiClientErrorLoginState(err))
}
}
}.flowOn(Dispatchers.IO)
private suspend fun authenticateFinish(server: Server, userInfo: UserDto, accessToken: String) {
val currentUser = authenticationStore.getUser(server.id, userInfo.id)
@@ -163,11 +167,11 @@ class AuthenticationRepositoryImpl(
val updatedUser = currentUser?.copy(
name = userInfo.name!!,
lastUsed = Instant.now().toEpochMilli(),
imageTag = userInfo.primaryImageTag,
imageTag = userInfo.primaryImage?.tag,
accessToken = accessToken,
) ?: AuthenticationStoreUser(
name = userInfo.name!!,
imageTag = userInfo.primaryImageTag,
imageTag = userInfo.primaryImage?.tag,
accessToken = accessToken,
)
authenticationStore.putUser(server.id, userInfo.id, updatedUser)
@@ -199,11 +203,15 @@ class AuthenticationRepositoryImpl(
else false
}
override fun getUserImageUrl(server: Server, user: User): String? = user.imageTag?.let { tag ->
jellyfin.createApi(server.address).imageApi.getUserImageUrl(
userId = user.id,
tag = tag,
maxHeight = ImageHelper.MAX_PRIMARY_IMAGE_HEIGHT
override fun getUserImageUrl(server: Server, user: User): String? = user.imageTag?.let { primaryImageTag ->
JellyfinImage(
item = user.id,
source = JellyfinImageSource.USER,
type = ImageType.PRIMARY,
tag = primaryImageTag,
blurHash = null,
aspectRatio = null,
index = null
)
}
}?.getUrl(jellyfin.createApi(server.address))
}

View File

@@ -1,11 +1,14 @@
package org.jellyfin.androidtv.auth.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.auth.model.AuthenticationStoreServer
import org.jellyfin.androidtv.auth.model.ConnectedState
import org.jellyfin.androidtv.auth.model.ConnectingState
@@ -23,7 +26,7 @@ import org.jellyfin.sdk.api.client.extensions.systemApi
import org.jellyfin.sdk.discovery.RecommendedServerInfo
import org.jellyfin.sdk.discovery.RecommendedServerInfoScore
import org.jellyfin.sdk.model.ServerVersion
import org.jellyfin.sdk.model.api.BrandingOptions
import org.jellyfin.sdk.model.api.BrandingOptionsDto
import org.jellyfin.sdk.model.api.ServerDiscoveryInfo
import org.jellyfin.sdk.model.serializer.toUUID
import timber.log.Timber
@@ -36,20 +39,23 @@ import java.util.UUID
interface ServerRepository {
val storedServers: StateFlow<List<Server>>
val discoveredServers: StateFlow<List<Server>>
val currentServer: StateFlow<Server?>
suspend fun loadStoredServers()
suspend fun loadDiscoveryServers()
fun setCurrentServer(server: Server?)
fun addServer(address: String): Flow<ServerAdditionState>
suspend fun getServer(id: UUID): Server?
suspend fun updateServer(server: Server): Boolean
suspend fun getServer(id: UUID, eagerUpdate: Boolean = false): Server?
suspend fun updateServer(server: Server, force: Boolean = false): Boolean
suspend fun deleteServer(server: UUID): Boolean
companion object {
val minimumServerVersion = Jellyfin.minimumVersion.copy(build = null)
val recommendedServerVersion = Jellyfin.apiVersion.copy(build = null)
val upcomingMinimumServerVersion = ServerVersion(10, 9, 0)
val upcomingMinimumServerVersion = ServerVersion(10, 11, 0)
}
}
@@ -64,6 +70,9 @@ class ServerRepositoryImpl(
private val _discoveredServers = MutableStateFlow(emptyList<Server>())
override val discoveredServers = _discoveredServers.asStateFlow()
private val _currentServer = MutableStateFlow<Server?>(null)
override val currentServer = _currentServer.asStateFlow()
// Loading data
override suspend fun loadStoredServers() {
authenticationStore.getServers()
@@ -84,6 +93,10 @@ class ServerRepositoryImpl(
}
}
override fun setCurrentServer(server: Server?) {
_currentServer.value = server
}
// Mutating data
override fun addServer(address: String): Flow<ServerAdditionState> = flow {
Timber.i("Adding server %s", address)
@@ -95,13 +108,14 @@ class ServerRepositoryImpl(
val goodRecommendations = mutableListOf<RecommendedServerInfo>()
val badRecommendations = mutableListOf<RecommendedServerInfo>()
val greatRecommendaton = jellyfin.discovery.getRecommendedServers(addressCandidates).firstOrNull { recommendedServer ->
val greatRecommendation = jellyfin.discovery.getRecommendedServers(addressCandidates).firstOrNull { recommendedServer ->
when (recommendedServer.score) {
RecommendedServerInfoScore.GREAT -> true
RecommendedServerInfoScore.GOOD -> {
goodRecommendations += recommendedServer
false
}
else -> {
badRecommendations += recommendedServer
false
@@ -109,9 +123,9 @@ class ServerRepositoryImpl(
}
}
Timber.d(buildString {
Timber.i(buildString {
append("Recommendations: ")
if (greatRecommendaton == null) append(0)
if (greatRecommendation == null) append(0)
else append(1)
append(" great, ")
append(goodRecommendations.size)
@@ -120,7 +134,7 @@ class ServerRepositoryImpl(
append(" bad")
})
val chosenRecommendation = greatRecommendaton ?: goodRecommendations.firstOrNull()
val chosenRecommendation = greatRecommendation ?: goodRecommendations.firstOrNull()
if (chosenRecommendation != null && chosenRecommendation.systemInfo.isSuccess) {
// Get system info
val systemInfo = chosenRecommendation.systemInfo.getOrThrow()
@@ -159,13 +173,17 @@ class ServerRepositoryImpl(
.mapValues { (_, entry) -> entry.flatMap { server -> server.issues } }
emit(UnableToConnectState(addressCandidatesWithIssues))
}
}
}.flowOn(Dispatchers.IO)
override suspend fun getServer(id: UUID): Server? {
override suspend fun getServer(id: UUID, eagerUpdate: Boolean): Server? {
val server = authenticationStore.getServer(id) ?: return null
val updatedServer = try {
updateServerInternal(id, server)
val forceUpdate = eagerUpdate && server.version
?.let(ServerVersion::fromString)
?.let { version -> version < ServerRepository.minimumServerVersion } == true
updateServerInternal(id, server, forceUpdate)
} catch (err: ApiClientException) {
Timber.e(err, "Unable to update server")
null
@@ -174,12 +192,12 @@ class ServerRepositoryImpl(
return (updatedServer ?: server).asServer(id)
}
override suspend fun updateServer(server: Server): Boolean {
override suspend fun updateServer(server: Server, force: Boolean): Boolean {
// Only update existing servers
val serverInfo = authenticationStore.getServer(server.id) ?: return false
return try {
updateServerInternal(server.id, serverInfo) != null
updateServerInternal(server.id, serverInfo, force) != null
} catch (err: ApiClientException) {
Timber.e(err, "Unable to update server")
@@ -187,25 +205,32 @@ class ServerRepositoryImpl(
}
}
private suspend fun updateServerInternal(id: UUID, server: AuthenticationStoreServer): AuthenticationStoreServer? {
private suspend fun updateServerInternal(
id: UUID,
server: AuthenticationStoreServer,
forceUpdate: Boolean
): AuthenticationStoreServer? {
val now = Instant.now().toEpochMilli()
// Only update every 10 minutes
if (now - server.lastRefreshed < 600000 && server.version != null) return null
if (now - server.lastRefreshed < 600000 && server.version != null && !forceUpdate) return null
val api = jellyfin.createApi(server.address)
// Get login disclaimer
val branding = api.getBrandingOptionsOrDefault()
val systemInfo by api.systemApi.getPublicSystemInfo()
val newServer = withContext(Dispatchers.IO) {
val api = jellyfin.createApi(server.address)
val newServer = server.copy(
name = systemInfo.serverName ?: server.name,
version = systemInfo.version ?: server.version,
loginDisclaimer = branding.loginDisclaimer ?: server.loginDisclaimer,
splashscreenEnabled = branding.splashscreenEnabled,
setupCompleted = systemInfo.startupWizardCompleted ?: server.setupCompleted,
lastRefreshed = now
)
// Get login disclaimer
val branding = api.getBrandingOptionsOrDefault()
val systemInfo by api.systemApi.getPublicSystemInfo()
server.copy(
name = systemInfo.serverName ?: server.name,
version = systemInfo.version ?: server.version,
loginDisclaimer = branding.loginDisclaimer ?: server.loginDisclaimer,
splashscreenEnabled = branding.splashscreenEnabled,
setupCompleted = systemInfo.startupWizardCompleted ?: server.setupCompleted,
lastRefreshed = now
)
}
authenticationStore.putServer(id, newServer)
return newServer
@@ -237,7 +262,7 @@ class ServerRepositoryImpl(
brandingApi.getBrandingOptions().content
} catch (exception: InvalidContentException) {
Timber.w(exception, "Invalid branding options response, using default value")
BrandingOptions(
BrandingOptionsDto(
loginDisclaimer = null,
customCss = null,
splashscreenEnabled = false,

View File

@@ -1,5 +1,7 @@
package org.jellyfin.androidtv.auth.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.auth.model.PrivateUser
import org.jellyfin.androidtv.auth.model.PublicUser
import org.jellyfin.androidtv.auth.model.Server
@@ -47,7 +49,9 @@ class ServerUserRepositoryImpl(
val api = jellyfin.createApi(server.address)
return try {
val users by api.userApi.getPublicUsers()
val users = withContext(Dispatchers.IO) {
api.userApi.getPublicUsers().content
}
users.mapNotNull(UserDto::toPublicUser)
} catch (err: ApiClientException) {
Timber.e(err, "Unable to retrieve public users")

View File

@@ -1,5 +1,6 @@
package org.jellyfin.androidtv.auth.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -7,7 +8,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.auth.apiclient.ApiBinder
import org.jellyfin.androidtv.auth.model.Server
import org.jellyfin.androidtv.auth.store.AuthenticationPreferences
import org.jellyfin.androidtv.auth.store.AuthenticationStore
import org.jellyfin.androidtv.preference.PreferencesRepository
@@ -48,7 +49,6 @@ interface SessionRepository {
class SessionRepositoryImpl(
private val authenticationPreferences: AuthenticationPreferences,
private val apiBinder: ApiBinder,
private val authenticationStore: AuthenticationStore,
private val userApiClient: ApiClient,
private val preferencesRepository: PreferencesRepository,
@@ -112,13 +112,15 @@ class SessionRepositoryImpl(
override fun destroyCurrentSession() {
Timber.i("Destroying current session")
userRepository.updateCurrentUser(null)
userRepository.setCurrentUser(null)
serverRepository.setCurrentServer(null)
_currentSession.value = null
apiBinder.updateSession(null, userApiClient.deviceInfo)
_state.value = SessionRepositoryState.READY
}
private suspend fun setCurrentSession(session: Session?): Boolean {
var server: Server? = null
if (session != null) {
// No change in session - don't switch
if (currentSession.value?.userId == session.userId) return true
@@ -128,40 +130,40 @@ class SessionRepositoryImpl(
authenticationPreferences[AuthenticationPreferences.lastUserId] = session.userId.toString()
// Check if server version is supported
val server = serverRepository.getServer(session.serverId)
server = serverRepository.getServer(session.serverId, true)
if (server == null || !server.versionSupported) return false
}
// Update session after binding the apiclient settings
val deviceInfo = session?.let { defaultDeviceInfo.forUser(it.userId) } ?: defaultDeviceInfo
val success = apiBinder.updateSession(session, deviceInfo)
Timber.i("Updating current session. userId=${session?.userId} apiBindingSuccess=${success}")
Timber.i("Updating current session. userId=${session?.userId} server=${server?.serverVersion}")
if (success) {
val applied = userApiClient.applySession(session, deviceInfo)
if (applied && session != null) {
try {
val user by userApiClient.userApi.getCurrentUser()
userRepository.updateCurrentUser(user)
} catch (err: ApiClientException) {
Timber.e(err, "Unable to authenticate: bad response when getting user info")
destroyCurrentSession()
return false
val applied = userApiClient.applySession(session, deviceInfo)
if (applied && session != null) {
try {
val user = withContext(Dispatchers.IO) {
userApiClient.userApi.getCurrentUser().content
}
// Update crash reporting URL
val crashReportUrl = userApiClient.clientLogApi.logFileUrl()
telemetryPreferences[TelemetryPreferences.crashReportUrl] = crashReportUrl
telemetryPreferences[TelemetryPreferences.crashReportToken] = session.accessToken
} else {
userRepository.updateCurrentUser(null)
userRepository.setCurrentUser(user)
serverRepository.setCurrentServer(server)
} catch (err: ApiClientException) {
Timber.e(err, "Unable to authenticate: bad response when getting user info")
destroyCurrentSession()
return false
}
preferencesRepository.onSessionChanged()
_currentSession.value = session
} else destroyCurrentSession()
return success
// Update crash reporting URL
val crashReportUrl = userApiClient.clientLogApi.logFileUrl()
telemetryPreferences[TelemetryPreferences.crashReportUrl] = crashReportUrl
telemetryPreferences[TelemetryPreferences.crashReportToken] = session.accessToken
} else {
userRepository.setCurrentUser(null)
serverRepository.setCurrentServer(null)
}
preferencesRepository.onSessionChanged()
_currentSession.value = session
return true
}
private fun createLastUserSession(): Session? {

View File

@@ -10,13 +10,13 @@ import org.jellyfin.sdk.model.api.UserDto
interface UserRepository {
val currentUser: StateFlow<UserDto?>
fun updateCurrentUser(user: UserDto?)
fun setCurrentUser(user: UserDto?)
}
class UserRepositoryImpl : UserRepository {
override val currentUser = MutableStateFlow<UserDto?>(null)
override fun updateCurrentUser(user: UserDto?) {
override fun setCurrentUser(user: UserDto?) {
currentUser.value = user
}
}

View File

@@ -1,79 +0,0 @@
package org.jellyfin.androidtv.auth.service
import android.accounts.AbstractAccountAuthenticator
import android.accounts.Account
import android.accounts.AccountAuthenticatorResponse
import android.accounts.AccountManager
import android.app.Service
import android.content.Intent
import android.os.Bundle
import android.os.IBinder
import androidx.core.os.bundleOf
import org.jellyfin.androidtv.ui.preference.PreferencesActivity
class AuthenticatorService : Service() {
private val authenticator by lazy {
Authenticator(this)
}
override fun onBind(intent: Intent): IBinder? = authenticator.iBinder
private inner class Authenticator(
private val service: AuthenticatorService
) : AbstractAccountAuthenticator(service) {
private val unsupportedOperationBundle = bundleOf(
AccountManager.KEY_ERROR_CODE to AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
AccountManager.KEY_ERROR_MESSAGE to "Unsupported operation"
)
override fun addAccount(
response: AccountAuthenticatorResponse,
accountType: String,
authTokenType: String?,
requiredFeatures: Array<String>?,
options: Bundle,
): Bundle = unsupportedOperationBundle
override fun confirmCredentials(
response: AccountAuthenticatorResponse,
account: Account,
options: Bundle?,
): Bundle = unsupportedOperationBundle
override fun editProperties(
response: AccountAuthenticatorResponse,
accountType: String,
): Bundle = bundleOf(
AccountManager.KEY_INTENT to Intent(service, PreferencesActivity::class.java)
)
override fun getAccountRemovalAllowed(
response: AccountAuthenticatorResponse,
account: Account,
): Bundle = bundleOf(
AccountManager.KEY_BOOLEAN_RESULT to true
)
override fun getAuthToken(
response: AccountAuthenticatorResponse,
account: Account,
authTokenType: String,
options: Bundle,
): Bundle = unsupportedOperationBundle
override fun getAuthTokenLabel(authTokenType: String): String? = null
override fun hasFeatures(
response: AccountAuthenticatorResponse,
account: Account,
features: Array<String>,
): Bundle = unsupportedOperationBundle
override fun updateCredentials(
response: AccountAuthenticatorResponse,
account: Account,
authTokenType: String?,
options: Bundle?,
): Bundle = unsupportedOperationBundle
}
}

View File

@@ -2,7 +2,6 @@ package org.jellyfin.androidtv.auth.store
import android.content.Context
import kotlinx.serialization.SerializationException
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
@@ -13,7 +12,6 @@ import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual
import org.jellyfin.androidtv.auth.AccountManagerMigration
import org.jellyfin.androidtv.auth.model.AuthenticationStoreServer
import org.jellyfin.androidtv.auth.model.AuthenticationStoreUser
import org.jellyfin.sdk.model.serializer.UUIDSerializer
@@ -28,7 +26,6 @@ import java.util.UUID
*/
class AuthenticationStore(
private val context: Context,
private val accountManagerMigration: AccountManagerMigration,
) {
private val storePath
get() = context.filesDir.resolve("authentication_store.json")
@@ -59,11 +56,13 @@ class AuthenticationStore(
// Check for version
return when (root["version"]?.jsonPrimitive?.intOrNull) {
1 -> json.decodeFromJsonElement<Map<UUID, AuthenticationStoreServer>>(root["servers"]!!)
// Add access tokens from account manager to stored users and save the migrated data
.let { servers -> accountManagerMigration.migrate(servers) }
.also { servers -> write(servers) }
// Migration was removed, clear stored servers
1 -> {
Timber.e("Migrating from version 1 is no longer possible")
emptyMap()
}
// Current version, return as-is
2 -> json.decodeFromJsonElement<Map<UUID, AuthenticationStoreServer>>(root["servers"]!!)
null -> {

View File

@@ -66,6 +66,7 @@ object Codec {
const val VP8 = "vp8"
const val VP9 = "vp9"
const val AV1 = "av1"
const val VC1 = "vc1"
}
object Subtitle {

View File

@@ -18,7 +18,6 @@ enum class QueryType {
LiveTvProgram,
LiveTvRecording,
StaticItems,
StaticAudioQueueItems,
Artists,
AlbumArtists,
AudioPlaylists,

View File

@@ -1,7 +1,6 @@
package org.jellyfin.androidtv.data.compat
import org.jellyfin.apiclient.model.dlna.DeviceProfile
import org.jellyfin.apiclient.model.dlna.EncodingContext
import org.jellyfin.sdk.model.api.DeviceProfile
import org.jellyfin.sdk.model.api.MediaSourceInfo
import java.util.UUID
@@ -22,11 +21,4 @@ open class AudioOptions {
* Example: DeviceProfile supports five channel, but user only has stereo speakers
*/
var maxAudioChannels: Int? = null
/**
* The application's configured quality setting
*/
var maxBitrate: Int? = null
var context = EncodingContext.Streaming
}

View File

@@ -1,7 +1,7 @@
package org.jellyfin.androidtv.data.compat
import org.jellyfin.apiclient.model.dlna.PlaybackErrorCode
import org.jellyfin.sdk.model.api.PlaybackErrorCode
class PlaybackException : RuntimeException() {
var errorCode = PlaybackErrorCode.NotAllowed
var errorCode = PlaybackErrorCode.NOT_ALLOWED
}

View File

@@ -1,97 +0,0 @@
package org.jellyfin.androidtv.data.compat;
import org.jellyfin.androidtv.util.Utils;
import org.jellyfin.apiclient.model.dlna.SubtitleDeliveryMethod;
import org.jellyfin.apiclient.model.dlna.SubtitleProfile;
import org.jellyfin.apiclient.model.entities.MediaStream;
import org.jellyfin.apiclient.model.session.PlayMethod;
public class StreamBuilder
{
public static SubtitleProfile getSubtitleProfile(org.jellyfin.sdk.model.api.MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod)
{
if (playMethod != PlayMethod.Transcode && !subtitleStream.isExternal())
{
// Look for supported embedded subs
for (SubtitleProfile profile : subtitleProfiles)
{
if (!profile.SupportsLanguage(subtitleStream.getLanguage()))
{
continue;
}
if (profile.getMethod() != SubtitleDeliveryMethod.Embed)
{
continue;
}
if (subtitleStream.isTextSubtitleStream() == MediaStream.IsTextFormat(profile.getFormat()) && Utils.equalsIgnoreCase(profile.getFormat(), subtitleStream.getCodec()))
{
return profile;
}
}
}
// Look for an external or hls profile that matches the stream type (text/graphical) and doesn't require conversion
SubtitleProfile tempVar = new SubtitleProfile();
tempVar.setMethod(SubtitleDeliveryMethod.Encode);
tempVar.setFormat(subtitleStream.getCodec());
SubtitleProfile tempVar2 = getExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false);
SubtitleProfile tempVar3 = getExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, true);
return (tempVar2 != null) ? tempVar2 : (tempVar3 != null) ? tempVar3 : tempVar;
}
private static SubtitleProfile getExternalSubtitleProfile(org.jellyfin.sdk.model.api.MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, boolean allowConversion)
{
for (SubtitleProfile profile : subtitleProfiles)
{
if (profile.getMethod() != SubtitleDeliveryMethod.External && profile.getMethod() != SubtitleDeliveryMethod.Hls)
{
continue;
}
if (profile.getMethod() == SubtitleDeliveryMethod.Hls && playMethod != PlayMethod.Transcode)
{
continue;
}
if (!profile.SupportsLanguage(subtitleStream.getLanguage()))
{
continue;
}
if ((profile.getMethod() == SubtitleDeliveryMethod.External && subtitleStream.isTextSubtitleStream() == MediaStream.IsTextFormat(profile.getFormat())) || (profile.getMethod() == SubtitleDeliveryMethod.Hls && subtitleStream.isTextSubtitleStream()))
{
boolean requiresConversion = !Utils.equalsIgnoreCase(subtitleStream.getCodec(), profile.getFormat());
if (!requiresConversion)
{
return profile;
}
if (!allowConversion)
{
continue;
}
if (subtitleStream.isTextSubtitleStream() && subtitleStream.getSupportsExternalStream() && supportsSubtitleConversionTo(subtitleStream, profile.getFormat()))
{
return profile;
}
}
}
return null;
}
public static boolean supportsSubtitleConversionTo(org.jellyfin.sdk.model.api.MediaStream mediaStream, String codec)
{
if (!mediaStream.isTextSubtitleStream())
{
return false;
}
// Can't convert from this
return !("ass".equalsIgnoreCase(mediaStream.getCodec()) || "ssa".equalsIgnoreCase(mediaStream.getCodec()) || "ass".equalsIgnoreCase(codec) || "ssa".equalsIgnoreCase(codec));
}
}

View File

@@ -1,16 +1,10 @@
package org.jellyfin.androidtv.data.compat;
import org.jellyfin.androidtv.util.Utils;
import org.jellyfin.apiclient.model.dlna.DeviceProfile;
import org.jellyfin.apiclient.model.dlna.EncodingContext;
import org.jellyfin.apiclient.model.dlna.SubtitleDeliveryMethod;
import org.jellyfin.apiclient.model.dlna.SubtitleProfile;
import org.jellyfin.apiclient.model.dlna.TranscodeSeekInfo;
import org.jellyfin.apiclient.model.session.PlayMethod;
import org.jellyfin.sdk.model.api.MediaProtocol;
import org.jellyfin.sdk.model.api.MediaSourceInfo;
import org.jellyfin.sdk.model.api.MediaStream;
import org.jellyfin.sdk.model.api.MediaStreamType;
import org.jellyfin.sdk.model.api.PlayMethod;
import org.jellyfin.sdk.model.api.SubtitleDeliveryMethod;
import java.util.ArrayList;
import java.util.UUID;
@@ -36,24 +30,14 @@ public class StreamInfo {
MediaUrl = value;
}
private PlayMethod PlayMethod = getPlayMethod().values()[0];
private PlayMethod playMethod = PlayMethod.DIRECT_PLAY;
public final PlayMethod getPlayMethod() {
return PlayMethod;
return playMethod;
}
public final void setPlayMethod(PlayMethod value) {
PlayMethod = value;
}
private EncodingContext Context = EncodingContext.values()[0];
public final EncodingContext getContext() {
return Context;
}
public final void setContext(EncodingContext value) {
Context = value;
playMethod = value;
}
private String Container;
@@ -66,26 +50,6 @@ public class StreamInfo {
Container = value;
}
private long StartPositionTicks;
public final long getStartPositionTicks() {
return StartPositionTicks;
}
public final void setStartPositionTicks(long value) {
StartPositionTicks = value;
}
private DeviceProfile DeviceProfile;
public final DeviceProfile getDeviceProfile() {
return DeviceProfile;
}
public final void setDeviceProfile(DeviceProfile value) {
DeviceProfile = value;
}
private Long RunTimeTicks = null;
public final Long getRunTimeTicks() {
@@ -96,12 +60,6 @@ public class StreamInfo {
RunTimeTicks = value;
}
private TranscodeSeekInfo TranscodeSeekInfo = getTranscodeSeekInfo().values()[0];
public final TranscodeSeekInfo getTranscodeSeekInfo() {
return TranscodeSeekInfo;
}
private MediaSourceInfo MediaSource;
public final MediaSourceInfo getMediaSource() {
@@ -112,10 +70,10 @@ public class StreamInfo {
MediaSource = value;
}
private SubtitleDeliveryMethod SubtitleDeliveryMethod = getSubtitleDeliveryMethod().values()[0];
public final SubtitleDeliveryMethod getSubtitleDeliveryMethod() {
return SubtitleDeliveryMethod;
public final org.jellyfin.sdk.model.api.SubtitleDeliveryMethod getSubtitleDeliveryMethod() {
Integer subtitleStreamIndex = MediaSource.getDefaultSubtitleStreamIndex();
if (subtitleStreamIndex == null || subtitleStreamIndex == -1) return SubtitleDeliveryMethod.DROP;
return MediaSource.getMediaStreams().get(subtitleStreamIndex).getDeliveryMethod();
}
private String PlaySessionId;
@@ -132,69 +90,6 @@ public class StreamInfo {
return getMediaSource() == null ? null : getMediaSource().getId();
}
public final ArrayList<SubtitleStreamInfo> getSubtitleProfiles(boolean includeSelectedTrackOnly, String baseUrl, String accessToken) {
return getSubtitleProfiles(includeSelectedTrackOnly, false, baseUrl, accessToken);
}
public final ArrayList<SubtitleStreamInfo> getSubtitleProfiles(boolean includeSelectedTrackOnly, boolean enableAllProfiles, String baseUrl, String accessToken) {
ArrayList<SubtitleStreamInfo> list = new ArrayList<SubtitleStreamInfo>();
// HLS will preserve timestamps so we can just grab the full subtitle stream
long startPositionTicks = getPlayMethod() == PlayMethod.Transcode ? getStartPositionTicks() : 0;
if (!includeSelectedTrackOnly) {
if (getMediaSource() == null) return list;
for (org.jellyfin.sdk.model.api.MediaStream stream : getMediaSource().getMediaStreams()) {
if (stream.getType() == org.jellyfin.sdk.model.api.MediaStreamType.SUBTITLE) {
addSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks);
}
}
}
return list;
}
private void addSubtitleProfiles(ArrayList<SubtitleStreamInfo> list, org.jellyfin.sdk.model.api.MediaStream stream, boolean enableAllProfiles, String baseUrl, String accessToken, long startPositionTicks) {
if (enableAllProfiles) {
for (SubtitleProfile profile : getDeviceProfile().getSubtitleProfiles()) {
SubtitleStreamInfo info = getSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new SubtitleProfile[]{profile});
list.add(info);
}
} else {
SubtitleStreamInfo info = getSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, getDeviceProfile().getSubtitleProfiles());
list.add(info);
}
}
private SubtitleStreamInfo getSubtitleStreamInfo(org.jellyfin.sdk.model.api.MediaStream stream, String baseUrl, String accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles) {
SubtitleProfile subtitleProfile = StreamBuilder.getSubtitleProfile(stream, subtitleProfiles, getPlayMethod());
SubtitleStreamInfo tempVar = new SubtitleStreamInfo();
String tempVar2 = stream.getLanguage();
tempVar.setName((tempVar2 != null) ? tempVar2 : "Unknown");
tempVar.setFormat(subtitleProfile.getFormat());
tempVar.setIndex(stream.getIndex());
tempVar.setDeliveryMethod(subtitleProfile.getMethod());
tempVar.setDisplayTitle(stream.getDisplayTitle());
SubtitleStreamInfo info = tempVar;
if (info.getDeliveryMethod() == SubtitleDeliveryMethod.External) {
if (getMediaSource().getProtocol() == MediaProtocol.FILE || !stream.getCodec().equalsIgnoreCase(subtitleProfile.getFormat())) {
info.setUrl(String.format("%1$s/Videos/%2$s/%3$s/Subtitles/%4$s/%5$s/Stream.%6$s", baseUrl, getItemId(), getMediaSourceId(), String.valueOf(stream.getIndex()), String.valueOf(startPositionTicks), subtitleProfile.getFormat()));
if (!Utils.isEmpty(accessToken)) {
info.setUrl(info.getUrl() + "?api_key=" + accessToken);
}
} else {
info.setUrl(stream.getPath());
}
}
return info;
}
public final ArrayList<MediaStream> getSelectableAudioStreams() {
return getSelectableStreams(MediaStreamType.AUDIO);
}

View File

@@ -1,12 +0,0 @@
package org.jellyfin.androidtv.data.compat
import org.jellyfin.apiclient.model.dlna.SubtitleDeliveryMethod
class SubtitleStreamInfo {
var url: String? = null
var name: String? = null
var format: String? = null
var displayTitle: String? = null
var index = 0
var deliveryMethod = SubtitleDeliveryMethod.Encode
}

View File

@@ -2,12 +2,15 @@ package org.jellyfin.androidtv.data.eventhandling
import android.content.Context
import android.media.AudioManager
import android.os.Build
import android.widget.Toast
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.data.model.DataRefreshService
@@ -16,6 +19,7 @@ import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.ui.playback.MediaManager
import org.jellyfin.androidtv.ui.playback.PlaybackControllerContainer
import org.jellyfin.androidtv.ui.playback.setSubtitleIndex
import org.jellyfin.androidtv.util.PlaybackHelper
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.exception.ApiClientException
@@ -49,105 +53,111 @@ class SocketHandler(
private val audioManager: AudioManager,
private val itemLauncher: ItemLauncher,
private val playbackHelper: PlaybackHelper,
private val lifecycle: Lifecycle,
) {
private val coroutineScope = CoroutineScope(Dispatchers.IO)
suspend fun updateSession() {
try {
api.sessionApi.postCapabilities(
playableMediaTypes = listOf(MediaType.VIDEO, MediaType.AUDIO),
supportsMediaControl = true,
supportedCommands = buildList {
add(GeneralCommandType.DISPLAY_CONTENT)
add(GeneralCommandType.SET_SUBTITLE_STREAM_INDEX)
add(GeneralCommandType.SET_AUDIO_STREAM_INDEX)
add(GeneralCommandType.DISPLAY_MESSAGE)
add(GeneralCommandType.SEND_STRING)
// Note: These are used in the PlaySessionSocketService
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !audioManager.isVolumeFixed) {
add(GeneralCommandType.VOLUME_UP)
add(GeneralCommandType.VOLUME_DOWN)
add(GeneralCommandType.SET_VOLUME)
add(GeneralCommandType.MUTE)
add(GeneralCommandType.UNMUTE)
add(GeneralCommandType.TOGGLE_MUTE)
}
},
)
} catch (err: ApiClientException) {
Timber.e(err, "Unable to update capabilities")
return
init {
lifecycle.coroutineScope.launch(Dispatchers.IO) {
lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
subscribe(this)
}
}
}
init {
api.webSocket.apply {
// Library
subscribe<LibraryChangedMessage>()
.onEach { message -> message.data?.let(::onLibraryChanged) }
.launchIn(coroutineScope)
suspend fun updateSession() {
try {
withContext(Dispatchers.IO) {
api.sessionApi.postCapabilities(
playableMediaTypes = listOf(MediaType.VIDEO, MediaType.AUDIO),
supportsMediaControl = true,
supportedCommands = buildList {
add(GeneralCommandType.DISPLAY_CONTENT)
add(GeneralCommandType.SET_SUBTITLE_STREAM_INDEX)
add(GeneralCommandType.SET_AUDIO_STREAM_INDEX)
// Media playback
subscribe<PlayMessage>()
.onEach { message -> onPlayMessage(message) }
.launchIn(coroutineScope)
add(GeneralCommandType.DISPLAY_MESSAGE)
add(GeneralCommandType.SEND_STRING)
subscribe<PlaystateMessage>()
.onEach { message -> onPlayStateMessage(message) }
.launchIn(coroutineScope)
// Note: These are used in the PlaySessionSocketService
if (!audioManager.isVolumeFixed) {
add(GeneralCommandType.VOLUME_UP)
add(GeneralCommandType.VOLUME_DOWN)
add(GeneralCommandType.SET_VOLUME)
subscribeGeneralCommand(GeneralCommandType.SET_SUBTITLE_STREAM_INDEX)
.onEach { message ->
val index = message["index"]?.toIntOrNull() ?: return@onEach
withContext(Dispatchers.Main) {
playbackControllerContainer.playbackController?.switchSubtitleStream(index)
}
}
.launchIn(coroutineScope)
subscribeGeneralCommand(GeneralCommandType.SET_AUDIO_STREAM_INDEX)
.onEach { message ->
val index = message["index"]?.toIntOrNull() ?: return@onEach
withContext(Dispatchers.Main) {
playbackControllerContainer.playbackController?.switchAudioStream(index)
}
}
.launchIn(coroutineScope)
// General commands
subscribeGeneralCommand(GeneralCommandType.DISPLAY_CONTENT)
.onEach { message ->
val itemId by message
val itemType by message
val itemUuid = itemId?.toUUIDOrNull()
val itemKind = itemType?.let { type ->
BaseItemKind.entries.find { value ->
value.serialName.equals(type, true)
add(GeneralCommandType.MUTE)
add(GeneralCommandType.UNMUTE)
add(GeneralCommandType.TOGGLE_MUTE)
}
}
if (itemUuid != null && itemKind != null) onDisplayContent(itemUuid, itemKind)
}
.launchIn(coroutineScope)
subscribeGeneralCommands(setOf(GeneralCommandType.DISPLAY_MESSAGE, GeneralCommandType.SEND_STRING))
.onEach { message ->
val header by message
val text by message
val string by message
onDisplayMessage(header, text ?: string)
}
.launchIn(coroutineScope)
},
)
}
} catch (err: ApiClientException) {
Timber.e(err, "Unable to update capabilities")
}
}
private fun subscribe(coroutineScope: CoroutineScope) = api.webSocket.apply {
// Library
subscribe<LibraryChangedMessage>()
.onEach { message -> message.data?.let(::onLibraryChanged) }
.launchIn(coroutineScope)
// Media playback
subscribe<PlayMessage>()
.onEach { message -> onPlayMessage(message) }
.launchIn(coroutineScope)
subscribe<PlaystateMessage>()
.onEach { message -> onPlayStateMessage(message) }
.launchIn(coroutineScope)
subscribeGeneralCommand(GeneralCommandType.SET_SUBTITLE_STREAM_INDEX)
.onEach { message ->
val index = message["index"]?.toIntOrNull() ?: return@onEach
withContext(Dispatchers.Main) {
playbackControllerContainer.playbackController?.setSubtitleIndex(index)
}
}
.launchIn(coroutineScope)
subscribeGeneralCommand(GeneralCommandType.SET_AUDIO_STREAM_INDEX)
.onEach { message ->
val index = message["index"]?.toIntOrNull() ?: return@onEach
withContext(Dispatchers.Main) {
playbackControllerContainer.playbackController?.switchAudioStream(index)
}
}
.launchIn(coroutineScope)
// General commands
subscribeGeneralCommand(GeneralCommandType.DISPLAY_CONTENT)
.onEach { message ->
val itemId by message
val itemType by message
val itemUuid = itemId?.toUUIDOrNull()
val itemKind = itemType?.let { type ->
BaseItemKind.entries.find { value ->
value.serialName.equals(type, true)
}
}
if (itemUuid != null && itemKind != null) onDisplayContent(itemUuid, itemKind)
}
.launchIn(coroutineScope)
subscribeGeneralCommands(setOf(GeneralCommandType.DISPLAY_MESSAGE, GeneralCommandType.SEND_STRING))
.onEach { message ->
val header by message
val text by message
val string by message
onDisplayMessage(header, text ?: string)
}
.launchIn(coroutineScope)
}
private fun onLibraryChanged(info: LibraryUpdateInfo) {
Timber.d(buildString {
appendLine("Library changed.")
@@ -161,13 +171,14 @@ class SocketHandler(
}
private fun onPlayMessage(message: PlayMessage) {
val itemId = message.data?.itemIds?.firstOrNull() ?: return
val itemIds = message.data?.itemIds ?: return
runCatching {
playbackHelper.retrieveAndPlay(
itemId,
itemIds,
false,
message.data?.startPositionTicks,
message.data?.startIndex,
context
)
}.onFailure { Timber.w(it, "Failed to start playback") }

View File

@@ -1,10 +1,11 @@
package org.jellyfin.androidtv.data.model
import org.jellyfin.androidtv.util.apiclient.JellyfinImage
import java.util.UUID
data class ChapterItemInfo(
val itemId: UUID,
val name: String?,
val startPositionTicks: Long,
val imagePath: String?,
val image: JellyfinImage?,
)

View File

@@ -0,0 +1,62 @@
package org.jellyfin.androidtv.data.repository
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.ResolveInfo
import androidx.core.net.toUri
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.util.componentName
class ExternalAppRepository(
private val userPreferences: UserPreferences,
) {
companion object {
const val SAMPLE_VIDEO_URL = "http://jellyfin.local/query.mp4"
const val MEDIA_TYPE_VIDEO = "video/*"
}
private val externalPlayerAppIntent = Intent(Intent.ACTION_VIEW).apply {
setDataAndTypeAndNormalize(SAMPLE_VIDEO_URL.toUri(), MEDIA_TYPE_VIDEO)
}
fun getExternalPlayerApps(context: Context): List<ResolveInfo> = context.packageManager
.queryIntentActivities(externalPlayerAppIntent, 0)
// Hide apps with priority below zero (system stubs)
.filter { it.priority >= 0 }
fun getCurrentExternalPlayerApp(context: Context): ActivityInfo? {
// Validate if external app should be used at all
val useExternalPlayer = userPreferences[UserPreferences.useExternalPlayer]
if (!useExternalPlayer) return null
// Resolve external app information
val resolvedInfo = userPreferences[UserPreferences.externalPlayerComponentName]
.takeIf { it.isNotEmpty() }
?.let(ComponentName::unflattenFromString)
?.runCatching { context.packageManager.getActivityInfo(this, 0) }
?.getOrNull()
if (resolvedInfo != null) return resolvedInfo
// Fallback in case the app is uninstalled or unavailable for some other reason
val externalApps = getExternalPlayerApps(context)
// System default
val systemDefault = externalApps.find { it.isDefault }?.activityInfo
if (systemDefault != null) return systemDefault
// First compatible, or none
return externalApps.firstOrNull()?.activityInfo
}
fun setExternalPlayerapp(activityInfo: ActivityInfo?) {
if (activityInfo == null) {
userPreferences[UserPreferences.useExternalPlayer] = false
userPreferences[UserPreferences.externalPlayerComponentName] = ""
} else {
userPreferences[UserPreferences.useExternalPlayer] = true
userPreferences[UserPreferences.externalPlayerComponentName] = activityInfo.componentName.flattenToShortString()
}
}
}

View File

@@ -1,5 +1,7 @@
package org.jellyfin.androidtv.data.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.data.model.DataRefreshService
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.playStateApi
@@ -19,8 +21,8 @@ class ItemMutationRepositoryImpl(
) : ItemMutationRepository {
override suspend fun setFavorite(item: UUID, favorite: Boolean): UserItemDataDto {
val response by when {
favorite -> api.userLibraryApi.markFavoriteItem(itemId = item)
else -> api.userLibraryApi.unmarkFavoriteItem(itemId = item)
favorite -> withContext(Dispatchers.IO) { api.userLibraryApi.markFavoriteItem(itemId = item) }
else -> withContext(Dispatchers.IO) { api.userLibraryApi.unmarkFavoriteItem(itemId = item) }
}
dataRefreshService.lastFavoriteUpdate = Instant.now()
@@ -29,8 +31,8 @@ class ItemMutationRepositoryImpl(
override suspend fun setPlayed(item: UUID, played: Boolean): UserItemDataDto {
val response by when {
played -> api.playStateApi.markPlayedItem(itemId = item)
else -> api.playStateApi.markUnplayedItem(itemId = item)
played -> withContext(Dispatchers.IO) { api.playStateApi.markPlayedItem(itemId = item) }
else -> withContext(Dispatchers.IO) { api.playStateApi.markUnplayedItem(itemId = item) }
}
return response

View File

@@ -0,0 +1,25 @@
package org.jellyfin.androidtv.data.repository
import org.jellyfin.sdk.model.api.ItemFields
object ItemRepository {
val itemFields = setOf(
ItemFields.CAN_DELETE,
ItemFields.CHANNEL_INFO,
ItemFields.CHAPTERS,
ItemFields.CHILD_COUNT,
ItemFields.CUMULATIVE_RUN_TIME_TICKS,
ItemFields.DATE_CREATED,
ItemFields.DISPLAY_PREFERENCES_ID,
ItemFields.GENRES,
ItemFields.ITEM_COUNTS,
ItemFields.MEDIA_SOURCE_COUNT,
ItemFields.MEDIA_SOURCES,
ItemFields.MEDIA_STREAMS,
ItemFields.OVERVIEW,
ItemFields.PATH,
ItemFields.PRIMARY_IMAGE_ASPECT_RATIO,
ItemFields.TAGLINES,
ItemFields.TRICKPLAY,
)
}

View File

@@ -1,7 +1,9 @@
package org.jellyfin.androidtv.data.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.userViewsApi
import org.jellyfin.sdk.model.api.BaseItemDto
@@ -21,10 +23,9 @@ class UserViewsRepositoryImpl(
override val views = flow {
val views by api.userViewsApi.getUserViews()
val filteredViews = views.items
.orEmpty()
.filter { isSupported(it.collectionType) }
emit(filteredViews)
}
}.flowOn(Dispatchers.IO)
override fun isSupported(collectionType: CollectionType?) = collectionType !in unsupportedCollectionTypes
override fun allowViewSelection(collectionType: CollectionType?) = collectionType !in disallowViewSelectionCollectionTypes

View File

@@ -3,9 +3,9 @@ package org.jellyfin.androidtv.data.service
import android.content.Context
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.core.graphics.drawable.toBitmap
import coil.ImageLoader
import coil.request.ImageRequest
import coil3.ImageLoader
import coil3.request.ImageRequest
import coil3.toBitmap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
@@ -15,13 +15,15 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.jellyfin.androidtv.auth.model.Server
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.preference.constant.BackdropBehavior
import org.jellyfin.androidtv.util.apiclient.getUrl
import org.jellyfin.androidtv.util.apiclient.itemBackdropImages
import org.jellyfin.androidtv.util.apiclient.parentBackdropImages
import org.jellyfin.sdk.Jellyfin
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.ImageType
import java.time.Instant
import java.util.UUID
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@@ -54,38 +56,23 @@ class BackgroundService(
val blurBackground get() = _blurBackground.asStateFlow()
val enabled get() = _enabled.asStateFlow()
// Helper function for [setBackground]
private fun List<String>?.getUrls(itemId: UUID?): List<String> {
// Check for nullability
if (itemId == null || isNullOrEmpty()) return emptyList()
return mapIndexed { index, tag ->
api.imageApi.getItemImageUrl(
itemId = itemId,
imageType = ImageType.BACKDROP,
tag = tag,
imageIndex = index,
fillWidth = context.resources.displayMetrics.widthPixels,
fillHeight = context.resources.displayMetrics.heightPixels,
)
}
}
/**
* Use all available backdrops from [baseItem] as background.
*/
fun setBackground(baseItem: BaseItemDto?) {
val backdropBehavior = userPreferences[UserPreferences.backdropBehavior]
// Check if item is set and backgrounds are enabled
if (baseItem == null || !userPreferences[UserPreferences.backdropEnabled])
if (baseItem == null || backdropBehavior == BackdropBehavior.DISABLED)
return clearBackgrounds()
// Enable blur for backdrops
_blurBackground.value = true
_blurBackground.value = backdropBehavior == BackdropBehavior.BACKDROP_WITH_BLUR
// Get all backdrop urls
val itemBackdropUrls = baseItem.backdropImageTags.getUrls(baseItem.id)
val parentBackdropUrls = baseItem.parentBackdropImageTags.getUrls(baseItem.parentBackdropItemId)
val backdropUrls = itemBackdropUrls.union(parentBackdropUrls)
val backdropUrls = (baseItem.itemBackdropImages + baseItem.parentBackdropImages)
.map { it.getUrl(api) }
.toSet()
loadBackgrounds(backdropUrls)
}
@@ -95,7 +82,7 @@ class BackgroundService(
*/
fun setBackground(server: Server) {
// Check if item is set and backgrounds are enabled
if (!userPreferences[UserPreferences.backdropEnabled])
if (userPreferences[UserPreferences.backdropBehavior] == BackdropBehavior.DISABLED)
return clearBackgrounds()
// Check if splashscreen is enabled in (cached) branding options
@@ -124,7 +111,7 @@ class BackgroundService(
_backgrounds = backdropUrls.mapNotNull { url ->
imageLoader.execute(
request = ImageRequest.Builder(context).data(url).build()
).drawable?.toBitmap()?.asImageBitmap()
).image?.toBitmap()?.asImageBitmap()
}
// Go to first background

View File

@@ -2,10 +2,16 @@ package org.jellyfin.androidtv.di
import android.content.Context
import android.os.Build
import coil.ImageLoader
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import coil.decode.SvgDecoder
import androidx.lifecycle.ProcessLifecycleOwner
import coil3.ImageLoader
import coil3.annotation.ExperimentalCoilApi
import coil3.gif.AnimatedImageDecoder
import coil3.gif.GifDecoder
import coil3.network.NetworkFetcher
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
import coil3.serviceLoaderEnabled
import coil3.svg.SvgDecoder
import coil3.util.Logger
import org.jellyfin.androidtv.BuildConfig
import org.jellyfin.androidtv.auth.repository.ServerRepository
import org.jellyfin.androidtv.auth.repository.UserRepository
@@ -14,6 +20,7 @@ import org.jellyfin.androidtv.data.eventhandling.SocketHandler
import org.jellyfin.androidtv.data.model.DataRefreshService
import org.jellyfin.androidtv.data.repository.CustomMessageRepository
import org.jellyfin.androidtv.data.repository.CustomMessageRepositoryImpl
import org.jellyfin.androidtv.data.repository.ExternalAppRepository
import org.jellyfin.androidtv.data.repository.ItemMutationRepository
import org.jellyfin.androidtv.data.repository.ItemMutationRepositoryImpl
import org.jellyfin.androidtv.data.repository.NotificationsRepository
@@ -22,18 +29,22 @@ import org.jellyfin.androidtv.data.repository.UserViewsRepository
import org.jellyfin.androidtv.data.repository.UserViewsRepositoryImpl
import org.jellyfin.androidtv.data.service.BackgroundService
import org.jellyfin.androidtv.integration.dream.DreamViewModel
import org.jellyfin.androidtv.ui.ScreensaverViewModel
import org.jellyfin.androidtv.ui.InteractionTrackerViewModel
import org.jellyfin.androidtv.ui.itemhandling.ItemLauncher
import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.ui.navigation.NavigationRepositoryImpl
import org.jellyfin.androidtv.ui.picture.PictureViewerViewModel
import org.jellyfin.androidtv.ui.playback.PlaybackControllerContainer
import org.jellyfin.androidtv.ui.playback.nextup.NextUpViewModel
import org.jellyfin.androidtv.ui.playback.segment.MediaSegmentRepository
import org.jellyfin.androidtv.ui.playback.segment.MediaSegmentRepositoryImpl
import org.jellyfin.androidtv.ui.playback.stillwatching.StillWatchingViewModel
import org.jellyfin.androidtv.ui.player.photo.PhotoPlayerViewModel
import org.jellyfin.androidtv.ui.search.SearchFragmentDelegate
import org.jellyfin.androidtv.ui.search.SearchRepository
import org.jellyfin.androidtv.ui.search.SearchRepositoryImpl
import org.jellyfin.androidtv.ui.search.SearchViewModel
import org.jellyfin.androidtv.ui.settings.compat.SettingsViewModel
import org.jellyfin.androidtv.ui.startup.ServerAddViewModel
import org.jellyfin.androidtv.ui.startup.StartupViewModel
import org.jellyfin.androidtv.ui.startup.UserLoginViewModel
@@ -41,68 +52,76 @@ import org.jellyfin.androidtv.util.KeyProcessor
import org.jellyfin.androidtv.util.MarkdownRenderer
import org.jellyfin.androidtv.util.PlaybackHelper
import org.jellyfin.androidtv.util.apiclient.ReportingHelper
import org.jellyfin.androidtv.util.coil.CoilTimberLogger
import org.jellyfin.androidtv.util.coil.createCoilConnectivityChecker
import org.jellyfin.androidtv.util.sdk.SdkPlaybackHelper
import org.jellyfin.androidtv.util.sdk.legacy
import org.jellyfin.apiclient.AppInfo
import org.jellyfin.apiclient.android
import org.jellyfin.apiclient.logging.AndroidLogger
import org.jellyfin.sdk.android.androidDevice
import org.jellyfin.sdk.api.client.HttpClientOptions
import org.jellyfin.sdk.api.okhttp.OkHttpFactory
import org.jellyfin.sdk.createJellyfin
import org.jellyfin.sdk.model.ClientInfo
import org.jellyfin.sdk.model.DeviceInfo
import org.koin.android.ext.koin.androidApplication
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.module.dsl.viewModel
import org.koin.core.qualifier.named
import org.koin.dsl.module
import org.jellyfin.apiclient.Jellyfin as JellyfinApiClient
import org.jellyfin.sdk.Jellyfin as JellyfinSdk
val defaultDeviceInfo = named("defaultDeviceInfo")
val appModule = module {
// New SDK
// SDK
single(defaultDeviceInfo) { androidDevice(get()) }
single { OkHttpFactory() }
single { HttpClientOptions() }
single {
createJellyfin {
context = androidContext()
// Add client info
clientInfo = ClientInfo("Android TV", BuildConfig.VERSION_NAME)
val clientName = buildString {
append("Jellyfin Android TV")
if (BuildConfig.DEBUG) append(" (debug)")
}
clientInfo = ClientInfo(clientName, BuildConfig.VERSION_NAME)
deviceInfo = get(defaultDeviceInfo)
// Change server version
minimumServerVersion = ServerRepository.minimumServerVersion
// Use our own shared factory instance
apiClientFactory = get<OkHttpFactory>()
socketConnectionFactory = get<OkHttpFactory>()
}
}
single {
// Create an empty API instance, the actual values are set by the SessionRepository
get<JellyfinSdk>().createApi()
get<JellyfinSdk>().createApi(httpClientOptions = get<HttpClientOptions>())
}
single { SocketHandler(get(), get(), get(), get(), get(), get(), get(), get(), get()) }
// Old apiclient
single {
JellyfinApiClient {
appInfo = AppInfo("Android TV", BuildConfig.VERSION_NAME)
logger = AndroidLogger()
android(androidApplication())
}
}
single {
get<JellyfinApiClient>().createApi(
device = get<DeviceInfo>(defaultDeviceInfo).legacy()
)
}
single { SocketHandler(get(), get(), get(), get(), get(), get(), get(), get(), get(), ProcessLifecycleOwner.get().lifecycle) }
// Coil (images)
single {
val okHttpFactory = get<OkHttpFactory>()
val httpClientOptions = get<HttpClientOptions>()
@OptIn(ExperimentalCoilApi::class)
OkHttpNetworkFetcherFactory(
callFactory = { okHttpFactory.createClient(httpClientOptions) },
connectivityChecker = ::createCoilConnectivityChecker,
)
}
single {
ImageLoader.Builder(androidContext()).apply {
serviceLoaderEnabled(false)
logger(CoilTimberLogger(if (BuildConfig.DEBUG) Logger.Level.Warn else Logger.Level.Error))
components {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) add(ImageDecoderDecoder.Factory())
add(get<NetworkFetcher.Factory>())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) add(AnimatedImageDecoder.Factory())
else add(GifDecoder.Factory())
add(SvgDecoder.Factory())
}
@@ -112,6 +131,7 @@ val appModule = module {
// Non API related
single { DataRefreshService() }
single { PlaybackControllerContainer() }
single { InteractionTrackerViewModel(get(), get()) }
single<UserRepository> { UserRepositoryImpl() }
single<UserViewsRepository> { UserViewsRepositoryImpl(get()) }
@@ -120,23 +140,26 @@ val appModule = module {
single<CustomMessageRepository> { CustomMessageRepositoryImpl() }
single<NavigationRepository> { NavigationRepositoryImpl(Destinations.home) }
single<SearchRepository> { SearchRepositoryImpl(get()) }
single<MediaSegmentRepository> { MediaSegmentRepositoryImpl(get(), get()) }
single<ExternalAppRepository> { ExternalAppRepository(get()) }
viewModel { StartupViewModel(get(), get(), get(), get()) }
viewModel { UserLoginViewModel(get(), get(), get(), get(defaultDeviceInfo)) }
viewModel { ServerAddViewModel(get()) }
viewModel { NextUpViewModel(get(), get(), get(), get()) }
viewModel { PictureViewerViewModel(get()) }
viewModel { ScreensaverViewModel(get()) }
viewModel { NextUpViewModel(get(), get(), get()) }
viewModel { StillWatchingViewModel(get(), get(), get(), get()) }
viewModel { PhotoPlayerViewModel(get()) }
viewModel { SearchViewModel(get()) }
viewModel { DreamViewModel(get(), get(), get(), get(), get()) }
viewModel { SettingsViewModel() }
single { BackgroundService(get(), get(), get(), get(), get()) }
single { MarkdownRenderer(get()) }
single { ItemLauncher() }
single { KeyProcessor() }
single { ReportingHelper() }
single<PlaybackHelper> { SdkPlaybackHelper(get(), get(), get(), get(), get(), get(), get()) }
single { ReportingHelper(get(), get()) }
single<PlaybackHelper> { SdkPlaybackHelper(get(), get(), get(), get()) }
factory { (context: Context) -> SearchFragmentDelegate(context, get(), get()) }
}

View File

@@ -1,7 +1,5 @@
package org.jellyfin.androidtv.di
import org.jellyfin.androidtv.auth.AccountManagerMigration
import org.jellyfin.androidtv.auth.apiclient.ApiBinder
import org.jellyfin.androidtv.auth.repository.AuthenticationRepository
import org.jellyfin.androidtv.auth.repository.AuthenticationRepositoryImpl
import org.jellyfin.androidtv.auth.repository.ServerRepository
@@ -15,8 +13,7 @@ import org.jellyfin.androidtv.auth.store.AuthenticationStore
import org.koin.dsl.module
val authModule = module {
single { AccountManagerMigration(get()) }
single { AuthenticationStore(get(), get()) }
single { AuthenticationStore(get()) }
single { AuthenticationPreferences(get()) }
single<AuthenticationRepository> {
@@ -25,8 +22,11 @@ val authModule = module {
single<ServerRepository> { ServerRepositoryImpl(get(), get()) }
single<ServerUserRepository> { ServerUserRepositoryImpl(get(), get()) }
single<SessionRepository> {
SessionRepositoryImpl(get(), get(), get(), get(), get(), get(defaultDeviceInfo), get(), get(), get())
SessionRepositoryImpl(get(), get(), get(), get(), get(defaultDeviceInfo), get(), get(), get())
}
single { ApiBinder(get(), get()) }
factory {
val serverRepository = get<ServerRepository>()
serverRepository.currentServer.value?.serverVersion ?: ServerRepository.minimumServerVersion
}
}

View File

@@ -6,40 +6,49 @@ import android.app.PendingIntent
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationManagerCompat
import org.jellyfin.androidtv.BuildConfig
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.media3.datasource.HttpDataSource
import androidx.media3.datasource.okhttp.OkHttpDataSource
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.preference.UserSettingPreferences
import org.jellyfin.androidtv.ui.browsing.MainActivity
import org.jellyfin.androidtv.ui.playback.GarbagePlaybackLauncher
import org.jellyfin.androidtv.ui.playback.MediaManager
import org.jellyfin.androidtv.ui.playback.RewritePlaybackLauncher
import org.jellyfin.androidtv.ui.playback.PlaybackLauncher
import org.jellyfin.androidtv.ui.playback.VideoQueueManager
import org.jellyfin.androidtv.ui.playback.rewrite.RewriteMediaManager
import org.jellyfin.androidtv.util.profile.createDeviceProfile
import org.jellyfin.playback.core.playbackManager
import org.jellyfin.playback.jellyfin.jellyfinPlugin
import org.jellyfin.playback.media3.exoplayer.ExoPlayerOptions
import org.jellyfin.playback.media3.exoplayer.exoPlayerPlugin
import org.jellyfin.playback.media3.session.MediaSessionOptions
import org.jellyfin.playback.media3.session.media3SessionPlugin
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.HttpClientOptions
import org.jellyfin.sdk.api.okhttp.OkHttpFactory
import org.jellyfin.sdk.model.api.MediaSegmentType
import org.koin.android.ext.koin.androidContext
import org.koin.core.scope.Scope
import org.koin.dsl.module
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import org.jellyfin.androidtv.ui.playback.PlaybackManager as LegacyPlaybackManager
val playbackModule = module {
single { LegacyPlaybackManager(get()) }
single { VideoQueueManager() }
single<MediaManager> { RewriteMediaManager(get(), get(), get(), get()) }
single<MediaManager> { RewriteMediaManager(get(), get()) }
factory {
val preferences = get<UserPreferences>()
val useRewrite = preferences[UserPreferences.playbackRewriteVideoEnabled] && BuildConfig.DEVELOPMENT
single { PlaybackLauncher(get(), get(), get(), get()) }
if (useRewrite) RewritePlaybackLauncher()
else GarbagePlaybackLauncher(get())
single<HttpDataSource.Factory> {
val okHttpFactory = get<OkHttpFactory>()
val httpClientOptions = get<HttpClientOptions>().copy(
// Disable request timeout for media playback as this causes issues with Live TV
requestTimeout = Duration.ZERO
)
OkHttpDataSource.Factory(okHttpFactory.createClient(httpClientOptions))
}
single { createPlaybackManager() }
@@ -56,13 +65,16 @@ fun Scope.createPlaybackManager() = playbackManager(androidContext()) {
notificationChannelId,
NotificationManager.IMPORTANCE_LOW
)
channel.setShowBadge(false)
NotificationManagerCompat.from(get()).createNotificationChannel(channel)
}
val api = get<ApiClient>()
val userPreferences = get<UserPreferences>()
val exoPlayerOptions = ExoPlayerOptions(
httpConnectTimeout = api.httpClientOptions.connectTimeout,
httpReadTimeout = api.httpClientOptions.requestTimeout
preferFfmpeg = userPreferences[UserPreferences.preferExoPlayerFfmpeg],
enableLibass = userPreferences[UserPreferences.assDirectPlay],
enableDebugLogging = userPreferences[UserPreferences.debuggingEnabled],
baseDataSourceFactory = get<HttpDataSource.Factory>(),
)
install(exoPlayerPlugin(get(), exoPlayerOptions))
@@ -74,7 +86,8 @@ fun Scope.createPlaybackManager() = playbackManager(androidContext()) {
)
install(media3SessionPlugin(get(), mediaSessionOptions))
install(jellyfinPlugin(get()))
val deviceProfileBuilder = { createDeviceProfile(androidContext(), userPreferences, get()) }
install(jellyfinPlugin(get(), deviceProfileBuilder, setOf(MediaSegmentType.INTRO), ProcessLifecycleOwner.get().lifecycle))
// Options
val userSettingPreferences = get<UserSettingPreferences>()

View File

@@ -7,8 +7,10 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.core.content.edit
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.net.toUri
import androidx.tvprovider.media.tv.Channel
import androidx.tvprovider.media.tv.ChannelLogoUtils
import androidx.tvprovider.media.tv.PreviewProgram
@@ -21,37 +23,38 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.data.repository.ItemRepository
import org.jellyfin.androidtv.data.repository.UserViewsRepository
import org.jellyfin.androidtv.integration.provider.ImageProvider
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.ui.startup.StartupActivity
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.apiclient.getUrl
import org.jellyfin.androidtv.util.apiclient.itemImages
import org.jellyfin.androidtv.util.apiclient.parentImages
import org.jellyfin.androidtv.util.dp
import org.jellyfin.androidtv.util.sdk.isUsable
import org.jellyfin.androidtv.util.stripHtml
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.exception.ApiClientException
import org.jellyfin.sdk.api.client.exception.TimeoutException
import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.api.client.extensions.itemsApi
import org.jellyfin.sdk.api.client.extensions.tvShowsApi
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
import org.jellyfin.sdk.api.client.extensions.userViewsApi
import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.ImageFormat
import org.jellyfin.sdk.model.api.ImageType
import org.jellyfin.sdk.model.api.ItemFields
import org.jellyfin.sdk.model.api.MediaType
import org.jellyfin.sdk.model.extensions.ticks
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import timber.log.Timber
import java.time.Instant
import java.time.ZoneOffset
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import kotlin.time.Duration
/**
* Manages channels on the android tv home screen.
*
@@ -99,39 +102,39 @@ class LeanbackChannelWorker(
// Get channel URIs
val latestMediaChannel = getChannelUri(
"latest_media", Channel.Builder()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.home_section_latest_media))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build(),
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.home_section_latest_media))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build(),
default = true
)
val myMediaChannel = getChannelUri(
"my_media", Channel.Builder()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_my_media))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_my_media))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
)
val nextUpChannel = getChannelUri(
"next_up", Channel.Builder()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_next_up))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_next_up))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
)
val latestMoviesChannel = getChannelUri(
"latest_movies", Channel.Builder()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_movies))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_movies))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
)
val latestEpisodesChannel = getChannelUri(
"latest_episodes", Channel.Builder()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_new_episodes))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
.setType(TvContractCompat.Channels.TYPE_PREVIEW)
.setDisplayName(context.getString(R.string.lbl_new_episodes))
.setAppLinkIntent(Intent(context, StartupActivity::class.java))
.build()
)
val preferParentThumb = userPreferences[UserPreferences.seriesThumbnailsEnabled]
@@ -143,18 +146,21 @@ class LeanbackChannelWorker(
latestEpisodes to latestEpisodesChannel,
myMedia to myMediaChannel,
).forEach { (items, channel) ->
Timber.d("Updating channel %s", channel)
items.map { item ->
createPreviewProgram(
channel,
item,
preferParentThumb
)
}.let {
context.contentResolver.bulkInsert(
TvContractCompat.PreviewPrograms.CONTENT_URI,
it.toTypedArray()
)
if (channel == null) {
Timber.e("Skipping channel because it was not available")
} else {
items.map { item ->
createPreviewProgram(
channel,
item,
preferParentThumb
)
}.let {
context.contentResolver.bulkInsert(
TvContractCompat.PreviewPrograms.CONTENT_URI,
it.toTypedArray()
)
}
}
}
updateWatchNext(resumeItems + nextUpItems)
@@ -177,35 +183,46 @@ class LeanbackChannelWorker(
* update or create the channel. The [name] parameter is used to store the id and should be
* unique.
*/
private fun getChannelUri(name: String, settings: Channel, default: Boolean = false): Uri {
private fun getChannelUri(name: String, settings: Channel, default: Boolean = false): Uri? {
val store = context.getSharedPreferences("leanback_channels", Context.MODE_PRIVATE)
var uri: Uri? = null
val uri = if (store.contains(name)) {
// Retrieve uri and update content resolver
Uri.parse(store.getString(name, null)).also { uri ->
context.contentResolver.update(uri, settings.toContentValues(), null, null)
}
} else {
// Create new channel and save uri
context.contentResolver.insert(
TvContractCompat.Channels.CONTENT_URI,
settings.toContentValues()
)!!.also { uri ->
store.edit().putString(name, uri.toString()).apply()
if (default) {
// Set as default row to display (we can request one row to automatically be added to the home screen)
TvContractCompat.requestChannelBrowsable(context, ContentUris.parseId(uri))
}
// Try and re-use our existing channel definition
if (store.contains(name)) {
uri = store.getString(name, null)?.toUri()
if (uri != null) {
val result = context.contentResolver.update(uri, settings.toContentValues(), null, null)
// If we did not affect exactly 1 row there might be something wrong, so recreate it
if (result != 1) uri = null
}
}
// Update logo
ResourcesCompat.getDrawable(context.resources, R.mipmap.app_icon, context.theme)?.let {
ChannelLogoUtils.storeChannelLogo(
context,
ContentUris.parseId(uri),
it.toBitmap(80.dp(context), 80.dp(context))
if (uri == null) {
// Create new channel
uri = context.contentResolver.insert(
TvContractCompat.Channels.CONTENT_URI,
settings.toContentValues()
)
// Set as default row to display (we can request one row to automatically be added to the home screen)
if (uri != null && default) {
TvContractCompat.requestChannelBrowsable(context, ContentUris.parseId(uri))
}
// Save uri to shared preferences
store.edit { putString(name, uri?.toString()) }
}
// Update logo
if (uri != null) {
ResourcesCompat.getDrawable(context.resources, R.mipmap.app_icon, context.theme)?.let {
ChannelLogoUtils.storeChannelLogo(
context,
ContentUris.parseId(uri),
it.toBitmap(80.dp(context), 80.dp(context))
)
}
}
return uri
@@ -220,7 +237,6 @@ class LeanbackChannelWorker(
// Add new items
return response.items
.orEmpty()
.filter { userViewsRepository.isSupported(it.collectionType) }
}
@@ -231,35 +247,12 @@ class LeanbackChannelWorker(
private fun BaseItemDto.getPosterArtImageUrl(
preferParentThumb: Boolean
): Uri = when {
type == BaseItemKind.MOVIE || type == BaseItemKind.SERIES -> api.imageApi.getItemImageUrl(
itemId = id,
imageType = ImageType.PRIMARY,
format = ImageFormat.WEBP,
width = 106.dp(context),
height = 153.dp(context),
tag = imageTags?.get(ImageType.PRIMARY),
)
(preferParentThumb || imageTags?.contains(ImageType.PRIMARY) != true) && parentThumbItemId != null -> api.imageApi.getItemImageUrl(
itemId = parentThumbItemId!!,
imageType = ImageType.THUMB,
format = ImageFormat.WEBP,
width = 272.dp(context),
height = 153.dp(context),
tag = imageTags?.get(ImageType.THUMB),
)
imageTags?.containsKey(ImageType.PRIMARY) == true -> api.imageApi.getItemImageUrl(
itemId = id,
imageType = ImageType.PRIMARY,
format = ImageFormat.WEBP,
width = 272.dp(context),
height = 153.dp(context),
tag = imageTags?.get(ImageType.PRIMARY),
)
else -> imageHelper.getResourceUrl(context, R.drawable.tile_land_tv)
}.let(ImageProvider::getImageUri)
type == BaseItemKind.MOVIE || type == BaseItemKind.SERIES -> itemImages[ImageType.PRIMARY]
(preferParentThumb || !itemImages.contains(ImageType.PRIMARY)) && parentImages.contains(ImageType.THUMB) -> parentImages[ImageType.THUMB]
else -> itemImages[ImageType.PRIMARY]
}.let { image ->
ImageProvider.getImageUri(image?.getUrl(api) ?: imageHelper.getResourceUrl(context, R.drawable.tile_land_tv))
}
/**
* Gets the resume and next up episodes. The returned pair contains two lists:
@@ -270,13 +263,13 @@ class LeanbackChannelWorker(
withContext(Dispatchers.IO) {
val resume = async {
api.itemsApi.getResumeItems(
fields = listOf(ItemFields.DATE_CREATED),
fields = ItemRepository.itemFields,
imageTypeLimit = 1,
limit = 10,
mediaTypes = listOf(MediaType.VIDEO),
includeItemTypes = listOf(BaseItemKind.EPISODE, BaseItemKind.MOVIE),
excludeActiveSessions = true,
).content.items.orEmpty()
).content.items
}
val nextUp = async {
@@ -284,8 +277,8 @@ class LeanbackChannelWorker(
imageTypeLimit = 1,
limit = 10,
enableResumable = false,
fields = listOf(ItemFields.DATE_CREATED),
).content.items.orEmpty()
fields = ItemRepository.itemFields,
).content.items
}
// Concat
@@ -296,9 +289,7 @@ class LeanbackChannelWorker(
withContext(Dispatchers.IO) {
val latestEpisodes = async {
api.userLibraryApi.getLatestMedia(
fields = listOf(
ItemFields.OVERVIEW,
),
fields = ItemRepository.itemFields,
limit = 50,
includeItemTypes = listOf(BaseItemKind.EPISODE),
isPlayed = false
@@ -307,9 +298,7 @@ class LeanbackChannelWorker(
val latestMovies = async {
api.userLibraryApi.getLatestMedia(
fields = listOf(
ItemFields.OVERVIEW,
),
fields = ItemRepository.itemFields,
limit = 50,
includeItemTypes = listOf(BaseItemKind.MOVIE),
isPlayed = false
@@ -318,9 +307,7 @@ class LeanbackChannelWorker(
val latestMedia = async {
api.userLibraryApi.getLatestMedia(
fields = listOf(
ItemFields.OVERVIEW,
),
fields = ItemRepository.itemFields,
limit = 50,
includeItemTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.SERIES),
isPlayed = false
@@ -361,23 +348,11 @@ class LeanbackChannelWorker(
)
.setTitle(item.seriesName ?: item.name)
.setEpisodeTitle(if (item.type == BaseItemKind.EPISODE) item.name else null)
.setSeasonNumber(seasonString, item.parentIndexNumber ?: 0)
.setEpisodeNumber(episodeString, item.indexNumber ?: 0)
.setDescription(item.overview)
.setDescription(item.overview?.stripHtml())
.setReleaseDate(
if (item.premiereDate != null) DateTimeFormatter.ISO_DATE.format(item.premiereDate)
else null
)
.setDurationMillis(
if (item.runTimeTicks?.ticks != null) {
// If we are resuming, we need to show remaining time, cause GoogleTV
// ignores setLastPlaybackPositionMillis
val duration = item.runTimeTicks?.ticks ?: Duration.ZERO
val playbackPosition = item.userData?.playbackPositionTicks?.ticks
?: Duration.ZERO
(duration - playbackPosition).inWholeMilliseconds.toInt()
} else 0
)
.setPosterArtUri(imageUri)
.setPosterArtAspectRatio(
when (item.type) {
@@ -391,8 +366,22 @@ class LeanbackChannelWorker(
putExtra(StartupActivity.EXTRA_ITEM_ID, item.id.toString())
putExtra(StartupActivity.EXTRA_ITEM_IS_USER_VIEW, item.type == BaseItemKind.COLLECTION_FOLDER)
})
.build()
.toContentValues()
.setDurationMillis(
if (item.runTimeTicks?.ticks != null) {
// If we are resuming, we need to show remaining time, cause GoogleTV
// ignores setLastPlaybackPositionMillis
val duration = item.runTimeTicks?.ticks ?: Duration.ZERO
val playbackPosition = item.userData?.playbackPositionTicks?.ticks
?: Duration.ZERO
(duration - playbackPosition).inWholeMilliseconds.toInt()
} else 0
)
.apply {
if ((item.parentIndexNumber ?: 0) > 0)
setSeasonNumber(seasonString, item.parentIndexNumber!!)
if ((item.indexNumber ?: 0) > 0)
setEpisodeNumber(episodeString, item.indexNumber!!)
}.build().toContentValues()
}
/**
@@ -400,16 +389,57 @@ class LeanbackChannelWorker(
* or other types of media. Uses the [nextUpItems] parameter to store items returned by a
* NextUpQuery().
*/
@SuppressLint("RestrictedApi")
private fun updateWatchNext(nextUpItems: List<BaseItemDto>) {
// Delete current items
context.contentResolver.delete(WatchNextPrograms.CONTENT_URI, null, null)
deletePrograms(nextUpItems)
// Add new items
// Get current watch next state
val currentWatchNextPrograms = getCurrentWatchNext()
// Create all programs in nextUpItems but not in watch next
val programsToAdd = nextUpItems
.filter { next -> currentWatchNextPrograms.none { it.internalProviderId == next.id.toString() } }
context.contentResolver.bulkInsert(
WatchNextPrograms.CONTENT_URI,
nextUpItems.map { item -> getBaseItemAsWatchNextProgram(item).toContentValues() }
.toTypedArray()
)
programsToAdd.map { item -> getBaseItemAsWatchNextProgram(item).toContentValues() }
.toTypedArray())
}
/**
* Delete stale programs from the watch next row. Items that don't need to be touched are
* kept as is, so they keep their ordering in the watch next row.
*/
@SuppressLint("RestrictedApi")
private fun deletePrograms(nextUpItems: List<BaseItemDto>) {
// Retrieve current watch next row
val currentWatchNextPrograms = getCurrentWatchNext()
// Find all stale programs to delete
val deletedByUser = currentWatchNextPrograms.filter { !it.isBrowsable }
val noLongerInWatchNext =
currentWatchNextPrograms.filter { (nextUpItems).none { next -> it.internalProviderId == next.id.toString() } }
val continueWatching = currentWatchNextPrograms.filter { it.watchNextType == WatchNextPrograms.WATCH_NEXT_TYPE_CONTINUE }
// Delete the programs
(deletedByUser + noLongerInWatchNext + continueWatching)
.forEach { context.contentResolver.delete(TvContractCompat.buildWatchNextProgramUri(it.id), null, null) }
}
/**
* Retrieves the current watch next row state.
*/
@SuppressLint("RestrictedApi")
private fun getCurrentWatchNext(): MutableList<WatchNextProgram> {
val currentWatchNextPrograms: MutableList<WatchNextProgram> = mutableListOf()
context.contentResolver.query(WatchNextPrograms.CONTENT_URI, WatchNextProgram.PROJECTION, null, null, null)
.use { cursor ->
if (cursor != null && cursor.moveToFirst()) {
do {
currentWatchNextPrograms.add(WatchNextProgram.fromCursor(cursor))
} while (cursor.moveToNext())
}
}
return currentWatchNextPrograms
}
/**
@@ -431,39 +461,51 @@ class LeanbackChannelWorker(
setPosterArtAspectRatio(WatchNextPrograms.ASPECT_RATIO_MOVIE_POSTER)
}
// Name
if (item.seriesName != null) setTitle("${item.seriesName} - ${item.name}")
else setTitle(item.name)
// Name and episode details
if (item.seriesName != null) {
setTitle(item.seriesName)
setEpisodeTitle(item.name)
item.indexNumber?.takeIf { it > 0 }?.let { setEpisodeNumber(it) }
item.parentIndexNumber?.takeIf { it > 0 }?.let { setSeasonNumber(it) }
} else {
setTitle(item.name)
}
setDescription(item.overview?.stripHtml())
// Poster
setPosterArtUri(item.getPosterArtImageUrl(preferParentThumb))
// Use date created or fallback to current time if unavailable
var engagement = item.dateCreated
when {
// User has started playing the episode
(item.userData?.playbackPositionTicks ?: 0) > 0 -> {
setWatchNextType(WatchNextPrograms.WATCH_NEXT_TYPE_CONTINUE)
setLastPlaybackPositionMillis(item.userData!!.playbackPositionTicks.ticks.inWholeMilliseconds.toInt())
// Use last played date to prioritize
engagement = item.userData?.lastPlayedDate
setLastEngagementTimeUtcMillis(
item.userData?.lastPlayedDate?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
?: Instant.now().toEpochMilli()
)
}
// First episode of the season
item.indexNumber == 1 -> setWatchNextType(WatchNextPrograms.WATCH_NEXT_TYPE_NEW)
item.indexNumber == 1 -> {
setWatchNextType(WatchNextPrograms.WATCH_NEXT_TYPE_NEW)
setLastEngagementTimeUtcMillis(
item.dateCreated?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
?: Instant.now().toEpochMilli()
)
}
// Default
else -> setWatchNextType(WatchNextPrograms.WATCH_NEXT_TYPE_NEXT)
else -> {
setWatchNextType(WatchNextPrograms.WATCH_NEXT_TYPE_NEXT)
setLastEngagementTimeUtcMillis(Instant.now().toEpochMilli())
}
}
setLastEngagementTimeUtcMillis(
engagement?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
?: Instant.now().toEpochMilli()
)
// Episode runtime has been determined
item.runTimeTicks?.let { runTimeTicks ->
setDurationMillis(runTimeTicks.ticks.inWholeMilliseconds.toInt())
}
// Runtime has been determined
item.runTimeTicks?.ticks?.let { setDurationMillis(it.inWholeMilliseconds.toInt()) }
// Set intent to open the episode
setIntent(Intent(context, StartupActivity::class.java).apply {

View File

@@ -9,19 +9,22 @@ import android.database.Cursor
import android.database.MatrixCursor
import android.net.Uri
import android.provider.BaseColumns
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.BuildConfig
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.data.repository.ItemRepository
import org.jellyfin.androidtv.integration.provider.ImageProvider
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.apiclient.getUrl
import org.jellyfin.androidtv.util.apiclient.itemImages
import org.jellyfin.androidtv.util.sdk.isUsable
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.exception.ApiClientException
import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.api.client.extensions.itemsApi
import org.jellyfin.sdk.model.api.BaseItemDtoQueryResult
import org.jellyfin.sdk.model.api.ImageType
import org.jellyfin.sdk.model.api.ItemFields
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import timber.log.Timber
@@ -61,8 +64,9 @@ class MediaContentProvider : ContentProvider(), KoinComponent {
val limit = uri.getQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT)?.toIntOrNull()
?: DEFAULT_LIMIT
return getSuggestions(query, limit)
return runBlocking { getSuggestions(query, limit) }
}
else -> throw IllegalArgumentException("Unknown Uri: $uri")
}
}
@@ -75,7 +79,7 @@ class MediaContentProvider : ContentProvider(), KoinComponent {
searchTerm = query,
recursive = true,
limit = limit,
fields = setOf(ItemFields.TAGLINES)
fields = ItemRepository.itemFields
)
items
@@ -84,7 +88,7 @@ class MediaContentProvider : ContentProvider(), KoinComponent {
null
}
private fun getSuggestions(query: String, limit: Int) = runBlocking {
private suspend fun getSuggestions(query: String, limit: Int) = withContext(Dispatchers.IO) {
val searchResult = searchItems(query, limit)
if (searchResult != null) Timber.d("Query resulted in %d items", searchResult.totalRecordCount)
@@ -104,10 +108,10 @@ class MediaContentProvider : ContentProvider(), KoinComponent {
MatrixCursor(columns).also { cursor ->
searchResult?.items?.forEach { item ->
val imageUri = if (item.imageTags?.contains(ImageType.PRIMARY) == true)
ImageProvider.getImageUri(api.imageApi.getItemImageUrl(item.id, ImageType.PRIMARY))
else
imageHelper.getResourceUrl(context!!, R.drawable.tile_land_tv)
val imageUri = ImageProvider.getImageUri(
item.itemImages[ImageType.PRIMARY]?.getUrl(api)
?: imageHelper.getResourceUrl(context!!, R.drawable.tile_land_tv)
)
cursor.newRow().apply {
add(BaseColumns._ID, item.id)

View File

@@ -2,39 +2,43 @@ package org.jellyfin.androidtv.integration.dream
import android.annotation.SuppressLint
import android.content.Context
import androidx.core.graphics.drawable.toBitmap
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import coil.ImageLoader
import coil.request.ImageRequest
import coil3.ImageLoader
import coil3.request.ImageRequest
import coil3.toBitmap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.integration.dream.model.DreamContent
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.ui.playback.AudioEventListener
import org.jellyfin.androidtv.ui.playback.MediaManager
import org.jellyfin.androidtv.ui.playback.PlaybackController
import org.jellyfin.androidtv.util.apiclient.getUrl
import org.jellyfin.androidtv.util.apiclient.itemBackdropImages
import org.jellyfin.androidtv.util.apiclient.itemImages
import org.jellyfin.playback.core.PlaybackManager
import org.jellyfin.playback.core.queue.queue
import org.jellyfin.playback.jellyfin.queue.baseItem
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.exception.ApiClientException
import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.api.client.extensions.itemsApi
import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.ImageFormat
import org.jellyfin.sdk.model.api.ImageType
import org.jellyfin.sdk.model.api.ItemSortBy
import timber.log.Timber
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
@SuppressLint("StaticFieldLeak")
@@ -42,35 +46,18 @@ class DreamViewModel(
private val api: ApiClient,
private val imageLoader: ImageLoader,
private val context: Context,
private val mediaManager: MediaManager,
playbackManager: PlaybackManager,
private val userPreferences: UserPreferences,
) : ViewModel() {
private val _mediaContent = callbackFlow {
trySend(mediaManager.currentAudioItem)
val listener = object : AudioEventListener {
override fun onPlaybackStateChange(
newState: PlaybackController.PlaybackState,
currentItem: BaseItemDto?
) {
trySend(currentItem)
}
override fun onQueueStatusChanged(hasQueue: Boolean) {
trySend(mediaManager.currentAudioItem)
}
@OptIn(ExperimentalCoroutinesApi::class)
private val _mediaContent = playbackManager.queue.entry
.map { entry ->
entry
?.takeIf { it.visibleInScreensaver }
?.baseItem
?.let { baseItem -> DreamContent.NowPlaying(entry, baseItem) }
}
mediaManager.addAudioEventListener(listener)
awaitClose { mediaManager.removeAudioEventListener(listener) }
}
.distinctUntilChanged()
.map { it?.let(DreamContent::NowPlaying) }
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
DreamContent.NowPlaying(mediaManager.currentAudioItem)
)
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
private val _libraryContent = flow {
// Load first library item after 2 seconds
@@ -78,15 +65,19 @@ class DreamViewModel(
emit(null)
delay(2.seconds)
while (true) {
val next = getRandomLibraryShowcase()
if (next != null) {
emit(next)
delay(30.seconds)
} else {
delay(3.seconds)
}
}
val requireParentalRating = userPreferences[UserPreferences.screensaverAgeRatingRequired]
val maxParentalRating = userPreferences[UserPreferences.screensaverAgeRatingMax]
emitAll(
getRandomLibraryShowcaseItems(
requireParentalRating = requireParentalRating,
maxParentalRating = maxParentalRating,
// A batch size of 60 should be equal to 30 minutes of items
batchSize = 60,
emitDelay = 30.seconds,
noItemsDelay = 2.minutes,
errorDelay = 3.seconds,
)
)
}
.distinctUntilChanged()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
@@ -99,70 +90,71 @@ class DreamViewModel(
initialValue = _mediaContent.value ?: _libraryContent.value ?: DreamContent.Logo,
)
private suspend fun getRandomLibraryShowcase(): DreamContent.LibraryShowcase? {
val requireParentalRating = userPreferences[UserPreferences.screensaverAgeRatingRequired]
val maxParentalRating = userPreferences[UserPreferences.screensaverAgeRatingMax]
try {
val response by api.itemsApi.getItems(
includeItemTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.SERIES),
recursive = true,
sortBy = listOf(ItemSortBy.RANDOM),
limit = 5,
imageTypes = listOf(ImageType.BACKDROP),
maxOfficialRating = if (maxParentalRating == -1) null else maxParentalRating.toString(),
hasParentalRating = if (requireParentalRating) true else null,
)
val item = response.items?.firstOrNull { item ->
!item.backdropImageTags.isNullOrEmpty()
} ?: return null
Timber.i("Loading random library showcase item ${item.id}")
val backdropTag = item.backdropImageTags!!.randomOrNull()
?: item.imageTags?.get(ImageType.BACKDROP)
val logoTag = item.imageTags?.get(ImageType.LOGO)
val backdropUrl = api.imageApi.getItemImageUrl(
itemId = item.id,
imageType = ImageType.BACKDROP,
tag = backdropTag,
format = ImageFormat.WEBP,
)
val logoUrl = api.imageApi.getItemImageUrl(
itemId = item.id,
imageType = ImageType.LOGO,
tag = logoTag,
format = ImageFormat.WEBP,
)
val (logo, backdrop) = withContext(Dispatchers.IO) {
val logoDeferred = async {
imageLoader.execute(
request = ImageRequest.Builder(context).data(logoUrl).build()
).drawable?.toBitmap()
private fun getRandomLibraryShowcaseItems(
requireParentalRating: Boolean,
maxParentalRating: Int,
batchSize: Int,
emitDelay: Duration,
noItemsDelay: Duration,
errorDelay: Duration,
): Flow<DreamContent.LibraryShowcase?> = flow {
while (true) {
val items = try {
withContext(Dispatchers.IO) {
val response by api.itemsApi.getItems(
includeItemTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.SERIES),
recursive = true,
sortBy = listOf(ItemSortBy.RANDOM),
limit = batchSize,
imageTypes = listOf(ImageType.BACKDROP),
maxOfficialRating = if (maxParentalRating == -1) null else maxParentalRating.toString(),
hasParentalRating = if (requireParentalRating) true else null,
)
response.items
}
val backdropDeferred = async {
imageLoader.execute(
request = ImageRequest.Builder(context).data(backdropUrl).build()
).drawable?.toBitmap()
}
awaitAll(logoDeferred, backdropDeferred)
} catch (err: ApiClientException) {
Timber.e(err)
null
}
if (backdrop == null) {
return null
if (items == null) {
emit(null)
delay(errorDelay)
} else if (items.isEmpty()) {
emit(null)
delay(noItemsDelay)
} else {
for (item in items) {
if (item.itemBackdropImages.isEmpty()) continue
val showcase = item.asLibraryShowcase() ?: continue
emit(showcase)
delay(emitDelay)
}
}
return DreamContent.LibraryShowcase(item, backdrop, logo)
} catch (err: ApiClientException) {
Timber.e(err)
return null
}
}.cancellable()
private suspend fun BaseItemDto.asLibraryShowcase(): DreamContent.LibraryShowcase? = withContext(Dispatchers.IO) {
val logoUrl = itemImages[ImageType.LOGO]?.getUrl(api)
val backdropUrl = itemBackdropImages.randomOrNull()?.getUrl(api)
// Require a backdrop
if (backdropUrl == null) return@withContext null
// Only attempt to load logo if there is one, wrap in async {} to load it parallel with the backdrop
val logo = logoUrl?.let { url ->
async {
imageLoader.execute(
request = ImageRequest.Builder(context).data(url).build()
).image?.toBitmap()
}
}
val backdrop = imageLoader.execute(
request = ImageRequest.Builder(context).data(backdropUrl).build()
).image?.toBitmap()
if (backdrop == null) null
else DreamContent.LibraryShowcase(this@asLibraryShowcase, backdrop, logo?.await())
}
}

View File

@@ -0,0 +1,12 @@
package org.jellyfin.androidtv.integration.dream
import org.jellyfin.playback.core.element.ElementKey
import org.jellyfin.playback.core.element.requiredElement
import org.jellyfin.playback.core.queue.QueueEntry
private val visibleInScreensaverKey = ElementKey<Boolean>("visibleInScreensaver")
/**
* Get or set whether this [QueueEntry] is shown in the screensaver.
*/
var QueueEntry.visibleInScreensaver by requiredElement(visibleInScreensaverKey) { false }

View File

@@ -2,9 +2,10 @@ package org.jellyfin.androidtv.integration.dream.composable
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -14,10 +15,10 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.tv.material3.Text
import org.jellyfin.androidtv.integration.dream.model.DreamContent
import org.jellyfin.androidtv.ui.base.Text
import org.jellyfin.androidtv.ui.composable.ZoomBox
import org.jellyfin.androidtv.ui.composable.overscan
import org.jellyfin.androidtv.ui.composable.modifier.overscan
@Composable
fun DreamContentLibraryShowcase(
@@ -50,12 +51,17 @@ fun DreamContentLibraryShowcase(
.overscan(),
) {
if (content.logo != null) {
Image(
bitmap = content.logo.asImageBitmap(),
contentDescription = content.item.name,
modifier = Modifier
.height(75.dp)
)
BoxWithConstraints {
Image(
bitmap = content.logo.asImageBitmap(),
contentDescription = content.item.name,
modifier = Modifier
.sizeIn(
maxWidth = maxWidth * 0.35f,
maxHeight = 75.dp
)
)
}
} else {
Text(
text = content.item.name.orEmpty(),

View File

@@ -14,36 +14,39 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.tv.material3.Text
import org.jellyfin.androidtv.integration.dream.model.DreamContent
import org.jellyfin.androidtv.ui.base.SeekbarDefaults
import org.jellyfin.androidtv.ui.base.Text
import org.jellyfin.androidtv.ui.composable.AsyncImage
import org.jellyfin.androidtv.ui.composable.LyricsDtoBox
import org.jellyfin.androidtv.ui.composable.blurHashPainter
import org.jellyfin.androidtv.ui.composable.overscan
import org.jellyfin.androidtv.ui.playback.AudioEventListener
import org.jellyfin.androidtv.ui.playback.MediaManager
import org.jellyfin.androidtv.ui.composable.modifier.fadingEdges
import org.jellyfin.androidtv.ui.composable.modifier.overscan
import org.jellyfin.androidtv.ui.composable.rememberPlayerProgress
import org.jellyfin.androidtv.ui.player.base.PlayerSeekbar
import org.jellyfin.androidtv.util.apiclient.albumPrimaryImage
import org.jellyfin.androidtv.util.apiclient.getUrl
import org.jellyfin.androidtv.util.apiclient.itemImages
import org.jellyfin.androidtv.util.apiclient.parentImages
import org.jellyfin.playback.core.PlaybackManager
import org.jellyfin.playback.core.model.PlayState
import org.jellyfin.playback.jellyfin.lyrics.lyrics
import org.jellyfin.playback.jellyfin.lyrics.lyricsFlow
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.model.api.ImageFormat
import org.jellyfin.sdk.model.api.ImageType
import org.jellyfin.sdk.model.extensions.ticks
import org.koin.compose.koinInject
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
@Composable
fun DreamContentNowPlaying(
@@ -52,21 +55,17 @@ fun DreamContentNowPlaying(
modifier = Modifier.fillMaxSize(),
) {
val api = koinInject<ApiClient>()
val mediaManager = koinInject<MediaManager>()
val item = content.item ?: return@Box
val playbackManager = koinInject<PlaybackManager>()
val lyrics = content.entry.run { lyricsFlow.collectAsState(lyrics) }.value
val primaryImageTag = item.imageTags?.get(ImageType.PRIMARY)
val (imageItemId, imageTag) = when {
primaryImageTag != null -> item.id to primaryImageTag
(item.albumId != null && item.albumPrimaryImageTag != null) -> item.albumId to item.albumPrimaryImageTag
else -> null to null
}
val primaryImage = content.item.itemImages[ImageType.PRIMARY]
?: content.item.albumPrimaryImage
?: content.item.parentImages[ImageType.PRIMARY]
val imageBlurHash =
imageTag?.let { tag -> item.imageBlurHashes?.get(ImageType.PRIMARY)?.get(tag) }
if (imageBlurHash != null) {
// Background
if (primaryImage?.blurHash != null) {
Image(
painter = blurHashPainter(imageBlurHash, IntSize(32, 32)),
painter = blurHashPainter(primaryImage.blurHash, IntSize(32, 32)),
contentDescription = null,
alignment = Alignment.Center,
contentScale = ContentScale.Crop,
@@ -76,7 +75,29 @@ fun DreamContentNowPlaying(
DreamContentVignette()
}
// Overlay
// Lyrics overlay (on top of background)
if (lyrics != null) {
val playState by remember { playbackManager.state.playState }.collectAsState()
// Using the progress animation causes the layout to recompose, which we need for synced lyrics to work
// we don't actually use the animation value here
rememberPlayerProgress(playbackManager)
LyricsDtoBox(
lyricDto = lyrics,
currentTimestamp = playbackManager.state.positionInfo.active,
duration = playbackManager.state.positionInfo.duration,
paused = playState != PlayState.PLAYING,
fontSize = 22.sp,
color = Color.White,
modifier = Modifier
.fillMaxSize()
.fadingEdges(vertical = 250.dp)
.padding(horizontal = 50.dp),
)
}
// Metadata overlay (includes title / progress)
Row(
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.spacedBy(20.dp),
@@ -84,15 +105,10 @@ fun DreamContentNowPlaying(
.align(Alignment.BottomStart)
.overscan(),
) {
if (imageItemId != null) {
if (primaryImage != null) {
AsyncImage(
url = api.imageApi.getItemImageUrl(
itemId = imageItemId,
imageType = ImageType.PRIMARY,
tag = imageTag,
format = ImageFormat.WEBP,
),
blurHash = imageBlurHash,
url = primaryImage.getUrl(api),
blurHash = primaryImage.blurHash,
scaleType = ImageView.ScaleType.CENTER_CROP,
modifier = Modifier
.size(128.dp)
@@ -105,7 +121,7 @@ fun DreamContentNowPlaying(
.padding(bottom = 10.dp)
) {
Text(
text = item.name.orEmpty(),
text = content.item.name.orEmpty(),
style = TextStyle(
color = Color.White,
fontSize = 26.sp,
@@ -113,7 +129,7 @@ fun DreamContentNowPlaying(
)
Text(
text = item.run {
text = content.item.run {
val artistNames = artists.orEmpty()
val albumArtistNames = albumArtists?.mapNotNull { it.name }.orEmpty()
@@ -131,33 +147,16 @@ fun DreamContentNowPlaying(
Spacer(modifier = Modifier.height(10.dp))
var progress by remember { mutableFloatStateOf(0f) }
DisposableEffect(Unit) {
val listener = object : AudioEventListener {
override fun onProgress(pos: Long) {
val duration = item.runTimeTicks?.ticks ?: Duration.ZERO
progress = (pos.milliseconds / duration).toFloat()
}
}
mediaManager.addAudioEventListener(listener)
onDispose {
mediaManager.removeAudioEventListener(listener)
}
}
Box(
PlayerSeekbar(
playbackManager = playbackManager,
colors = SeekbarDefaults.colors(
backgroundColor = Color.White.copy(alpha = 0.2f),
progressColor = Color.White,
bufferColor = Color.Transparent,
),
modifier = Modifier
.fillMaxWidth()
.height(4.dp)
.clip(RoundedCornerShape(2.dp))
.drawWithContent {
// Background
drawRect(Color.White, alpha = 0.2f)
// Foreground
drawRect(Color.White, size = size.copy(width = size.width * progress))
}
)
}
}

View File

@@ -1,72 +1,32 @@
package org.jellyfin.androidtv.integration.dream.composable
import android.text.format.DateUtils
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.tv.material3.Text
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.ui.composable.overscan
import org.jellyfin.androidtv.ui.composable.rememberCurrentTime
import org.jellyfin.androidtv.ui.composable.modifier.overscan
import org.jellyfin.androidtv.ui.shared.toolbar.ToolbarClock
@Composable
fun DreamHeader(
showLogo: Boolean,
showClock: Boolean,
) = Box(
modifier = Modifier
.fillMaxWidth()
.overscan(),
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
// Clock
AnimatedVisibility(
visible = showClock,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
.fillMaxWidth()
.overscan(),
.align(Alignment.TopEnd),
) {
// Logo
AnimatedVisibility(
visible = showLogo,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier.height(41.dp),
) {
Image(
painter = painterResource(R.drawable.app_logo),
contentDescription = stringResource(R.string.app_name),
)
}
Spacer(
modifier = Modifier
.fillMaxWidth(0f)
)
// Clock
AnimatedVisibility(
visible = showClock,
enter = fadeIn(),
exit = fadeOut(),
) {
val time = rememberCurrentTime()
Text(
text = DateUtils.formatDateTime(LocalContext.current, time, DateUtils.FORMAT_SHOW_TIME),
style = TextStyle(
color = Color.White,
fontSize = 20.sp
),
)
}
ToolbarClock()
}
}

View File

@@ -36,7 +36,6 @@ fun DreamView(
// Header overlay
DreamHeader(
showLogo = content != DreamContent.Logo,
showClock = showClock,
)
}

View File

@@ -1,10 +1,11 @@
package org.jellyfin.androidtv.integration.dream.model
import android.graphics.Bitmap
import org.jellyfin.playback.core.queue.QueueEntry
import org.jellyfin.sdk.model.api.BaseItemDto
sealed interface DreamContent {
data object Logo : DreamContent
data class LibraryShowcase(val item: BaseItemDto, val backdrop: Bitmap, val logo: Bitmap?) : DreamContent
data class NowPlaying(val item: BaseItemDto?) : DreamContent
data class NowPlaying(val entry: QueueEntry, val item: BaseItemDto) : DreamContent
}

View File

@@ -9,8 +9,10 @@ import android.os.Build
import android.os.ParcelFileDescriptor
import androidx.core.graphics.drawable.toBitmap
import androidx.core.net.toUri
import coil.ImageLoader
import coil.request.ImageRequest
import coil3.ImageLoader
import coil3.asDrawable
import coil3.request.ImageRequest
import coil3.request.error
import org.jellyfin.androidtv.BuildConfig
import org.jellyfin.androidtv.R
import org.koin.android.ext.android.inject
@@ -37,8 +39,8 @@ class ImageProvider : ContentProvider() {
data(src)
error(R.drawable.placeholder_icon)
target(
onSuccess = { drawable -> writeDrawable(drawable, outputStream) },
onError = { drawable -> writeDrawable(requireNotNull(drawable), outputStream) }
onSuccess = { image -> writeDrawable(image.asDrawable(context!!.resources), outputStream) },
onError = { image -> writeDrawable(requireNotNull(image?.asDrawable(context!!.resources)), outputStream) }
)
}.build())

View File

@@ -1,21 +1,27 @@
package org.jellyfin.androidtv.preference
import android.content.Context
import android.view.KeyEvent
import androidx.preference.PreferenceManager
import org.jellyfin.androidtv.preference.UserPreferences.Companion.screensaverInAppEnabled
import org.jellyfin.androidtv.preference.constant.AppTheme
import org.jellyfin.androidtv.preference.constant.AudioBehavior
import org.jellyfin.androidtv.preference.constant.BackdropBehavior
import org.jellyfin.androidtv.preference.constant.ClockBehavior
import org.jellyfin.androidtv.preference.constant.NextUpBehavior
import org.jellyfin.androidtv.preference.constant.RatingType
import org.jellyfin.androidtv.preference.constant.RefreshRateSwitchingBehavior
import org.jellyfin.androidtv.preference.constant.StillWatchingBehavior
import org.jellyfin.androidtv.preference.constant.WatchedIndicatorBehavior
import org.jellyfin.androidtv.preference.constant.ZoomMode
import org.jellyfin.androidtv.ui.playback.segment.MediaSegmentAction
import org.jellyfin.androidtv.ui.playback.segment.toMediaSegmentActionsString
import org.jellyfin.preference.booleanPreference
import org.jellyfin.preference.enumPreference
import org.jellyfin.preference.floatPreference
import org.jellyfin.preference.intPreference
import org.jellyfin.preference.longPreference
import org.jellyfin.preference.store.SharedPreferenceStore
import org.jellyfin.preference.stringPreference
import org.jellyfin.sdk.model.api.MediaSegmentType
import kotlin.time.Duration.Companion.minutes
/**
@@ -35,19 +41,9 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
var appTheme = enumPreference("app_theme", AppTheme.DARK)
/**
* Enable background images while browsing
* Behavior of app background while browsing
*/
var backdropEnabled = booleanPreference("pref_show_backdrop", true)
/**
* Show premieres on home screen
*/
var premieresEnabled = booleanPreference("pref_enable_premieres", false)
/**
* Enable management of media like deleting items when the user has sufficient permisisons.
*/
var mediaManagementEnabled = booleanPreference("enable_media_management", false)
var backdropBehavior = enumPreference("backdrop_behavior", BackdropBehavior.BACKDROP_WITH_BLUR)
/* Playback - General*/
/**
@@ -81,22 +77,37 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
*/
var cinemaModeEnabled = booleanPreference("pref_enable_cinema_mode", true)
/**
* Enable still watching
*/
var stillWatchingBehavior = enumPreference("enable_still_watching", StillWatchingBehavior.DISABLED)
/* Playback - Video */
/**
* Whether to use an external playback application or not.
*/
var useExternalPlayer = booleanPreference("external_player", false)
/**
* Component name for the external playback application.
*/
var externalPlayerComponentName = stringPreference("external_player_component", "")
/**
* Change refresh rate to match media when device supports it
*/
var refreshRateSwitchingBehavior = enumPreference("refresh_rate_switching_behavior", RefreshRateSwitchingBehavior.DISABLED)
/**
* Whether ExoPlayer should prefer FFmpeg renderers to core ones.
*/
var preferExoPlayerFfmpeg = booleanPreference("exoplayer_prefer_ffmpeg", defaultValue = false)
/* Playback - Audio related */
/**
* Preferred behavior for audio streaming.
*/
var audioBehaviour = enumPreference("audio_behavior", AudioBehavior.DOWNMIX_TO_STEREO)
var audioBehaviour = enumPreference("audio_behavior", AudioBehavior.DIRECT_STREAM)
/**
* Preferred behavior for audio streaming.
@@ -114,16 +125,6 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
*/
var liveTvDirectPlayEnabled = booleanPreference("pref_live_direct", true)
/**
* Shortcut used for changing the audio track
*/
var shortcutAudioTrack = intPreference("shortcut_audio_track", KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK)
/**
* Shortcut used for changing the subtitle track
*/
var shortcutSubtitleTrack = intPreference("shortcut_subtitle_track", KeyEvent.KEYCODE_CAPTIONS)
/* Developer options */
/**
* Show additional debug information
@@ -140,11 +141,6 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
*/
var clockBehavior = enumPreference("pref_clock_behavior", ClockBehavior.ALWAYS)
/**
* Set which ratings provider should show on MyImageCardViews
*/
var defaultRatingType = enumPreference("pref_rating_type", RatingType.RATING_TOMATOES)
/**
* Set when watched indicators should show on MyImageCardViews
*/
@@ -156,30 +152,35 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
var seriesThumbnailsEnabled = booleanPreference("pref_enable_series_thumbnails", true)
/**
* Enable subtitles background
* Subtitles foreground color
*/
var subtitlesBackgroundEnabled = booleanPreference("subtitles_background_enabled", true)
var subtitlesBackgroundColor = longPreference("subtitles_background_color", 0x00FFFFFF)
/**
* Subtitles font size
* Subtitles bold text
*/
var subtitlesSize = intPreference("subtitles_size", 28)
/**
* Subtitles stroke size
*/
var subtitleStrokeSize = intPreference("subtitles_stroke_size", 0)
/**
* Subtitles position
*/
var subtitlePosition = intPreference("subtitles_position", 40)
var subtitlesTextWeight = intPreference("subtitles_text_weight", 400)
/**
* Subtitles foreground color
*/
var subtitlesTextColor = longPreference("subtitles_text_color", 0xFFFFFFFF)
/**
* Subtitles stroke color
*/
var subtitleTextStrokeColor = longPreference("subtitles_text_stroke_color", 0xFF000000)
/**
* Subtitles font size
*/
var subtitlesTextSize = floatPreference("subtitles_text_size", 24f)
/**
* Subtitles offset
*/
var subtitlesOffsetPosition = floatPreference("subtitles_offset_position", 0.08f)
/**
* Show screensaver in app
*/
@@ -201,9 +202,40 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
var screensaverAgeRatingRequired = booleanPreference("screensaver_agerating_required", true)
/**
* Enable reactive homepage
* Delay when starting video playback after loading the video player.
*/
var homeReactive = booleanPreference("home_reactive", false)
var videoStartDelay = longPreference("video_start_delay", 0)
/**
* The actions to take for each media segment type. Managed by the [MediaSegmentRepository].
*/
var mediaSegmentActions = stringPreference(
key = "media_segment_actions",
defaultValue = mapOf(
MediaSegmentType.INTRO to MediaSegmentAction.ASK_TO_SKIP,
MediaSegmentType.OUTRO to MediaSegmentAction.ASK_TO_SKIP,
).toMediaSegmentActionsString()
)
/**
* Preferred behavior for player aspect ratio (zoom mode).
*/
var playerZoomMode = enumPreference("player_zoom_mode", ZoomMode.FIT)
/**
* Enable TrickPlay in legacy player user interface while seeking.
*/
var trickPlayEnabled = booleanPreference("trick_play_enabled", false)
/**
* Enable libass.
*/
var assDirectPlay = booleanPreference("libass_enabled", false)
/**
* Enable PGS subtitle direct-play.
*/
var pgsDirectPlay = booleanPreference("pgs_enabled", true)
}
init {
@@ -216,6 +248,30 @@ class UserPreferences(context: Context) : SharedPreferenceStore(
// Enable playback rewrite for music
putBoolean("playback_new_audio", true)
}
// v0.17.z to v0.18.0
migration(toVersion = 8) {
// Set subtitle background color to black if it was enabled in a previous version
val subtitlesBackgroundEnabled = it.getBoolean("subtitles_background_enabled", true)
putLong("subtitles_background_color", if (subtitlesBackgroundEnabled) 0XFF000000L else 0X00FFFFFFL)
// Set subtitle text stroke color to black if it was enabled in a previous version
val subtitleStrokeSize = it.getInt("subtitles_stroke_size", 0)
putLong("subtitles_text_stroke_color", if (subtitleStrokeSize > 0) 0XFF000000L else 0X00FFFFFFL)
}
// v0.19.0 to v0.20.0
migration(toVersion = 9) {
// Reset subtitle text size as we changed from fractional sizing to absolute sizing
remove("subtitles_text_size")
// Set the BackdropBehavior if it was enabled in a previous version
val backdropEnabled = it.getBoolean("pref_show_backdrop", true)
putString(
"backdrop_behavior",
if (backdropEnabled) BackdropBehavior.BACKDROP_WITH_BLUR.name else BackdropBehavior.DISABLED.name
)
}
}
}
}

View File

@@ -24,10 +24,26 @@ class UserSettingPreferences(
val homesection4 = enumPreference("homesection4", HomeSectionType.LIVE_TV)
val homesection5 = enumPreference("homesection5", HomeSectionType.NEXT_UP)
val homesection6 = enumPreference("homesection6", HomeSectionType.LATEST_MEDIA)
val homesection7 = enumPreference("homesection7", HomeSectionType.NONE)
val homesection8 = enumPreference("homesection8", HomeSectionType.NONE)
val homesection9 = enumPreference("homesection9", HomeSectionType.NONE)
}
val homesections
get() = listOf(homesection0, homesection1, homesection2, homesection3, homesection4, homesection5, homesection6)
val homesections = listOf(
homesection0,
homesection1,
homesection2,
homesection3,
homesection4,
homesection5,
homesection6,
homesection7,
homesection8,
homesection9,
)
val activeHomesections
get() = homesections
.map(::get)
.filterNot { it == HomeSectionType.NONE }
}

View File

@@ -0,0 +1,20 @@
package org.jellyfin.androidtv.preference.constant
import org.jellyfin.androidtv.R
import org.jellyfin.preference.PreferenceEnum
enum class BackdropBehavior(
override val nameRes: Int,
) : PreferenceEnum {
DISABLED(R.string.state_disabled),
/**
* When selected, backdrop is shown with a blur effect.
*/
BACKDROP_WITH_BLUR(R.string.backdrop_behavior_with_blur),
/**
* When selected, backdrop is shown without any blur effect.
*/
BACKDROP_WITHOUT_BLUR(R.string.backdrop_behavior_without_blur),
}

View File

@@ -1,23 +0,0 @@
package org.jellyfin.androidtv.preference.constant
import org.jellyfin.androidtv.R
import org.jellyfin.preference.PreferenceEnum
enum class RatingType(
override val nameRes: Int,
) : PreferenceEnum {
/**
* Sets default rating type to tomatoes.
*/
RATING_TOMATOES(R.string.lbl_tomatoes),
/**
* Sets the default rating type to stars.
*/
RATING_STARS(R.string.lbl_stars),
/**
* Sets the default rating type to hidden.
*/
RATING_HIDDEN(R.string.lbl_hidden),
}

View File

@@ -0,0 +1,63 @@
package org.jellyfin.androidtv.preference.constant
import org.jellyfin.androidtv.R
import org.jellyfin.preference.PreferenceEnum
import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
enum class StillWatchingBehavior(
override val nameRes: Int,
val enabled: Boolean,
val episodeCount: Int,
val minDuration: Duration,
) : PreferenceEnum {
/**
* Shorter than default. Show screen at 2 episodes or 60 minutes of uninterrupted watch time.
*/
SHORT(
nameRes = R.string.lbl_still_watching_short,
enabled = true,
episodeCount = 2,
minDuration = 1.hours,
),
/**
* Default behavior for still watching. Show screen at 3 episodes or 90 minutes of uninterrupted watch time.
*/
DEFAULT(
nameRes = R.string.lbl_still_watching_default,
enabled = true,
episodeCount = 3,
minDuration = 1.5.hours,
),
/**
* Longer than default. Show screen at 5 episodes or 150 minutes of uninterrupted watch time.
*/
LONG(
nameRes = R.string.lbl_still_watching_long,
enabled = true,
episodeCount = 5,
minDuration = 2.5.hours,
),
/**
* Much longer than default. Show screen at 8 episodes or 240 minutes of uninterrupted watch time.
*/
VERY_LONG(
nameRes = R.string.lbl_still_watching_very_long,
enabled = true,
episodeCount = 8,
minDuration = 4.hours,
),
/**
* Disables still watching screen.
*/
DISABLED(
nameRes = R.string.state_disabled,
enabled = false,
episodeCount = 0,
minDuration = Duration.ZERO,
)
}

View File

@@ -0,0 +1,24 @@
package org.jellyfin.androidtv.preference.constant
import org.jellyfin.androidtv.R
import org.jellyfin.preference.PreferenceEnum
enum class ZoomMode(
override val nameRes: Int,
) : PreferenceEnum {
/**
* Sets the zoom mode to normal (fit).
*/
FIT(R.string.lbl_fit),
/**
* Sets the zoom mode to auto crop.
*/
AUTO_CROP(R.string.lbl_auto_crop),
/**
* Sets the zoom mode to stretch.
*/
STRETCH(R.string.lbl_stretch),
}

View File

@@ -1,5 +1,7 @@
package org.jellyfin.androidtv.preference.store
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jellyfin.preference.Preference
import org.jellyfin.preference.PreferenceEnum
import org.jellyfin.preference.migration.MigrationContext
@@ -56,10 +58,12 @@ abstract class DisplayPreferencesStore(
override suspend fun update(): Boolean {
try {
val result by api.displayPreferencesApi.getDisplayPreferences(
displayPreferencesId = displayPreferencesId,
client = app
)
val result = withContext(Dispatchers.IO) {
api.displayPreferencesApi.getDisplayPreferences(
displayPreferencesId = displayPreferencesId,
client = app
).content
}
displayPreferencesDto = result
cachedPreferences = result.customPrefs.toMutableMap()
@@ -82,6 +86,9 @@ abstract class DisplayPreferencesStore(
override fun getLong(key: String, defaultValue: Long) =
cachedPreferences[key]?.toLongOrNull() ?: defaultValue
override fun getFloat(key: String, defaultValue: Float) =
cachedPreferences[key]?.toFloatOrNull() ?: defaultValue
override fun getBool(key: String, defaultValue: Boolean) =
cachedPreferences[key]?.toBooleanStrictOrNull() ?: defaultValue
@@ -96,6 +103,10 @@ abstract class DisplayPreferencesStore(
cachedPreferences[key] = value.toString()
}
override fun setFloat(key: String, value: Float) {
cachedPreferences[key] = value.toString()
}
override fun setBool(key: String, value: Boolean) {
cachedPreferences[key] = value.toString()
}

View File

@@ -18,6 +18,11 @@ import org.acra.sender.ReportSenderFactory
import org.jellyfin.androidtv.BuildConfig
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.preference.TelemetryPreferences
import org.jellyfin.androidtv.util.appendCodeBlock
import org.jellyfin.androidtv.util.appendItem
import org.jellyfin.androidtv.util.appendSection
import org.jellyfin.androidtv.util.appendValue
import org.jellyfin.androidtv.util.buildMarkdown
import org.jellyfin.sdk.api.client.util.AuthorizationHeaderBuilder
import java.net.HttpURLConnection
import java.net.URL
@@ -63,8 +68,12 @@ object TelemetryService {
// Create connection
val connection = URL(url).openConnection() as HttpURLConnection
// Add authorization
val clientName = buildString {
append("Jellyfin Android TV")
if (BuildConfig.DEBUG) append(" (debug)")
}
val authorization = AuthorizationHeaderBuilder.buildHeader(
clientName = BuildConfig.APPLICATION_ID,
clientName = clientName,
clientVersion = BuildConfig.VERSION_NAME,
deviceId = "",
deviceName = "",
@@ -85,31 +94,7 @@ object TelemetryService {
throw ReportSenderException("Unable to send crash report to server", e)
}
private fun StringBuilder.appendSection(name: String, content: StringBuilder.() -> Unit) {
appendLine("### $name")
appendLine()
content()
appendLine()
}
private fun StringBuilder.appendItem(name: String, value: StringBuilder.() -> Unit) {
append("***$name***: ")
value()
appendLine(" ")
}
private fun StringBuilder.appendCodeBlock(language: String, code: String?) {
appendLine()
appendLine("```$language")
appendLine(code ?: "<null>")
append("```")
}
private fun StringBuilder.appendValue(value: String?) {
append("`", value ?: "<null>", "`")
}
private fun CrashReportData.toReport(): String = buildString {
private fun CrashReportData.toReport(): String = buildMarkdown {
// Header
appendLine("---")
appendLine("client: Jellyfin for Android TV")
@@ -118,6 +103,7 @@ object TelemetryService {
appendLine("type: crash_report")
appendLine("format: markdown")
appendLine("---")
appendLine()
// Content
appendSection("Logs") {

View File

@@ -1,18 +1,25 @@
package org.jellyfin.androidtv.ui
import android.app.ActivityManager
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.widget.ImageView
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toDrawable
import androidx.core.view.doOnAttach
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.lifecycleScope
import coil.ImageLoader
import coil.request.ImageRequest
import coil.transform.CircleCropTransformation
import coil3.ImageLoader
import coil3.asImage
import coil3.request.ImageRequest
import coil3.request.crossfade
import coil3.request.target
import coil3.request.transformations
import coil3.transform.CircleCropTransformation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.R
@@ -35,6 +42,7 @@ class AsyncImageView @JvmOverloads constructor(
private val lifeCycleOwner get() = findViewTreeLifecycleOwner()
private val styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.AsyncImageView, defStyleAttr, 0)
private val imageLoader by inject<ImageLoader>()
private var loadJob: Job? = null
/**
* The duration of the crossfade when changing switching the images of the url, blurhash and
@@ -60,11 +68,15 @@ class AsyncImageView @JvmOverloads constructor(
aspectRatio: Double = 1.0,
blurHashResolution: Int = 32,
) = doOnAttach {
lifeCycleOwner?.lifecycleScope?.launch {
// Cancel the previous load if still running
loadJob?.cancel()
loadJob = lifeCycleOwner?.lifecycleScope?.launch(Dispatchers.IO) {
var placeholderOrBlurHash = placeholder
// Only show blurhash if an image is going to be loaded from the network
if (url != null && blurHash != null) withContext(Dispatchers.IO) {
val isLowRamDevice = context.getSystemService<ActivityManager>()?.isLowRamDevice == true
if (url != null && blurHash != null && !isLowRamDevice) withContext(Dispatchers.IO) {
val blurHashBitmap = BlurHashDecoder.decode(
blurHash,
if (aspectRatio > 1) round(blurHashResolution * aspectRatio).toInt() else blurHashResolution,
@@ -74,25 +86,27 @@ class AsyncImageView @JvmOverloads constructor(
}
// Start loading image or placeholder
if (url == null) {
imageLoader.enqueue(ImageRequest.Builder(context).apply {
val request = if (url == null) {
ImageRequest.Builder(context).apply {
target(this@AsyncImageView)
data(placeholder)
if (circleCrop) transformations(CircleCropTransformation())
}.build())
}.build()
} else {
imageLoader.enqueue(ImageRequest.Builder(context).apply {
ImageRequest.Builder(context).apply {
val crossFadeDurationMs = crossFadeDuration.inWholeMilliseconds.toInt()
if (crossFadeDurationMs > 0) crossfade(crossFadeDurationMs)
else crossfade(false)
target(this@AsyncImageView)
data(url)
placeholder(placeholderOrBlurHash)
placeholder(placeholderOrBlurHash?.asImage())
if (circleCrop) transformations(CircleCropTransformation())
error(placeholder)
}.build())
error(placeholder?.asImage())
}.build()
}
imageLoader.enqueue(request).job.await()
}
}
}

View File

@@ -4,16 +4,12 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.RelativeLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.auth.repository.UserRepository
import org.jellyfin.androidtv.databinding.ClockUserBugBinding
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.preference.constant.ClockBehavior
import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.util.ImageHelper
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
@@ -25,9 +21,7 @@ class ClockUserView @JvmOverloads constructor(
) : RelativeLayout(context, attrs, defStyleAttr, defStyleRes), KoinComponent {
private val binding: ClockUserBugBinding = ClockUserBugBinding.inflate(LayoutInflater.from(context), this, true)
private val userPreferences by inject<UserPreferences>()
private val userRepository by inject<UserRepository>()
private val navigationRepository by inject<NavigationRepository>()
private val imageHelper by inject<ImageHelper>()
var isVideoPlayer = false
set(value) {
@@ -40,15 +34,6 @@ class ClockUserView @JvmOverloads constructor(
init {
updateClockVisibility()
val currentUser = userRepository.currentUser.value
binding.clockUserImage.load(
url = currentUser?.let(imageHelper::getPrimaryImageUrl),
placeholder = ContextCompat.getDrawable(context, R.drawable.ic_user)
)
binding.clockUserImage.isVisible = currentUser != null
binding.home.setOnClickListener {
navigationRepository.reset(Destinations.home, clearHistory = true)
}

View File

@@ -1,61 +0,0 @@
package org.jellyfin.androidtv.ui
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.animation.AlphaAnimation
import android.widget.FrameLayout
import androidx.annotation.IntRange
class FadeViewSwitcherLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0,
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
companion object {
const val VIEW_NONE = -1
}
private var currentView = VIEW_NONE
private val nextViewId
get() = if (currentView >= childCount - 1) 0 else currentView + 1
private val previousViewId
get() = if (currentView <= 0) childCount - 1 else currentView - 1
override fun onViewAdded(child: View?) {
super.onViewAdded(child)
// Hide new views by default
child?.alpha = 0f
}
fun showNextView() = showView(nextViewId)
fun showPreviousView() = showView(previousViewId)
fun hideAllViews() = showView(VIEW_NONE)
fun <V : View> getNextView() = getChildAt(nextViewId) as V
fun <V : View> getCurrentView() = if (currentView == VIEW_NONE) null else currentView as V
fun <V : View> getPreviousView() = getChildAt(previousViewId) as V
fun showView(@IntRange(from = -1) view: Int) {
// TODO: right now crossfades, need to be smarter to hide old view after new view is completely visible
if (currentView != VIEW_NONE) getChildAt(currentView).fadeOut()
if (view != VIEW_NONE) getChildAt(view).fadeIn()
currentView = view
}
private fun View.fadeIn() {
alpha = 1f
startAnimation(AlphaAnimation(0f, 1f).apply {
duration = 1_000
fillAfter = true
})
}
private fun View.fadeOut() = startAnimation(AlphaAnimation(1f, 0f).apply {
duration = 1_000
fillAfter = true
})
}

View File

@@ -0,0 +1,160 @@
package org.jellyfin.androidtv.ui
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.jellyfin.androidtv.preference.UserPreferences
import org.jellyfin.androidtv.ui.playback.PlaybackControllerContainer
import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
class InteractionTrackerViewModel(
private val userPreferences: UserPreferences,
private val playbackControllerContainer: PlaybackControllerContainer
) : ViewModel() {
// Screensaver
private var timer: Job? = null
private var locks = 0
// Still Watching
private var isWatchingEpisodes = false
private var episodeCount = 0
private var watchTime = 0L
private var episodeWasInterrupted: Boolean = false
// Preferences
private val inAppEnabled get() = userPreferences[UserPreferences.screensaverInAppEnabled]
private val timeout get() = userPreferences[UserPreferences.screensaverInAppTimeout].milliseconds
private val stillWatchingBehavior get() = userPreferences[UserPreferences.stillWatchingBehavior]
// State
private val _screensaverVisible = MutableStateFlow(false)
val visible get() = _screensaverVisible.asStateFlow()
private val _keepScreenOn = MutableStateFlow(inAppEnabled)
val keepScreenOn get() = _keepScreenOn.asStateFlow()
var activityPaused: Boolean = false
set(value) {
field = value
notifyInteraction(canCancel = true, userInitiated = false)
}
init {
notifyInteraction(canCancel = true, userInitiated = false)
}
fun getShowStillWatching(): Boolean {
if (!stillWatchingBehavior.enabled) return false
if (stillWatchingBehavior.episodeCount > 0 && episodeCount >= stillWatchingBehavior.episodeCount) return true
if (stillWatchingBehavior.minDuration > Duration.ZERO && watchTime.milliseconds >= stillWatchingBehavior.minDuration) return true
return false
}
fun notifyStartSession(item: BaseItemDto, items: List<BaseItemDto>) {
// No need to track when only watching 1 episode
if (item.type == BaseItemKind.EPISODE && items.size > 1) {
resetSession()
episodeWasInterrupted = false
}
}
fun notifyStillWatching() {
resetSession()
}
fun onEpisodeWatched() {
if (!episodeWasInterrupted) episodeCount++
watchTime += playbackControllerContainer.playbackController?.duration ?: 0
episodeWasInterrupted = false
}
fun notifyStart(item: BaseItemDto) {
if (item.type == BaseItemKind.EPISODE) isWatchingEpisodes = true
}
fun notifyInteraction(canCancel: Boolean, userInitiated: Boolean) {
// Cancel pending screensaver timer (if any)
timer?.cancel()
// If watching episodes, reset episode count and watch time
if (isWatchingEpisodes && userInitiated) {
resetSession()
episodeWasInterrupted = true
}
// Hide screensaver when interacted with allowed cancellation or when disabled
if (_screensaverVisible.value && (canCancel || !inAppEnabled || activityPaused)) {
_screensaverVisible.value = false
}
// Create new timer to show screensaver when enabled
if (inAppEnabled && !activityPaused && locks == 0) {
timer = viewModelScope.launch {
delay(timeout)
_screensaverVisible.value = true
}
}
// Update KEEP_SCREEN_ON flag value
_keepScreenOn.value = inAppEnabled || locks > 0
}
/**
* Create a lock that prevents the screensaver for running until the returned function is called
* or the lifecycle is destroyed.
*
* @return Function to cancel the lock
*/
fun addLifecycleLock(lifecycle: Lifecycle): () -> Unit {
if (lifecycle.currentState == Lifecycle.State.DESTROYED) return {}
val lock = ScreensaverLock(lifecycle)
lock.activate()
return lock::cancel
}
private inner class ScreensaverLock(private val lifecycle: Lifecycle) : LifecycleEventObserver {
private var active: Boolean = false
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_DESTROY) cancel()
}
fun activate() {
if (active) return
lifecycle.addObserver(this)
locks++
notifyInteraction(canCancel = true, userInitiated = false)
active = true
}
fun cancel() {
if (!active) return
locks--
lifecycle.removeObserver(this)
notifyInteraction(canCancel = false, userInitiated = false)
active = false
}
}
private fun resetSession() {
watchTime = 0L
episodeCount = 0
}
}

View File

@@ -2,27 +2,24 @@ package org.jellyfin.androidtv.ui
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.data.repository.ItemRepository
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.itemsApi
import org.jellyfin.sdk.model.api.ItemFields
import org.koin.java.KoinJavaComponent
fun ItemListView.refresh() {
val api by KoinJavaComponent.inject<ApiClient>(ApiClient::class.java)
findViewTreeLifecycleOwner()?.lifecycleScope?.launch {
val response by api.itemsApi.getItems(
ids = mItemIds,
fields = setOf(
ItemFields.PRIMARY_IMAGE_ASPECT_RATIO,
ItemFields.OVERVIEW,
ItemFields.ITEM_COUNTS,
ItemFields.DISPLAY_PREFERENCES_ID,
ItemFields.CHILD_COUNT,
ItemFields.MEDIA_SOURCES,
)
)
val response = withContext(Dispatchers.IO) {
api.itemsApi.getItems(
ids = mItemIds,
fields = ItemRepository.itemFields
).content
}
response.items?.forEachIndexed { index, item ->
val view = mList.getChildAt(index)

View File

@@ -24,7 +24,7 @@ import org.jellyfin.androidtv.data.model.DataRefreshService;
import org.jellyfin.androidtv.ui.livetv.LiveTvGuide;
import org.jellyfin.androidtv.ui.livetv.TvManager;
import org.jellyfin.androidtv.util.Utils;
import org.jellyfin.androidtv.util.apiclient.EmptyLifecycleAwareResponse;
import org.jellyfin.androidtv.util.apiclient.EmptyResponse;
import org.jellyfin.sdk.model.api.BaseItemDto;
import org.koin.java.KoinJavaComponent;
@@ -48,13 +48,13 @@ public class LiveProgramDetailPopup {
private Button mFirstButton;
private Button mSeriesSettingsButton;
private EmptyLifecycleAwareResponse mTuneAction;
private EmptyResponse mTuneAction;
private View mAnchor;
private int mPosLeft;
private int mPosTop;
public LiveProgramDetailPopup(Context context, LifecycleOwner lifecycleOwner, LiveTvGuide tvGuide, int width, EmptyLifecycleAwareResponse tuneAction) {
public LiveProgramDetailPopup(Context context, LifecycleOwner lifecycleOwner, LiveTvGuide tvGuide, int width, EmptyResponse tuneAction) {
mContext = context;
lifecycle = lifecycleOwner.getLifecycle();
mTvGuide = tvGuide;
@@ -247,7 +247,7 @@ public class LiveProgramDetailPopup {
tune.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mTuneAction != null && mTuneAction.getActive()) mTuneAction.onResponse();
if (mTuneAction != null) mTuneAction.onResponse();
mPopup.dismiss();
}
});

View File

@@ -1,7 +1,9 @@
package org.jellyfin.androidtv.ui
import androidx.lifecycle.coroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.data.repository.ItemMutationRepository
import org.jellyfin.androidtv.util.getActivity
import org.jellyfin.sdk.api.client.ApiClient
@@ -32,7 +34,9 @@ fun LiveProgramDetailPopup.cancelTimer(
lifecycle.coroutineScope.launch {
runCatching {
api.liveTvApi.cancelTimer(timerId)
withContext(Dispatchers.IO) {
api.liveTvApi.cancelTimer(timerId)
}
}.onSuccess {
callback()
}
@@ -47,7 +51,9 @@ fun LiveProgramDetailPopup.cancelSeriesTimer(
lifecycle.coroutineScope.launch {
runCatching {
api.liveTvApi.cancelSeriesTimer(seriesTimerId)
withContext(Dispatchers.IO) {
api.liveTvApi.cancelSeriesTimer(seriesTimerId)
}
}.onSuccess {
callback()
}
@@ -88,10 +94,12 @@ fun LiveProgramDetailPopup.recordProgram(
lifecycle.coroutineScope.launch {
runCatching {
val seriesTimer by api.liveTvApi.getDefaultTimer(programId.toString())
val timer = seriesTimer.asTimerInfoDto()
api.liveTvApi.createTimer(timer)
api.liveTvApi.getProgram(programId.toString()).content
withContext(Dispatchers.IO) {
val seriesTimer by api.liveTvApi.getDefaultTimer(programId.toString())
val timer = seriesTimer.asTimerInfoDto()
api.liveTvApi.createTimer(timer)
api.liveTvApi.getProgram(programId.toString()).content
}
}.onSuccess { program ->
callback(program)
}
@@ -106,9 +114,11 @@ fun LiveProgramDetailPopup.recordSeries(
lifecycle.coroutineScope.launch {
runCatching {
val timer by api.liveTvApi.getDefaultTimer(programId.toString())
api.liveTvApi.createSeriesTimer(timer)
api.liveTvApi.getProgram(programId.toString()).content
withContext(Dispatchers.IO) {
val timer by api.liveTvApi.getDefaultTimer(programId.toString())
api.liveTvApi.createSeriesTimer(timer)
api.liveTvApi.getProgram(programId.toString()).content
}
}.onSuccess { program ->
callback(program)
}
@@ -123,7 +133,9 @@ fun LiveProgramDetailPopup.getSeriesTimer(
lifecycle.coroutineScope.launch {
runCatching {
api.liveTvApi.getSeriesTimer(seriesTimerId).content
withContext(Dispatchers.IO) {
api.liveTvApi.getSeriesTimer(seriesTimerId).content
}
}.onSuccess { seriesTimer ->
callback(seriesTimer)
}

View File

@@ -2,103 +2,157 @@ package org.jellyfin.androidtv.ui
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.AbstractComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.databinding.ViewNowPlayingBinding
import org.jellyfin.androidtv.ui.base.JellyfinTheme
import org.jellyfin.androidtv.ui.base.ProvideTextStyle
import org.jellyfin.androidtv.ui.base.Text
import org.jellyfin.androidtv.ui.base.button.ButtonBase
import org.jellyfin.androidtv.ui.composable.AsyncImage
import org.jellyfin.androidtv.ui.composable.rememberPlayerProgress
import org.jellyfin.androidtv.ui.composable.rememberQueueEntry
import org.jellyfin.androidtv.ui.navigation.Destinations
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
import org.jellyfin.androidtv.ui.playback.AudioEventListener
import org.jellyfin.androidtv.ui.playback.MediaManager
import org.jellyfin.androidtv.ui.playback.PlaybackController
import org.jellyfin.androidtv.util.ImageHelper
import org.jellyfin.androidtv.util.TimeUtils
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.jellyfin.androidtv.util.apiclient.albumPrimaryImage
import org.jellyfin.androidtv.util.apiclient.getUrl
import org.jellyfin.androidtv.util.apiclient.itemImages
import org.jellyfin.androidtv.util.apiclient.parentImages
import org.jellyfin.playback.core.PlaybackManager
import org.jellyfin.playback.jellyfin.queue.baseItem
import org.jellyfin.playback.jellyfin.queue.baseItemFlow
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.model.api.ImageType
import org.koin.compose.koinInject
class NowPlayingView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = R.style.Button_Default,
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes), KoinComponent {
val binding = ViewNowPlayingBinding.inflate(LayoutInflater.from(context), this, true)
@Composable
fun NowPlayingComposable(
modifier: Modifier = Modifier,
onFocusableChange: (focusable: Boolean) -> Unit,
) {
val api = koinInject<ApiClient>()
val playbackManager = koinInject<PlaybackManager>()
val navigationRepository = koinInject<NavigationRepository>()
private val mediaManager by inject<MediaManager>()
private val navigationRepository by inject<NavigationRepository>()
private val imageHelper by inject<ImageHelper>()
private var currentDuration: String = ""
val entry by rememberQueueEntry(playbackManager)
val item = entry?.run { baseItemFlow.collectAsState(baseItem) }?.value
val progress = rememberPlayerProgress(playbackManager)
init {
setPadding(0)
LaunchedEffect(item == null) { onFocusableChange(item != null) }
if (!isInEditMode) setOnClickListener {
navigationRepository.navigate(Destinations.nowPlaying)
}
}
AnimatedContent(
modifier = modifier,
targetState = item,
transitionSpec = { fadeIn() togetherWith fadeOut() },
) { item ->
if (item != null) {
ButtonBase(
onClick = { navigationRepository.navigate(Destinations.nowPlaying) },
modifier = Modifier
.widthIn(100.dp, 250.dp)
) {
ProvideTextStyle(
value = TextStyle.Default.copy(
fontSize = 12.sp,
)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(3.dp)
) {
val image = item.itemImages[ImageType.PRIMARY] ?: item.albumPrimaryImage ?: item.parentImages[ImageType.PRIMARY]
val progressFillColor = JellyfinTheme.colorScheme.rangeControlFill
override fun onAttachedToWindow() {
super.onAttachedToWindow()
AsyncImage(
url = image?.getUrl(api),
blurHash = image?.blurHash,
placeholder = ContextCompat.getDrawable(LocalContext.current, R.drawable.ic_album),
aspectRatio = image?.aspectRatio ?: 1f,
modifier = Modifier
.size(35.dp)
.clip(CircleShape)
.drawWithContent {
drawContent()
if (!isInEditMode) {
// hook our events
mediaManager.addAudioEventListener(audioEventListener)
val width = 3.dp.toPx()
if (mediaManager.hasAudioQueueItems()) {
isVisible = true
setInfo(mediaManager.currentAudioItem!!)
setStatus(mediaManager.currentAudioPosition)
} else isVisible = false
}
}
// Background
drawCircle(
style = Stroke(width),
color = Color.Black,
alpha = 0.4f,
)
// Foreground
drawArc(
style = Stroke(width, cap = StrokeCap.Round),
color = progressFillColor,
useCenter = false,
startAngle = -90f,
sweepAngle = 360f * progress,
)
},
scaleType = ImageView.ScaleType.CENTER_CROP,
)
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
if (!isInEditMode) mediaManager.removeAudioEventListener(audioEventListener)
}
private fun setInfo(item: org.jellyfin.sdk.model.api.BaseItemDto) {
val placeholder = ContextCompat.getDrawable(context, R.drawable.ic_album)
val blurHash = item.imageBlurHashes?.get(org.jellyfin.sdk.model.api.ImageType.PRIMARY)?.get(item.imageTags?.get(org.jellyfin.sdk.model.api.ImageType.PRIMARY))
binding.npIcon.load(imageHelper.getPrimaryImageUrl(item), blurHash, placeholder, item.primaryImageAspectRatio ?: 1.0)
currentDuration = TimeUtils.formatMillis(if (item.runTimeTicks != null) item.runTimeTicks!! / 10_000 else 0)
binding.npDesc.text = if (item.albumArtist != null) item.albumArtist else item.name
}
private fun setStatus(pos: Long) {
binding.npStatus.text = resources.getString(R.string.lbl_status, TimeUtils.formatMillis(pos), currentDuration)
}
fun showDescription(show: Boolean) {
binding.npDesc.isVisible = show
}
private var audioEventListener: AudioEventListener = object : AudioEventListener {
override fun onPlaybackStateChange(newState: PlaybackController.PlaybackState, currentItem: org.jellyfin.sdk.model.api.BaseItemDto?) {
when {
currentItem == null -> Unit
newState == PlaybackController.PlaybackState.PLAYING -> setInfo(currentItem)
newState == PlaybackController.PlaybackState.IDLE && isShown -> setStatus(mediaManager.currentAudioPosition)
}
}
override fun onProgress(pos: Long) {
if (isShown) setStatus(pos)
}
override fun onQueueStatusChanged(hasQueue: Boolean) {
isVisible = hasQueue
if (hasQueue) {
// may have just added one so update display
setInfo(mediaManager.currentAudioItem!!)
setStatus(mediaManager.currentAudioPosition)
Column(
verticalArrangement = Arrangement.SpaceAround,
modifier = Modifier
.padding(start = 2.dp, end = 8.dp)
) {
// Name
Text(text = item.name.orEmpty(), maxLines = 1, overflow = TextOverflow.Ellipsis, fontWeight = FontWeight.Bold)
val artists = item.artists ?: item.albumArtists ?: item.albumArtist?.let(::listOf)
Text(text = artists?.joinToString(", ").orEmpty(), maxLines = 1, overflow = TextOverflow.Ellipsis)
}
}
}
}
}
}
}
class NowPlayingView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : AbstractComposeView(context, attrs, defStyle) {
@Composable
override fun Content() = NowPlayingComposable(
// Workaround for older Android versions unable to find focus in our toolbar view when the NowPlayingView is added but inactive
onFocusableChange = { focusable ->
isFocusable = focusable
descendantFocusability = if (focusable) FOCUS_AFTER_DESCENDANTS else FOCUS_BLOCK_DESCENDANTS
}
)
}

View File

@@ -1,31 +0,0 @@
package org.jellyfin.androidtv.ui
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import org.jellyfin.androidtv.databinding.ViewNumberSpinnerBinding
class NumberSpinnerView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0,
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
val binding = ViewNumberSpinnerBinding.inflate(LayoutInflater.from(context), this, true)
var increment = 10L
var valueChangedListener: ValueChangedListener<Long>? = null
var value = 0L
set(value) {
field = value
binding.value.text = value.toString()
valueChangedListener?.onValueChanged(value)
}
init {
binding.increase.setOnClickListener { value += increment }
binding.decrease.setOnClickListener { value -= increment }
}
}

View File

@@ -1,7 +1,9 @@
package org.jellyfin.androidtv.ui
import androidx.lifecycle.coroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jellyfin.androidtv.util.getActivity
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.liveTvApi
@@ -41,9 +43,11 @@ fun RecordPopup.updateSeriesTimer(
lifecycle.coroutineScope.launch {
runCatching {
val id = seriesTimer.id
if (id == null) api.liveTvApi.createSeriesTimer(seriesTimer)
else api.liveTvApi.updateSeriesTimer(id, seriesTimer)
withContext(Dispatchers.IO) {
val id = seriesTimer.id
if (id == null) api.liveTvApi.createSeriesTimer(seriesTimer)
else api.liveTvApi.updateSeriesTimer(id, seriesTimer)
}
}.onSuccess {
callback()
}
@@ -58,9 +62,11 @@ fun RecordPopup.updateTimer(
lifecycle.coroutineScope.launch {
runCatching {
val id = timer.id
if (id == null) api.liveTvApi.createTimer(timer)
else api.liveTvApi.updateTimer(id, timer)
withContext(Dispatchers.IO) {
val id = timer.id
if (id == null) api.liveTvApi.createTimer(timer)
else api.liveTvApi.updateTimer(id, timer)
}
}.onSuccess {
callback()
}
@@ -86,7 +92,9 @@ fun RecordPopup.getLiveTvProgram(
lifecycle.coroutineScope.launch {
runCatching {
api.liveTvApi.getProgram(id.toString()).content
withContext(Dispatchers.IO) {
api.liveTvApi.getProgram(id.toString()).content
}
}.onSuccess { program ->
callback(program)
}

View File

@@ -0,0 +1,33 @@
package org.jellyfin.androidtv.ui
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.compose.LocalLifecycleOwner
import org.koin.compose.koinInject
private typealias Lock = () -> Unit
@Composable
fun ScreensaverLock(
enabled: Boolean
) {
val viewModel = koinInject<InteractionTrackerViewModel>()
val lifecycleOwner = LocalLifecycleOwner.current
var lock by remember { mutableStateOf<Lock?>(null) }
DisposableEffect(enabled, lifecycleOwner) {
if (enabled && lock == null) {
lock = viewModel.addLifecycleLock(lifecycleOwner.lifecycle)
}
onDispose {
lock?.invoke()
lock = null
}
}
}

View File

@@ -1,103 +0,0 @@
package org.jellyfin.androidtv.ui
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.jellyfin.androidtv.preference.UserPreferences
import kotlin.time.Duration.Companion.milliseconds
class ScreensaverViewModel(
private val userPreferences: UserPreferences,
) : ViewModel() {
private var timer: Job? = null
private var locks = 0
// Preferences
val inAppEnabled get() = userPreferences[UserPreferences.screensaverInAppEnabled]
private val timeout get() = userPreferences[UserPreferences.screensaverInAppTimeout].milliseconds
// State
private val _visible = MutableStateFlow(false)
val visible get() = _visible.asStateFlow()
private val _keepScreenOn = MutableStateFlow(inAppEnabled)
val keepScreenOn get() = _keepScreenOn.asStateFlow()
var activityPaused: Boolean = false
set(value) {
field = value
notifyInteraction(true)
}
init {
notifyInteraction(true)
}
fun notifyInteraction(canCancel: Boolean) {
// Cancel pending timer (if any)
timer?.cancel()
// Hide when interacted with allowed cancelation or when disabled
if (_visible.value && (canCancel || !inAppEnabled || activityPaused)) {
_visible.value = false
}
// Create new timer to show screensaver when enabled
if (inAppEnabled && !activityPaused && locks == 0) {
timer = viewModelScope.launch {
delay(timeout)
_visible.value = true
}
}
// Update KEEP_SCREEN_ON flag value
_keepScreenOn.value = inAppEnabled || locks > 0
}
/**
* Create a lock that prevents the screensaver for running until the returned function is called
* or the lifecycle is destroyed.
*
* @return Function to cancel the lock
*/
fun addLifecycleLock(lifecycle: Lifecycle): () -> Unit {
if (lifecycle.currentState == Lifecycle.State.DESTROYED) return {}
val lock = ScreensaverLock(lifecycle)
lock.activate()
return lock::cancel
}
private inner class ScreensaverLock(private val lifecycle: Lifecycle) : LifecycleEventObserver {
private var active: Boolean = false
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_DESTROY) cancel()
}
fun activate() {
if (active) return
lifecycle.addObserver(this)
locks++
notifyInteraction(true)
active = true
}
fun cancel() {
if (!active) return
locks--
lifecycle.removeObserver(this)
notifyInteraction(false)
active = false
}
}
}

View File

@@ -1,86 +1,118 @@
package org.jellyfin.androidtv.ui
import android.content.Context
import android.graphics.Rect
import android.os.Build
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.compose.foundation.interaction.FocusInteraction
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.AbstractComposeView
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.databinding.ViewButtonServerBinding
import org.jellyfin.androidtv.ui.base.CircularProgressIndicator
import org.jellyfin.androidtv.ui.base.Icon
import org.jellyfin.androidtv.ui.base.LocalTextStyle
import org.jellyfin.androidtv.ui.base.ProvideTextStyle
import org.jellyfin.androidtv.ui.base.Text
import org.jellyfin.androidtv.ui.base.button.ButtonBase
import org.jellyfin.androidtv.ui.base.button.ButtonDefaults
import org.jellyfin.androidtv.util.MenuBuilder
import org.jellyfin.androidtv.util.popupMenu
import org.jellyfin.androidtv.util.showIfNotEmpty
@Composable
fun ServerButton(
icon: @Composable () -> Unit,
name: @Composable () -> Unit,
address: @Composable () -> Unit,
version: @Composable () -> Unit,
onClick: () -> Unit,
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = ButtonDefaults.Shape,
) {
ButtonBase(
onClick = onClick,
modifier = modifier,
interactionSource = interactionSource,
shape = shape,
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp, vertical = 8.dp)
) {
icon()
Column(
modifier = Modifier
.weight(1f)
.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceBetween,
) {
ProvideTextStyle(LocalTextStyle.current.copy(fontSize = 14.sp)) {
name()
}
ProvideTextStyle(LocalTextStyle.current.copy(fontSize = 12.sp)) {
address()
}
}
Box(modifier = Modifier.align(Alignment.Bottom)) {
ProvideTextStyle(LocalTextStyle.current.copy(fontSize = 12.sp)) {
version()
}
}
}
}
}
class ServerButtonView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0,
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
val binding = ViewButtonServerBinding.inflate(LayoutInflater.from(context), this, true)
) : AbstractComposeView(context, attrs, defStyleAttr) {
var name by mutableStateOf("")
var address by mutableStateOf("")
var version by mutableStateOf<String?>(null)
var state by mutableStateOf(State.DEFAULT)
private var focused by mutableStateOf(false)
init {
isFocusable = true
isClickable = true
descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
foreground = ResourcesCompat.getDrawable(resources, R.drawable.ripple, context.theme)
descendantFocusability = FOCUS_BLOCK_DESCENDANTS
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) defaultFocusHighlightEnabled = false
}
var name: String
get() = binding.serverName.text.toString()
set(value) {
binding.serverName.text = value
}
var address: String
get() = binding.serverAddress.text.toString()
set(value) {
binding.serverAddress.text = value
}
var version: String?
get() = binding.serverVersion.text?.toString()
set(value) {
binding.serverVersion.text = value
}
private var _state: State = State.DEFAULT
var state: State
get() = _state
set(value) {
_state = value
when (_state) {
State.DEFAULT -> {
binding.iconDefault.isVisible = true
binding.iconDefault.setImageResource(R.drawable.ic_house)
binding.iconProgress.isVisible = false
}
State.EDIT -> {
binding.iconDefault.isVisible = true
binding.iconDefault.setImageResource(R.drawable.ic_house_edit)
binding.iconProgress.isVisible = false
}
State.CONNECTING -> {
binding.iconDefault.isInvisible = true
binding.iconProgress.isVisible = true
}
State.ERROR -> {
binding.iconDefault.isVisible = true
binding.iconDefault.setImageResource(R.drawable.ic_error)
binding.iconProgress.isVisible = false
}
}
}
fun setPopupMenu(init: MenuBuilder.() -> Unit) {
setOnLongClickListener {
popupMenu(context, binding.root, init = init).showIfNotEmpty()
popupMenu(context, this, init = init).showIfNotEmpty()
}
}
@@ -93,6 +125,59 @@ class ServerButtonView @JvmOverloads constructor(
return false
}
override fun onFocusChanged(gainFocus: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)
focused = gainFocus
}
@Composable
override fun Content() {
val interactionSource = remember { MutableInteractionSource() }
// Forward focus events to the interaction source
val focusInteraction = remember { FocusInteraction.Focus() }
LaunchedEffect(focused) {
if (focused) interactionSource.emit(focusInteraction)
else interactionSource.emit(FocusInteraction.Unfocus(focusInteraction))
}
ServerButton(
icon = {
when (state) {
State.DEFAULT -> Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_house),
contentDescription = null,
)
State.EDIT -> Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_house_edit),
contentDescription = null,
)
State.CONNECTING -> CircularProgressIndicator(
modifier = Modifier.size(24.dp)
)
State.ERROR -> Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_error),
contentDescription = null,
)
}
},
name = { Text(name) },
address = { Text(address) },
version = { Text(version.orEmpty()) },
interactionSource = interactionSource,
// Use the old shape as the Android View implementation is only used in legacy UI
shape = RoundedCornerShape(3.dp),
// New implementation doesn't end up at 51.dp by default so force the old size
modifier = Modifier.height(51.dp),
// We use our own click handler for the view
onClick = {}
)
}
enum class State {
DEFAULT,
EDIT,

View File

@@ -1,5 +0,0 @@
package org.jellyfin.androidtv.ui
fun interface ValueChangedListener<T> {
fun onValueChanged(value: T)
}

View File

@@ -0,0 +1,36 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
import org.jellyfin.design.Tokens
@Composable
fun Badge(
modifier: Modifier = Modifier,
shape: Shape = CircleShape,
containerColor: Color = JellyfinTheme.colorScheme.badge,
contentColor: Color = JellyfinTheme.colorScheme.onBadge,
content: @Composable BoxScope.() -> Unit,
) {
ProvideTextStyle(JellyfinTheme.typography.badge.copy(color = contentColor)) {
Box(
modifier = modifier
.defaultMinSize(minWidth = 24.dp, minHeight = 24.dp)
.background(containerColor, shape)
.padding(Tokens.Space.spaceXs),
contentAlignment = Alignment.Center,
) {
content()
}
}
}

View File

@@ -0,0 +1,29 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
@Composable
@Stable
fun BaseScreen(
content: @Composable () -> Unit,
) {
// Work around a focus issue with our current fragment based navigation approach
// by always focusing the screen contents whenever the screen is created
val focusRequester = remember { FocusRequester() }
Box(
modifier = Modifier
.focusRequester(focusRequester)
.focusGroup()
) {
content()
}
LaunchedEffect(focusRequester) { focusRequester.requestFocus() }
}

View File

@@ -0,0 +1,48 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
@Composable
fun CircularProgressIndicator(
modifier: Modifier = Modifier,
color: Color = LocalTextStyle.current.color,
) {
val infiniteTransition = rememberInfiniteTransition()
val rotation by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = 1_500, // 1.5 seconds
easing = LinearEasing,
)
)
)
Canvas(
modifier = modifier
.aspectRatio(1f)
.rotate(rotation)
) {
drawArc(
color = color,
startAngle = 0f,
sweepAngle = 270f,
useCenter = false,
style = Stroke(width = 4f, cap = StrokeCap.Round)
)
}
}

View File

@@ -0,0 +1,82 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.toolingGraphicsLayer
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
@Composable
fun Icon(
imageVector: ImageVector,
contentDescription: String?,
modifier: Modifier = Modifier,
tint: Color = LocalTextStyle.current.color,
) = Icon(
painter = rememberVectorPainter(imageVector),
contentDescription = contentDescription,
modifier = modifier,
tint = tint,
)
@Composable
fun Icon(
bitmap: ImageBitmap,
contentDescription: String?,
modifier: Modifier = Modifier,
tint: Color = LocalTextStyle.current.color,
) = Icon(
painter = remember(bitmap) { BitmapPainter(bitmap) },
contentDescription = contentDescription,
modifier = modifier,
tint = tint,
)
@Composable
fun Icon(
painter: Painter,
contentDescription: String?,
modifier: Modifier = Modifier,
tint: Color = LocalTextStyle.current.color,
) {
val colorFilter = remember(tint) { tint.takeUnless { it == Color.Unspecified }?.let(ColorFilter::tint) }
val semantics = if (contentDescription != null) Modifier.semantics {
this.contentDescription = contentDescription
this.role = Role.Image
} else Modifier
Box(
modifier
.toolingGraphicsLayer()
.defaultSizeFor(painter)
.paint(painter, colorFilter = colorFilter, contentScale = ContentScale.Fit)
.then(semantics)
)
}
private fun Modifier.defaultSizeFor(painter: Painter) = then(
if (painter.intrinsicSize == Size.Unspecified || painter.intrinsicSize.isInfinite()) {
Modifier.size(20.dp)
} else {
Modifier
}
)
private fun Size.isInfinite() = width.isInfinite() && height.isInfinite()

View File

@@ -0,0 +1,36 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.foundation.LocalOverscrollFactory
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ReadOnlyComposable
@Composable
fun JellyfinTheme(
colorScheme: ColorScheme = JellyfinTheme.colorScheme,
shapes: Shapes = JellyfinTheme.shapes,
typography: Typography = JellyfinTheme.typography,
content: @Composable () -> Unit
) {
CompositionLocalProvider(
LocalColorScheme provides colorScheme,
LocalShapes provides shapes,
LocalTypography provides typography,
LocalTextStyle provides LocalTextStyle.current.merge(typography.default),
// Disable overscroll
LocalOverscrollFactory provides null,
) {
content()
}
}
object JellyfinTheme {
val colorScheme: ColorScheme
@Composable @ReadOnlyComposable get() = LocalColorScheme.current
val typography: Typography
@Composable @ReadOnlyComposable get() = LocalTypography.current
val shapes: Shapes
@Composable @ReadOnlyComposable get() = LocalShapes.current
}

View File

@@ -0,0 +1,54 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.vectorResource
import coil3.compose.AsyncImagePainter
import coil3.compose.rememberAsyncImagePainter
import org.jellyfin.androidtv.R
@Composable
fun ProfilePicture(
url: String?,
modifier: Modifier = Modifier,
contentDescription: String? = null,
iconPadding: PaddingValues = PaddingValues.Zero,
) {
Box(
modifier = modifier
) {
val userImagePainter = rememberAsyncImagePainter(url)
val userImageState by userImagePainter.state.collectAsState()
val userImageVisible = userImageState is AsyncImagePainter.State.Success
if (!userImageVisible) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_user),
contentDescription = contentDescription,
modifier = Modifier
.align(Alignment.Center)
.padding(iconPadding)
.fillMaxSize()
)
} else {
Image(
painter = userImagePainter,
contentDescription = contentDescription,
contentScale = ContentScale.Crop,
modifier = Modifier
.aspectRatio(1f)
)
}
}
}

View File

@@ -0,0 +1,191 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.focusable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.key.type
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.times
@Immutable
data class SeekbarColors(
val backgroundColor: Color,
val bufferColor: Color,
val progressColor: Color,
val knobColor: Color,
)
object SeekbarDefaults {
@ReadOnlyComposable
@Composable
fun colors(
backgroundColor: Color = JellyfinTheme.colorScheme.rangeControlBackground,
bufferColor: Color = JellyfinTheme.colorScheme.seekbarBuffer,
progressColor: Color = JellyfinTheme.colorScheme.rangeControlFill,
knobColor: Color = JellyfinTheme.colorScheme.rangeControlKnob,
) = SeekbarColors(
backgroundColor = backgroundColor,
bufferColor = bufferColor,
progressColor = progressColor,
knobColor = knobColor,
)
}
@Composable
fun Seekbar(
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
progress: Duration = Duration.ZERO,
buffer: Duration = Duration.ZERO,
duration: Duration = Duration.ZERO,
seekForwardAmount: Duration = duration / 100,
seekRewindAmount: Duration = duration / 100,
onScrubbing: ((scrubbing: Boolean) -> Unit)? = null,
onSeek: ((progress: Duration) -> Unit)? = null,
enabled: Boolean = true,
colors: SeekbarColors = SeekbarDefaults.colors(),
) {
val durationMs = duration.inWholeMilliseconds.toFloat().coerceAtLeast(1f)
val progressPercentage = progress.inWholeMilliseconds.toFloat() / durationMs
val bufferPercentage = buffer.inWholeMilliseconds.toFloat() / durationMs
val seekForwardPercentage = seekForwardAmount.inWholeMilliseconds.toFloat() / durationMs
val seekRewindPercentage = seekRewindAmount.inWholeMilliseconds.toFloat() / durationMs
Seekbar(
modifier = modifier,
interactionSource = interactionSource,
progress = progressPercentage,
buffer = bufferPercentage,
seekForwardAmount = seekForwardPercentage,
seekRewindAmount = seekRewindPercentage,
onScrubbing = onScrubbing,
onSeek = if (onSeek == null) null else { progress -> onSeek(progress.toDouble() * duration) },
enabled = enabled,
colors = colors,
)
}
@Composable
fun Seekbar(
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
progress: Float = 0f,
buffer: Float = 0f,
seekForwardAmount: Float = 0.01f,
seekRewindAmount: Float = 0.01f,
onScrubbing: ((scrubbing: Boolean) -> Unit)? = null,
onSeek: ((progress: Float) -> Unit)? = null,
enabled: Boolean = true,
colors: SeekbarColors = SeekbarDefaults.colors(),
) {
val coroutineScope = rememberCoroutineScope()
val focused by interactionSource.collectIsFocusedAsState()
var progressOverride by remember { mutableStateOf<Float?>(null) }
val visibleProgress = progressOverride ?: progress
val knobAlpha by animateFloatAsState(if (focused) 1f else 0f)
var scrubCancelJob by remember { mutableStateOf<Job?>(null) }
Box(
modifier = modifier
.onKeyEvent {
if (!enabled) return@onKeyEvent false
val isForward = it.key == Key.DirectionRight
val isRewind = it.key == Key.DirectionLeft
val isScrubbing = isForward || isRewind
val isKeyUp = it.type == KeyEventType.KeyUp
val isKeyDown = it.type == KeyEventType.KeyDown
val newProgress = when {
isKeyDown && isForward -> (visibleProgress + seekForwardAmount).coerceAtMost(1f)
isKeyDown && isRewind -> (visibleProgress - seekRewindAmount).coerceAtLeast(0f)
else -> visibleProgress
}
if (isScrubbing && isKeyDown && onScrubbing != null) {
scrubCancelJob?.cancel()
onScrubbing(true)
}
if (visibleProgress != newProgress) {
progressOverride = newProgress
if (onSeek != null) onSeek(newProgress)
}
if (isScrubbing && isKeyUp && onScrubbing != null) {
scrubCancelJob?.cancel()
scrubCancelJob = coroutineScope.launch {
delay(300.milliseconds)
onScrubbing(false)
progressOverride = null
}
}
return@onKeyEvent isScrubbing
}
.focusable(interactionSource = interactionSource, enabled = enabled)
.drawWithContent {
val barCornerRadius = CornerRadius(size.minDimension, size.minDimension)
// Background bar
drawRoundRect(
color = colors.backgroundColor,
cornerRadius = barCornerRadius,
)
// Buffer bar
if (buffer > 0f) {
drawRoundRect(
color = colors.bufferColor,
size = size.copy(
width = buffer * size.width,
),
cornerRadius = barCornerRadius,
)
}
// Progress bar
if (visibleProgress > 0f) {
drawRoundRect(
color = colors.progressColor,
size = size.copy(
width = visibleProgress * size.width,
),
cornerRadius = barCornerRadius,
)
}
// Progress knob
drawCircle(
color = colors.knobColor,
alpha = knobAlpha,
center = center.copy(
x = visibleProgress * size.width,
),
radius = size.minDimension * 2,
)
}
)
}

View File

@@ -0,0 +1,122 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.structuralEqualityPolicy
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.TextUnit
@Composable
fun Text(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
fontFamily: FontFamily? = null,
letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null,
lineHeight: TextUnit = TextUnit.Unspecified,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
minLines: Int = 1,
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) {
val textColor = color.takeOrElse { style.color.takeOrElse { Color.Black } }
BasicText(
text = text,
modifier = modifier.graphicsLayer { this.compositingStrategy = CompositingStrategy.Offscreen },
style = style.merge(
color = textColor,
fontSize = fontSize,
fontWeight = fontWeight,
textAlign = textAlign ?: TextAlign.Unspecified,
lineHeight = lineHeight,
fontFamily = fontFamily,
textDecoration = textDecoration,
fontStyle = fontStyle,
letterSpacing = letterSpacing
),
onTextLayout = onTextLayout,
overflow = overflow,
softWrap = softWrap,
maxLines = maxLines,
minLines = minLines
)
}
@Composable
fun Text(
text: AnnotatedString,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
fontStyle: FontStyle? = null,
fontWeight: FontWeight? = null,
fontFamily: FontFamily? = null,
letterSpacing: TextUnit = TextUnit.Unspecified,
textDecoration: TextDecoration? = null,
textAlign: TextAlign? = null,
lineHeight: TextUnit = TextUnit.Unspecified,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
minLines: Int = 1,
inlineContent: Map<String, InlineTextContent> = mapOf(),
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) {
val textColor = color.takeOrElse { style.color.takeOrElse { Color.Black } }
BasicText(
text = text,
modifier = modifier.graphicsLayer { this.compositingStrategy = CompositingStrategy.Offscreen },
style =
style.merge(
color = textColor,
fontSize = fontSize,
fontWeight = fontWeight,
textAlign = textAlign ?: TextAlign.Unspecified,
lineHeight = lineHeight,
fontFamily = fontFamily,
textDecoration = textDecoration,
fontStyle = fontStyle,
letterSpacing = letterSpacing
),
onTextLayout = onTextLayout,
overflow = overflow,
softWrap = softWrap,
maxLines = maxLines,
minLines = minLines,
inlineContent = inlineContent
)
}
val LocalTextStyle = compositionLocalOf(structuralEqualityPolicy()) { TypographyDefaults.Default }
@Composable
fun ProvideTextStyle(value: TextStyle, content: @Composable () -> Unit) {
val mergedStyle = LocalTextStyle.current.merge(value)
CompositionLocalProvider(LocalTextStyle provides mergedStyle, content = content)
}

View File

@@ -0,0 +1,115 @@
package org.jellyfin.androidtv.ui.base.button
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
import org.jellyfin.androidtv.ui.base.JellyfinTheme
object ButtonDefaults {
val Shape: Shape = CircleShape
val ContentPadding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 10.dp)
@ReadOnlyComposable
@Composable
fun colors(
containerColor: Color = JellyfinTheme.colorScheme.button,
contentColor: Color = JellyfinTheme.colorScheme.onButton,
focusedContainerColor: Color = JellyfinTheme.colorScheme.buttonFocused,
focusedContentColor: Color = JellyfinTheme.colorScheme.onButtonFocused,
disabledContainerColor: Color = JellyfinTheme.colorScheme.buttonDisabled,
disabledContentColor: Color = JellyfinTheme.colorScheme.onButtonDisabled,
) = ButtonColors(
containerColor = containerColor,
contentColor = contentColor,
focusedContainerColor = focusedContainerColor,
focusedContentColor = focusedContentColor,
disabledContainerColor = disabledContainerColor,
disabledContentColor = disabledContentColor,
)
}
@Composable
fun Button(
onClick: () -> Unit,
modifier: Modifier = Modifier,
onLongClick: (() -> Unit)? = null,
enabled: Boolean = true,
shape: Shape = ButtonDefaults.Shape,
colors: ButtonColors = ButtonDefaults.colors(),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
content: @Composable RowScope.() -> Unit
) {
ButtonBase(
onClick = onClick,
modifier = modifier,
onLongClick = onLongClick,
enabled = enabled,
shape = shape,
colors = colors,
interactionSource = interactionSource,
) {
ButtonRow(
contentPadding = contentPadding,
content = content,
)
}
}
@Composable
fun ProgressButton(
progress: Float,
onClick: () -> Unit,
modifier: Modifier = Modifier,
onLongClick: (() -> Unit)? = null,
enabled: Boolean = true,
shape: Shape = ButtonDefaults.Shape,
colors: ButtonColors = ButtonDefaults.colors(),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
content: @Composable RowScope.() -> Unit
) {
ProgressButtonBase(
progress = progress,
onClick = onClick,
modifier = modifier,
onLongClick = onLongClick,
enabled = enabled,
shape = shape,
colors = colors,
interactionSource = interactionSource,
) {
ButtonRow(
contentPadding = contentPadding,
content = content,
)
}
}
@Composable
private fun ButtonRow(
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit,
) = Row(
modifier = Modifier
.defaultMinSize(
minWidth = 58.dp,
minHeight = 40.dp
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)

View File

@@ -0,0 +1,62 @@
package org.jellyfin.androidtv.ui.base.button
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.sp
import org.jellyfin.androidtv.ui.base.JellyfinTheme
import org.jellyfin.androidtv.ui.base.ProvideTextStyle
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ButtonBase(
onClick: () -> Unit,
modifier: Modifier = Modifier,
onLongClick: (() -> Unit)? = null,
enabled: Boolean = true,
shape: Shape = ButtonDefaults.Shape,
colors: ButtonColors = ButtonDefaults.colors(),
interactionSource: MutableInteractionSource? = null,
content: @Composable BoxScope.() -> Unit
) {
@Suppress("NAME_SHADOWING")
val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
val focused by interactionSource.collectIsFocusedAsState()
val pressed by interactionSource.collectIsPressedAsState()
val colors = when {
!enabled -> colors.disabledContainerColor to colors.disabledContentColor
pressed -> colors.focusedContainerColor to colors.focusedContentColor
focused -> colors.focusedContainerColor to colors.focusedContentColor
else -> colors.containerColor to colors.contentColor
}
ProvideTextStyle(value = JellyfinTheme.typography.default.copy(fontSize = 14.sp, color = colors.second)) {
Box(
modifier = modifier
.combinedClickable(
interactionSource = interactionSource,
indication = null,
enabled = enabled,
role = Role.Button,
onClick = onClick,
onLongClick = onLongClick,
)
.background(colors.first, shape)
.clip(shape),
content = content,
)
}
}

View File

@@ -0,0 +1,14 @@
package org.jellyfin.androidtv.ui.base.button
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
@Immutable
data class ButtonColors(
val containerColor: Color,
val contentColor: Color,
val focusedContainerColor: Color,
val focusedContentColor: Color,
val disabledContainerColor: Color,
val disabledContentColor: Color,
)

View File

@@ -0,0 +1,66 @@
package org.jellyfin.androidtv.ui.base.button
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
import org.jellyfin.androidtv.ui.base.JellyfinTheme
object IconButtonDefaults {
val Shape: Shape = ButtonDefaults.Shape
val ContentPadding: PaddingValues = PaddingValues(horizontal = 10.dp, vertical = 10.dp)
@ReadOnlyComposable
@Composable
fun colors(
containerColor: Color = JellyfinTheme.colorScheme.button,
contentColor: Color = JellyfinTheme.colorScheme.onButton,
focusedContainerColor: Color = JellyfinTheme.colorScheme.buttonFocused,
focusedContentColor: Color = JellyfinTheme.colorScheme.onButtonFocused,
disabledContainerColor: Color = JellyfinTheme.colorScheme.buttonDisabled,
disabledContentColor: Color = JellyfinTheme.colorScheme.onButtonDisabled,
) = ButtonDefaults.colors(
containerColor = containerColor,
contentColor = contentColor,
focusedContainerColor = focusedContainerColor,
focusedContentColor = focusedContentColor,
disabledContainerColor = disabledContainerColor,
disabledContentColor = disabledContentColor,
)
}
@Composable
fun IconButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
onLongClick: (() -> Unit)? = null,
enabled: Boolean = true,
shape: Shape = IconButtonDefaults.Shape,
colors: ButtonColors = ButtonDefaults.colors(),
contentPadding: PaddingValues = IconButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource? = null,
content: @Composable BoxScope.() -> Unit
) {
ButtonBase(
onClick = onClick,
modifier = modifier,
onLongClick = onLongClick,
enabled = enabled,
shape = shape,
colors = colors,
interactionSource = interactionSource,
) {
Box(
modifier = Modifier
.padding(contentPadding),
content = content,
)
}
}

View File

@@ -0,0 +1,49 @@
package org.jellyfin.androidtv.ui.base.button
import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.colorResource
import org.jellyfin.androidtv.R
@Composable
fun ProgressButtonBase(
progress: Float,
onClick: () -> Unit,
modifier: Modifier = Modifier,
onLongClick: (() -> Unit)? = null,
enabled: Boolean = true,
shape: Shape = ButtonDefaults.Shape,
colors: ButtonColors = ButtonDefaults.colors(),
interactionSource: MutableInteractionSource? = null,
content: @Composable BoxScope.() -> Unit
) {
val progressColor = colorResource(R.color.button_default_progress_background)
ButtonBase(
onClick = onClick,
modifier = modifier,
onLongClick = onLongClick,
enabled = enabled,
shape = shape,
colors = colors,
interactionSource = interactionSource,
) {
Box(Modifier.matchParentSize()) {
Box(
Modifier
.fillMaxHeight()
.fillMaxWidth(progress)
.background(progressColor)
)
}
content()
}
}

View File

@@ -0,0 +1,82 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import org.jellyfin.design.Tokens
fun colorScheme(): ColorScheme = ColorScheme(
background = Tokens.Color.colorGrey975,
onBackground = Tokens.Color.colorBluegrey25,
button = Color(0xB3747474),
onButton = Color(0xFFDDDDDD),
buttonFocused = Color(0xE6CCCCCC),
onButtonFocused = Color(0xFF444444),
buttonDisabled = Color(0x33747474),
onButtonDisabled = Color(0xFF686868),
buttonActive = Color(0x4DCCCCCC),
onButtonActive = Color(0xFFDDDDDD),
input = Color(0xB3747474),
onInput = Color(0xE6CCCCCC),
inputFocused = Color(0xE6CCCCCC),
onInputFocused = Color(0xFFDDDDDD),
rangeControlBackground = Tokens.Color.colorBluegrey700,
rangeControlFill = Tokens.Color.colorCyan500,
rangeControlKnob = Tokens.Color.colorBluegrey100,
seekbarBuffer = Tokens.Color.colorBluegrey300,
recording = Tokens.Color.colorRed300,
onRecording = Tokens.Color.colorRed25,
badge = Tokens.Color.colorCyan500,
onBadge = Tokens.Color.colorBluegrey100,
listHeader = Tokens.Color.colorGrey50,
listOverline = Tokens.Color.colorGrey500,
listHeadline = Tokens.Color.colorGrey25,
listCaption = Tokens.Color.colorGrey200,
listButton = Color.Transparent,
listButtonFocused = Tokens.Color.colorBluegrey800,
surface = Tokens.Color.colorBluegrey900,
scrim = Tokens.Color.colorBlack.copy(alpha = 0.67f),
)
@Immutable
data class ColorScheme(
val background: Color,
val onBackground: Color,
val button: Color,
val onButton: Color,
val buttonFocused: Color,
val onButtonFocused: Color,
val buttonDisabled: Color,
val onButtonDisabled: Color,
val buttonActive: Color,
val onButtonActive: Color,
val input: Color,
val onInput: Color,
val inputFocused: Color,
val onInputFocused: Color,
val rangeControlBackground: Color,
val rangeControlFill: Color,
val rangeControlKnob: Color,
val seekbarBuffer: Color,
val recording: Color,
val onRecording: Color,
val badge: Color,
val onBadge: Color,
val listHeader: Color,
val listOverline: Color,
val listHeadline: Color,
val listCaption: Color,
val listButton: Color,
val listButtonFocused: Color,
val surface: Color,
val scrim: Color,
)
val LocalColorScheme = staticCompositionLocalOf { colorScheme() }

View File

@@ -0,0 +1,84 @@
package org.jellyfin.androidtv.ui.base.dialog
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import org.jellyfin.androidtv.ui.base.JellyfinTheme
import org.jellyfin.androidtv.ui.base.interactionTracker
@Composable
fun DialogBase(
visible: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
scrimColor: Color = JellyfinTheme.colorScheme.scrim,
enterTransition: EnterTransition = fadeIn(tween(300)),
exitTransition: ExitTransition = fadeOut(tween(300)),
contentAlignment: Alignment = Alignment.Center,
content: @Composable BoxScope.() -> Unit,
) {
val transition = updateTransition(visible)
val alpha by transition.animateFloat(
transitionSpec = { tween(1000) },
targetValueByState = { visible -> if (visible) 1f else 0f }
)
if (transition.currentState || transition.isRunning) {
val focusRequester = remember { FocusRequester() }
var contentVisible by remember { mutableStateOf(false) }
Dialog(
onDismissRequest = onDismissRequest,
properties = DialogProperties(
dismissOnBackPress = true,
dismissOnClickOutside = true,
usePlatformDefaultWidth = false,
decorFitsSystemWindows = false
),
) {
Box(
modifier = modifier
.fillMaxSize()
.background(scrimColor.copy(alpha = scrimColor.alpha * alpha))
.focusRequester(focusRequester)
.focusGroup()
.interactionTracker(),
contentAlignment = contentAlignment,
) {
transition.AnimatedVisibility(
visible = { it && contentVisible },
enter = enterTransition,
exit = exitTransition,
) {
content()
LaunchedEffect(focusRequester) { focusRequester.requestFocus() }
}
}
}
LaunchedEffect(contentVisible) { contentVisible = true }
}
}

View File

@@ -0,0 +1,49 @@
package org.jellyfin.androidtv.ui.base.form
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.ui.base.Icon
import org.jellyfin.androidtv.ui.base.JellyfinTheme
@Composable
fun Checkbox(
checked: Boolean,
modifier: Modifier = Modifier,
shape: Shape = JellyfinTheme.shapes.extraSmall,
containerColor: Color = JellyfinTheme.colorScheme.button,
contentColor: Color = JellyfinTheme.colorScheme.onButton
) {
Box(
modifier = modifier
.defaultMinSize(minWidth = 18.dp, minHeight = 18.dp)
.background(if (checked) containerColor else Color.Unspecified, shape)
.border(if (checked) 0.dp else 2.dp, containerColor, shape),
contentAlignment = Alignment.Center,
) {
AnimatedVisibility(
visible = checked,
modifier = Modifier
.matchParentSize()
) {
Icon(
painterResource(R.drawable.ic_check),
tint = contentColor,
contentDescription = null,
modifier = Modifier
.padding(3.dp)
)
}
}
}

View File

@@ -0,0 +1,51 @@
package org.jellyfin.androidtv.ui.base.form
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
@Composable
fun ColorSwatch(
color: Color,
modifier: Modifier = Modifier,
shape: Shape = CircleShape,
) {
Box(
modifier = modifier
.defaultMinSize(minWidth = 18.dp, minHeight = 18.dp)
.clip(shape)
) {
Canvas(
modifier = Modifier
.matchParentSize()
) {
if (color.alpha < 1f) {
val squareSize = 6.dp.toPx()
repeat((size.height / squareSize).toInt()) { row ->
repeat((size.width / squareSize).toInt()) { col ->
val isLight = (row + col) % 2 == 0
drawRect(
color = if (isLight) Color.LightGray else Color.DarkGray,
topLeft = Offset(col * squareSize, row * squareSize),
size = Size(squareSize, squareSize),
)
}
}
}
drawRect(
color = color,
)
}
}
}

View File

@@ -0,0 +1,50 @@
package org.jellyfin.androidtv.ui.base.form
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.ui.base.Icon
import org.jellyfin.androidtv.ui.base.JellyfinTheme
@Composable
fun RadioButton(
checked: Boolean,
modifier: Modifier = Modifier,
shape: Shape = CircleShape,
containerColor: Color = JellyfinTheme.colorScheme.button,
contentColor: Color = JellyfinTheme.colorScheme.onButton
) {
Box(
modifier = modifier
.defaultMinSize(minWidth = 18.dp, minHeight = 18.dp)
.background(if (checked) containerColor else Color.Unspecified, shape)
.border(if (checked) 0.dp else 2.dp, containerColor, shape),
contentAlignment = Alignment.Center,
) {
AnimatedVisibility(
visible = checked,
modifier = Modifier
.matchParentSize()
) {
Icon(
painterResource(R.drawable.ic_check),
tint = contentColor,
contentDescription = null,
modifier = Modifier
.padding(3.dp)
)
}
}
}

View File

@@ -0,0 +1,115 @@
package org.jellyfin.androidtv.ui.base.form
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.focusable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.key.type
import org.jellyfin.androidtv.ui.base.JellyfinTheme
@Immutable
data class RangeControlColors(
val backgroundColor: Color,
val fillColor: Color,
val knobColor: Color,
)
object RangeControlDefaults {
@ReadOnlyComposable
@Composable
fun colors(
backgroundColor: Color = JellyfinTheme.colorScheme.rangeControlBackground,
fillColor: Color = JellyfinTheme.colorScheme.rangeControlFill,
knobColor: Color = JellyfinTheme.colorScheme.rangeControlKnob,
) = RangeControlColors(
backgroundColor = backgroundColor,
fillColor = fillColor,
knobColor = knobColor,
)
}
@Composable
fun RangeControl(
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
min: Float = 0f,
max: Float = 1f,
value: Float = 0f,
stepForward: Float = 0.01f,
stepBackward: Float = stepForward,
onValueChange: ((vakye: Float) -> Unit)? = null,
enabled: Boolean = true,
colors: RangeControlColors = RangeControlDefaults.colors(),
) {
val focused by interactionSource.collectIsFocusedAsState()
val knobSize by animateFloatAsState(if (focused) 1.75f else 1f)
Box(
modifier = modifier
.onKeyEvent {
if (!enabled) return@onKeyEvent false
val isForward = it.key == Key.DirectionRight
val isRewind = it.key == Key.DirectionLeft
val isScrubbing = isForward || isRewind
val isKeyDown = it.type == KeyEventType.KeyDown
val newValue = when {
isKeyDown && isForward -> (value + stepForward).coerceAtMost(max)
isKeyDown && isRewind -> (value - stepBackward).coerceAtLeast(min)
else -> value
}
if (value != newValue && onValueChange != null) onValueChange(newValue)
return@onKeyEvent isScrubbing
}
.focusable(interactionSource = interactionSource, enabled = enabled)
.drawWithContent {
val barCornerRadius = CornerRadius(size.minDimension, size.minDimension)
// Background bar
drawRoundRect(
color = colors.backgroundColor,
cornerRadius = barCornerRadius,
)
// Get percental value based on min/max options
val valuePercentage = (value - min) / (max - min)
// Value fill bar
if (valuePercentage > 0) {
drawRoundRect(
color = colors.fillColor,
size = size.copy(
width = valuePercentage * size.width,
),
cornerRadius = barCornerRadius,
)
}
// Progress knob
drawCircle(
color = colors.knobColor,
center = center.copy(
x = valuePercentage * size.width,
),
radius = size.minDimension * knobSize,
)
}
)
}

View File

@@ -0,0 +1,38 @@
package org.jellyfin.androidtv.ui.base
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.onPreviewKeyEvent
typealias InteractionTracker = () -> Unit
private val DefaultInteractionTracker: InteractionTracker = {}
val LocalInteractionTracker = staticCompositionLocalOf<InteractionTracker> { DefaultInteractionTracker }
@Composable
fun ProvideLocalInteractionTracker(
interactionTracker: InteractionTracker,
content: @Composable () -> Unit
) {
CompositionLocalProvider(
LocalInteractionTracker provides interactionTracker
) {
Box(
modifier = Modifier.interactionTracker(interactionTracker),
) {
content()
}
}
}
@Composable
fun Modifier.interactionTracker(
interactionTracker: InteractionTracker = LocalInteractionTracker.current,
): Modifier = onPreviewKeyEvent {
interactionTracker()
false
}

Some files were not shown because too many files have changed in this diff Show More