Skip to content

Commit

Permalink
Move Home() and TiviContent() to :ui:root
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbanes committed Jun 29, 2023
1 parent 87b39c1 commit cf60cbb
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 104 deletions.
21 changes: 3 additions & 18 deletions android-app/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -148,37 +148,22 @@ androidComponents {

dependencies {
implementation(projects.shared)

implementation(projects.ui.account)
implementation(projects.ui.settings)

implementation(libs.circuit.overlay)

implementation(libs.androidx.lifecycle.viewmodel.ktx)

implementation(libs.androidx.activity.activity)
implementation(libs.androidx.activity.compose)

implementation(libs.androidx.emoji)

implementation(compose.foundation)
implementation(compose.material)
implementation(compose.materialIconsExtended)
implementation(compose.material3)
implementation(libs.compose.material3.windowsizeclass)
implementation(compose.animation)
implementation(compose.uiTooling)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.profileinstaller)

implementation(libs.kotlin.coroutines.android)

implementation(libs.androidx.profileinstaller)
implementation(libs.google.firebase.crashlytics)

implementation(libs.okhttp.loggingInterceptor)

ksp(libs.kotlininject.compiler)

implementation(libs.google.firebase.crashlytics)

qaImplementation(libs.chucker.library)

qaImplementation(libs.debugdrawer.debugdrawer)
Expand Down
92 changes: 15 additions & 77 deletions android-app/app/src/main/kotlin/app/tivi/home/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.viewModels
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.core.view.WindowCompat
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.findViewTreeViewModelStoreOwner
Expand All @@ -27,35 +26,20 @@ import app.tivi.ContentViewSetter
import app.tivi.TiviActivity
import app.tivi.common.compose.LocalTiviDateFormatter
import app.tivi.common.compose.LocalTiviTextCreator
import app.tivi.common.compose.LocalWindowSizeClass
import app.tivi.common.compose.shouldUseDarkColors
import app.tivi.common.compose.shouldUseDynamicColors
import app.tivi.common.compose.theme.TiviTheme
import app.tivi.core.analytics.Analytics
import app.tivi.data.traktauth.LoginToTraktInteractor
import app.tivi.data.traktauth.TraktAuthActivityComponent
import app.tivi.inject.ActivityComponent
import app.tivi.inject.ActivityScope
import app.tivi.inject.AndroidApplicationComponent
import app.tivi.overlays.LocalNavigator
import app.tivi.screens.DiscoverScreen
import app.tivi.screens.SettingsScreen
import app.tivi.screens.TiviScreen
import app.tivi.settings.SettingsActivity
import app.tivi.settings.TiviPreferences
import app.tivi.util.TiviDateFormatter
import app.tivi.util.TiviTextCreator
import com.seiko.imageloader.ImageLoader
import com.seiko.imageloader.LocalImageLoader
import com.slack.circuit.backstack.SaveableBackStack
import com.slack.circuit.backstack.rememberSaveableBackStack
import com.slack.circuit.foundation.CircuitCompositionLocals
import com.slack.circuit.foundation.CircuitConfig
import com.slack.circuit.foundation.push
import com.slack.circuit.foundation.rememberCircuitNavigator
import com.slack.circuit.foundation.screen
import com.slack.circuit.runtime.Navigator
import com.slack.circuit.runtime.Screen
import me.tatarka.inject.annotations.Component
import me.tatarka.inject.annotations.Provides

Expand All @@ -69,6 +53,7 @@ class MainActivity : TiviActivity() {
}
}

@OptIn(ExperimentalComposeUiApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
component = MainActivityComponent::class.create(this)
Expand All @@ -89,9 +74,19 @@ class MainActivity : TiviActivity() {
TiviContent(
analytics = component.analytics,
preferences = component.preferences,
onRootPop = {
if (onBackPressedDispatcher.hasEnabledCallbacks()) {
onBackPressedDispatcher.onBackPressed()
}
},
onOpenSettings = {
context.startActivity(Intent(context, SettingsActivity::class.java))
},
modifier = Modifier.semantics {
// Enables testTag -> UiAutomator resource id
// See https://developer.android.com/jetpack/compose/testing#uiautomator-interop
testTagsAsResourceId = true
},
)
}
}
Expand All @@ -108,63 +103,6 @@ class MainActivity : TiviActivity() {
}
}

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
private fun TiviContent(
onOpenSettings: () -> Unit,
analytics: Analytics,
preferences: TiviPreferences,
) {
val backstack: SaveableBackStack = rememberSaveableBackStack { push(DiscoverScreen) }
val circuitNavigator = rememberCircuitNavigator(backstack)

val navigator: Navigator = remember(circuitNavigator) {
TiviNavigator(circuitNavigator, onOpenSettings)
}

// Launch an effect to track changes to the current back stack entry, and push them
// as a screen views to analytics
LaunchedEffect(backstack.topRecord) {
val topScreen = backstack.topRecord?.screen as? TiviScreen
analytics.trackScreenView(
name = topScreen?.name ?: "unknown screen",
arguments = topScreen?.arguments,
)
}

CompositionLocalProvider(
LocalNavigator provides navigator,
LocalWindowSizeClass provides calculateWindowSizeClass(),
) {
TiviTheme(
useDarkColors = preferences.shouldUseDarkColors(),
useDynamicColors = preferences.shouldUseDynamicColors(),
) {
Home(backstack = backstack, navigator = navigator)
}
}
}

