Skip to content

Commit

Permalink
protocol commands
Browse files Browse the repository at this point in the history
  • Loading branch information
shalom938 committed Sep 25, 2024
1 parent 2240585 commit ee81604
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.digma.intellij.plugin.protocol

import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.digma.intellij.plugin.common.DisposableAdaptor
import org.digma.intellij.plugin.errorreporting.ErrorReporter
import org.digma.intellij.plugin.log.Log

const val ACTION_ASSETS = "assets"

@Service(Service.Level.PROJECT)
class DigmaProtocolApi(val cs: CoroutineScope) : DisposableAdaptor {

private val logger: Logger = Logger.getInstance(this::class.java)

fun performAction(project: Project, action: String, waitForJcef: Boolean) {
try {

Log.log(logger::trace, "perform action {}, thread {}", action, Thread.currentThread().name)

cs.launch {
if (waitForJcef) {
delay(5000)
}
project.messageBus.syncPublisher(ProtocolCommandEvent.PROTOCOL_COMMAND_TOPIC).protocolCommand(action)
}

} catch (e: Throwable) {
ErrorReporter.getInstance().reportError("DigmaProtocolApi.performAction", e)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.digma.intellij.plugin.protocol

import com.intellij.ide.RecentProjectListActionProvider
import com.intellij.ide.RecentProjectsManager
import com.intellij.ide.RecentProjectsManagerBase
import com.intellij.ide.ReopenProjectAction
import com.intellij.ide.impl.OpenProjectTask
import com.intellij.navigation.PROJECT_NAME_KEY
import com.intellij.navigation.ProtocolOpenProjectResult
import com.intellij.navigation.openProject
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.JBProtocolCommand
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.Logger
import com.intellij.util.text.nullize
import org.digma.intellij.plugin.common.findActiveProject
import org.digma.intellij.plugin.errorreporting.ErrorReporter
import org.digma.intellij.plugin.log.Log
import org.digma.intellij.plugin.ui.ToolWindowShower
import java.nio.file.Path
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future

const val DIGMA_COMMAND = "digma"
const val DIGMA_PLUGIN_TARGET = "plugin"
const val ACTION_NAME_KEY = "action"

//jetbrains://idea/digma/plugin?action=assets
//jetbrains://idea/digma/plugin?project=spring-petclinic&action=assets

class DigmaProtocolCommand : JBProtocolCommand(DIGMA_COMMAND) {
private val logger: Logger = Logger.getInstance(this::class.java)

// override fun perform(target: String?, parameters: Map<String, String>, fragment: String?): Future<String?> {
override suspend fun execute(target: String?, parameters: Map<String, String>, fragment: String?): String? {
try {
return executeImpl(target,parameters,fragment)
}catch (e:Throwable){
ErrorReporter.getInstance().reportError("DigmaProtocolCommand.execute",e)
return "Error $e"
}
}

private suspend fun executeImpl(target: String?, parameters: Map<String, String>, fragment: String?): String? {

if (target != DIGMA_PLUGIN_TARGET) {
// return CompletableFuture.completedFuture("DigmaProtocolCommand Supports Only Plugin Target")
return "DigmaProtocolCommand Supports Only Plugin Target"
}

Log.log(
logger::trace,
"execute called with target={},fragment={},parameters={}, thread={}",
target,
fragment.toString(),
parameters.toUrlQueryString(),
Thread.currentThread().name
)


var project = if (parameters.containsKey(PROJECT_NAME_KEY)) {
when (val openProjectResult = openProject(parameters)) {
is ProtocolOpenProjectResult.Success -> openProjectResult.project
// is ProtocolOpenProjectResult.Error -> return CompletableFuture.completedFuture(openProjectResult.message)
is ProtocolOpenProjectResult.Error -> return openProjectResult.message
}
} else {
findActiveProject()
}

if (project == null) {
val recentProjectPath =
RecentProjectListActionProvider.getInstance().getActions().asSequence().filterIsInstance(ReopenProjectAction::class.java)
.firstOrNull()?.projectPath ?: RecentProjectsManager.getInstance().lastProjectCreationLocation
if (recentProjectPath != null) {
project = RecentProjectsManagerBase.getInstanceEx().openProject(Path.of(recentProjectPath), OpenProjectTask())
}
}


if (project != null) {

Log.log(logger::trace, "got project {}", project.name)

val action = parameters[ACTION_NAME_KEY]?.nullize(nullizeSpaces = true)
// ?: return CompletableFuture.completedFuture("DigmaProtocolCommand no action in request")
?: return "DigmaProtocolCommand no action in request"


var waitForJcef = false
if (!ToolWindowShower.getInstance(project).isToolWindowVisible) {
waitForJcef = true
ApplicationManager.getApplication().invokeAndWait {
Log.log(logger::trace, "showing tool window")
ToolWindowShower.getInstance(project).showToolWindow()
Log.log(logger::trace, "tool window shown")
}
}

Log.log(logger::trace, "executing action {}", action)
project.service<DigmaProtocolApi>().performAction(project, action, waitForJcef)
Log.log(logger::trace, "after execute action {}", action)
// return CompletableFuture.completedFuture(null)
return null
}

// return CompletableFuture.completedFuture("DigmaProtocolCommand can not find project")
return "DigmaProtocolCommand can not find project"

}

// override suspend fun execute(target: String?, parameters: Map<String, String>, fragment: String?): String? {
// return super.execute(target, parameters, fragment)
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.digma.intellij.plugin.protocol

import com.intellij.util.messages.Topic


/**
* this is an application event that should fire when we change the api client,
* usually when user changes the api url in settings.
*/
fun interface ProtocolCommandEvent {


companion object {
@JvmStatic
@Topic.ProjectLevel
val PROTOCOL_COMMAND_TOPIC: Topic<ProtocolCommandEvent> = Topic.create(
"PROTOCOL COMMAND",
ProtocolCommandEvent::class.java
)
}

fun protocolCommand(action: String)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.digma.intellij.plugin.protocol

import java.net.URLEncoder


fun Map<String, String>.toUrlQueryString() =
this.map {(k,v) -> "${URLEncoder.encode(k, "UTF-8")}=${URLEncoder.encode(v, "UTF-8")}" }
.joinToString("&")
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import com.intellij.openapi.util.Disposer
import kotlinx.datetime.Clock
import kotlinx.datetime.toKotlinInstant
import org.digma.intellij.plugin.engagement.EngagementScoreService
import org.digma.intellij.plugin.log.Log
import org.digma.intellij.plugin.persistence.PersistenceService
import org.digma.intellij.plugin.protocol.ACTION_ASSETS
import org.digma.intellij.plugin.protocol.ProtocolCommandEvent
import org.digma.intellij.plugin.scheduling.disposingPeriodicTask
import org.digma.intellij.plugin.ui.jcef.JCefComponent
import org.digma.intellij.plugin.ui.jcef.sendGenericPluginEvent
Expand All @@ -26,6 +29,22 @@ class MainAppService(private val project: Project) : Disposable {

init {

project.messageBus.connect(this).subscribe(ProtocolCommandEvent.PROTOCOL_COMMAND_TOPIC,
ProtocolCommandEvent { action ->

Log.log(logger::trace,"got protocol command {}",action)

jCefComponent?.let { jcefComp ->
when (action) {
ACTION_ASSETS -> {
Log.log(logger::trace,"sending generic event to open assets page")
sendGenericPluginEvent(project, jcefComp.jbCefBrowser.cefBrowser, "first asset notification link click")
}
}
} ?: Log.log(logger::trace,"jcef component is null")
})


if ( //todo: check if user clicked don't show again
!PersistenceService.getInstance().isUserRequestedEarlyAccess() &&
PersistenceService.getInstance().getUserEmail() == null && PersistenceService.getInstance().getUserRegistrationEmail() == null
Expand All @@ -37,8 +56,8 @@ class MainAppService(private val project: Project) : Disposable {
val installTime = PersistenceService.getInstance().getFirstTimePluginLoadedTimestamp()
if (installTime != null) {
if (Clock.System.now() > (installTime.toKotlinInstant().plus(14.days))) {
if (EngagementScoreService.getInstance().getLatestRegisteredActiveDays() >= 5){
sendGenericPluginEvent(project,jcefComp.jbCefBrowser.cefBrowser,"SHOW_EARLY_ACCESS_PROMOTION")
if (EngagementScoreService.getInstance().getLatestRegisteredActiveDays() >= 5) {
sendGenericPluginEvent(project, jcefComp.jbCefBrowser.cefBrowser, "SHOW_EARLY_ACCESS_PROMOTION")
Disposer.dispose(disposable)
}
}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@

<postStartupActivity implementation="org.digma.intellij.plugin.posthog.CountingProjectActivity"/>

<jbProtocolCommand implementation="org.digma.intellij.plugin.protocol.DigmaProtocolCommand"/>

</extensions>

Expand Down

0 comments on commit ee81604

Please sign in to comment.