refactor MainActivity to use hiltViewModel and relocate AppScaffold to its own file

This commit is contained in:
jonasgaudian
2026-02-13 15:57:15 +01:00
parent 391fe403ad
commit b5a9f5873a
4 changed files with 106 additions and 49 deletions

View File

@@ -6,7 +6,6 @@ import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
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.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
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.buildColorScheme
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.BottomNavigationBar
import eu.gaudian.translator.view.composable.Screen
@@ -76,7 +77,7 @@ val LocalConnectionConfigured = compositionLocalOf { true }
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val statusViewModel: StatusViewModel by viewModels()
private val settingsViewModel: SettingsViewModel by viewModels()
private var isReady = false
private var isUiLoaded = false
@@ -100,10 +101,7 @@ class MainActivity : ComponentActivity() {
// Show UI immediately and load data in background
setContent {
AppTheme(settingsViewModel = settingsViewModel) {
TranslatorApp(
statusViewModel = statusViewModel,
settingsViewModel = settingsViewModel
)
TranslatorApp(settingsViewModel = settingsViewModel)
}
}
@@ -146,9 +144,15 @@ class MainActivity : ComponentActivity() {
@SuppressLint("LocalContextResourcesRead")
@Composable
fun TranslatorApp(
statusViewModel: StatusViewModel,
settingsViewModel: SettingsViewModel
) {
val activity = LocalContext.current.findActivity()
val statusViewModel: StatusViewModel = hiltViewModel(activity)
val navController = rememberNavController()
val statusState by statusViewModel.status.collectAsStateWithLifecycle()
val keyboardInsets = WindowInsets.ime
@@ -171,7 +175,6 @@ fun TranslatorApp(
showExitDialog = true
}
val activity = LocalActivity.current
if (showExitDialog) {
AppAlertDialog(
@@ -182,7 +185,7 @@ fun TranslatorApp(
TextButton(onClick = {
showExitDialog = false
// Minimize the app similar to default back at root behavior
activity?.moveTaskToBack(true)
activity.moveTaskToBack(true)
}) {
Text(stringResource(R.string.quit))
}

View File

@@ -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
)
)
}

View File

@@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -28,19 +27,15 @@ import androidx.compose.material3.ButtonElevation
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.FabPosition
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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)
}
}