feat(connector): add Navigation

This commit is contained in:
Anthony 2024-04-01 13:24:13 +02:00
parent 32c9be2eee
commit ddb6c94d5e
9 changed files with 308 additions and 78 deletions

View File

@ -8,6 +8,7 @@ plugins {
kotlin {
jvm("desktop")
jvmToolchain(21)
sourceSets {
val desktopMain by getting
@ -24,6 +25,34 @@ kotlin {
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
implementation("org.jetbrains.compose.material3:material3-desktop:1.6.1")
// Voyager - Navigation
val voyagerVersion = "1.0.0"
// Multiplatform
// Navigator
implementation("cafe.adriel.voyager:voyager-navigator:$voyagerVersion")
// Screen Model
implementation("cafe.adriel.voyager:voyager-screenmodel:$voyagerVersion")
// BottomSheetNavigator
implementation("cafe.adriel.voyager:voyager-bottom-sheet-navigator:$voyagerVersion")
// TabNavigator
implementation("cafe.adriel.voyager:voyager-tab-navigator:$voyagerVersion")
// Transitions
implementation("cafe.adriel.voyager:voyager-transitions:$voyagerVersion")
// Desktop + Android
// Kodein integration
implementation("cafe.adriel.voyager:voyager-kodein:$voyagerVersion")
// RxJava integration
implementation("cafe.adriel.voyager:voyager-rxjava:$voyagerVersion")
}
}
}

View File

@ -0,0 +1,36 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import connector.composeapp.generated.resources.Res
import connector.composeapp.generated.resources.info_24px
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
class About : Tab {
@OptIn(ExperimentalResourceApi::class)
override val options: TabOptions
@Composable
get() {
val title = "About"
val icon = painterResource(Res.drawable.info_24px)
return remember {
TabOptions(
index = 0u,
title = title,
icon = icon,
)
}
}
@Composable
override fun Content() {
Column {
Text("About")
}
}
}

View File

@ -1,27 +1,22 @@
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import connector.composeapp.generated.resources.*
import cafe.adriel.voyager.navigator.tab.CurrentTab
import cafe.adriel.voyager.navigator.tab.LocalTabNavigator
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabNavigator
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.ui.tooling.preview.Preview
import theme.AppTheme
@ -30,49 +25,35 @@ import theme.AppTheme
@Preview
fun App() {
AppTheme {
var showContent by remember { mutableStateOf(false) }
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
AppScaffold {
Button(onClick = { showContent = !showContent }) {
Text("Click me!")
}
AnimatedVisibility(showContent) {
val greeting = remember { Greeting().greet() }
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Image(painterResource(Res.drawable.compose_multiplatform), null)
Text("Compose: $greeting")
}
}
}
}
AppScaffold()
}
}
@Composable
fun AppScaffold(content: @Composable() () -> Unit) {
fun AppScaffold() {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()
Scaffold(
topBar = {
TopBar(drawerState, scope)
},
) { innerPadding ->
Column(
modifier = Modifier.padding(innerPadding)
) {
NavigationDrawer(drawerState) {
TabNavigator(Projects) {
Scaffold(
topBar = {
TopBar(drawerState, scope)
},
content = { innerPadding ->
Column(
verticalArrangement = Arrangement.spacedBy(16.dp)
modifier = Modifier.padding(innerPadding)
) {
content()
Text("Test")
NavigationDrawer(drawerState) {
CurrentTab()
}
}
}
}
)
}
}
/**
* Component for the bar on top of the screen
*/
@ -128,48 +109,18 @@ fun NavigationDrawer(
ModalDrawerSheet {
Column(modifier = Modifier.verticalScroll(rememberScrollState()) ) {
Text("Project Name...", modifier = Modifier.padding(16.dp))
NavigationDrawerItem(
label = { Text(text = "Projects") },
icon = { Icon(painterResource(Res.drawable.folder_24px), null) },
selected = false,
onClick = { /* TODO */ },
)
TabNavigationItem(Projects)
HorizontalDivider()
Text("Tester", modifier = Modifier.padding(16.dp))
NavigationDrawerItem(
label = { Text(text = "Procedures") },
icon = { Icon(imageVector = Icons.Outlined.Edit, null) },
selected = false,
onClick = { /* TODO */ },
)
NavigationDrawerItem(
label = { Text(text = "Simulator Test") },
icon = { Icon(painterResource(Res.drawable.check_box_24px), null) },
selected = false,
onClick = { /* TODO */ },
)
NavigationDrawerItem(
label = { Text(text = "Test Results") },
icon = { Icon(painterResource(Res.drawable.history_24px), null) },
selected = false,
onClick = { /* TODO */ },
)
TabNavigationItem(Procedures())
TabNavigationItem(SimulatorTest())
TabNavigationItem(TestResults())
HorizontalDivider()
Text("Application", modifier = Modifier.padding(16.dp))
NavigationDrawerItem(
label = { Text(text = "Settings") },
icon = { Icon(imageVector = Icons.Outlined.Settings, null) },
selected = false,
onClick = { /* TODO */ },
)
NavigationDrawerItem(
label = { Text(text = "About") },
icon = { Icon(painterResource(Res.drawable.info_24px), null) },
selected = false,
onClick = { /* TODO */ },
)
TabNavigationItem(Settings())
TabNavigationItem(About())
}
}
}
@ -177,3 +128,18 @@ fun NavigationDrawer(
content()
}
}
/**
* Creates button in NavigationDrawer
*/
@Composable
private fun TabNavigationItem(tab: Tab) {
val tabNavigator = LocalTabNavigator.current
NavigationDrawerItem(
label = { Text(tab.options.title) },
icon = { tab.options.icon?.let { Icon(it, null) } },
selected = tabNavigator.current == tab,
onClick = { tabNavigator.current = tab },
)
}

View File

@ -0,0 +1,55 @@
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import connector.composeapp.generated.resources.Res
import connector.composeapp.generated.resources.compose_multiplatform
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
class Procedures : Tab {
override val options: TabOptions
@Composable
get() {
val title = "Procedures"
val icon = rememberVectorPainter(Icons.Outlined.Edit)
return remember {
TabOptions(
index = 1u,
title = title,
icon = icon,
)
}
}
@OptIn(ExperimentalResourceApi::class)
@Composable
override fun Content() {
var showContent by remember { mutableStateOf(false) }
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Button(onClick = { showContent = !showContent }) {
Text("Click me!")
}
AnimatedVisibility(showContent) {
val greeting = remember { Greeting().greet() }
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Image(painterResource(Res.drawable.compose_multiplatform), null)
Text("Compose: $greeting")
}
}
}
}
}

