Merge branch 'main' into Skip-credit

This commit is contained in:
Cd16d 2024-04-15 20:07:07 +02:00 committed by GitHub
commit e10ae9c487
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
98 changed files with 1181 additions and 245 deletions

65
.github/workflows/publish.yaml vendored Normal file
View file

@ -0,0 +1,65 @@
name: Publish
on:
push:
tags:
- v*
jobs:
publish:
name: Publish
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3.0
bundler-cache: true
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3
- name: Decode keystore file
uses: timheuer/base64-to-file@v1
id: findroid_keystore
with:
fileName: 'findroid-keystore.jks'
encodedString: ${{ secrets.FINDROID_KEYSTORE }}
- name: Decode Play API credentials file
uses: timheuer/base64-to-file@v1
id: findroid_play_api_credentials
with:
fileName: 'findroid-play-api-credentials.json'
encodedString: ${{ secrets.FINDROID_PLAY_API_CREDENTIALS }}
- name: Build and publish
run: bundle exec fastlane publish
env:
FINDROID_KEYSTORE: ${{ steps.findroid_keystore.outputs.filePath }}
FINDROID_KEYSTORE_PASSWORD: ${{ secrets.FINDROID_KEYSTORE_PASSWORD }}
FINDROID_KEY_ALIAS: ${{ secrets.FINDROID_KEY_ALIAS }}
FINDROID_KEY_PASSWORD: ${{ secrets.FINDROID_KEY_PASSWORD }}
FINDROID_PLAY_API_CREDENTIALS: ${{ steps.findroid_play_api_credentials.outputs.filePath }}
- name: Create release
uses: softprops/action-gh-release@v2
with:
draft: true
files: |
./app/phone/build/outputs/apk/libre/release/findroid-${{ github.ref_name }}-libre-arm64-v8a.apk
./app/phone/build/outputs/apk/libre/release/findroid-${{ github.ref_name }}-libre-armeabi-v7a.apk
./app/phone/build/outputs/apk/libre/release/findroid-${{ github.ref_name }}-libre-x86_64.apk
./app/phone/build/outputs/apk/libre/release/findroid-${{ github.ref_name }}-libre-x86.apk

8
.gitignore vendored
View file

@ -30,4 +30,10 @@ render.experimental.xml
google-services.json
# Android Profiling
*.hprof
*.hprof
# Fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output

3
Gemfile Normal file
View file

@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "fastlane"

218
Gemfile.lock Normal file
View file

@ -0,0 +1,218 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.7)
base64
nkf
rexml
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.0)
aws-partitions (1.913.0)
aws-sdk-core (3.191.6)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.79.0)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.146.1)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.8)
aws-sigv4 (1.8.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107)
dotenv (2.8.1)
emoji_regex (3.2.3)
excon (0.110.0)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.3.1)
fastlane (2.220.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.5)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.7.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.4.0)
google-cloud-storage (1.47.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.6.2)
json (2.7.2)
jwt (2.8.1)
base64
mini_magick (4.12.0)
mini_mime (1.1.5)
multi_json (1.15.0)
multipart-post (2.4.0)
nanaimo (0.3.0)
naturally (2.2.1)
nkf (0.2.0)
optparse (0.4.0)
os (1.1.4)
plist (3.7.1)
public_suffix (5.0.5)
rake (13.2.1)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.6)
rouge (2.0.7)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.5)
signet (0.19.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unicode-display_width (2.5.0)
word_wrap (1.0.0)
xcodeproj (1.24.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
x86_64-linux
DEPENDENCIES
fastlane
BUNDLED WITH
2.5.4

View file

@ -14,7 +14,7 @@ I am developing this application in my spare time.
**This project is in its early stages so expect bugs.**
<a href='https://play.google.com/store/apps/details?id=dev.jdtech.jellyfin'><img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png' height="80"/></a><a href='http://www.amazon.com/gp/product/B0BTWC8DNZ'><img alt='Available at Amazon Appstore' src='https://user-images.githubusercontent.com/32322857/219019331-027a6775-7362-44bb-a026-281f71e9b37b.png' height="80"/></a><a href='https://appgallery.huawei.com/app/C107646987'><img alt='Explore it on Huawei AppGallery' src='https://user-images.githubusercontent.com/32322857/219013519-f0a11e17-c32c-42fd-8009-ab77fe2c23e7.png' height="80"/></a><a href='https://apt.izzysoft.de/fdroid/index/apk/dev.jdtech.jellyfin'><img alt='Get it on IzzyOnDroid' src='https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png' height="80"/></a>
<a href='https://play.google.com/store/apps/details?id=dev.jdtech.jellyfin'><img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png' height="80"/></a><a href='http://www.amazon.com/gp/product/B0BTWC8DNZ'><img alt='Available at Amazon Appstore' src='https://user-images.githubusercontent.com/32322857/219019331-027a6775-7362-44bb-a026-281f71e9b37b.png' height="80"/></a><a href='https://apt.izzysoft.de/fdroid/index/apk/dev.jdtech.jellyfin'><img alt='Get it on IzzyOnDroid' src='https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png' height="80"/></a>
## Screenshots
| Home | Library | Movie | Season | Episode |
@ -29,7 +29,7 @@ I am developing this application in my spare time.
- ExoPlayer
- Video codecs: H.263, H.264, H.265, VP8, VP9, AV1
- Support depends on Android device
- Audio codecs: Vorbis, Opus, FLAC, ALAC, PCM, MP3, AMR-NB, AMR-WB, AAC, AC-3, E-AC-3, DTS, DTS-HD, TrueHD
- Audio codecs: Vorbis, Opus, FLAC, ALAC, PCM, MP3, AAC, AC-3, E-AC-3, DTS, DTS-HD, TrueHD
- Support provided by ExoPlayer FFmpeg extension
- Subtitle codecs: SRT, VTT, SSA/ASS, PGSSUB
- SSA/ASS has limited styling support see [this issue](https://github.com/google/ExoPlayer/issues/8435)

View file

@ -21,6 +21,20 @@ android {
versionCode = Versions.appCode
versionName = Versions.appName
testInstrumentationRunner = "dev.jdtech.jellyfin.HiltTestRunner"
}
applicationVariants.all {
val variant = this
variant.outputs
.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
.forEach { output ->
if (variant.buildType.name == "release") {
val outputFileName = "findroid-v${variant.versionName}-${variant.flavorName}-${output.getFilter("ABI")}.apk"
output.outputFileName = outputFileName
}
}
}
buildTypes {
@ -47,9 +61,6 @@ android {
dimension = "variant"
isDefault = true
}
register("huawei") {
dimension = "variant"
}
}
splits {
@ -61,6 +72,8 @@ android {
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = Versions.java
targetCompatibility = Versions.java
}
@ -109,7 +122,14 @@ dependencies {
implementation(libs.jellyfin.core)
compileOnly(libs.libmpv)
implementation(libs.material)
implementation(libs.media3.ffmpeg.decoder)
implementation(libs.timber)
implementation(rootProject.files("libs/lib-decoder-ffmpeg-release.aar"))
coreLibraryDesugaring(libs.android.desugar.jdk)
androidTestImplementation(libs.androidx.room.runtime)
androidTestImplementation(libs.junit)
androidTestImplementation(libs.bundles.androidx.test)
androidTestImplementation(libs.hilt.android.testing)
kspTest(libs.hilt.android.compiler)
}

View file

@ -0,0 +1,16 @@
package dev.jdtech.jellyfin
import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import dagger.hilt.android.testing.HiltTestApplication
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?,
): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}

View file

@ -0,0 +1,95 @@
package dev.jdtech.jellyfin
import android.util.Log
import androidx.hilt.work.HiltWorkerFactory
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isEnabled
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.platform.app.InstrumentationRegistry
import androidx.work.Configuration
import androidx.work.testing.SynchronousExecutor
import androidx.work.testing.WorkManagerTestInitHelper
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import dev.jdtech.jellyfin.di.DatabaseModule
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.not
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import javax.inject.Inject
@HiltAndroidTest
@UninstallModules(DatabaseModule::class)
class MainActivityTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@Inject
lateinit var workerFactory: HiltWorkerFactory
@Before
fun setUp() {
hiltRule.inject()
val context = InstrumentationRegistry.getInstrumentation().targetContext
val config = Configuration.Builder()
.setWorkerFactory(workerFactory)
.setMinimumLoggingLevel(Log.DEBUG)
.setExecutor(SynchronousExecutor())
.build()
// Initialize WorkManager for instrumentation tests.
WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
}
@Test
fun testMainFlow() {
launchActivity<MainActivity>().use {
// Wait for the app to load
waitForElement(allOf(withId(R.id.edit_text_server_address), isDisplayed()))
// Connect to demo server
onView(withId(R.id.edit_text_server_address)).perform(typeText("https://demo.jellyfin.org/stable"), closeSoftKeyboard())
onView(withId(R.id.button_connect)).perform(click())
// Connecting to the server
waitForElement(allOf(withId(R.id.edit_text_username), isDisplayed()))
// Login
onView(withId(R.id.edit_text_username)).perform(typeText("demo"), closeSoftKeyboard())
onView(withId(R.id.button_login)).perform(click())
// Navigate to My media
waitForElement(allOf(withText("Continue Watching"), isDisplayed()))
onView(withId(R.id.mediaFragment)).perform(click())
// Navigate to movies
waitForElement(allOf(withText("Movies"), isDisplayed()))
onView(withText("Movies")).perform(click())
// Navigate to Battle of the Stars
waitForElement(allOf(withText("Battle of the Stars"), isDisplayed()))
onView(withText("Battle of the Stars")).perform(click())
// Play the movie
waitForElement(allOf(withId(R.id.play_button), isEnabled()))
onView(withId(R.id.play_button)).perform(click())
// Wait for movie to start playing
waitForElement(allOf(withId(androidx.media3.ui.R.id.exo_buffering), isDisplayed()))
waitForElement(allOf(withId(androidx.media3.ui.R.id.exo_buffering), not(isDisplayed())))
// Navigate back
Espresso.pressBack()
}
}
}

View file

@ -0,0 +1,64 @@
package dev.jdtech.jellyfin
import android.view.View
import android.view.ViewTreeObserver
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.IdlingResource
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import org.hamcrest.CoreMatchers
import org.hamcrest.Matcher
import org.hamcrest.StringDescription
private class ViewPropertyChangeCallback(private val matcher: Matcher<View>, private val view: View) : IdlingResource, ViewTreeObserver.OnDrawListener {
private lateinit var callback: IdlingResource.ResourceCallback
private var matched = false
override fun getName() = "View property change callback"
override fun isIdleNow() = matched
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) {
this.callback = callback
}
override fun onDraw() {
matched = matcher.matches(view)
callback.onTransitionToIdle()
}
}
fun waitUntil(matcher: Matcher<View>): ViewAction = object : ViewAction {
override fun getConstraints(): Matcher<View> {
return CoreMatchers.any(View::class.java)
}
override fun getDescription(): String {
return StringDescription().let {
matcher.describeTo(it)
"wait until: $it"
}
}
override fun perform(uiController: UiController, view: View) {
if (!matcher.matches(view)) {
ViewPropertyChangeCallback(matcher, view).run {
try {
IdlingRegistry.getInstance().register(this)
view.viewTreeObserver.addOnDrawListener(this)
uiController.loopMainThreadUntilIdle()
} finally {
view.viewTreeObserver.removeOnDrawListener(this)
IdlingRegistry.getInstance().unregister(this)
}
}
}
}
}
fun waitForElement(matcher: Matcher<View>) {
onView(isRoot()).perform(waitUntil(hasDescendant(matcher)))
}

View file

