feat(ui): drawer navigation and history
This commit is contained in:
parent
542253c518
commit
69b9f018b7
11 changed files with 294 additions and 104 deletions
|
@ -53,7 +53,15 @@ dependencies {
|
||||||
implementation(libs.androidx.material.icons.extended)
|
implementation(libs.androidx.material.icons.extended)
|
||||||
implementation(libs.androidx.material3)
|
implementation(libs.androidx.material3)
|
||||||
implementation(libs.androidx.ui.tooling.preview)
|
implementation(libs.androidx.ui.tooling.preview)
|
||||||
|
|
||||||
runtimeOnly(libs.androidx.ui.tooling)
|
runtimeOnly(libs.androidx.ui.tooling)
|
||||||
implementation(libs.org.eclipse.jgit)
|
implementation(libs.org.eclipse.jgit)
|
||||||
implementation("com.meetup:twain:0.2.2")
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
10
app/src/main/java/net/mbess/popequer/CalendarProvider.kt
Normal file
10
app/src/main/java/net/mbess/popequer/CalendarProvider.kt
Normal 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
|
||||||
|
) {
|
||||||
|
}
|
10
app/src/main/java/net/mbess/popequer/PopequerProvider.kt
Normal file
10
app/src/main/java/net/mbess/popequer/PopequerProvider.kt
Normal 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
|
||||||
|
) {
|
||||||
|
}
|
172
app/src/main/java/net/mbess/popequer/ui/App.kt
Normal file
172
app/src/main/java/net/mbess/popequer/ui/App.kt
Normal 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")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
34
app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt
Normal file
34
app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
app/src/main/java/net/mbess/popequer/ui/AppNavigation.kt
Normal file
39
app/src/main/java/net/mbess/popequer/ui/AppNavigation.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
app/src/main/java/net/mbess/popequer/ui/HomeRoute.kt
Normal file
9
app/src/main/java/net/mbess/popequer/ui/HomeRoute.kt
Normal 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")
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ class MainActivity : ComponentActivity() {
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme ?: MaterialTheme.colorScheme,
|
colorScheme = colorScheme ?: MaterialTheme.colorScheme,
|
||||||
) {
|
) {
|
||||||
NoteContainer(appContext)
|
AppContainer(appContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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")
|
||||||
|
}
|
|
@ -9,5 +9,6 @@ crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
jni = "0.21.1"
|
jni = "0.21.1"
|
||||||
|
popequer_rust = { path = "../../../popequer_rust" }
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
|
|
Loading…
Reference in a new issue