11package com.getcode
22
3- import androidx.compose.animation.AnimatedContent
4- import androidx.compose.animation.AnimatedVisibility
53import androidx.compose.animation.fadeIn
64import androidx.compose.animation.fadeOut
75import androidx.compose.animation.togetherWith
8- import androidx.compose.foundation.Image
96import androidx.compose.foundation.background
10- import androidx.compose.foundation.layout.Arrangement
117import androidx.compose.foundation.layout.Box
12- import androidx.compose.foundation.layout.Column
138import androidx.compose.foundation.layout.PaddingValues
14- import androidx.compose.foundation.layout.fillMaxHeight
159import androidx.compose.foundation.layout.fillMaxSize
16- import androidx.compose.foundation.layout.fillMaxWidth
1710import androidx.compose.foundation.layout.padding
1811import androidx.compose.material.ExperimentalMaterialApi
1912import androidx.compose.runtime.Composable
2013import androidx.compose.runtime.CompositionLocalProvider
2114import androidx.compose.runtime.LaunchedEffect
15+ import androidx.compose.runtime.collectAsState
2216import androidx.compose.runtime.getValue
2317import androidx.compose.runtime.mutableStateOf
2418import androidx.compose.runtime.remember
2519import androidx.compose.runtime.setValue
26- import androidx.compose.ui.Alignment
2720import androidx.compose.ui.Modifier
2821import androidx.compose.ui.platform.LocalContext
29- import androidx.compose.ui.res.painterResource
3022import androidx.compose.ui.unit.dp
23+ import androidx.lifecycle.Lifecycle
3124import cafe.adriel.voyager.core.screen.Screen
3225import cafe.adriel.voyager.core.screen.ScreenKey
3326import cafe.adriel.voyager.core.screen.uniqueScreenKey
@@ -46,102 +39,115 @@ import com.getcode.theme.CodeTheme
4639import com.getcode.theme.LocalCodeColors
4740import com.getcode.ui.components.AuthCheck
4841import com.getcode.ui.components.BottomBarContainer
49- import com.getcode.ui.components.CodeCircularProgressIndicator
5042import com.getcode.ui.components.CodeScaffold
43+ import com.getcode.ui.components.OnLifecycleEvent
5144import com.getcode.ui.components.TitleBar
5245import com.getcode.ui.components.TopBarContainer
5346import com.getcode.ui.utils.getActivity
5447import com.getcode.ui.utils.getActivityScopedViewModel
5548import com.getcode.ui.utils.measured
49+ import com.getcode.view.main.home.components.BiometricsBlockingView
50+ import com.getcode.view.main.home.components.rememberBiometricsState
5651import dev.bmcreations.tipkit.TipScaffold
5752import dev.bmcreations.tipkit.engines.TipsEngine
58- import kotlinx.coroutines.delay
5953
6054@Composable
6155fun CodeApp (tipsEngine : TipsEngine ) {
6256 val tlvm = MainRoot .getActivityScopedViewModel<TopLevelViewModel >()
57+ val state by tlvm.state.collectAsState()
6358 val activity = LocalContext .current.getActivity()
59+ val biometricsState = rememberBiometricsState(
60+ requireBiometrics = state.requireBiometrics,
61+ onBiometricsNotEnrolled = { tlvm.onMissingBiometrics() }
62+ )
63+
64+ OnLifecycleEvent { _, event ->
65+ if (event == Lifecycle .Event .ON_RESUME ) {
66+ tlvm.onResume()
67+ }
68+ }
6469
6570 CodeTheme {
6671 val appState = rememberCodeAppState()
67- AppNavHost {
68- val codeNavigator = LocalCodeNavigator .current
69-
70- TipScaffold (tipsEngine = tipsEngine) {
71- CodeScaffold (
72- scaffoldState = appState.scaffoldState
73- ) { innerPaddingModifier ->
74- Navigator (
75- screen = MainRoot ,
76- ) { navigator ->
77- appState.navigator = codeNavigator
78-
79- LaunchedEffect (navigator.lastItem) {
80- // update global navigator for platform access to support push/pop from a single
81- // navigator current
82- codeNavigator.screensNavigator = navigator
83- }
72+ CompositionLocalProvider ( LocalBiometricsState provides biometricsState) {
73+ AppNavHost {
74+ val codeNavigator = LocalCodeNavigator .current
75+ TipScaffold (tipsEngine = tipsEngine) {
76+ CodeScaffold (
77+ scaffoldState = appState.scaffoldState
78+ ) { innerPaddingModifier ->
79+ Navigator (
80+ screen = MainRoot ,
81+ ) { navigator ->
82+ appState.navigator = codeNavigator
83+
84+ LaunchedEffect (navigator.lastItem) {
85+ // update global navigator for platform access to support push/pop from a single
86+ // navigator current
87+ codeNavigator.screensNavigator = navigator
88+ }
8489
85- var topBarHeight by remember {
86- mutableStateOf(0 .dp)
87- }
90+ var topBarHeight by remember {
91+ mutableStateOf(0 .dp)
92+ }
8893
89- val (isVisibleTopBar, isVisibleBackButton) = appState.isVisibleTopBar
90- if (isVisibleTopBar && appState.currentTitle.isNotBlank()) {
91- TitleBar (
92- modifier = Modifier .measured { topBarHeight = it.height },
93- title = appState.currentTitle,
94- backButton = isVisibleBackButton,
95- onBackIconClicked = appState::upPress
96- )
97- } else {
98- topBarHeight = 0 .dp
99- }
94+ val (isVisibleTopBar, isVisibleBackButton) = appState.isVisibleTopBar
95+ if (isVisibleTopBar && appState.currentTitle.isNotBlank()) {
96+ TitleBar (
97+ modifier = Modifier .measured { topBarHeight = it.height },
98+ title = appState.currentTitle,
99+ backButton = isVisibleBackButton,
100+ onBackIconClicked = appState::upPress
101+ )
102+ } else {
103+ topBarHeight = 0 .dp
104+ }
100105
101- CompositionLocalProvider (
102- LocalTopBarPadding provides PaddingValues (top = topBarHeight),
103- ) {
104- Box (
105- modifier = Modifier
106- .padding(innerPaddingModifier)
106+ CompositionLocalProvider (
107+ LocalTopBarPadding provides PaddingValues (top = topBarHeight),
107108 ) {
108- when (navigator.lastEvent) {
109- StackEvent .Push ,
110- StackEvent .Pop -> {
111- when (navigator.lastItem) {
112- is LoginScreen , is MainRoot -> CrossfadeTransition (
113- navigator = navigator
114- )
115-
116- else -> SlideTransition (navigator = navigator)
109+ Box (
110+ modifier = Modifier
111+ .padding(innerPaddingModifier)
112+ ) {
113+ when (navigator.lastEvent) {
114+ StackEvent .Push ,
115+ StackEvent .Pop -> {
116+ when (navigator.lastItem) {
117+ is LoginScreen , is MainRoot -> CrossfadeTransition (
118+ navigator = navigator
119+ )
120+
121+ else -> SlideTransition (navigator = navigator)
122+ }
117123 }
118- }
119124
120- StackEvent .Idle ,
121- StackEvent .Replace -> CurrentScreen ()
125+ StackEvent .Idle ,
126+ StackEvent .Replace -> CurrentScreen ()
127+ }
122128 }
123129 }
124- }
125130
126- // Listen for authentication changes here
127- AuthCheck (
128- navigator = codeNavigator,
129- onNavigate = { screens ->
130- codeNavigator.replaceAll(screens, inSheet = false )
131- },
132- onSwitchAccounts = { seed ->
133- activity?.let {
134- tlvm.logout(it) {
135- appState.navigator.replaceAll(LoginScreen (seed))
131+ // Listen for authentication changes here
132+ AuthCheck (
133+ navigator = codeNavigator,
134+ onNavigate = { screens ->
135+ codeNavigator.replaceAll(screens, inSheet = false )
136+ },
137+ onSwitchAccounts = { seed ->
138+ activity?.let {
139+ tlvm.logout(it) {
140+ appState.navigator.replaceAll(LoginScreen (seed))
141+ }
136142 }
137143 }
138- }
139- )
144+ )
145+ }
140146 }
141147 }
142148 }
143149 }
144-
150+ BiometricsBlockingView (modifier = Modifier .fillMaxSize(), biometricsState)
145151 TopBarContainer (appState)
146152 BottomBarContainer (appState)
147153 }
0 commit comments