Skip to content

Commit

Permalink
puts debugger UI back into IJ plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
cjbrooks12 committed Sep 29, 2022
1 parent 0e36915 commit 6e44cc7
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 41 deletions.
56 changes: 33 additions & 23 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
## 2.1.0 - 2022-09-29

- Restores the Debugger UI in the Ballast Intellij Plugin
- Removed deprecated `AndroidViewModel.attachEventHandler()` version that should have been removed in 2.0.0, adds new
`AndroidViewModel.runOnLifecycle()` to combine attaching an eventHandler and observing states with 1 method

## 2.0.1 - 2022-09-06

- Fixed issue publishing Intellij Plugin

## 2.0.0 - 2022-09-02

- Updates to Kotlin 1.7.10
- Updates Ktor to 2.1.0
- Updates other dependencies to latest versions
- Removes Debugger UI from IntelliJ plugin, so the that plugin can be republished without the Compose dependency,
- Removes Debugger UI from IntelliJ plugin, so the that plugin can be republished without the Compose dependency,
allowing the templating feature in the latest IntelliJ versions, at least

**New/Updated Features**
- Adds `BootstrapInterceptor` for sending an Input when the ViewModel is created, instead of making the UI send the
- Adds `BootstrapInterceptor` for sending an Input when the ViewModel is created, instead of making the UI send the
initial Input
- `InputStrategy` is now typed with the same type paramters as everything else in the `DefaultViewModelConfiguration`
- Some configuration DSL methods are deprecated:
- `builder.forViewModel()` should be replaced with `builder.withViewModel().build()`
- `BallastRepository` now takes `BallastViewModelConfiguration` in its primary constructor instead of
- `BallastRepository` now takes `BallastViewModelConfiguration` in its primary constructor instead of
`BallastViewModelConfiguration.Builder`. Use `builder.withRepository().build()` instead of the old constructor.
- Adds a configuration callback to `BallastSavedStateInterceptor` to allow user-specified buffering/filtering on the
- Adds a configuration callback to `BallastSavedStateInterceptor` to allow user-specified buffering/filtering on the
States as they are sent to be saved

## 1.3.0 - 2022-08-16
Expand All @@ -30,12 +40,12 @@
## 1.2.0 - 2022-05-18

- Improvements to `AndroidViewModel`
- Adds `attachEventHandler()` override which runs on a `CoroutineScope` rather than a `Lifecycle`, which is
- Adds `attachEventHandler()` override which runs on a `CoroutineScope` rather than a `Lifecycle`, which is
better-suited for Compose EventHandlers
- Adds `attachEventHandlerOnLifecycle()` to be more explicit about when the eventHandler is running on a Lifecycle
- Original `attachEventHandler()` is now marked as deprecated, and should be replaced with
- Original `attachEventHandler()` is now marked as deprecated, and should be replaced with
`attachEventHandlerOnLifecycle()`
- Adds `observeStatesOnLifecycle()` method for more easily collecting states in XML-based Views
- Adds `observeStatesOnLifecycle()` method for more easily collecting states in XML-based Views

## 1.1.0 - 2022-04-29

Expand All @@ -55,18 +65,18 @@

- Fix bug in IntelliJ plugin where settings were not being saved
- Removes "sample" from IntelliJ plugin, as that example and several more are available from the documentation site

## 0.15.0 - 2022-04-06

- Fix several bugs in Debugger UI
- Fix several bugs in Debugger UI
- Kotlin coroutines versions were in conflict and crashing the debugger
- Timestamps not correctly reported once ViewModel was refreshed
- Connection Ballast Version not reported correctly once refreshed
- Adds new `ballast-saved-state` module
- Adds `ballast-test` API for isolating a single input
- Reverts Coroutines version back to 1.5.2. To use Ballast on iOS with the new memory model, manually include the
- Reverts Coroutines version back to 1.5.2. To use Ballast on iOS with the new memory model, manually include the
1.6.0 dependency

## 0.14.0 - 2022-03-28

- Attempts to get iOS support working and documented, with M1 Simulator support
Expand All @@ -79,28 +89,28 @@
## 0.13.0 - 2022-03-24