View File

@ -0,0 +1,35 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import connector.composeapp.generated.resources.Res
import connector.composeapp.generated.resources.folder_24px
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
object Projects : Tab {
@OptIn(ExperimentalResourceApi::class)
override val options: TabOptions
@Composable
get() {
val title = "Projects"
val icon = painterResource(Res.drawable.folder_24px)
return remember {
TabOptions(
index = 0u,
title = title,
icon = icon,
)
}
}
@Composable
override fun Content() {
Column {
Text("Projects")
}
}
}

View File

@ -0,0 +1,36 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import org.jetbrains.compose.resources.ExperimentalResourceApi
class Settings : Tab {
@OptIn(ExperimentalResourceApi::class)
override val options: TabOptions
@Composable
get() {
val title = "Settings"
val icon = rememberVectorPainter(Icons.Outlined.Settings)
return remember {
TabOptions(
index = 4u,
title = title,
icon = icon,
)
}
}
@Composable
override fun Content() {
Column {
Text("Settings")
}
}
}

View File

@ -0,0 +1,36 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import connector.composeapp.generated.resources.Res
import connector.composeapp.generated.resources.check_box_24px
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
class SimulatorTest : Tab {
@OptIn(ExperimentalResourceApi::class)
override val options: TabOptions
@Composable
get() {
val title = "Simulator Test"
val icon = painterResource(Res.drawable.check_box_24px)
return remember {
TabOptions(
index = 2u,
title = title,
icon = icon,
)
}
}
@Composable
override fun Content() {
Column {
Text("Simulator Test")
}
}
}

View File

@ -0,0 +1,36 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import connector.composeapp.generated.resources.Res
import connector.composeapp.generated.resources.history_24px
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource
class TestResults : Tab {
@OptIn(ExperimentalResourceApi::class)
override val options: TabOptions
@Composable
get() {
val title = "Test Results"
val icon = painterResource(Res.drawable.history_24px)
return remember {
TabOptions(
index = 3u,
title = title,
icon = icon,
)
}
}
@Composable
override fun Content() {
Column {
Text("Test Results")
}
}
}

View File

@ -1,12 +1,13 @@
plugins {
alias(libs.plugins.kotlinMultiplatform)
}
kotlin {
jvm()
jvmToolchain(21)
sourceSets {
commonMain.dependencies {
// put your Multiplatform dependencies here