Get views in home fragment

This commit is contained in:
Jarne Demeulemeester 2021-06-13 14:42:03 +02:00
parent da5233593f
commit 93518f67ee
No known key found for this signature in database
GPG key ID: B61B7B150DB6A6D2
12 changed files with 220 additions and 33 deletions

View file

@ -14,8 +14,7 @@
android:label="@string/title_activity_main"/> android:label="@string/title_activity_main"/>
<activity <activity
android:name=".SetupActivity" android:name=".SetupActivity"
android:windowSoftInputMode="adjustPan" android:windowSoftInputMode="adjustPan">
android:noHistory="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View file

@ -4,9 +4,17 @@ import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dev.jdtech.jellyfin.database.Server import dev.jdtech.jellyfin.database.Server
import dev.jdtech.jellyfin.adapters.ServerGridAdapter import dev.jdtech.jellyfin.adapters.ServerGridAdapter
import dev.jdtech.jellyfin.adapters.ViewListAdapter
import org.jellyfin.sdk.model.api.BaseItemDto
@BindingAdapter("listData") @BindingAdapter("servers")
fun bindRecyclerView(recyclerView: RecyclerView, data: List<Server>?) { fun bindServers(recyclerView: RecyclerView, data: List<Server>?) {
val adapter = recyclerView.adapter as ServerGridAdapter val adapter = recyclerView.adapter as ServerGridAdapter
adapter.submitList(data) adapter.submitList(data)
} }
@BindingAdapter("views")
fun bindViews(recyclerView: RecyclerView, data: List<BaseItemDto>?) {
val adapter = recyclerView.adapter as ViewListAdapter
adapter.submitList(data)
}

View file

@ -0,0 +1,37 @@
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.ViewItemBinding
import org.jellyfin.sdk.model.api.BaseItemDto
class ViewListAdapter : ListAdapter<BaseItemDto, ViewListAdapter.ViewHolder>(DiffCallback) {
class ViewHolder(private var binding: ViewItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(view: BaseItemDto) {
binding.view = view
binding.executePendingBindings()
}
}
companion object DiffCallback : DiffUtil.ItemCallback<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
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(ViewItemBinding.inflate(LayoutInflater.from(parent.context)))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val view = getItem(position)
holder.bind(view)
}
}

View file

@ -7,7 +7,9 @@ import org.jellyfin.sdk.Jellyfin
import org.jellyfin.sdk.android import org.jellyfin.sdk.android
import org.jellyfin.sdk.api.operations.SystemApi import org.jellyfin.sdk.api.operations.SystemApi
import org.jellyfin.sdk.api.operations.UserApi import org.jellyfin.sdk.api.operations.UserApi
import org.jellyfin.sdk.api.operations.UserViewsApi
import org.jellyfin.sdk.model.ClientInfo import org.jellyfin.sdk.model.ClientInfo
import java.util.*
/** /**
@ -24,8 +26,11 @@ class JellyfinApi(context: Context, baseUrl: String) {
android(context) android(context)
} }
val api = jellyfin.createApi(baseUrl = baseUrl) val api = jellyfin.createApi(baseUrl = baseUrl)
var userId: UUID? = null
val systemApi = SystemApi(api) val systemApi = SystemApi(api)
val userApi = UserApi(api) val userApi = UserApi(api)
val viewsApi = UserViewsApi(api)
init { init {
Log.i("JellyfinApi", "Constructor called!") Log.i("JellyfinApi", "Constructor called!")

View file

@ -1,11 +1,17 @@
package dev.jdtech.jellyfin.fragments package dev.jdtech.jellyfin.fragments
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import dev.jdtech.jellyfin.R import dev.jdtech.jellyfin.R
import dev.jdtech.jellyfin.adapters.ViewListAdapter
import dev.jdtech.jellyfin.databinding.FragmentHomeBinding
import dev.jdtech.jellyfin.viewmodels.HomeViewModel
import dev.jdtech.jellyfin.viewmodels.HomeViewModelFactory
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
@ -13,6 +19,15 @@ class HomeFragment : Fragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
return inflater.inflate(R.layout.fragment_home, container, false) val application = requireNotNull(this.activity).application
val binding = FragmentHomeBinding.inflate(inflater)
val viewModelFactory = HomeViewModelFactory(application)
val viewModel = ViewModelProvider(this, viewModelFactory).get(HomeViewModel::class.java)
binding.lifecycleOwner = this
binding.viewModel = viewModel
binding.viewsRecyclerView.adapter = ViewListAdapter()
return binding.root
} }
} }

View file

@ -29,21 +29,35 @@ class ServerSelectFragment : Fragment() {
val dataSource = ServerDatabase.getInstance(application).serverDatabaseDao val dataSource = ServerDatabase.getInstance(application).serverDatabaseDao
val viewModelFactory = ServerSelectViewModelFactory(dataSource, application) val viewModelFactory = ServerSelectViewModelFactory(dataSource, application)
val viewModel = ViewModelProvider(this, viewModelFactory).get(ServerSelectViewModel::class.java) val viewModel =
ViewModelProvider(this, viewModelFactory).get(ServerSelectViewModel::class.java)
binding.lifecycleOwner = this binding.lifecycleOwner = this
binding.viewModel = viewModel binding.viewModel = viewModel
binding.serversRecyclerView.adapter = ServerGridAdapter(ServerGridAdapter.OnClickListener { server -> binding.serversRecyclerView.adapter =
Toast.makeText(application, "You selected server $server", Toast.LENGTH_SHORT).show() ServerGridAdapter(ServerGridAdapter.OnClickListener { server ->
findNavController().navigate(R.id.action_serverSelectFragment_to_mainActivity) Toast.makeText(application, "You selected server $server", Toast.LENGTH_SHORT)
.show()
viewModel.connectToServer(server)
}, ServerGridAdapter.OnLongClickListener { server -> }, ServerGridAdapter.OnLongClickListener { server ->
DeleteServerDialogFragment(viewModel, server).show(parentFragmentManager, "deleteServer") DeleteServerDialogFragment(viewModel, server).show(
parentFragmentManager,
"deleteServer"
)
true true
}) })
binding.buttonAddServer.setOnClickListener { binding.buttonAddServer.setOnClickListener {
this.findNavController().navigate(R.id.action_serverSelectFragment_to_addServerFragment) this.findNavController().navigate(R.id.action_serverSelectFragment_to_addServerFragment)
} }
viewModel.navigateToMain.observe(viewLifecycleOwner, {
if (it) {
findNavController().navigate(R.id.action_serverSelectFragment_to_mainActivity)
viewModel.doneNavigatingToMain()
}
})
return binding.root return binding.root
} }
} }

View file

@ -0,0 +1,27 @@
package dev.jdtech.jellyfin.viewmodels
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dev.jdtech.jellyfin.api.JellyfinApi
import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.BaseItemDto
class HomeViewModel(
application: Application
) : ViewModel() {
private val jellyfinApi = JellyfinApi.getInstance(application, "")
private val _views = MutableLiveData<List<BaseItemDto>>()
val views: LiveData<List<BaseItemDto>> = _views
init {
viewModelScope.launch {
val result by jellyfinApi.viewsApi.getUserViews(jellyfinApi.userId!!)
_views.value = result.items
}
}
}

View file

@ -0,0 +1,18 @@
package dev.jdtech.jellyfin.viewmodels
import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import java.lang.IllegalArgumentException
class HomeViewModelFactory(
private val application: Application
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(HomeViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return HomeViewModel(application) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}

View file

@ -2,13 +2,16 @@ package dev.jdtech.jellyfin.viewmodels
import android.app.Application import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dev.jdtech.jellyfin.api.JellyfinApi
import dev.jdtech.jellyfin.database.Server import dev.jdtech.jellyfin.database.Server
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.*
class ServerSelectViewModel( class ServerSelectViewModel(
val database: ServerDatabaseDao, val database: ServerDatabaseDao,
@ -17,6 +20,9 @@ class ServerSelectViewModel(
private val _servers = database.getAllServers() private val _servers = database.getAllServers()
val servers: LiveData<List<Server>> = _servers val servers: LiveData<List<Server>> = _servers
private val _navigateToMain = MutableLiveData<Boolean>()
val navigateToMain: LiveData<Boolean> = _navigateToMain
/** /**
* Delete server from database * Delete server from database
* *
@ -29,4 +35,16 @@ class ServerSelectViewModel(
} }
} }
} }
fun connectToServer(server: Server) {
JellyfinApi.getInstance(application, server.address).apply {
api.accessToken = server.accessToken
userId = UUID.fromString(server.userId)
}
_navigateToMain.value = true
}
fun doneNavigatingToMain() {
_navigateToMain.value = false
}
} }

View file

@ -1,23 +1,31 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="dev.jdtech.jellyfin.viewmodels.HomeViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".fragments.HomeFragment"> tools:context=".fragments.HomeFragment">
<TextView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/text_home" android:id="@+id/views_recycler_view"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_marginStart="8dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
android:text="@string/title_home"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent"
app:views="@{viewModel.views}"
tools:itemCount="4"
tools:listitem="@layout/view_item" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -60,7 +60,7 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image_banner" app:layout_constraintTop_toBottomOf="@+id/image_banner"
app:layout_constraintVertical_bias="0.36" app:layout_constraintVertical_bias="0.36"
app:listData="@{viewModel.servers}" app:servers="@{viewModel.servers}"
app:spanCount="3" app:spanCount="3"
tools:itemCount="4" tools:itemCount="4"
tools:listitem="@layout/server_item" /> tools:listitem="@layout/server_item" />

View file

@ -0,0 +1,38 @@
<?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="view"
type="org.jellyfin.sdk.model.api.BaseItemDto" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/view_name"
style="@style/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{view.name}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Movies" />
<TextView
android:id="@+id/view_all"
style="@style/text_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="View all"
app:layout_constraintBaseline_toBaselineOf="@id/view_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>