- [BREAKING CHANGE] Renames `ballast-crashlytics` module to `ballast-firebase-crashlytics`
- [BREAKING CHANGE] Renames `sideEffect()` to `sideJob()` to be more accurate and less confusing in comparison to
- [BREAKING CHANGE] Renames `sideEffect()` to `sideJob()` to be more accurate and less confusing in comparison to
other Kotlin MVI libraries.
- [BREAKING CHANGE] `BallastViewModel` no longer implements the `SendChannel` interface, it exposes the `send` and
`trySend` methods directly. It also adds `sendAndAwaitCompletion()` to send an Input and wait for it to completely
- [BREAKING CHANGE] `BallastViewModel` no longer implements the `SendChannel` interface, it exposes the `send` and
`trySend` methods directly. It also adds `sendAndAwaitCompletion()` to send an Input and wait for it to completely
finish processing.
- [BREAKING CHANGE] The `logger` property of `BallastViewModelConfiguration.Builder` is now a function, which receives
the viewModel name when built, to pass as the tag of a logger.
- [BREAKING CHANGE] Moves annotations for Firebase into commonMain and renames them:
- `@FirebaseCrashlyticsInterceptor.Ignore` --> `@FirebaseCrashlyticsIgnore`
- `@FirebaseAnalyticsInterceptor.TrackInput` --> `@FirebaseAnalyticsTrackInput`
- [FUNCTIONAL CHANGE] SideJobs are now posted to the VM immediately, rather than collected and dispatched explicitly
after handling. The default implementation still requires that SideJobs are sent as the last statements of the
- [FUNCTIONAL CHANGE] SideJobs are now posted to the VM immediately, rather than collected and dispatched explicitly
after handling. The default implementation still requires that SideJobs are sent as the last statements of the
`InputHandler`, though.
- By writing a custom `InputStrategy.Guardian`, you could remove the restriction that sideJobs must be started at the
end of the Input. This is dangerous and you shouldn't do it unless you really know what you're doing.
- [BUG FIX] Fixes issue where JS Debugger cannot connect because JS browser websocket clients can't send headers
- [NEW] Adds platform-specific `BallastLogger` implementations (`AndroidBallastLogger`, `JsConsoleBallastLogger`). The
default logger of `BallastViewModelConfiguration` is still `NoOpLogger()`.
- [NEW] Adds platform-specific `BallastLogger` implementations (`AndroidBallastLogger`, `JsConsoleBallastLogger`). The
default logger of `BallastViewModelConfiguration` is still `NoOpLogger()`.

## 0.12.0 - 2022-03-17

- Fixes issue with `inputHandler { }` and `eventHandler { }` functions, which previously didn't actually send the input
- Fixes issue with `inputHandler { }` and `eventHandler { }` functions, which previously didn't actually send the input
or event to the lambda
- Move all InputHandler checks into the Guardian, so any/all of them could be thrown away by the end-user if needed
- make a dedicated `InputStrategyScope` to match the pattern of all other pluggable features
Expand All @@ -127,7 +137,7 @@
- Converts Debugger UI to an IntelliJ Plugin, instead of a standalone desktop application
- Adds a few new `BallastNotification`s, to notify of Inputs and Events being queued, but not yet processed
- Fixed bug where SideEffect errors and cancellation was not being notified properly
- `SideEffectcope` is now also a `CoroutineScope`, so you can `launch` other coroutines directly within the
- `SideEffectcope` is now also a `CoroutineScope`, so you can `launch` other coroutines directly within the
`sideEffect(key) { }` block without having to manually wrap it in `coroutineScope { }`

## 0.8.2 - 2022-02-23
Expand All @@ -140,20 +150,20 @@

## 0.8.0 - 2022-02-22

This is a major release, with lots of new features, greatly improved safety, but with several significant breaking
This is a major release, with lots of new features, greatly improved safety, but with several significant breaking
changes, as descibed below:

- Improves side-effects
- They are now started through a Channel, instead of relying on a Mutex for safety
- New `BallastInterceptor` methods added to track sideEffect starts/errors
- SideEffects (and related APIs) now _require_ a `key` to be provided, to avoid accidental restarting cause by
- SideEffects (and related APIs) now _require_ a `key` to be provided, to avoid accidental restarting cause by
disparate Inputs forgetting to provide a key
- Improves safety of `ParallelInputStrategy` to prevent multiple updates, rather than just throwing an error at the end
of the Input handler block if it was used incorrectly
- Replaces `onCompleted` callback with a `Guardian` interface, which each InputStrategy can create for itself to check
accesses during the InputHandler, rather than at the end
- Rewrites Interceptor API
- Instead of an interface, interceptors "events" are sent as a sealed class, `BallastNotification`. These
- Instead of an interface, interceptors "events" are sent as a sealed class, `BallastNotification`. These
Notifications are sent to a SharedFlow inside the core ViewModel, and each Interceptor observes this SharedFlow
from its own coroutine, launched in the viewModel coroutineScope
- Improves Repository `Cached` DSL:
Expand Down
3 changes: 2 additions & 1 deletion ballast-core/api/android/ballast-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ public final class com/copperleaf/ballast/core/AndroidBallastLogger : com/copper

