Skip to content

Commit

Permalink
Add compose navigation scaffold
Browse files Browse the repository at this point in the history
  • Loading branch information
jsixface committed Jan 2, 2025
1 parent c090bb5 commit 31ad823
Show file tree
Hide file tree
Showing 12 changed files with 339 additions and 303 deletions.
24 changes: 24 additions & 0 deletions .run/Run Desktop.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Desktop" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName"/>
<option name="externalProjectPath" value="$PROJECT_DIR$"/>
<option name="externalSystemIdString" value="GRADLE"/>
<option name="scriptParameters" value=""/>
<option name="taskDescriptions">
<list/>
</option>
<option name="taskNames">
<list>
<option value="composeApp:run"/>
</list>
</option>
<option name="vmOptions"/>
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2"/>
</configuration>
</component>
24 changes: 24 additions & 0 deletions .run/Run Server.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Server" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName"/>
<option name="externalProjectPath" value="$PROJECT_DIR$"/>
<option name="externalSystemIdString" value="GRADLE"/>
<option name="scriptParameters" value=""/>
<option name="taskDescriptions">
<list/>
</option>
<option name="taskNames">
<list>
<option value="server:run"/>
</list>
</option>
<option name="vmOptions"/>
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2"/>
</configuration>
</component>
3 changes: 2 additions & 1 deletion composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl

plugins {
alias(libs.plugins.compose.compiler)
Expand Down Expand Up @@ -32,6 +32,7 @@ kotlin {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.material3AdaptiveNavigationSuite)
implementation(compose.materialIconsExtended)
implementation(compose.ui)
implementation(compose.components.resources)
Expand Down
196 changes: 102 additions & 94 deletions composeApp/src/commonMain/kotlin/ui/BackupsScreen.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
package ui

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.sharp.Delete
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material3.Card
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
Expand All @@ -19,114 +38,103 @@ import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import org.koin.compose.koinInject
import ui.model.ModelState
import ui.model.Screen
import viewmodels.BackupScreenViewModel

object BackupsScreen : Screen {
private val padding = Modifier.padding(16.dp)
private val paddingSmall = Modifier.padding(8.dp)
private val filePattern = Regex(".*\\.([0-9]+)\\.bkp$")

private val padding = Modifier.padding(16.dp)
private val paddingSmall = Modifier.padding(8.dp)
private val filePattern = Regex(".*\\.([0-9]+)\\.bkp$")

override val name: String
get() = "Backups"

@Composable
override fun icon() {
Icon(Icons.Filled.Archive, contentDescription = name)
}

@Composable
override fun content() {
Column(
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
val backupScreenViewModel = koinInject<BackupScreenViewModel>()
val scope = rememberCoroutineScope()
var backups by remember { mutableStateOf(listOf<String>()) }
suspend fun loadBackups() {
backupScreenViewModel.backupFiles.collect {
if (it is ModelState.Success) {
backups = it.result
}
@Composable
fun BackupsScreen() {
Column(
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
val backupScreenViewModel = koinInject<BackupScreenViewModel>()
val scope = rememberCoroutineScope()
var backups by remember { mutableStateOf(listOf<String>()) }
suspend fun loadBackups() {
backupScreenViewModel.backupFiles.collect {
if (it is ModelState.Success) {
backups = it.result
}
}
LaunchedEffect(Unit) {
}
LaunchedEffect(Unit) {
scope.launch {
loadBackups()
}
}
BackupContent(
backups,
onClear = {
scope.launch {
backupScreenViewModel.clearBackups()
loadBackups()
}
}
BackupContent(
backups,
onClear = {
scope.launch {
backupScreenViewModel.clearBackups()
loadBackups()
}
},
onDelete = {
scope.launch {
backupScreenViewModel.delete(it)
loadBackups()
}
})

}
},
onDelete = {
scope.launch {
backupScreenViewModel.delete(it)
loadBackups()
}
})

}

@Composable
fun BackupContent(backups: List<String>, onDelete: (String) -> Unit, onClear: () -> Unit) {
Card(
modifier = Modifier.width(width = 900.dp).fillMaxHeight().padding(20.dp)
) {
Column(modifier = padding) {
Row {
Text(
text = "Backups",
fontSize = 30.sp,
modifier = padding,
textAlign = TextAlign.Center,
)
}
Column {
backups.forEach { backup -> BackupItem(backup) { onDelete(backup) } }
}
Row(modifier = Modifier.fillMaxSize()) {
Spacer(modifier = Modifier.weight(1f))
ElevatedButton(onClick = onClear, modifier = padding) {
Text("Clear All Backups")
}
Spacer(modifier = Modifier.weight(1f))
}

@Composable
fun BackupContent(backups: List<String>, onDelete: (String) -> Unit, onClear: () -> Unit) {
Card(
modifier = Modifier.width(width = 900.dp).fillMaxHeight().padding(20.dp)
) {
Column(modifier = padding) {
Row {
Text(
text = "Backups",
fontSize = 30.sp,
modifier = padding,
textAlign = TextAlign.Center,
)
}
Column {
backups.forEach { backup -> BackupItem(backup) { onDelete(backup) } }
}
Row(modifier = Modifier.fillMaxSize()) {
Spacer(modifier = Modifier.weight(1f))
ElevatedButton(onClick = onClear, modifier = padding) {
Text("Clear All Backups")
}
Spacer(modifier = Modifier.weight(1f))
}
}
}
}

@Composable
fun BackupItem(backup: String, onDelete: () -> Unit) {
Column {
OutlinedCard(
modifier = Modifier.padding(16.dp, 4.dp).fillMaxWidth()
) {
val ts = filePattern.find(backup)?.groupValues?.get(1)?.toLongOrNull() ?: 0
val modified = Instant.fromEpochSeconds(ts).toLocalDateTime(TimeZone.currentSystemDefault())
Row(verticalAlignment = Alignment.CenterVertically) {
Column(modifier = Modifier.weight(1f).padding(8.dp)) {
Text(backup.substringAfterLast('/'), modifier = paddingSmall)
Text(
"Completed at ${modified.date} ${modified.time}",
style = MaterialTheme.typography.labelSmall,
modifier = paddingSmall
)
}
IconButton(onClick = onDelete) {
Icon(Icons.Sharp.Delete, "Delete Backup")
}
@Composable
fun BackupItem(backup: String, onDelete: () -> Unit) {
Column {
OutlinedCard(
modifier = Modifier.padding(16.dp, 4.dp).fillMaxWidth()
) {
val ts = filePattern.find(backup)?.groupValues?.get(1)?.toLongOrNull() ?: 0
val modified = Instant.fromEpochSeconds(ts).toLocalDateTime(TimeZone.currentSystemDefault())
Row(verticalAlignment = Alignment.CenterVertically) {
Column(modifier = Modifier.weight(1f).padding(8.dp)) {
Text(backup.substringAfterLast('/'), modifier = paddingSmall)
Text(
"Completed at ${modified.date} ${modified.time}",
style = MaterialTheme.typography.labelSmall,
modifier = paddingSmall
)
}
IconButton(onClick = onDelete) {
Icon(Icons.Sharp.Delete, "Delete Backup")
}
}
}
}
}

16 changes: 3 additions & 13 deletions composeApp/src/commonMain/kotlin/ui/JobsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Inbox
import androidx.compose.material.icons.sharp.Close
import androidx.compose.material3.Card
import androidx.compose.material3.ElevatedButton
Expand Down Expand Up @@ -43,24 +42,15 @@ import io.github.jsixface.common.JobStatus.Starting
import kotlinx.coroutines.launch
import org.koin.compose.koinInject
import ui.model.ModelState
import ui.model.Screen
import viewmodels.JobsScreenModel

object JobsScreen : Screen {

private val padding = Modifier.padding(16.dp)
private val padding = Modifier.padding(16.dp)
private val paddingSmall = Modifier.padding(8.dp)

override val name: String
get() = "Jobs"

@Composable
override fun icon() {
Icon(Icons.Filled.Inbox, contentDescription = name)
}

@Composable
override fun content() {
fun JobsScreen() {
Column(
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
Expand Down Expand Up @@ -160,4 +150,4 @@ object JobsScreen : Screen {
}
}
}
}

Loading

0 comments on commit 31ad823

Please sign in to comment.