From 69b9f018b706af3b9103d5d46b3b592f93f6ee11 Mon Sep 17 00:00:00 2001 From: Matthieu Bessat Date: Mon, 29 Jan 2024 18:37:29 +0100 Subject: [PATCH] feat(ui): drawer navigation and history --- app/build.gradle.kts | 10 +- .../net/mbess/popequer/CalendarProvider.kt | 10 + .../net/mbess/popequer/PopequerProvider.kt | 10 + .../main/java/net/mbess/popequer/ui/App.kt | 172 ++++++++++++++++++ .../java/net/mbess/popequer/ui/AppNavGraph.kt | 34 ++++ .../net/mbess/popequer/ui/AppNavigation.kt | 39 ++++ .../java/net/mbess/popequer/ui/HomeRoute.kt | 9 + .../net/mbess/popequer/ui/MainActivity.kt | 2 +- .../main/java/net/mbess/popequer/ui/Notes.kt | 102 ----------- .../mbess/popequer/ui/UpcomingEventsRoute.kt | 9 + rust-sandbox/Cargo.toml | 1 + 11 files changed, 294 insertions(+), 104 deletions(-) create mode 100644 app/src/main/java/net/mbess/popequer/CalendarProvider.kt create mode 100644 app/src/main/java/net/mbess/popequer/PopequerProvider.kt create mode 100644 app/src/main/java/net/mbess/popequer/ui/App.kt create mode 100644 app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt create mode 100644 app/src/main/java/net/mbess/popequer/ui/AppNavigation.kt create mode 100644 app/src/main/java/net/mbess/popequer/ui/HomeRoute.kt delete mode 100644 app/src/main/java/net/mbess/popequer/ui/Notes.kt create mode 100644 app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 46601d4..ecf9f76 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -53,7 +53,15 @@ dependencies { implementation(libs.androidx.material.icons.extended) implementation(libs.androidx.material3) implementation(libs.androidx.ui.tooling.preview) + runtimeOnly(libs.androidx.ui.tooling) implementation(libs.org.eclipse.jgit) implementation("com.meetup:twain:0.2.2") -} \ No newline at end of file + + val composeBom = platform("androidx.compose:compose-bom:2024.01.00") + implementation(composeBom) + + debugImplementation("androidx.compose.ui:ui-tooling") + implementation("androidx.compose.ui:ui-tooling-preview") +} + diff --git a/app/src/main/java/net/mbess/popequer/CalendarProvider.kt b/app/src/main/java/net/mbess/popequer/CalendarProvider.kt new file mode 100644 index 0000000..5cb33ee --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/CalendarProvider.kt @@ -0,0 +1,10 @@ +package net.mbess.popequer + +import android.content.Context +import android.util.Log +import kotlin.math.absoluteValue + +class CalendarProvider( + private val context: Context +) { +} diff --git a/app/src/main/java/net/mbess/popequer/PopequerProvider.kt b/app/src/main/java/net/mbess/popequer/PopequerProvider.kt new file mode 100644 index 0000000..4d8d1b2 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/PopequerProvider.kt @@ -0,0 +1,10 @@ +package net.mbess.popequer + +import android.content.Context +import android.util.Log +import kotlin.math.absoluteValue + +class PopequerProvider( + private val context: Context +) { +} diff --git a/app/src/main/java/net/mbess/popequer/ui/App.kt b/app/src/main/java/net/mbess/popequer/ui/App.kt new file mode 100644 index 0000000..a711283 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/ui/App.kt @@ -0,0 +1,172 @@ +package net.mbess.popequer.ui + +import android.util.Log +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import net.mbess.popequer.AppContext +import androidx.navigation.compose.rememberNavController +import androidx.compose.runtime.remember +import androidx.navigation.compose.currentBackStackEntryAsState + + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) +@Composable +fun AppContainer( + context: AppContext +) { + val scope = rememberCoroutineScope() + val androidContext = LocalContext.current + + + val navController = rememberNavController() + val navigationActions = remember(navController) { + AppNavigationActions(navController) + } + + val coroutineScope = rememberCoroutineScope() + + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute = + navBackStackEntry?.destination?.route ?: AppDestinations.HOME_ROUTE + + val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) + val openDrawer: () -> Unit = { coroutineScope.launch { drawerState.open() } } + val closeDrawer: () -> Unit = { coroutineScope.launch { drawerState.close() } } + + ModalNavigationDrawer( + drawerState = drawerState, + drawerContent = { + ModalDrawerSheet { + Text("Popequer", modifier = Modifier.padding(16.dp)) + Divider() + NavigationDrawerItem( + label = { Text("Home") }, + selected = currentRoute == AppDestinations.HOME_ROUTE, + onClick = { + navigationActions.navigateToHome() + closeDrawer() + } + ) + NavigationDrawerItem( + label = { Text("Upcoming events") }, + selected = currentRoute == AppDestinations.UPCOMING_EVENTS, + onClick = { + navigationActions.navigateToUpcomingEventsActivity() + closeDrawer() + } + ) + } + }, + ) { + Scaffold( + topBar = { + TopAppBar( + title = { + Text(text = "Popequer") + }, + navigationIcon = { + IconButton(onClick = openDrawer) { + Icon(Icons.Filled.Menu, contentDescription = null) + } + }, + actions = { + IconButton(onClick = { + // TODO: switch to settings view + }) { + Icon(Icons.Filled.Settings, contentDescription = null) + } + }) + }, + floatingActionButton = { + Box( + modifier = Modifier.padding(30.dp) + ) { + FloatingActionButton( + onClick = { + scope.launch(Dispatchers.IO) { + runCatching { + context.gitActions.trigger() + }.onFailure { + Log.e("MainActivity", "Failed to trigger git actions", it) + } + } + }, + content = { Icon(Icons.Filled.Add, contentDescription = null) } + ) + } + }, + floatingActionButtonPosition = FabPosition.End, + ) { padding -> + Surface( + modifier = Modifier.padding(padding) + ) { + AppNavGraph( + appContext = context, + navController = navController, + ) + } + } + } +} + +// val old_home = Surface( +// modifier = Modifier.padding(padding) +// ) { +// FlowColumn { +// FlowRow( +// modifier = Modifier.fillMaxWidth(), +// horizontalArrangement = Arrangement.SpaceAround +// ) { +// Button( +// onClick = { +// Toast.makeText( +// context.androidContext, +// "Will pull repo changes", +// Toast.LENGTH_SHORT +// ).show() +// scope.launch(Dispatchers.IO) { +// runCatching { +// context.gitActions.sync() +// Toast.makeText( +// context.androidContext, +// "Repo changes are sync", +// Toast.LENGTH_LONG +// ).show() +// }.onFailure { +// Log.e("MainActivity", "Failed to trigger git actions", it) +// } +// } +// } +// ) { +// Text("Pull") +// } +// Button( +// onClick = { +// +// } +// ) { +// Text("New quick note") +// } +// } +// LazyColumn { +// // Add 5 items +// items(30) { index -> +// Text(text = "Item: $index") +// } +// } +// } +// } diff --git a/app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt b/app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt new file mode 100644 index 0000000..d22ae56 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt @@ -0,0 +1,34 @@ +package net.mbess.popequer.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import net.mbess.popequer.AppContext + +@Composable +fun AppNavGraph( + appContext: AppContext, + modifier: Modifier = Modifier, + navController: NavHostController = rememberNavController(), + startDestination: String = AppDestinations.HOME_ROUTE, +) { + NavHost( + navController = navController, + startDestination = startDestination, + modifier = modifier + ) { + composable( + route = AppDestinations.HOME_ROUTE, + ) { + HomeRoute() + } + composable( + route = AppDestinations.UPCOMING_EVENTS + ) { + UpcomingEventsRoute() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/mbess/popequer/ui/AppNavigation.kt b/app/src/main/java/net/mbess/popequer/ui/AppNavigation.kt new file mode 100644 index 0000000..e72fbfe --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/ui/AppNavigation.kt @@ -0,0 +1,39 @@ +package net.mbess.popequer.ui + +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavHostController + +object AppDestinations { + const val HOME_ROUTE = "home" + const val UPCOMING_EVENTS = "upcoming-events" +} + +/** + * Models the navigation actions in the app. + */ +class AppNavigationActions(navController: NavHostController) { + val navigateToHome: () -> Unit = { + navController.navigate(AppDestinations.HOME_ROUTE) { + // Pop up to the start destination of the graph to + // avoid building up a large stack of destinations + // on the back stack as users select items + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + // Avoid multiple copies of the same destination when + // reselecting the same item + launchSingleTop = true + // Restore state when reselecting a previously selected item + restoreState = true + } + } + val navigateToUpcomingEventsActivity: () -> Unit = { + navController.navigate(AppDestinations.UPCOMING_EVENTS) { + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + restoreState = true + } + } +} diff --git a/app/src/main/java/net/mbess/popequer/ui/HomeRoute.kt b/app/src/main/java/net/mbess/popequer/ui/HomeRoute.kt new file mode 100644 index 0000000..a8c7824 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/ui/HomeRoute.kt @@ -0,0 +1,9 @@ +package net.mbess.popequer.ui + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable + +@Composable +fun HomeRoute() { + Text(text = "This is the home route") +} diff --git a/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt b/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt index 295afc8..50a352c 100644 --- a/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt +++ b/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt @@ -56,7 +56,7 @@ class MainActivity : ComponentActivity() { MaterialTheme( colorScheme = colorScheme ?: MaterialTheme.colorScheme, ) { - NoteContainer(appContext) + AppContainer(appContext) } } } diff --git a/app/src/main/java/net/mbess/popequer/ui/Notes.kt b/app/src/main/java/net/mbess/popequer/ui/Notes.kt deleted file mode 100644 index d85ac66..0000000 --- a/app/src/main/java/net/mbess/popequer/ui/Notes.kt +++ /dev/null @@ -1,102 +0,0 @@ -package net.mbess.popequer.ui - -import android.os.Looper -import android.util.Log -import android.widget.Toast -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.Settings -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import net.mbess.popequer.AppContext - - -@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) -@Composable -fun NoteContainer( - context: AppContext -) { - val scope = rememberCoroutineScope() - val androidContext = LocalContext.current - - Scaffold( - topBar = { - TopAppBar( - title = { - Text(text = "Popequer") - }, - actions = { - IconButton(onClick = { - // TODO: switch to settings view - }) { - Icon(Icons.Filled.Settings, contentDescription = null) - } - }) - }, - floatingActionButton = { - Box( - modifier = Modifier.padding(30.dp) - ) { - FloatingActionButton( - onClick = { - scope.launch(Dispatchers.IO) { - runCatching { - context.gitActions.trigger() - }.onFailure { - Log.e("MainActivity", "Failed to trigger git actions", it) - } - } - }, - content = { Icon(Icons.Filled.Add, contentDescription = null) } - ) - } - }, - floatingActionButtonPosition = FabPosition.End, - ) { padding -> - Surface( - modifier = Modifier.padding(padding) - ){ - //Editor() - FlowRow ( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceAround - ) { - Button( - onClick = { - Toast.makeText(context.androidContext, "Will pull repo changes", Toast.LENGTH_SHORT ).show() - scope.launch(Dispatchers.IO) { - runCatching { - context.gitActions.sync() - Toast.makeText(context.androidContext, "Repo changes are sync", Toast.LENGTH_LONG ).show() - }.onFailure { - Log.e("MainActivity", "Failed to trigger git actions", it) - } - } - } - ) { - Text("Pull") - } - Button( - onClick = { - Toast.makeText(context.androidContext, "Will pull repo changes", Toast.LENGTH_LONG ).show() - } - ) { - Text("New quick note") - } - } - } - } -} diff --git a/app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt b/app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt new file mode 100644 index 0000000..0ccc7bc --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt @@ -0,0 +1,9 @@ +package net.mbess.popequer.ui + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable + +@Composable +fun UpcomingEventsRoute() { + Text(text = "This is the upcoming events route") +} diff --git a/rust-sandbox/Cargo.toml b/rust-sandbox/Cargo.toml index bc979df..394f150 100644 --- a/rust-sandbox/Cargo.toml +++ b/rust-sandbox/Cargo.toml @@ -9,5 +9,6 @@ crate-type = ["cdylib"] [dependencies] jni = "0.21.1" +popequer_rust = { path = "../../../popequer_rust" } [target.'cfg(target_os = "android")'.dependencies]