Merge branch 'jarnedemeulemeester:main' into Skip-credit
This commit is contained in:
commit
0999823d6d
61 changed files with 110 additions and 159 deletions
4
.github/workflows/build.yaml
vendored
4
.github/workflows/build.yaml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
|
@ -29,7 +29,7 @@ jobs:
|
|||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
|
|
2
.github/workflows/publish.yaml
vendored
2
.github/workflows/publish.yaml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
|||
bundler-cache: true
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
uses: gradle/actions/wrapper-validation@v3
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
|
|
|
@ -103,9 +103,7 @@ dependencies {
|
|||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.hilt.work)
|
||||
implementation(libs.androidx.lifecycle.runtime)
|
||||
implementation(libs.androidx.lifecycle.viewmodel)
|
||||
implementation(libs.androidx.media3.exoplayer)
|
||||
implementation(libs.androidx.media3.ui)
|
||||
implementation(libs.androidx.media3.session)
|
||||
implementation(libs.androidx.navigation.fragment)
|
||||
|
|
|
@ -8,7 +8,6 @@ import androidx.core.view.WindowCompat
|
|||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.media3.exoplayer.trackselection.MappingTrackSelector
|
||||
import androidx.media3.session.MediaSession
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
||||
|
||||
|
@ -72,19 +71,6 @@ abstract class BasePlayerActivity : AppCompatActivity() {
|
|||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
}
|
||||
|
||||
protected fun isRendererType(
|
||||
mappedTrackInfo: MappingTrackSelector.MappedTrackInfo,
|
||||
rendererIndex: Int,
|
||||
type: Int,
|
||||
): Boolean {
|
||||
val trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex)
|
||||
if (trackGroupArray.length == 0) {
|
||||
return false
|
||||
}
|
||||
val trackType = mappedTrackInfo.getRendererType(rendererIndex)
|
||||
return type == trackType
|
||||
}
|
||||
|
||||
protected fun configureInsets(playerControls: View) {
|
||||
playerControls.setOnApplyWindowInsetsListener { _, windowInsets ->
|
||||
val cutout = windowInsets.displayCutout
|
||||
|
|
|
@ -293,7 +293,7 @@ class PlayerActivity : BasePlayerActivity() {
|
|||
hideSystemUI()
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
|
||||
|
@ -302,6 +302,7 @@ class PlayerActivity : BasePlayerActivity() {
|
|||
}
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
super.onUserLeaveHint()
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S &&
|
||||
appPreferences.playerPipGesture &&
|
||||
viewModel.player.isPlaying &&
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dev.jdtech.jellyfin.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Html.fromHtml
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -82,7 +83,7 @@ class LoginFragment : Fragment() {
|
|||
viewModel.uiState.collect { uiState ->
|
||||
Timber.d("$uiState")
|
||||
when (uiState) {
|
||||
is LoginViewModel.UiState.Normal -> bindUiStateNormal()
|
||||
is LoginViewModel.UiState.Normal -> bindUiStateNormal(uiState)
|
||||
is LoginViewModel.UiState.Error -> bindUiStateError(uiState)
|
||||
is LoginViewModel.UiState.Loading -> bindUiStateLoading()
|
||||
}
|
||||
|
@ -135,11 +136,15 @@ class LoginFragment : Fragment() {
|
|||
return binding.root
|
||||
}
|
||||
|
||||
private fun bindUiStateNormal() {
|
||||
private fun bindUiStateNormal(uiState: LoginViewModel.UiState.Normal) {
|
||||
binding.buttonLogin.isEnabled = true
|
||||
binding.progressCircular.isVisible = false
|
||||
binding.editTextUsernameLayout.isEnabled = true
|
||||
binding.editTextPasswordLayout.isEnabled = true
|
||||
|
||||
uiState.disclaimer?.let { disclaimer ->
|
||||
binding.loginDisclaimer.text = fromHtml(disclaimer, 0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUiStateError(uiState: LoginViewModel.UiState.Error) {
|
||||
|
|
|
@ -141,6 +141,15 @@
|
|||
android:visibility="invisible" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/login_disclaimer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_margin="24dp"
|
||||
android:textSize="16sp"
|
||||
tools:text="Sample login disclaimer" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose.compiler)
|
||||
alias(libs.plugins.kotlin.parcelize)
|
||||
alias(libs.plugins.hilt)
|
||||
alias(libs.plugins.ksp)
|
||||
|
@ -56,6 +57,8 @@ android {
|
|||
}
|
||||
|
||||
compileOptions {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
|
||||
sourceCompatibility = Versions.java
|
||||
targetCompatibility = Versions.java
|
||||
}
|
||||
|
@ -64,10 +67,6 @@ android {
|
|||
compose = true
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = Versions.composeCompiler
|
||||
}
|
||||
|
||||
packaging {
|
||||
resources {
|
||||
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
||||
|
@ -95,12 +94,13 @@ dependencies {
|
|||
implementation(libs.androidx.compose.material3)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.hilt.navigation.compose)
|
||||
implementation(libs.androidx.lifecycle.runtime)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||
implementation(libs.androidx.media3.exoplayer)
|
||||
implementation(libs.androidx.media3.ui)
|
||||
implementation(libs.androidx.media3.session)
|
||||
implementation(libs.androidx.paging.compose)
|
||||
implementation(libs.androidx.tv.foundation)
|
||||
implementation(libs.androidx.tv.material)
|
||||
implementation(libs.coil.compose)
|
||||
implementation(libs.coil.svg)
|
||||
implementation(libs.compose.destinations.core)
|
||||
|
@ -108,8 +108,9 @@ dependencies {
|
|||
implementation(libs.hilt.android)
|
||||
ksp(libs.hilt.compiler)
|
||||
implementation(libs.jellyfin.core)
|
||||
implementation(libs.androidx.tv.foundation)
|
||||
implementation(libs.androidx.tv.material)
|
||||
implementation(libs.media3.ffmpeg.decoder)
|
||||
|
||||
coreLibraryDesugaring(libs.android.desugar.jdk)
|
||||
|
||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
}
|
||||
|
|
2
app/tv/proguard-rules.pro
vendored
2
app/tv/proguard-rules.pro
vendored
|
@ -28,3 +28,5 @@
|
|||
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
|
||||
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
|
||||
-dontwarn org.openjsse.net.ssl.OpenJSSE
|
||||
|
||||
-keep class dev.jdtech.**
|
|
@ -23,7 +23,6 @@ data class PlayerActivityNavArgs(
|
|||
@ActivityDestination(
|
||||
navArgsDelegate = PlayerActivityNavArgs::class,
|
||||
)
|
||||
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
||||
class PlayerActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
|
@ -32,7 +32,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.material3.Button
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.LocalContentColor
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
|
@ -71,7 +70,6 @@ fun AddServerScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun AddServerScreenLayout(
|
||||
uiState: AddServerViewModel.UiState,
|
||||
|
|
|
@ -22,7 +22,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import androidx.tv.foundation.lazy.list.TvLazyColumn
|
||||
import androidx.tv.foundation.lazy.list.TvLazyRow
|
||||
import androidx.tv.foundation.lazy.list.items
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
|
@ -88,7 +87,6 @@ fun HomeScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun HomeScreenLayout(
|
||||
uiState: HomeViewModel.UiState,
|
||||
|
|
|
@ -17,7 +17,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import androidx.tv.foundation.lazy.grid.TvGridCells
|
||||
import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
|
||||
import androidx.tv.foundation.lazy.grid.items
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
|
@ -50,7 +49,6 @@ fun LibrariesScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun LibrariesScreenLayout(
|
||||
uiState: MediaViewModel.UiState,
|
||||
|
|
|
@ -18,7 +18,6 @@ import androidx.paging.compose.collectAsLazyPagingItems
|
|||
import androidx.tv.foundation.lazy.grid.TvGridCells
|
||||
import androidx.tv.foundation.lazy.grid.TvGridItemSpan
|
||||
import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
|
@ -75,7 +74,6 @@ fun LibraryScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun LibraryScreenLayout(
|
||||
libraryName: String,
|
||||
|
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Spacer
|
|||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
|
@ -32,7 +33,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.material3.Button
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.LocalContentColor
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
|
@ -86,7 +86,6 @@ fun LoginScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun LoginScreenLayout(
|
||||
uiState: LoginViewModel.UiState,
|
||||
|
@ -110,6 +109,14 @@ private fun LoginScreenLayout(
|
|||
else -> Unit
|
||||
}
|
||||
|
||||
var disclaimer: String? by remember {
|
||||
mutableStateOf(null)
|
||||
}
|
||||
|
||||
if (uiState is LoginViewModel.UiState.Normal) {
|
||||
disclaimer = uiState.disclaimer
|
||||
}
|
||||
|
||||
val isError = uiState is LoginViewModel.UiState.Error
|
||||
val isLoading = uiState is LoginViewModel.UiState.Loading
|
||||
|
||||
|
@ -241,6 +248,10 @@ private fun LoginScreenLayout(
|
|||
}
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = disclaimer ?: "",
|
||||
modifier = Modifier.padding(MaterialTheme.spacings.default),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,7 +265,7 @@ private fun LoginScreenLayout(
|
|||
private fun LoginScreenLayoutPreview() {
|
||||
FindroidTheme {
|
||||
LoginScreenLayout(
|
||||
uiState = LoginViewModel.UiState.Normal,
|
||||
uiState = LoginViewModel.UiState.Normal(),
|
||||
quickConnectUiState = LoginViewModel.QuickConnectUiState.Normal,
|
||||
onLoginClick = { _, _ -> },
|
||||
onQuickConnectClick = {},
|
||||
|
|
|
@ -29,7 +29,6 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Tab
|
||||
|
@ -78,7 +77,6 @@ enum class TabDestination(
|
|||
// LiveTV(CoreR.drawable.ic_tv, CoreR.string.live_tv)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun MainScreenLayout(
|
||||
uiState: MainViewModel.UiState,
|
||||
|
|
|
@ -39,7 +39,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.toSize
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.material3.Button
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.LocalContentColor
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
|
@ -115,7 +114,6 @@ fun MovieScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun MovieScreenLayout(
|
||||
uiState: MovieViewModel.UiState,
|
||||
|
|
|
@ -30,7 +30,6 @@ import androidx.media3.common.TrackSelectionOverride
|
|||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.session.MediaSession
|
||||
import androidx.media3.ui.PlayerView
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
|
@ -204,7 +203,6 @@ fun PlayerScreen(
|
|||
}
|
||||
|
||||
@androidx.annotation.OptIn(UnstableApi::class)
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun VideoPlayerControls(
|
||||
title: String,
|
||||
|
|
|
@ -18,7 +18,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.foundation.lazy.list.TvLazyColumn
|
||||
import androidx.tv.foundation.lazy.list.items
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
|
@ -76,7 +75,6 @@ fun SeasonScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun SeasonScreenLayout(
|
||||
seriesName: String,
|
||||
|
|
|
@ -35,7 +35,6 @@ import androidx.tv.foundation.lazy.list.TvLazyRow
|
|||
import androidx.tv.foundation.lazy.list.items
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.OutlinedButton
|
||||
|
@ -103,7 +102,6 @@ fun ServerSelectScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ServerSelectScreenLayout(
|
||||
uiState: ServerSelectViewModel.UiState,
|
||||
|
@ -246,7 +244,6 @@ private fun ServerSelectScreenLayoutPreviewNoServers() {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ServerComponent(
|
||||
server: DiscoveredServer,
|
||||
|
|
|
@ -19,7 +19,6 @@ import androidx.tv.foundation.lazy.grid.TvGridCells
|
|||
import androidx.tv.foundation.lazy.grid.TvGridItemSpan
|
||||
import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
|
||||
import androidx.tv.foundation.lazy.grid.items
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
|
@ -80,7 +79,6 @@ fun SettingsScreen(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun SettingsScreenLayout(
|
||||
uiState: SettingsViewModel.UiState,
|
||||
|
|
|
@ -25,7 +25,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.tv.foundation.lazy.list.TvLazyColumn
|
||||
import androidx.tv.foundation.lazy.list.items
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
|
@ -90,7 +89,6 @@ fun SettingsSubScreen(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun SettingsSubScreenLayout(
|
||||
uiState: SettingsViewModel.UiState,
|
||||
|
|
|
@ -49,7 +49,6 @@ import androidx.tv.foundation.lazy.list.TvLazyRow
|
|||
import androidx.tv.foundation.lazy.list.items
|
||||
import androidx.tv.foundation.lazy.list.rememberTvLazyListState
|
||||
import androidx.tv.material3.Button
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.LocalContentColor
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
|
@ -126,7 +125,6 @@ fun ShowScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ShowScreenLayout(
|
||||
uiState: ShowViewModel.UiState,
|
||||
|
|
|
@ -33,7 +33,6 @@ import androidx.tv.foundation.lazy.list.TvLazyRow
|
|||
import androidx.tv.foundation.lazy.list.items
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.OutlinedButton
|
||||
|
@ -99,7 +98,6 @@ fun UserSelectScreen(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun UserSelectScreenLayout(
|
||||
uiState: UserSelectViewModel.UiState,
|
||||
|
@ -204,7 +202,6 @@ private fun UserSelectScreenLayoutPreviewNoUsers() {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
private fun UserComponent(
|
||||
user: User,
|
||||
|
|
|
@ -23,7 +23,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Surface
|
||||
import androidx.tv.material3.Text
|
||||
|
@ -32,7 +31,6 @@ import dev.jdtech.jellyfin.ui.dummy.dummyEpisode
|
|||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun EpisodeCard(
|
||||
episode: FindroidEpisode,
|
||||
|
|
|
@ -21,7 +21,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Surface
|
||||
import androidx.tv.material3.Text
|
||||
|
@ -33,7 +32,6 @@ import dev.jdtech.jellyfin.ui.dummy.dummyMovie
|
|||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun ItemCard(
|
||||
item: FindroidItem,
|
||||
|
|
|
@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import coil.compose.AsyncImage
|
||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
||||
|
@ -17,7 +16,6 @@ enum class Direction {
|
|||
HORIZONTAL, VERTICAL
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun ItemPoster(
|
||||
item: FindroidItem,
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.height
|
||||
import androidx.compose.ui.unit.width
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.TabRow
|
||||
|
||||
|
@ -35,7 +34,6 @@ import androidx.tv.material3.TabRow
|
|||
*
|
||||
* This component is adapted from androidx.tv.material3.TabRowDefaults.PillIndicator
|
||||
*/
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun PillBorderIndicator(
|
||||
currentTabPosition: DpRect,
|
||||
|
|
|
@ -17,7 +17,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.Surface
|
||||
import coil.compose.AsyncImage
|
||||
|
@ -29,7 +28,6 @@ import dev.jdtech.jellyfin.ui.dummy.dummyUser
|
|||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
import org.jellyfin.sdk.model.api.ImageType
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun ProfileButton(
|
||||
user: User?,
|
||||
|
|
|
@ -14,7 +14,6 @@ import androidx.compose.ui.draw.clip
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
|
@ -25,7 +24,6 @@ import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
|||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
import dev.jdtech.jellyfin.core.R as CoreR
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun ProgressBadge(
|
||||
item: FindroidItem,
|
||||
|
|
|
@ -21,7 +21,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Surface
|
||||
|
@ -31,7 +30,6 @@ import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
|||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
import dev.jdtech.jellyfin.core.R as CoreR
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsCategoryCard(
|
||||
preference: PreferenceCategory,
|
||||
|
|
|
@ -22,7 +22,6 @@ import androidx.tv.foundation.lazy.list.TvLazyColumn
|
|||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.RadioButton
|
||||
import androidx.tv.material3.Surface
|
||||
|
@ -33,7 +32,6 @@ import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
|||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
import dev.jdtech.jellyfin.core.R as CoreR
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsDetailsCard(
|
||||
preference: PreferenceSelect,
|
||||
|
|
|
@ -21,7 +21,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Surface
|
||||
|
@ -32,7 +31,6 @@ import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
|||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
import dev.jdtech.jellyfin.core.R as CoreR
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsSelectCard(
|
||||
preference: PreferenceSelect,
|
||||
|
|
|
@ -21,7 +21,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Surface
|
||||
|
@ -32,7 +31,6 @@ import dev.jdtech.jellyfin.models.PreferenceSwitch
|
|||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsSwitchCard(
|
||||
preference: PreferenceSwitch,
|
||||
|
|
|
@ -15,12 +15,10 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun VideoPlayerControlsLayout(
|
||||
mediaTitle: @Composable () -> Unit,
|
||||
|
|
|
@ -7,11 +7,9 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.IconButton
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun VideoPlayerMediaButton(
|
||||
icon: Painter,
|
||||
|
|
|
@ -4,12 +4,10 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun VideoPlayerMediaTitle(
|
||||
title: String,
|
||||
|
|
|
@ -21,12 +21,10 @@ import androidx.compose.ui.graphics.Brush
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun VideoPlayerOverlay(
|
||||
isPlaying: Boolean,
|
||||
|
|
|
@ -25,12 +25,11 @@ import androidx.compose.ui.graphics.StrokeCap
|
|||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
||||
import dev.jdtech.jellyfin.utils.handleDPadKeyEvents
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalComposeUiApi::class)
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun VideoPlayerSeekBar(
|
||||
progress: Float,
|
||||
|
|
|
@ -15,7 +15,6 @@ import androidx.compose.ui.focus.focusRequester
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Icon
|
||||
import androidx.tv.material3.IconButton
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
|
@ -25,7 +24,6 @@ import dev.jdtech.jellyfin.ui.theme.spacings
|
|||
import kotlin.time.Duration
|
||||
import dev.jdtech.jellyfin.core.R as CoreR
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun VideoPlayerSeeker(
|
||||
focusRequester: FocusRequester,
|
||||
|
|
|
@ -24,7 +24,6 @@ import androidx.tv.foundation.lazy.list.items
|
|||
import androidx.tv.material3.Border
|
||||
import androidx.tv.material3.ClickableSurfaceDefaults
|
||||
import androidx.tv.material3.ClickableSurfaceScale
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.RadioButton
|
||||
import androidx.tv.material3.Surface
|
||||
|
@ -45,7 +44,6 @@ data class VideoPlayerTrackSelectorDialogResult(
|
|||
val index: Int,
|
||||
) : Parcelable
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Destination(style = BaseDialogStyle::class)
|
||||
@Composable
|
||||
fun VideoPlayerTrackSelectorDialog(
|
||||
|
|
|
@ -2,7 +2,6 @@ package dev.jdtech.jellyfin.ui.theme
|
|||
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.darkColorScheme as darkColorSchemeTv
|
||||
|
||||
val PrimaryDark = Color(0xffa1c9ff)
|
||||
|
@ -23,7 +22,6 @@ val ColorScheme = darkColorScheme(
|
|||
background = Neutral1000,
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
val ColorSchemeTv = darkColorSchemeTv(
|
||||
primary = ColorScheme.primary,
|
||||
onPrimary = ColorScheme.onPrimary,
|
||||
|
|
|
@ -3,7 +3,6 @@ package dev.jdtech.jellyfin.ui.theme
|
|||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Shapes
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Shapes as ShapesTv
|
||||
|
||||
val shapes = Shapes(
|
||||
|
@ -11,7 +10,6 @@ val shapes = Shapes(
|
|||
small = RoundedCornerShape(10.dp),
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
val shapesTv = ShapesTv(
|
||||
extraSmall = shapes.extraSmall,
|
||||
small = shapes.small,
|
||||
|
|
|
@ -4,7 +4,6 @@ import androidx.compose.runtime.Immutable
|
|||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
|
||||
@Immutable
|
||||
|
@ -17,9 +16,7 @@ data class Spacings(
|
|||
val extraLarge: Dp = 64.dp,
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
val MaterialTheme.spacings
|
||||
get() = Spacings()
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
val LocalSpacings = compositionLocalOf { MaterialTheme.spacings }
|
||||
|
|
|
@ -10,12 +10,10 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.NonInteractiveSurfaceDefaults
|
||||
import androidx.tv.material3.Surface
|
||||
import androidx.tv.material3.SurfaceDefaults
|
||||
import androidx.tv.material3.MaterialTheme as MaterialThemeTv
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
@Composable
|
||||
fun FindroidTheme(
|
||||
content: @Composable BoxScope.() -> Unit,
|
||||
|
@ -34,7 +32,7 @@ fun FindroidTheme(
|
|||
shapes = shapesTv,
|
||||
content = {
|
||||
Surface(
|
||||
colors = NonInteractiveSurfaceDefaults.colors(
|
||||
colors = SurfaceDefaults.colors(
|
||||
containerColor = androidx.tv.material3.MaterialTheme.colorScheme.background,
|
||||
),
|
||||
shape = RectangleShape,
|
||||
|
|
|
@ -4,7 +4,6 @@ import androidx.compose.material3.Typography
|
|||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.tv.material3.ExperimentalTvMaterial3Api
|
||||
import androidx.tv.material3.Typography as TypographyTv
|
||||
|
||||
val Typography = Typography(
|
||||
|
@ -34,7 +33,6 @@ val Typography = Typography(
|
|||
),
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalTvMaterial3Api::class)
|
||||
val TypographyTv = TypographyTv(
|
||||
displayMedium = Typography.displayMedium,
|
||||
headlineMedium = Typography.headlineMedium,
|
||||
|
|
|
@ -11,6 +11,5 @@ object Versions {
|
|||
|
||||
val java = JavaVersion.VERSION_17
|
||||
|
||||
const val composeCompiler = "1.5.11"
|
||||
const val ktlint = "0.50.0"
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose.compiler)
|
||||
alias(libs.plugins.kotlin.parcelize)
|
||||
alias(libs.plugins.ksp)
|
||||
alias(libs.plugins.androidx.navigation.safeargs)
|
||||
|
@ -39,10 +40,6 @@ android {
|
|||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = Versions.composeCompiler
|
||||
}
|
||||
}
|
||||
|
||||
ktlint {
|
||||
|
@ -57,16 +54,13 @@ dependencies {
|
|||
implementation(projects.data)
|
||||
implementation(projects.preferences)
|
||||
implementation(projects.player.core)
|
||||
implementation(libs.androidx.activity)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(composeBom)
|
||||
implementation(libs.androidx.compose.ui)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.hilt.work)
|
||||
ksp(libs.androidx.hilt.compiler)
|
||||
implementation(libs.androidx.lifecycle.runtime)
|
||||
implementation(libs.androidx.lifecycle.viewmodel)
|
||||
implementation(libs.androidx.navigation.fragment)
|
||||
implementation(libs.androidx.paging)
|
||||
implementation(libs.androidx.preference)
|
||||
implementation(libs.androidx.room.runtime)
|
||||
|
|
|
@ -61,7 +61,7 @@ constructor(
|
|||
parentId = parentId,
|
||||
includeTypes = itemType,
|
||||
recursive = recursive,
|
||||
sortBy = sortBy,
|
||||
sortBy = if (libraryType == CollectionType.TvShows && sortBy == SortBy.DATE_PLAYED) SortBy.SERIES_DATE_PLAYED else sortBy, // Jellyfin uses a different enum for sorting series by data played
|
||||
sortOrder = sortOrder,
|
||||
).cachedIn(viewModelScope)
|
||||
_uiState.emit(UiState.Normal(items))
|
||||
|
|
|
@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.receiveAsFlow
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jellyfin.sdk.api.client.extensions.authenticateWithQuickConnect
|
||||
import org.jellyfin.sdk.api.client.extensions.brandingApi
|
||||
import org.jellyfin.sdk.model.api.AuthenticateUserByName
|
||||
import org.jellyfin.sdk.model.api.AuthenticationResult
|
||||
import javax.inject.Inject
|
||||
|
@ -32,7 +33,7 @@ constructor(
|
|||
private val jellyfinApi: JellyfinApi,
|
||||
private val database: ServerDatabaseDao,
|
||||
) : ViewModel() {
|
||||
private val _uiState = MutableStateFlow<UiState>(UiState.Normal)
|
||||
private val _uiState = MutableStateFlow<UiState>(UiState.Normal())
|
||||
val uiState = _uiState.asStateFlow()
|
||||
private val _usersState = MutableStateFlow<UsersState>(UsersState.Loading)
|
||||
val usersState = _usersState.asStateFlow()
|
||||
|
@ -44,8 +45,10 @@ constructor(
|
|||
|
||||
private var quickConnectJob: Job? = null
|
||||
|
||||
private var loginDisclaimer: String? = null
|
||||
|
||||
sealed class UiState {
|
||||
data object Normal : UiState()
|
||||
data class Normal(val disclaimer: String? = null) : UiState()
|
||||
data object Loading : UiState()
|
||||
data class Error(val message: UiText) : UiState()
|
||||
}
|
||||
|
@ -62,10 +65,18 @@ constructor(
|
|||
}
|
||||
|
||||
init {
|
||||
loadDisclaimer()
|
||||
loadPublicUsers()
|
||||
loadQuickConnectAvailable()
|
||||
}
|
||||
|
||||
private fun loadDisclaimer() {
|
||||
viewModelScope.launch {
|
||||
loginDisclaimer = jellyfinApi.api.brandingApi.getBrandingOptions().content.loginDisclaimer
|
||||
_uiState.emit(UiState.Normal(loginDisclaimer))
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadPublicUsers() {
|
||||
viewModelScope.launch {
|
||||
_usersState.emit(UsersState.Loading)
|
||||
|
@ -121,7 +132,7 @@ constructor(
|
|||
|
||||
saveAuthenticationResult(authenticationResult)
|
||||
|
||||
_uiState.emit(UiState.Normal)
|
||||
_uiState.emit(UiState.Normal(loginDisclaimer))
|
||||
eventsChannel.send(LoginEvent.NavigateToHome)
|
||||
} catch (e: Exception) {
|
||||
val message =
|
||||
|
|
|
@ -175,4 +175,21 @@
|
|||
<string name="picture_in_picture_gesture">Gest domowy obrazu w obrazie</string>
|
||||
<string name="picture_in_picture">Obraz w obrazie</string>
|
||||
<string name="picture_in_picture_gesture_summary">Użyj przycisku strony głównej lub gestu, aby przejść do trybu obrazu w obrazie podczas odtwarzania wideo</string>
|
||||
<string name="collection_no_media">Ta kolekcja nie zawiera żadnych elementów</string>
|
||||
<string name="no_servers_found">Nie znaleziono żadnego serwera</string>
|
||||
<string name="no_users_found">Nie znaleziono użytkowników</string>
|
||||
<string name="select_user">Wybierz użytkownika</string>
|
||||
<string name="live_tv">Telewizja na żywo</string>
|
||||
<string name="play">Odtwórz</string>
|
||||
<string name="watch_trailer">Odtwórz trailer</string>
|
||||
<string name="player_start_maximized">Uruchom w trybie pełnoekranowym</string>
|
||||
<string name="player_start_maximized_summary">Domyślnie odtwórz wideo w trybie pełnoekranowym</string>
|
||||
<string name="player_gestures_chapter_skip_summary">Długo przytrzymaj z prawej lub lewej strony aby pominąć rozdziały (omija 2x przyspieszenie wideo)</string>
|
||||
<string name="player_gestures_chapter_skip">Gest rozdziału</string>
|
||||
<string name="pref_player_chapter_markers">Znaczniki rozdziałów</string>
|
||||
<string name="pref_player_chapter_markers_summary">Wyświetl znaczniki rozdziałów na pasku odtwarzania</string>
|
||||
<string name="mark_as_played">Zaznacz jako obejrzane</string>
|
||||
<string name="unmark_as_played">Zaznacz jako nieobejrzane</string>
|
||||
<string name="add_to_favorites">Dodaj do ulubionych</string>
|
||||
<string name="remove_from_favorites">Usuń z ulubionych</string>
|
||||
</resources>
|
|
@ -185,4 +185,11 @@
|
|||
<string name="unmark_as_played">Zrušiť označenie pozretého</string>
|
||||
<string name="add_to_favorites">Pridať k obľúbeným</string>
|
||||
<string name="remove_from_favorites">Odstrániť z obľúbených</string>
|
||||
<string name="collection_no_media">Táto kolekcia neobsahuje žiadne média</string>
|
||||
<string name="player_start_maximized">Začni maximalizovaný</string>
|
||||
<string name="player_start_maximized_summary">Štandardne otvor video v maximalizovanom režime</string>
|
||||
<string name="player_gestures_chapter_skip">Gesto na kapitoly</string>
|
||||
<string name="player_gestures_chapter_skip_summary">Dlhé stlačenie na ľavej / pravej strane pre preskočenie kapitoly (prepíše gesto na 2x rýchlosť)</string>
|
||||
<string name="pref_player_chapter_markers">Značky kapitol</string>
|
||||
<string name="pref_player_chapter_markers_summary">Zobraz značky kapitol na časovej osi</string>
|
||||
</resources>
|
|
@ -7,6 +7,7 @@ enum class SortBy(val sortString: String) {
|
|||
DATE_ADDED("DateCreated"),
|
||||
DATE_PLAYED("DatePlayed"),
|
||||
RELEASE_DATE("PremiereDate"),
|
||||
SERIES_DATE_PLAYED("SeriesDatePlayed"),
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -306,7 +306,6 @@ class JellyfinRepositoryImpl(
|
|||
responseProfiles = emptyList(),
|
||||
subtitleProfiles = listOf(
|
||||
SubtitleProfile("srt", SubtitleDeliveryMethod.EXTERNAL),
|
||||
SubtitleProfile("vtt", SubtitleDeliveryMethod.EXTERNAL),
|
||||
SubtitleProfile("ass", SubtitleDeliveryMethod.EXTERNAL),
|
||||
),
|
||||
xmlRootAttributes = emptyList(),
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
[versions]
|
||||
aboutlibraries = "11.1.3"
|
||||
aboutlibraries = "11.2.0"
|
||||
android-desugar-jdk-libs = "2.0.4"
|
||||
android-plugin = "8.3.2"
|
||||
androidx-activity = "1.8.2"
|
||||
android-plugin = "8.4.1"
|
||||
androidx-activity = "1.9.0"
|
||||
androidx-appcompat = "1.6.1"
|
||||
androidx-compose-bom = "2024.04.00"
|
||||
androidx-compose-bom = "2024.05.00"
|
||||
androidx-compose-material3 = "1.2.1"
|
||||
androidx-constraintlayout = "2.1.4"
|
||||
androidx-core = "1.12.0"
|
||||
androidx-core = "1.13.1"
|
||||
androidx-hilt = "1.2.0"
|
||||
androidx-lifecycle = "2.7.0"
|
||||
androidx-lifecycle = "2.8.0"
|
||||
androidx-media3 = "1.3.1"
|
||||
androidx-navigation = "2.7.7"
|
||||
androidx-paging = "3.2.1"
|
||||
androidx-paging = "3.3.0"
|
||||
androidx-preference = "1.2.1"
|
||||
androidx-recyclerview = "1.3.2"
|
||||
androidx-room = "2.6.1"
|
||||
|
@ -23,19 +23,20 @@ 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-tv-material3 = "1.0.0-beta01"
|
||||
androidx-work = "2.9.0"
|
||||
coil = "2.6.0"
|
||||
hilt = "2.51.1"
|
||||
compose-destinations = "1.10.2"
|
||||
jellyfin = "1.4.7"
|
||||
junit = "4.13.2"
|
||||
kotlin = "1.9.23"
|
||||
kotlin = "2.0.0"
|
||||
kotlinx-serialization = "1.6.3"
|
||||
ksp = "1.9.23-1.0.20"
|
||||
ktlint = "12.1.0"
|
||||
ksp = "2.0.0-1.0.21"
|
||||
ktlint = "12.1.1"
|
||||
libmpv = "0.2.0"
|
||||
material = "1.11.0"
|
||||
media3-ffmpeg-decoder = "1.2.1+1"
|
||||
material = "1.12.0"
|
||||
media3-ffmpeg-decoder = "1.3.1+2"
|
||||
timber = "5.0.1"
|
||||
|
||||
[libraries]
|
||||
|
@ -55,7 +56,7 @@ androidx-core = { group = "androidx.core", name = "core", version.ref = "android
|
|||
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidx-hilt" }
|
||||
androidx-hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "androidx-hilt" }
|
||||
androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "androidx-hilt" }
|
||||
androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime", version.ref = "androidx-lifecycle" }
|
||||
androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" }
|
||||
androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" }
|
||||
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
|
||||
androidx-media3-common = { group = "androidx.media3", name = "media3-common", version.ref = "androidx-media3" }
|
||||
|
@ -79,7 +80,7 @@ androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref
|
|||
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-tv-material = { group = "androidx.tv", name = "tv-material", version.ref = "androidx-tv-material3" }
|
||||
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" }
|
||||
|
@ -106,6 +107,7 @@ android-library = { id = "com.android.library", version.ref = "android-plugin" }
|
|||
androidx-navigation-safeargs = { id = "androidx.navigation.safeargs.kotlin", version.ref = "androidx-navigation" }
|
||||
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
kotlin-compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
|
||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
|
|
|
@ -36,10 +36,5 @@ ktlint {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.data)
|
||||
implementation(projects.preferences)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.preference)
|
||||
implementation(libs.jellyfin.core)
|
||||
implementation(libs.timber)
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ dependencies {
|
|||
implementation(projects.player.core)
|
||||
implementation(projects.data)
|
||||
implementation(projects.preferences)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.lifecycle.runtime)
|
||||
implementation(libs.androidx.lifecycle.viewmodel)
|
||||
implementation(libs.androidx.media3.exoplayer)
|
||||
|
|
|
@ -9,7 +9,7 @@ fun List<Tracks.Group>.getTrackNames(): Array<String> {
|
|||
val format = group.mediaTrackGroup.getFormat(0)
|
||||
nameParts.run {
|
||||
add(format.label)
|
||||
add(format.language?.let { Locale(it).displayLanguage })
|
||||
add(format.language?.let { Locale(it.split("-").last()).displayLanguage })
|
||||
add(format.codecs)
|
||||
filterNotNull().joinToString(separator = " - ")
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import dev.jdtech.jellyfin.repository.JellyfinRepository
|
|||
import dev.jdtech.jellyfin.utils.bif.BifData
|
||||
import dev.jdtech.jellyfin.utils.bif.BifUtil
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -37,7 +36,6 @@ import kotlinx.coroutines.flow.asStateFlow
|
|||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
@ -193,11 +191,6 @@ constructor(
|
|||
currentMediaItemIndex,
|
||||
startPosition,
|
||||
)
|
||||
if (appPreferences.playerMpv) { // For some reason, adding a 1ms delay between these two lines fixes a crash when playing with mpv from downloads
|
||||
withContext(Dispatchers.IO) {
|
||||
Thread.sleep(1)
|
||||
}
|
||||
}
|
||||
player.prepare()
|
||||
player.play()
|
||||
pollPosition(player)
|
||||
|
|
|
@ -139,20 +139,13 @@ class PlayerViewModel @Inject internal constructor(
|
|||
mediaStream.isExternal && mediaStream.type == MediaStreamType.SUBTITLE && !mediaStream.path.isNullOrBlank()
|
||||
}
|
||||
.map { mediaStream ->
|
||||
// Temp fix for vtt
|
||||
// Jellyfin returns a srt stream when it should return vtt stream.
|
||||
var deliveryUrl = mediaStream.path!!
|
||||
if (mediaStream.codec == "webvtt") {
|
||||
deliveryUrl = deliveryUrl.replace("Stream.srt", "Stream.vtt")
|
||||
}
|
||||
|
||||
ExternalSubtitle(
|
||||
mediaStream.title,
|
||||
mediaStream.language,
|
||||
Uri.parse(deliveryUrl),
|
||||
Uri.parse(mediaStream.path!!),
|
||||
when (mediaStream.codec) {
|
||||
"subrip" -> MimeTypes.APPLICATION_SUBRIP
|
||||
"webvtt" -> MimeTypes.TEXT_VTT
|
||||
"webvtt" -> MimeTypes.APPLICATION_SUBRIP
|
||||
"ass" -> MimeTypes.TEXT_SSA
|
||||
else -> MimeTypes.TEXT_UNKNOWN
|
||||
},
|
||||
|
|
|
@ -15,4 +15,5 @@
|
|||
<string name="player_controls_progress">Pasek postępu</string>
|
||||
<string name="player_controls_play_pause">Odtwórz/wstrzymaj</string>
|
||||
<string name="player_controls_picture_in_picture">Wejdź w tryb obrazu w obrazie</string>
|
||||
<string name="none">Brak</string>
|
||||
</resources>
|
Loading…
Reference in a new issue