@ -0,0 +1,29 @@
package dev.jdtech.jellyfin.di
import android.content.Context
import androidx.room.Room
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dev.jdtech.jellyfin.database.ServerDatabase
import dev.jdtech.jellyfin.database.ServerDatabaseDao
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object DatabaseTestModule {
@Singleton
@Provides
fun provideServerDatabaseDao(@ApplicationContext app: Context): ServerDatabaseDao {
return Room.inMemoryDatabaseBuilder(
app.applicationContext,
ServerDatabase::class.java,
)
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build()
.getServerDatabaseDao()
}
}

View file

@ -200,7 +200,9 @@ class PlayerActivity : BasePlayerActivity() {
is PlayerEvents.NavigateBack -> finish()
is PlayerEvents.IsPlayingChanged -> {
if (appPreferences.playerPipGesture) {
setPictureInPictureParams(pipParams(event.isPlaying))
try {
setPictureInPictureParams(pipParams(event.isPlaying))
} catch (_: IllegalArgumentException) { }
}
}
}

View file

@ -1,5 +1,6 @@
package dev.jdtech.jellyfin.adapters
import android.text.Html.fromHtml
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
@ -45,7 +46,7 @@ class EpisodeListAdapter(
binding.root.context.getString(CoreR.string.episode_name_with_end, episode.indexNumber, episode.indexNumberEnd, episode.name)
}
binding.episodeOverview.text = episode.overview
binding.episodeOverview.text = fromHtml(episode.overview, 0)
if (episode.playbackPositionTicks > 0) {
binding.progressBar.layoutParams.width = TypedValue.applyDimension(

View file

@ -24,6 +24,7 @@ import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.viewmodels.CollectionViewModel
import kotlinx.coroutines.launch
import timber.log.Timber
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint
class CollectionFragment : Fragment() {
@ -40,6 +41,8 @@ class CollectionFragment : Fragment() {
): View {
binding = FragmentFavoriteBinding.inflate(inflater, container, false)
binding.noFavoritesText.text = getString(CoreR.string.collection_no_media)
binding.favoritesRecyclerView.adapter = FavoritesListAdapter { item ->
navigateToMediaItem(item)
}

View file

@ -2,6 +2,7 @@ package dev.jdtech.jellyfin.fragments
import android.app.DownloadManager
import android.os.Bundle
import android.text.Html.fromHtml
import android.text.format.Formatter
import android.util.TypedValue
import android.view.LayoutInflater
@ -285,11 +286,13 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
}
binding.seriesName.text = episode.seriesName
binding.overview.text = episode.overview
binding.overview.text = fromHtml(episode.overview, 0)
binding.year.text = formatDateTime(episode.premiereDate)
binding.playtime.text = getString(CoreR.string.runtime_minutes, episode.runtimeTicks.div(600000000))
binding.communityRating.isVisible = episode.communityRating != null
binding.communityRating.text = episode.communityRating.toString()
episode.communityRating?.also {
binding.communityRating.text = episode.communityRating.toString()
binding.communityRating.isVisible = true
}
binding.missingIcon.isVisible = false
if (appPreferences.displayExtraInfo) {

View file

@ -4,6 +4,7 @@ import android.app.DownloadManager
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.Html.fromHtml
import android.text.format.Formatter
import android.view.LayoutInflater
import android.view.View
@ -276,7 +277,6 @@ class MovieFragment : Fragment() {
if (item.trailer != null) {
binding.itemActions.trailerButton.isVisible = true
}
binding.communityRating.isVisible = item.communityRating != null
binding.actors.isVisible = actors.isNotEmpty()
binding.itemActions.playButton.isEnabled = item.canPlay && item.sources.isNotEmpty()
@ -309,7 +309,10 @@ class MovieFragment : Fragment() {
binding.playtime.text = runTime
}
binding.officialRating.text = item.officialRating
binding.communityRating.text = item.communityRating.toString()
item.communityRating?.also {
binding.communityRating.text = it.toString()
binding.communityRating.isVisible = true
}
videoMetadata.let {
with(binding) {
@ -379,7 +382,7 @@ class MovieFragment : Fragment() {
binding.info.sizeGroup.isVisible = size != null
}
binding.info.description.text = item.overview
binding.info.description.text = fromHtml(item.overview, 0)
binding.info.genres.text = genresString
binding.info.genresGroup.isVisible = item.genres.isNotEmpty()
binding.info.director.text = director?.name

View file

@ -3,6 +3,7 @@ package dev.jdtech.jellyfin.fragments
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.Html.fromHtml
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -170,7 +171,6 @@ class ShowFragment : Fragment() {
if (item.trailer != null) {
binding.itemActions.trailerButton.isVisible = true
}
binding.communityRating.isVisible = item.communityRating != null
binding.actors.isVisible = actors.isNotEmpty()
// TODO currently the sources of a show is always empty, we need a way to check if sources are available
@ -212,9 +212,12 @@ class ShowFragment : Fragment() {
binding.playtime.text = runTime
}
binding.officialRating.text = item.officialRating
binding.communityRating.text = item.communityRating.toString()
item.communityRating?.also {
binding.communityRating.text = item.communityRating.toString()
binding.communityRating.isVisible = true
}
binding.info.description.text = item.overview
binding.info.description.text = fromHtml(item.overview, 0)
binding.info.genres.text = genresString
binding.info.genresGroup.isVisible = item.genres.isNotEmpty()
binding.info.director.text = director?.name

View file

@ -1,8 +1,8 @@
import org.gradle.api.JavaVersion
object Versions {
const val appCode = 23
const val appName = "2024.02"
const val appCode = 25
const val appName = "0.14.2"
const val compileSdk = 34
const val buildTools = "34.0.0"
@ -11,6 +11,6 @@ object Versions {
val java = JavaVersion.VERSION_17
const val composeCompiler = "1.5.10"
const val composeCompiler = "1.5.11"
const val ktlint = "0.50.0"
}

View file

@ -29,7 +29,6 @@ android {
flavorDimensions += "variant"
productFlavors {
register("libre")
register("huawei")
}
compileOptions {

View file

@ -1,81 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="1536dp"
android:height="512dp"
android:viewportWidth="1536"
android:viewportHeight="512">
<group android:scaleX="0.62"
android:scaleY="0.62"
android:translateX="-60"
android:translateY="-60">
<path
android:pathData="m512,136.5c-99.4,0 -419.3,580 -370.5,678 48.7,98 692.8,96.8 741.1,0 48.3,-96.8 -271.1,-678 -370.5,-678zM512,285.3c65,0 274.5,380.7 242.9,444.3 -31.6,63.4 -453.6,64.2 -485.6,0C237.4,665.3 447,285.3 512,285.3ZM437.6,503.2c18.3,51.8 26.5,80.7 2.8,129.3 -5.5,11.4 -0.7,20.2 11.9,20.2l131.1,0.9c12.5,0.1 19,-9.3 13.7,-20.6 -19.3,-41.2 -69.6,-130.3 -149.6,-142.7 -8.2,-1.3 -12.8,5 -10,12.9z"
android:strokeWidth="0.23938">
<aapt:attr name="android:fillColor">
<gradient
android:startY="479.77658"
android:startX="363.41766"
android:endY="702.5666"
android:endX="749.3077"
android:type="linear">
<item android:offset="0" android:color="@color/logo_primary"/>
<item android:offset="1" android:color="@color/logo_secondary"/>
</gradient>
</aapt:attr>
</path>
</group>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m569.69,357.11q-3.73,0 -6.13,-2.4 -2.13,-2.4 -2.13,-5.6v-170.67q0,-3.2 2.4,-5.6t5.6,-2.4h97.07q3.47,0 5.6,2.4 2.4,2.13 2.4,5.6 0,3.2 -2.4,5.6 -2.13,2.13 -5.6,2.13h-89.87l1.07,-1.6v70.93l-1.33,-2.4h78.13q3.47,0 5.6,2.4 2.4,2.13 2.4,5.33 0,3.47 -2.4,5.6 -2.13,2.13 -5.6,2.13h-78.67l1.87,-2.13v82.67q0,3.2 -2.4,5.6 -2.13,2.4 -5.6,2.4z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m723.83,349.11q0,3.2 -2.4,5.6t-5.6,2.4q-3.47,0 -5.87,-2.4 -2.13,-2.4 -2.13,-5.6v-122.67q0,-3.2 2.13,-5.6 2.4,-2.4 5.87,-2.4t5.6,2.4q2.4,2.4 2.4,5.6zM715.83,200.58q-5.6,0 -8.53,-2.4 -2.67,-2.67 -2.67,-7.47v-2.67q0,-4.8 2.93,-7.2 3.2,-2.67 8.53,-2.67 5.07,0 7.73,2.67 2.93,2.4 2.93,7.2v2.67q0,4.8 -2.93,7.47 -2.67,2.4 -8,2.4z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m829.69,217.65q17.6,0 28,7.2 10.67,6.93 15.2,19.2 4.8,12 4.8,26.67v78.4q0,3.2 -2.4,5.6t-5.6,2.4q-3.73,0 -5.87,-2.4t-2.13,-5.6v-77.6q0,-10.67 -3.47,-19.47t-11.47,-14.13q-7.73,-5.33 -20.53,-5.33 -11.47,0 -21.87,5.33 -10.13,5.33 -16.53,14.13 -6.4,8.8 -6.4,19.47v77.6q0,3.2 -2.4,5.6 -2.4,2.4 -5.6,2.4 -3.73,0 -5.87,-2.4 -2.13,-2.4 -2.13,-5.6v-119.47q0,-3.2 2.13,-5.6 2.4,-2.4 5.87,-2.4t5.6,2.4q2.4,2.4 2.4,5.6v22.4l-6.13,9.6q0.53,-8.53 5.33,-16.27 5.07,-8 12.8,-14.13 7.73,-6.4 17.07,-9.87 9.6,-3.73 19.2,-3.73z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1030.2,159.78q3.47,0 5.6,2.4 2.4,2.13 2.4,5.6v181.33q0,3.2 -2.4,5.6t-5.6,2.4q-3.73,0 -5.87,-2.4 -2.13,-2.4 -2.13,-5.6v-31.73l4.53,-3.73q0,7.47 -4,15.73 -4,8 -11.47,14.93 -7.2,6.93 -17.07,11.2 -9.6,4.27 -21.07,4.27 -17.6,0 -32,-9.33 -14.13,-9.33 -22.4,-25.33 -8.27,-16 -8.27,-36.53 0,-20.27 8.27,-36.27 8.27,-16.27 22.4,-25.33 14.13,-9.33 31.73,-9.33 11.2,0 21.07,4 9.87,4 17.33,10.93 7.73,6.93 12,16 4.53,8.8 4.53,18.4l-5.6,-4v-95.2q0,-3.2 2.13,-5.6 2.13,-2.4 5.87,-2.4zM974.73,344.85q14.13,0 25.07,-7.2 10.93,-7.47 17.07,-20 6.4,-12.8 6.4,-29.07 0,-16 -6.4,-28.53 -6.13,-12.8 -17.07,-20 -10.93,-7.47 -25.07,-7.47 -13.87,0 -25.07,7.47 -10.93,7.2 -17.33,20 -6.13,12.53 -6.13,28.53t6.13,28.8q6.4,12.8 17.33,20.27 11.2,7.2 25.07,7.2z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1088.1,357.11q-3.73,0 -5.87,-2.4 -2.13,-2.4 -2.13,-5.6v-119.47q0,-3.2 2.13,-5.6 2.4,-2.4 5.87,-2.4t5.6,2.4q2.4,2.4 2.4,5.6v40l-4,0.8q0.8,-9.33 4.53,-18.4 4,-9.33 10.67,-17.07t15.73,-12.53q9.33,-4.8 20.8,-4.8 4.8,0 9.33,2.13 4.53,1.87 4.53,6.4 0,4 -2.13,6.13 -2.13,2.13 -5.07,2.13 -2.4,0 -5.33,-1.33 -2.67,-1.33 -7.2,-1.33 -7.47,0 -14.93,4.53 -7.47,4.27 -13.6,11.73 -6.13,7.47 -9.87,16.8 -3.47,9.07 -3.47,18.4v65.87q0,3.2 -2.4,5.6t-5.6,2.4z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1302.8,288.85q0,20.27 -9.07,36.53 -8.8,16 -24,25.33 -15.2,9.07 -34.4,9.07 -18.93,0 -34.4,-9.07 -15.2,-9.33 -24.27,-25.33 -8.8,-16.27 -8.8,-36.53 0,-20.53 8.8,-36.53 9.07,-16 24.27,-25.33 15.47,-9.33 34.4,-9.33 19.2,0 34.4,9.33 15.2,9.33 24,25.33 9.07,16 9.07,36.53zM1286.8,288.85q0,-16.27 -6.67,-28.8 -6.67,-12.8 -18.4,-20 -11.47,-7.47 -26.4,-7.47 -14.67,0 -26.4,7.47 -11.47,7.2 -18.4,20 -6.67,12.53 -6.67,28.8 0,16.27 6.67,28.8 6.93,12.53 18.4,20 11.73,7.2 26.4,7.2 14.93,0 26.4,-7.2 11.73,-7.47 18.4,-20 6.67,-12.53 6.67,-28.8z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1351,349.11q0,3.2 -2.4,5.6t-5.6,2.4q-3.47,0 -5.87,-2.4 -2.13,-2.4 -2.13,-5.6v-122.67q0,-3.2 2.13,-5.6 2.4,-2.4 5.87,-2.4 3.47,0 5.6,2.4 2.4,2.4 2.4,5.6zM1343,200.58q-5.6,0 -8.53,-2.4 -2.67,-2.67 -2.67,-7.47v-2.67q0,-4.8 2.93,-7.2 3.2,-2.67 8.53,-2.67 5.07,0 7.73,2.67 2.93,2.4 2.93,7.2v2.67q0,4.8 -2.93,7.47 -2.67,2.4 -8,2.4z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1503.3,159.78q3.47,0 5.6,2.4 2.4,2.13 2.4,5.6v181.33q0,3.2 -2.4,5.6t-5.6,2.4q-3.73,0 -5.87,-2.4 -2.13,-2.4 -2.13,-5.6v-31.73l4.53,-3.73q0,7.47 -4,15.73 -4,8 -11.47,14.93 -7.2,6.93 -17.07,11.2 -9.6,4.27 -21.07,4.27 -17.6,0 -32,-9.33 -14.13,-9.33 -22.4,-25.33 -8.27,-16 -8.27,-36.53 0,-20.27 8.27,-36.27 8.27,-16.27 22.4,-25.33 14.13,-9.33 31.73,-9.33 11.2,0 21.07,4 9.87,4 17.33,10.93 7.73,6.93 12,16 4.53,8.8 4.53,18.4l-5.6,-4v-95.2q0,-3.2 2.13,-5.6 2.13,-2.4 5.87,-2.4zM1447.83,344.85q14.13,0 25.07,-7.2 10.93,-7.47 17.07,-20 6.4,-12.8 6.4,-29.07 0,-16 -6.4,-28.53 -6.13,-12.8 -17.07,-20 -10.93,-7.47 -25.07,-7.47 -13.87,0 -25.07,7.47 -10.93,7.2 -17.33,20 -6.13,12.53 -6.13,28.53t6.13,28.8q6.4,12.8 17.33,20.27 11.2,7.2 25.07,7.2z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1093.4,453.74q-1.19,0 -1.96,-0.77 -0.68,-0.77 -0.68,-1.79v-54.61q0,-1.02 0.77,-1.79t1.79,-0.77h31.06q1.11,0 1.79,0.77 0.77,0.68 0.77,1.79 0,1.02 -0.77,1.79 -0.68,0.68 -1.79,0.68h-28.76l0.34,-0.51v22.7l-0.43,-0.77h25q1.11,0 1.79,0.77 0.77,0.68 0.77,1.71 0,1.11 -0.77,1.79 -0.68,0.68 -1.79,0.68h-25.17l0.6,-0.68v26.45q0,1.02 -0.77,1.79 -0.68,0.77 -1.79,0.77z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1176.8,431.9q0,6.49 -2.9,11.69 -2.82,5.12 -7.68,8.11 -4.86,2.9 -11.01,2.9 -6.06,0 -11.01,-2.9 -4.86,-2.99 -7.77,-8.11 -2.82,-5.21 -2.82,-11.69 0,-6.57 2.82,-11.69 2.9,-5.12 7.77,-8.11 4.95,-2.99 11.01,-2.99 6.14,0 11.01,2.99 4.86,2.99 7.68,8.11 2.9,5.12 2.9,11.69zM1171.68,431.9q0,-5.21 -2.13,-9.22 -2.13,-4.1 -5.89,-6.4 -3.67,-2.39 -8.45,-2.39 -4.69,0 -8.45,2.39 -3.67,2.3 -5.89,6.4 -2.13,4.01 -2.13,9.22 0,5.21 2.13,9.22 2.22,4.01 5.89,6.4 3.75,2.3 8.45,2.3 4.78,0 8.45,-2.3 3.75,-2.39 5.89,-6.4 2.13,-4.01 2.13,-9.22z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1189.9,453.74q-1.19,0 -1.88,-0.77 -0.68,-0.77 -0.68,-1.79v-38.23q0,-1.02 0.68,-1.79 0.77,-0.77 1.88,-0.77 1.11,0 1.79,0.77 0.77,0.77 0.77,1.79v12.8l-1.28,0.26q0.26,-2.99 1.45,-5.89 1.28,-2.99 3.41,-5.46 2.13,-2.47 5.03,-4.01 2.99,-1.54 6.66,-1.54 1.54,0 2.99,0.68 1.45,0.6 1.45,2.05 0,1.28 -0.68,1.96 -0.68,0.68 -1.62,0.68 -0.77,0 -1.71,-0.43 -0.85,-0.43 -2.3,-0.43 -2.39,0 -4.78,1.45 -2.39,1.37 -4.35,3.75 -1.96,2.39 -3.16,5.38 -1.11,2.9 -1.11,5.89v21.08q0,1.02 -0.77,1.79t-1.79,0.77z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1258.9,454.59q-5.38,0 -9.64,-2.99 -4.27,-2.99 -6.49,-7.85 -0.43,-0.77 -0.43,-1.37 0,-1.11 0.85,-1.71 0.85,-0.68 1.71,-0.68t1.37,0.43q0.6,0.43 1.02,1.02 1.62,3.58 4.69,5.8 3.07,2.22 6.91,2.22 3.93,0 6.91,-1.62 2.99,-1.71 4.61,-4.69 1.71,-2.99 1.71,-6.83v-39.76q0,-1.02 0.77,-1.79 0.85,-0.77 1.96,-0.77 1.19,0 1.88,0.77 0.77,0.77 0.77,1.79v39.76q0,5.29 -2.39,9.47 -2.39,4.1 -6.57,6.49 -4.18,2.3 -9.64,2.3z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1311.6,454.59q-6.57,0 -11.6,-2.82t-7.85,-7.85q-2.82,-5.03 -2.82,-11.78 0,-7.25 2.82,-12.37 2.9,-5.12 7.42,-7.85 4.61,-2.82 9.73,-2.82 3.75,0 7.25,1.37 3.58,1.28 6.31,3.93 2.73,2.56 4.44,6.31 1.71,3.75 1.79,8.7 0,1.02 -0.77,1.79 -0.77,0.68 -1.79,0.68h-34.22l-1.02,-4.61h33.62l-1.11,1.02v-1.71q-0.43,-4.01 -2.65,-6.83 -2.22,-2.82 -5.38,-4.27 -3.07,-1.45 -6.49,-1.45 -2.56,0 -5.29,1.02 -2.65,1.02 -4.86,3.24 -2.13,2.13 -3.5,5.55 -1.37,3.33 -1.37,7.94 0,5.03 2.05,9.13 2.05,4.1 5.89,6.49 3.84,2.39 9.3,2.39 2.9,0 5.29,-0.85 2.39,-0.85 4.18,-2.22 1.88,-1.45 3.07,-2.99 0.94,-0.77 1.79,-0.77 0.94,0 1.54,0.68 0.68,0.68 0.68,1.54 0,1.02 -0.85,1.79 -2.56,3.07 -6.66,5.38 -4.1,2.22 -8.96,2.22z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1345.4,451.18q0,1.02 -0.77,1.79t-1.79,0.77q-1.11,0 -1.88,-0.77 -0.68,-0.77 -0.68,-1.79v-58.03q0,-1.02 0.77,-1.79t1.79,-0.77q1.11,0 1.79,0.77 0.77,0.77 0.77,1.79z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1365,451.18q0,1.02 -0.77,1.79t-1.79,0.77q-1.11,0 -1.88,-0.77 -0.68,-0.77 -0.68,-1.79v-58.03q0,-1.02 0.77,-1.79t1.79,-0.77q1.11,0 1.79,0.77 0.77,0.77 0.77,1.79z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1410.2,409.37q1.11,0 1.79,0.77 0.77,0.77 0.77,1.79v37.63q0,6.91 -2.73,11.6 -2.73,4.78 -7.34,7.17 -4.61,2.47 -10.5,2.47 -3.67,0 -6.83,-0.85 -3.07,-0.77 -5.03,-2.05 -1.02,-0.6 -1.54,-1.45t-0.09,-1.79q0.43,-1.19 1.28,-1.62 0.94,-0.34 1.88,0.09 1.45,0.77 4.18,1.88 2.73,1.11 6.23,1.11 4.69,0 8.11,-1.96 3.5,-1.96 5.38,-5.72 1.88,-3.67 1.88,-8.79v-6.14l0.6,2.05q-1.28,2.65 -3.67,4.69 -2.3,2.05 -5.38,3.24 -2.99,1.11 -6.4,1.11 -5.12,0 -8.53,-2.05 -3.33,-2.13 -4.95,-5.8t-1.62,-8.62v-26.2q0,-1.02 0.68,-1.79 0.68,-0.77 1.88,-0.77 1.11,0 1.79,0.77 0.77,0.77 0.77,1.79v25.43q0,5.97 2.56,9.22 2.65,3.24 8.53,3.24 3.67,0 6.74,-1.71 3.07,-1.79 5.03,-4.61 1.96,-2.9 1.96,-6.14v-25.43q0,-1.02 0.68,-1.79 0.77,-0.77 1.88,-0.77z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1441.9,390.94q1.28,0 2.73,0.26 1.54,0.26 2.65,0.94 1.11,0.6 1.11,1.88 0,0.94 -0.68,1.71 -0.68,0.68 -1.54,0.68 -0.85,0 -2.13,-0.43 -1.28,-0.51 -2.73,-0.51 -1.79,0 -3.07,0.85 -1.28,0.77 -1.96,2.3 -0.68,1.45 -0.68,3.58v48.98q0,1.02 -0.77,1.79 -0.68,0.77 -1.79,0.77t-1.88,-0.77q-0.68,-0.77 -0.68,-1.79v-48.98q0,-5.46 3.16,-8.36 3.24,-2.9 8.28,-2.9zM1445.14,410.99q1.02,0 1.71,0.68 0.68,0.68 0.68,1.71t-0.68,1.71q-0.68,0.68 -1.71,0.68h-20.91q-0.94,0 -1.71,-0.68 -0.68,-0.77 -0.68,-1.71 0,-1.11 0.68,-1.71 0.77,-0.68 1.71,-0.68zM1461.19,451.18q0,1.02 -0.77,1.79t-1.79,0.77q-1.11,0 -1.88,-0.77 -0.68,-0.77 -0.68,-1.79v-39.25q0,-1.02 0.68,-1.79 0.77,-0.77 1.88,-0.77t1.79,0.77q0.77,0.77 0.77,1.79zM1458.63,403.65q-1.79,0 -2.73,-0.77 -0.85,-0.85 -0.85,-2.39v-0.85q0,-1.54 0.94,-2.3 1.02,-0.85 2.73,-0.85 1.62,0 2.47,0.85 0.94,0.77 0.94,2.3v0.85q0,1.54 -0.94,2.39 -0.85,0.77 -2.56,0.77z"/>
<path
android:fillColor="?attr/colorOnBackground"
android:pathData="m1495.1,409.11q5.63,0 8.96,2.3 3.41,2.22 4.86,6.14 1.54,3.84 1.54,8.53v25.09q0,1.02 -0.77,1.79 -0.77,0.77 -1.79,0.77 -1.19,0 -1.88,-0.77 -0.68,-0.77 -0.68,-1.79v-24.83q0,-3.41 -1.11,-6.23 -1.11,-2.82 -3.67,-4.52 -2.47,-1.71 -6.57,-1.71 -3.67,0 -7,1.71 -3.24,1.71 -5.29,4.52t-2.05,6.23v24.83q0,1.02 -0.77,1.79t-1.79,0.77q-1.19,0 -1.88,-0.77t-0.68,-1.79v-38.23q0,-1.02 0.68,-1.79 0.77,-0.77 1.88,-0.77 1.11,0 1.79,0.77 0.77,0.77 0.77,1.79v7.17l-1.96,3.07q0.17,-2.73 1.71,-5.21 1.62,-2.56 4.1,-4.52 2.47,-2.05 5.46,-3.16 3.07,-1.19 6.14,-1.19z"/>
</vector>

View file

@ -1,60 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="320dp"
android:height="180dp"
android:viewportWidth="320"
android:viewportHeight="180">
<group android:scaleX="0.6666667"
android:scaleY="0.6666667"
android:translateX="53.333332"
android:translateY="30">
<group android:scaleX="1.6666666"
android:scaleY="1.6666666"
android:translateX="-16.4">
<group android:scaleX="0.056557618"
android:scaleY="0.056557618"
android:translateX="25.0425"
android:translateY="25.0425">
<path
android:pathData="m512,136.5c-99.4,0 -419.3,580 -370.5,678 48.7,98 692.8,96.8 741.1,0 48.3,-96.8 -271.1,-678 -370.5,-678zM512,285.3c65,0 274.5,380.7 242.9,444.3 -31.6,63.4 -453.6,64.2 -485.6,0C237.4,665.3 447,285.3 512,285.3ZM437.6,503.2c18.3,51.8 26.5,80.7 2.8,129.3 -5.5,11.4 -0.7,20.2 11.9,20.2l131.1,0.9c12.5,0.1 19,-9.3 13.7,-20.6 -19.3,-41.2 -69.6,-130.3 -149.6,-142.7 -8.2,-1.3 -12.8,5 -10,12.9z"
android:strokeWidth="0.23938">
<aapt:attr name="android:fillColor">
<gradient
android:startY="479.77658"
android:startX="363.41766"
android:endY="702.5666"
android:endX="749.3077"
android:type="linear">
<item android:offset="0" android:color="@color/logo_primary"/>
<item android:offset="1" android:color="@color/logo_secondary"/>
</gradient>
</aapt:attr>
</path>
</group>
</group>
<group android:scaleX="0.29483145"
android:scaleY="0.29483145"
android:translateX="128"
android:translateY="63.46516">
<group android:translateY="144.00006">
<path android:pathData="M17.28125,0.5Q15.984375,0.5,15.1875,-0.359375Q14.40625,-1.21875,14.40625,-2.375L14.40625,-97.125Q14.40625,-98.265625,15.265625,-99.125Q16.125,-100,17.28125,-100L71.5625,-100Q72.71875,-100,73.578125,-99.125Q74.453125,-98.265625,74.453125,-97.125Q74.453125,-95.828125,73.578125,-95.03125Q72.71875,-94.25,71.5625,-94.25L19.734375,-94.25L20.15625,-94.828125L20.15625,-53.59375L19.578125,-54.734375L65.09375,-54.734375Q66.234375,-54.734375,67.09375,-53.875Q67.96875,-53.015625,67.96875,-51.875Q67.96875,-50.578125,67.09375,-49.78125Q66.234375,-49,65.09375,-49L19.296875,-49L20.15625,-50.140625L20.15625,-2.375Q20.15625,-1.21875,19.359375,-0.359375Q18.578125,0.5,17.28125,0.5Z"
android:fillColor="#FFFFFF"/>
<path android:pathData="M99.71875,-2.875Q99.71875,-1.71875,98.84375,-0.859375Q97.984375,0,96.828125,0Q95.53125,0,94.734375,-0.859375Q93.953125,-1.71875,93.953125,-2.875L93.953125,-71.125Q93.953125,-72.28125,94.8125,-73.140625Q95.6875,-74,96.828125,-74Q98.125,-74,98.921875,-73.140625Q99.71875,-72.28125,99.71875,-71.125L99.71875,-2.875ZM96.828125,-83.65625Q94.53125,-83.65625,93.15625,-84.9375Q91.796875,-86.234375,91.796875,-88.25L91.796875,-89.390625Q91.796875,-91.40625,93.234375,-92.703125Q94.671875,-94,96.96875,-94Q98.984375,-94,100.359375,-92.703125Q101.734375,-91.40625,101.734375,-89.390625L101.734375,-88.25Q101.734375,-86.234375,100.359375,-84.9375Q98.984375,-83.65625,96.828125,-83.65625Z"
android:fillColor="#FFFFFF"/>
<path android:pathData="M156.64062,-74Q165.71875,-74,171.40625,-70.40625Q177.09375,-66.8125,179.75,-60.640625Q182.42188,-54.484375,182.42188,-46.859375L182.42188,-2.921875Q182.42188,-1.765625,181.54688,-0.90625Q180.6875,-0.046875,179.53125,-0.046875Q178.23438,-0.046875,177.4375,-0.90625Q176.65625,-1.765625,176.65625,-2.921875L176.65625,-46.28125Q176.65625,-52.46875,174.5625,-57.484375Q172.48438,-62.515625,167.9375,-65.53125Q163.40625,-68.546875,156.0625,-68.546875Q149.73438,-68.546875,143.67188,-65.53125Q137.625,-62.515625,133.67188,-57.484375Q129.71875,-52.46875,129.71875,-46.28125L129.71875,-2.921875Q129.71875,-1.765625,128.84375,-0.90625Q127.984375,-0.046875,126.828125,-0.046875Q125.53125,-0.046875,124.734375,-0.90625Q123.953125,-1.765625,123.953125,-2.921875L123.953125,-68.828125Q123.953125,-69.984375,124.8125,-70.84375Q125.6875,-71.703125,126.828125,-71.703125Q128.125,-71.703125,128.92188,-70.84375Q129.71875,-69.984375,129.71875,-68.828125L129.71875,-54.765625L126.109375,-47.875Q126.109375,-53.0625,128.84375,-57.796875Q131.57812,-62.53125,136.04688,-66.1875Q140.51562,-69.84375,145.90625,-71.921875Q151.3125,-74,156.64062,-74Z"
android:fillColor="#FFFFFF"/>
<path android:pathData="M264.84375,-106Q266.14062,-106,266.9375,-105.140625Q267.73438,-104.28125,267.73438,-103.15625L267.73438,-2.84375Q267.73438,-1.6875,266.85938,-0.828125Q266,0.03125,264.84375,0.03125Q263.54688,0.03125,262.75,-0.828125Q261.96875,-1.6875,261.96875,-2.84375L261.96875,-23.265625L264.26562,-26.421875Q264.26562,-21.53125,262.03125,-16.5625Q259.8125,-11.609375,255.70312,-7.515625Q251.59375,-3.421875,246.125,-0.96875Q240.65625,1.46875,234.3125,1.46875Q224.8125,1.46875,217.25,-3.484375Q209.70312,-8.453125,205.29688,-17Q200.90625,-25.5625,200.90625,-36.34375Q200.90625,-47.109375,205.29688,-55.671875Q209.70312,-64.234375,217.25,-69.109375Q224.8125,-74,234.3125,-74Q240.21875,-74,245.625,-71.765625Q251.03125,-69.546875,255.20312,-65.515625Q259.375,-61.5,261.8125,-56.09375Q264.26562,-50.703125,264.26562,-44.390625L261.96875,-47.984375L261.96875,-103.15625Q261.96875,-104.296875,262.75,-105.140625Q263.54688,-106,264.84375,-106ZM234.60938,-4Q242.8125,-4,249.07812,-8.15625Q255.34375,-12.328125,258.9375,-19.65625Q262.54688,-27,262.54688,-36.34375Q262.54688,-45.6875,258.9375,-52.9375Q255.34375,-60.203125,249,-64.375Q242.67188,-68.546875,234.60938,-68.546875Q226.6875,-68.546875,220.34375,-64.375Q214.01562,-60.203125,210.34375,-52.9375Q206.67188,-45.6875,206.67188,-36.34375Q206.67188,-27.140625,210.34375,-19.796875Q214.01562,-12.46875,220.34375,-8.234375Q226.6875,-4,234.60938,-4Z"
android:fillColor="#FFFFFF"/>
<path android:pathData="M294.82812,0.03125Q293.53125,0.03125,292.73438,-0.828125Q291.95312,-1.6875,291.95312,-2.84375L291.95312,-68.828125Q291.95312,-69.984375,292.8125,-70.84375Q293.6875,-71.703125,294.82812,-71.703125Q296.125,-71.703125,296.92188,-70.84375Q297.71875,-69.984375,297.71875,-68.828125L297.71875,-44.546875L295.26562,-40.796875Q295.26562,-46.390625,297.20312,-52.140625Q299.15625,-57.90625,302.89062,-62.859375Q306.64062,-67.828125,312.03125,-70.90625Q317.4375,-74,324.5,-74Q326.51562,-74,328.8125,-73.421875Q331.125,-72.859375,331.125,-70.703125Q331.125,-69.40625,330.40625,-68.546875Q329.6875,-67.6875,328.53125,-67.6875Q327.65625,-67.6875,326.4375,-68.328125Q325.21875,-68.96875,322.90625,-68.96875Q318.29688,-68.96875,313.82812,-66.234375Q309.375,-63.515625,305.70312,-58.984375Q302.03125,-54.46875,299.875,-49.140625Q297.71875,-43.8125,297.71875,-38.78125L297.71875,-2.84375Q297.71875,-1.6875,296.84375,-0.828125Q295.98438,0.03125,294.82812,0.03125Z"
android:fillColor="#FFFFFF"/>
<path android:pathData="M410.90625,-36.203125Q410.90625,-25.5625,406.29688,-17Q401.6875,-8.453125,393.6875,-3.484375Q385.70312,1.46875,375.48438,1.46875Q365.40625,1.46875,357.32812,-3.484375Q349.26562,-8.453125,344.57812,-17Q339.90625,-25.5625,339.90625,-36.203125Q339.90625,-46.96875,344.57812,-55.53125Q349.26562,-64.09375,357.32812,-69.046875Q365.40625,-74,375.48438,-74Q385.70312,-74,393.6875,-69.046875Q401.6875,-64.09375,406.29688,-55.53125Q410.90625,-46.96875,410.90625,-36.203125ZM405.14062,-36.203125Q405.14062,-45.53125,401.32812,-52.796875Q397.51562,-60.0625,390.8125,-64.296875Q384.125,-68.546875,375.48438,-68.546875Q366.98438,-68.546875,360.21875,-64.296875Q353.45312,-60.0625,349.5625,-52.796875Q345.67188,-45.53125,345.67188,-36.203125Q345.67188,-27,349.5625,-19.734375Q353.45312,-12.46875,360.21875,-8.234375Q366.98438,-4,375.48438,-4Q384.125,-4,390.8125,-8.234375Q397.51562,-12.46875,401.32812,-19.734375Q405.14062,-27,405.14062,-36.203125Z"
android:fillColor="#FFFFFF"/>
<path android:pathData="M435.71875,-2.875Q435.71875,-1.71875,434.84375,-0.859375Q433.98438,0,432.82812,0Q431.53125,0,430.73438,-0.859375Q429.95312,-1.71875,429.95312,-2.875L429.95312,-71.125Q429.95312,-72.28125,430.8125,-73.140625Q431.6875,-74,432.82812,-74Q434.125,-74,434.92188,-73.140625Q435.71875,-72.28125,435.71875,-71.125L435.71875,-2.875ZM432.82812,-83.65625Q430.53125,-83.65625,429.15625,-84.9375Q427.79688,-86.234375,427.79688,-88.25L427.79688,-89.390625Q427.79688,-91.40625,429.23438,-92.703125Q430.67188,-94,432.96875,-94Q434.98438,-94,436.35938,-92.703125Q437.73438,-91.40625,437.73438,-89.390625L437.73438,-88.25Q437.73438,-86.234375,436.35938,-84.9375Q434.98438,-83.65625,432.82812,-83.65625Z"
android:fillColor="#FFFFFF"/>
<path android:pathData="M518.84375,-106Q520.1406,-106,520.9375,-105.140625Q521.7344,-104.28125,521.7344,-103.15625L521.7344,-2.84375Q521.7344,-1.6875,520.8594,-0.828125Q520,0.03125,518.84375,0.03125Q517.5469,0.03125,516.75,-0.828125Q515.96875,-1.6875,515.96875,-2.84375L515.96875,-23.265625L518.2656,-26.421875Q518.2656,-21.53125,516.03125,-16.5625Q513.8125,-11.609375,509.70312,-7.515625Q505.59375,-3.421875,500.125,-0.96875Q494.65625,1.46875,488.3125,1.46875Q478.8125,1.46875,471.25,-3.484375Q463.70312,-8.453125,459.29688,-17Q454.90625,-25.5625,454.90625,-36.34375Q454.90625,-47.109375,459.29688,-55.671875Q463.70312,-64.234375,471.25,-69.109375Q478.8125,-74,488.3125,-74Q494.21875,-74,499.625,-71.765625Q505.03125,-69.546875,509.20312,-65.515625Q513.375,-61.5,515.8125,-56.09375Q518.2656,-50.703125,518.2656,-44.390625L515.96875,-47.984375L515.96875,-103.15625Q515.96875,-104.296875,516.75,-105.140625Q517.5469,-106,518.84375,-106ZM488.60938,-4Q496.8125,-4,503.07812,-8.15625Q509.34375,-12.328125,512.9375,-19.65625Q516.5469,-27,516.5469,-36.34375Q516.5469,-45.6875,512.9375,-52.9375Q509.34375,-60.203125,503,-64.375Q496.67188,-68.546875,488.60938,-68.546875Q480.6875,-68.546875,474.34375,-64.375Q468.01562,-60.203125,464.34375,-52.9375Q460.67188,-45.6875,460.67188,-36.34375Q460.67188,-27.140625,464.34375,-19.796875Q468.01562,-12.46875,474.34375,-8.234375Q480.6875,-4,488.60938,-4Z"
android:fillColor="#FFFFFF"/>
</group>
</group>
</group>
</vector>

View file

@ -1,27 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group android:scaleX="0.056557618"
android:scaleY="0.056557618"
android:translateX="25.0425"
android:translateY="25.0425">
<path
android:pathData="m512,136.5c-99.4,0 -419.3,580 -370.5,678 48.7,98 692.8,96.8 741.1,0 48.3,-96.8 -271.1,-678 -370.5,-678zM512,285.3c65,0 274.5,380.7 242.9,444.3 -31.6,63.4 -453.6,64.2 -485.6,0C237.4,665.3 447,285.3 512,285.3ZM437.6,503.2c18.3,51.8 26.5,80.7 2.8,129.3 -5.5,11.4 -0.7,20.2 11.9,20.2l131.1,0.9c12.5,0.1 19,-9.3 13.7,-20.6 -19.3,-41.2 -69.6,-130.3 -149.6,-142.7 -8.2,-1.3 -12.8,5 -10,12.9z"
android:strokeWidth="0.23938">
<aapt:attr name="android:fillColor">
<gradient
android:startY="479.77658"
android:startX="363.41766"
android:endY="702.5666"
android:endX="749.3077"
android:type="linear">
<item android:offset="0" android:color="@color/logo_primary"/>
<item android:offset="1" android:color="@color/logo_secondary"/>
</gradient>
</aapt:attr>
</path>
</group>
</vector>

View file

@ -2,6 +2,7 @@ package dev.jdtech.jellyfin.dialogs
import android.app.Dialog
import android.os.Bundle
import android.text.InputType
import android.widget.EditText
import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@ -15,13 +16,14 @@ class AddServerAddressDialog(
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val editText = EditText(this.context)
editText.hint = "http://<server_ip>:8096"
editText.inputType = InputType.TYPE_TEXT_VARIATION_URI
return activity?.let { activity ->
val builder = MaterialAlertDialogBuilder(activity)
builder
.setTitle(getString(R.string.add_server_address))
.setView(editText)
.setPositiveButton(getString(R.string.add)) { _, _ ->
viewModel.addAddress(editText.text.toString())
viewModel.addAddress(requireContext(), editText.text.toString())
}
.setNegativeButton(getString(R.string.cancel)) { _, _ ->
}

View file

@ -9,6 +9,7 @@ import dev.jdtech.jellyfin.models.FavoriteSection
import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.models.SortBy
import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.repository.JellyfinRepository
import kotlinx.coroutines.Dispatchers
@ -39,7 +40,10 @@ constructor(
_uiState.emit(UiState.Loading)
try {
val items = jellyfinRepository.getItems(parentId = parentId)
val items = jellyfinRepository.getItems(
parentId = parentId,
sortBy = SortBy.RELEASE_DATE,
)
if (items.isEmpty()) {
_uiState.emit(UiState.Normal(emptyList()))

View file

@ -1,5 +1,6 @@
package dev.jdtech.jellyfin.viewmodels
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
@ -79,11 +80,19 @@ constructor(
}
}
fun addAddress(address: String) {
fun addAddress(context: Context, address: String) {
viewModelScope.launch(Dispatchers.IO) {
val serverAddress = ServerAddress(UUID.randomUUID(), currentServerId, address)
database.insertServerAddress(serverAddress)
loadAddresses(currentServerId)
try {
val jellyfinApi = JellyfinApi(context)
jellyfinApi.api.baseUrl = address
val systemInfo by jellyfinApi.systemApi.getPublicSystemInfo()
if (systemInfo.id != currentServerId) {
return@launch
}
val serverAddress = ServerAddress(UUID.randomUUID(), currentServerId, address)
database.insertServerAddress(serverAddress)
loadAddresses(currentServerId)
} catch (_: Exception) { }
}
}
}

View file

@ -170,4 +170,21 @@
<string name="stop_download">Download stoppen</string>
<string name="downloaded_indicator">Download Indikator</string>
<string name="episode_name_with_end">%1$d-%2$d. %3$s</string>
<string name="watch_trailer">Trailer anschauen</string>
<string name="remove_from_favorites">Aus Favoriten entfernen</string>
<string name="no_servers_found">Keine Server gefunden</string>
<string name="no_users_found">Keine Benutzer gefunden</string>
<string name="picture_in_picture">Bild-in-Bild</string>
<string name="remove_server_address_dialog_text">Bist du sicher, dass du die Server Adresse \"%1$s\" entfernen möchtest?</string>
<string name="remove_server_address">Server Adresse entfernen</string>
<string name="collection_no_media">Diese Sammlung enthält keine Medien</string>
<string name="player_start_maximized">Maximiert starten</string>
<string name="player_start_maximized_summary">Video standardmäßig maximiert öffnen</string>
<string name="pref_player_chapter_markers">Kapitelmarker</string>
<string name="pref_player_chapter_markers_summary">Zeige Kapitelmarker in der Zeitleiste an</string>
<string name="select_user">Benutzer auswählen</string>
<string name="mark_as_played">Als angesehen markieren</string>
<string name="add_to_favorites">Zu Favoriten hinzufügen</string>
<string name="player_gestures_chapter_skip">Kapitel Geste</string>
<string name="player_gestures_chapter_skip_summary">Drücke lange auf der linken/rechten Seite um Kapitel zu überspringen (überschreibt die 2x-Geschwindigkeitsgesten)</string>
</resources>

View file

@ -172,4 +172,6 @@
<string name="downloading_error">Ocurrió un error al descargar</string>
<string name="remove_server_address_dialog_text">¿Está seguro de remover el servidor con dirección %1$s</string>
<string name="remove_server_address">Remover dirección del servidor</string>
<string name="collection_no_media">Ésta colección no contiene elementos</string>
<string name="player_gestures_chapter_skip">Gesto para cambiar capítulos</string>
</resources>

View file

@ -142,7 +142,7 @@
<string name="add_address">Ajouter une adresse</string>
<string name="add_server_address">Ajouter l\'adresse d\'un serveur</string>
<string name="add">Ajouter</string>
<string name="pref_player_trick_play_summary">Le plugin Jellyscrub de nicknsy doit être installé sur le serveur</string>
<string name="pref_player_trick_play_summary">Nécessite que le plugin Jellyscrub de Nicknsy soit installé sur le serveur</string>
<string name="temp">temporaire</string>
<string name="subtitle_chip_text">CC</string>
<string name="player_gestures_seek">Déplacement du curseur de lecture</string>
@ -175,4 +175,21 @@
<string name="picture_in_picture">Fenêtre flottante</string>
<string name="picture_in_picture_gesture">Geste de retour à l\'accueil depuis la fenêtre flottante</string>
<string name="picture_in_picture_gesture_summary">Lors de la lecture, utilisez le bouton d\'accueil ou la navigation gestuelle pour lancer la fenêtre flottante</string>
<string name="unmark_as_played">Non marqué comme joué</string>
<string name="no_servers_found">Aucun serveur trouvé</string>
<string name="no_users_found">Aucun utilisateur trouvé</string>
<string name="select_user">Sélectionner un utilisateur</string>
<string name="live_tv">Direct TV</string>
<string name="add_to_favorites">Ajouter aux favoris</string>
<string name="collection_no_media">Cette collection ne contient aucun média</string>
<string name="player_start_maximized_summary">Ouvrir la vidéo en plein écran par défaut</string>
<string name="player_start_maximized">Démarrer en plein écran</string>
<string name="player_gestures_chapter_skip_summary">Appuyer longtemps sur les côtés de l\'écran pour passer le chapitre (cela remplace le geste de vitesse 2x)</string>
<string name="pref_player_chapter_markers">Marqueurs de chapitre</string>
<string name="pref_player_chapter_markers_summary">Afficher les marqueurs de chapitre sur la barre temporelle</string>
<string name="play">Lecture</string>
<string name="player_gestures_chapter_skip">Geste du chapitre</string>
<string name="watch_trailer">Regarder la bande annonce</string>
<string name="mark_as_played">Marquer comme joué</string>
<string name="remove_from_favorites">Retirer des favoris</string>
</resources>

View file

@ -30,7 +30,7 @@
<string name="director">Rendező</string>
<string name="writers">Írók</string>
<string name="cast_amp_crew">Szereplők &amp; Stáb</string>
<string name="seasons">Szezonok</string>
<string name="seasons">Évadok</string>
<string name="trailer_button_description">Előzetes megtekintése</string>
<string name="check_button_description">Megjelölés megtekintettnek, vagy nem-megtekintettnek</string>
<string name="favorite_button_description">Kedvenc</string>
@ -187,4 +187,9 @@
<string name="watch_trailer">Előzetes megtekintése</string>
<string name="player_start_maximized_summary">Videó megnyitása alapértelmezés szerint maximalizált módban</string>
<string name="player_start_maximized">Indítás maximalizálva</string>
<string name="collection_no_media">Ez a gyűjtemény nem tartalmaz médiát</string>
<string name="player_gestures_chapter_skip">Fejezet gesztus</string>
<string name="player_gestures_chapter_skip_summary">Hosszan nyomd meg a bal / jobb oldalt a fejezetek átugrására (felülírja a 2x sebesség gesztust)</string>
<string name="pref_player_chapter_markers">Fejezet jelölések</string>
<string name="pref_player_chapter_markers_summary">Fejezetjelzők megjelenítése az idősávon</string>
</resources>

View file

@ -2,14 +2,14 @@
<resources>
<string name="jellyfin_banner">Jellyfin banner</string>
<string name="add_server">Adicionar Servidor</string>
<string name="add_server_error_outdated">Versão do servidor desactualizada: %1$s. Por favor, actualize o seu servidor</string>
<string name="add_server_error_not_jellyfin">Não é um servidor Jellyfin: %1$s</string>
<string name="add_server_error_version">Versão de servidor não suportada: %1$s. Por favor, actualize o seu servidor</string>
<string name="add_server_error_outdated">Versão do servidor desatualizada: %1$s. Por favor, atualize o seu servidor</string>
<string name="add_server_error_not_jellyfin">Não é um servidor de Jellyfin: %1$s</string>
<string name="add_server_error_version">Versão de servidor não suportada: %1$s. Por favor, atualize o seu servidor</string>
<string name="add_server_error_slow">O servidor é demasiado lento para responder: %1$s</string>
<string name="add_server_error_empty_address">Endereço de servidor vazio</string>
<string name="add_server_error_not_found">Servidor não encontrado</string>
<string name="add_server_error_no_id">O servidor não tem identificação, algo parece estar errado com o servidor</string>
<string name="login">Início de Sessão</string>
<string name="add_server_error_no_id">O servidor não tem id, algo parece estar errado com o servidor</string>
<string name="login">Iníciar Sessão</string>
<string name="select_server">Selecionar servidor</string>
<string name="edit_text_server_address_hint">Endereço de servidor</string>
<string name="button_connect">Ligar</string>
@ -18,18 +18,18 @@
<string name="title_home">Início</string>
<string name="cancel">Cancelar</string>
<string name="remove">Remover</string>
<string name="remove_server">Remover Servidor</string>
<string name="remove_server">Remover servidor</string>
<string name="remove_server_dialog_text">Têm a certeza que pretende remover o servidor %1$s</string>
<string name="title_favorite">Favoritos</string>
<string name="title_settings">Definições</string>
<string name="title_download">Transferências</string>
<string name="view_all">Ver todos</string>
<string name="app_description">Aplicação Jellyfin nativa de terceiros</string>
<string name="button_login">Entrar</string>
<string name="button_login">Iníciar Sessão</string>
<string name="login_error_wrong_username_password">Nome de utilizador ou palavra-passe errados</string>
<string name="error_loading_data">Erro ao carregar dados</string>
<string name="retry">Tentar novamente</string>
<string name="title_media">Conteúdo</string>
<string name="title_media">O meu Conteúdo</string>
<string name="writers">Escritores</string>
<string name="seasons">Temporadas</string>
<string name="favorite_button_description">Favorito</string>
@ -41,16 +41,16 @@
<string name="series_poster">Cartaz de Séries</string>
<string name="no_favorites">Não tem favoritos</string>
<string name="search">Procurar</string>
<string name="settings_preferred_subtitle_language">Preferir idioma legenda</string>
<string name="settings_category_player">Reprodutor</string>
<string name="settings_preferred_subtitle_language">Preferir idioma de subtítulo</string>
<string name="settings_category_player">Reprodutor de video</string>
<string name="settings_use_cache_title">Imagens em cache</string>
<string name="settings_category_appearance">Aspecto</string>
<string name="settings_category_appearance">Aspeto</string>
<string name="settings_category_device">Dispositivo</string>
<string name="device_name">Nome do Dispositivo</string>
<string name="device_name">Nome de dispositivo</string>
<string name="settings_category_cache">Cache</string>
<string name="settings_cache_size">Tamanho da cache (MB)</string>
<string name="app_info">Info da Aplicação</string>
<string name="unknown_error">Erro Desconhecido</string>
<string name="unknown_error">Erro desconhecido</string>
<string name="search_hint">Procurar filmes, séries, episódios…</string>
<string name="about">Sobre</string>
<string name="mpv_player">reprodutor mpv</string>
@ -63,15 +63,15 @@
<string name="movies_label">Filmes</string>
<string name="shows_label">Séries</string>
<string name="episodes_label">Espisódios</string>
<string name="hide">Esconder</string>
<string name="hide">Ocultar</string>
<string name="share">Partilhar</string>
<string name="close">Fechar</string>
<string name="download_button_description">Transferir</string>
<string name="mpv_player_summary">Utilize o leitor experimental de MPV para reproduzir vídeos. MPV tem suporte de vários codecs de vídeo, áudio e subtítulos.</string>
<string name="mpv_player_summary">Utilize o leitor experimental de MPV para reproduzir vídeos. MPV tem suporte para mais codecs de vídeo, áudio e subtítulos.</string>
<string name="player_gestures_zoom">Gestor de Zoom</string>
<string name="image_description_poster">%1$s cartaz</string>
<string name="image_description_backdrop">%1$s cenário</string>
<string name="gestures">Gestor</string>
<string name="gestures">Gestos</string>
<string name="player_gestures_vb">Gestor de volume e luminosidade</string>
<string name="sort_by">Ordenar por</string>
<string name="sort_order">Ordenar por ordem</string>
@ -104,7 +104,7 @@
<string name="settings_socket_timeout">Tempo limite do soquete (ms)</string>
<string name="genres">Género</string>
<string name="director">Diretor</string>
<string name="cast_amp_crew">Elenco e Equipa</string>
<string name="cast_amp_crew">Elenco &amp; Equipa</string>
<string name="trailer_button_description">Ver o trailer</string>
<string name="settings_category_servers">Servidores</string>
<string name="settings_category_download">Transferências</string>
@ -115,13 +115,13 @@
<string name="error_preparing_player_items">Erro na preparação de itens do reprodutor.</string>
<string name="no_downloads">Não tem nada transferido</string>
<string name="no_search_results">Sem resultados da pesquisa</string>
<string name="settings_cache_size_message">A App irá utilizar esta quantidade de MB do seu espaço em disco para armazenar imagens do servidor Jellyfin. Valores maiores podem ser benéficos em redes mais lentas.</string>
<string name="settings_preferred_audio_language">Preferir idioma audio</string>
<string name="settings_cache_size_message">A aplicação irá utilizar esta quantidade de MB do seu espaço em disco para armazenar imagens do servidor Jellyfin. Valores maiores podem ser benéficos em redes mais lentas.</string>
<string name="settings_preferred_audio_language">Preferir idioma de audio</string>
<string name="settings_use_cache_summary">Cache de imagens em memória para acelerar o tempo de carregamento. Terá efeito após o reinício da aplicação.</string>
<string name="remove_server_address">Remover endereço do servidor</string>
<string name="external">Externo</string>
<string name="remove_user">Remover usuário</string>
<string name="remove_user_dialog_text">Tem certeza de que deseja remover o usuário %1$s</string>
<string name="remove_user">Remover utilizador</string>
<string name="remove_user_dialog_text">Tem certeza de que deseja remover o utilizador %1$s</string>
<string name="pref_player_mpv_vo">Saida de video</string>
<string name="pref_player_mpv_ao">Saída de áudio</string>
<string name="add_address">Adicionar endereço</string>
@ -145,7 +145,7 @@
<string name="users">Usuários</string>
<string name="app_language">Idioma do aplicativo</string>
<string name="add">Adicionar</string>
<string name="downloaded_indicator">Indicador baixado</string>
<string name="downloaded_indicator">Indicador de transferido</string>
<string name="pref_player_mpv_hwdec">Decodificação de hardware</string>
<string name="addresses">Endereços</string>
<string name="quick_connect">Conexão rápida</string>
@ -158,21 +158,38 @@
<string name="temp">temperatura</string>
<string name="picture_in_picture">Imagem em imagem</string>
<string name="picture_in_picture_gesture_summary">Use o botão home ou gesto para entrar na imagem enquanto o vídeo está sendo reproduzido</string>
<string name="privacy_policy_notice">Ao usar o Findroid, você concorda com a <a href="https://raw.githubusercontent.com/jarnedemeulemeester/findroid/main/PRIVACY">Política de Privacidade</a>, que afirma que não coletamos quaisquer dados</string>
<string name="privacy_policy_notice">Ao usar o Findroid, esta a concordar com a <a href="https://raw.githubusercontent.com/jarnedemeulemeester/findroid/main/PRIVACY">Política de Privacidade</a>, que afirma que não coletamos quaisquer dados</string>
<string name="video">Video</string>
<string name="offline_mode_icon">Ícone do modo off-line</string>
<string name="no_server_connection">Sem conexão com o servidor Jellyfin, para assistir off-line, ative o modo off-line</string>
<string name="internal">Interno</string>
<string name="select_storage_location">Selecione o local de armazenamento</string>
<string name="storage_unavailable">O local de armazenamento não está disponível</string>
<string name="storage_name">%1$s (%2$d MB grátis)</string>
<string name="preparing_download">Preparando para baixar</string>
<string name="storage_name">%1$s (%2$d MB livre)</string>
<string name="preparing_download">Preparando transferência</string>
<string name="extra_info">Exibir informações extras</string>
<string name="not_enough_storage">Este item requer %1$s de armazenamento gratuito, mas apenas %2$s está disponível</string>
<string name="offline_mode_go_online">Fique online</string>
<string name="downloading_error">Erro ao baixar</string>
<string name="stop_download">Pare de baixar</string>
<string name="stop_download">Parar transferência</string>
<string name="picture_in_picture_gesture">Gesto inicial imagem em imagem</string>
<string name="extra_info_summary">Exibe informações detalhadas sobre áudio, vídeo e legendas</string>
<string name="cancel_download_message">Tem certeza de que deseja cancelar a transferência\?</string>
<string name="collection_no_media">Esta coleção não contém nenhum conteúdo</string>
<string name="player_start_maximized">Inicie maximizado</string>
<string name="player_start_maximized_summary">Abra o vídeo no modo maximizado por padrão</string>
<string name="no_servers_found">Nenhum servidor encontrado</string>
<string name="no_users_found">Nenhum utilizador encontrado</string>
<string name="select_user">Seleccione um utilizador</string>
<string name="live_tv">TV ao vivo</string>
<string name="play">Reproduzir</string>
<string name="player_gestures_chapter_skip">Gesto de capítulo</string>
<string name="pref_player_chapter_markers">Marcadores de capítulo</string>
<string name="pref_player_chapter_markers_summary">Exibir marcadores de capítulo na barra de tempo</string>
<string name="watch_trailer">Ver trailer</string>
<string name="remove_from_favorites">Remover dos favoritos</string>
<string name="player_gestures_chapter_skip_summary">Manter pressionado no Esquerdo / Direito para saltar capítulos (anula o gesto de velocidade x2)</string>
<string name="mark_as_played">Marcar como visto</string>
<string name="unmark_as_played">Desmarcar como visto</string>
<string name="add_to_favorites">Adicionar aos favoritos</string>
</resources>

View file

@ -3,6 +3,6 @@
<dimen name="setup_container_width">400dp</dimen>
<item name="server_columns" type="integer">6</item>
<item name="collection_columns" type="integer">3</item>
<item name="library_columns" type="integer">4</item>
<item name="library_columns" type="integer">3</item>
<dimen name="person_detail_overview_height">124dp</dimen>
</resources>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="server_columns" type="integer">8</item>
<item name="library_columns" type="integer">6</item>
<item name="library_columns" type="integer">4</item>
<dimen name="person_detail_overview_height">200dp</dimen>
</resources>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="library_columns" type="integer">6</item>
</resources>

View file

@ -187,4 +187,9 @@
<string name="player_start_maximized_summary">默认以最大化模式打开视频</string>
<string name="play">播放</string>
<string name="watch_trailer">观看预告</string>
<string name="collection_no_media">该集合不包含任何媒体</string>
<string name="player_gestures_chapter_skip">章节手势</string>
<string name="player_gestures_chapter_skip_summary">长按左/右侧可跳过章节(覆盖 2 倍速度手势)</string>
<string name="pref_player_chapter_markers">章节标记</string>
<string name="pref_player_chapter_markers_summary">在进度栏上显示章节标记</string>
</resources>

View file

@ -175,4 +175,21 @@
<string name="remove_server_address_dialog_text">您確定要刪除伺服器位址嗎%1$s</string>
<string name="pref_player_trick_play">跳轉預覽</string>
<string name="temp">臨時文件</string>
<string name="no_servers_found">未找到伺服器</string>
<string name="no_users_found">未找到相應的用戶</string>
<string name="select_user">選擇用戶</string>
<string name="live_tv">電視直播</string>
<string name="play">播放</string>
<string name="watch_trailer">觀看預告</string>
<string name="mark_as_played">標記為已播放</string>
<string name="unmark_as_played">取消標記為已播放</string>
<string name="add_to_favorites">加入收藏夾</string>
<string name="remove_from_favorites">從收藏夾中刪除</string>
<string name="player_start_maximized">開始最大化</string>
<string name="player_start_maximized_summary">預設以最大化模式開啟視頻</string>
<string name="player_gestures_chapter_skip">章節手勢</string>
<string name="player_gestures_chapter_skip_summary">長按左/右側可跳過章節(覆蓋 2 倍速度手勢)</string>
<string name="pref_player_chapter_markers">章節標記</string>
<string name="pref_player_chapter_markers_summary">在時間欄上顯示章節標記</string>
<string name="collection_no_media">該集合不包含任何媒體</string>
</resources>

View file

@ -54,6 +54,7 @@
<string name="latest_library">Latest %1$s</string>
<string name="libraries">Libraries</string>
<string name="series_poster">Series poster</string>
<string name="collection_no_media">This collection does not contain any media</string>
<string name="no_favorites">You have no favorites</string>
<string name="no_downloads">You have nothing downloaded</string>
<string name="search">Search</string>

View file

@ -63,7 +63,7 @@ suspend fun BaseItemDto.toFindroidEpisode(
seriesName = seriesName.orEmpty(),
seriesId = seriesId!!,
seasonId = seasonId!!,
communityRating = communityRating,
communityRating = communityRating?.let { Math.round(it * 10).div(10F) },
missing = locationType == LocationType.VIRTUAL,
images = toFindroidImages(jellyfinRepository),
chapters = toFindroidChapters(),

View file

@ -56,7 +56,7 @@ suspend fun BaseItemDto.toFindroidMovie(
runtimeTicks = runTimeTicks ?: 0,
playbackPositionTicks = userData?.playbackPositionTicks ?: 0,
premiereDate = premiereDate,
communityRating = communityRating,
communityRating = communityRating?.let { Math.round(it * 10).div(10F) },
genres = genres ?: emptyList(),
people = people ?: emptyList(),
officialRating = officialRating,

View file

@ -52,7 +52,7 @@ fun BaseItemDto.toFindroidShow(
genres = genres ?: emptyList(),
people = people ?: emptyList(),
runtimeTicks = runTimeTicks ?: 0,
communityRating = communityRating,
communityRating = communityRating?.let { Math.round(it * 10).div(10F) },
officialRating = officialRating,
status = status ?: "Ended",
productionYear = productionYear,

1
fastlane/Appfile Normal file
View file

@ -0,0 +1 @@
package_name("dev.jdtech.jellyfin")

40
fastlane/Fastfile Normal file
View file

@ -0,0 +1,40 @@
default_platform(:android)
platform :android do
desc "Build and publish"
lane :publish do
gradle(task: "clean")
gradle(
task: "app:phone:assemble",
flavor: "libre",
build_type: "release",
print_command: false,
properties: {
"android.injected.signing.store.file" => ENV["FINDROID_KEYSTORE"],
"android.injected.signing.store.password" => ENV["FINDROID_KEYSTORE_PASSWORD"],
"android.injected.signing.key.alias" => ENV["FINDROID_KEY_ALIAS"],
"android.injected.signing.key.password" => ENV["FINDROID_KEY_PASSWORD"],
}
)
gradle(
task: "app:phone:bundle",
flavor: "libre",
build_type: "release",
print_command: false,
properties: {
"android.injected.signing.store.file" => ENV["FINDROID_KEYSTORE"],
"android.injected.signing.store.password" => ENV["FINDROID_KEYSTORE_PASSWORD"],
"android.injected.signing.key.alias" => ENV["FINDROID_KEY_ALIAS"],
"android.injected.signing.key.password" => ENV["FINDROID_KEY_PASSWORD"],
}
)
upload_to_play_store(
track: "production",
json_key: ENV["FINDROID_PLAY_API_CREDENTIALS"],
skip_upload_apk: true,
sync_image_upload: true
)
end
end

56
fastlane/README.md Normal file
View file

@ -0,0 +1,56 @@
fastlane documentation
----
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```sh
xcode-select --install
```
For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
# Available Actions
## Android
### android test
```sh
[bundle exec] fastlane android test
```
Runs all the tests
### android beta
```sh
[bundle exec] fastlane android beta
```
Submit a new Beta Build to Crashlytics Beta
### android deploy
```sh
[bundle exec] fastlane android deploy
```
Deploy a new version to the Google Play
### android build
```sh
[bundle exec] fastlane android build
```
build
----
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).

View file

@ -0,0 +1,9 @@
Features:
- Completely native interface
- Supported media items: movies, series, seasons, episodes
- Video codes: H.263, H.264, H.265, VP8, VP9, AV1
- Audio codes: Vorbis, Opus, FLAC, ALAC, PCM µ-law, PCM A-law, MP1, MP2, MP3, AMR-NB, AMR-WB, AAC, AC-3, E-AC-3, DTS, DTS-HD, TrueHD
- Subtitle codecs: SRT, VTT, SSA/ASS, PGSSUB
- Support for multiple servers
- Set preferred audio and subtitle language
- Light & dark theme

View file

@ -0,0 +1,13 @@
New features:
- Split gesture option into volume & brightness and zoom
- Add support for external subtitles (only ExoPlayer)
- Customize the seeking increments
- Add option to disable subtitles in mpv
Improvements:
- Lot's of translations (Bulgarian, Chinese, French, German, Hungarian, Italian, Polish, Portuguese, Spanish)
- Provide better error messages with stacktrace
- Display downloaded episodes by series
- Add paging support to the library
Also fixed a few crashes

View file

@ -0,0 +1,14 @@
New features:
- Allow seeking video by swiping or tapping
- Material You Dynamic colors
- Display public users on login screen
- Display discovered servers on add server screen
Improvements:
- Layout improvements for larger screens
- Bring back Android TV (fix crashes and improvements)
Translations: Chinese (Simplified), French, Italian, Korean, Russian
Fixes:
- Fix crash when navigating to login screen (and other screens)

View file

@ -0,0 +1,13 @@
Improvements:
- Add "pinch to zoom" support to mpv
Fixes:
- Fix play icon color in settings
- Fix mpv subfont.ttf not loading
- This fixes mpv not displaying SubRip Text (SRT) subtitles
- Fix external subtiles not working in mpv
- Fix crash when using swiping gesture if video is not loaded yet
- Fix player crashing when no PlayerItems are passed
- Fix only showing 1 discovered server
Translations: Korean, Polish, Spanish

View file

@ -0,0 +1,18 @@
This update forces a servers database reset! Servers will need to be added again!
New features:
- Servers database v2
- Network settings
- Request timeout
- Connect timeout
- Socket timeout
- Mutli-user support
Improvements:
- Add series name to episode sheet with navigation
- Enable predictive back gesture
- Improve downloads management
- Upgrade libmpv
- Handle audio focus
- Lot's of library upgrades
- Bugfixes

View file

@ -0,0 +1,16 @@
Highlights:
- Add support for media sessions
- Basic support for multiple server addresses
- More mpv options
Improvements:
- Add search button to home screen
Translations:
- Chinese
- French
- Korean
Fixes:
- Fix tv player showing subtitle tracks instead of audio tracks
- Remove server already added error

View file

@ -0,0 +1,14 @@
New features:
- Allow logging in with Quick Connect
- Support for ConfusedPolarBears intro-skipper
Improvements:
- Updated mpv release (now includes all codecs in FFmpeg)
- Including an experimental AV1 hardware decoder.
- Respect "Allow media playback"
Translations: Chinese, Dutch, French, Italian, Korean, Polish, Portuguese, Spanish
Fixes:
- Fix playback position reporting not closing properly.
- Optimized the loading of app preferences (backend, not the settings screen)

View file

@ -0,0 +1,13 @@
New features:
- Support for collections
Improvements:
- Follow "Play next episode automatically" from user playback settings
- ExoPlayer can now play HLS content
Translations: Chinese, Italian, Korean, Portuguese
Fixes:
- Fix Quick Connect code not readable in light mode
- Fix multiple download related issues
- Fix app crashing when exiting the player after finishing an item using mpv

View file

@ -0,0 +1,6 @@
Fixes:
- Fix resuming playback
- Fix downloads playback when there is no connection to the server
- Fix next up episode image crop
Translations: Chinese, Dutch, Vietnamese, German, Hungarian, Italian, Portuguese, Polish, Russian, Yue

View file

@ -0,0 +1,18 @@
New features:
- Item metadata chips
- Seek gesture toggle
- AMOLED dark theme
- Scrubbing preview (trick play)
- Downloads rework
Improvements:
- Material 3 styling in preferences
- Gesture exclusion zones
Fixes:
- 500 error when trying to play an item
- mpv memory leak, anr and stuck loading icon
- And more
Translations:
- Chinese (Simplified), Dutch, French, German, Hebrew, Italian, Polish, Portuguese, Russian, Slovak, Slovenian, Spanish, Swedish, Vietnamese

View file

@ -0,0 +1,13 @@
Improvements:
- Search in offline mode
- App language setting for devices running Android 13+
- Show movie size in extra info and improve size formatting
Fixes:
- Navigation to collection
- Text overflowing into "View all"
- Text overlapping in movie and show screens
- AMOLED theme not taking Material 3 colors
- NullPointerException on episodes which do not contain a seriesId or seasonId
Translations: Hungarian, Polish, Portuguese (Brazil), Russian, Slovak, Spanish

View file

@ -0,0 +1,9 @@
Improvements:
- Replaced oss-licenses-plugin with AboutLibraries.
- Improved server url discovery, no more http://, https:// or ports required!
- New error panel to display detailed error messages.
- Make library images smaller to fit more on one screen.
Fixes:
- Removed books from home & media screens.
- Move episode metadata to under the image to adjust for larger font sizes and smaller screens.

View file

@ -0,0 +1,16 @@
New features:
- Picture-in-picture support
- Double tap center to play/pause
Improvements:
- Ripple effect when double tapping in player
- Improvements to hiding system bars
- Show episode size when extra info is enabled
Fixes:
- Fix playback position reset on process death or device lock
- Fix playback sync of download being too far ahead
- ...
Translations:
- Chinese, Dutch, French, Hebrew, Hungarian, Italian, Korean, Polish, Portuguese, Romanian, Russion, Slovak, Spanish, Ukranian

View file

@ -0,0 +1,16 @@
New features:
- Picture-in-picture support
- Double tap center to play/pause
Improvements:
- Ripple effect when double tapping in player
- Improvements to hiding system bars
- Show episode size when extra info is enabled
Fixes:
- Fix playback position reset on process death or device lock
- Fix playback sync of download being too far ahead
- ...
Translations:
- Chinese, Dutch, French, Hebrew, Hungarian, Italian, Korean, Polish, Portuguese, Romanian, Russion, Slovak, Spanish, Ukranian

View file

@ -0,0 +1,10 @@
Fixes:
- Multiple crashes
- Offline mode snackbar not visible in landscape mode
- Incorrect popup background in player when using dark mode
- Playback resets
- Deleted server stays visible
- Stuck on login screen when server has no user
Translations:
- Chinese, Czech, Hebrew, Hungarian, Italian, Korean, Portuguese, Slovak, Slovenian

View file

@ -0,0 +1,16 @@
New features:
- Disable audio track
- Long press for 2x speed
- Chapters
- Markers are displayed on the timebar
- Gestures
- Support for mixed libraries
Improvements:
- Custom track selection dialog
- Make PiP remember zoom and brightness levels
- Improve PiP transition when using home gesture
- Increase the limit of items displayed on the home screen
Translations:
- Bulgarian, Chinese, Danish, French, Hungarian, Italian, Korean, Portuguese, Slovak, Spanish, Turkish, Vietnamese

View file

@ -0,0 +1,15 @@
Improvements:
- Request audio focus in mpv
- Sort items in collections by release date
- Improve landscape library layout on mobile
- Reduce community rating to one decimal place
Fixes:
- Set correct surface colors when using dynamic colors or AMOLED theme
- Fix crash when setting picture-in-picture params
- Check address when adding extra addresses to server
- Display correct empty collection string
Translations:
- Dutch
- Portuguese (Brazil)

View file

@ -0,0 +1,14 @@
Improvements:
- Support HTML in media descriptions
Fixes:
- Library media items too small on tablet when in portrait mode
Translations:
- Chinese
- French
- German
- Hungarian
- Portuguese
- Spanish (Mexico)
- Turkish

View file

@ -0,0 +1,15 @@
Improvements:
- Improved home screen loading
- Added missing episode icon
- Reworked player items preparation:
- Supports intros
- Improved loading speed
- Show complete detailed error messages
- Ask for login if server responds with 401
Fixes:
- Fixed playing episodes if missing episodes occur in the season
- Fixed missing images in some places
- Fixed library broken when media items are grouped in folders
- Removed Live TV section from home screen
- Fixed underlined "View detail" text

View file

@ -0,0 +1,12 @@
New Features:
- Experimental mpv player
- Can be enabled in the settings
- With extra option to force software decoding
- New player UI to support mpv
Improvements:
- Spanish translations
- Video now extends into display cutout
Fixes:
- Fix crash when trailer button is pressed but no trailers are available

View file

@ -0,0 +1,2 @@
Fixes:
- Fix mpv player crashing

View file

@ -0,0 +1,16 @@
New Features:
- Playback speed controls
- Sorting options in library
- Person detail screen
- Downloads and offline playback
- Gestures in player to adjust volume and brightness
- STRM support
- Image caching with options in settings
- Customizable device name
- Basic Android TV layout
Improvements:
- Theme improvements
- Pull to refresh on home screen
- Server setup improvements
- Czech and Spanish localization

View file

@ -0,0 +1,10 @@
Improvements:
- Change downloads to use internal database for metadata instead of files
- Only show download button if user is allowed to download
- Improve player gestures and add pinch to zoom
- Reduce the size of the mpv library by disabling lot's of decoders and other components
- If you notice certain content doesn't play anymore please report
Fixes:
- Fix person placeholder drawable
- Add error handling to played and favorite buttons

View file

@ -0,0 +1,6 @@
Improvements:
- Enable avi container format in mpv
- Many dependencies updated
Fixes:
- Add missing check for if user is allowed to download in episode sheet

View file

@ -0,0 +1,14 @@
New features:
- Add option to display extended episode title in player
- Add option to download over mobile network
- Add option to disable player gestures and remember screen brightness
Improvements:
- Expand episode bottom sheet by default
- Upgrade to Material 3 theme and components
- Redesign settings using two pane layout
- Add option to turn off subtitles in player (only ExoPlayer)
- Enable image caching by default
- Add support for Vorbis audio codec in mpv player
Plus bugfixes!

View file

@ -0,0 +1,8 @@
Findroid is a third-party Android application for Jellyfin that provides a native user interface to browse and play movies and series.
To use this app you must have a Jellyfin server.
You can also download movies and TV shows for offline playback while on the road.
And with the built-in mpv player you are sure that all media formats will play correctly including styled SSA/ASS subtitles.
Thanks for using Findroid!

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View file

@ -0,0 +1 @@
Third-party native Jellyfin app

View file

@ -0,0 +1 @@
Findroid

View file

@ -1,38 +1,47 @@
[versions]
aboutlibraries = "11.1.0"
android-plugin = "8.3.0"
aboutlibraries = "11.1.3"
android-desugar-jdk-libs = "2.0.4"
android-plugin = "8.3.2"
androidx-activity = "1.8.2"
androidx-appcompat = "1.6.1"
androidx-compose-bom = "2024.02.01"
androidx-compose-material3 = "1.2.0"
androidx-compose-bom = "2024.04.00"
androidx-compose-material3 = "1.2.1"
androidx-constraintlayout = "2.1.4"
androidx-core = "1.12.0"
androidx-hilt = "1.2.0"
androidx-lifecycle = "2.7.0"
androidx-media3 = "1.2.1"
androidx-media3 = "1.3.1"
androidx-navigation = "2.7.7"
androidx-paging = "3.2.1"
androidx-preference = "1.2.1"
androidx-recyclerview = "1.3.2"
androidx-room = "2.6.1"
androidx-swiperefreshlayout = "1.1.0"
androidx-test-core = "1.5.0"
androidx-test-expresso = "3.5.1"
androidx-test-junit = "1.1.5"
androidx-test-rules = "1.5.0"
androidx-test-runner = "1.5.2"
androidx-tv = "1.0.0-alpha10"
androidx-work = "2.9.0"
coil = "2.6.0"
hilt = "2.51"
compose-destinations = "1.10.1"
jellyfin = "1.4.6"
kotlin = "1.9.22"
hilt = "2.51.1"
compose-destinations = "1.10.2"
jellyfin = "1.4.7"
junit = "4.13.2"
kotlin = "1.9.23"
kotlinx-serialization = "1.6.3"
ksp = "1.9.22-1.0.17"
ksp = "1.9.23-1.0.20"
ktlint = "12.1.0"
libmpv = "0.2.0"
material = "1.11.0"
media3-ffmpeg-decoder = "1.2.1+1"
timber = "5.0.1"
[libraries]
aboutlibraries-core = { group = "com.mikepenz", name = "aboutlibraries-core", version.ref = "aboutlibraries" }
aboutlibraries = { group = "com.mikepenz", name = "aboutlibraries", version.ref = "aboutlibraries" }
android-desugar-jdk = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "android-desugar-jdk-libs" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "androidx-activity" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidx-activity" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
@ -63,19 +72,30 @@ androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview"
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "androidx-room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "androidx-room" }
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "androidx-swiperefreshlayout" }
androidx-work = { group = "androidx.work", name = "work-runtime", version.ref = "androidx-work" }
androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidx-test-core" }
androidx-test-core-ktx = { group = "androidx.test", name = "core-ktx", version.ref = "androidx-test-core" }
androidx-test-expresso = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-test-expresso"}
androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" }
androidx-test-rules = { group = "androidx.test" , name = "rules", version.ref = "androidx-test-rules" }
androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidx-test-runner" }
androidx-tv-foundation = { group = "androidx.tv", name = "tv-foundation", version.ref = "androidx-tv" }
androidx-tv-material = { group = "androidx.tv", name = "tv-material", version.ref = "androidx-tv" }
androidx-work = { group = "androidx.work", name = "work-runtime", version.ref = "androidx-work" }
androidx-work-testing = { group = "androidx.work", name = "work-testing", version.ref = "androidx-work" }
coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" }
coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" }
coil-svg = { group = "io.coil-kt", name = "coil-svg", version.ref = "coil" }
compose-destinations-core = { group = "io.github.raamcosta.compose-destinations", name = "core", version.ref = "compose-destinations" }
compose-destinations-ksp = { group = "io.github.raamcosta.compose-destinations", name = "ksp", version.ref = "compose-destinations" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
hilt-android-testing = { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
jellyfin-core = { group = "org.jellyfin.sdk", name = "jellyfin-core", version.ref = "jellyfin" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
libmpv = { group = "dev.jdtech.mpv", name = "libmpv", version.ref = "libmpv" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
media3-ffmpeg-decoder = { group = "org.jellyfin.media3", name = "media3-ffmpeg-decoder", version.ref = "media3-ffmpeg-decoder" }
timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
@ -90,3 +110,6 @@ kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref =
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
[bundles]
androidx-test = ["androidx-test-core", "androidx-test-core-ktx", "androidx-test-expresso", "androidx-test-junit", "androidx-test-rules", "androidx-test-runner", "androidx-work-testing"]

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

Binary file not shown.

View file

@ -755,7 +755,17 @@ class MPVPlayer(
playWhenReadyChangeReason = Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
)
if (isPlayerReady) {
MPVLib.setPropertyBoolean("pause", !playWhenReady)
// Request audio focus when starting playback
if (requestAudioFocus && playWhenReady) {
val res = audioManager.requestAudioFocus(audioFocusRequest)
if (res != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
MPVLib.setPropertyBoolean("pause", true)
} else {
MPVLib.setPropertyBoolean("pause", false)
}
} else {
MPVLib.setPropertyBoolean("pause", !playWhenReady)
}
}
}
}

View file

@ -101,7 +101,7 @@ constructor(
.build()
player = MPVPlayer(
context = application,
requestAudioFocus = false,
requestAudioFocus = true,
trackSelectionParameters = trackSelectionParameters,
seekBackIncrement = appPreferences.playerSeekBackIncrement,
seekForwardIncrement = appPreferences.playerSeekForwardIncrement,

View file

@ -8,4 +8,11 @@
<string name="player_controls_exit">Player verlassen</string>
<string name="player_controls_rewind">Wiederholen</string>
<string name="player_controls_fast_forward">Vorspulen</string>
</resources>
<string name="player_controls_lock">Player sperren</string>
<string name="player_controls_skip_back">Zurückspulen</string>
<string name="player_controls_play_pause">Starten/Anhalten</string>
<string name="player_controls_skip_forward">Vor springen</string>
<string name="player_controls_progress">Fortschrittsanzeige</string>
<string name="none">Keine</string>
<string name="player_controls_picture_in_picture">Bild-in-Bild öffnen</string>
</resources>

View file

@ -15,4 +15,5 @@
<string name="player_controls_skip_forward">Avancer</string>
<string name="player_controls_progress">Barre de progression</string>
<string name="player_controls_picture_in_picture">Détacher la fenêtre flottante</string>
<string name="none">Aucun</string>
</resources>

View file

@ -15,4 +15,5 @@
<string name="player_controls_skip_forward">Avançar</string>
<string name="player_controls_skip_back">Pular para trás</string>
<string name="player_controls_picture_in_picture">Insira imagem em imagem</string>
<string name="none">Nenhum</string>
</resources>

View file

@ -1,2 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>
<resources>
<string name="select_audio_track">Ses parçasını seç</string>
<string name="select_subtile_track">Altyazı parçasını seç</string>
<string name="select_playback_speed">Oynatma hızını seç</string>
<string name="select_a_version">Bir sürüm seç</string>
<string name="none">Hiçbiri</string>
</resources>

View file

@ -15,4 +15,5 @@
<string name="player_controls_picture_in_picture">輸入畫中畫</string>
<string name="player_trickplay">特技播放</string>
<string name="player_controls_progress">進度條</string>
<string name="none">一個也沒有</string>
</resources>