From 17994fe7517223b8945c14fb2fd03dabaae20407 Mon Sep 17 00:00:00 2001 From: higan Date: Fri, 27 Oct 2023 14:29:42 +0800 Subject: [PATCH] Upgrade sisyphus to 2.1.0 --- .github/workflows/build.yml | 7 +- build.gradle.kts | 8 +- core/build.gradle.kts | 12 +- desktop/build.gradle.kts | 18 +- .../io/kanro/mediator/desktop/ui/CallList.kt | 29 +-- .../io/kanro/mediator/desktop/ui/CallView.kt | 66 +++--- .../kanro/mediator/desktop/ui/ConfigView.kt | 188 +++++++++++------- .../kanro/mediator/internal/ServerManager.kt | 58 ++++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 9 files changed, 230 insertions(+), 158 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 407639a..2946cff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,11 +6,6 @@ jobs: name: Gradle Wrapper runs-on: ubuntu-latest steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.7.0 - with: - access_token: ${{ secrets.GITHUB_TOKEN }} - # Check out current repository - name: Fetch Sources uses: actions/checkout@v2 @@ -110,7 +105,7 @@ jobs: path: | ./desktop/build/compose/binaries/main/msi/ ./desktop/build/compose/binaries/main/deb/ - ./desktop/build/compose/notarization/main/*/*.dmg + ./desktop/build/compose/notarization/**/*.dmg # Prepare a draft release for GitHub Releases page for the manual verification # If accepted and published, release workflow would be triggered diff --git a/build.gradle.kts b/build.gradle.kts index c88968b..af2130d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,14 +1,14 @@ plugins { - kotlin("jvm") version "1.6.10" apply false - id("org.jetbrains.compose") version "1.1.1" apply false - id("com.bybutter.sisyphus.protobuf") version "1.3.21" apply false + kotlin("jvm") version "1.9.10" apply false + id("org.jetbrains.compose") version "1.5.2" apply false + id("com.bybutter.sisyphus.protobuf") version "2.1.0" apply false id("org.jlleitschuh.gradle.ktlint") version "10.0.0" apply false id("org.jetbrains.changelog") version "1.3.0" } allprojects { group = "io.kanro" - version = "1.4.7" + version = "1.5.0" repositories { mavenLocal() diff --git a/core/build.gradle.kts b/core/build.gradle.kts index e495fbe..5730959 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -11,11 +11,11 @@ protobuf { } dependencies { - api("io.grpc:grpc-core:1.42.1") - api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.0") - api("com.bybutter.sisyphus:sisyphus-grpc-coroutine:1.3.35") - api("com.bybutter.sisyphus:sisyphus-jackson-protobuf:1.3.35") - api("io.grpc:grpc-netty:1.42.1") + api("io.grpc:grpc-core:1.59.0") + api("io.grpc:grpc-netty:1.59.0") + api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.7.3") + api("com.bybutter.sisyphus:sisyphus-grpc-coroutine:2.1.0") + api("com.bybutter.sisyphus:sisyphus-jackson-protobuf:2.1.0") api("io.netty:netty-handler-proxy:4.1.72.Final") api("org.bouncycastle:bcpkix-jdk15on:1.70") @@ -29,7 +29,7 @@ tasks.test { } tasks.withType() { - kotlinOptions.jvmTarget = "16" + kotlinOptions.jvmTarget = "17" } ktlint { diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index 7765261..d1afa4e 100755 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -17,19 +16,20 @@ repositories { dependencies { implementation(project(":core")) - implementation("com.bybutter.compose:compose-jetbrains-theme:1.1.0") + implementation("com.bybutter.compose:compose-jetbrains-theme:2.2.0") implementation("org.jetbrains.kotlin:kotlin-reflect:1.6.10") - testImplementation(kotlin("test-junit5")) - testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.2") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.2") implementation("net.harawata:appdirs:1.2.1") implementation("com.github.java-json-tools:json-patch:1.13") implementation("com.github.Dansoftowner:jSystemThemeDetector:3.8") - implementation("com.bybutter.sisyphus.tools:sisyphus-protoc-runner:1.3.35") + implementation("com.bybutter.sisyphus.tools:sisyphus-protoc-runner:2.1.0") implementation("ch.qos.logback:logback-classic:1.4.1") implementation(compose.desktop.currentOs) implementation(compose.uiTooling) + + testImplementation(kotlin("test-junit5")) + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.2") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.2") } tasks.test { @@ -37,10 +37,10 @@ tasks.test { } tasks.withType() { - kotlinOptions.jvmTarget = "16" + kotlinOptions.jvmTarget = "17" kotlinOptions.freeCompilerArgs += listOf( "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true" + "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true", ) } @@ -49,7 +49,7 @@ compose.desktop { mainClass = "io.kanro.mediator.desktop.MainKt" nativeDistributions { jvmArgs( - "-Dapple.awt.application.appearance=system" + "-Dapple.awt.application.appearance=system", ) targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) modules("java.management") diff --git a/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallList.kt b/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallList.kt index 6416c79..6e50cec 100644 --- a/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallList.kt +++ b/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallList.kt @@ -42,10 +42,10 @@ import com.bybutter.sisyphus.protobuf.primitives.minus import com.bybutter.sisyphus.protobuf.primitives.toTime import io.grpc.Status import io.kanro.compose.jetbrains.JBTheme -import io.kanro.compose.jetbrains.SelectionScope import io.kanro.compose.jetbrains.control.Icon import io.kanro.compose.jetbrains.control.JPanelBorder import io.kanro.compose.jetbrains.control.ListItemHoverIndication +import io.kanro.compose.jetbrains.control.SelectionScope import io.kanro.compose.jetbrains.control.Text import io.kanro.compose.jetbrains.control.jBorder import io.kanro.mediator.desktop.model.CallEvent @@ -111,7 +111,7 @@ fun CallList(modifier: Modifier = Modifier) { VerticalScrollbar( rememberScrollbarAdapter(listState), - Modifier.align(Alignment.CenterEnd) + Modifier.align(Alignment.CenterEnd), ) } } @@ -134,7 +134,7 @@ fun CallRowHeader( .fillMaxWidth() .background(JBTheme.panelColors.bgContent) .jBorder(bottom = 1.dp, color = JBTheme.panelColors.border), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { val idState = rememberDraggableState { delta -> resizing(0, delta) @@ -150,7 +150,7 @@ fun CallRowHeader( return pointerHoverIcon(PointerIcon(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR))) .draggable( orientation = Orientation.Horizontal, - state = state + state = state, ) } @@ -183,7 +183,7 @@ fun CallRow( selected: Boolean, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, role: Role? = null, - onClick: () -> Unit + onClick: () -> Unit, ) { SelectionScope(selected) { Row( @@ -202,7 +202,7 @@ fun CallRow( interactionSource = interactionSource, indication = ListItemHoverIndication, onClick = onClick, - role = role + role = role, ) .run { if (selected) { @@ -213,7 +213,7 @@ fun CallRow( } .hoverable(interactionSource) .jBorder(bottom = 1.dp, color = JBTheme.panelColors.border), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { val call by record.asState() val start = call.start() @@ -296,25 +296,30 @@ fun CallIcon(call: CallTimeline, modifier: Modifier = Modifier) { Status.Code.OK -> Icon("icons/toolbarPassed.svg") Status.Code.ABORTED, - Status.Code.CANCELLED -> Icon("icons/toolbarTerminated.svg") + Status.Code.CANCELLED, + -> Icon("icons/toolbarTerminated.svg") Status.Code.DEADLINE_EXCEEDED, Status.Code.PERMISSION_DENIED, - Status.Code.UNAUTHENTICATED -> Icon("icons/toolbarSkipped.svg") + Status.Code.UNAUTHENTICATED, + -> Icon("icons/toolbarSkipped.svg") Status.Code.ALREADY_EXISTS, Status.Code.RESOURCE_EXHAUSTED, Status.Code.FAILED_PRECONDITION, Status.Code.OUT_OF_RANGE, Status.Code.UNAVAILABLE, - Status.Code.INVALID_ARGUMENT -> Icon("icons/toolbarFailed.svg") + Status.Code.INVALID_ARGUMENT, + -> Icon("icons/toolbarFailed.svg") Status.Code.DATA_LOSS, - Status.Code.NOT_FOUND -> Icon("icons/testUnknown.svg") + Status.Code.NOT_FOUND, + -> Icon("icons/testUnknown.svg") Status.Code.UNIMPLEMENTED, Status.Code.UNKNOWN, - Status.Code.INTERNAL -> Icon("icons/toolbarError.svg") + Status.Code.INTERNAL, + -> Icon("icons/toolbarError.svg") else -> Icon("icons/run.svg") } diff --git a/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallView.kt b/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallView.kt index 16cdde6..61e90e0 100644 --- a/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallView.kt +++ b/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/CallView.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.PointerIcon import androidx.compose.ui.input.pointer.pointerHoverIcon +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp import com.bybutter.sisyphus.coroutine.io @@ -33,7 +34,6 @@ import com.bybutter.sisyphus.rpc.Status import com.bybutter.sisyphus.string.toUpperSpaceCase import io.grpc.Metadata import io.kanro.compose.jetbrains.JBTheme -import io.kanro.compose.jetbrains.SelectionScope import io.kanro.compose.jetbrains.control.* import io.kanro.compose.jetbrains.control.ContextMenuArea import io.kanro.mediator.desktop.model.CallEvent @@ -54,26 +54,30 @@ fun CallView(call: CallTimeline?) { Box(Modifier.fillMaxWidth()) { JPanelBorder(Modifier.fillMaxWidth().height(1.dp).align(Alignment.BottomStart)) + val density = LocalDensity.current + Box( Modifier.matchParentSize().pointerHoverIcon(PointerIcon(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR))) .draggable( orientation = Orientation.Vertical, state = rememberDraggableState { delta -> - height -= delta.dp - } - ) + with(density) { + height -= delta.toDp() + } + }, + ), ) {} Row(Modifier.fillMaxWidth().align(Alignment.CenterStart)) { Tab( selectedTab == 0, { selectedTab = 0 - } + }, ) { Row( modifier = Modifier.padding(7.dp, 4.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp) + horizontalArrangement = Arrangement.spacedBy(4.dp), ) { Icon("icons/ppLib.svg") Text("Statistics", modifier = Modifier.offset(y = (-1).dp)) @@ -83,12 +87,12 @@ fun CallView(call: CallTimeline?) { selectedTab == 1, { selectedTab = 1 - } + }, ) { Row( modifier = Modifier.padding(7.dp, 4.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp) + horizontalArrangement = Arrangement.spacedBy(4.dp), ) { Icon("icons/timeline.svg") Text("Timeline", modifier = Modifier.offset(y = (-1).dp)) @@ -112,7 +116,6 @@ fun CallView(call: CallTimeline?) { @Composable fun StatisticsView(call: CallTimeline) { Column(Modifier.background(JBTheme.panelColors.bgContent).fillMaxSize()) { - var selectedKey by remember(call) { mutableStateOf(-1) } MetadataItem("ID", call.id, selectedKey == 0) { @@ -184,8 +187,8 @@ fun TimelineView(call: CallTimeline) { orientation = Orientation.Horizontal, state = rememberDraggableState { delta -> width += delta.dp - } - ) + }, + ), ) Box(Modifier.fillMaxSize()) { @@ -199,6 +202,7 @@ fun TimelineView(call: CallTimeline) { is CallEvent.Input -> EventView(timeline, event) is CallEvent.Output -> EventView(timeline, event) is CallEvent.Start -> EventView(event) + else -> {} } } } @@ -213,7 +217,7 @@ fun TimelineItemRow( selected: Boolean, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, role: Role? = null, - onClick: () -> Unit + onClick: () -> Unit, ) { ContextMenuArea({ val result = mutableListOf() @@ -228,9 +232,9 @@ fun TimelineItemRow( result += ContextMenuItem("Copy Headers") { Toolkit.getDefaultToolkit().systemClipboard.setContents( StringSelection( - event.header.toMap().toJson() + event.header.toMap().toJson(), ), - null + null, ) } } @@ -239,9 +243,9 @@ fun TimelineItemRow( result += ContextMenuItem("Copy Headers") { Toolkit.getDefaultToolkit().systemClipboard.setContents( StringSelection( - event.header.toMap().toJson() + event.header.toMap().toJson(), ), - null + null, ) } } @@ -250,9 +254,9 @@ fun TimelineItemRow( result += ContextMenuItem("Copy Trails") { Toolkit.getDefaultToolkit().systemClipboard.setContents( StringSelection( - event.trails.toMap().toJson() + event.trails.toMap().toJson(), ), - null + null, ) } } @@ -263,7 +267,8 @@ fun TimelineItemRow( } result += ContextMenuItem("Copy Message") { Toolkit.getDefaultToolkit().systemClipboard.setContents( - StringSelection(json), null + StringSelection(json), + null, ) } } @@ -274,10 +279,13 @@ fun TimelineItemRow( } result += ContextMenuItem("Copy Message") { Toolkit.getDefaultToolkit().systemClipboard.setContents( - StringSelection(json), null + StringSelection(json), + null, ) } } + + else -> {} } result }) { @@ -288,7 +296,7 @@ fun TimelineItemRow( interactionSource = interactionSource, indication = ListItemHoverIndication, onClick = onClick, - role = role + role = role, ).run { if (selected) { background(color = JBTheme.selectionColors.active) @@ -296,7 +304,7 @@ fun TimelineItemRow( this } }.hoverable(interactionSource), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { val icon = when (event) { is CallEvent.Transparent -> "icons/testUnknown.svg" @@ -367,6 +375,7 @@ fun EventView(call: CallTimeline, event: CallEvent) { when (event) { is CallEvent.Input -> MessageView(call.reflection(), event.message()) is CallEvent.Output -> MessageView(call.reflection(), event.message()) + else -> {} } } else { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { @@ -403,18 +412,23 @@ fun MetadataView(metadata: Metadata, modifier: Modifier = Modifier) { if (key.endsWith("-bin")) { val value = metadata[Metadata.Key.of(it, Metadata.BINARY_BYTE_MARSHALLER)] ?: byteArrayOf() MessageFieldView( - Modifier, selectedKey, ProtoReflection.current(), + Modifier, + selectedKey, + ProtoReflection.current(), FieldDescriptorProto { this.type = FieldDescriptorProto.Type.MESSAGE this.name = "status" this.typeName = Status.name }, - it, Status.parse(value) + it, + Status.parse(value), ) } else { val value = metadata[Metadata.Key.of(it, Metadata.ASCII_STRING_MARSHALLER)] ?: "" MetadataItem( - it, value, selectedKey.value == it + it, + value, + selectedKey.value == it, ) { selectedKey.value = it } @@ -430,7 +444,7 @@ fun MetadataItem( key: String, value: String, selected: Boolean, - onClick: () -> Unit + onClick: () -> Unit, ) { ContextMenuArea({ val result = mutableListOf() diff --git a/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/ConfigView.kt b/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/ConfigView.kt index 86a826f..509adfa 100644 --- a/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/ConfigView.kt +++ b/desktop/src/main/kotlin/io/kanro/mediator/desktop/ui/ConfigView.kt @@ -49,7 +49,6 @@ import androidx.compose.ui.window.rememberDialogState import com.bybutter.sisyphus.string.toTitleCase import io.kanro.compose.jetbrains.JBTheme import io.kanro.compose.jetbrains.JBThemeStyle -import io.kanro.compose.jetbrains.SelectionScope import io.kanro.compose.jetbrains.control.Button import io.kanro.compose.jetbrains.control.CheckBox import io.kanro.compose.jetbrains.control.DropdownList @@ -58,6 +57,7 @@ import io.kanro.compose.jetbrains.control.Icon import io.kanro.compose.jetbrains.control.JPanelBorder import io.kanro.compose.jetbrains.control.ListItemHoverIndication import io.kanro.compose.jetbrains.control.OutlineButton +import io.kanro.compose.jetbrains.control.SelectionScope import io.kanro.compose.jetbrains.control.Text import io.kanro.compose.jetbrains.control.TextField import io.kanro.compose.jetbrains.control.jBorder @@ -91,7 +91,7 @@ fun ConfigDialog( enabled: Boolean = true, focusable: Boolean = true, onPreviewKeyEvent: ((KeyEvent) -> Boolean) = { false }, - onKeyEvent: ((KeyEvent) -> Boolean) = { false } + onKeyEvent: ((KeyEvent) -> Boolean) = { false }, ) { Dialog( onCloseRequest, @@ -105,10 +105,10 @@ fun ConfigDialog( enabled, focusable, onPreviewKeyEvent, - onKeyEvent + onKeyEvent, ) { CompositionLocalProvider( - LocalWindow provides this.window + LocalWindow provides this.window, ) { Column(Modifier.background(JBTheme.panelColors.bgDialog)) { JPanelBorder(Modifier.height(1.dp).fillMaxWidth()) @@ -125,24 +125,24 @@ fun ConfigDialog( selectedItem == 0, { selectedItem = 0 - } + }, ) { Text( "General", Modifier.padding(horizontal = 12.dp), - style = JBTheme.typography.defaultBold + style = JBTheme.typography.defaultBold, ) } ConfigItem( selectedItem == 1, { selectedItem = 1 - } + }, ) { Text( "Server Rule", Modifier.padding(horizontal = 12.dp), - style = JBTheme.typography.defaultBold + style = JBTheme.typography.defaultBold, ) } // ConfigItem( @@ -173,7 +173,8 @@ fun ConfigDialog( Row(Modifier.height(49.dp).jBorder(top = 1.dp, color = JBTheme.panelColors.border)) { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.CenterEnd) { Row( - Modifier.padding(horizontal = 21.dp), horizontalArrangement = Arrangement.spacedBy(12.dp) + Modifier.padding(horizontal = 21.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { OutlineButton({ onCloseRequest() @@ -185,7 +186,7 @@ fun ConfigDialog( onSave(vm) vm.changed.value = false }, - enabled = vm.changed.value + enabled = vm.changed.value, ) { Text("Apply") } @@ -208,7 +209,7 @@ fun ConfigItem( selected: Boolean, onClick: () -> Unit, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - content: @Composable () -> Unit + content: @Composable () -> Unit, ) { Box( Modifier.fillMaxWidth().height(25.dp).selectable( @@ -216,7 +217,7 @@ fun ConfigItem( interactionSource = interactionSource, indication = null, onClick = onClick, - role = null + role = null, ).run { if (selected) { background(color = JBTheme.selectionColors.active) @@ -224,7 +225,7 @@ fun ConfigItem( this } }, - contentAlignment = Alignment.CenterStart + contentAlignment = Alignment.CenterStart, ) { SelectionScope(selected, block = content) } @@ -238,7 +239,8 @@ fun GeneralConfigView(vm: ConfigViewModel) { Row(Modifier.height(28.dp), verticalAlignment = Alignment.CenterVertically) { Text("Theme:", modifier = Modifier.width(70.dp)) DropdownList( - listOf(null, *JBThemeStyle.values()), vm.theme.value, + listOf(null, *JBThemeStyle.values()), + vm.theme.value, onValueChange = { vm.theme.value = it vm.changed.value = true @@ -246,7 +248,7 @@ fun GeneralConfigView(vm: ConfigViewModel) { }, valueRender = { it?.toString()?.toTitleCase() ?: "Auto" - } + }, ) } @@ -275,14 +277,15 @@ fun GeneralConfigView(vm: ConfigViewModel) { vm.proxyPort.value = vm.proxyPort.value } }, - isError = error, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number) + isError = error, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), ) } Column( Modifier.fillMaxSize(), horizontalAlignment = Alignment.Start, - verticalArrangement = Arrangement.spacedBy(6.dp) + verticalArrangement = Arrangement.spacedBy(6.dp), ) { Text("Local Address:", modifier = Modifier.width(100.dp)) val localAddress = remember { @@ -301,7 +304,7 @@ fun GeneralConfigView(vm: ConfigViewModel) { modifier = Modifier.fillMaxSize(), readOnly = true, singleLine = false, - maxLines = Int.MAX_VALUE + maxLines = Int.MAX_VALUE, ) } } @@ -340,19 +343,21 @@ fun ServerRuleView(vm: ConfigViewModel) { vm.serverRules.remove(rule) vm.serverRules.add(index + 1, rule) vm.changed.value = true - } + }, ) Row(Modifier.fillMaxSize(), horizontalArrangement = Arrangement.spacedBy(20.dp)) { LazyColumn( Modifier.width(150.dp).fillMaxHeight().background(JBTheme.panelColors.bgContent) - .jBorder(1.dp, JBTheme.panelColors.border) + .jBorder(1.dp, JBTheme.panelColors.border), ) { items(vm.serverRules) { x -> RuleRow( - x.name.value, x.enabled.value, selectedRule == x, + x.name.value, + x.enabled.value, + selectedRule == x, { selectedRule = x - } + }, ) } } @@ -362,14 +367,14 @@ fun ServerRuleView(vm: ConfigViewModel) { Row( Modifier.height(28.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { CheckBox( rule.enabled.value, { rule.enabled.value = it vm.changed.value = true - } + }, ) Text("Enable server rule") } @@ -381,7 +386,8 @@ fun ServerRuleView(vm: ConfigViewModel) { rule.name.value = it.trim() vm.changed.value = true }, - Modifier.width(200.dp), singleLine = true + Modifier.width(200.dp), + singleLine = true, ) } @@ -393,7 +399,9 @@ fun ServerRuleView(vm: ConfigViewModel) { rule.regex.value = it.trim() vm.changed.value = true }, - Modifier.width(200.dp), isError = !rule.regex.value.isValidRegex(), singleLine = true + Modifier.width(200.dp), + isError = !rule.regex.value.isValidRegex(), + singleLine = true, ) } @@ -401,7 +409,8 @@ fun ServerRuleView(vm: ConfigViewModel) { Text("Rewrite:", Modifier.width(80.dp)) DropdownList( - listOf(false, true), rule.replaceSsl.value, + listOf(false, true), + rule.replaceSsl.value, onValueChange = { rule.replaceSsl.value = it vm.changed.value = true @@ -409,7 +418,7 @@ fun ServerRuleView(vm: ConfigViewModel) { valueRender = { if (it) "HTTPS" else "HTTP" }, - enabled = rule.replaceEnabled.value + enabled = rule.replaceEnabled.value, ) Spacer(Modifier.width(8.dp)) TextField( @@ -418,21 +427,24 @@ fun ServerRuleView(vm: ConfigViewModel) { rule.replace.value = it.trim() vm.changed.value = true }, - Modifier.width(200.dp), singleLine = true, enabled = rule.replaceEnabled.value + Modifier.width(200.dp), + singleLine = true, + enabled = rule.replaceEnabled.value, ) Spacer(Modifier.width(8.dp)) CheckBox( rule.replaceEnabled.value, onCheckedChange = { rule.replaceEnabled.value = it - } + }, ) } Row(Modifier.height(28.dp), verticalAlignment = Alignment.CenterVertically) { Text("Schema:", Modifier.width(80.dp)) DropdownList( - ProtobufSchemaSource.values().toList(), rule.schemaSource.value, + ProtobufSchemaSource.values().toList(), + rule.schemaSource.value, onValueChange = { rule.schemaSource.value = it vm.changed.value = true @@ -444,7 +456,7 @@ fun ServerRuleView(vm: ConfigViewModel) { ProtobufSchemaSource.FILE_DESCRIPTOR_SET -> "File descriptor set" else -> it.name } - } + }, ) } @@ -453,22 +465,25 @@ fun ServerRuleView(vm: ConfigViewModel) { when (rule.schemaSource.value) { ProtobufSchemaSource.SERVER_REFLECTION -> { Column( - verticalArrangement = Arrangement.spacedBy(6.dp) + verticalArrangement = Arrangement.spacedBy(6.dp), ) { Text("Reflection api metadata:") MetadataView( - vm, rule.reflectionMetadata, Modifier.height(0.dp).weight(1.0f).fillMaxWidth() + vm, + rule.reflectionMetadata, + Modifier.height(0.dp).weight(1.0f).fillMaxWidth(), ) } } ProtobufSchemaSource.PROTO_ROOT -> { Column( - verticalArrangement = Arrangement.spacedBy(6.dp) + verticalArrangement = Arrangement.spacedBy(6.dp), ) { Text("Proto file roots:") PathsView( - vm, rule.roots, + vm, + rule.roots, { val fileChooser = JFileChooser().apply { fileSelectionMode = JFileChooser.DIRECTORIES_ONLY @@ -479,18 +494,19 @@ fun ServerRuleView(vm: ConfigViewModel) { fileChooser.showOpenDialog(window) fileChooser.selectedFile?.toPath()?.toString() }, - Modifier.height(0.dp).weight(1.0f).fillMaxWidth() + Modifier.height(0.dp).weight(1.0f).fillMaxWidth(), ) } } ProtobufSchemaSource.FILE_DESCRIPTOR_SET -> { Column( - verticalArrangement = Arrangement.spacedBy(6.dp) + verticalArrangement = Arrangement.spacedBy(6.dp), ) { Text("File descriptor set:") PathsView( - vm, rule.descriptors, + vm, + rule.descriptors, { val dialog = FileDialog(window, "Select", FileDialog.LOAD) dialog.isVisible = true @@ -498,7 +514,7 @@ fun ServerRuleView(vm: ConfigViewModel) { Path.of(dialog.directory, dialog.file).toString() } }, - Modifier.height(0.dp).weight(1.0f).fillMaxWidth() + Modifier.height(0.dp).weight(1.0f).fillMaxWidth(), ) } } @@ -546,19 +562,21 @@ fun RequestRuleView(vm: ConfigViewModel) { vm.requestRules.remove(rule) vm.requestRules.add(index + 1, rule) vm.changed.value = true - } + }, ) Row(Modifier.fillMaxSize(), horizontalArrangement = Arrangement.spacedBy(20.dp)) { LazyColumn( Modifier.width(150.dp).fillMaxHeight().background(JBTheme.panelColors.bgContent) - .jBorder(1.dp, JBTheme.panelColors.border) + .jBorder(1.dp, JBTheme.panelColors.border), ) { items(vm.requestRules) { x -> RuleRow( - x.name.value, x.enabled.value, selectedRule == x, + x.name.value, + x.enabled.value, + selectedRule == x, { selectedRule = x - } + }, ) } } @@ -568,14 +586,14 @@ fun RequestRuleView(vm: ConfigViewModel) { Row( Modifier.height(28.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { CheckBox( rule.enabled.value, { rule.enabled.value = it vm.changed.value = true - } + }, ) Text("Enable request rule") } @@ -587,7 +605,8 @@ fun RequestRuleView(vm: ConfigViewModel) { rule.name.value = it.trim() vm.changed.value = true }, - Modifier.width(200.dp), singleLine = true + Modifier.width(200.dp), + singleLine = true, ) } @@ -599,35 +618,39 @@ fun RequestRuleView(vm: ConfigViewModel) { rule.method.value = it.trim() vm.changed.value = true }, - Modifier.width(200.dp), isError = !rule.method.value.isValidRegex(), singleLine = true + Modifier.width(200.dp), + isError = !rule.method.value.isValidRegex(), + singleLine = true, ) } Row(Modifier.height(28.dp), verticalAlignment = Alignment.CenterVertically) { Text("Type:", Modifier.width(80.dp)) DropdownList( - RequestRule.Type.values().toList(), rule.type.value, + RequestRule.Type.values().toList(), + rule.type.value, onValueChange = { rule.type.value = it vm.changed.value = true }, valueRender = { it.toString().toTitleCase() - } + }, ) } Row(Modifier.height(28.dp), verticalAlignment = Alignment.CenterVertically) { Text("Operation:", Modifier.width(80.dp)) DropdownList( - RequestRule.Operation.values().toList(), rule.op.value, + RequestRule.Operation.values().toList(), + rule.op.value, onValueChange = { rule.op.value = it vm.changed.value = true }, valueRender = { it.toString().toTitleCase() - } + }, ) } @@ -647,7 +670,8 @@ fun RequestRuleView(vm: ConfigViewModel) { rule.path.value = it.trim() vm.changed.value = true }, - Modifier.width(200.dp), singleLine = true + Modifier.width(200.dp), + singleLine = true, ) } @@ -655,7 +679,8 @@ fun RequestRuleView(vm: ConfigViewModel) { RequestRule.Operation.REMOVE -> {} RequestRule.Operation.TEST, RequestRule.Operation.ADD, RequestRule.Operation.REPLACE -> { Column( - Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(6.dp) + Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(6.dp), ) { Text("Value:", Modifier.width(80.dp)) TextField( @@ -664,7 +689,9 @@ fun RequestRuleView(vm: ConfigViewModel) { rule.value.value = it.trim() vm.changed.value = true }, - Modifier.fillMaxSize(), singleLine = false, maxLines = Int.MAX_VALUE + Modifier.fillMaxSize(), + singleLine = false, + maxLines = Int.MAX_VALUE, ) } } @@ -678,7 +705,8 @@ fun RequestRuleView(vm: ConfigViewModel) { rule.value.value = it.trim() vm.changed.value = true }, - Modifier.width(200.dp), singleLine = true + Modifier.width(200.dp), + singleLine = true, ) } } @@ -708,7 +736,7 @@ fun RuleRow( interactionSource = interactionSource, indication = ListItemHoverIndication, onClick = onSelect, - role = null + role = null, ).run { if (selected) { background(color = JBTheme.selectionColors.active) @@ -717,7 +745,7 @@ fun RuleRow( } }.hoverable(interactionSource).padding(horizontal = 12.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(6.dp) + horizontalArrangement = Arrangement.spacedBy(6.dp), ) { Box(Modifier.size(16.dp)) { if (enabled) { @@ -747,16 +775,21 @@ fun MetadataView( } items(metadata) { x -> MetadataRow( - keyWidth, configVm, x, selectedEntry == x, + keyWidth, + configVm, + x, + selectedEntry == x, { selectedEntry = x - } + }, ) } } JPanelBorder(Modifier.width(1.dp).fillMaxHeight()) ListToolBar( - list = metadata, selectedItem = selectedEntry, orientation = Orientation.Vertical, + list = metadata, + selectedItem = selectedEntry, + orientation = Orientation.Vertical, onCreate = { metadata += MetadataEntry("(new)") configVm.changed.value = true @@ -765,7 +798,7 @@ fun MetadataView( metadata.remove(selectedEntry) selectedEntry = null configVm.changed.value = true - } + }, ) } } @@ -777,7 +810,7 @@ fun MetadataRowHeader( ) { Row( modifier = Modifier.height(28.dp).fillMaxWidth().background(JBTheme.panelColors.bgContent), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { val fromState = rememberDraggableState { delta -> resizing(delta) @@ -789,8 +822,9 @@ fun MetadataRowHeader( JPanelBorder( Modifier.width(1.dp).fillMaxHeight() .pointerHoverIcon(PointerIcon(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR))).draggable( - orientation = Orientation.Horizontal, state = fromState - ) + orientation = Orientation.Horizontal, + state = fromState, + ), ) Box(Modifier.width(0.dp).weight(1.0f)) { Text("Value", Modifier.padding(start = 7.dp)) @@ -814,7 +848,7 @@ fun MetadataRow( interactionSource = interactionSource, indication = ListItemHoverIndication, onClick = onSelect, - role = null + role = null, ).run { if (selected) { background(color = JBTheme.selectionColors.active) @@ -822,7 +856,7 @@ fun MetadataRow( this } }.hoverable(interactionSource), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { EmbeddedTextField( entry.key.value, @@ -835,7 +869,7 @@ fun MetadataRow( onSelect() } }, - singleLine = true + singleLine = true, ) Spacer(Modifier.width(1.dp)) EmbeddedTextField( @@ -849,7 +883,7 @@ fun MetadataRow( onSelect() } }, - singleLine = true + singleLine = true, ) } } @@ -869,20 +903,22 @@ fun PathsView( stickyHeader { Row( modifier = Modifier.height(28.dp).fillMaxWidth().background(JBTheme.panelColors.bgContent), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text("Path", Modifier.padding(start = 7.dp)) } } itemsIndexed(roots) { index, x -> PathRow( - configVm, x, selected == index, + configVm, + x, + selected == index, { selected = index }, { roots[index] = it - } + }, ) } } @@ -901,7 +937,7 @@ fun PathsView( roots.removeAt(selected) selected = -1 configVm.changed.value = true - } + }, ) } } @@ -922,7 +958,7 @@ fun PathRow( interactionSource = interactionSource, indication = ListItemHoverIndication, onClick = onSelect, - role = null + role = null, ).run { if (selected) { background(color = JBTheme.selectionColors.active) @@ -930,7 +966,7 @@ fun PathRow( this } }.hoverable(interactionSource), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { EmbeddedTextField( path, @@ -943,7 +979,7 @@ fun PathRow( onSelect() } }, - singleLine = true + singleLine = true, ) } } diff --git a/desktop/src/main/kotlin/io/kanro/mediator/internal/ServerManager.kt b/desktop/src/main/kotlin/io/kanro/mediator/internal/ServerManager.kt index 13f9cff..8de91b5 100644 --- a/desktop/src/main/kotlin/io/kanro/mediator/internal/ServerManager.kt +++ b/desktop/src/main/kotlin/io/kanro/mediator/internal/ServerManager.kt @@ -2,15 +2,20 @@ package io.kanro.mediator.internal import com.bybutter.sisyphus.protobuf.ProtobufBooster import io.grpc.ConnectivityState +import io.grpc.Grpc import io.grpc.HttpConnectProxiedSocketAddress import io.grpc.ManagedChannel import io.grpc.ManagedChannelBuilder +import io.grpc.TlsChannelCredentials import io.kanro.mediator.desktop.model.MediatorConfiguration import io.kanro.mediator.desktop.model.ProtobufSchemaSource import io.kanro.mediator.desktop.model.ServerRule import io.kanro.mediator.desktop.viewmodel.MainViewModel import io.kanro.mediator.netty.frontend.GrpcProxyServer import java.net.InetSocketAddress +import java.security.cert.CertificateException +import java.security.cert.X509Certificate +import javax.net.ssl.X509TrustManager class ServerManager(vm: MainViewModel, private val config: MediatorConfiguration) { /** @@ -58,42 +63,59 @@ class ServerManager(vm: MainViewModel, private val config: MediatorConfiguration fun replayChannel(authority: String, ssl: Boolean): io.grpc.Channel { return replayChannels.getOrPut("http${if (ssl) "s" else ""}://$authority") { - ManagedChannelBuilder.forTarget(authority).proxyDetector { - HttpConnectProxiedSocketAddress.newBuilder().setTargetAddress(it as InetSocketAddress).setProxyAddress( - InetSocketAddress( - "127.0.0.1", config.proxyPort - ) - ).build() + if (ssl) { + val creds = TlsChannelCredentials.newBuilder().trustManager(object : X509TrustManager { + override fun getAcceptedIssuers(): Array = arrayOf() + + @Throws(CertificateException::class) + override fun checkServerTrusted(chain: Array, authType: String) = Unit + + @Throws(CertificateException::class) + override fun checkClientTrusted(chain: Array, authType: String) = Unit + }).build() + Grpc.newChannelBuilder(authority, creds).proxyDetector { + HttpConnectProxiedSocketAddress.newBuilder().setTargetAddress(it as InetSocketAddress) + .setProxyAddress( + InetSocketAddress( + "127.0.0.1", + config.proxyPort, + ), + ).build() + }.build() + } else { + ManagedChannelBuilder.forTarget(authority).proxyDetector { + HttpConnectProxiedSocketAddress.newBuilder().setTargetAddress(it as InetSocketAddress) + .setProxyAddress( + InetSocketAddress( + "127.0.0.1", + config.proxyPort, + ), + ).build() + }.usePlaintext().build() }.apply { - if (ssl) { - useTransportSecurity() - } else { - usePlaintext() - } - }.build().apply { this.notifyWhenStateChanged( ConnectivityState.CONNECTING, { println("Connecting to $authority") - } + }, ) this.notifyWhenStateChanged( ConnectivityState.IDLE, { println("Connected to $authority") - } + }, ) this.notifyWhenStateChanged( ConnectivityState.READY, { println("$authority ready") - } + }, ) this.notifyWhenStateChanged( ConnectivityState.TRANSIENT_FAILURE, { println("File to connect to $authority") - } + }, ) } } @@ -105,11 +127,11 @@ class ServerManager(vm: MainViewModel, private val config: MediatorConfiguration when (rule?.schemaSource) { ProtobufSchemaSource.PROTO_ROOT -> ProtoRootReflection( - rule.roots + rule.roots, ) ProtobufSchemaSource.FILE_DESCRIPTOR_SET -> FileDescriptorSetReflection( - rule.descriptors + rule.descriptors, ) else -> ServerProtoReflection(channel(authority, ssl)).apply { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 669386b..fce403e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists