Refactor MainActivity to use compose as basis
This commit is contained in:
committed by
Niels van Velzen
parent
72ff0cfae8
commit
b9f8757123
@@ -6,7 +6,7 @@ import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Lifecycle
|
||||
@@ -20,11 +20,11 @@ import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.androidtv.auth.repository.SessionRepository
|
||||
import org.jellyfin.androidtv.auth.repository.UserRepository
|
||||
import org.jellyfin.androidtv.databinding.ActivityMainBinding
|
||||
import org.jellyfin.androidtv.integration.LeanbackChannelWorker
|
||||
import org.jellyfin.androidtv.ui.InteractionTrackerViewModel
|
||||
import org.jellyfin.androidtv.ui.background.AppBackground
|
||||
import org.jellyfin.androidtv.ui.navigation.NavigationAction
|
||||
import org.jellyfin.androidtv.ui.base.JellyfinTheme
|
||||
import org.jellyfin.androidtv.ui.composable.compat.AppNavigationHost
|
||||
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
|
||||
import org.jellyfin.androidtv.ui.screensaver.InAppScreensaver
|
||||
import org.jellyfin.androidtv.ui.settings.compat.MainActivitySettings
|
||||
@@ -42,14 +42,6 @@ class MainActivity : FragmentActivity() {
|
||||
private val interactionTrackerViewModel by viewModel<InteractionTrackerViewModel>()
|
||||
private val workManager by inject<WorkManager>()
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
private val backPressedCallback = object : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (navigationRepository.canGoBack) navigationRepository.goBack()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
applyTheme()
|
||||
|
||||
@@ -63,22 +55,24 @@ class MainActivity : FragmentActivity() {
|
||||
else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
onBackPressedDispatcher.addCallback(this, backPressedCallback)
|
||||
if (savedInstanceState == null && navigationRepository.canGoBack) navigationRepository.reset(clearHistory = true)
|
||||
|
||||
navigationRepository.currentAction
|
||||
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
|
||||
.onEach { action ->
|
||||
handleNavigationAction(action)
|
||||
backPressedCallback.isEnabled = navigationRepository.canGoBack
|
||||
.onEach {
|
||||
interactionTrackerViewModel.notifyInteraction(canCancel = false, userInitiated = false)
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
binding.background.setContent { AppBackground() }
|
||||
binding.settings.setContent { MainActivitySettings() }
|
||||
binding.screensaver.setContent { InAppScreensaver() }
|
||||
setContentView(binding.root)
|
||||
setContent {
|
||||
JellyfinTheme {
|
||||
AppBackground()
|
||||
AppNavigationHost(
|
||||
navigationRepository = navigationRepository,
|
||||
)
|
||||
InAppScreensaver()
|
||||
MainActivitySettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -119,17 +113,6 @@ class MainActivity : FragmentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleNavigationAction(action: NavigationAction) {
|
||||
interactionTrackerViewModel.notifyInteraction(canCancel = true, userInitiated = false)
|
||||
|
||||
when (action) {
|
||||
is NavigationAction.NavigateFragment -> binding.contentView.navigate(action)
|
||||
NavigationAction.GoBack -> binding.contentView.goBack()
|
||||
|
||||
NavigationAction.Nothing -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
// Forward key events to fragments
|
||||
private fun Fragment.onKeyEvent(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
var result = childFragmentManager.fragments.any { it.onKeyEvent(keyCode, event) }
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.jellyfin.androidtv.ui.composable.compat
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.jellyfin.androidtv.ui.browsing.DestinationFragmentView
|
||||
import org.jellyfin.androidtv.ui.navigation.NavigationAction
|
||||
import org.jellyfin.androidtv.ui.navigation.NavigationRepository
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
@Composable
|
||||
fun AppNavigationHost(
|
||||
modifier: Modifier = Modifier,
|
||||
navigationRepository: NavigationRepository = koinInject(),
|
||||
) {
|
||||
val factory = remember { AppNavigationHostViewFactory() }
|
||||
|
||||
val currentAction by navigationRepository.currentAction.collectAsState(NavigationAction.Nothing)
|
||||
val canGoBack by remember {
|
||||
navigationRepository.currentAction.map { navigationRepository.canGoBack }.distinctUntilChanged()
|
||||
}.collectAsState(navigationRepository.canGoBack)
|
||||
|
||||
BackHandler(canGoBack) { navigationRepository.goBack() }
|
||||
|
||||
AndroidView(
|
||||
factory = factory,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
LaunchedEffect(currentAction) {
|
||||
when (val currentAction = currentAction) {
|
||||
is NavigationAction.NavigateFragment -> factory.view.navigate(currentAction)
|
||||
NavigationAction.GoBack -> factory.view.goBack()
|
||||
|
||||
NavigationAction.Nothing -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AppNavigationHostViewFactory : (Context) -> View {
|
||||
private var _view: DestinationFragmentView? = null
|
||||
|
||||
val view get() = requireNotNull(_view)
|
||||
|
||||
override operator fun invoke(
|
||||
context: Context
|
||||
): View = DestinationFragmentView(context).also { view ->
|
||||
_view = view
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout 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:fitsSystemWindows="true"
|
||||
tools:context=".ui.startup.MainActivity">
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:focusable="false" />
|
||||
|
||||
<org.jellyfin.androidtv.ui.browsing.DestinationFragmentView
|
||||
android:id="@+id/content_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/screensaver"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</RelativeLayout>
|
||||
Reference in New Issue
Block a user