From a7b3097a03f99f9f5f0d8cf97c8b96218a114e65 Mon Sep 17 00:00:00 2001 From: Omni Devel Date: Wed, 17 Jun 2026 20:23:49 +0300 Subject: [PATCH] refactor: use navigation drawer instead bottom bar --- .../main/java/ru/omni_devel/cards/Elements.kt | 107 ++++++++++++-- .../java/ru/omni_devel/cards/MainActivity.kt | 136 +++--------------- .../ru/omni_devel/cards/NavigationPageData.kt | 9 ++ 3 files changed, 120 insertions(+), 132 deletions(-) create mode 100644 mobile/src/main/java/ru/omni_devel/cards/NavigationPageData.kt diff --git a/mobile/src/main/java/ru/omni_devel/cards/Elements.kt b/mobile/src/main/java/ru/omni_devel/cards/Elements.kt index 2f7515c..31f0afb 100644 --- a/mobile/src/main/java/ru/omni_devel/cards/Elements.kt +++ b/mobile/src/main/java/ru/omni_devel/cards/Elements.kt @@ -1,7 +1,10 @@ package ru.omni_devel.cards import android.content.Intent +import androidx.activity.compose.BackHandler +import androidx.activity.compose.LocalActivity import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -17,17 +20,25 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.DrawerValue import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalDrawerSheet +import androidx.compose.material3.ModalNavigationDrawer +import androidx.compose.material3.NavigationDrawerItem +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalContext @@ -36,37 +47,103 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.graphics.toColorInt +import kotlinx.coroutines.launch @Composable -fun Page(name: String, innerPadding: PaddingValues, content: @Composable () -> Unit) { - Column() { - TopBar(name, innerPadding) +fun Page(name: String, innerPadding: PaddingValues, pages: List? = null, content: @Composable () -> Unit) { + val activityContext = LocalActivity.current - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp) - .background(MaterialTheme.colorScheme.background) - .padding(top = 16.dp) - ) { - content() + val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) + val scope = rememberCoroutineScope() + + BackHandler( + enabled = pages != null && drawerState.isOpen + ) { + scope.launch { + drawerState.close() + } + } + + ModalNavigationDrawer( + drawerState = drawerState, + drawerContent = { + if (pages != null) { + ModalDrawerSheet( + modifier = Modifier.background(MaterialTheme.colorScheme.background).padding(8.dp) + ) { + for (page in pages) { + NavigationDrawerItem( + label = { Text(page.name) }, + selected = false, + onClick = { + scope.launch { drawerState.close() } + + if (page.pageClass != null) { + val intent = Intent(activityContext, page.pageClass) + + activityContext!!.startActivity(intent) + } else if (page.onClick != null) { + page.onClick() + } + } + ) + } + } + } + } + ) { + Scaffold( + topBar = { + TopBar(name, innerPadding, if (pages != null) { + { + Text( + "☰", + fontSize = 24.sp, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.clickable() { + scope.launch { + drawerState.open() + } + } + ) + } + } else null) + } + ) { padding -> + Box( + modifier = Modifier + .padding(padding) + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .padding(horizontal = 16.dp) + .padding(top = 16.dp) + ) { + Column() { + content() + } + } } } } @Composable -fun TopBar(text: String, innerPadding: PaddingValues) { +fun TopBar(text: String, innerPadding: PaddingValues, openMenuButton: (@Composable () -> Unit)? = null) { Row( modifier = Modifier .fillMaxWidth() .background(MaterialTheme.colorScheme.primaryContainer) .padding(top = innerPadding.calculateTopPadding()) - .padding(horizontal = 8.dp) - .padding(bottom = 8.dp) + .padding(vertical = 12.dp, horizontal = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { + if (openMenuButton != null) { + openMenuButton() + } + Text( text, - modifier = Modifier.padding(vertical = 4.dp, horizontal = 12.dp), + modifier = Modifier, fontSize = 24.sp, color = MaterialTheme.colorScheme.onPrimaryContainer ) diff --git a/mobile/src/main/java/ru/omni_devel/cards/MainActivity.kt b/mobile/src/main/java/ru/omni_devel/cards/MainActivity.kt index 7ed6122..71ec9e3 100644 --- a/mobile/src/main/java/ru/omni_devel/cards/MainActivity.kt +++ b/mobile/src/main/java/ru/omni_devel/cards/MainActivity.kt @@ -96,22 +96,31 @@ fun MainPage( ) { val context = LocalContext.current val uriHandler = LocalUriHandler.current - val scope = rememberCoroutineScope() - - var isActionBarShowed by remember { mutableStateOf(false) } Box( modifier = Modifier.fillMaxSize() ) { - BackHandler( - enabled = isActionBarShowed, - ) { - isActionBarShowed = false - } - Page( stringResource(R.string.app_name), - innerPadding + innerPadding, + pages = listOf( + NavigationPageData(stringResource(R.string.do_add_card), EditCardActivity::class.java), + NavigationPageData(stringResource(R.string.do_sync)) { + Toast.makeText(context, context.getString(R.string.sync_in_progress), Toast.LENGTH_SHORT).show() + + sendToWatch(context, "/updateCards", Json.encodeToString(getDbFun().getCards())) { isSuccess -> + if (isSuccess) { + Toast.makeText(context, context.getString(R.string.sync_is_successful), Toast.LENGTH_SHORT).show() + } else { + Toast.makeText(context, context.getString(R.string.sync_is_fail), Toast.LENGTH_LONG).show() + } + } + }, + NavigationPageData(stringResource(R.string.open_backup_menu), BackupActivity::class.java), + NavigationPageData(stringResource(R.string.source_code)) { + uriHandler.openUri("https://github.com/omni-devel/OmniCards") + }, + ) ) { Column( modifier = Modifier.verticalScroll(rememberScrollState()).padding(bottom = 64.dp).background(Color.Transparent), @@ -141,112 +150,5 @@ fun MainPage( } ) { } } - - AnimatedVisibility( - modifier = Modifier - .align(Alignment.BottomEnd) - .padding(innerPadding) - .padding(16.dp), - visible = isActionBarShowed, - enter = slideInVertically(initialOffsetY = { it }) + fadeIn(), - exit = slideOutVertically(targetOffsetY = { it }) + fadeOut() - ) { - Column( - modifier = Modifier - .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null - ) {} - .background( - MaterialTheme.colorScheme.inversePrimary, - RoundedCornerShape(24.dp) - ) - .padding(16.dp) - .fillMaxWidth() - ) { - FullWidthButton( - onClick = { - isActionBarShowed = false - - scope.launch { - delay(ANIMATION_DELAY) - - val intent = Intent(context, EditCardActivity::class.java) - - context.startActivity(intent) - } - } - ) { - Text(stringResource(R.string.do_add_card)) - } - FullWidthButton( - onClick = { - Toast.makeText(context, context.getString(R.string.sync_in_progress), Toast.LENGTH_SHORT).show() - - sendToWatch(context, "/updateCards", Json.encodeToString(getDbFun().getCards())) { isSuccess -> - if (isSuccess) { - Toast.makeText(context, context.getString(R.string.sync_is_successful), Toast.LENGTH_SHORT).show() - } else { - Toast.makeText(context, context.getString(R.string.sync_is_fail), Toast.LENGTH_LONG).show() - } - } - - isActionBarShowed = false - } - ) { - Text(stringResource(R.string.do_sync)) - } - FullWidthButton( - onClick = { - isActionBarShowed = false - - scope.launch { - delay(ANIMATION_DELAY) - - val intent = Intent(context, BackupActivity::class.java) - - context.startActivity(intent) - } - } - ) { - Text(stringResource(R.string.open_backup_menu)) - } - FullWidthButton( - onClick = { - uriHandler.openUri("https://github.com/omni-devel/OmniCards") - - isActionBarShowed = false - } - ) { - Text(stringResource(R.string.source_code)) - } - FullWidthButton( - onClick = { - isActionBarShowed = false - } - ) { - Text(">") - } - } - } - - AnimatedVisibility( - modifier = Modifier - .align(Alignment.BottomEnd) - .padding(innerPadding) - .padding(32.dp), - visible = !isActionBarShowed, - enter = fadeIn() + scaleIn(), - exit = fadeOut() + scaleOut() - ){ - Button( - modifier = Modifier, - onClick = { - isActionBarShowed = true - } - ) { - Text("<") - } - } } } diff --git a/mobile/src/main/java/ru/omni_devel/cards/NavigationPageData.kt b/mobile/src/main/java/ru/omni_devel/cards/NavigationPageData.kt new file mode 100644 index 0000000..d504f93 --- /dev/null +++ b/mobile/src/main/java/ru/omni_devel/cards/NavigationPageData.kt @@ -0,0 +1,9 @@ +package ru.omni_devel.cards + +import android.app.Activity + +data class NavigationPageData( + val name: String, + val pageClass: Class? = null, + val onClick: (() -> Unit)? = null +)