public class com/copperleaf/ballast/core/AndroidViewModel : androidx/lifecycle/ViewModel, com/copperleaf/ballast/BallastViewModel {
public fun <init> (Lcom/copperleaf/ballast/BallastViewModelConfiguration;)V
public final fun attachEventHandler (Landroidx/lifecycle/LifecycleOwner;Lcom/copperleaf/ballast/EventHandler;)V
public final fun attachEventHandler (Lkotlinx/coroutines/CoroutineScope;Lcom/copperleaf/ballast/EventHandler;)Lkotlinx/coroutines/Job;
public static synthetic fun attachEventHandler$default (Lcom/copperleaf/ballast/core/AndroidViewModel;Lkotlinx/coroutines/CoroutineScope;Lcom/copperleaf/ballast/EventHandler;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
public final fun attachEventHandlerOnLifecycle (Landroidx/lifecycle/LifecycleOwner;Lcom/copperleaf/ballast/EventHandler;Landroidx/lifecycle/Lifecycle$State;)Lkotlinx/coroutines/Job;
Expand All @@ -373,6 +372,8 @@ public class com/copperleaf/ballast/core/AndroidViewModel : androidx/lifecycle/V
public fun observeStates ()Lkotlinx/coroutines/flow/StateFlow;
public final fun observeStatesOnLifecycle (Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$State;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/Job;
public static synthetic fun observeStatesOnLifecycle$default (Lcom/copperleaf/ballast/core/AndroidViewModel;Landroidx/lifecycle/LifecycleOwner;Landroidx/lifecycle/Lifecycle$State;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
public final fun runOnLifecycle (Landroidx/lifecycle/LifecycleOwner;Lcom/copperleaf/ballast/EventHandler;Landroidx/lifecycle/Lifecycle$State;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/Job;
public static synthetic fun runOnLifecycle$default (Lcom/copperleaf/ballast/core/AndroidViewModel;Landroidx/lifecycle/LifecycleOwner;Lcom/copperleaf/ballast/EventHandler;Landroidx/lifecycle/Lifecycle$State;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
public fun send (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendAndAwaitCompletion (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun trySend-JP2dKIU (Ljava/lang/Object;)Ljava/lang/Object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,26 +115,29 @@ public class BallastDebuggerClientConnection<out T : HttpClientEngineConfig>(

try {
coroutineScope {
attemptConnection(currentTimeoutValue) {
attemptConnection(logger, currentTimeoutValue) {
logger?.debug("Connected to Ballast debugger: $connectionId")
failedAttempts = 0
}
}
} catch (e: CancellationException) {
throw e
} catch (t: Throwable) {
logger?.debug("Connection attempt failed: $connectionId")
logger?.error(t)
}
}
}
return job
}

private suspend fun attemptConnection(currentTimeoutValue: Duration, onSuccessfulConnection: () -> Unit) {
private suspend fun attemptConnection(logger: BallastLogger?, currentTimeoutValue: Duration, onSuccessfulConnection: () -> Unit) {
// either wait for a given timeout to reconnect, or if a new event comes in connect immediately
withTimeoutOrNull(currentTimeoutValue) {
waitForEvent.await()
}

logger?.debug("Attempting to connect to Ballast debugger: $connectionId")
client.webSocket(
method = HttpMethod.Get,
request = {
Expand Down
11 changes: 8 additions & 3 deletions ballast-idea-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,26 @@ description = "Debugger UI application for Ballast MVI"

dependencies {
// compose Desktop Intellij Plugin
compileOnly(compose.desktop.currentOs)
implementation(compose.desktop.macos_x64)
implementation(compose.desktop.macos_arm64)
implementation(compose.desktop.linux_x64)
implementation(compose.desktop.linux_arm64)
implementation(compose.desktop.windows_x64)
implementation(compose.desktop.components.splitPane)
implementation(compose.materialIconsExtended)

// Ktor websocker server
// Ktor websocket server
implementation(libs.kotlinx.coroutines.swing)
implementation(libs.kotlinx.serialization)
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.datetime)
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.server.logging)
implementation(libs.ktor.server.websockets)
implementation(libs.ktor.server.serialization)
implementation(libs.ktor.server.serialization.json)
implementation(libs.slf4j.nop)
implementation(libs.slf4j.simple)

// Ballast, to manage its own UI state (with debugger artifact to share serialization models between the client and server)
implementation(project(":ballast-core"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ class BallastPluginSettingsPanel(
}

private var initialDebuggerPort: Int = injector.prefs.debuggerPort
var debuggerPort: Int = initialDebuggerPort
set(value) {
println("setting debuggerPort to $value")
field = value
}
private var debuggerPort: Int = initialDebuggerPort

override fun Panel.Content() {
onReset { debuggerPort = initialDebuggerPort }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.ktor.server.plugins.callloging.*
import io.ktor.server.request.*
import io.ktor.server.response.respondText
import io.ktor.server.routing.get
import io.ktor.server.routing.routing
Expand All @@ -26,6 +28,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.withContext
import org.slf4j.event.*

public class BallastDebuggerServerConnection(
private val port: Int,
Expand All @@ -37,6 +40,9 @@ public class BallastDebuggerServerConnection(
withContext(Dispatchers.IO) {
embeddedServer(CIO, port = port) {
install(WebSockets)
install(CallLogging) {
level = Level.INFO
}

routing {
get("/") {
Expand Down
12 changes: 6 additions & 6 deletions ballast-idea-plugin/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ This IDEA plugin is built upon the best features of Kotlin:

<extensions defaultExtensionNs="com.intellij">
<!-- Tool Windows -->
<!-- <toolWindow-->
<!-- id="Ballast Debugger"-->
<!-- secondary="true"-->
<!-- icon="AllIcons.Actions.Preview"-->
<!-- anchor="bottom"-->
<!-- factoryClass="com.copperleaf.ballast.debugger.idea.tool.BallastDebuggerToolWindow"/>-->
<toolWindow
id="Ballast Debugger"
secondary="true"
icon="AllIcons.Actions.Preview"
anchor="bottom"
factoryClass="com.copperleaf.ballast.debugger.idea.tool.BallastDebuggerToolWindow"/>

<!-- File Templates -->
<fileTemplateGroup
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies {
implementation("org.jlleitschuh.gradle:ktlint-gradle:11.0.0")
implementation("com.squareup.okhttp3:okhttp:4.10.0")
implementation("com.github.gmazzo:gradle-buildconfig-plugin:3.1.0")
implementation("org.jetbrains.intellij.plugins:gradle-intellij-plugin:1.4.0")
implementation("org.jetbrains.intellij.plugins:gradle-intellij-plugin:1.5.2")
implementation("org.jetbrains.intellij.plugins:gradle-changelog-plugin:1.3.1")
}
tasks.withType<JavaCompile> {
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.

ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }
ktor-server-logging = { module = "io.ktor:ktor-server-call-logging", version.ref = "ktor" }
ktor-server-websockets = { module = "io.ktor:ktor-server-websockets", version.ref = "ktor" }
ktor-server-serialization = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" }
ktor-server-serialization-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
Expand Down Expand Up @@ -56,3 +57,4 @@ multiplatformSettings-noArg = { module = "com.russhwolf:multiplatform-settings-n

benasher44-uuid = { module = "com.benasher44:uuid", version.ref = "uuid" }
slf4j-nop = { module = "org.slf4j:slf4j-nop", version.ref = "slf4j" }
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }

0 comments on commit 6e44cc7

Please sign in to comment.