Compare commits
2
Commits
768bb0c650
...
563ee98d03
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
563ee98d03
|
||
|
|
7f92df1ca5
|
+1
-1
@@ -14,4 +14,4 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
version = PhoebenchVersion(1, 2, 0, "")
|
version = PhoebenchVersion(1, 2, 1, "")
|
||||||
@@ -80,7 +80,9 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<ShadowJar> {
|
tasks.withType<ShadowJar> {
|
||||||
archiveFileName = if(isDebug) "phoebench-cli-debug.jar" else "phoebench-cli.jar"
|
val archive = if(isDebug) "phoebench-cli-debug.jar" else "phoebench-cli.jar"
|
||||||
|
println("Using archive '$archive'")
|
||||||
|
archiveFileName = archive
|
||||||
}
|
}
|
||||||
|
|
||||||
buildConfig {
|
buildConfig {
|
||||||
|
|||||||
@@ -6,16 +6,21 @@ import kotlin.system.exitProcess
|
|||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
object AuthHandlers {
|
object AuthHandlers {
|
||||||
|
suspend fun checkServer() =
|
||||||
|
Client.callRoute(Routes.handshake, EmptyRequest()).bind { handshake ->
|
||||||
|
if(handshake.version != ProtocolVersion.VERSION) {
|
||||||
|
val server = Client.getServer() ?: "<unknown server ULR>"
|
||||||
|
Client.onClearServer()
|
||||||
|
ErrorResponse("Cannot use $server: protocol version mismatch (server: ${handshake.version}, expected: ${ProtocolVersion.VERSION})").error()
|
||||||
|
}
|
||||||
|
Unit.value()
|
||||||
|
}
|
||||||
|
|
||||||
fun serverPrompt(server: String?): Either<ErrorResponse, Unit> {
|
fun serverPrompt(server: String?): Either<ErrorResponse, Unit> {
|
||||||
val useServer = server.maybePrompt("server") { it }
|
val useServer = server.maybePrompt("server") { it }
|
||||||
Client.onSelectServer(useServer)
|
Client.onSelectServer(useServer)
|
||||||
return runBlocking {
|
return runBlocking {
|
||||||
Client.callRoute(Routes.handshake, EmptyRequest()).bind { handshake ->
|
checkServer().bind { Client.onSelectServer(useServer).value() }
|
||||||
if (handshake.version != ProtocolVersion.VERSION) {
|
|
||||||
Client.onClearServer()
|
|
||||||
ErrorResponse("Mismatched protocol version (server: ${handshake.version}, client: ${ProtocolVersion.VERSION})").error()
|
|
||||||
} else Unit.value()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.jaytux.phoebench.clients.cli
|
|||||||
|
|
||||||
import com.github.javakeyring.BackendNotSupportedException
|
import com.github.javakeyring.BackendNotSupportedException
|
||||||
import com.github.javakeyring.Keyring
|
import com.github.javakeyring.Keyring
|
||||||
|
import com.github.javakeyring.PasswordAccessException
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
@@ -22,7 +23,11 @@ object PersistentStorage {
|
|||||||
private object KeyringBackend : IBackend {
|
private object KeyringBackend : IBackend {
|
||||||
override fun read(key: String): String? = try {
|
override fun read(key: String): String? = try {
|
||||||
Keyring.create().use { it.getPassword(SERVICE, key) }
|
Keyring.create().use { it.getPassword(SERVICE, key) }
|
||||||
} catch(e: Exception) {
|
}
|
||||||
|
catch(e: PasswordAccessException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
catch(e: BackendNotSupportedException) {
|
||||||
_backend = PreferencesBackend
|
_backend = PreferencesBackend
|
||||||
_backend.read(key)
|
_backend.read(key)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import androidx.compose.material3.DropdownMenuItem
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
@@ -237,10 +238,12 @@ fun SignupView(server: String?, error: String?, onSwitchLogin: () -> Unit, onSig
|
|||||||
@Composable
|
@Composable
|
||||||
fun AuthenticatedRoot() {
|
fun AuthenticatedRoot() {
|
||||||
val snacks = SnackProvider.get()
|
val snacks = SnackProvider.get()
|
||||||
|
val auth = AuthProvider.get()
|
||||||
val state = remember { SnackbarHostState() }
|
val state = remember { SnackbarHostState() }
|
||||||
val vm = viewModel { HomeVM() }
|
val vm = viewModel { HomeVM() }
|
||||||
var loggingOut by remember { mutableStateOf(false) }
|
var loggingOut by remember { mutableStateOf(false) }
|
||||||
var currentProject by remember { mutableStateOf<Uuid?>(null) }
|
var currentProject by remember { mutableStateOf<Uuid?>(null) }
|
||||||
|
val server by auth.server
|
||||||
|
|
||||||
LaunchedEffect(snacks) {
|
LaunchedEffect(snacks) {
|
||||||
snacks.snacks.collect { state.showSnackbar(it) }
|
snacks.snacks.collect { state.showSnackbar(it) }
|
||||||
@@ -254,7 +257,12 @@ fun AuthenticatedRoot() {
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text("PhoeBench v${ClientVersion.VERSION}", style = MaterialTheme.typography.headlineLarge) },
|
title = {
|
||||||
|
Column {
|
||||||
|
Text("PhoeBench v${ClientVersion.VERSION}", style = MaterialTheme.typography.headlineLarge)
|
||||||
|
server?.let { Text("Connected to $it", style = MaterialTheme.typography.bodySmall, color = LocalContentColor.current.copy(0.6f)) }
|
||||||
|
}
|
||||||
|
},
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||||
titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer
|
titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer
|
||||||
|
|||||||
+2
-6
@@ -133,24 +133,20 @@ fun MonitorMessage(msg: ServerMonitorEvent.ITextEvent) = when(msg) {
|
|||||||
val weight = if(ANSI.BOLD in ansi) FontWeight.Bold else null
|
val weight = if(ANSI.BOLD in ansi) FontWeight.Bold else null
|
||||||
val decoration = if(ANSI.UNDERLINE in ansi) TextDecoration.Underline else null
|
val decoration = if(ANSI.UNDERLINE in ansi) TextDecoration.Underline else null
|
||||||
val color = when {
|
val color = when {
|
||||||
ANSI.FG_BLACK in ansi -> Color.Black
|
|
||||||
ANSI.FG_RED in ansi -> Color.Red
|
ANSI.FG_RED in ansi -> Color.Red
|
||||||
ANSI.FG_GREEN in ansi -> Color.Green
|
ANSI.FG_GREEN in ansi -> Color.Green
|
||||||
ANSI.FG_YELLOW in ansi -> Color.Yellow
|
ANSI.FG_YELLOW in ansi -> Color.Yellow
|
||||||
ANSI.FG_BLUE in ansi -> Color.Blue
|
ANSI.FG_BLUE in ansi -> Color.Blue
|
||||||
ANSI.FG_MAGENTA in ansi -> Color.Magenta
|
ANSI.FG_GRAY in ansi -> Color.Gray
|
||||||
ANSI.FG_CYAN in ansi -> Color.Cyan
|
|
||||||
else -> LocalContentColor.current
|
else -> LocalContentColor.current
|
||||||
}
|
}
|
||||||
|
|
||||||
val background = when {
|
val background = when {
|
||||||
ANSI.BG_BLACK in ansi -> Color.Black
|
|
||||||
ANSI.BG_RED in ansi -> Color.Red
|
ANSI.BG_RED in ansi -> Color.Red
|
||||||
ANSI.BG_GREEN in ansi -> Color.Green
|
ANSI.BG_GREEN in ansi -> Color.Green
|
||||||
ANSI.BG_YELLOW in ansi -> Color.Yellow
|
ANSI.BG_YELLOW in ansi -> Color.Yellow
|
||||||
ANSI.BG_BLUE in ansi -> Color.Blue
|
ANSI.BG_BLUE in ansi -> Color.Blue
|
||||||
ANSI.BG_MAGENTA in ansi -> Color.Magenta
|
ANSI.BG_GRAY in ansi -> Color.Gray
|
||||||
ANSI.BG_CYAN in ansi -> Color.Cyan
|
|
||||||
else -> null
|
else -> null
|
||||||
}?.let { Modifier.background(it) } ?: Modifier
|
}?.let { Modifier.background(it) } ?: Modifier
|
||||||
|
|
||||||
|
|||||||
@@ -78,13 +78,11 @@ sealed class ProjectEvent {
|
|||||||
enum class ANSI(val bitIdx: Int, val ansiCode: Int) {
|
enum class ANSI(val bitIdx: Int, val ansiCode: Int) {
|
||||||
BOLD(0, 1), UNDERLINE(1, 4),
|
BOLD(0, 1), UNDERLINE(1, 4),
|
||||||
|
|
||||||
FG_BLACK(2, 30), FG_RED(3, 31), FG_GREEN(4, 32),
|
FG_RED(2, 31), FG_GREEN(3, 32), FG_YELLOW(4, 33),
|
||||||
FG_YELLOW(5, 33), FG_BLUE(6, 34), FG_MAGENTA(7, 35),
|
FG_BLUE(5, 34), FG_GRAY(6, 90),
|
||||||
FG_CYAN(8, 36),
|
|
||||||
|
|
||||||
BG_BLACK(9, 40), BG_RED(10, 41), BG_GREEN(11, 42),
|
BG_RED(7, 41), BG_GREEN(8, 42), BG_YELLOW(9, 43),
|
||||||
BG_YELLOW(12, 43), BG_BLUE(13, 44), BG_MAGENTA(14, 45),
|
BG_BLUE(10, 44), BG_GRAY(11, 100);
|
||||||
BG_CYAN(15, 46);
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val _mapping: Map<Int, ANSI>
|
private val _mapping: Map<Int, ANSI>
|
||||||
|
|||||||
@@ -179,7 +179,6 @@ fun Application.module() {
|
|||||||
) { _, id, sender ->
|
) { _, id, sender ->
|
||||||
val bus = Buses.monitorBus(id)
|
val bus = Buses.monitorBus(id)
|
||||||
val backlog = bus.onConnect()
|
val backlog = bus.onConnect()
|
||||||
println("Bus [$id] connected; sending backlog (${backlog.start != null} // ${backlog.messages.size} // ${backlog.end != null})")
|
|
||||||
sender(bus.bus.serializer, backlog)
|
sender(bus.bus.serializer, backlog)
|
||||||
bus.bus
|
bus.bus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,21 +11,18 @@ class MutableBackLog<TStart, TEvent, TEnd> {
|
|||||||
fun registerStart(event: TStart) {
|
fun registerStart(event: TStart) {
|
||||||
if(start != null) throw IllegalStateException("Start is already set.")
|
if(start != null) throw IllegalStateException("Start is already set.")
|
||||||
start = event
|
start = event
|
||||||
println("[BACKLOG]: start '$event'")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEvent(event: TEvent) {
|
fun onEvent(event: TEvent) {
|
||||||
if(start == null) throw IllegalStateException("Start is not set yet.")
|
if(start == null) throw IllegalStateException("Start is not set yet.")
|
||||||
if(end != null) throw IllegalStateException("End is already set.")
|
if(end != null) throw IllegalStateException("End is already set.")
|
||||||
_events += event
|
_events += event
|
||||||
println("[BACKLOG]: event '$event'")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerEnd(event: TEnd) {
|
fun registerEnd(event: TEnd) {
|
||||||
if(start == null) throw IllegalStateException("Start is not set yet.")
|
if(start == null) throw IllegalStateException("Start is not set yet.")
|
||||||
if(end != null) throw IllegalStateException("End is already set.")
|
if(end != null) throw IllegalStateException("End is already set.")
|
||||||
end = event
|
end = event
|
||||||
println("[BACKLOG]: end '$event'")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
|
|||||||
Reference in New Issue
Block a user