Rework complete navigation

This commit is contained in:
jarnedemeulemeester 2021-08-03 19:04:03 +02:00
parent fb64f7e02d
commit 8aa36cdd6e
No known key found for this signature in database
GPG key ID: 60884A0C1EBA43E5
19 changed files with 254 additions and 105 deletions

View file

@ -16,13 +16,9 @@
<activity android:name=".PlayerActivity" />
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:windowSoftInputMode="adjustPan"/>
<activity
android:name=".SetupActivity"
android:exported="true"
android:theme="@style/Theme.JellyfinSplashScreen"
android:windowSoftInputMode="adjustPan">
android:windowSoftInputMode="adjustPan"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View file

@ -1,24 +1,33 @@
package dev.jdtech.jellyfin
import android.os.Bundle
import android.view.View
import androidx.activity.viewModels
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.databinding.ActivityMainBinding
import dev.jdtech.jellyfin.fragments.InitializingFragmentDirections
import dev.jdtech.jellyfin.viewmodels.MainViewModel
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
installSplashScreen()
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navView: BottomNavigationView = binding.navView
@ -34,11 +43,32 @@ class MainActivity : AppCompatActivity() {
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_media, R.id.favoriteFragment
R.id.homeFragment, R.id.mediaFragment, R.id.favoriteFragment
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
binding.navView.visibility = when (destination.id) {
R.id.settingsFragment, R.id.serverSelectFragment, R.id.addServerFragment, R.id.loginFragment -> View.GONE
else -> View.VISIBLE
}
}
viewModel.navigateToAddServer.observe(this, {
if (it) {
navController.navigate(InitializingFragmentDirections.actionInitializingFragmentToAddServerFragment3())
viewModel.doneNavigateToAddServer()
}
})
viewModel.doneLoading.observe(this, {
if (it) {
navController.navigate(InitializingFragmentDirections.actionInitializingFragmentToNavigationHome())
}
})
}
override fun onSupportNavigateUp(): Boolean {

View file

@ -1,15 +0,0 @@
package dev.jdtech.jellyfin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class SetupActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
installSplashScreen()
setContentView(R.layout.activity_setup)
}
}

View file

@ -0,0 +1,22 @@
package dev.jdtech.jellyfin.di
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object SharedPreferencesModule {
@Singleton
@Provides
fun provideSharedPreferences(@ApplicationContext application: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(application)
}
}

View file

@ -51,7 +51,7 @@ class AddServerFragment : Fragment() {
}
private fun navigateToLoginFragment() {
findNavController().navigate(AddServerFragmentDirections.actionAddServerFragmentToLoginFragment())
findNavController().navigate(AddServerFragmentDirections.actionAddServerFragment3ToLoginFragment2())
viewModel.onNavigateToLoginDone()
}
}

View file

@ -0,0 +1,24 @@
package dev.jdtech.jellyfin.fragments
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import dev.jdtech.jellyfin.R
class InitializingFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_initializing, container, false)
}
}

View file

@ -47,7 +47,7 @@ class LoginFragment : Fragment() {
}
private fun navigateToMainActivity() {
findNavController().navigate(LoginFragmentDirections.actionLoginFragmentToMainActivity())
findNavController().navigate(LoginFragmentDirections.actionLoginFragment2ToNavigationHome())
viewModel.doneNavigatingToMain()
}
}

View file

@ -55,11 +55,13 @@ class ServerSelectFragment : Fragment() {
}
private fun navigateToAddServerFragment() {
findNavController().navigate(R.id.action_serverSelectFragment_to_addServerFragment)
findNavController().navigate(
ServerSelectFragmentDirections.actionServerSelectFragment2ToAddServerFragment3()
)
}
private fun navigateToMainActivity() {
findNavController().navigate(R.id.action_serverSelectFragment_to_mainActivity)
findNavController().navigate(ServerSelectFragmentDirections.actionServerSelectFragmentToHomeFragment())
viewModel.doneNavigatingToMain()
}
}

View file

@ -1,11 +1,18 @@
package dev.jdtech.jellyfin.fragments
import android.os.Bundle
import androidx.navigation.fragment.findNavController
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import dev.jdtech.jellyfin.R
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.fragment_settings, rootKey)
findPreference<Preference>("switchServer")?.setOnPreferenceClickListener {
findNavController().navigate(SettingsFragmentDirections.actionNavigationSettingsToServerSelectFragment2())
true
}
}
}

View file

@ -1,5 +1,6 @@
package dev.jdtech.jellyfin.viewmodels
import android.content.SharedPreferences
import androidx.lifecycle.*
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.api.JellyfinApi
@ -17,6 +18,7 @@ import javax.inject.Inject
class LoginViewModel
@Inject
constructor(
private val sharedPreferences: SharedPreferences,
private val jellyfinApi: JellyfinApi,
private val database: ServerDatabaseDao
) : ViewModel() {
@ -54,6 +56,9 @@ constructor(
authenticationResult.accessToken!!
)
insert(server)
val spEdit = sharedPreferences.edit()
spEdit.putString("selectedServer", server.id)
spEdit.apply()
jellyfinApi.apply {
api.accessToken = authenticationResult.accessToken
userId = authenticationResult.user?.id

View file

@ -0,0 +1,65 @@
package dev.jdtech.jellyfin.viewmodels
import android.app.Application
import android.content.SharedPreferences
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.api.JellyfinApi
import dev.jdtech.jellyfin.database.Server
import dev.jdtech.jellyfin.database.ServerDatabaseDao
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.util.*
import javax.inject.Inject
@HiltViewModel
class MainViewModel
@Inject
constructor(
private val sharedPreferences: SharedPreferences,
private val database: ServerDatabaseDao,
private val jellyfinApi: JellyfinApi,
) : ViewModel() {
private val _doneLoading = MutableLiveData<Boolean>()
val doneLoading: LiveData<Boolean> = _doneLoading
private val _navigateToAddServer = MutableLiveData<Boolean>()
val navigateToAddServer: LiveData<Boolean> = _navigateToAddServer
init {
Timber.d("Start Main")
viewModelScope.launch {
val servers: List<Server>
withContext(Dispatchers.IO) {
servers = database.getAllServersSync()
}
if (servers.isEmpty()) {
_navigateToAddServer.value = true
} else {
val serverId = sharedPreferences.getString("selectedServer", null)
val selectedServer = servers.find { server -> server.id == serverId }
Timber.d("Selected server: $selectedServer")
if (selectedServer != null) {
jellyfinApi.apply {
api.baseUrl = selectedServer.address
api.accessToken = selectedServer.accessToken
userId = UUID.fromString(selectedServer.userId)
}
Timber.d("Finish Main")
}
_doneLoading.value = true
}
}
}
fun doneNavigateToAddServer() {
_navigateToAddServer.value = false
}
}

View file

@ -1,5 +1,6 @@
package dev.jdtech.jellyfin.viewmodels
import android.content.SharedPreferences
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@ -18,6 +19,7 @@ import javax.inject.Inject
class ServerSelectViewModel
@Inject
constructor(
private val sharedPreferences: SharedPreferences,
private val jellyfinApi: JellyfinApi,
private val database: ServerDatabaseDao,
) : ViewModel() {
@ -42,6 +44,10 @@ constructor(
}
fun connectToServer(server: Server) {
val spEdit = sharedPreferences.edit()
spEdit.putString("selectedServer", server.id)
spEdit.apply()
jellyfinApi.apply {
api.baseUrl = server.address
api.accessToken = server.accessToken

View file

@ -1,21 +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=".SetupActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/setup_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".fragments.InitializingFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/initializing" />
</FrameLayout>

View file

@ -2,12 +2,12 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:id="@+id/homeFragment"
android:icon="@drawable/ic_home"
android:title="@string/title_home" />
<item
android:id="@+id/navigation_media"
android:id="@+id/mediaFragment"
android:icon="@drawable/ic_library"
android:title="@string/title_media" />

View file

@ -3,10 +3,10 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_navigation"
app:startDestination="@+id/navigation_home">
app:startDestination="@+id/initializingFragment">
<fragment
android:id="@+id/navigation_home"
android:id="@+id/homeFragment"
android:name="dev.jdtech.jellyfin.fragments.HomeFragment"
android:label="@string/title_home"
tools:layout="@layout/fragment_home">
@ -29,7 +29,7 @@
app:destination="@id/episodeBottomSheetFragment" />
<action
android:id="@+id/action_navigation_home_to_navigation_settings"
app:destination="@id/navigation_settings"
app:destination="@id/settingsFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
@ -37,7 +37,7 @@
</fragment>
<fragment
android:id="@+id/navigation_media"
android:id="@+id/mediaFragment"
android:name="dev.jdtech.jellyfin.fragments.MediaFragment"
android:label="@string/title_media"
tools:layout="@layout/fragment_media">
@ -54,9 +54,13 @@
</fragment>
<fragment
android:id="@+id/navigation_settings"
android:id="@+id/settingsFragment"
android:name="dev.jdtech.jellyfin.fragments.SettingsFragment"
android:label="@string/title_settings" />
android:label="@string/title_settings" >
<action
android:id="@+id/action_navigation_settings_to_serverSelectFragment2"
app:destination="@id/serverSelectFragment" />
</fragment>
<fragment
android:id="@+id/libraryFragment"
android:name="dev.jdtech.jellyfin.fragments.LibraryFragment"
@ -183,4 +187,54 @@
android:name="query"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/addServerFragment"
android:name="dev.jdtech.jellyfin.fragments.AddServerFragment"
android:label="AddServerFragment"
tools:layout="@layout/fragment_add_server">
<action
android:id="@+id/action_addServerFragment3_to_loginFragment2"
app:destination="@id/loginFragment" />
</fragment>
<fragment
android:id="@+id/serverSelectFragment"
android:name="dev.jdtech.jellyfin.fragments.ServerSelectFragment"
android:label="ServerSelectFragment"
tools:layout="@layout/fragment_server_select">
<action
android:id="@+id/action_serverSelectFragment2_to_addServerFragment3"
app:destination="@id/addServerFragment" />
<action
android:id="@+id/action_serverSelectFragment_to_homeFragment"
app:destination="@id/homeFragment"
app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/loginFragment"
android:name="dev.jdtech.jellyfin.fragments.LoginFragment"
android:label="LoginFragment"
tools:layout="@layout/fragment_login">
<action
android:id="@+id/action_loginFragment2_to_navigation_home"
app:destination="@id/homeFragment"
app:popUpTo="@id/initializingFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/initializingFragment"
android:name="dev.jdtech.jellyfin.fragments.InitializingFragment"
android:label="fragment_initializing"
tools:layout="@layout/fragment_initializing" >
<action
android:id="@+id/action_initializingFragment_to_navigation_home"
app:destination="@id/homeFragment"
app:popUpTo="@id/initializingFragment"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_initializingFragment_to_addServerFragment3"
app:destination="@id/addServerFragment"
app:popUpTo="@id/initializingFragment"
app:popUpToInclusive="true" />
</fragment>
</navigation>

View file

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/navigation"
app:startDestination="@id/serverSelectFragment">
<fragment
android:id="@+id/addServerFragment"
android:name="dev.jdtech.jellyfin.fragments.AddServerFragment"
android:label="fragment_add_server"
tools:layout="@layout/fragment_add_server">
<action
android:id="@+id/action_addServerFragment_to_loginFragment"
app:destination="@id/loginFragment"
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" />
</fragment>
<fragment
android:id="@+id/loginFragment"
android:name="dev.jdtech.jellyfin.fragments.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login">
<action
android:id="@+id/action_loginFragment_to_mainActivity"
app:destination="@id/mainActivity" />
</fragment>
<fragment
android:id="@+id/serverSelectFragment"
android:name="dev.jdtech.jellyfin.fragments.ServerSelectFragment"
android:label="ServerSelectFragment"
tools:layout="@layout/fragment_server_select">
<action
android:id="@+id/action_serverSelectFragment_to_addServerFragment"
app:destination="@id/addServerFragment"
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_serverSelectFragment_to_mainActivity"
app:destination="@id/mainActivity" />
</fragment>
<activity
android:id="@+id/mainActivity"
android:name="dev.jdtech.jellyfin.MainActivity"
android:label="MainActivity"
tools:layout="@layout/activity_main" />
</navigation>

View file

@ -44,4 +44,7 @@
<string name="settings_category_language">Language</string>
<string name="settings_preferred_audio_language">Preferred audio language</string>
<string name="settings_preferred_subtitle_language">Preferred subtitle language</string>
<string name="initializing">Initializing…</string>
<string name="settings_category_servers">Servers</string>
<string name="switch_server">Switch server</string>
</resources>

View file

@ -21,5 +21,12 @@
</PreferenceCategory>
<PreferenceCategory app:title="@string/settings_category_servers">
<Preference
app:key="switchServer"
app:title="@string/switch_server" />
</PreferenceCategory>
</PreferenceScreen>