Temporary remove all TV code (#229)
* Remove all tv code * Remove banner
This commit is contained in:
parent
4a611e160d
commit
25efbb6eab
46 changed files with 54 additions and 2522 deletions
|
@ -74,7 +74,6 @@ dependencies {
|
|||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.leanback)
|
||||
implementation(libs.androidx.lifecycle.runtime)
|
||||
implementation(libs.androidx.lifecycle.viewmodel)
|
||||
implementation(libs.androidx.media3.exoplayer)
|
||||
|
|
|
@ -3,14 +3,11 @@
|
|||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.wifi" android:required="false" />
|
||||
|
||||
<application
|
||||
android:name=".BaseApplication"
|
||||
android:allowBackup="true"
|
||||
android:banner="@mipmap/ic_banner"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:fullBackupOnly="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
@ -23,10 +20,6 @@
|
|||
android:name=".PlayerActivity"
|
||||
android:screenOrientation="sensorLandscape" />
|
||||
|
||||
<activity
|
||||
android:name=".tv.TvPlayerActivity"
|
||||
android:screenOrientation="userLandscape" />
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
|
@ -34,9 +27,7 @@
|
|||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package dev.jdtech.jellyfin
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.viewModels
|
||||
|
@ -26,7 +24,6 @@ import javax.inject.Inject
|
|||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
|
||||
private val viewModel: MainViewModel by viewModels()
|
||||
|
||||
|
@ -43,7 +40,6 @@ class MainActivity : AppCompatActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
uiModeManager = getSystemService(UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
setContentView(binding.root)
|
||||
|
||||
|
@ -53,24 +49,13 @@ class MainActivity : AppCompatActivity() {
|
|||
val inflater = navController.navInflater
|
||||
val graph = inflater.inflate(R.navigation.app_navigation)
|
||||
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
graph.setStartDestination(R.id.homeFragmentTv)
|
||||
checkServersEmpty(graph)
|
||||
checkUser(graph)
|
||||
if (!viewModel.startDestinationTvChanged) {
|
||||
viewModel.startDestinationTvChanged = true
|
||||
navController.setGraph(graph, intent.extras)
|
||||
}
|
||||
} else {
|
||||
checkServersEmpty(graph) {
|
||||
navController.setGraph(graph, intent.extras)
|
||||
}
|
||||
checkUser(graph) {
|
||||
navController.setGraph(graph, intent.extras)
|
||||
}
|
||||
}
|
||||
|
||||
if (uiModeManager.currentModeType != Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
val navView: NavigationBarView = binding.navView as NavigationBarView
|
||||
|
||||
setSupportActionBar(binding.mainToolbar)
|
||||
|
@ -92,14 +77,13 @@ class MainActivity : AppCompatActivity() {
|
|||
NavigationUI.setupWithNavController(navView, navController, false)
|
||||
|
||||
navController.addOnDestinationChangedListener { _, destination, _ ->
|
||||
binding.navView!!.visibility = when (destination.id) {
|
||||
binding.navView.visibility = when (destination.id) {
|
||||
R.id.twoPaneSettingsFragment, R.id.serverSelectFragment, R.id.addServerFragment, R.id.loginFragment, R.id.about_libraries_dest, R.id.usersFragment, R.id.serverAddressesFragment -> View.GONE
|
||||
else -> View.VISIBLE
|
||||
}
|
||||
if (destination.id == R.id.about_libraries_dest) binding.mainToolbar?.title =
|
||||
if (destination.id == R.id.about_libraries_dest) binding.mainToolbar.title =
|
||||
getString(R.string.app_info)
|
||||
}
|
||||
}
|
||||
|
||||
loadDownloadLocation(applicationContext)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
package dev.jdtech.jellyfin.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.widget.EditText
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dev.jdtech.jellyfin.R
|
||||
|
@ -17,16 +13,10 @@ class AddServerAddressDialog(
|
|||
private val viewModel: ServerAddressesViewModel
|
||||
) : DialogFragment() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
val editText = EditText(this.context)
|
||||
editText.hint = "http://<server_ip>:8096"
|
||||
return activity?.let { activity ->
|
||||
val builder = if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
AlertDialog.Builder(activity)
|
||||
} else {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
}
|
||||
val builder = MaterialAlertDialogBuilder(activity)
|
||||
builder
|
||||
.setTitle("Add server address")
|
||||
.setView(editText)
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package dev.jdtech.jellyfin.fragments
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.AppCompatEditText
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -27,7 +24,6 @@ import timber.log.Timber
|
|||
class AddServerFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentAddServerBinding
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
private val viewModel: AddServerViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -36,8 +32,6 @@ class AddServerFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentAddServerBinding.inflate(inflater)
|
||||
uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
(binding.editTextServerAddress as AppCompatEditText).setOnEditorActionListener { _, actionId, _ ->
|
||||
return@setOnEditorActionListener when (actionId) {
|
||||
|
@ -98,43 +92,25 @@ class AddServerFragment : Fragment() {
|
|||
private fun bindUiStateNormal() {
|
||||
binding.buttonConnect.isEnabled = true
|
||||
binding.progressCircular.isVisible = false
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
(binding.editTextServerAddress as AppCompatEditText).isEnabled = true
|
||||
} else {
|
||||
binding.editTextServerAddressLayout!!.isEnabled = true
|
||||
}
|
||||
binding.editTextServerAddressLayout.isEnabled = true
|
||||
}
|
||||
|
||||
private fun bindUiStateError(uiState: AddServerViewModel.UiState.Error) {
|
||||
binding.buttonConnect.isEnabled = true
|
||||
binding.progressCircular.isVisible = false
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
(binding.editTextServerAddress as AppCompatEditText).apply {
|
||||
binding.editTextServerAddressLayout.apply {
|
||||
error = uiState.message
|
||||
isEnabled = true
|
||||
}
|
||||
} else {
|
||||
binding.editTextServerAddressLayout!!.apply {
|
||||
error = uiState.message
|
||||
isEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUiStateLoading() {
|
||||
binding.buttonConnect.isEnabled = false
|
||||
binding.progressCircular.isVisible = true
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
(binding.editTextServerAddress as AppCompatEditText).apply {
|
||||
binding.editTextServerAddressLayout.apply {
|
||||
error = null
|
||||
isEnabled = false
|
||||
}
|
||||
} else {
|
||||
binding.editTextServerAddressLayout!!.apply {
|
||||
error = null
|
||||
isEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindDiscoveredServersStateServers(
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package dev.jdtech.jellyfin.fragments
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
|
@ -10,7 +8,6 @@ import android.view.MenuInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.MenuHost
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -22,7 +19,6 @@ import androidx.lifecycle.repeatOnLifecycle
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.paging.LoadState
|
||||
import androidx.recyclerview.widget.LinearSnapHelper
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.adapters.ViewItemPagingAdapter
|
||||
|
@ -42,7 +38,6 @@ import org.jellyfin.sdk.model.api.SortOrder
|
|||
class LibraryFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentLibraryBinding
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
private val viewModel: LibraryViewModel by viewModels()
|
||||
private val args: LibraryFragmentArgs by navArgs()
|
||||
|
||||
|
@ -57,8 +52,6 @@ class LibraryFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentLibraryBinding.inflate(inflater, container, false)
|
||||
uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
return binding.root
|
||||
}
|
||||
|
||||
|
@ -105,8 +98,6 @@ class LibraryFragment : Fragment() {
|
|||
viewLifecycleOwner, Lifecycle.State.RESUMED
|
||||
)
|
||||
|
||||
binding.title?.text = args.libraryName
|
||||
|
||||
binding.errorLayout.errorRetryButton.setOnClickListener {
|
||||
viewModel.loadItems(args.libraryId, args.libraryType)
|
||||
}
|
||||
|
@ -118,11 +109,6 @@ class LibraryFragment : Fragment() {
|
|||
)
|
||||
}
|
||||
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
val snapHelper = LinearSnapHelper()
|
||||
snapHelper.attachToRecyclerView(binding.itemsRecyclerView)
|
||||
}
|
||||
|
||||
binding.itemsRecyclerView.adapter =
|
||||
ViewItemPagingAdapter(
|
||||
ViewItemPagingAdapter.OnClickListener { item ->
|
||||
|
@ -205,15 +191,6 @@ class LibraryFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun navigateToMediaInfoFragment(item: BaseItemDto) {
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
findNavController().navigate(
|
||||
LibraryFragmentDirections.actionLibraryFragmentToMediaDetailFragment(
|
||||
item.id,
|
||||
item.name,
|
||||
item.type
|
||||
)
|
||||
)
|
||||
} else {
|
||||
findNavController().navigate(
|
||||
LibraryFragmentDirections.actionLibraryFragmentToMediaInfoFragment(
|
||||
item.id,
|
||||
|
@ -223,4 +200,3 @@ class LibraryFragment : Fragment() {
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package dev.jdtech.jellyfin.fragments
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.AppCompatEditText
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -31,7 +28,6 @@ import timber.log.Timber
|
|||
class LoginFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentLoginBinding
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
private val viewModel: LoginViewModel by viewModels()
|
||||
private val args: LoginFragmentArgs by navArgs()
|
||||
|
||||
|
@ -47,8 +43,6 @@ class LoginFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentLoginBinding.inflate(inflater)
|
||||
uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
if (args.reLogin) {
|
||||
appPreferences.currentServer?.let { currentServerId ->
|
||||
|
@ -117,49 +111,28 @@ class LoginFragment : Fragment() {
|
|||
private fun bindUiStateNormal() {
|
||||
binding.buttonLogin.isEnabled = true
|
||||
binding.progressCircular.isVisible = false
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
(binding.editTextUsername as AppCompatEditText).isEnabled = true
|
||||
(binding.editTextPassword as AppCompatEditText).isEnabled = true
|
||||
} else {
|
||||
binding.editTextUsernameLayout!!.isEnabled = true
|
||||
binding.editTextPasswordLayout!!.isEnabled = true
|
||||
}
|
||||
binding.editTextUsernameLayout.isEnabled = true
|
||||
binding.editTextPasswordLayout.isEnabled = true
|
||||
}
|
||||
|
||||
private fun bindUiStateError(uiState: LoginViewModel.UiState.Error) {
|
||||
binding.buttonLogin.isEnabled = true
|
||||
binding.progressCircular.isVisible = false
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
(binding.editTextUsername as AppCompatEditText).apply {
|
||||
binding.editTextUsernameLayout.apply {
|
||||
error = uiState.message
|
||||
isEnabled = true
|
||||
}
|
||||
(binding.editTextPassword as AppCompatEditText).isEnabled = true
|
||||
} else {
|
||||
binding.editTextUsernameLayout!!.apply {
|
||||
error = uiState.message
|
||||
isEnabled = true
|
||||
}
|
||||
binding.editTextPasswordLayout!!.isEnabled = true
|
||||
}
|
||||
binding.editTextPasswordLayout.isEnabled = true
|
||||
}
|
||||
|
||||
private fun bindUiStateLoading() {
|
||||
binding.buttonLogin.isEnabled = false
|
||||
binding.progressCircular.isVisible = true
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
(binding.editTextUsername as AppCompatEditText).apply {
|
||||
binding.editTextUsernameLayout.apply {
|
||||
error = null
|
||||
isEnabled = false
|
||||
}
|
||||
(binding.editTextPassword as AppCompatEditText).isEnabled = false
|
||||
} else {
|
||||
binding.editTextUsernameLayout!!.apply {
|
||||
error = null
|
||||
isEnabled = false
|
||||
}
|
||||
binding.editTextPasswordLayout!!.isEnabled = false
|
||||
}
|
||||
binding.editTextPasswordLayout.isEnabled = false
|
||||
}
|
||||
|
||||
private fun bindUsersStateUsers(usersState: LoginViewModel.UsersState.Users) {
|
||||
|
@ -179,10 +152,6 @@ class LoginFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun navigateToHomeFragment() {
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
findNavController().navigate(LoginFragmentDirections.actionLoginFragmentToHomeFragmentTv())
|
||||
} else {
|
||||
findNavController().navigate(LoginFragmentDirections.actionLoginFragmentToHomeFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package dev.jdtech.jellyfin.fragments
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
|
@ -27,7 +24,6 @@ import timber.log.Timber
|
|||
class ServerAddressesFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentServerAddressesBinding
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
private val viewModel: ServerAddressesViewModel by viewModels()
|
||||
private val args: UsersFragmentArgs by navArgs()
|
||||
|
||||
|
@ -37,8 +33,6 @@ class ServerAddressesFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentServerAddressesBinding.inflate(inflater)
|
||||
uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
binding.addressesRecyclerView.adapter =
|
||||
ServerAddressAdapter(
|
||||
|
@ -98,10 +92,6 @@ class ServerAddressesFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun navigateToMainActivity() {
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
findNavController().navigate(UsersFragmentDirections.actionUsersFragmentToHomeFragmentTv())
|
||||
} else {
|
||||
findNavController().navigate(UsersFragmentDirections.actionUsersFragmentToHomeFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package dev.jdtech.jellyfin.fragments
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
|
@ -24,7 +21,6 @@ import kotlinx.coroutines.launch
|
|||
class ServerSelectFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentServerSelectBinding
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
private val viewModel: ServerSelectViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -33,8 +29,6 @@ class ServerSelectFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentServerSelectBinding.inflate(inflater)
|
||||
uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
|
||||
|
@ -78,10 +72,6 @@ class ServerSelectFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun navigateToMainActivity() {
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
findNavController().navigate(ServerSelectFragmentDirections.actionServerSelectFragmentToHomeFragmentTv())
|
||||
} else {
|
||||
findNavController().navigate(ServerSelectFragmentDirections.actionServerSelectFragmentToHomeFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package dev.jdtech.jellyfin.fragments
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
|
@ -27,7 +24,6 @@ import timber.log.Timber
|
|||
class UsersFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentUsersBinding
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
private val viewModel: UsersViewModel by viewModels()
|
||||
private val args: UsersFragmentArgs by navArgs()
|
||||
|
||||
|
@ -37,8 +33,6 @@ class UsersFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentUsersBinding.inflate(inflater)
|
||||
uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
binding.usersRecyclerView.adapter =
|
||||
UserListAdapter(
|
||||
|
@ -101,10 +95,6 @@ class UsersFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun navigateToMainActivity() {
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
findNavController().navigate(UsersFragmentDirections.actionUsersFragmentToHomeFragmentTv())
|
||||
} else {
|
||||
findNavController().navigate(UsersFragmentDirections.actionUsersFragmentToHomeFragment())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
package dev.jdtech.jellyfin.tv
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageButton
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.navigation.navArgs
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.BasePlayerActivity
|
||||
import dev.jdtech.jellyfin.PlayerActivityArgs
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.databinding.ActivityPlayerTvBinding
|
||||
import dev.jdtech.jellyfin.mpv.MPVPlayer
|
||||
import dev.jdtech.jellyfin.mpv.TrackType
|
||||
import dev.jdtech.jellyfin.mpv.TrackType.AUDIO
|
||||
import dev.jdtech.jellyfin.mpv.TrackType.SUBTITLE
|
||||
import dev.jdtech.jellyfin.tv.ui.TrackSelectorAdapter
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
||||
import timber.log.Timber
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class TvPlayerActivity : BasePlayerActivity() {
|
||||
|
||||
private lateinit var binding: ActivityPlayerTvBinding
|
||||
override val viewModel: PlayerActivityViewModel by viewModels()
|
||||
private val args: PlayerActivityArgs by navArgs()
|
||||
private var displayedPopup: PopupWindow? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Timber.d("Player activity created.")
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityPlayerTvBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
||||
binding.playerView.player = viewModel.player
|
||||
val playerControls = binding.playerView.findViewById<View>(R.id.player_controls)
|
||||
configureInsets(playerControls)
|
||||
|
||||
bind()
|
||||
viewModel.initializePlayer(args.items)
|
||||
hideSystemUI()
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return if (!binding.playerView.isControllerFullyVisible) {
|
||||
binding.playerView.showController()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun bind() = with(binding.playerView) {
|
||||
val videoNameTextView = findViewById<TextView>(R.id.video_name)
|
||||
viewModel.currentItemTitle.observe(this@TvPlayerActivity) { title ->
|
||||
videoNameTextView.text = title
|
||||
}
|
||||
|
||||
findViewById<ImageButton>(R.id.exo_play_pause).apply {
|
||||
setOnClickListener {
|
||||
when {
|
||||
viewModel.player.isPlaying -> {
|
||||
viewModel.player.pause()
|
||||
setImageDrawable(
|
||||
ResourcesCompat.getDrawable(resources, R.drawable.ic_play, theme)
|
||||
)
|
||||
}
|
||||
viewModel.player.isLoading -> Unit
|
||||
else -> {
|
||||
viewModel.player.play()
|
||||
setImageDrawable(
|
||||
ResourcesCompat.getDrawable(resources, R.drawable.ic_play, theme)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findViewById<View>(R.id.back_button).setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
bindAudioControl()
|
||||
bindSubtitleControl()
|
||||
}
|
||||
|
||||
private fun bindAudioControl() {
|
||||
val audioBtn = binding.playerView.findViewById<ImageButton>(R.id.btn_audio_track)
|
||||
|
||||
audioBtn.setOnFocusChangeListener { _, hasFocus ->
|
||||
displayedPopup = if (hasFocus) {
|
||||
val items = viewModel.currentAudioTracks.toUiTrack()
|
||||
audioBtn.showPopupWindowAbove(items, AUDIO)
|
||||
} else {
|
||||
displayedPopup?.dismiss()
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindSubtitleControl() {
|
||||
val subtitleBtn = binding.playerView.findViewById<ImageButton>(R.id.btn_subtitle)
|
||||
|
||||
subtitleBtn.setOnFocusChangeListener { v, hasFocus ->
|
||||
v.isFocusable = true
|
||||
displayedPopup = if (hasFocus) {
|
||||
val items = viewModel.currentSubtitleTracks.toUiTrack()
|
||||
subtitleBtn.showPopupWindowAbove(items, SUBTITLE)
|
||||
} else {
|
||||
displayedPopup?.dismiss()
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<MPVPlayer.Companion.Track>.toUiTrack() = map { track ->
|
||||
TrackSelectorAdapter.Track(
|
||||
title = track.title,
|
||||
language = track.lang,
|
||||
codec = track.codec,
|
||||
selected = track.selected,
|
||||
playerTrack = track
|
||||
)
|
||||
}
|
||||
|
||||
private fun View.showPopupWindowAbove(
|
||||
items: List<TrackSelectorAdapter.Track>,
|
||||
type: TrackType
|
||||
): PopupWindow {
|
||||
val popup = PopupWindow(this.context)
|
||||
popup.contentView = LayoutInflater.from(context).inflate(R.layout.track_selector, null)
|
||||
val recyclerView = popup.contentView.findViewById<RecyclerView>(R.id.track_selector)
|
||||
|
||||
recyclerView.adapter = TrackSelectorAdapter(items, viewModel, type) { popup.dismiss() }
|
||||
|
||||
val startViewCoords = IntArray(2)
|
||||
getLocationInWindow(startViewCoords)
|
||||
|
||||
val itemHeight = resources.getDimension(R.dimen.track_selection_item_height).toInt()
|
||||
val totalHeight = items.size * itemHeight
|
||||
|
||||
popup.showAsDropDown(
|
||||
binding.root,
|
||||
startViewCoords.first(),
|
||||
startViewCoords.last() - totalHeight,
|
||||
Gravity.TOP
|
||||
)
|
||||
|
||||
return popup
|
||||
}
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
package dev.jdtech.jellyfin.tv.ui
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent.KEYCODE_DPAD_DOWN
|
||||
import android.view.KeyEvent.KEYCODE_DPAD_DOWN_LEFT
|
||||
import android.view.View
|
||||
import android.widget.ImageButton
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.leanback.app.BrowseSupportFragment
|
||||
import androidx.leanback.widget.ArrayObjectAdapter
|
||||
import androidx.leanback.widget.DiffCallback
|
||||
import androidx.leanback.widget.HeaderItem
|
||||
import androidx.leanback.widget.ListRow
|
||||
import androidx.leanback.widget.ListRowPresenter
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.adapters.HomeItem
|
||||
import dev.jdtech.jellyfin.fragments.HomeFragmentDirections
|
||||
import dev.jdtech.jellyfin.viewmodels.HomeViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import timber.log.Timber
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class HomeFragment : BrowseSupportFragment() {
|
||||
|
||||
private val viewModel: HomeViewModel by viewModels()
|
||||
|
||||
private lateinit var rowsAdapter: ArrayObjectAdapter
|
||||
private lateinit var uiModeManager: UiModeManager
|
||||
|
||||
private val adapterMap = mutableMapOf<String, ArrayObjectAdapter>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
uiModeManager =
|
||||
requireContext().getSystemService(AppCompatActivity.UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
val rowPresenter = ListRowPresenter()
|
||||
rowPresenter.selectEffectEnabled = false
|
||||
|
||||
headersState = HEADERS_ENABLED
|
||||
rowsAdapter = ArrayObjectAdapter(rowPresenter)
|
||||
adapter = rowsAdapter
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
view.findViewById<ImageButton>(R.id.settings).apply {
|
||||
setOnKeyListener { _, keyCode, _ ->
|
||||
if (keyCode == KEYCODE_DPAD_DOWN || keyCode == KEYCODE_DPAD_DOWN_LEFT) {
|
||||
headersSupportFragment.view?.requestFocus()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
setOnClickListener { navigateToSettingsFragment() }
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.uiState.collect { uiState ->
|
||||
Timber.d("$uiState")
|
||||
when (uiState) {
|
||||
is HomeViewModel.UiState.Normal -> bindUiStateNormal(uiState)
|
||||
is HomeViewModel.UiState.Loading -> bindUiStateLoading()
|
||||
is HomeViewModel.UiState.Error -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.loadData(includeLibraries = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val diffCallbackListRow = object : DiffCallback<ListRow>() {
|
||||
override fun areItemsTheSame(oldItem: ListRow, newItem: ListRow): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: ListRow, newItem: ListRow): Boolean {
|
||||
Timber.d((oldItem.adapter.size() == newItem.adapter.size()).toString())
|
||||
return oldItem.adapter.size() == newItem.adapter.size()
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUiStateNormal(uiState: HomeViewModel.UiState.Normal) {
|
||||
progressBarManager.hide()
|
||||
uiState.apply {
|
||||
rowsAdapter.setItems(homeItems.map { homeItem -> homeItem.toListRow() }, diffCallbackListRow)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUiStateLoading() {
|
||||
progressBarManager.show()
|
||||
}
|
||||
|
||||
private fun HomeItem.toListRow(): ListRow {
|
||||
return ListRow(
|
||||
toHeader(),
|
||||
toItems()
|
||||
)
|
||||
}
|
||||
|
||||
private fun HomeItem.toHeader(): HeaderItem {
|
||||
return when (this) {
|
||||
is HomeItem.Libraries -> HeaderItem(section.name)
|
||||
is HomeItem.Section -> HeaderItem(homeSection.name)
|
||||
is HomeItem.ViewItem -> HeaderItem(
|
||||
String.format(
|
||||
resources.getString(R.string.latest_library),
|
||||
view.name
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val diffCallback = object : DiffCallback<BaseItemDto>() {
|
||||
override fun areItemsTheSame(oldItem: BaseItemDto, newItem: BaseItemDto): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: BaseItemDto, newItem: BaseItemDto): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
}
|
||||
|
||||
private fun HomeItem.toItems(): ArrayObjectAdapter {
|
||||
val name = this.toHeader().name
|
||||
val items = when (this) {
|
||||
is HomeItem.Libraries -> section.items
|
||||
is HomeItem.Section -> homeSection.items
|
||||
is HomeItem.ViewItem -> view.items
|
||||
}
|
||||
if (name in adapterMap) {
|
||||
adapterMap[name]?.setItems(items, diffCallback)
|
||||
} else {
|
||||
adapterMap[name] = when (this) {
|
||||
is HomeItem.Libraries -> ArrayObjectAdapter(
|
||||
LibaryItemPresenter { item ->
|
||||
navigateToLibraryFragment(item)
|
||||
}
|
||||
).apply { setItems(items, diffCallback) }
|
||||
is HomeItem.Section -> ArrayObjectAdapter(
|
||||
DynamicMediaItemPresenter { item ->
|
||||
navigateToMediaDetailFragment(item)
|
||||
}
|
||||
).apply { setItems(items, diffCallback) }
|
||||
is HomeItem.ViewItem -> ArrayObjectAdapter(
|
||||
MediaItemPresenter { item ->
|
||||
navigateToMediaDetailFragment(item)
|
||||
}
|
||||
).apply { setItems(items, diffCallback) }
|
||||
}
|
||||
}
|
||||
|
||||
return adapterMap[name]!!
|
||||
}
|
||||
|
||||
private fun navigateToLibraryFragment(library: BaseItemDto) {
|
||||
if (uiModeManager.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
|
||||
findNavController().navigate(
|
||||
dev.jdtech.jellyfin.tv.ui.HomeFragmentDirections.actionHomeFragmentToLibraryFragment(
|
||||
library.id,
|
||||
library.name,
|
||||
library.collectionType
|
||||
)
|
||||
)
|
||||
} else {
|
||||
findNavController().navigate(
|
||||
HomeFragmentDirections.actionNavigationHomeToLibraryFragment(
|
||||
library.id,
|
||||
library.name,
|
||||
library.collectionType
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToMediaDetailFragment(item: BaseItemDto) {
|
||||
findNavController().navigate(
|
||||
HomeFragmentDirections.actionHomeFragmentToMediaDetailFragment(
|
||||
item.id,
|
||||
item.seriesName ?: item.name,
|
||||
item.type
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun navigateToSettingsFragment() {
|
||||
findNavController().navigate(
|
||||
HomeFragmentDirections.actionHomeFragmentToSettingsFragment()
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,258 +0,0 @@
|
|||
package dev.jdtech.jellyfin.tv.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.adapters.PersonListAdapter
|
||||
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
|
||||
import dev.jdtech.jellyfin.bindBaseItemImage
|
||||
import dev.jdtech.jellyfin.databinding.MediaDetailFragmentBinding
|
||||
import dev.jdtech.jellyfin.dialogs.VideoVersionDialogFragment
|
||||
import dev.jdtech.jellyfin.models.PlayerItem
|
||||
import dev.jdtech.jellyfin.viewmodels.MediaInfoViewModel
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel.PlayerItemError
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel.PlayerItems
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class MediaDetailFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: MediaDetailFragmentBinding
|
||||
|
||||
private val viewModel: MediaInfoViewModel by viewModels()
|
||||
private val playerViewModel: PlayerViewModel by viewModels()
|
||||
|
||||
private val args: MediaDetailFragmentArgs by navArgs()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
viewModel.loadData(args.itemId, args.itemType)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = MediaDetailFragmentBinding.inflate(inflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.uiState.collect { uiState ->
|
||||
Timber.d("$uiState")
|
||||
when (uiState) {
|
||||
is MediaInfoViewModel.UiState.Normal -> bindUiStateNormal(uiState)
|
||||
is MediaInfoViewModel.UiState.Loading -> Unit
|
||||
is MediaInfoViewModel.UiState.Error -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val seasonsAdapter = ViewItemListAdapter(
|
||||
fixedWidth = true,
|
||||
onClickListener = ViewItemListAdapter.OnClickListener {}
|
||||
)
|
||||
|
||||
binding.seasonsRow.gridView.adapter = seasonsAdapter
|
||||
binding.seasonsRow.gridView.verticalSpacing = 25
|
||||
|
||||
val castAdapter = PersonListAdapter {
|
||||
Toast.makeText(requireContext(), "Not yet implemented", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
binding.castRow.gridView.adapter = castAdapter
|
||||
binding.castRow.gridView.verticalSpacing = 25
|
||||
|
||||
playerViewModel.onPlaybackRequested(lifecycleScope) { playerItems ->
|
||||
when (playerItems) {
|
||||
is PlayerItemError -> bindPlayerItemsError(playerItems)
|
||||
is PlayerItems -> bindPlayerItems(playerItems)
|
||||
}
|
||||
}
|
||||
|
||||
binding.playButton.setOnClickListener {
|
||||
binding.playButton.setImageResource(android.R.color.transparent)
|
||||
binding.progressCircular.isVisible = true
|
||||
viewModel.item?.let { item ->
|
||||
playerViewModel.loadPlayerItems(item) {
|
||||
VideoVersionDialogFragment(item, playerViewModel).show(
|
||||
parentFragmentManager,
|
||||
"videoversiondialog"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.trailerButton.setOnClickListener {
|
||||
if (viewModel.item?.remoteTrailers.isNullOrEmpty()) return@setOnClickListener
|
||||
val intent = Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse(viewModel.item?.remoteTrailers?.get(0)?.url)
|
||||
)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.checkButton.setOnClickListener {
|
||||
when (viewModel.played) {
|
||||
true -> {
|
||||
viewModel.markAsUnplayed(args.itemId)
|
||||
binding.checkButton.imageTintList = ColorStateList.valueOf(
|
||||
resources.getColor(
|
||||
R.color.white,
|
||||
requireActivity().theme
|
||||
)
|
||||
)
|
||||
}
|
||||
false -> {
|
||||
viewModel.markAsPlayed(args.itemId)
|
||||
binding.checkButton.imageTintList = ColorStateList.valueOf(
|
||||
resources.getColor(
|
||||
R.color.red,
|
||||
requireActivity().theme
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.favoriteButton.setOnClickListener {
|
||||
when (viewModel.favorite) {
|
||||
true -> {
|
||||
viewModel.unmarkAsFavorite(args.itemId)
|
||||
binding.favoriteButton.setImageResource(R.drawable.ic_heart)
|
||||
binding.favoriteButton.imageTintList = ColorStateList.valueOf(
|
||||
resources.getColor(
|
||||
R.color.white,
|
||||
requireActivity().theme
|
||||
)
|
||||
)
|
||||
}
|
||||
false -> {
|
||||
viewModel.markAsFavorite(args.itemId)
|
||||
binding.favoriteButton.setImageResource(R.drawable.ic_heart_filled)
|
||||
binding.favoriteButton.imageTintList = ColorStateList.valueOf(
|
||||
resources.getColor(
|
||||
R.color.red,
|
||||
requireActivity().theme
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindUiStateNormal(uiState: MediaInfoViewModel.UiState.Normal) {
|
||||
uiState.apply {
|
||||
binding.seasonsLayout.isVisible = seasons.isNotEmpty()
|
||||
val seasonsAdapter = binding.seasonsRow.gridView.adapter as ViewItemListAdapter
|
||||
seasonsAdapter.submitList(seasons)
|
||||
binding.castLayout.isVisible = actors.isNotEmpty()
|
||||
val actorsAdapter = binding.castRow.gridView.adapter as PersonListAdapter
|
||||
actorsAdapter.submitList(actors)
|
||||
|
||||
// Check icon
|
||||
when (played) {
|
||||
true -> {
|
||||
binding.checkButton.imageTintList = ColorStateList.valueOf(
|
||||
resources.getColor(
|
||||
R.color.red,
|
||||
requireActivity().theme
|
||||
)
|
||||
)
|
||||
}
|
||||
false -> {
|
||||
val typedValue = TypedValue()
|
||||
requireActivity().theme.resolveAttribute(R.attr.colorOnSecondaryContainer, typedValue, true)
|
||||
/*binding.checkButton.imageTintList = ColorStateList.valueOf(
|
||||
resources.getColor(
|
||||
typedValue.resourceId,
|
||||
requireActivity().theme
|
||||
)
|
||||
)*/
|
||||
}
|
||||
}
|
||||
|
||||
// Favorite icon
|
||||
val favoriteDrawable = when (favorite) {
|
||||
true -> R.drawable.ic_heart_filled
|
||||
false -> R.drawable.ic_heart
|
||||
}
|
||||
binding.favoriteButton.setImageResource(favoriteDrawable)
|
||||
if (favorite) binding.favoriteButton.imageTintList = ColorStateList.valueOf(
|
||||
resources.getColor(
|
||||
R.color.red,
|
||||
requireActivity().theme
|
||||
)
|
||||
)
|
||||
|
||||
binding.title.text = item.name
|
||||
binding.genres.text = genresString
|
||||
binding.year.text = dateString
|
||||
binding.playtime.text = runTime
|
||||
binding.officialRating.text = item.officialRating
|
||||
binding.communityRating.text = item.communityRating.toString()
|
||||
binding.description.text = item.overview
|
||||
bindBaseItemImage(binding.poster, item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindPlayerItems(items: PlayerItems) {
|
||||
navigateToPlayerActivity(items.items.toTypedArray())
|
||||
binding.playButton.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
requireActivity(),
|
||||
R.drawable.ic_play
|
||||
)
|
||||
)
|
||||
binding.progressCircular.visibility = View.INVISIBLE
|
||||
}
|
||||
|
||||
private fun bindPlayerItemsError(error: PlayerItemError) {
|
||||
Timber.e(error.error.message)
|
||||
|
||||
binding.errorLayout.errorPanel.isVisible = true
|
||||
binding.playButton.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
requireActivity(),
|
||||
R.drawable.ic_play
|
||||
)
|
||||
)
|
||||
binding.progressCircular.visibility = View.INVISIBLE
|
||||
}
|
||||
|
||||
private fun navigateToPlayerActivity(
|
||||
playerItems: Array<PlayerItem>,
|
||||
) {
|
||||
findNavController().navigate(
|
||||
MediaDetailFragmentDirections.actionMediaDetailFragmentToPlayerActivity(
|
||||
playerItems
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package dev.jdtech.jellyfin.tv.ui
|
||||
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.leanback.widget.Presenter
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.databinding.BaseItemBinding
|
||||
import dev.jdtech.jellyfin.databinding.CollectionItemBinding
|
||||
import dev.jdtech.jellyfin.databinding.HomeEpisodeItemBinding
|
||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
|
||||
class LibaryItemPresenter(private val onClick: (BaseItemDto) -> Unit) : Presenter() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
|
||||
return ViewHolder(
|
||||
CollectionItemBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
).root
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: ViewHolder, item: Any) {
|
||||
if (item is BaseItemDto) {
|
||||
DataBindingUtil.getBinding<CollectionItemBinding>(viewHolder.view)?.apply {
|
||||
this.collection = item
|
||||
viewHolder.view.setOnClickListener { onClick(item) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUnbindViewHolder(viewHolder: ViewHolder) = Unit
|
||||
}
|
||||
|
||||
class MediaItemPresenter(private val onClick: (BaseItemDto) -> Unit) : Presenter() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
|
||||
return ViewHolder(
|
||||
BaseItemBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
).root
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: ViewHolder, item: Any) {
|
||||
if (item is BaseItemDto) {
|
||||
DataBindingUtil.getBinding<BaseItemBinding>(viewHolder.view)?.apply {
|
||||
this.item = item
|
||||
this.itemName.text =
|
||||
if (item.type == BaseItemKind.EPISODE) item.seriesName else item.name
|
||||
this.itemCount.visibility =
|
||||
if (item.userData?.unplayedItemCount != null && item.userData?.unplayedItemCount!! > 0) View.VISIBLE else View.GONE
|
||||
this.itemLayout.layoutParams.width =
|
||||
this.itemLayout.resources.getDimension(R.dimen.overview_media_width).toInt()
|
||||
(this.itemLayout.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = 0
|
||||
viewHolder.view.setOnClickListener { onClick(item) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUnbindViewHolder(viewHolder: ViewHolder) = Unit
|
||||
}
|
||||
|
||||
class DynamicMediaItemPresenter(private val onClick: (BaseItemDto) -> Unit) : Presenter() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
|
||||
return ViewHolder(
|
||||
HomeEpisodeItemBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
).root
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: ViewHolder, item: Any) {
|
||||
if (item is BaseItemDto) {
|
||||
DataBindingUtil.getBinding<HomeEpisodeItemBinding>(viewHolder.view)?.apply {
|
||||
episode = item
|
||||
item.userData?.playedPercentage?.toInt()?.let {
|
||||
progressBar.layoutParams.width = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
(it.times(2.24)).toFloat(), progressBar.context.resources.displayMetrics
|
||||
).toInt()
|
||||
progressBar.isVisible = true
|
||||
}
|
||||
|
||||
if (item.type == BaseItemKind.MOVIE) {
|
||||
primaryName.text = item.name
|
||||
secondaryName.visibility = View.GONE
|
||||
} else if (item.type == BaseItemKind.EPISODE) {
|
||||
primaryName.text = item.seriesName
|
||||
}
|
||||
|
||||
viewHolder.view.setOnClickListener { onClick(item) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUnbindViewHolder(viewHolder: ViewHolder) = Unit
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package dev.jdtech.jellyfin.tv.ui
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import dev.jdtech.jellyfin.R
|
||||
import dev.jdtech.jellyfin.mpv.MPVPlayer
|
||||
import dev.jdtech.jellyfin.mpv.TrackType
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
||||
|
||||
class TrackSelectorAdapter(
|
||||
private val items: List<Track>,
|
||||
private val viewModel: PlayerActivityViewModel,
|
||||
private val trackType: TrackType,
|
||||
private val dismissWindow: () -> Unit
|
||||
) : RecyclerView.Adapter<TrackSelectorAdapter.TrackSelectorViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TrackSelectorViewHolder {
|
||||
return TrackSelectorViewHolder(
|
||||
LayoutInflater.from(parent.context).inflate(R.layout.track_item, parent, false)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: TrackSelectorViewHolder, position: Int) {
|
||||
holder.bind(items[position], viewModel, trackType, dismissWindow)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
class TrackSelectorViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
fun bind(
|
||||
item: Track,
|
||||
viewModel: PlayerActivityViewModel,
|
||||
trackType: TrackType,
|
||||
dismissWindow: () -> Unit
|
||||
) {
|
||||
view.findViewById<Button>(R.id.track_name).apply {
|
||||
text = String.format(
|
||||
view.resources.getString(R.string.track_selection),
|
||||
item.language,
|
||||
item.title,
|
||||
item.codec
|
||||
)
|
||||
setOnClickListener {
|
||||
viewModel.switchToTrack(trackType, item.playerTrack)
|
||||
dismissWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Track(
|
||||
val title: String,
|
||||
val language: String,
|
||||
val codec: String,
|
||||
val selected: Boolean,
|
||||
val playerTrack: MPVPlayer.Companion.Track
|
||||
)
|
||||
}
|
|
@ -4,5 +4,4 @@ import androidx.lifecycle.ViewModel
|
|||
|
||||
class MainViewModel : ViewModel() {
|
||||
var startDestinationChanged = false
|
||||
var startDestinationTvChanged = false
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="true" android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/neutral_700"/>
|
||||
<stroke android:width="2dp" android:color="@color/white" />
|
||||
<corners android:radius="10dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/neutral_700"/>
|
||||
<corners android:radius="10dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="true" android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?attr/colorPrimary"/>
|
||||
<stroke android:width="2dp" android:color="@color/white" />
|
||||
<corners android:radius="10dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?attr/colorPrimary"/>
|
||||
<corners android:radius="10dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?attr/colorPrimary" />
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:bottom="18dp"
|
||||
android:drawable="@drawable/ic_user"
|
||||
android:end="18dp"
|
||||
android:gravity="center"
|
||||
android:start="18dp"
|
||||
android:top="18dp" />
|
||||
</layer-list>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment_activity_main"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:navGraph="@navigation/app_navigation" />
|
||||
|
||||
</FrameLayout>
|
|
@ -1,80 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<import type="android.view.View" />
|
||||
|
||||
<variable
|
||||
name="item"
|
||||
type="org.jellyfin.sdk.model.api.BaseItemDto" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/item_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:background="@drawable/focus_border"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/item_image"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:itemImage="@{item}"
|
||||
app:layout_constraintDimensionRatio="H,2:3"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Findroid.Image"
|
||||
app:strokeColor="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_image"
|
||||
tools:text="Movie title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_count"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/circle_background"
|
||||
android:gravity="center"
|
||||
android:text="@{item.userData.unplayedItemCount.toString()}"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="9" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/played_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/circle_background"
|
||||
android:contentDescription="@string/episode_watched_indicator"
|
||||
android:padding="4dp"
|
||||
android:src="@drawable/ic_check"
|
||||
android:visibility="@{item.userData.played == true ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="@id/item_image"
|
||||
app:layout_constraintTop_toTopOf="@id/item_image" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,34 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="16dp"
|
||||
tools:ignore="MissingDefaultResource">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:background="@drawable/focus_border"
|
||||
android:contentDescription="@string/title_settings"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:src="@drawable/ic_settings"
|
||||
app:layout_constraintEnd_toStartOf="@+id/clock"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="12:00" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,49 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="collection"
|
||||
type="org.jellyfin.sdk.model.api.BaseItemDto" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="240dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:background="@drawable/focus_border"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/collection_image"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop"
|
||||
app:baseItemImage="@{collection}"
|
||||
app:layout_constraintDimensionRatio="H,16:9"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Findroid.Image"
|
||||
app:strokeColor="@null" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@{collection.name}"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/collection_image"
|
||||
tools:text="Movies" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,60 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="server"
|
||||
type="dev.jdtech.jellyfin.models.DiscoveredServer" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:background="@drawable/focus_border"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/server_icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/button_setup_background"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="no"
|
||||
app:srcCompat="@drawable/ic_server"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/server_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@{server.name}"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/server_icon"
|
||||
tools:text="username" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,136 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/player_controls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/player_background"
|
||||
tools:ignore="MissingDefaultResource"
|
||||
>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/back_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/transparent_circle_background"
|
||||
android:contentDescription="@string/player_controls_exit"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:src="@drawable/ic_arrow_left"
|
||||
android:focusable="true"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/video_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textColor="@color/white"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/back_button"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="The Dawn of Despair"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btn_audio_track"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/transparent_circle_background"
|
||||
android:contentDescription="@string/select_audio_track"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:src="@drawable/ic_speaker"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/exo_progress"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btn_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/tv_controls_margin_start"
|
||||
android:background="@drawable/transparent_circle_background"
|
||||
android:contentDescription="@string/select_subtile_track"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:src="@drawable/ic_closed_caption"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/exo_progress"
|
||||
app:layout_constraintStart_toEndOf="@id/btn_audio_track"
|
||||
/>
|
||||
|
||||
<androidx.media3.ui.DefaultTimeBar
|
||||
android:id="@+id/exo_progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@id/exo_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:focusable="true"
|
||||
app:played_color="?colorPrimary"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/exo_rew"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/transparent_circle_background"
|
||||
android:contentDescription="@string/player_controls_rewind"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:src="@drawable/ic_rewind"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/exo_play_pause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/tv_controls_margin_start"
|
||||
android:background="@drawable/transparent_circle_background"
|
||||
android:contentDescription="@string/play_button_description"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:src="@drawable/ic_pause"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/exo_rew"
|
||||
android:focusedByDefault="true"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/exo_ffwd"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/tv_controls_margin_start"
|
||||
android:background="@drawable/transparent_circle_background"
|
||||
android:contentDescription="@string/player_controls_fast_forward"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:src="@drawable/ic_fast_forward"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/exo_play_pause"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/exo_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/tv_controls_margin_start"
|
||||
android:background="@drawable/transparent_circle_background"
|
||||
android:contentDescription="@string/player_controls_skip"
|
||||
android:padding="@dimen/tv_controls_padding"
|
||||
android:src="@drawable/ic_skip_forward"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/exo_ffwd"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,96 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
tools:context=".fragments.AddServerFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_banner"
|
||||
android:layout_width="268dp"
|
||||
android:layout_height="75dp"
|
||||
android:layout_marginTop="64dp"
|
||||
android:contentDescription="@string/jellyfin_banner"
|
||||
android:src="@drawable/ic_banner"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="@dimen/setup_container_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/image_banner"
|
||||
app:layout_constraintVertical_bias="0.36">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_add_server"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/add_server"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
android:textColor="?android:textColorPrimary" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/servers_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:visibility="gone"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="2"
|
||||
tools:listitem="@layout/discovered_server_item"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_text_server_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:autofillHints=""
|
||||
android:focusedByDefault="true"
|
||||
android:hint="@string/edit_text_server_address_hint"
|
||||
android:imeOptions="actionGo"
|
||||
android:inputType="textUri" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_connect"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/button_connect" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_circular"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:elevation="8dp"
|
||||
android:indeterminateTint="@color/white"
|
||||
android:padding="8dp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
|
@ -1,54 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.LibraryFragment">
|
||||
|
||||
<include
|
||||
android:id="@+id/error_layout"
|
||||
layout="@layout/error_panel" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Movies" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/items_recycler_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingTop="16dp"
|
||||
android:scrollbars="none"
|
||||
android:layout_marginTop="12dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:spanCount="@integer/library_columns"
|
||||
tools:itemCount="14"
|
||||
tools:listitem="@layout/base_item">
|
||||
<requestFocus/>
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/loading_indicator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
tools:context=".fragments.LoginFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_banner"
|
||||
android:layout_width="268dp"
|
||||
android:layout_height="75dp"
|
||||
android:layout_marginTop="64dp"
|
||||
android:contentDescription="@string/jellyfin_banner"
|
||||
android:src="@drawable/ic_banner"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="@dimen/setup_container_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/image_banner"
|
||||
app:layout_constraintVertical_bias="0.36">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_login"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/login"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
|
||||
android:textColor="?android:textColorPrimary" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/users_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:visibility="gone"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="2"
|
||||
tools:listitem="@layout/user_item"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_text_username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:autofillHints="username"
|
||||
android:hint="@string/edit_text_username_hint"
|
||||
android:inputType="text" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_text_password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:autofillHints="password"
|
||||
android:hint="@string/edit_text_password_hint"
|
||||
android:imeOptions="actionGo"
|
||||
android:inputType="textPassword"
|
||||
app:passwordToggleEnabled="true" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_login"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/button_login" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_circular"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:elevation="8dp"
|
||||
android:indeterminateTint="@color/white"
|
||||
android:padding="8dp"
|
||||
android:visibility="invisible" />
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/addresses_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="4"
|
||||
tools:listitem="@layout/server_address_list_item" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_add_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/add_address"
|
||||
app:icon="@drawable/ic_plus" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="dev.jdtech.jellyfin.viewmodels.ServerSelectViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/servers_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:orientation="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:servers="@{viewModel.servers}"
|
||||
app:spanCount="10"
|
||||
tools:itemCount="4"
|
||||
tools:listitem="@layout/server_item" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_add_server"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/add_server" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</layout>
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/users_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:itemCount="4"
|
||||
tools:listitem="@layout/user_list_item" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_add_user"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/add_user"
|
||||
app:icon="@drawable/ic_plus" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="episode"
|
||||
type="org.jellyfin.sdk.model.api.BaseItemDto" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="240dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:background="@drawable/focus_border"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/episode_image"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:baseItemImage="@{episode}"
|
||||
app:layout_constraintDimensionRatio="H,16:9"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Findroid.Image"
|
||||
app:strokeColor="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/primary_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/episode_image"
|
||||
tools:text="Wonder Egg Priority" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/secondary_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@{String.format(@string/episode_name_extended, episode.parentIndexNumber, episode.indexNumber, episode.name)}"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/primary_name"
|
||||
tools:text="The Girl Flautist" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/progress_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="4dp"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/button_setup_background"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/episode_image"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:layout_width="50dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="MissingDefaultResource"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/header_icon"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/header_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,258 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:ignore="MissingDefaultResource">
|
||||
|
||||
<include
|
||||
android:id="@+id/error_layout"
|
||||
layout="@layout/error_panel"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/horizontal_margin"
|
||||
android:layout_marginTop="12dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Alita: Battle Angel" />
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="12:00" />
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/poster"
|
||||
android:layout_width="320dp"
|
||||
android:layout_height="180dp"
|
||||
android:layout_marginStart="@dimen/horizontal_margin"
|
||||
android:layout_marginTop="12dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Findroid.Image"
|
||||
app:strokeColor="@null" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/main_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/horizontal_margin"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintStart_toEndOf="@id/poster"
|
||||
app:layout_constraintTop_toTopOf="@id/poster">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/year"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
tools:text="2019" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playtime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
tools:text="122 min" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/official_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
tools:text="PG-13" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/community_rating"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="bottom"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
app:drawableStartCompat="@drawable/ic_star"
|
||||
app:drawableTint="@color/yellow"
|
||||
tools:text="7.3" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genres"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="Action, Science Fiction, Adventure" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="400dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="5"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
tools:text="An angel falls. A warrior rises. When Alita awakens with no memory of who she is in a future world she does not recognize, she is taken in by Ido, a compassionate doctor who realizes that somewhere in this abandoned cyborg shell is the heart and soul of a young woman with an extraordinary past." />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/play_button"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/button_setup_background"
|
||||
android:contentDescription="@string/play_button_description"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:focusedByDefault="true"
|
||||
android:nextFocusLeft="@id/play_button"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingVertical="12dp"
|
||||
android:src="@drawable/ic_play">
|
||||
|
||||
<requestFocus />
|
||||
</ImageButton>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_circular"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:elevation="8dp"
|
||||
android:indeterminateTint="@color/white"
|
||||
android:padding="8dp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/trailer_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/button_accent_background"
|
||||
android:contentDescription="@string/trailer_button_description"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_film" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/check_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/button_accent_background"
|
||||
android:contentDescription="@string/check_button_description"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_check" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/favorite_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/button_accent_background"
|
||||
android:contentDescription="@string/favorite_button_description"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_heart" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/seasons_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/main_info">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/season_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/horizontal_margin"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="@string/seasons"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleMedium" />
|
||||
|
||||
<androidx.leanback.widget.ListRowView
|
||||
android:id="@+id/seasons_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/cast_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/seasons_layout">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cast_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/horizontal_margin"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/cast_amp_crew"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleMedium" />
|
||||
|
||||
<androidx.leanback.widget.ListRowView
|
||||
android:id="@+id/cast_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</FrameLayout>
|
|
@ -1,54 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="person"
|
||||
type="org.jellyfin.sdk.model.api.BaseItemPerson" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/item_layout"
|
||||
android:layout_width="110dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:background="@drawable/focus_border"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/person_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:personImage="@{person}"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Findroid.Image"
|
||||
app:strokeColor="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/person_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@{person.name}"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
tools:text="Rosa Salazar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/person_role"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@{person.role}"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
|
||||
tools:text="Alita" />
|
||||
</LinearLayout>
|
||||
</layout>
|
|
@ -1,58 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="server"
|
||||
type="dev.jdtech.jellyfin.models.Server" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="@drawable/ripple_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="24dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/server_icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/button_setup_background"
|
||||
app:layout_constraintBottom_toTopOf="@id/server_name"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="no"
|
||||
app:srcCompat="@drawable/ic_server" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/server_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{server.name}"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/server_icon"
|
||||
tools:text="JDTech" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/track_selection_item_height"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:ignore="MissingDefaultResource"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
>
|
||||
|
||||
<Button
|
||||
android:id="@+id/track_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:textSize="@dimen/track_selection_item_text_size"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
tools:text="subtitle track"
|
||||
/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.leanback.widget.BrowseFrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/selector_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:orientation="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:ignore="MissingDefaultResource"
|
||||
>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/track_selector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:orientation="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:ignore="MissingDefaultResource"
|
||||
/>
|
||||
|
||||
</androidx.leanback.widget.BrowseFrameLayout>
|
|
@ -1,53 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="user"
|
||||
type="dev.jdtech.jellyfin.models.User" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:background="@drawable/focus_border"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/user_image"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:duplicateParentState="true"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Findroid.Image"
|
||||
app:userImage="@{user}" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/user_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@{user.name}"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/user_image"
|
||||
tools:text="username" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/nav_host_fragment_activity_main"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:navGraph="@navigation/app_navigation" />
|
||||
|
||||
</FrameLayout>
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".PlayerActivity">
|
||||
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/player_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
app:animation_enabled="false"
|
||||
app:show_buffering="always" />
|
||||
|
||||
</FrameLayout>
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_banner_background"/>
|
||||
<foreground android:drawable="@drawable/ic_banner_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -39,42 +39,11 @@
|
|||
app:destination="@id/addServerFragment"
|
||||
app:popUpTo="@id/homeFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
<action
|
||||
android:id="@+id/action_homeFragment_to_mediaDetailFragment"
|
||||
app:destination="@id/mediaDetailFragment" />
|
||||
<action
|
||||
android:id="@+id/action_homeFragment_to_searchResultFragment"
|
||||
app:destination="@id/searchResultFragment" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/homeFragmentTv"
|
||||
android:name="dev.jdtech.jellyfin.tv.ui.HomeFragment"
|
||||
android:label="@string/title_home" >
|
||||
|
||||
<action
|
||||
android:id="@+id/action_homeFragment_to_mediaDetailFragment"
|
||||
app:destination="@id/mediaDetailFragment" />
|
||||
<action
|
||||
android:id="@+id/action_homeFragment_to_settingsFragment"
|
||||
app:destination="@id/twoPaneSettingsFragment"
|
||||
app:enterAnim="@anim/nav_default_enter_anim"
|
||||
app:exitAnim="@anim/nav_default_exit_anim"
|
||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_homeFragment_to_addServerFragment"
|
||||
app:destination="@id/addServerFragment"
|
||||
app:popUpTo="@id/homeFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_homeFragment_to_libraryFragment"
|
||||
app:destination="@id/libraryFragment" />
|
||||
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/mediaFragment"
|
||||
android:name="dev.jdtech.jellyfin.fragments.MediaFragment"
|
||||
|
@ -133,9 +102,6 @@
|
|||
app:exitAnim="@anim/nav_default_exit_anim"
|
||||
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
|
||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||
<action
|
||||
android:id="@+id/action_libraryFragment_to_mediaDetailFragment"
|
||||
app:destination="@id/mediaDetailFragment" />
|
||||
<argument
|
||||
android:name="libraryType"
|
||||
android:defaultValue="unknown"
|
||||
|
@ -181,29 +147,7 @@
|
|||
app:argType="boolean"
|
||||
android:defaultValue="false" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/mediaDetailFragment"
|
||||
android:name="dev.jdtech.jellyfin.tv.ui.MediaDetailFragment"
|
||||
android:label="{itemName}"
|
||||
tools:layout="@layout/media_detail_fragment">
|
||||
|
||||
<argument
|
||||
android:name="itemId"
|
||||
app:argType="java.util.UUID" />
|
||||
<argument
|
||||
android:name="itemName"
|
||||
android:defaultValue="Media Info"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="itemType"
|
||||
app:argType="org.jellyfin.sdk.model.api.BaseItemKind"
|
||||
android:defaultValue="MOVIE" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_mediaDetailFragment_to_playerActivity"
|
||||
app:destination="@id/playerActivityTv" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/seasonFragment"
|
||||
android:name="dev.jdtech.jellyfin.fragments.SeasonFragment"
|
||||
|
@ -334,11 +278,6 @@
|
|||
app:destination="@id/homeFragment"
|
||||
app:popUpTo="@id/homeFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
<action
|
||||
android:id="@+id/action_serverSelectFragment_to_homeFragmentTv"
|
||||
app:destination="@id/homeFragmentTv"
|
||||
app:popUpTo="@id/homeFragmentTv"
|
||||
app:popUpToInclusive="true" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/loginFragment"
|
||||
|
@ -350,11 +289,6 @@
|
|||
app:destination="@id/homeFragment"
|
||||
app:popUpTo="@id/homeFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
<action
|
||||
android:id="@+id/action_loginFragment_to_homeFragmentTv"
|
||||
app:destination="@id/homeFragmentTv"
|
||||
app:popUpTo="@id/homeFragmentTv"
|
||||
app:popUpToInclusive="true" />
|
||||
<argument
|
||||
android:name="reLogin"
|
||||
app:argType="boolean"
|
||||
|
@ -386,16 +320,6 @@
|
|||
app:argType="dev.jdtech.jellyfin.models.PlayerItem[]" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:id="@+id/playerActivityTv"
|
||||
android:name="dev.jdtech.jellyfin.tv.TvPlayerActivity"
|
||||
android:label="activity_player_tv"
|
||||
tools:layout="@layout/activity_player_tv">
|
||||
<argument
|
||||
android:name="items"
|
||||
app:argType="dev.jdtech.jellyfin.models.PlayerItem[]" />
|
||||
</activity>
|
||||
|
||||
<include app:graph="@navigation/aboutlibs_navigation" />
|
||||
<action
|
||||
android:id="@+id/action_global_loginFragment"
|
||||
|
@ -414,11 +338,6 @@
|
|||
app:destination="@id/homeFragment"
|
||||
app:popUpTo="@id/homeFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
<action
|
||||
android:id="@+id/action_usersFragment_to_homeFragmentTv"
|
||||
app:destination="@id/homeFragmentTv"
|
||||
app:popUpTo="@id/homeFragmentTv"
|
||||
app:popUpToInclusive="true" />
|
||||
<argument
|
||||
android:name="serverId"
|
||||
app:argType="string" />
|
||||
|
@ -434,11 +353,6 @@
|
|||
app:destination="@id/homeFragment"
|
||||
app:popUpTo="@id/homeFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
<action
|
||||
android:id="@+id/action_usersFragment_to_homeFragmentTv"
|
||||
app:destination="@id/homeFragmentTv"
|
||||
app:popUpTo="@id/homeFragmentTv"
|
||||
app:popUpToInclusive="true" />
|
||||
<argument
|
||||
android:name="serverId"
|
||||
app:argType="string" />
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="MissingDefaultResource">
|
||||
|
||||
<dimen name="horizontal_margin">48dp</dimen>
|
||||
<dimen name="vertical_margin">48dp</dimen>
|
||||
|
||||
<dimen name="tv_controls_padding">8dp</dimen>
|
||||
<dimen name="tv_controls_margin_start">32dp</dimen>
|
||||
|
||||
<dimen name="track_selection_item_height">48dp</dimen>
|
||||
<dimen name="track_selection_item_text_size">16sp</dimen>
|
||||
|
||||
<item name="library_columns" type="integer">6</item>
|
||||
|
||||
</resources>
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="roundedCardView">
|
||||
<item name="cornerFamily">rounded</item>
|
||||
<item name="cornerSize">40dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -1,17 +0,0 @@
|
|||
<resources>
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Findroid" parent="Theme.AppCompat.Leanback">
|
||||
<item name="colorPrimary">@color/blue_600</item>
|
||||
<item name="colorPrimaryVariant">@color/blue_800</item>
|
||||
<item name="colorSecondary">@color/green_500</item>
|
||||
<item name="colorSecondaryVariant">@color/green_800</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">@color/neutral_900</item>
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="android:windowBackground">@color/neutral_900</item>
|
||||
<item name="android:colorBackgroundFloating">@color/neutral_900</item>
|
||||
|
||||
<item name="defaultBrandColor">@color/neutral_900</item>
|
||||
<item name="browseTitleViewLayout">@layout/browse_support_fragment_title_view</item>
|
||||
</style>
|
||||
</resources>
|
Loading…
Reference in a new issue