From 7b85df6e69f26c6c0bab95daeafb2b8e186d26e4 Mon Sep 17 00:00:00 2001 From: Jarne Demeulemeester <32322857+jarnedemeulemeester@users.noreply.github.com> Date: Sun, 21 Aug 2022 16:45:57 +0200 Subject: [PATCH] Display discovered servers on AddServerFragment (#143) --- app/src/main/AndroidManifest.xml | 1 + .../adapters/DiscoveredServerListAdapter.kt | 58 ++++++++++++++++++ .../jellyfin/fragments/AddServerFragment.kt | 27 +++++++++ .../jellyfin/models/DiscoveredServer.kt | 7 +++ .../jellyfin/viewmodels/AddServerViewModel.kt | 25 ++++++++ .../discovered_server_item.xml | 60 +++++++++++++++++++ .../layout-television/fragment_add_server.xml | 21 ++++++- .../res/layout/discovered_server_item.xml | 59 ++++++++++++++++++ .../main/res/layout/fragment_add_server.xml | 21 ++++++- app/src/main/res/layout/user_item.xml | 1 + 10 files changed, 274 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/dev/jdtech/jellyfin/adapters/DiscoveredServerListAdapter.kt create mode 100644 app/src/main/java/dev/jdtech/jellyfin/models/DiscoveredServer.kt create mode 100644 app/src/main/res/layout-television/discovered_server_item.xml create mode 100644 app/src/main/res/layout/discovered_server_item.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0c463e68..9bbe2e50 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ package="dev.jdtech.jellyfin"> + diff --git a/app/src/main/java/dev/jdtech/jellyfin/adapters/DiscoveredServerListAdapter.kt b/app/src/main/java/dev/jdtech/jellyfin/adapters/DiscoveredServerListAdapter.kt new file mode 100644 index 00000000..f057edcb --- /dev/null +++ b/app/src/main/java/dev/jdtech/jellyfin/adapters/DiscoveredServerListAdapter.kt @@ -0,0 +1,58 @@ +package dev.jdtech.jellyfin.adapters + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import dev.jdtech.jellyfin.databinding.DiscoveredServerItemBinding +import dev.jdtech.jellyfin.models.DiscoveredServer + +class DiscoveredServerListAdapter( + private val clickListener: (server: DiscoveredServer) -> Unit) : + ListAdapter( + DiffCallback + ) { + class DiscoveredServerViewHolder(private var binding: DiscoveredServerItemBinding) : + RecyclerView.ViewHolder(binding.root) { + fun bind(server: DiscoveredServer) { + binding.server = server + binding.executePendingBindings() + } + } + + companion object DiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: DiscoveredServer, + newItem: DiscoveredServer + ): Boolean { + return oldItem.id == newItem.id + } + + override fun areContentsTheSame( + oldItem: DiscoveredServer, + newItem: DiscoveredServer + ): Boolean { + return oldItem == newItem + } + } + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): DiscoveredServerViewHolder { + return DiscoveredServerViewHolder( + DiscoveredServerItemBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: DiscoveredServerViewHolder, position: Int) { + val server = getItem(position) + holder.itemView.setOnClickListener { clickListener(server) } + holder.bind(server) + } +} \ No newline at end of file diff --git a/app/src/main/java/dev/jdtech/jellyfin/fragments/AddServerFragment.kt b/app/src/main/java/dev/jdtech/jellyfin/fragments/AddServerFragment.kt index 5adf1656..200bedab 100644 --- a/app/src/main/java/dev/jdtech/jellyfin/fragments/AddServerFragment.kt +++ b/app/src/main/java/dev/jdtech/jellyfin/fragments/AddServerFragment.kt @@ -17,6 +17,7 @@ import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.navigation.fragment.findNavController import dagger.hilt.android.AndroidEntryPoint +import dev.jdtech.jellyfin.adapters.DiscoveredServerListAdapter import dev.jdtech.jellyfin.databinding.FragmentAddServerBinding import dev.jdtech.jellyfin.viewmodels.AddServerViewModel import kotlinx.coroutines.launch @@ -51,6 +52,11 @@ class AddServerFragment : Fragment() { connectToServer() } + binding.serversRecyclerView.adapter = DiscoveredServerListAdapter { server -> + (binding.editTextServerAddress as AppCompatEditText).setText(server.address) + connectToServer() + } + viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.uiState.collect { uiState -> @@ -64,6 +70,17 @@ class AddServerFragment : Fragment() { } } + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.discoveredServersState.collect { serversState -> + when (serversState) { + is AddServerViewModel.DiscoveredServersState.Loading -> Unit + is AddServerViewModel.DiscoveredServersState.Servers -> bindDiscoveredServersStateServers(serversState) + } + } + } + } + viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.navigateToLogin.collect { @@ -102,6 +119,16 @@ class AddServerFragment : Fragment() { } } + private fun bindDiscoveredServersStateServers(serversState: AddServerViewModel.DiscoveredServersState.Servers) { + val servers = serversState.servers + if (servers.isEmpty()) { + binding.serversRecyclerView.isVisible = false + } else { + binding.serversRecyclerView.isVisible = true + (binding.serversRecyclerView.adapter as DiscoveredServerListAdapter).submitList(servers) + } + } + private fun connectToServer() { val serverAddress = (binding.editTextServerAddress as AppCompatEditText).text.toString() viewModel.checkServer(serverAddress.removeSuffix("/")) diff --git a/app/src/main/java/dev/jdtech/jellyfin/models/DiscoveredServer.kt b/app/src/main/java/dev/jdtech/jellyfin/models/DiscoveredServer.kt new file mode 100644 index 00000000..acc548c3 --- /dev/null +++ b/app/src/main/java/dev/jdtech/jellyfin/models/DiscoveredServer.kt @@ -0,0 +1,7 @@ +package dev.jdtech.jellyfin.models + +data class DiscoveredServer( + val id: String, + val name: String, + val address: String +) \ No newline at end of file diff --git a/app/src/main/java/dev/jdtech/jellyfin/viewmodels/AddServerViewModel.kt b/app/src/main/java/dev/jdtech/jellyfin/viewmodels/AddServerViewModel.kt index 0008ba7d..2e25a85b 100644 --- a/app/src/main/java/dev/jdtech/jellyfin/viewmodels/AddServerViewModel.kt +++ b/app/src/main/java/dev/jdtech/jellyfin/viewmodels/AddServerViewModel.kt @@ -10,6 +10,7 @@ import dev.jdtech.jellyfin.R import dev.jdtech.jellyfin.api.JellyfinApi import dev.jdtech.jellyfin.database.Server import dev.jdtech.jellyfin.database.ServerDatabaseDao +import dev.jdtech.jellyfin.models.DiscoveredServer import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.jellyfin.sdk.discovery.RecommendedServerInfo @@ -32,7 +33,10 @@ constructor( val uiState = _uiState.asStateFlow() private val _navigateToLogin = MutableSharedFlow() val navigateToLogin = _navigateToLogin.asSharedFlow() + private val _discoveredServersState = MutableStateFlow(DiscoveredServersState.Loading) + val discoveredServersState = _discoveredServersState.asStateFlow() + private val discoveredServers = mutableListOf() private var serverFound = false sealed class UiState { @@ -41,6 +45,27 @@ constructor( data class Error(val message: String) : UiState() } + sealed class DiscoveredServersState { + object Loading : DiscoveredServersState() + data class Servers(val servers: List) : DiscoveredServersState() + } + + init { + viewModelScope.launch(Dispatchers.IO) { + val servers = jellyfinApi.jellyfin.discovery.discoverLocalServers() + servers.collect { serverDiscoveryInfo -> + discoveredServers.add(DiscoveredServer( + serverDiscoveryInfo.id, + serverDiscoveryInfo.name, + serverDiscoveryInfo.address + )) + _discoveredServersState.emit( + DiscoveredServersState.Servers(discoveredServers) + ) + } + } + } + /** * Run multiple check on the server before continuing: * diff --git a/app/src/main/res/layout-television/discovered_server_item.xml b/app/src/main/res/layout-television/discovered_server_item.xml new file mode 100644 index 00000000..b0432b86 --- /dev/null +++ b/app/src/main/res/layout-television/discovered_server_item.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-television/fragment_add_server.xml b/app/src/main/res/layout-television/fragment_add_server.xml index 81cb1302..b9184b12 100644 --- a/app/src/main/res/layout-television/fragment_add_server.xml +++ b/app/src/main/res/layout-television/fragment_add_server.xml @@ -26,8 +26,6 @@ android:id="@+id/linearLayout" android:layout_width="@dimen/setup_container_width" android:layout_height="wrap_content" - android:layout_marginStart="24dp" - android:layout_marginEnd="24dp" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" @@ -39,15 +37,31 @@ 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" /> + + + android:layout_height="wrap_content" + android:layout_marginHorizontal="24dp">