feat(ui): drawer navigation and history

This commit is contained in:
Matthieu Bessat 2024-01-29 18:37:29 +01:00
parent 542253c518
commit 69b9f018b7
11 changed files with 294 additions and 104 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -56,7 +56,7 @@ class MainActivity : ComponentActivity() {
MaterialTheme(
colorScheme = colorScheme ?: MaterialTheme.colorScheme,
) {
NoteContainer(appContext)
AppContainer(appContext)
}
}
}

View file

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

View file

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

View file

@ -9,5 +9,6 @@ crate-type = ["cdylib"]
[dependencies]
jni = "0.21.1"
popequer_rust = { path = "../../../popequer_rust" }
[target.'cfg(target_os = "android")'.dependencies]