Compare commits

..
2 Commits
Author SHA1 Message Date
omni 24a1e704ca update: updated versions 2026-06-17 20:24:19 +03:00
omni a7b3097a03 refactor: use navigation drawer instead bottom bar 2026-06-17 20:23:49 +03:00
4 changed files with 121 additions and 133 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ android {
minSdk = 30 minSdk = 30
targetSdk = 36 targetSdk = 36
versionCode = generateVersionCode() versionCode = generateVersionCode()
versionName = "2.5.2" versionName = "2.6.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -1,7 +1,10 @@
package ru.omni_devel.cards package ru.omni_devel.cards
import android.content.Intent import android.content.Intent
import androidx.activity.compose.BackHandler
import androidx.activity.compose.LocalActivity
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box 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.foundation.layout.width
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.MaterialTheme 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.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberDrawerState
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
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext 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.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.graphics.toColorInt import androidx.core.graphics.toColorInt
import kotlinx.coroutines.launch
@Composable @Composable
fun Page(name: String, innerPadding: PaddingValues, content: @Composable () -> Unit) { fun Page(name: String, innerPadding: PaddingValues, pages: List<NavigationPageData>? = null, content: @Composable () -> Unit) {
Column() { val activityContext = LocalActivity.current
TopBar(name, innerPadding)
Column( 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 modifier = Modifier
.padding(padding)
.fillMaxSize() .fillMaxSize()
.padding(horizontal = 16.dp)
.background(MaterialTheme.colorScheme.background) .background(MaterialTheme.colorScheme.background)
.padding(horizontal = 16.dp)
.padding(top = 16.dp) .padding(top = 16.dp)
) { ) {
Column() {
content() content()
} }
} }
} }
}
}
@Composable @Composable
fun TopBar(text: String, innerPadding: PaddingValues) { fun TopBar(text: String, innerPadding: PaddingValues, openMenuButton: (@Composable () -> Unit)? = null) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.background(MaterialTheme.colorScheme.primaryContainer) .background(MaterialTheme.colorScheme.primaryContainer)
.padding(top = innerPadding.calculateTopPadding()) .padding(top = innerPadding.calculateTopPadding())
.padding(horizontal = 8.dp) .padding(vertical = 12.dp, horizontal = 12.dp),
.padding(bottom = 8.dp) verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
if (openMenuButton != null) {
openMenuButton()
}
Text( Text(
text, text,
modifier = Modifier.padding(vertical = 4.dp, horizontal = 12.dp), modifier = Modifier,
fontSize = 24.sp, fontSize = 24.sp,
color = MaterialTheme.colorScheme.onPrimaryContainer color = MaterialTheme.colorScheme.onPrimaryContainer
) )
@@ -96,22 +96,31 @@ fun MainPage(
) { ) {
val context = LocalContext.current val context = LocalContext.current
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val scope = rememberCoroutineScope()
var isActionBarShowed by remember { mutableStateOf(false) }
Box( Box(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {
BackHandler(
enabled = isActionBarShowed,
) {
isActionBarShowed = false
}
Page( Page(
stringResource(R.string.app_name), 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( Column(
modifier = Modifier.verticalScroll(rememberScrollState()).padding(bottom = 64.dp).background(Color.Transparent), 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("<")
}
}
} }
} }
@@ -0,0 +1,9 @@
package ru.omni_devel.cards
import android.app.Activity
data class NavigationPageData(
val name: String,
val pageClass: Class<out Activity>? = null,
val onClick: (() -> Unit)? = null
)