refactor MainActivity to use hiltViewModel and relocate AppScaffold to its own file
This commit is contained in:
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@@ -1,4 +1,3 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="EntryPointsManager">
|
<component name="EntryPointsManager">
|
||||||
<list size="1">
|
<list size="1">
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.activity.compose.LocalActivity
|
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
@@ -45,6 +44,7 @@ import androidx.compose.ui.text.font.FontFamily
|
|||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||||
@@ -58,6 +58,7 @@ import eu.gaudian.translator.ui.theme.AllFonts
|
|||||||
import eu.gaudian.translator.ui.theme.AllThemes
|
import eu.gaudian.translator.ui.theme.AllThemes
|
||||||
import eu.gaudian.translator.ui.theme.buildColorScheme
|
import eu.gaudian.translator.ui.theme.buildColorScheme
|
||||||
import eu.gaudian.translator.utils.Log
|
import eu.gaudian.translator.utils.Log
|
||||||
|
import eu.gaudian.translator.utils.findActivity
|
||||||
import eu.gaudian.translator.view.composable.AppAlertDialog
|
import eu.gaudian.translator.view.composable.AppAlertDialog
|
||||||
import eu.gaudian.translator.view.composable.BottomNavigationBar
|
import eu.gaudian.translator.view.composable.BottomNavigationBar
|
||||||
import eu.gaudian.translator.view.composable.Screen
|
import eu.gaudian.translator.view.composable.Screen
|
||||||
@@ -76,7 +77,7 @@ val LocalConnectionConfigured = compositionLocalOf { true }
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
private val statusViewModel: StatusViewModel by viewModels()
|
|
||||||
private val settingsViewModel: SettingsViewModel by viewModels()
|
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||||
private var isReady = false
|
private var isReady = false
|
||||||
private var isUiLoaded = false
|
private var isUiLoaded = false
|
||||||
@@ -100,10 +101,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
// Show UI immediately and load data in background
|
// Show UI immediately and load data in background
|
||||||
setContent {
|
setContent {
|
||||||
AppTheme(settingsViewModel = settingsViewModel) {
|
AppTheme(settingsViewModel = settingsViewModel) {
|
||||||
TranslatorApp(
|
TranslatorApp(settingsViewModel = settingsViewModel)
|
||||||
statusViewModel = statusViewModel,
|
|
||||||
settingsViewModel = settingsViewModel
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,9 +144,15 @@ class MainActivity : ComponentActivity() {
|
|||||||
@SuppressLint("LocalContextResourcesRead")
|
@SuppressLint("LocalContextResourcesRead")
|
||||||
@Composable
|
@Composable
|
||||||
fun TranslatorApp(
|
fun TranslatorApp(
|
||||||
statusViewModel: StatusViewModel,
|
|
||||||
settingsViewModel: SettingsViewModel
|
settingsViewModel: SettingsViewModel
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
val activity = LocalContext.current.findActivity()
|
||||||
|
val statusViewModel: StatusViewModel = hiltViewModel(activity)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val statusState by statusViewModel.status.collectAsStateWithLifecycle()
|
val statusState by statusViewModel.status.collectAsStateWithLifecycle()
|
||||||
val keyboardInsets = WindowInsets.ime
|
val keyboardInsets = WindowInsets.ime
|
||||||
@@ -171,7 +175,6 @@ fun TranslatorApp(
|
|||||||
showExitDialog = true
|
showExitDialog = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val activity = LocalActivity.current
|
|
||||||
|
|
||||||
if (showExitDialog) {
|
if (showExitDialog) {
|
||||||
AppAlertDialog(
|
AppAlertDialog(
|
||||||
@@ -182,7 +185,7 @@ fun TranslatorApp(
|
|||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
showExitDialog = false
|
showExitDialog = false
|
||||||
// Minimize the app similar to default back at root behavior
|
// Minimize the app similar to default back at root behavior
|
||||||
activity?.moveTaskToBack(true)
|
activity.moveTaskToBack(true)
|
||||||
}) {
|
}) {
|
||||||
Text(stringResource(R.string.quit))
|
Text(stringResource(R.string.quit))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package eu.gaudian.translator.view.composable
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.AccountCircle
|
||||||
|
import androidx.compose.material.icons.filled.Search
|
||||||
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
|
import androidx.compose.material3.FabPosition
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.ScaffoldDefaults
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import eu.gaudian.translator.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AppScaffold(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
topBar: @Composable () -> Unit = {},
|
||||||
|
snackbarHost: @Composable () -> Unit = {},
|
||||||
|
floatingActionButton: @Composable () -> Unit = {},
|
||||||
|
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
||||||
|
containerColor: Color = MaterialTheme.colorScheme.background,
|
||||||
|
contentColor: Color = contentColorFor(containerColor),
|
||||||
|
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
|
||||||
|
content: @Composable (PaddingValues) -> Unit
|
||||||
|
) {
|
||||||
|
// A Scaffold variant that enforces no bottom bar while keeping proper content padding handling.
|
||||||
|
Scaffold(
|
||||||
|
modifier = modifier,
|
||||||
|
topBar = topBar,
|
||||||
|
snackbarHost = snackbarHost,
|
||||||
|
containerColor = containerColor,
|
||||||
|
contentColor = contentColor,
|
||||||
|
bottomBar = {},
|
||||||
|
floatingActionButton = floatingActionButton,
|
||||||
|
floatingActionButtonPosition = floatingActionButtonPosition
|
||||||
|
) { innerPadding ->
|
||||||
|
// Ensure bottom padding is always 0.dp
|
||||||
|
val customPadding = PaddingValues(
|
||||||
|
top = innerPadding.calculateTopPadding(),
|
||||||
|
bottom = 0.dp, // Force bottom padding to 0.dp
|
||||||
|
start = innerPadding.calculateLeftPadding(androidx.compose.ui.unit.LayoutDirection.Ltr),
|
||||||
|
end = innerPadding.calculateRightPadding(androidx.compose.ui.unit.LayoutDirection.Ltr)
|
||||||
|
)
|
||||||
|
content(customPadding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ParrotTopBar() {
|
||||||
|
val navyBlue = Color(0xFF1A237E) // The color from your mockup
|
||||||
|
|
||||||
|
CenterAlignedTopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
text = "ParrotPal",
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
color = Color.White
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
// Your new parrot logo icon
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_level_parrot),
|
||||||
|
contentDescription = "Logo",
|
||||||
|
modifier = Modifier.size(32.dp),
|
||||||
|
tint = Color.Unspecified // Keeps the logo's original colors
|
||||||
|
)
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
IconButton(onClick = { /* Search */ }) {
|
||||||
|
Icon(Icons.Default.Search, contentDescription = "Search", tint = Color.White)
|
||||||
|
}
|
||||||
|
IconButton(onClick = { /* Profile */ }) {
|
||||||
|
Icon(Icons.Default.AccountCircle, contentDescription = "Profile", tint = Color.White)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
||||||
|
containerColor = navyBlue
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.PaddingValues
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -28,19 +27,15 @@ import androidx.compose.material3.ButtonElevation
|
|||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.CheckboxDefaults
|
import androidx.compose.material3.CheckboxDefaults
|
||||||
import androidx.compose.material3.FabPosition
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedCard
|
import androidx.compose.material3.OutlinedCard
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.ScaffoldDefaults
|
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.SwitchDefaults
|
import androidx.compose.material3.SwitchDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.contentColorFor
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -755,37 +750,3 @@ fun WrongOutlinedButton(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun AppScaffold(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
topBar: @Composable () -> Unit = {},
|
|
||||||
snackbarHost: @Composable () -> Unit = {},
|
|
||||||
floatingActionButton: @Composable () -> Unit = {},
|
|
||||||
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
|
||||||
containerColor: Color = MaterialTheme.colorScheme.background,
|
|
||||||
contentColor: Color = contentColorFor(containerColor),
|
|
||||||
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
|
|
||||||
content: @Composable (PaddingValues) -> Unit
|
|
||||||
) {
|
|
||||||
// A Scaffold variant that enforces no bottom bar while keeping proper content padding handling.
|
|
||||||
Scaffold(
|
|
||||||
modifier = modifier,
|
|
||||||
topBar = topBar,
|
|
||||||
snackbarHost = snackbarHost,
|
|
||||||
containerColor = containerColor,
|
|
||||||
contentColor = contentColor,
|
|
||||||
bottomBar = {},
|
|
||||||
floatingActionButton = floatingActionButton,
|
|
||||||
floatingActionButtonPosition = floatingActionButtonPosition
|
|
||||||
) { innerPadding ->
|
|
||||||
// Ensure bottom padding is always 0.dp
|
|
||||||
val customPadding = PaddingValues(
|
|
||||||
top = innerPadding.calculateTopPadding(),
|
|
||||||
bottom = 0.dp, // Force bottom padding to 0.dp
|
|
||||||
start = innerPadding.calculateLeftPadding(androidx.compose.ui.unit.LayoutDirection.Ltr),
|
|
||||||
end = innerPadding.calculateRightPadding(androidx.compose.ui.unit.LayoutDirection.Ltr)
|
|
||||||
)
|
|
||||||
content(customPadding)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user