private class TiviNavigator(
private val navigator: Navigator,
private val onOpenSettings: () -> Unit,
) : Navigator {
override fun goTo(screen: Screen) {
when (screen) {
is SettingsScreen -> onOpenSettings()
else -> navigator.goTo(screen)
}
}

override fun pop(): Screen? {
return navigator.pop()
}

override fun resetRoot(newRoot: Screen): List<Screen> {
return navigator.resetRoot(newRoot)
}
}

@ActivityScope
@Component
abstract class MainActivityComponent(
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ include(
":ui:library",
":ui:account",
":ui:upnext",
":ui:root",
":android-app:app",
":android-app:benchmark",
":android-app:common-test",
Expand Down
1 change: 1 addition & 0 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ kotlin {
api(projects.ui.search)
api(projects.ui.show.details)
api(projects.ui.show.seasons)
api(projects.ui.root)
// api(projects.ui.settings)
api(projects.ui.upnext)
}
Expand Down
35 changes: 35 additions & 0 deletions ui/root/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2023, Google LLC, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0


plugins {
id("app.tivi.android.library")
id("app.tivi.kotlin.multiplatform")
alias(libs.plugins.composeMultiplatform)
}

android {
namespace = "app.tivi.home"
}

kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(projects.core.base)
implementation(projects.core.analytics)
implementation(projects.common.ui.compose)

implementation(projects.common.ui.screens)
implementation(libs.circuit.foundation)
implementation(libs.circuit.overlay)
implementation(projects.common.ui.circuitOverlay)

implementation(compose.foundation)
implementation(compose.material)
implementation(compose.materialIconsExtended)
implementation(compose.animation)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,8 @@ import androidx.compose.runtime.Immutable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.unit.dp
import app.tivi.common.compose.LocalWindowSizeClass
import app.tivi.common.ui.resources.MR
Expand All @@ -66,11 +63,12 @@ import com.slack.circuit.runtime.Screen
import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.compose.stringResource

@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun Home(
backstack: SaveableBackStack,
navigator: Navigator,
modifier: Modifier = Modifier,
) {
val windowSizeClass = LocalWindowSizeClass.current
val navigationType = remember(windowSizeClass) {
Expand Down Expand Up @@ -99,11 +97,7 @@ internal fun Home(
},
contentWindowInsets = ScaffoldDefaults.contentWindowInsets
.exclude(WindowInsets.statusBars), // We let content handle the status bar
modifier = Modifier.semantics {
// Enables testTag -> UiAutomator resource id
// See https://developer.android.com/jetpack/compose/testing#uiautomator-interop
testTagsAsResourceId = true
},
modifier = modifier,
) { paddingValues ->
Row(
modifier = Modifier
Expand Down
92 changes: 92 additions & 0 deletions ui/root/src/commonMain/kotlin/app/tivi/home/TiviContent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.home

import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import app.tivi.common.compose.LocalWindowSizeClass
import app.tivi.common.compose.shouldUseDarkColors
import app.tivi.common.compose.shouldUseDynamicColors
import app.tivi.common.compose.theme.TiviTheme
import app.tivi.core.analytics.Analytics
import app.tivi.overlays.LocalNavigator
import app.tivi.screens.DiscoverScreen
import app.tivi.screens.SettingsScreen
import app.tivi.screens.TiviScreen
import app.tivi.settings.TiviPreferences
import com.slack.circuit.backstack.SaveableBackStack
import com.slack.circuit.backstack.rememberSaveableBackStack
import com.slack.circuit.foundation.push
import com.slack.circuit.foundation.rememberCircuitNavigator
import com.slack.circuit.foundation.screen
import com.slack.circuit.runtime.Navigator
import com.slack.circuit.runtime.Screen

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
fun TiviContent(
onRootPop: () -> Unit,
onOpenSettings: () -> Unit,
analytics: Analytics,
preferences: TiviPreferences,
modifier: Modifier = Modifier,
) {
val backstack: SaveableBackStack = rememberSaveableBackStack { push(DiscoverScreen) }
val circuitNavigator = rememberCircuitNavigator(backstack, onRootPop)

val navigator: Navigator = remember(circuitNavigator) {
TiviNavigator(circuitNavigator, onOpenSettings)
}

// Launch an effect to track changes to the current back stack entry, and push them
// as a screen views to analytics
LaunchedEffect(backstack.topRecord) {
val topScreen = backstack.topRecord?.screen as? TiviScreen
analytics.trackScreenView(
name = topScreen?.name ?: "unknown screen",
arguments = topScreen?.arguments,
)
}

CompositionLocalProvider(
LocalNavigator provides navigator,
LocalWindowSizeClass provides calculateWindowSizeClass(),
) {
TiviTheme(
useDarkColors = preferences.shouldUseDarkColors(),
useDynamicColors = preferences.shouldUseDynamicColors(),
) {
Home(
backstack = backstack,
navigator = navigator,
modifier = modifier,
)
}
}
}

private class TiviNavigator(
private val navigator: Navigator,
private val onOpenSettings: () -> Unit,
) : Navigator {
override fun goTo(screen: Screen) {
when (screen) {
is SettingsScreen -> onOpenSettings()
else -> navigator.goTo(screen)
}
}

override fun pop(): Screen? {
return navigator.pop()
}

override fun resetRoot(newRoot: Screen): List<Screen> {
return navigator.resetRoot(newRoot)
}
}

0 comments on commit cf60cbb

Please sign in to comment.