130 lines
5.1 KiB
Kotlin
130 lines
5.1 KiB
Kotlin
package ch.ergon.anytask.ui
|
|
|
|
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.fillMaxSize
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
import androidx.compose.foundation.layout.height
|
|
import androidx.compose.foundation.layout.padding
|
|
import androidx.compose.foundation.layout.size
|
|
import androidx.compose.material.Button
|
|
import androidx.compose.material.CircularProgressIndicator
|
|
import androidx.compose.material.MaterialTheme
|
|
import androidx.compose.material.OutlinedTextField
|
|
import androidx.compose.material.Surface
|
|
import androidx.compose.material.Text
|
|
import androidx.compose.material.TextButton
|
|
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.focus.FocusRequester
|
|
import androidx.compose.ui.focus.focusRequester
|
|
import androidx.compose.ui.input.key.Key
|
|
import androidx.compose.ui.input.key.KeyEventType
|
|
import androidx.compose.ui.input.key.isMetaPressed
|
|
import androidx.compose.ui.input.key.key
|
|
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
|
import androidx.compose.ui.input.key.type
|
|
import androidx.compose.ui.unit.dp
|
|
import ch.ergon.anytask.api.AnyTypeApi
|
|
import kotlinx.coroutines.launch
|
|
|
|
@Composable
|
|
fun TaskWindow(client: AnyTypeApi, isVisible: Boolean, onDismiss: () -> Unit) {
|
|
val scope = rememberCoroutineScope()
|
|
var title by remember { mutableStateOf("") }
|
|
var details by remember { mutableStateOf("") }
|
|
var isLoading by remember { mutableStateOf(false) }
|
|
var errorMessage by remember { mutableStateOf<String?>(null) }
|
|
|
|
val focusRequester = remember { FocusRequester() }
|
|
|
|
fun submit() {
|
|
if (title.isBlank()) return
|
|
scope.launch {
|
|
isLoading = true
|
|
errorMessage = null
|
|
client.createTask(title = title.trim(), details = details.trim())
|
|
.onSuccess {
|
|
title = ""
|
|
details = ""
|
|
onDismiss()
|
|
}
|
|
.onFailure { errorMessage = it.message }
|
|
isLoading = false
|
|
}
|
|
}
|
|
|
|
MaterialTheme {
|
|
Surface(modifier = Modifier.fillMaxSize()) {
|
|
Column(
|
|
modifier = Modifier
|
|
.fillMaxSize()
|
|
.padding(24.dp)
|
|
.onPreviewKeyEvent { event ->
|
|
when {
|
|
event.type == KeyEventType.KeyDown && event.key == Key.Escape -> {
|
|
onDismiss(); true
|
|
}
|
|
event.type == KeyEventType.KeyDown &&
|
|
event.key == Key.Enter &&
|
|
event.isMetaPressed -> {
|
|
submit(); true
|
|
}
|
|
else -> false
|
|
}
|
|
},
|
|
) {
|
|
Text("New Task", style = MaterialTheme.typography.h6)
|
|
Spacer(modifier = Modifier.height(16.dp))
|
|
|
|
OutlinedTextField(
|
|
value = title,
|
|
onValueChange = { title = it },
|
|
label = { Text("Title") },
|
|
singleLine = true,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.focusRequester(focusRequester),
|
|
)
|
|
Spacer(modifier = Modifier.height(12.dp))
|
|
|
|
OutlinedTextField(
|
|
value = details,
|
|
onValueChange = { details = it },
|
|
label = { Text("Details (optional)") },
|
|
modifier = Modifier.fillMaxWidth().height(120.dp),
|
|
maxLines = 4,
|
|
)
|
|
|
|
if (errorMessage != null) {
|
|
Spacer(modifier = Modifier.height(8.dp))
|
|
Text(errorMessage!!, color = MaterialTheme.colors.error, style = MaterialTheme.typography.caption)
|
|
}
|
|
|
|
Spacer(modifier = Modifier.weight(1f))
|
|
|
|
Row(
|
|
modifier = Modifier.fillMaxWidth(),
|
|
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End),
|
|
) {
|
|
TextButton(onClick = onDismiss) { Text("Cancel") }
|
|
Button(onClick = ::submit, enabled = title.isNotBlank() && !isLoading) {
|
|
if (isLoading) CircularProgressIndicator(modifier = Modifier.size(16.dp), strokeWidth = 2.dp)
|
|
else Text("Create ⌘↵")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LaunchedEffect(isVisible) { if (isVisible) focusRequester.requestFocus() }
|
|
} |